X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=laserbrain_demo;a=blobdiff_plain;f=src%2Fexman.cc;h=02f4bc552181dcb954a2cbe2893e2f41501c4b57;hp=21e00749f7e9a405e3d29649be36f9ebc3b23546;hb=91c5d07b779f24afec373047afe401b8811811c7;hpb=b5ed5107e21ff834d5a4510b9047f976abb03dff diff --git a/src/exman.cc b/src/exman.cc index 21e0074..02f4bc5 100644 --- a/src/exman.cc +++ b/src/exman.cc @@ -7,6 +7,101 @@ static Exhibit *create_exhibit(const char *type); + +ExhibitSlot::ExhibitSlot(Exhibit *ex) +{ + this->ex = 0; + + init(ex); +} + +ExhibitSlot::~ExhibitSlot() +{ + detach_exhibit(); + + SceneNode *par = node.get_parent(); + if(par) { + par->remove_child(&node); + + while(node.get_num_children()) { + par->add_child(node.get_child(0)); + } + } +} + + +void ExhibitSlot::init(Exhibit *ex) +{ + std::string node_name = "ExhibitSlot"; + if(ex) { + if(ex->get_name()) { + node_name += std::string(":") + std::string(ex->get_name()); + } + + if(ex->node) { + if(ex->node->get_parent()) { + ex->node->get_parent()->add_child(&node); + } + node.set_position(ex->node->get_node_position()); + node.set_rotation(ex->node->get_node_rotation()); + ex->node->set_position(Vec3(0, 0, 0)); + ex->node->set_rotation(Quat::identity); + } + attach_exhibit(ex); + } else { + this->ex = 0; + } + + node.set_name(node_name.c_str()); +} + +bool ExhibitSlot::empty() const +{ + return ex == 0; +} + +Exhibit *ExhibitSlot::get_exhibit() const +{ + return ex; +} + +/* In the process of attaching the exhibit, we also steal the exhibit's node + * from its previous parent, and reparent it to the slot's node. As the slot's + * node itself should have been made a child of the original parent of the + * exhibit during init(), the initial state is we're interjecting a null node in + * the scene graph between the exhibit and its original parent. + * + * Attaching to a slot, implicitly detaches from the previous slot. + */ +bool ExhibitSlot::attach_exhibit(Exhibit *ex, ExSlotAttachMode mode) +{ + if(!ex || this->ex) return false; + + if(ex->prev_slot && ex->prev_slot->ex == ex) { + ex->prev_slot->detach_exhibit(); + } + + if(mode != EXSLOT_ATTACH_TRANSIENT) { + ex->prev_slot = this; + } + + node.add_child(ex->node); + this->ex = ex; + return true; +} + +bool ExhibitSlot::detach_exhibit() +{ + if(!ex) return false; + + node.remove_child(ex->node); + ex = 0; + return true; +} + + +// ---- exhibit manager implementation ---- + ExhibitManager::ExhibitManager() { } @@ -23,6 +118,12 @@ void ExhibitManager::clear() delete items[i]; } items.clear(); + + num = (int)exslots.size(); + for(int i=0; iset_node(snode); + items.push_back(ex); + const char *alabel = ts_get_attr_str(node, "label"); + if(alabel) { + ex->set_name(alabel); + } + + // create a new slot and attach the exhibit to it + ExhibitSlot *slot = new ExhibitSlot(ex); + exslots.push_back(slot); + + // grab any extra exhibit data const char *desc = ts_get_attr_str(node, "description"); const char *voice = ts_get_attr_str(node, "voiceover"); if(desc || voice) { @@ -92,9 +205,6 @@ bool ExhibitManager::load(MetaScene *mscn, const char *fname) } ex->data.push_back(exd); } - - ex->set_node(snode); - items.push_back(ex); } } @@ -129,6 +239,42 @@ ExSelection ExhibitManager::select(const Sphere &sph) const return sel; // TODO } +// TODO optimize +ExhibitSlot *ExhibitManager::nearest_empty_slot(const Vec3 &pos, float max_dist) const +{ + ExhibitSlot *nearest = 0; + float nearest_sqdist = max_dist * max_dist; + + int nslots = exslots.size(); + for(int i=0; iempty()) continue; + + Vec3 slotpos = slot->node.get_position(); + float dsq = length_sq(pos - slotpos); + if(dsq < nearest_sqdist) { + nearest = slot; + nearest_sqdist = dsq; + } + } + + return nearest; +} + +void ExhibitManager::stash_exhibit(Exhibit *ex) +{ + // make sure it's not already stashed + if(std::find(stashed.begin(), stashed.end(), ex) != stashed.end()) { + return; + } + stashed.push_back(ex); + + ex->prev_slot = 0; + if(ex->node->get_parent()) { + ex->node->get_parent()->remove_child(ex->node); + } +} + void ExhibitManager::update(float dt) { int num = items.size();