]> icculus.org git repositories - divverent/netradiant.git/blob - include/iscenegraph.h
Merge remote branch 'icculus/master'
[divverent/netradiant.git] / include / iscenegraph.h
1 /*
2 Copyright (C) 2001-2006, William Joseph.
3 All Rights Reserved.
4
5 This file is part of GtkRadiant.
6
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.
11
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.
16
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
20 */
21
22 #if !defined (INCLUDED_ISCENEGRAPH_H)
23 #define INCLUDED_ISCENEGRAPH_H
24
25 #include <cstddef>
26 #include "generic/constant.h"
27 #include "signal/signalfwd.h"
28
29 template<typename value_type>
30 class Stack;
31 template<typename Contained>
32 class Reference;
33
34 namespace scene
35 {
36   class Instance;
37   const Instance* const nullInstancePointer = 0;
38   inline const Instance& nullInstance()
39   {
40     return *nullInstancePointer;
41   }
42
43   class Node;
44   const Node* const nullNodePointer = 0;
45   inline const Node& nullNode()
46   {
47     return *nullNodePointer;
48   }
49 }
50
51 typedef Reference<scene::Node> NodeReference;
52
53 typedef std::size_t TypeId;
54
55 const TypeId NODETYPEID_MAX = 64;
56 const TypeId NODETYPEID_NONE = NODETYPEID_MAX;
57
58 const TypeId INSTANCETYPEID_MAX = 64;
59 const TypeId INSTANCETYPEID_NONE = INSTANCETYPEID_MAX;
60
61 namespace scene
62 {
63   /// \brief A unique key to an instance of a node in the scene-graph.
64   typedef Stack<NodeReference> Path;
65
66   /// \brief A scene-graph - a Directed Acyclic Graph (DAG).
67   ///
68   /// - Each node may refer to zero or more 'child' nodes (directed).
69   /// - A node may never have itself as one of its ancestors (acyclic).
70   /// - Each node may have more than one 'parent', thus having more than one 'instance' in the graph.
71   /// - Each instance is uniquely identified by the list of its ancestors plus itself, known as a 'path'.
72   class Graph
73   {
74   public:
75     INTEGER_CONSTANT(Version, 1);
76     STRING_CONSTANT(Name, "scenegraph");
77
78     class Walker
79     {
80     public:
81       /// \brief Called before traversing the first child-instance of 'instance'. If the return value is false, the children of the current instance are not traversed.
82       virtual bool pre(const Path& path, Instance& instance) const = 0;
83       /// \brief Called after traversing the last child-instance of 'instance'.
84       virtual void post(const Path& path, Instance& instance) const
85       {
86       }
87     };
88
89     /// \brief Returns the root-node of the graph.
90     virtual Node& root() = 0;
91     /// \brief Sets the root-node of the graph to be 'node'.
92     virtual void insert_root(Node& root) = 0;
93     /// \brief Clears the root-node of the graph.
94     virtual void erase_root() = 0;
95     /// \brief Traverses all nodes in the graph depth-first, starting from the root node.
96     virtual void traverse(const Walker& walker) = 0;
97     /// \brief Traverses all nodes in the graph depth-first, starting from 'start'.
98     virtual void traverse_subgraph(const Walker& walker, const Path& start) = 0;
99     /// \brief Returns the instance at the location identified by 'path', or 0 if it does not exist.
100     virtual scene::Instance* find(const Path& path) = 0;
101
102     /// \brief Invokes all scene-changed callbacks. Called when any part of the scene changes the way it will appear when the scene is rendered.
103     /// \todo Move to a separate class.
104     virtual void sceneChanged() = 0;
105     /// \brief Add a \p callback to be invoked when the scene changes.
106     /// \todo Move to a separate class.
107     virtual void addSceneChangedCallback(const SignalHandler& handler) = 0;
108
109     /// \brief Invokes all bounds-changed callbacks. Called when the bounds of any instance in the scene change.
110     /// \todo Move to a separate class.
111     virtual void boundsChanged() = 0;
112     /// \brief Add a \p callback to be invoked when the bounds of any instance in the scene change.
113     virtual SignalHandlerId addBoundsChangedCallback(const SignalHandler& boundsChanged) = 0;
114     /// \brief Remove a \p callback to be invoked when the bounds of any instance in the scene change.
115     virtual void removeBoundsChangedCallback(SignalHandlerId id) = 0;
116
117     virtual TypeId getNodeTypeId(const char* name) = 0;
118     virtual TypeId getInstanceTypeId(const char* name) = 0;
119   };
120
121   class Traversable
122   {
123   public:
124     STRING_CONSTANT(Name, "scene::Traversable");
125
126     class Observer
127     {
128     public:
129       /// \brief Called when a node is added to the container.
130       virtual void insert(Node& node) = 0;
131       /// \brief Called when a node is removed from the container.
132       virtual void erase(Node& node) = 0;
133     };
134
135     class Walker
136     {
137     public:
138       /// \brief Called before traversing the first child-node of 'node'. If the return value is false, the children of the current node are not traversed.
139       virtual bool pre(Node& node) const = 0;
140       /// \brief Called after traversing the last child-node of 'node'. 
141       virtual void post(Node& node) const
142       {
143       }
144     };
145     /// \brief Adds a node to the container.
146     virtual void insert(Node& node) = 0;
147     /// \brief Removes a node from the container.
148     virtual void erase(Node& node) = 0;
149     /// \brief Traverses the subgraphs rooted at each node in the container, depth-first.
150     virtual void traverse(const Walker& walker) = 0;
151     /// \brief Returns true if the container contains no nodes.
152     virtual bool empty() const = 0;
153   };
154
155   class Instantiable
156   {
157   public:
158     STRING_CONSTANT(Name, "scene::Instantiable");
159
160     class Observer
161     {
162     public:
163       /// \brief Called when an instance is added to the container.
164       virtual void insert(scene::Instance* instance) = 0;
165       /// \brief Called when an instance is removed from the container.
166       virtual void erase(scene::Instance* instance) = 0;
167     };
168
169     class Visitor
170     {
171     public:
172       virtual void visit(Instance& instance) const = 0;
173     };
174
175     /// \brief Returns a new instance uniquely identified by 'path'.
176     virtual scene::Instance* create(const scene::Path& path, scene::Instance* parent) = 0;
177     /// \brief Calls Visitor::visit(instance) for each instance in the container.
178     virtual void forEachInstance(const Visitor& visitor) = 0;
179     /// \brief Adds an instance to the container.
180     virtual void insert(Observer* observer, const Path& path, scene::Instance* instance) = 0;
181     /// \brief Returns an instance removed from the container.
182     virtual scene::Instance* erase(Observer* observer, const Path& path) = 0;
183   };
184
185   class Cloneable
186   {
187   public:
188     STRING_CONSTANT(Name, "scene::Cloneable");
189
190     /// \brief Returns a copy of itself.
191     virtual scene::Node& clone() const = 0;
192   };
193 }
194
195 #include "modulesystem.h"
196
197 template<typename Type>
198 class GlobalModule;
199 typedef GlobalModule<scene::Graph> GlobalSceneGraphModule;
200
201 template<typename Type>
202 class GlobalModuleRef;
203 typedef GlobalModuleRef<scene::Graph> GlobalSceneGraphModuleRef;
204
205 inline scene::Graph& GlobalSceneGraph()
206 {
207   return GlobalSceneGraphModule::getTable();
208 }
209
210 inline void AddSceneChangeCallback(const SignalHandler& handler)
211 {
212   GlobalSceneGraph().addSceneChangedCallback(handler);
213 }
214 inline void SceneChangeNotify()
215 {
216   GlobalSceneGraph().sceneChanged();
217 }
218
219
220
221 #endif