X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=laserbrain_demo;a=blobdiff_plain;f=src%2Fexman.cc;h=eea24a6e438da65ca5be930647a8f1f238c4f757;hp=02f4bc552181dcb954a2cbe2893e2f41501c4b57;hb=6ecd4ecfa020964e4250bf9322c1a26ac4073b76;hpb=91c5d07b779f24afec373047afe401b8811811c7 diff --git a/src/exman.cc b/src/exman.cc index 02f4bc5..eea24a6 100644 --- a/src/exman.cc +++ b/src/exman.cc @@ -4,8 +4,11 @@ #include "exhibit.h" #include "blob_exhibit.h" #include "treestore.h" +#include "app.h" +#include "geomdraw.h" static Exhibit *create_exhibit(const char *type); +static void clean_desc_text(char *dest, const char *src); ExhibitSlot::ExhibitSlot(Exhibit *ex) @@ -104,6 +107,7 @@ bool ExhibitSlot::detach_exhibit() ExhibitManager::ExhibitManager() { + own_scn = 0; } ExhibitManager::~ExhibitManager() @@ -113,17 +117,16 @@ ExhibitManager::~ExhibitManager() void ExhibitManager::clear() { - int num = (int)items.size(); - for(int i=0; i::iterator it = std::find(items.begin(), items.end(), ex); if(it == items.end()) { items.push_back(ex); + own_scn->add_object(ex); + if(ex->node) own_scn->add_node(ex->node); } } @@ -139,6 +144,8 @@ bool ExhibitManager::remove(Exhibit *ex) std::vector::iterator it = std::find(items.begin(), items.end(), ex); if(it != items.end()) { items.erase(it); + own_scn->remove_object(ex); + if(ex->node) own_scn->remove_node(ex->node); return true; } return false; @@ -153,35 +160,80 @@ bool ExhibitManager::load(MetaScene *mscn, const char *fname) return false; } + /* create our own scene to manage all exhibits not already in an existing scene + * and add it to the metascene. + * Also exhibit drawing happens due to the renderer drawing the metascene + */ + if(!own_scn) { + own_scn = new Scene; + own_scn->name = "ad-hoc exhibits"; + mscn->scenes.push_back(own_scn); + } + struct ts_node *iter = root->child_list; while(iter) { struct ts_node *node = iter; iter = iter->next; - if(strcmp(node->name, "item") == 0) { - SceneNode *snode; - - const char *amatch = ts_get_attr_str(node, "match_node"); - if(!amatch || !(snode = mscn->match_node(amatch))) { - error_log("ExhibitManager::load: regexp \"%s\" didn't match any nodes\n", - amatch ? amatch : ""); - continue; - } + SceneNode *snode = 0; + if(strcmp(node->name, "item") == 0) { Exhibit *ex; const char *atype = ts_get_attr_str(node, "type"); if(!atype || !(ex = create_exhibit(atype))) { error_log("failed to create exhibit of type: %s\n", atype); continue; } - ex->set_node(snode); - items.push_back(ex); - const char *alabel = ts_get_attr_str(node, "label"); if(alabel) { ex->set_name(alabel); } + const char *amatch = ts_get_attr_str(node, "match_node"); + if(amatch) { + if(!(snode = mscn->match_node(amatch))) { + error_log("ExhibitManager::load: regexp \"%s\" didn't match any nodes\n", + amatch ? amatch : ""); + continue; + } + } + + // add everything to our data structures + // equivalent to add_exhibit(ex), but without all the searching + own_scn->add_object(ex); + if(!snode) { + snode = new SceneNode; + snode->set_name(ex->get_name()); + own_scn->add_node(snode); + } + ex->set_node(snode); + items.push_back(ex); + + float *apos = ts_get_attr_vec(node, "pos"); + if(apos) { + snode->set_position(Vec3(apos[0], apos[1], apos[2])); + } + float *arot_axis = ts_get_attr_vec(node, "rotaxis"); + if(arot_axis) { + float arot_angle = ts_get_attr_num(node, "rotangle", 0.0f); + Vec3 axis = Vec3(arot_axis[0], arot_axis[1], arot_axis[2]); + Quat q; + q.set_rotation(axis, deg_to_rad(arot_angle)); + snode->set_rotation(q); + } + struct ts_attr *ascale = ts_get_attr(node, "scale"); + if(ascale) { + switch(ascale->val.type) { + case TS_NUMBER: + snode->set_scaling(Vec3(ascale->val.fnum, ascale->val.fnum, ascale->val.fnum)); + break; + case TS_VECTOR: + snode->set_scaling(Vec3(ascale->val.vec[0], ascale->val.vec[1], ascale->val.vec[2])); + default: + break; + } + } + // create a new slot and attach the exhibit to it ExhibitSlot *slot = new ExhibitSlot(ex); exslots.push_back(slot); @@ -193,7 +245,10 @@ bool ExhibitManager::load(MetaScene *mscn, const char *fname) ExData exd; if(desc) { - exd.text = std::string(desc); + char *fixed_desc = new char[strlen(desc) + 1]; + clean_desc_text(fixed_desc, desc); + exd.text = std::string(fixed_desc); + delete [] fixed_desc; } if(voice) { exd.voice = new OggVorbisStream; @@ -230,13 +285,14 @@ ExSelection ExhibitManager::select(const Ray &ray) const ExSelection ExhibitManager::select(const Sphere &sph) const { - ExSelection sel; - if(!items.empty()) { - sel.ex = items[0]; - sel.selsphere = sph; - sel.validmask = EXSEL_SPHERE; + int nitems = items.size(); + for(int i=0; iselect(sph); + if(sel) { + return sel; + } } - return sel; // TODO + return ExSelection(); } // TODO optimize @@ -280,8 +336,8 @@ void ExhibitManager::update(float dt) int num = items.size(); for(int i=0; inode->get_parent()) { + // node's update function (otherwise it would have been called recursively earlier) + if(items[i]->node && !items[i]->node->get_parent()) { items[i]->node->update(dt); } items[i]->update(dt); @@ -292,9 +348,10 @@ void ExhibitManager::draw() const { int num = items.size(); for(int i=0; ipre_draw(); - items[i]->draw(); - items[i]->post_draw(); + if(exsel_hover.ex == items[i]) { + const AABox &bvol = items[i]->get_aabox(); + draw_geom_object(&bvol); + } } } @@ -305,8 +362,38 @@ static Exhibit *create_exhibit(const char *type) return new Exhibit; } else if(strcmp(type, "blobs") == 0) { debug_log("creating blobs exhibit\n"); - return new BlobExhibit; + BlobExhibit *b = new BlobExhibit; + if(!b->init()) { + delete b; + error_log("failed to initialize blobs exhibit\n"); + return 0; + } + return b; } error_log("unknown exhibit type: %s\n", type); return 0; } + +/* clean up description text to be more easily layed out later. + * more specifically: + * - remove redundant spaces + * - remove all newlines except as paragraph separators + * - remove all other whitespace chars + * destination buffer must be as large as the source buffer + */ +static void clean_desc_text(char *dest, const char *src) +{ + while(*src) { + if(isspace(*src)) { + if(*src == '\n' && *(src + 1) == '\n') { + *dest++ = '\n'; + } else { + *dest++ = ' '; + } + while(*src && isspace(*src)) ++src; + } else { + *dest++ = *src++; + } + } + *dest = 0; +}