maplib.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #if !defined (INCLUDED_MAPLIB_H)
00023 #define INCLUDED_MAPLIB_H
00024
00025 #include "nameable.h"
00026 #include "mapfile.h"
00027
00028 #include "traverselib.h"
00029 #include "transformlib.h"
00030 #include "scenelib.h"
00031 #include "string/string.h"
00032 #include "instancelib.h"
00033 #include "selectionlib.h"
00034 #include "generic/callback.h"
00035
00036 class NameableString: public Nameable
00037 {
00038 std::string m_name;
00039 public:
00040 NameableString (const std::string& name) :
00041 m_name(name)
00042 {
00043 }
00044
00045 std::string name () const
00046 {
00047 return m_name;
00048 }
00049 void attach (const NameCallback& callback)
00050 {
00051 }
00052 void detach (const NameCallback& callback)
00053 {
00054 }
00055 };
00056
00057 const std::size_t MAPFILE_MAX_CHANGES = std::numeric_limits<std::size_t>::max();
00058
00059 class UndoFileChangeTracker: public UndoTracker, public MapFile
00060 {
00061 std::size_t m_size;
00062 std::size_t m_saved;
00063 typedef void (UndoFileChangeTracker::*Pending) ();
00064 Pending m_pending;
00065 Callback m_changed;
00066
00067 public:
00068 UndoFileChangeTracker () :
00069 m_size(0), m_saved(MAPFILE_MAX_CHANGES), m_pending(0)
00070 {
00071 }
00072 void print ()
00073 {
00074 globalOutputStream() << "saved: " << Unsigned(m_saved) << " size: " << Unsigned(m_size) << "\n";
00075 }
00076
00077 void push ()
00078 {
00079 ++m_size;
00080 m_changed();
00081
00082 }
00083 void pop ()
00084 {
00085 --m_size;
00086 m_changed();
00087
00088 }
00089 void pushOperation ()
00090 {
00091 if (m_size < m_saved) {
00092
00093 m_saved = MAPFILE_MAX_CHANGES;
00094 }
00095 push();
00096 }
00097 void clear ()
00098 {
00099 m_size = 0;
00100 m_changed();
00101
00102 }
00103 void clearRedo (void)
00104 {
00105
00106 }
00107 void begin ()
00108 {
00109 m_pending = Pending(&UndoFileChangeTracker::pushOperation);
00110 }
00111 void undo ()
00112 {
00113 m_pending = Pending(&UndoFileChangeTracker::pop);
00114 }
00115 void redo ()
00116 {
00117 m_pending = Pending(&UndoFileChangeTracker::push);
00118 }
00119
00120 void changed ()
00121 {
00122 if (m_pending != 0) {
00123 ((*this).*m_pending)();
00124 m_pending = 0;
00125 }
00126 }
00127
00128 void save ()
00129 {
00130 m_saved = m_size;
00131 m_changed();
00132 }
00133 bool saved () const
00134 {
00135 return m_saved == m_size;
00136 }
00137
00138 void setChangedCallback (const Callback& changed)
00139 {
00140 m_changed = changed;
00141 m_changed();
00142 }
00143
00144 std::size_t changes () const
00145 {
00146 return m_size;
00147 }
00148 };
00149
00150 class MapRoot: public scene::Node, public scene::Instantiable, public scene::Traversable::Observer
00151 {
00152 class TypeCasts
00153 {
00154 NodeTypeCastTable m_casts;
00155 public:
00156 TypeCasts ()
00157 {
00158 NodeContainedCast<MapRoot, scene::Traversable>::install(m_casts);
00159 NodeContainedCast<MapRoot, TransformNode>::install(m_casts);
00160 NodeContainedCast<MapRoot, MapFile>::install(m_casts);
00161 }
00162 NodeTypeCastTable& get ()
00163 {
00164 return m_casts;
00165 }
00166 };
00167
00168 IdentityTransform m_transform;
00169 TraversableNodeSet m_traverse;
00170 InstanceSet m_instances;
00171 typedef SelectableInstance Instance;
00172 NameableString m_name;
00173 UndoFileChangeTracker m_changeTracker;
00174 public:
00175 typedef LazyStatic<TypeCasts> StaticTypeCasts;
00176
00177 scene::Traversable& get (NullType<scene::Traversable> )
00178 {
00179 return m_traverse;
00180 }
00181 TransformNode& get (NullType<TransformNode> )
00182 {
00183 return m_transform;
00184 }
00185 Nameable& get (NullType<Nameable> )
00186 {
00187 return m_name;
00188 }
00189 MapFile& get (NullType<MapFile> )
00190 {
00191 return m_changeTracker;
00192 }
00193
00194 MapRoot (const std::string& name) :
00195 scene::Node(this, StaticTypeCasts::instance().get()), m_name(name)
00196 {
00197 m_isRoot = true;
00198
00199 m_traverse.attach(this);
00200
00201 GlobalUndoSystem().trackerAttach(m_changeTracker);
00202 }
00203 ~MapRoot ()
00204 {
00205 GlobalUndoSystem().trackerDetach(m_changeTracker);
00206 m_traverse.detach(this);
00207 }
00208 scene::Node& node ()
00209 {
00210 return *this;
00211 }
00212
00213 InstanceCounter m_instanceCounter;
00214 void instanceAttach (const scene::Path& path)
00215 {
00216 if (++m_instanceCounter.m_count == 1) {
00217 m_traverse.instanceAttach(path_find_mapfile(path.begin(), path.end()));
00218 }
00219 }
00220 void instanceDetach (const scene::Path& path)
00221 {
00222 if (--m_instanceCounter.m_count == 0) {
00223 m_traverse.instanceDetach(path_find_mapfile(path.begin(), path.end()));
00224 }
00225 }
00226
00227 void insert (scene::Node& child)
00228 {
00229 m_instances.insert(child);
00230 }
00231 void erase (scene::Node& child)
00232 {
00233 m_instances.erase(child);
00234 }
00235
00236 scene::Node& clone () const
00237 {
00238 return (new MapRoot(*this))->node();
00239 }
00240
00241 scene::Instance* create (const scene::Path& path, scene::Instance* parent)
00242 {
00243 return new Instance(path, parent);
00244 }
00245 void forEachInstance (const scene::Instantiable::Visitor& visitor)
00246 {
00247 m_instances.forEachInstance(visitor);
00248 }
00249 void insert (scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
00250 {
00251 m_instances.insert(observer, path, instance);
00252 instanceAttach(path);
00253 }
00254 scene::Instance* erase (scene::Instantiable::Observer* observer, const scene::Path& path)
00255 {
00256 instanceDetach(path);
00257 return m_instances.erase(observer, path);
00258 }
00259 };
00260
00261 inline void MapRoot_Construct ()
00262 {
00263 }
00264
00265 inline void MapRoot_Destroy ()
00266 {
00267 }
00268
00269 inline NodeSmartReference NewMapRoot (const std::string& name)
00270 {
00271 return NodeSmartReference((new MapRoot(name))->node());
00272 }
00273
00274 #endif