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_INSTANCELIB_H)
23 #define INCLUDED_INSTANCELIB_H
25 #include "debugging/debugging.h"
27 #include "iscenegraph.h"
30 #include "generic/reference.h"
31 #include "generic/callback.h"
34 class InstanceSubgraphWalker : public scene::Traversable::Walker
36 scene::Instantiable::Observer* m_observer;
37 mutable scene::Path m_path;
38 mutable Stack<scene::Instance*> m_parent;
40 InstanceSubgraphWalker(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* parent)
41 : m_observer(observer), m_path(path), m_parent(parent)
44 bool pre(scene::Node& node) const
46 m_path.push(makeReference(node));
47 scene::Instance* instance = Node_getInstantiable(node)->create(m_path, m_parent.top());
48 m_observer->insert(instance);
49 Node_getInstantiable(node)->insert(m_observer, m_path, instance);
50 m_parent.push(instance);
53 void post(scene::Node& node) const
60 class UninstanceSubgraphWalker : public scene::Traversable::Walker
62 scene::Instantiable::Observer* m_observer;
63 mutable scene::Path m_path;
65 UninstanceSubgraphWalker(scene::Instantiable::Observer* observer, const scene::Path& parent)
66 : m_observer(observer), m_path(parent)
69 bool pre(scene::Node& node) const
71 m_path.push(makeReference(node));
74 void post(scene::Node& node) const
76 scene::Instance* instance = Node_getInstantiable(node)->erase(m_observer, m_path);
77 m_observer->erase(instance);
83 class InstanceSet : public scene::Traversable::Observer
85 typedef std::pair<scene::Instantiable::Observer*, PathConstReference> CachePath;
87 typedef CachePath key_type;
89 typedef std::map<key_type, scene::Instance*> InstanceMap;
90 InstanceMap m_instances;
93 typedef InstanceMap::iterator iterator;
97 return m_instances.begin();
101 return m_instances.end();
105 void insert(scene::Node& child)
107 for(iterator i = begin(); i != end(); ++i)
109 Node_traverseSubgraph(child, InstanceSubgraphWalker((*i).first.first, (*i).first.second, (*i).second));
110 (*i).second->boundsChanged();
113 void erase(scene::Node& child)
115 for(iterator i = begin(); i != end(); ++i)
117 Node_traverseSubgraph(child, UninstanceSubgraphWalker((*i).first.first, (*i).first.second));
118 (*i).second->boundsChanged();
123 void forEachInstance(const scene::Instantiable::Visitor& visitor)
125 for(iterator i = begin(); i != end(); ++i)
127 visitor.visit(*(*i).second);
131 void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
133 ASSERT_MESSAGE(m_instances.find(key_type(observer, PathConstReference(instance->path()))) == m_instances.end(), "InstanceSet::insert - element already exists");
134 m_instances.insert(InstanceMap::value_type(key_type(observer, PathConstReference(instance->path())), instance));
136 scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path)
138 ASSERT_MESSAGE(m_instances.find(key_type(observer, PathConstReference(path))) != m_instances.end(), "InstanceSet::erase - failed to find element");
139 InstanceMap::iterator i = m_instances.find(key_type(observer, PathConstReference(path)));
140 scene::Instance* instance = i->second;
141 m_instances.erase(i);
145 void transformChanged()
147 for(InstanceMap::iterator i = m_instances.begin(); i != m_instances.end(); ++i)
149 (*i).second->transformChanged();
152 typedef MemberCaller<InstanceSet, &InstanceSet::transformChanged> TransformChangedCaller;
155 for(InstanceMap::iterator i = m_instances.begin(); i != m_instances.end(); ++i)
157 (*i).second->boundsChanged();
160 typedef MemberCaller<InstanceSet, &InstanceSet::boundsChanged> BoundsChangedCaller;
163 template<typename Functor>
164 inline void InstanceSet_forEach(InstanceSet& instances, const Functor& functor)
166 for(InstanceSet::iterator i = instances.begin(), end = instances.end(); i != end; ++i)
168 functor(*(*i).second);
172 template<typename Type>
173 class InstanceEvaluateTransform
176 inline void operator()(scene::Instance& instance) const
178 InstanceTypeCast<Type>::cast(instance)->evaluateTransform();
182 template<typename Type>
183 class InstanceSetEvaluateTransform
186 static void apply(InstanceSet& instances)
188 InstanceSet_forEach(instances, InstanceEvaluateTransform<Type>());
190 typedef ReferenceCaller<InstanceSet, &InstanceSetEvaluateTransform<Type>::apply> Caller;