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 class StringEqualPredicate
40 StringEqualPredicate( const char* string ) : m_string( string ){
42 bool operator()( const char* other ) const {
43 return string_equal( m_string, other );
47 template<std::size_t SIZE>
50 typedef const char* TypeName;
51 typedef TypeName TypeNames[SIZE];
52 TypeNames m_typeNames;
53 TypeName* m_typeNamesEnd;
56 TypeIdMap() : m_typeNamesEnd( m_typeNames ){
58 TypeId getTypeId( const char* name ){
59 TypeName* i = std::find_if( m_typeNames, m_typeNamesEnd, StringEqualPredicate( name ) );
60 if ( i == m_typeNamesEnd ) {
61 ASSERT_MESSAGE( m_typeNamesEnd != m_typeNames + SIZE, "reached maximum number of type names supported (" << Unsigned( SIZE ) << ")" );
62 *m_typeNamesEnd++ = name;
64 return i - m_typeNames;
68 class CompiledGraph : public scene::Graph, public scene::Instantiable::Observer
70 typedef std::map<PathConstReference, scene::Instance*> InstanceMap;
72 InstanceMap m_instances;
73 scene::Instantiable::Observer* m_observer;
74 Signal0 m_boundsChanged;
75 scene::Path m_rootpath;
76 Signal0 m_sceneChangedCallbacks;
78 TypeIdMap<NODETYPEID_MAX> m_nodeTypeIds;
79 TypeIdMap<INSTANCETYPEID_MAX> m_instanceTypeIds;
83 CompiledGraph( scene::Instantiable::Observer* observer )
84 : m_observer( observer ){
87 void addSceneChangedCallback( const SignalHandler& handler ){
88 m_sceneChangedCallbacks.connectLast( handler );
91 m_sceneChangedCallbacks();
95 ASSERT_MESSAGE( !m_rootpath.empty(), "scenegraph root does not exist" );
96 return m_rootpath.top();
98 void insert_root( scene::Node& root ){
99 //globalOutputStream() << "insert_root\n";
101 ASSERT_MESSAGE( m_rootpath.empty(), "scenegraph root already exists" );
105 Node_traverseSubgraph( root, InstanceSubgraphWalker( this, scene::Path(), 0 ) );
107 m_rootpath.push( makeReference( root ) );
110 //globalOutputStream() << "erase_root\n";
112 ASSERT_MESSAGE( !m_rootpath.empty(), "scenegraph root does not exist" );
114 scene::Node& root = m_rootpath.top();
118 Node_traverseSubgraph( root, UninstanceSubgraphWalker( this, scene::Path() ) );
122 void boundsChanged(){
126 void traverse( const Walker& walker ){
127 traverse_subgraph( walker, m_instances.begin() );
130 void traverse_subgraph( const Walker& walker, const scene::Path& start ){
131 if ( !m_instances.empty() ) {
132 traverse_subgraph( walker, m_instances.find( PathConstReference( start ) ) );
136 scene::Instance* find( const scene::Path& path ){
137 InstanceMap::iterator i = m_instances.find( PathConstReference( path ) );
138 if ( i == m_instances.end() ) {
141 return ( *i ).second;
144 void insert( scene::Instance* instance ){
145 m_instances.insert( InstanceMap::value_type( PathConstReference( instance->path() ), instance ) );
147 m_observer->insert( instance );
149 void erase( scene::Instance* instance ){
150 m_observer->erase( instance );
152 m_instances.erase( PathConstReference( instance->path() ) );
155 SignalHandlerId addBoundsChangedCallback( const SignalHandler& boundsChanged ){
156 return m_boundsChanged.connectLast( boundsChanged );
158 void removeBoundsChangedCallback( SignalHandlerId id ){
159 m_boundsChanged.disconnect( id );
162 TypeId getNodeTypeId( const char* name ){
163 return m_nodeTypeIds.getTypeId( name );
166 TypeId getInstanceTypeId( const char* name ){
167 return m_instanceTypeIds.getTypeId( name );
172 bool pre( const Walker& walker, const InstanceMap::iterator& i ){
173 return walker.pre( i->first, *i->second );
176 void post( const Walker& walker, const InstanceMap::iterator& i ){
177 walker.post( i->first, *i->second );
180 void traverse_subgraph( const Walker& walker, InstanceMap::iterator i ){
181 Stack<InstanceMap::iterator> stack;
182 if ( i != m_instances.end() ) {
183 const std::size_t startSize = ( *i ).first.get().size();
186 if ( i != m_instances.end()
187 && stack.size() < ( ( *i ).first.get().size() - startSize + 1 ) ) {
190 if ( !pre( walker, stack.top() ) ) {
192 while ( i != m_instances.end()
193 && stack.size() < ( ( *i ).first.get().size() - startSize + 1 ) )
201 post( walker, stack.top() );
205 while ( !stack.empty() );
212 CompiledGraph* g_sceneGraph;
213 GraphTreeModel* g_tree_model;
216 GraphTreeModel* scene_graph_get_tree_model(){
221 class SceneGraphObserver : public scene::Instantiable::Observer
224 void insert( scene::Instance* instance ){
225 g_sceneGraph->sceneChanged();
226 graph_tree_model_insert( g_tree_model, *instance );
228 void erase( scene::Instance* instance ){
229 g_sceneGraph->sceneChanged();
230 graph_tree_model_erase( g_tree_model, *instance );
234 SceneGraphObserver g_SceneGraphObserver;
236 void SceneGraph_Construct(){
237 g_tree_model = graph_tree_model_new();
239 g_sceneGraph = new CompiledGraph( &g_SceneGraphObserver );
242 void SceneGraph_Destroy(){
245 graph_tree_model_delete( g_tree_model );
249 #include "modulesystem/singletonmodule.h"
250 #include "modulesystem/moduleregistry.h"
254 scene::Graph* m_scenegraph;
256 typedef scene::Graph Type;
257 STRING_CONSTANT( Name, "*" );
260 SceneGraph_Construct();
262 m_scenegraph = g_sceneGraph;
265 SceneGraph_Destroy();
267 scene::Graph* getTable(){
272 typedef SingletonModule<SceneGraphAPI> SceneGraphModule;
273 typedef Static<SceneGraphModule> StaticSceneGraphModule;
274 StaticRegisterModule staticRegisterSceneGraph( StaticSceneGraphModule::instance() );