2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "scenegraph.h"
24 #include "debugging/debugging.h"
30 #include "string/string.h"
31 #include "generic/callback.h"
33 #include "instancelib.h"
34 #include "treemodel.h"
36 class StringEqualPredicate
40 StringEqualPredicate(const char* string) : m_string(string)
43 bool operator()(const char* other) const
45 return string_equal(m_string, other);
49 template<std::size_t SIZE>
52 typedef const char* TypeName;
53 typedef TypeName TypeNames[SIZE];
54 TypeNames m_typeNames;
55 TypeName* m_typeNamesEnd;
58 TypeIdMap() : m_typeNamesEnd(m_typeNames)
61 TypeId getTypeId(const char* name)
63 TypeName* i = std::find_if(m_typeNames, m_typeNamesEnd, StringEqualPredicate(name));
64 if(i == m_typeNamesEnd)
66 ASSERT_MESSAGE(m_typeNamesEnd != m_typeNames + SIZE, "reached maximum number of type names supported (" << Unsigned(SIZE) << ")");
67 *m_typeNamesEnd++ = name;
69 return i - m_typeNames;
73 class CompiledGraph : public scene::Graph, public scene::Instantiable::Observer
75 typedef std::map<PathConstReference, scene::Instance*> InstanceMap;
77 InstanceMap m_instances;
78 scene::Instantiable::Observer* m_observer;
79 typedef std::set<Callback> BoundsChangedCallbacks;
80 BoundsChangedCallbacks m_boundsChanged;
81 scene::Path m_rootpath;
82 std::vector<Callback> m_sceneChangedCallbacks;
84 TypeIdMap<NODETYPEID_MAX> m_nodeTypeIds;
85 TypeIdMap<INSTANCETYPEID_MAX> m_instanceTypeIds;
89 CompiledGraph(scene::Instantiable::Observer* observer)
90 : m_observer(observer)
94 void addSceneChangedCallback(const Callback& callback)
96 m_sceneChangedCallbacks.push_back(callback);
100 std::for_each(m_sceneChangedCallbacks.begin(), m_sceneChangedCallbacks.end(), CallbackInvoke());
105 ASSERT_MESSAGE(!m_rootpath.empty(), "scenegraph root does not exist");
106 return *m_rootpath.top();
108 void insert_root(scene::Node& root)
110 //globalOutputStream() << "insert_root\n";
112 ASSERT_MESSAGE(m_rootpath.empty(), "scenegraph root already exists");
116 Node_traverseSubgraph(root, InstanceSubgraphWalker(this, scene::Path(), 0));
118 m_rootpath.push(makeReference(root));
122 //globalOutputStream() << "erase_root\n";
124 ASSERT_MESSAGE(!m_rootpath.empty(), "scenegraph root does not exist");
126 scene::Node& root = *m_rootpath.top();
130 Node_traverseSubgraph(root, UninstanceSubgraphWalker(this, scene::Path()));
136 std::for_each(m_boundsChanged.begin(), m_boundsChanged.end(), CallbackInvoke());
139 void traverse(const Walker& walker)
141 traverse_subgraph(walker, m_instances.begin());
144 void traverse_subgraph(const Walker& walker, const scene::Path& start)
146 if(!m_instances.empty())
148 traverse_subgraph(walker, m_instances.find(PathConstReference(start)));
152 scene::Instance* find(const scene::Path& path)
154 InstanceMap::iterator i = m_instances.find(PathConstReference(path));
155 if(i == m_instances.end())
162 void insert(scene::Instance* instance)
164 m_instances.insert(InstanceMap::value_type(PathConstReference(instance->path()), instance));
166 m_observer->insert(instance);
168 void erase(scene::Instance* instance)
170 m_observer->erase(instance);
172 m_instances.erase(PathConstReference(instance->path()));
175 void addBoundsChangedCallback(const Callback& boundsChanged)
177 ASSERT_MESSAGE(m_boundsChanged.find(boundsChanged) == m_boundsChanged.end(), "bounds-changed callback already registered");
178 m_boundsChanged.insert(boundsChanged);
180 void removeBoundsChangedCallback(const Callback& boundsChanged)
182 ASSERT_MESSAGE(m_boundsChanged.find(boundsChanged) != m_boundsChanged.end(), "bounds-changed callback not registered");
183 m_boundsChanged.erase(boundsChanged);
186 TypeId getNodeTypeId(const char* name)
188 return m_nodeTypeIds.getTypeId(name);
191 TypeId getInstanceTypeId(const char* name)
193 return m_instanceTypeIds.getTypeId(name);
198 bool pre(const Walker& walker, const InstanceMap::iterator& i)
200 return walker.pre(i->first, *i->second);
203 void post(const Walker& walker, const InstanceMap::iterator& i)
205 walker.post(i->first, *i->second);
208 void traverse_subgraph(const Walker& walker, InstanceMap::iterator i)
210 Stack<InstanceMap::iterator> stack;
211 if(i != m_instances.end())
213 const std::size_t startSize = (*i).first.get().size();
216 if(i != m_instances.end()
217 && stack.size() < ((*i).first.get().size() - startSize + 1))
221 if(!pre(walker, stack.top()))
224 while(i != m_instances.end()
225 && stack.size() < ((*i).first.get().size() - startSize + 1))
233 post(walker, stack.top());
237 while(!stack.empty());
244 CompiledGraph* g_sceneGraph;
245 GraphTreeModel* g_tree_model;
248 GraphTreeModel* scene_graph_get_tree_model()
254 class SceneGraphObserver : public scene::Instantiable::Observer
257 void insert(scene::Instance* instance)
259 g_sceneGraph->sceneChanged();
260 graph_tree_model_insert(g_tree_model, *instance);
262 void erase(scene::Instance* instance)
264 g_sceneGraph->sceneChanged();
265 graph_tree_model_erase(g_tree_model, *instance);
269 SceneGraphObserver g_SceneGraphObserver;
271 void SceneGraph_Construct()
273 g_tree_model = graph_tree_model_new();
275 g_sceneGraph = new CompiledGraph(&g_SceneGraphObserver);
278 void SceneGraph_Destroy()
282 graph_tree_model_delete(g_tree_model);
286 #include "modulesystem/singletonmodule.h"
287 #include "modulesystem/moduleregistry.h"
291 scene::Graph* m_scenegraph;
293 typedef scene::Graph Type;
294 STRING_CONSTANT(Name, "*");
298 SceneGraph_Construct();
300 m_scenegraph = g_sceneGraph;
304 SceneGraph_Destroy();
306 scene::Graph* getTable()
312 typedef SingletonModule<SceneGraphAPI> SceneGraphModule;
313 typedef Static<SceneGraphModule> StaticSceneGraphModule;
314 StaticRegisterModule staticRegisterSceneGraph(StaticSceneGraphModule::instance());