#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)
void ExhibitManager::clear()
{
- int num = (int)items.size();
- for(int i=0; i<num; i++) {
- delete items[i];
- }
+ // not deleting exhibit objects, as they will be deleted the own_scn destructor
items.clear();
- num = (int)exslots.size();
+ int num = (int)exslots.size();
for(int i=0; i<num; i++) {
delete exslots[i];
}
std::vector<Exhibit*>::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);
}
}
std::vector<Exhibit*>::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;
bool ExhibitManager::load(MetaScene *mscn, const char *fname)
{
+ info_log("ExhibitManager::load(%s)\n", fname);
+
struct ts_node *root = ts_load(fname);
if(!root || strcmp(root->name, "exhibits") != 0) {
ts_free_tree(root);
return false;
}
- // create our own scene to manage all exhibits not already in an existing scene
- // and add it to the metascene
+ /* 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";
}
}
+ // 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");
const char *voice = ts_get_attr_str(node, "voiceover");
if(desc || voice) {
ExData exd;
+ exd.type = EXDATA_INFO;
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;
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; i<nitems; i++) {
+ ExSelection sel = items[i]->select(sph);
+ if(sel) {
+ return sel;
+ }
}
- return sel; // TODO
+ return ExSelection();
}
// TODO optimize
{
int num = items.size();
for(int i=0; i<num; i++) {
- items[i]->pre_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);
+ }
}
}
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;
+}