5 static void destroy_node_tree(SceneNode *n);
7 Scene::Scene(TextureSet *tset)
17 texset = new TextureSet;
29 destroy_node_tree(nodes);
32 for(int i=0; i<(int)meshes.size(); i++) {
40 for(int i=0; i<(int)objects.size(); i++) {
51 static void destroy_node_tree(SceneNode *n)
55 int nsub = n->get_num_children();
56 for(int i=0; i<nsub; i++) {
57 destroy_node_tree(n->get_child(i));
62 // Scene::load defined in sceneload.cc
64 bool Scene::merge(Scene *scn)
66 if(texset != scn->texset) {
67 // TODO handle this properly
68 error_log("for now only able to merge scenes using the same texture set\n");
74 walk_mesh->append(*scn->walk_mesh);
75 delete scn->walk_mesh;
79 walk_mesh = scn->walk_mesh;
83 int nmeshes = scn->meshes.size();
84 for(int i=0; i<nmeshes; i++) {
85 meshes.push_back(scn->meshes[i]);
89 int nobj = scn->objects.size();
90 for(int i=0; i<nobj; i++) {
91 objects.push_back(scn->objects[i]);
96 int nchildren = scn->nodes ? scn->nodes->get_num_children() : 0;
97 for(int i=0; i<nchildren; i++) {
98 SceneNode *n = scn->nodes->get_child(i);
99 scn->nodes->remove_child(n);
102 if(scn->nodes && scn->nodes->get_num_objects() > 0) {
103 warning_log("merging with scene which has objects in its root node. these objects will not be merged!\n");
114 void Scene::add_object(Object *obj)
116 objects.push_back(obj);
119 bool Scene::remove_object(Object *obj)
121 std::vector<Object*>::iterator it = std::find(objects.begin(), objects.end(), obj);
122 if(it != objects.end()) {
129 bool Scene::have_object(Object *obj) const
131 return std::find(objects.begin(), objects.end(), obj) != objects.end();
134 void Scene::add_mesh(Mesh *m)
139 bool Scene::remove_mesh(Mesh *m)
141 std::vector<Mesh*>::iterator it = std::find(meshes.begin(), meshes.end(), m);
142 if(it != meshes.end()) {
149 bool Scene::have_mesh(Mesh *m) const
151 return std::find(meshes.begin(), meshes.end(), m) != meshes.end();
154 void Scene::add_node(SceneNode *n)
156 // we always want to have a dedicated root node
158 nodes = new SceneNode;
160 nodes->set_name("root");
166 bool Scene::remove_node(SceneNode *n)
169 if(!n || !(par = n->get_parent())) {
173 int nsub = n->get_num_children();
174 for(int i=0; i<nsub; i++) {
175 SceneNode *c = n->get_child(i);
180 return par->remove_child(n);
183 bool Scene::have_node(SceneNode *n) const
185 return n->scene == this;
188 static void find_nodes_rec(std::list<SceneNode*> *res, SceneNode *tree, const std::regex &re)
190 if(std::regex_match(tree->get_name(), re)) {
191 res->push_back(tree);
194 int num = tree->get_num_children();
195 for(int i=0; i<num; i++) {
196 find_nodes_rec(res, tree->get_child(i), re);
200 Scene *Scene::extract_nodes(const char *qstr)
204 std::list<SceneNode*> nodelist;
205 find_nodes_rec(&nodelist, nodes, re);
206 if(nodelist.empty()) {
210 Scene *res = new Scene(texset);
212 for(SceneNode *n : nodelist) {
214 int nobj = n->get_num_objects();
215 for(int i=0; i<nobj; i++) {
216 Object *obj = n->get_object(i);
217 if(obj->get_type() == OBJ_MESH) {
218 // XXX this assumes that meshes aren't shared between objects.
219 // maybe we'll have to refcount them at some point, and copy if nref>1
220 ObjMesh *om = (ObjMesh*)obj;
221 remove_mesh(om->mesh);
222 res->add_mesh(om->mesh);
226 res->add_object(obj);
235 void Scene::apply_xform()
237 nodes->apply_xform();
240 void Scene::update(float dt)
246 int nobj = objects.size();
247 for(int i=0; i<nobj; i++) {
248 if(!objects[i]->node) {
249 // only update objects which don't belong to a scenegraph node
250 // to avoid updating objects twice
251 objects[i]->update(dt);
256 void Scene::draw() const
258 if(!objects.empty()) {
259 int nobj = objects.size();
260 for(int i=0; i<nobj; i++) {
264 int nmesh = meshes.size();
265 for(int i=0; i<nmesh; i++) {