]> icculus.org git repositories - divverent/netradiant.git/blob - libs/scenelib.h
Remove unnecessary locale/UTF-8 encoding conversions
[divverent/netradiant.git] / libs / scenelib.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_SCENELIB_H)
23 #define INCLUDED_SCENELIB_H
24
25 #include "iscenegraph.h"
26 #include "iselection.h"
27
28 #include "warnings.h"
29 #include <cstddef>
30 #include <string.h>
31
32 #include "math/aabb.h"
33 #include "transformlib.h"
34 #include "generic/callback.h"
35 #include "generic/reference.h"
36 #include "container/stack.h"
37 #include "typesystem.h"
38
39 class Selector;
40 class SelectionTest;
41 class VolumeTest;
42 template<typename Element> class BasicVector3;
43 typedef BasicVector3<float> Vector3;
44 template<typename Element> class BasicVector4;
45 typedef BasicVector4<float> Vector4;
46 class Matrix4;
47 typedef Vector4 Quaternion;
48 class AABB;
49
50 class ComponentSelectionTestable
51 {
52 public:
53   STRING_CONSTANT(Name, "ComponentSelectionTestable");
54
55   virtual bool isSelectedComponents() const = 0;
56   virtual void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) = 0;
57   virtual void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) = 0;
58 };
59
60 class ComponentEditable
61 {
62 public:
63   STRING_CONSTANT(Name, "ComponentEditable");
64
65   virtual const AABB& getSelectedComponentsBounds() const = 0;
66 };
67
68 class ComponentSnappable
69 {
70 public:
71   STRING_CONSTANT(Name, "ComponentSnappable");
72
73   virtual void snapComponents(float snap) = 0;
74 };
75
76 class Bounded
77 {
78 public:
79   STRING_CONSTANT(Name, "Bounded");
80
81   virtual const AABB& localAABB() const = 0;
82 };
83
84 class BrushDoom3
85 {
86 public:
87   STRING_CONSTANT(Name, "BrushDoom3");
88
89   virtual void setDoom3GroupOrigin(const Vector3& origin) = 0;
90 };
91
92
93
94
95 typedef TypeCastTable<NODETYPEID_MAX> NodeTypeCastTable;
96
97 template<typename Type>
98 class NodeType : public StaticTypeSystemInitialiser
99 {
100   TypeId m_typeId;
101 public:
102   typedef typename Type::Name Name;
103   NodeType() : m_typeId(NODETYPEID_NONE)
104   {
105     StaticTypeSystemInitialiser::instance().addInitialiser(InitialiseCaller(*this));
106   }
107   void initialise()
108   {
109     m_typeId = GlobalSceneGraph().getNodeTypeId(Name());
110   }
111   typedef MemberCaller<NodeType<Type>, &NodeType<Type>::initialise> InitialiseCaller;
112   TypeId getTypeId()
113   {
114 #if defined(_DEBUG)
115     ASSERT_MESSAGE(m_typeId != NODETYPEID_NONE, "node-type " << makeQuoted(Name()) << " used before being initialised");
116 #endif
117     return m_typeId;
118   }
119 };
120
121 template<typename Type>
122 class StaticNodeType
123 {
124 public:
125   enum unnamed0 { SIZE = NODETYPEID_MAX };
126   static TypeId getTypeId()
127   {
128     return Static< NodeType<Type> >::instance().getTypeId();
129   }
130 };
131
132 template<typename Type, typename Base>
133 class NodeStaticCast :
134   public CastInstaller<
135     StaticNodeType<Base>,
136     StaticCast<Type, Base>
137   >
138 {
139 };
140
141 template<typename Type, typename Contained>
142 class NodeContainedCast :
143   public CastInstaller<
144     StaticNodeType<Contained>,
145     ContainedCast<Type, Contained>
146   >
147 {
148 };
149
150 template<typename Type>
151 class NodeIdentityCast :
152   public CastInstaller<
153     StaticNodeType<Type>,
154     IdentityCast<Type>
155   >
156 {
157 };
158
159 namespace scene
160 {
161   class Node
162   {
163   public:
164     enum unnamed0 { eVisible = 0 };
165     enum unnamed1 { eHidden = 1 << 0 };
166     enum unnamed2 { eFiltered = 1 << 1 };
167     enum unnamed3 { eExcluded = 1 << 2 };
168
169     class Symbiot
170     {
171     public:
172       virtual void release() = 0;
173     };
174
175   private:
176     unsigned int m_state;
177     std::size_t m_refcount;
178     Symbiot* m_symbiot;
179     void* m_node;
180     NodeTypeCastTable& m_casts;
181
182   public:
183     bool m_isRoot;
184
185     bool isRoot()
186     {
187       return m_isRoot;
188     }
189
190     Node(Symbiot* symbiot, void* node, NodeTypeCastTable& casts) :
191       m_state(eVisible),
192       m_refcount(0),
193       m_symbiot(symbiot),
194       m_node(node),
195       m_casts(casts),
196       m_isRoot(false)
197     {
198     }
199     ~Node()
200     {
201     }
202
203     void IncRef()
204     {
205       ASSERT_MESSAGE(m_refcount < (1 << 24), "Node::decref: uninitialised refcount");
206       ++m_refcount;
207     }
208     void DecRef()
209     {
210       ASSERT_MESSAGE(m_refcount < (1 << 24), "Node::decref: uninitialised refcount");
211       if(--m_refcount == 0)
212       {
213         m_symbiot->release();
214       }
215     }
216     std::size_t getReferenceCount() const
217     {
218       return m_refcount;
219     }
220
221     void* cast(TypeId typeId) const
222     {
223       return m_casts.cast(typeId, m_node);
224     }
225
226     void enable(unsigned int state)
227     {
228       m_state |= state;
229     }
230     void disable(unsigned int state)
231     {
232       m_state &= ~state;
233     }
234     bool visible()
235     {
236       return m_state == eVisible;
237     }
238     bool excluded()
239     {
240       return (m_state & eExcluded) != 0;
241     }
242   };
243
244   class NullNode : public Node::Symbiot
245   {
246     NodeTypeCastTable m_casts;
247     Node m_node;
248   public:
249     NullNode() : m_node(this, 0, m_casts)
250     {
251     }
252     void release()
253     {
254       delete this;
255     }
256     scene::Node& node()
257     {
258       return m_node;
259     }
260   };
261 }
262
263 template<typename Type>
264 class NodeTypeCast
265 {
266 public:
267   static Type* cast(scene::Node& node)
268   {
269     return static_cast<Type*>(node.cast(StaticNodeType<Type>::getTypeId()));
270   }
271   static const Type* cast(const scene::Node& node)
272   {
273     return static_cast<const Type*>(node.cast(StaticNodeType<Type>::getTypeId()));
274   }
275 };
276
277
278 inline scene::Instantiable* Node_getInstantiable(scene::Node& node)
279 {
280   return NodeTypeCast<scene::Instantiable>::cast(node);
281 }
282
283 inline scene::Traversable* Node_getTraversable(scene::Node& node)
284 {
285   return NodeTypeCast<scene::Traversable>::cast(node);
286 }
287
288 inline void Node_traverseSubgraph(scene::Node& node, const scene::Traversable::Walker& walker)
289 {
290   if(walker.pre(node))
291   {
292     scene::Traversable* traversable = Node_getTraversable(node);
293     if(traversable != 0)
294     {
295       traversable->traverse(walker);
296     }
297   }
298   walker.post(node);
299 }
300
301 inline TransformNode* Node_getTransformNode(scene::Node& node)
302 {
303   return NodeTypeCast<TransformNode>::cast(node);
304 }
305
306 inline bool operator<(scene::Node& node, scene::Node& other)
307 {
308   return &node < &other;
309 }
310 inline bool operator==(scene::Node& node, scene::Node& other)
311 {
312   return &node == &other;
313 }
314 inline bool operator!=(scene::Node& node, scene::Node& other)
315 {
316   return !::operator==(node, other);
317 }
318
319
320 inline scene::Node& NewNullNode()
321 {
322   return (new scene::NullNode)->node();
323 }
324
325 inline void Path_deleteTop(const scene::Path& path)
326 {
327   Node_getTraversable(path.parent())->erase(path.top());
328 }
329
330
331
332
333
334 class delete_all : public scene::Traversable::Walker
335 {
336   scene::Node& m_parent;
337 public:
338   delete_all(scene::Node& parent) : m_parent(parent)
339   {
340   }
341   bool pre(scene::Node& node) const
342   {
343     return false;
344   }
345   void post(scene::Node& node) const
346   {
347     Node_getTraversable(m_parent)->erase(node);
348   }
349 };
350
351 inline void DeleteSubgraph(scene::Node& subgraph)
352 {
353   Node_getTraversable(subgraph)->traverse(delete_all(subgraph));
354 }
355
356
357 class EntityUndefined
358 {
359 public:
360   STRING_CONSTANT(Name, "Entity");
361 };
362
363 inline bool Node_isEntity(scene::Node& node)
364 {
365   return NodeTypeCast<EntityUndefined>::cast(node) != 0;
366 }
367
368 template<typename Functor>
369 class EntityWalker : public scene::Graph::Walker
370 {
371   const Functor& functor;
372 public:
373   EntityWalker(const Functor& functor) : functor(functor)
374   {
375   }
376   bool pre(const scene::Path& path, scene::Instance& instance) const
377   {
378     if(Node_isEntity(path.top()))
379     {
380       functor(instance);
381       return false;
382     }
383     return true;
384   }
385 };
386
387 template<typename Functor>
388 inline const Functor& Scene_forEachEntity(const Functor& functor)
389 {
390   GlobalSceneGraph().traverse(EntityWalker<Functor>(functor));
391   return functor;
392 }
393
394 class BrushUndefined
395 {
396 public:
397   STRING_CONSTANT(Name, "Brush");
398 };
399
400 inline bool Node_isBrush(scene::Node& node)
401 {
402   return NodeTypeCast<BrushUndefined>::cast(node) != 0;
403 }
404
405 class PatchUndefined
406 {
407 public:
408   STRING_CONSTANT(Name, "Patch");
409 };
410
411 inline bool Node_isPatch(scene::Node& node)
412 {
413   return NodeTypeCast<PatchUndefined>::cast(node) != 0;
414 }
415
416 inline bool Node_isPrimitive(scene::Node& node)
417 {
418 #if 1
419   return Node_isBrush(node) || Node_isPatch(node);
420 #else
421   return !node.isRoot();
422 #endif
423 }
424
425 class ParentBrushes : public scene::Traversable::Walker
426 {
427   scene::Node& m_parent;
428 public:
429   ParentBrushes(scene::Node& parent)
430     : m_parent(parent)
431   {
432   }
433   bool pre(scene::Node& node) const
434   {
435     return false;
436   }
437   void post(scene::Node& node) const
438   {
439     if(Node_isPrimitive(node))
440     {
441       Node_getTraversable(m_parent)->insert(node);
442     }
443   }
444 };
445
446 inline void parentBrushes(scene::Node& subgraph, scene::Node& parent)
447 {
448   Node_getTraversable(subgraph)->traverse(ParentBrushes(parent));
449 }
450
451 class HasBrushes : public scene::Traversable::Walker
452 {
453   bool& m_hasBrushes;
454 public:
455   HasBrushes(bool& hasBrushes)
456     : m_hasBrushes(hasBrushes)
457   {
458     m_hasBrushes = true;
459   }
460   bool pre(scene::Node& node) const
461   {
462     if(!Node_isPrimitive(node))
463     {
464       m_hasBrushes = false;
465     }
466     return false;
467   }
468 };
469
470 inline bool node_is_group(scene::Node& node)
471 {
472   scene::Traversable* traversable = Node_getTraversable(node);
473   if(traversable != 0)
474   {
475     bool hasBrushes = false;
476     traversable->traverse(HasBrushes(hasBrushes));
477     return hasBrushes;
478   }
479   return false;
480 }
481
482 typedef TypeCastTable<INSTANCETYPEID_MAX> InstanceTypeCastTable;
483
484 template<typename Type>
485 class InstanceType : public StaticTypeSystemInitialiser
486 {
487   TypeId m_typeId;
488 public:
489   typedef typename Type::Name Name;
490   InstanceType() : m_typeId(INSTANCETYPEID_NONE)
491   {
492     StaticTypeSystemInitialiser::instance().addInitialiser(InitialiseCaller(*this));
493   }
494   void initialise()
495   {
496     m_typeId = GlobalSceneGraph().getInstanceTypeId(Name());
497   }
498   typedef MemberCaller<InstanceType<Type>, &InstanceType<Type>::initialise> InitialiseCaller;
499   TypeId getTypeId()
500   {
501 #if defined(_DEBUG)
502     ASSERT_MESSAGE(m_typeId != INSTANCETYPEID_NONE, "instance-type " << makeQuoted(Name()) << " used before being initialised");
503 #endif
504     return m_typeId;
505   }
506 };
507
508 template<typename Type>
509 class StaticInstanceType
510 {
511 public:
512   enum unnamed0 { SIZE = INSTANCETYPEID_MAX };
513   static TypeId getTypeId()
514   {
515     return Static< InstanceType<Type> >::instance().getTypeId();
516   }
517 };
518
519 template<typename Type, typename Base>
520 class InstanceStaticCast :
521   public CastInstaller<
522     StaticInstanceType<Base>,
523     StaticCast<Type, Base>
524   >
525 {
526 };
527
528 template<typename Type, typename Contained>
529 class InstanceContainedCast :
530   public CastInstaller<
531     StaticInstanceType<Contained>,
532     ContainedCast<Type, Contained>
533   >
534 {
535 };
536
537 template<typename Type>
538 class InstanceIdentityCast :
539   public CastInstaller<
540     StaticInstanceType<Type>,
541     IdentityCast<Type>
542   >
543 {
544 };
545
546
547 inline Selectable* Instance_getSelectable(scene::Instance& instance);
548 inline const Selectable* Instance_getSelectable(const scene::Instance& instance);
549
550 inline Bounded* Instance_getBounded(scene::Instance& instance);
551 inline const Bounded* Instance_getBounded(const scene::Instance& instance);
552
553 namespace scene
554 {
555   class Instance
556   {
557     class AABBAccumulateWalker : public scene::Graph::Walker
558     {
559       AABB& m_aabb;
560       mutable std::size_t m_depth;
561     public:
562       AABBAccumulateWalker(AABB& aabb) : m_aabb(aabb), m_depth(0)
563       {
564       }
565       bool pre(const scene::Path& path, scene::Instance& instance) const
566       {
567         if(m_depth == 1)
568         {
569           aabb_extend_by_aabb_safe(m_aabb, instance.worldAABB());
570         }
571         return ++m_depth != 2;
572       }
573       void post(const scene::Path& path, scene::Instance& instance) const
574       {
575         --m_depth;
576       }
577     };
578
579
580     class TransformChangedWalker : public scene::Graph::Walker
581     {
582     public:
583       bool pre(const scene::Path& path, scene::Instance& instance) const
584       {
585         instance.transformChangedLocal();
586         return true;
587       }
588     };
589
590     class ParentSelectedChangedWalker : public scene::Graph::Walker
591     {
592     public:
593       bool pre(const scene::Path& path, scene::Instance& instance) const
594       {
595         instance.parentSelectedChanged();
596         return true;
597       }
598     };
599
600     class ChildSelectedWalker : public scene::Graph::Walker
601     {
602       bool& m_childSelected;
603       mutable std::size_t m_depth;
604     public:
605       ChildSelectedWalker(bool& childSelected) : m_childSelected(childSelected), m_depth(0)
606       {
607         m_childSelected = false;
608       }
609       bool pre(const scene::Path& path, scene::Instance& instance) const
610       {
611         if(m_depth == 1 && !m_childSelected)
612         {
613           m_childSelected = instance.isSelected() || instance.childSelected();
614         }
615         return ++m_depth != 2;
616       }
617       void post(const scene::Path& path, scene::Instance& instance) const
618       {
619         --m_depth;
620       }
621     };
622
623     Path m_path;
624     Instance* m_parent;
625     void* m_instance;
626     InstanceTypeCastTable& m_casts;
627
628     mutable Matrix4 m_local2world;
629     mutable AABB m_bounds;
630     mutable AABB m_childBounds;
631     mutable bool m_transformChanged;
632     mutable bool m_transformMutex;
633     mutable bool m_boundsChanged;
634     mutable bool m_boundsMutex;
635     mutable bool m_childBoundsChanged;
636     mutable bool m_childBoundsMutex;
637     mutable bool m_isSelected;
638     mutable bool m_isSelectedChanged;
639     mutable bool m_childSelected;
640     mutable bool m_childSelectedChanged;
641     mutable bool m_parentSelected;
642     mutable bool m_parentSelectedChanged;
643     Callback m_childSelectedChangedCallback;
644     Callback m_transformChangedCallback;
645
646
647     void evaluateTransform() const
648     {
649       if(m_transformChanged)
650       {
651         ASSERT_MESSAGE(!m_transformMutex, "re-entering transform evaluation");
652         m_transformMutex = true;
653
654         m_local2world = (m_parent != 0) ? m_parent->localToWorld() : g_matrix4_identity;
655         TransformNode* transformNode = Node_getTransformNode(m_path.top());
656         if(transformNode != 0)
657         {
658           matrix4_multiply_by_matrix4(m_local2world, transformNode->localToParent());
659         }
660
661         m_transformMutex = false;
662         m_transformChanged = false;
663       }
664     }
665     void evaluateChildBounds() const
666     {
667       if(m_childBoundsChanged)
668       {
669         ASSERT_MESSAGE(!m_childBoundsMutex, "re-entering bounds evaluation");
670         m_childBoundsMutex = true;
671
672         m_childBounds = AABB();
673
674         GlobalSceneGraph().traverse_subgraph(AABBAccumulateWalker(m_childBounds), m_path);
675
676         m_childBoundsMutex = false;
677         m_childBoundsChanged = false;
678       }
679     }
680     void evaluateBounds() const
681     {
682       if(m_boundsChanged)
683       {
684         ASSERT_MESSAGE(!m_boundsMutex, "re-entering bounds evaluation");
685         m_boundsMutex = true;
686
687         m_bounds = childBounds();
688
689         const Bounded* bounded = Instance_getBounded(*this);
690         if(bounded != 0)
691         {
692           aabb_extend_by_aabb_safe(
693             m_bounds,
694             aabb_for_oriented_aabb_safe(bounded->localAABB(), localToWorld())
695           );
696         }
697
698         m_boundsMutex = false;
699         m_boundsChanged = false;
700       }
701     }
702
703     Instance(const scene::Instance& other);
704     Instance& operator=(const scene::Instance& other);
705   public:
706
707     Instance(const scene::Path& path, Instance* parent, void* instance, InstanceTypeCastTable& casts) :
708       m_path(path),
709       m_parent(parent),
710       m_instance(instance),
711       m_casts(casts),
712       m_local2world(g_matrix4_identity),
713       m_transformChanged(true),
714       m_transformMutex(false),
715       m_boundsChanged(true),
716       m_boundsMutex(false),
717       m_childBoundsChanged(true),
718       m_childBoundsMutex(false),
719       m_isSelectedChanged(true),
720       m_childSelectedChanged(true),
721       m_parentSelectedChanged(true)
722     {
723       ASSERT_MESSAGE((parent == 0) == (path.size() == 1), "instance has invalid parent");
724     }
725     virtual ~Instance()
726     {
727     }
728
729     const scene::Path& path() const
730     {
731       return m_path;
732     }
733
734     void* cast(TypeId typeId) const
735     {
736       return m_casts.cast(typeId, m_instance);
737     }
738
739     const Matrix4& localToWorld() const
740     {
741       evaluateTransform();
742       return m_local2world;
743     }
744     void transformChangedLocal()
745     {
746       ASSERT_NOTNULL(m_parent);
747       m_transformChanged = true;
748       m_boundsChanged = true;
749       m_childBoundsChanged = true;
750       m_transformChangedCallback();
751     }
752     void transformChanged()
753     {
754       GlobalSceneGraph().traverse_subgraph(TransformChangedWalker(), m_path);
755       boundsChanged();
756     }
757     void setTransformChangedCallback(const Callback& callback)
758     {
759       m_transformChangedCallback = callback;
760     }
761
762
763     const AABB& worldAABB() const
764     {
765       evaluateBounds();
766       return m_bounds;
767     }
768     const AABB& childBounds() const
769     {
770       evaluateChildBounds();
771       return m_childBounds;
772     }
773     void boundsChanged()
774     {
775       m_boundsChanged = true;
776       m_childBoundsChanged = true;
777       if(m_parent != 0)
778       {
779         m_parent->boundsChanged();
780       }
781       GlobalSceneGraph().boundsChanged();
782     }
783
784     void childSelectedChanged()
785     {
786       m_childSelectedChanged = true;
787       m_childSelectedChangedCallback();
788       if(m_parent != 0)
789       {
790         m_parent->childSelectedChanged();
791       }
792     }
793     bool childSelected() const
794     {
795       if(m_childSelectedChanged)
796       {
797         m_childSelectedChanged = false;
798         GlobalSceneGraph().traverse_subgraph(ChildSelectedWalker(m_childSelected), m_path);
799       }
800       return m_childSelected;
801     }
802
803     void setChildSelectedChangedCallback(const Callback& callback)
804     {
805       m_childSelectedChangedCallback = callback;
806     }
807     void selectedChanged()
808     {
809       m_isSelectedChanged = true;
810       if(m_parent != 0)
811       {
812         m_parent->childSelectedChanged();
813       }
814       GlobalSceneGraph().traverse_subgraph(ParentSelectedChangedWalker(), m_path);
815     }
816     bool isSelected() const
817     {
818       if(m_isSelectedChanged)
819       {
820         m_isSelectedChanged = false;
821         const Selectable* selectable = Instance_getSelectable(*this);
822         m_isSelected = selectable != 0 && selectable->isSelected();
823       }
824       return m_isSelected;
825     }
826
827     void parentSelectedChanged()
828     {
829       m_parentSelectedChanged = true;
830     }
831     bool parentSelected() const
832     {
833       if(m_parentSelectedChanged)
834       {
835         m_parentSelectedChanged = false;
836         m_parentSelected = m_parent != 0 && (m_parent->isSelected() || m_parent->parentSelected());
837       }
838       return m_parentSelected;
839     }
840   };
841 }
842
843 template<typename Type>
844 class InstanceTypeCast
845 {
846 public:
847   static Type* cast(scene::Instance& instance)
848   {
849     return static_cast<Type*>(instance.cast(StaticInstanceType<Type>::getTypeId()));
850   }
851   static const Type* cast(const scene::Instance& instance)
852   {
853     return static_cast<const Type*>(instance.cast(StaticInstanceType<Type>::getTypeId()));
854   }
855 };
856
857 template<typename Functor>
858 class InstanceWalker : public scene::Graph::Walker
859 {
860   const Functor& m_functor;
861 public:
862   InstanceWalker(const Functor& functor) : m_functor(functor)
863   {
864   }
865   bool pre(const scene::Path& path, scene::Instance& instance) const
866   {
867     m_functor(instance);
868     return true;
869   }
870 };
871
872 template<typename Functor>
873 class ChildInstanceWalker : public scene::Graph::Walker
874 {
875   const Functor& m_functor;
876   mutable std::size_t m_depth;
877 public:
878   ChildInstanceWalker(const Functor& functor) : m_functor(functor), m_depth(0)
879   {
880   }
881   bool pre(const scene::Path& path, scene::Instance& instance) const
882   {
883     if(m_depth == 1)
884     {
885       m_functor(instance);
886     }
887     return ++m_depth != 2;
888   }
889   void post(const scene::Path& path, scene::Instance& instance) const
890   {
891     --m_depth;
892   }
893 };
894
895 template<typename Type, typename Functor>
896 class InstanceApply : public Functor
897 {
898 public:
899   InstanceApply(const Functor& functor) : Functor(functor)
900   {
901   }
902   void operator()(scene::Instance& instance) const
903   {
904     Type* result = InstanceTypeCast<Type>::cast(instance);
905     if(result != 0)
906     {
907       Functor::operator()(*result);
908     }
909   }
910 };
911
912 inline Selectable* Instance_getSelectable(scene::Instance& instance)
913 {
914   return InstanceTypeCast<Selectable>::cast(instance);
915 }
916 inline const Selectable* Instance_getSelectable(const scene::Instance& instance)
917 {
918   return InstanceTypeCast<Selectable>::cast(instance);
919 }
920
921 template<typename Functor>
922 inline void Scene_forEachChildSelectable(const Functor& functor, const scene::Path& path)
923 {
924   GlobalSceneGraph().traverse_subgraph(ChildInstanceWalker< InstanceApply<Selectable, Functor> >(functor), path);
925 }
926
927 class SelectableSetSelected
928 {
929   bool m_selected;
930 public:
931   SelectableSetSelected(bool selected) : m_selected(selected)
932   {
933   }
934   void operator()(Selectable& selectable) const
935   {
936     selectable.setSelected(m_selected);
937   }
938 };
939
940 inline Bounded* Instance_getBounded(scene::Instance& instance)
941 {
942   return InstanceTypeCast<Bounded>::cast(instance);
943 }
944 inline const Bounded* Instance_getBounded(const scene::Instance& instance)
945 {
946   return InstanceTypeCast<Bounded>::cast(instance);
947 }
948
949 inline Transformable* Instance_getTransformable(scene::Instance& instance)
950 {
951   return InstanceTypeCast<Transformable>::cast(instance);
952 }
953 inline const Transformable* Instance_getTransformable(const scene::Instance& instance)
954 {
955   return InstanceTypeCast<Transformable>::cast(instance);
956 }
957
958
959 inline ComponentSelectionTestable* Instance_getComponentSelectionTestable(scene::Instance& instance)
960 {
961   return InstanceTypeCast<ComponentSelectionTestable>::cast(instance);
962 }
963
964 inline ComponentEditable* Instance_getComponentEditable(scene::Instance& instance)
965 {
966   return InstanceTypeCast<ComponentEditable>::cast(instance);
967 }
968
969 inline ComponentSnappable* Instance_getComponentSnappable(scene::Instance& instance)
970 {
971   return InstanceTypeCast<ComponentSnappable>::cast(instance);
972 }
973
974
975 inline void Instance_setSelected(scene::Instance& instance, bool selected)
976 {
977   Selectable* selectable = Instance_getSelectable(instance);
978   if(selectable != 0)
979   {
980     selectable->setSelected(selected);
981   }
982 }
983
984 inline bool Instance_isSelected(scene::Instance& instance)
985 {
986   Selectable* selectable = Instance_getSelectable(instance);
987   if(selectable != 0)
988   {
989     return selectable->isSelected();
990   }
991   return false;
992 }
993
994 inline scene::Instance& findInstance(const scene::Path& path)
995 {
996   scene::Instance* instance = GlobalSceneGraph().find(path);
997   ASSERT_MESSAGE(instance != 0, "findInstance: path not found in scene-graph");
998   return *instance;
999 }
1000
1001 inline void selectPath(const scene::Path& path, bool selected)
1002 {
1003   Instance_setSelected(findInstance(path), selected);
1004 }
1005
1006 class SelectChildren : public scene::Traversable::Walker
1007 {
1008   mutable scene::Path m_path;
1009 public:
1010   SelectChildren(const scene::Path& root)
1011     : m_path(root)
1012   {
1013   }
1014   bool pre(scene::Node& node) const
1015   {
1016     m_path.push(makeReference(node));
1017     selectPath(m_path, true);
1018     return false;
1019   }
1020   void post(scene::Node& node) const
1021   {
1022     m_path.pop();
1023   }
1024 };
1025
1026 inline void Entity_setSelected(scene::Instance& entity, bool selected)
1027 {
1028   scene::Node& node = entity.path().top();
1029   if(node_is_group(node))
1030   {
1031     Node_getTraversable(node)->traverse(SelectChildren(entity.path()));
1032   }
1033   else
1034   {
1035     Instance_setSelected(entity, selected);
1036   }
1037 }
1038
1039 inline bool Entity_isSelected(scene::Instance& entity)
1040 {
1041   if(node_is_group(entity.path().top()))
1042   {
1043     return entity.childSelected();
1044   }
1045   return Instance_isSelected(entity);
1046 }
1047
1048
1049
1050 class InstanceCounter
1051 {
1052 public:
1053   unsigned int m_count;
1054   InstanceCounter() : m_count(0)
1055   {
1056   }
1057 };
1058
1059
1060 class Counter
1061 {
1062 public:
1063   virtual void increment() = 0;
1064   virtual void decrement() = 0;
1065 };
1066
1067 #include "generic/callback.h"
1068
1069 class SimpleCounter : public Counter
1070 {
1071   Callback m_countChanged;
1072   std::size_t m_count;
1073 public:
1074   void setCountChangedCallback(const Callback& countChanged)
1075   {
1076     m_countChanged = countChanged;
1077   }
1078   void increment()
1079   {
1080     ++m_count;
1081     m_countChanged();
1082   }
1083   void decrement()
1084   {
1085     --m_count;
1086     m_countChanged();
1087   }
1088   std::size_t get() const
1089   {
1090     return m_count;
1091   }
1092 };
1093
1094
1095 template<typename Contained>
1096 class ConstReference;
1097 typedef ConstReference<scene::Path> PathConstReference;
1098
1099 #include "generic/referencecounted.h"
1100 typedef SmartReference<scene::Node, IncRefDecRefCounter<scene::Node> > NodeSmartReference;
1101
1102
1103 #endif