adding exhibit data, starting with descriptions
[laserbrain_demo] / src / exman.cc
1 #include <algorithm>
2 #include "exman.h"
3 #include "exhibit.h"
4 #include "blob_exhibit.h"
5 #include "treestore.h"
6
7 static Exhibit *create_exhibit(const char *type);
8
9 ExhibitManager::ExhibitManager()
10 {
11 }
12
13 ExhibitManager::~ExhibitManager()
14 {
15         clear();
16 }
17
18 void ExhibitManager::clear()
19 {
20         int num = (int)items.size();
21         for(int i=0; i<num; i++) {
22                 delete items[i];
23         }
24         items.clear();
25 }
26
27 void ExhibitManager::add(Exhibit *ex)
28 {
29         std::vector<Exhibit*>::iterator it = std::find(items.begin(), items.end(), ex);
30         if(it == items.end()) {
31                 items.push_back(ex);
32         }
33 }
34
35 bool ExhibitManager::remove(Exhibit *ex)
36 {
37         std::vector<Exhibit*>::iterator it = std::find(items.begin(), items.end(), ex);
38         if(it != items.end()) {
39                 items.erase(it);
40                 return true;
41         }
42         return false;
43 }
44
45 bool ExhibitManager::load(MetaScene *mscn, const char *fname)
46 {
47         struct ts_node *root = ts_load(fname);
48         if(!root || strcmp(root->name, "exhibits") != 0) {
49                 ts_free_tree(root);
50                 error_log("failed to load exhibits\n");
51                 return false;
52         }
53
54         struct ts_node *iter = root->child_list;
55         while(iter) {
56                 struct ts_node *node = iter;
57                 iter = iter->next;
58
59                 if(strcmp(node->name, "item") == 0) {
60                         SceneNode *snode;
61
62                         const char *amatch = ts_get_attr_str(node, "match_node");
63                         if(!amatch || !(snode = mscn->match_node(amatch))) {
64                                 error_log("ExhibitManager::load: regexp \"%s\" didn't match any nodes\n",
65                                                 amatch ? amatch : "");
66                                 continue;
67                         }
68
69                         Exhibit *ex;
70                         const char *atype = ts_get_attr_str(node, "type");
71                         if(!atype || !(ex = create_exhibit(atype))) {
72                                 error_log("failed to create exhibit of type: %s\n", atype);
73                                 continue;
74                         }
75
76                         const char *desc = ts_get_attr_str(node, "description");
77                         const char *voice = ts_get_attr_str(node, "voiceover");
78                         if(desc || voice) {
79                                 ExData exd;
80
81                                 if(desc) {
82                                         exd.text = std::string(desc);
83                                 }
84                                 if(voice) {
85                                         exd.voice = new OggVorbisStream;
86                                         if(!exd.voice->open(voice)) {
87                                                 error_log("failed to open voiceover: %s\n", voice);
88                                                 delete exd.voice;
89                                                 exd.voice = 0;
90                                         }
91                                 }
92                                 ex->data.push_back(exd);
93                         }
94
95                         ex->set_node(snode);
96                         items.push_back(ex);
97                 }
98         }
99
100         ts_free_tree(root);
101         return true;
102 }
103
104 ExSelection ExhibitManager::select(const Ray &ray) const
105 {
106         ExSelection sel;
107         if(!items.empty()) {
108                 sel.ex = items[0];
109                 sel.selray = ray;
110                 sel.validmask = EXSEL_RAY;
111         }
112         return sel;     // TODO
113 }
114
115 ExSelection ExhibitManager::select(const Sphere &sph) const
116 {
117         ExSelection sel;
118         if(!items.empty()) {
119                 sel.ex = items[0];
120                 sel.selsphere = sph;
121                 sel.validmask = EXSEL_SPHERE;
122         }
123         return sel;     // TODO
124 }
125
126 void ExhibitManager::update(float dt)
127 {
128         int num = items.size();
129         for(int i=0; i<num; i++) {
130                 // if the exhibit is not part of a scene graph, first call its
131                 // node's update function (otherwise it'll have been called recursively earlier)
132                 if(!items[i]->node->get_parent()) {
133                         items[i]->node->update(dt);
134                 }
135                 items[i]->update(dt);
136         }
137 }
138
139 void ExhibitManager::draw() const
140 {
141         int num = items.size();
142         for(int i=0; i<num; i++) {
143                 items[i]->pre_draw();
144                 items[i]->draw();
145                 items[i]->post_draw();
146         }
147 }
148
149 static Exhibit *create_exhibit(const char *type)
150 {
151         if(strcmp(type, "static") == 0) {
152                 debug_log("creating static exhibit\n");
153                 return new Exhibit;
154         } else if(strcmp(type, "blobs") == 0) {
155                 debug_log("creating blobs exhibit\n");
156                 return new BlobExhibit;
157         }
158         error_log("unknown exhibit type: %s\n", type);
159         return 0;
160 }