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 #if !defined ( INCLUDED_MAPLIB_H )
23 #define INCLUDED_MAPLIB_H
28 #include "traverselib.h"
29 #include "transformlib.h"
31 #include "string/string.h"
32 #include "instancelib.h"
33 #include "selectionlib.h"
34 #include "generic/callback.h"
37 class NameableString : public Nameable
41 NameableString( const char* name )
45 const char* name() const {
46 return m_name.c_str();
48 void attach( const NameCallback& callback ){
50 void detach( const NameCallback& callback ){
55 class UndoFileChangeTracker : public UndoTracker, public MapFile
59 typedef void ( UndoFileChangeTracker::*Pending )();
61 Callback<void()> m_changed;
64 UndoFileChangeTracker() : m_size( 0 ), m_saved( MAPFILE_MAX_CHANGES ), m_pending( 0 ){
67 globalOutputStream() << "saved: " << Unsigned( m_saved ) << " size: " << Unsigned( m_size ) << "\n";
81 if ( m_size < m_saved ) {
82 // redo queue has been flushed.. it is now impossible to get back to the saved state via undo/redo
83 m_saved = MAPFILE_MAX_CHANGES;
93 m_pending = Pending( &UndoFileChangeTracker::pushOperation );
96 m_pending = Pending( &UndoFileChangeTracker::pop );
99 m_pending = Pending( &UndoFileChangeTracker::push );
103 if ( m_pending != 0 ) {
104 ( ( *this ).*m_pending )();
114 return m_saved == m_size;
117 void setChangedCallback( const Callback<void()>& changed ){
122 std::size_t changes() const {
128 class MapRoot : public scene::Node::Symbiot, public scene::Instantiable, public scene::Traversable::Observer
132 NodeTypeCastTable m_casts;
135 NodeStaticCast<MapRoot, scene::Instantiable>::install( m_casts );
136 NodeContainedCast<MapRoot, scene::Traversable>::install( m_casts );
137 NodeContainedCast<MapRoot, TransformNode>::install( m_casts );
138 NodeContainedCast<MapRoot, Nameable>::install( m_casts );
139 NodeContainedCast<MapRoot, MapFile>::install( m_casts );
141 NodeTypeCastTable& get(){
147 IdentityTransform m_transform;
148 TraversableNodeSet m_traverse;
149 InstanceSet m_instances;
150 typedef SelectableInstance Instance;
151 NameableString m_name;
152 UndoFileChangeTracker m_changeTracker;
154 typedef LazyStatic<TypeCasts> StaticTypeCasts;
156 scene::Traversable& get( NullType<scene::Traversable>){
159 TransformNode& get( NullType<TransformNode>){
162 Nameable& get( NullType<Nameable>){
165 MapFile& get( NullType<MapFile>){
166 return m_changeTracker;
169 MapRoot( const char* name ) : m_node( this, this, StaticTypeCasts::instance().get() ), m_name( name ){
170 m_node.m_isRoot = true;
172 m_traverse.attach( this );
174 GlobalUndoSystem().trackerAttach( m_changeTracker );
179 GlobalUndoSystem().trackerDetach( m_changeTracker );
181 m_traverse.detach( this );
188 InstanceCounter m_instanceCounter;
189 void instanceAttach( const scene::Path& path ){
190 if ( ++m_instanceCounter.m_count == 1 ) {
191 m_traverse.instanceAttach( path_find_mapfile( path.begin(), path.end() ) );
194 void instanceDetach( const scene::Path& path ){
195 if ( --m_instanceCounter.m_count == 0 ) {
196 m_traverse.instanceDetach( path_find_mapfile( path.begin(), path.end() ) );
200 void insert( scene::Node& child ){
201 m_instances.insert( child );
203 void erase( scene::Node& child ){
204 m_instances.erase( child );
207 scene::Node& clone() const {
208 return ( new MapRoot( *this ) )->node();
211 scene::Instance* create( const scene::Path& path, scene::Instance* parent ){
212 return new Instance( path, parent );
214 void forEachInstance( const scene::Instantiable::Visitor& visitor ){
215 m_instances.forEachInstance( visitor );
217 void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){
218 m_instances.insert( observer, path, instance );
219 instanceAttach( path );
221 scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){
222 instanceDetach( path );
223 return m_instances.erase( observer, path );
227 inline void MapRoot_construct(){
230 inline void MapRoot_destroy(){
233 inline NodeSmartReference NewMapRoot( const char* name ){
234 return NodeSmartReference( ( new MapRoot( name ) )->node() );