+#include <algorithm>
#include "exman.h"
#include "exhibit.h"
#include "blob_exhibit.h"
+#include "treestore.h"
static Exhibit *create_exhibit(const char *type);
ExhibitManager::~ExhibitManager()
{
+ clear();
+}
+
+void ExhibitManager::clear()
+{
int num = (int)items.size();
for(int i=0; i<num; i++) {
delete items[i];
items.clear();
}
-bool ExhibitManager::load(const MetaScene *mscn, const char *fname)
+void ExhibitManager::add(Exhibit *ex)
+{
+ std::vector<Exhibit*>::iterator it = std::find(items.begin(), items.end(), ex);
+ if(it == items.end()) {
+ items.push_back(ex);
+ }
+}
+
+bool ExhibitManager::remove(Exhibit *ex)
+{
+ std::vector<Exhibit*>::iterator it = std::find(items.begin(), items.end(), ex);
+ if(it != items.end()) {
+ items.erase(it);
+ return true;
+ }
+ return false;
+}
+
+bool ExhibitManager::load(MetaScene *mscn, const char *fname)
{
struct ts_node *root = ts_load(fname);
if(!root || strcmp(root->name, "exhibits") != 0) {
return false;
}
+ 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;
+ }
+
+ 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;
+ }
+
+ const char *desc = ts_get_attr_str(node, "description");
+ const char *voice = ts_get_attr_str(node, "voiceover");
+ if(desc || voice) {
+ ExData exd;
+
+ if(desc) {
+ exd.text = std::string(desc);
+ }
+ if(voice) {
+ exd.voice = new OggVorbisStream;
+ if(!exd.voice->open(voice)) {
+ error_log("failed to open voiceover: %s\n", voice);
+ delete exd.voice;
+ exd.voice = 0;
+ }
+ }
+ ex->data.push_back(exd);
+ }
+
+ ex->set_node(snode);
+ items.push_back(ex);
+ }
+ }
+
ts_free_tree(root);
return true;
}
+ExSelection ExhibitManager::select(const Ray &ray) const
+{
+ ExSelection sel;
+ if(!items.empty()) {
+ sel.ex = items[0];
+ sel.selray = ray;
+ sel.validmask = EXSEL_RAY;
+ }
+ return sel; // TODO
+}
+
+ExSelection ExhibitManager::select(const Sphere &sph) const
+{
+ ExSelection sel;
+ if(!items.empty()) {
+ sel.ex = items[0];
+ sel.selsphere = sph;
+ sel.validmask = EXSEL_SPHERE;
+ }
+ return sel; // TODO
+}
+
+void ExhibitManager::update(float dt)
+{
+ int num = items.size();
+ for(int i=0; i<num; i++) {
+ // if the exhibit is not part of a scene graph, first call its
+ // node's update function (otherwise it'll have been called recursively earlier)
+ if(!items[i]->node->get_parent()) {
+ items[i]->node->update(dt);
+ }
+ items[i]->update(dt);
+ }
+}
+
+void ExhibitManager::draw() const
+{
+ int num = items.size();
+ for(int i=0; i<num; i++) {
+ items[i]->pre_draw();
+ items[i]->draw();
+ items[i]->post_draw();
+ }
+}
static Exhibit *create_exhibit(const char *type)
{
if(strcmp(type, "static") == 0) {
+ debug_log("creating static exhibit\n");
return new Exhibit;
} else if(strcmp(type, "blobs") == 0) {
+ debug_log("creating blobs exhibit\n");
return new BlobExhibit;
}
+ error_log("unknown exhibit type: %s\n", type);
return 0;
}