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 "signal/signal.h"
33 #include "instancelib.h"
34 #include "treemodel.h"
36 template<std::size_t SIZE>
39 typedef const char* TypeName;
40 typedef TypeName TypeNames[SIZE];
41 TypeNames m_typeNames;
42 TypeName* m_typeNamesEnd;
45 TypeIdMap() : m_typeNamesEnd( m_typeNames ){
47 TypeId getTypeId( const char* name ){
48 TypeName *i = std::find_if(m_typeNames, m_typeNamesEnd, [&](const char *other) {
49 return string_equal(name, other);
51 if ( i == m_typeNamesEnd ) {
52 ASSERT_MESSAGE( m_typeNamesEnd != m_typeNames + SIZE, "reached maximum number of type names supported (" << Unsigned( SIZE ) << ")" );
53 *m_typeNamesEnd++ = name;
55 return i - m_typeNames;
59 class CompiledGraph : public scene::Graph, public scene::Instantiable::Observer
61 typedef std::map<PathConstReference, scene::Instance*> InstanceMap;
63 InstanceMap m_instances;
64 scene::Instantiable::Observer* m_observer;
65 Signal0 m_boundsChanged;
66 scene::Path m_rootpath;
67 Signal0 m_sceneChangedCallbacks;
69 TypeIdMap<NODETYPEID_MAX> m_nodeTypeIds;
70 TypeIdMap<INSTANCETYPEID_MAX> m_instanceTypeIds;
74 CompiledGraph( scene::Instantiable::Observer* observer )
75 : m_observer( observer ){
78 void addSceneChangedCallback( const SignalHandler& handler ){
79 m_sceneChangedCallbacks.connectLast( handler );
82 m_sceneChangedCallbacks();
86 ASSERT_MESSAGE( !m_rootpath.empty(), "scenegraph root does not exist" );
87 return m_rootpath.top();
89 void insert_root( scene::Node& root ){
90 //globalOutputStream() << "insert_root\n";
92 ASSERT_MESSAGE( m_rootpath.empty(), "scenegraph root already exists" );
96 Node_traverseSubgraph( root, InstanceSubgraphWalker( this, scene::Path(), 0 ) );
98 m_rootpath.push( makeReference( root ) );
101 //globalOutputStream() << "erase_root\n";
103 ASSERT_MESSAGE( !m_rootpath.empty(), "scenegraph root does not exist" );
105 scene::Node& root = m_rootpath.top();
109 Node_traverseSubgraph( root, UninstanceSubgraphWalker( this, scene::Path() ) );
113 void boundsChanged(){
117 void traverse( const Walker& walker ){
118 traverse_subgraph( walker, m_instances.begin() );
121 void traverse_subgraph( const Walker& walker, const scene::Path& start ){
122 if ( !m_instances.empty() ) {
123 traverse_subgraph( walker, m_instances.find( PathConstReference( start ) ) );
127 scene::Instance* find( const scene::Path& path ){
128 InstanceMap::iterator i = m_instances.find( PathConstReference( path ) );
129 if ( i == m_instances.end() ) {
132 return ( *i ).second;
135 void insert( scene::Instance* instance ){
136 m_instances.insert( InstanceMap::value_type( PathConstReference( instance->path() ), instance ) );
138 m_observer->insert( instance );
140 void erase( scene::Instance* instance ){
141 m_observer->erase( instance );
143 m_instances.erase( PathConstReference( instance->path() ) );
146 SignalHandlerId addBoundsChangedCallback( const SignalHandler& boundsChanged ){
147 return m_boundsChanged.connectLast( boundsChanged );
149 void removeBoundsChangedCallback( SignalHandlerId id ){
150 m_boundsChanged.disconnect( id );
153 TypeId getNodeTypeId( const char* name ){
154 return m_nodeTypeIds.getTypeId( name );
157 TypeId getInstanceTypeId( const char* name ){
158 return m_instanceTypeIds.getTypeId( name );
163 bool pre( const Walker& walker, const InstanceMap::iterator& i ){
164 return walker.pre( i->first, *i->second );
167 void post( const Walker& walker, const InstanceMap::iterator& i ){
168 walker.post( i->first, *i->second );
171 void traverse_subgraph( const Walker& walker, InstanceMap::iterator i ){
172 Stack<InstanceMap::iterator> stack;
173 if ( i != m_instances.end() ) {
174 const std::size_t startSize = ( *i ).first.get().size();
177 if ( i != m_instances.end()
178 && stack.size() < ( ( *i ).first.get().size() - startSize + 1 ) ) {
181 if ( !pre( walker, stack.top() ) ) {
183 while ( i != m_instances.end()
184 && stack.size() < ( ( *i ).first.get().size() - startSize + 1 ) )
192 post( walker, stack.top() );
196 while ( !stack.empty() );
203 CompiledGraph* g_sceneGraph;
204 GraphTreeModel* g_tree_model;
207 GraphTreeModel* scene_graph_get_tree_model(){
212 class SceneGraphObserver : public scene::Instantiable::Observer
215 void insert( scene::Instance* instance ){
216 g_sceneGraph->sceneChanged();
217 graph_tree_model_insert( g_tree_model, *instance );
219 void erase( scene::Instance* instance ){
220 g_sceneGraph->sceneChanged();
221 graph_tree_model_erase( g_tree_model, *instance );
225 SceneGraphObserver g_SceneGraphObserver;
227 void SceneGraph_Construct(){
228 g_tree_model = graph_tree_model_new();
230 g_sceneGraph = new CompiledGraph( &g_SceneGraphObserver );
233 void SceneGraph_Destroy(){
236 graph_tree_model_delete( g_tree_model );
240 #include "modulesystem/singletonmodule.h"
241 #include "modulesystem/moduleregistry.h"
245 scene::Graph* m_scenegraph;
247 typedef scene::Graph Type;
248 STRING_CONSTANT( Name, "*" );
251 SceneGraph_Construct();
253 m_scenegraph = g_sceneGraph;
256 SceneGraph_Destroy();
258 scene::Graph* getTable(){
263 typedef SingletonModule<SceneGraphAPI> SceneGraphModule;
264 typedef Static<SceneGraphModule> StaticSceneGraphModule;
265 StaticRegisterModule staticRegisterSceneGraph( StaticSceneGraphModule::instance() );