instancelib.h

Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2001-2006, William Joseph.
00003  All Rights Reserved.
00004 
00005  This file is part of GtkRadiant.
00006 
00007  GtkRadiant is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU General Public License as published by
00009  the Free Software Foundation; either version 2 of the License, or
00010  (at your option) any later version.
00011 
00012  GtkRadiant is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU General Public License for more details.
00016 
00017  You should have received a copy of the GNU General Public License
00018  along with GtkRadiant; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  */
00021 
00022 #if !defined (INCLUDED_INSTANCELIB_H)
00023 #define INCLUDED_INSTANCELIB_H
00024 
00025 #include "debugging/debugging.h"
00026 
00027 #include "iscenegraph.h"
00028 
00029 #include "scenelib.h"
00030 #include "generic/reference.h"
00031 #include "generic/callback.h"
00032 #include <map>
00033 
00034 class InstanceSubgraphWalker: public scene::Traversable::Walker
00035 {
00036         scene::Instantiable::Observer* m_observer;
00037         mutable scene::Path m_path;
00038         mutable Stack<scene::Instance*> m_parent;
00039     public:
00040         InstanceSubgraphWalker (scene::Instantiable::Observer* observer, const scene::Path& path,
00041                 scene::Instance* parent) :
00042             m_observer(observer), m_path(path), m_parent(parent)
00043         {
00044         }
00045         ~InstanceSubgraphWalker ()
00046         {
00047         }
00048         bool pre (scene::Node& node) const
00049         {
00050             m_path.push(makeReference(node));
00051             scene::Instance* instance = Node_getInstantiable(node)->create(m_path, m_parent.top());
00052             m_observer->insert(instance);
00053             Node_getInstantiable(node)->insert(m_observer, m_path, instance);
00054             m_parent.push(instance);
00055             return true;
00056         }
00057         void post (scene::Node& node) const
00058         {
00059             m_path.pop();
00060             m_parent.pop();
00061         }
00062 };
00063 
00064 class UninstanceSubgraphWalker: public scene::Traversable::Walker
00065 {
00066         scene::Instantiable::Observer* m_observer;
00067         mutable scene::Path m_path;
00068     public:
00069         UninstanceSubgraphWalker (scene::Instantiable::Observer* observer, const scene::Path& parent) :
00070             m_observer(observer), m_path(parent)
00071         {
00072         }
00073         ~UninstanceSubgraphWalker ()
00074         {
00075         }
00076         bool pre (scene::Node& node) const
00077         {
00078             m_path.push(makeReference(node));
00079             return true;
00080         }
00081         void post (scene::Node& node) const
00082         {
00083             scene::Instance* instance = Node_getInstantiable(node)->erase(m_observer, m_path);
00084             m_observer->erase(instance);
00085             delete instance;
00086             m_path.pop();
00087         }
00088 };
00089 
00090 class InstanceSet: public scene::Traversable::Observer
00091 {
00092         typedef std::pair<scene::Instantiable::Observer*, PathConstReference> CachePath;
00093 
00094         typedef CachePath key_type;
00095 
00096         typedef std::map<key_type, scene::Instance*> InstanceMap;
00097         InstanceMap m_instances;
00098     public:
00099 
00100         typedef InstanceMap::iterator iterator;
00101 
00102         ~InstanceSet ()
00103         {
00104         }
00105         iterator begin ()
00106         {
00107             return m_instances.begin();
00108         }
00109         iterator end ()
00110         {
00111             return m_instances.end();
00112         }
00113 
00114         // traverse observer
00115         void insert (scene::Node& child)
00116         {
00117             for (iterator i = begin(); i != end(); ++i) {
00118                 Node_traverseSubgraph(child, InstanceSubgraphWalker((*i).first.first, (*i).first.second, (*i).second));
00119                 (*i).second->boundsChanged();
00120             }
00121         }
00122         void erase (scene::Node& child)
00123         {
00124             for (iterator i = begin(); i != end(); ++i) {
00125                 Node_traverseSubgraph(child, UninstanceSubgraphWalker((*i).first.first, (*i).first.second));
00126                 (*i).second->boundsChanged();
00127             }
00128         }
00129 
00130         // instance
00131         void forEachInstance (const scene::Instantiable::Visitor& visitor)
00132         {
00133             for (iterator i = begin(); i != end(); ++i) {
00134                 visitor.visit(*(*i).second);
00135             }
00136         }
00137 
00138         void insert (scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance)
00139         {
00140             ASSERT_MESSAGE(m_instances.find(key_type(observer, PathConstReference(instance->path()))) == m_instances.end(), "InstanceSet::insert - element already exists");
00141             m_instances.insert(InstanceMap::value_type(key_type(observer, PathConstReference(instance->path())),
00142                     instance));
00143         }
00144         scene::Instance* erase (scene::Instantiable::Observer* observer, const scene::Path& path)
00145         {
00146             ASSERT_MESSAGE(m_instances.find(key_type(observer, PathConstReference(path))) != m_instances.end(), "InstanceSet::erase - failed to find element");
00147             InstanceMap::iterator i = m_instances.find(key_type(observer, PathConstReference(path)));
00148             scene::Instance* instance = i->second;
00149             m_instances.erase(i);
00150             return instance;
00151         }
00152 
00153         void transformChanged ()
00154         {
00155             for (InstanceMap::iterator i = m_instances.begin(); i != m_instances.end(); ++i) {
00156                 (*i).second->transformChanged();
00157             }
00158         }
00159         typedef MemberCaller<InstanceSet, &InstanceSet::transformChanged> TransformChangedCaller;
00160         void boundsChanged ()
00161         {
00162             for (InstanceMap::iterator i = m_instances.begin(); i != m_instances.end(); ++i) {
00163                 (*i).second->boundsChanged();
00164             }
00165         }
00166         typedef MemberCaller<InstanceSet, &InstanceSet::boundsChanged> BoundsChangedCaller;
00167 };
00168 
00169 template<typename Functor>
00170 inline void InstanceSet_forEach (InstanceSet& instances, const Functor& functor)
00171 {
00172     for (InstanceSet::iterator i = instances.begin(), end = instances.end(); i != end; ++i) {
00173         functor(*(*i).second);
00174     }
00175 }
00176 
00177 template<typename Type>
00178 class InstanceEvaluateTransform
00179 {
00180     public:
00181         inline
00182         void operator() (scene::Instance& instance) const
00183         {
00184             InstanceTypeCast<Type>::cast(instance)->evaluateTransform();
00185         }
00186 };
00187 
00188 template<typename Type>
00189 class InstanceSetEvaluateTransform
00190 {
00191     public:
00192         static void apply (InstanceSet& instances)
00193         {
00194             InstanceSet_forEach(instances, InstanceEvaluateTransform<Type> ());
00195         }
00196         typedef ReferenceCaller<InstanceSet, &InstanceSetEvaluateTransform<Type>::apply> Caller;
00197 };
00198 
00199 #endif

Generated by  doxygen 1.6.2