5 static void destroy_node_tree(SceneNode *n);
7 Scene::Scene(TextureSet *tset)
18 texset = new TextureSet;
30 destroy_node_tree(nodes);
33 for(int i=0; i<(int)meshes.size(); i++) {
41 for(int i=0; i<(int)objects.size(); i++) {
52 static void destroy_node_tree(SceneNode *n)
56 int nsub = n->get_num_children();
57 for(int i=0; i<nsub; i++) {
58 destroy_node_tree(n->get_child(i));
63 // Scene::load defined in sceneload.cc
65 bool Scene::merge(Scene *scn)
67 if(texset != scn->texset) {
68 // TODO handle this properly
69 error_log("for now only able to merge scenes using the same texture set\n");
75 walk_mesh->append(*scn->walk_mesh);
76 delete scn->walk_mesh;
80 walk_mesh = scn->walk_mesh;
84 int nmeshes = scn->meshes.size();
85 for(int i=0; i<nmeshes; i++) {
86 meshes.push_back(scn->meshes[i]);
90 int nobj = scn->objects.size();
91 for(int i=0; i<nobj; i++) {
92 objects.push_back(scn->objects[i]);
97 int nchildren = scn->nodes ? scn->nodes->get_num_children() : 0;
98 for(int i=0; i<nchildren; i++) {
99 SceneNode *n = scn->nodes->get_child(i);
100 scn->nodes->remove_child(n);
103 if(scn->nodes && scn->nodes->get_num_objects() > 0) {
104 warning_log("merging with scene which has objects in its root node. these objects will not be merged!\n");
115 void Scene::add_object(Object *obj)
117 objects.push_back(obj);
120 bool Scene::remove_object(Object *obj)
122 std::vector<Object*>::iterator it = std::find(objects.begin(), objects.end(), obj);
123 if(it != objects.end()) {
130 bool Scene::have_object(Object *obj) const
132 return std::find(objects.begin(), objects.end(), obj) != objects.end();
135 void Scene::add_mesh(Mesh *m)
140 bool Scene::remove_mesh(Mesh *m)
142 std::vector<Mesh*>::iterator it = std::find(meshes.begin(), meshes.end(), m);
143 if(it != meshes.end()) {
150 bool Scene::have_mesh(Mesh *m) const
152 return std::find(meshes.begin(), meshes.end(), m) != meshes.end();
155 void Scene::add_node(SceneNode *n)
157 // we always want to have a dedicated root node
159 nodes = new SceneNode;
161 nodes->set_name("root");
167 bool Scene::remove_node(SceneNode *n)
170 if(!n || !(par = n->get_parent())) {
174 int nsub = n->get_num_children();
175 for(int i=0; i<nsub; i++) {
176 SceneNode *c = n->get_child(i);
181 return par->remove_child(n);
184 bool Scene::have_node(SceneNode *n) const
186 return n->scene == this;
189 static void find_nodes_rec(std::list<SceneNode*> *res, SceneNode *tree, const std::regex &re)
191 if(std::regex_match(tree->get_name(), re)) {
192 res->push_back(tree);
195 int num = tree->get_num_children();
196 for(int i=0; i<num; i++) {
197 find_nodes_rec(res, tree->get_child(i), re);
201 Scene *Scene::extract_nodes(const char *qstr)
205 std::list<SceneNode*> nodelist;
206 find_nodes_rec(&nodelist, nodes, re);
207 if(nodelist.empty()) {
211 Scene *res = new Scene(texset);
213 for(SceneNode *n : nodelist) {
215 int nobj = n->get_num_objects();
216 for(int i=0; i<nobj; i++) {
217 Object *obj = n->get_object(i);
218 if(obj->get_type() == OBJ_MESH) {
219 // XXX this assumes that meshes aren't shared between objects.
220 // maybe we'll have to refcount them at some point, and copy if nref>1
221 ObjMesh *om = (ObjMesh*)obj;
222 remove_mesh(om->mesh);
223 res->add_mesh(om->mesh);
227 res->add_object(obj);
236 void Scene::apply_xform()
238 nodes->apply_xform();
241 void Scene::update(float dt)
247 int nobj = objects.size();
248 for(int i=0; i<nobj; i++) {
249 if(!objects[i]->node) {
250 // only update objects which don't belong to a scenegraph node
251 // to avoid updating objects twice
252 objects[i]->update(dt);
257 void Scene::draw() const
259 if(!objects.empty()) {
260 int nobj = objects.size();
261 for(int i=0; i<nobj; i++) {
265 int nmesh = meshes.size();
266 for(int i=0; i<nmesh; i++) {