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)
46 const char* name() const
48 return m_name.c_str();
50 void attach(const NameCallback& callback)
53 void detach(const NameCallback& callback)
59 class UndoFileChangeTracker : public UndoTracker, public MapFile
63 typedef void (UndoFileChangeTracker::*Pending)();
68 UndoFileChangeTracker() : m_size(0), m_saved(MAPFILE_MAX_CHANGES), m_pending(0)
73 globalOutputStream() << "saved: " << Unsigned(m_saved) << " size: " << Unsigned(m_size) << "\n";
92 // redo queue has been flushed.. it is now impossible to get back to the saved state via undo/redo
93 m_saved = MAPFILE_MAX_CHANGES;
105 m_pending = Pending(&UndoFileChangeTracker::pushOperation);
109 m_pending = Pending(&UndoFileChangeTracker::pop);
113 m_pending = Pending(&UndoFileChangeTracker::push);
120 ((*this).*m_pending)();
132 return m_saved == m_size;
135 void setChangedCallback(const Callback& changed)
141 std::size_t changes() const
148 class MapRoot : public scene::Node::Symbiot, public scene::Instantiable, public scene::Traversable::Observer
152 NodeTypeCastTable m_casts;
156 NodeStaticCast<MapRoot, scene::Instantiable>::install(m_casts);
157 NodeContainedCast<MapRoot, scene::Traversable>::install(m_casts);
158 NodeContainedCast<MapRoot, TransformNode>::install(m_casts);
159 NodeContainedCast<MapRoot, Nameable>::install(m_casts);
160 NodeContainedCast<MapRoot, MapFile>::install(m_casts);
162 NodeTypeCastTable& get()
169 IdentityTransform m_transform;
170 TraversableNodeSet m_traverse;
171 InstanceSet m_instances;
172 typedef SelectableInstance Instance;
173 NameableString m_name;
174 UndoFileChangeTracker m_changeTracker;
176 typedef LazyStatic<TypeCasts> StaticTypeCasts;
178 scene::Traversable& get(NullType<scene::Traversable>)
182 TransformNode& get(NullType<TransformNode>)
186 Nameable& get(NullType<Nameable>)
190 MapFile& get(NullType<MapFile>)
192 return m_changeTracker;
195 MapRoot(const char* name) : m_node(this, this, StaticTypeCasts::instance().get()), m_name(name)
197 m_node.m_isRoot = true;
199 m_traverse.attach(this);
201 GlobalUndoSystem().trackerAttach(m_changeTracker);
208 GlobalUndoSystem().trackerDetach(m_changeTracker);
210 m_traverse.detach(this);
218 InstanceCounter m_instanceCounter;
219 void instanceAttach(const scene::Path& path)
221 if(++m_instanceCounter.m_count == 1)
223 m_traverse.instanceAttach(path_find_mapfile(path.begin(), path.end()));
226 void instanceDetach(const scene::Path& path)
228 if(--m_instanceCounter.m_count == 0)
230 m_traverse.instanceDetach(path_find_mapfile(path.begin(), path.end()));
234 void insert(scene::Node& child)
236 m_instances.insert(child);
238 void erase(scene::Node& child)
240 m_instances.erase(child);
243 scene::Node& clone() const
245 return (new MapRoot(*this))->node();
248 scene::Instance* create(const scene::Path& path, scene::Instance* parent)
250 return new Instance(path, parent);
252 void forEachInstance(const scene::Instantiable::Visitor& visitor)
254 m_instances.forEachInstance(visitor);
256 void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
258 m_instances.insert(observer, path, instance);
259 instanceAttach(path);
261 scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
263 instanceDetach(path);
264 return m_instances.erase(observer, path);
268 inline void MapRoot_construct()
272 inline void MapRoot_destroy()
276 inline NodeSmartReference NewMapRoot(const char* name)
278 return NodeSmartReference((new MapRoot(name))->node());