7 static void destroy_node_tree(SceneNode *n);
38 destroy_node_tree(nodes);
41 for(int i=0; i<(int)meshes.size(); i++) {
49 for(int i=0; i<(int)objects.size(); i++) {
55 static void destroy_node_tree(SceneNode *n)
59 int nsub = n->get_num_children();
60 for(int i=0; i<nsub; i++) {
61 destroy_node_tree(n->get_child(i));
66 // Scene::load defined in sceneload.cc
68 bool Scene::merge(Scene *scn)
72 walk_mesh->append(*scn->walk_mesh);
73 delete scn->walk_mesh;
77 walk_mesh = scn->walk_mesh;
81 int nmeshes = scn->meshes.size();
82 for(int i=0; i<nmeshes; i++) {
83 meshes.push_back(scn->meshes[i]);
87 int nobj = scn->objects.size();
88 for(int i=0; i<nobj; i++) {
89 objects.push_back(scn->objects[i]);
94 int nchildren = scn->nodes ? scn->nodes->get_num_children() : 0;
95 for(int i=0; i<nchildren; i++) {
96 SceneNode *n = scn->nodes->get_child(i);
97 scn->nodes->remove_child(n);
100 if(scn->nodes && scn->nodes->get_num_objects() > 0) {
101 warning_log("merging with scene which has objects in its root node. these objects will not be merged!\n");
112 void Scene::add_object(Object *obj)
114 objects.push_back(obj);
117 bool Scene::remove_object(Object *obj)
119 std::vector<Object*>::iterator it = std::find(objects.begin(), objects.end(), obj);
120 if(it != objects.end()) {
127 bool Scene::have_object(Object *obj) const
129 return std::find(objects.begin(), objects.end(), obj) != objects.end();
132 void Scene::add_mesh(Mesh *m)
137 bool Scene::remove_mesh(Mesh *m)
139 std::vector<Mesh*>::iterator it = std::find(meshes.begin(), meshes.end(), m);
140 if(it != meshes.end()) {
147 bool Scene::have_mesh(Mesh *m) const
149 return std::find(meshes.begin(), meshes.end(), m) != meshes.end();
152 void Scene::add_node(SceneNode *n)
154 // we always want to have a dedicated root node
156 nodes = new SceneNode;
158 nodes->set_name("root");
164 bool Scene::remove_node(SceneNode *n)
167 if(!n || !(par = n->get_parent())) {
171 int nsub = n->get_num_children();
172 for(int i=0; i<nsub; i++) {
173 SceneNode *c = n->get_child(i);
178 return par->remove_child(n);
181 bool Scene::have_node(SceneNode *n) const
183 return n->scene == this;
186 /* traverse scene graph and find node by name */
187 static SceneNode *find_node_rec(SceneNode *tree, const char *name)
189 if(strcmp(tree->get_name(), name) == 0) {
193 int num = tree->get_num_children();
194 for(int i=0; i<num; i++) {
195 SceneNode *n = find_node_rec(tree->get_child(i), name);
201 static SceneNode *find_node_rec(SceneNode *tree, const std::regex &re)
203 if(std::regex_match(tree->get_name(), re)) {
207 int num = tree->get_num_children();
208 for(int i=0; i<num; i++) {
209 SceneNode *n = find_node_rec(tree->get_child(i), re);
215 static void find_nodes_rec(std::list<SceneNode*> *res, SceneNode *tree, const std::regex &re)
217 if(std::regex_match(tree->get_name(), re)) {
218 res->push_back(tree);
221 int num = tree->get_num_children();
222 for(int i=0; i<num; i++) {
223 find_nodes_rec(res, tree->get_child(i), re);
227 SceneNode *Scene::find_node(const char *name) const
230 return find_node_rec(nodes, name);
233 SceneNode *Scene::match_node(const char *qstr) const
238 return find_node_rec(nodes, re);
241 std::list<SceneNode*> Scene::match_nodes(const char *qstr) const
243 std::list<SceneNode*> res;
246 find_nodes_rec(&res, nodes, re);
248 return std::move(res);
251 Scene *Scene::extract_nodes(const char *qstr)
257 std::list<SceneNode*> nodelist;
258 find_nodes_rec(&nodelist, nodes, re);
259 if(nodelist.empty()) {
263 Scene *res = new Scene;
265 for(SceneNode *n : nodelist) {
267 int nobj = n->get_num_objects();
268 for(int i=0; i<nobj; i++) {
269 Object *obj = n->get_object(i);
270 if(obj->get_type() == OBJ_MESH) {
271 // XXX this assumes that meshes aren't shared between objects.
272 // maybe we'll have to refcount them at some point, and copy if nref>1
273 ObjMesh *om = (ObjMesh*)obj;
274 remove_mesh(om->mesh);
275 res->add_mesh(om->mesh);
279 res->add_object(obj);
288 void Scene::apply_xform()
290 nodes->apply_xform();
293 void Scene::update(float dt)
299 int nobj = objects.size();
300 for(int i=0; i<nobj; i++) {
301 if(!objects[i]->node) {
302 // only update objects which don't belong to a scenegraph node
303 // to avoid updating objects twice
304 objects[i]->update(dt);
309 void Scene::draw() const
311 if(!objects.empty()) {
312 int nobj = objects.size();
313 for(int i=0; i<nobj; i++) {
317 int nmesh = meshes.size();
318 for(int i=0; i<nmesh; i++) {