implemented metascene spawn point/rot
[laserbrain_demo] / src / metascene.cc
index 66e0027..e0b2b20 100644 (file)
@@ -4,6 +4,7 @@
 #include "scene.h"
 #include "treestore.h"
 #include "logger.h"
+#include "app.h"
 
 #ifdef WIN32
 #include <malloc.h>
@@ -19,7 +20,7 @@ struct MaterialEdit {
 
 static bool proc_node(MetaScene *mscn, struct ts_node *node);
 static bool proc_scenefile(MetaScene *mscn, struct ts_node *node);
-static bool proc_mtledit(MetaScene *mscn, MaterialEdit *med, struct ts_node *node, TextureSet *texset);
+static bool proc_mtledit(MetaScene *mscn, MaterialEdit *med, struct ts_node *node);
 static void apply_mtledit(Scene *scn, const MaterialEdit &med);
 static void apply_mtledit(Material *mtl, const MaterialEdit &med);
 static struct ts_attr *attr_inscope(struct ts_node *node, const char *name);
@@ -27,10 +28,8 @@ static struct ts_attr *attr_inscope(struct ts_node *node, const char *name);
 static void print_scene_graph(SceneNode *n, int level);
 
 
-MetaScene::MetaScene(SceneSet *sman, TextureSet *tman)
+MetaScene::MetaScene()
 {
-       sceneman = sman;
-       texman = tman;
        walk_mesh = 0;
 }
 
@@ -103,7 +102,8 @@ static bool proc_node(MetaScene *mscn, struct ts_node *node)
 
 
 struct SceneData {
-       std::string walkmesh_regexp;
+       MetaScene *meta;
+       std::string walkmesh_regexp, spawn_regexp;
        std::vector<MaterialEdit> mtledit;
 };
 
@@ -112,6 +112,7 @@ static bool proc_scenefile(MetaScene *mscn, struct ts_node *node)
        const char *fname = ts_get_attr_str(node, "file");
        if(fname) {
                SceneData *sdat = new SceneData;
+               sdat->meta = mscn;
 
                // datapath
                struct ts_attr *adpath = attr_inscope(node, "datapath");
@@ -126,6 +127,28 @@ static bool proc_scenefile(MetaScene *mscn, struct ts_node *node)
                        sdat->walkmesh_regexp = std::string(awmesh->val.str);
                }
 
+               // spawn node
+               struct ts_attr *awspawn = attr_inscope(node, "spawn");
+               if(awspawn) {
+                       switch(awspawn->val.type) {
+                       case TS_VECTOR:
+                               mscn->start_pos = Vec3(awspawn->val.vec[0], awspawn->val.vec[1],
+                                               awspawn->val.vec[2]);
+                               break;
+
+                       case TS_STRING:
+                       default:
+                               sdat->spawn_regexp = std::string(awspawn->val.str);
+                       }
+               }
+               if((awspawn = attr_inscope(node, "spawn_rot")) && awspawn->val.type == TS_VECTOR) {
+                       Quat rot;
+                       rot.rotate(Vec3(1, 0, 0), deg_to_rad(awspawn->val.vec[0]));
+                       rot.rotate(Vec3(0, 1, 0), deg_to_rad(awspawn->val.vec[1]));
+                       rot.rotate(Vec3(0, 0, 1), deg_to_rad(awspawn->val.vec[2]));
+                       mscn->start_rot = rot;
+               }
+
                int namesz = mscn->datamap.lookup(fname, 0, 0);
                char *namebuf = (char*)alloca(namesz + 1);
                if(mscn->datamap.lookup(fname, namebuf, namesz + 1)) {
@@ -136,13 +159,13 @@ static bool proc_scenefile(MetaScene *mscn, struct ts_node *node)
                struct ts_node *child = node->child_list;
                while(child) {
                        MaterialEdit medit;
-                       if(proc_mtledit(mscn, &medit, child, mscn->texman)) {
+                       if(proc_mtledit(mscn, &medit, child)) {
                                sdat->mtledit.push_back(medit);
                        }
                        child = child->next;
                }
 
-               Scene *newscn = mscn->sceneman->get(fname);
+               Scene *newscn = sceneman.get(fname);
                /* NOTE: setting all these after get() is not a race condition, because
                 * scene_loaded() which uses this, will only run in our main loop during
                 * SceneSet::update() on the main thread.
@@ -185,6 +208,30 @@ bool MetaScene::scene_loaded(Scene *newscn)
                delete wscn;
        }
 
+       // extract the spawn node
+       if(!sdat->spawn_regexp.empty() && (wscn = newscn->extract_nodes(sdat->spawn_regexp.c_str()))) {
+
+               int nmeshes = wscn->meshes.size();
+               int nnodes = wscn->nodes ? wscn->nodes->get_num_children() : 0;
+
+               if(nmeshes) {
+                       Vec3 pos;
+                       for(int i=0; i<nmeshes; i++) {
+                               const Sphere &bsph = wscn->meshes[i]->get_bsphere();
+                               pos += bsph.center;
+                       }
+                       pos /= (float)nmeshes;
+                       sdat->meta->start_pos = pos;
+
+               } else if(nnodes) {
+                       // just use the first one
+                       SceneNode *first = wscn->nodes->get_child(0);
+                       sdat->meta->start_pos = first->get_position();
+                       sdat->meta->start_rot = first->get_rotation();
+               }
+               delete wscn;
+       }
+
        int num_medits = sdat->mtledit.size();
        for(int i=0; i<num_medits; i++) {
                // perform material edits
@@ -195,7 +242,7 @@ bool MetaScene::scene_loaded(Scene *newscn)
        return true;
 }
 
-static bool proc_mtledit(MetaScene *mscn, MaterialEdit *med, struct ts_node *node, TextureSet *texset)
+static bool proc_mtledit(MetaScene *mscn, MaterialEdit *med, struct ts_node *node)
 {
        if(strcmp(node->name, "mtledit") != 0) {
                return false;
@@ -241,7 +288,7 @@ static bool proc_mtledit(MetaScene *mscn, MaterialEdit *med, struct ts_node *nod
                                // remove
                                med->tex = 0;
                        } else {
-                               med->tex = texset->get_texture(afile->val.str, TEX_2D, &mscn->datamap);
+                               med->tex = texman.get_texture(afile->val.str, TEX_2D, &mscn->datamap);
                        }
                }
                // TODO add more edit modes