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