]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/scenelib.h
fixed crash on disabling lighting
[xonotic/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   static const int 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     static const int eVisible = 0;
165     static const int eHidden = 1 << 0;
166     static const int eFiltered = 1 << 1;
167     static const int 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 class BrushUndefined
369 {
370 public:
371   STRING_CONSTANT(Name, "Brush");
372 };
373
374 inline bool Node_isBrush(scene::Node& node)
375 {
376   return NodeTypeCast<BrushUndefined>::cast(node) != 0;
377 }
378
379 class PatchUndefined
380 {
381 public:
382   STRING_CONSTANT(Name, "Patch");
383 };
384
385 inline bool Node_isPatch(scene::Node& node)
386 {
387   return NodeTypeCast<PatchUndefined>::cast(node) != 0;
388 }
389
390 inline bool Node_isPrimitive(scene::Node& node)
391 {
392 #if 1
393   return Node_isBrush(node) || Node_isPatch(node);
394 #else
395   return !node.isRoot();
396 #endif
397 }
398
399 class ParentBrushes : public scene::Traversable::Walker
400 {
401   scene::Node& m_parent;
402 public:
403   ParentBrushes(scene::Node& parent)
404     : m_parent(parent)
405   {
406   }
407   bool pre(scene::Node& node) const
408   {
409     return false;
410   }
411   void post(scene::Node& node) const
412   {
413     if(Node_isPrimitive(node))
414     {
415       Node_getTraversable(m_parent)->insert(node);
416     }
417   }
418 };
419
420 inline void parentBrushes(scene::Node& subgraph, scene::Node& parent)
421 {
422   Node_getTraversable(subgraph)->traverse(ParentBrushes(parent));
423 }
424
425 class HasBrushes : public scene::Traversable::Walker
426 {
427   bool& m_hasBrushes;
428 public:
429   HasBrushes(bool& hasBrushes)
430     : m_hasBrushes(hasBrushes)
431   {
432     m_hasBrushes = true;
433   }
434   bool pre(scene::Node& node) const
435   {
436     if(!Node_isPrimitive(node))
437     {
438       m_hasBrushes = false;
439     }
440     return false;
441   }
442 };
443
444 inline bool node_is_group(scene::Node& node)
445 {
446   scene::Traversable* traversable = Node_getTraversable(node);
447   if(traversable != 0)
448   {
449     bool hasBrushes = false;
450     traversable->traverse(HasBrushes(hasBrushes));
451     return hasBrushes;
452   }
453   return false;
454 }
455
456 typedef TypeCastTable<INSTANCETYPEID_MAX> InstanceTypeCastTable;
457
458 template<typename Type>
459 class InstanceType : public StaticTypeSystemInitialiser
460 {
461   TypeId m_typeId;
462 public:
463   typedef typename Type::Name Name;
464   InstanceType() : m_typeId(INSTANCETYPEID_NONE)
465   {
466     StaticTypeSystemInitialiser::instance().addInitialiser(InitialiseCaller(*this));
467   }
468   void initialise()
469   {
470     m_typeId = GlobalSceneGraph().getInstanceTypeId(Name());
471   }
472   typedef MemberCaller<InstanceType<Type>, &InstanceType<Type>::initialise> InitialiseCaller;
473   TypeId getTypeId()
474   {
475 #if defined(_DEBUG)
476     ASSERT_MESSAGE(m_typeId != INSTANCETYPEID_NONE, "instance-type " << makeQuoted(Name()) << " used before being initialised");
477 #endif
478     return m_typeId;
479   }
480 };
481
482 template<typename Type>
483 class StaticInstanceType
484 {
485 public:
486   static const int SIZE = INSTANCETYPEID_MAX;
487   static TypeId getTypeId()
488   {
489     return Static< InstanceType<Type> >::instance().getTypeId();
490   }
491 };
492
493 template<typename Type, typename Base>
494 class InstanceStaticCast :
495   public CastInstaller<
496     StaticInstanceType<Base>,
497     StaticCast<Type, Base>
498   >
499 {
500 };
501
502 template<typename Type, typename Contained>
503 class InstanceContainedCast :
504   public CastInstaller<
505     StaticInstanceType<Contained>,
506     ContainedCast<Type, Contained>
507   >
508 {
509 };
510
511 template<typename Type>
512 class InstanceIdentityCast :
513   public CastInstaller<
514     StaticInstanceType<Type>,
515     IdentityCast<Type>
516   >
517 {
518 };
519
520
521 inline Selectable* Instance_getSelectable(scene::Instance& instance);
522 inline const Selectable* Instance_getSelectable(const scene::Instance& instance);
523
524 inline Bounded* Instance_getBounded(scene::Instance& instance);
525 inline const Bounded* Instance_getBounded(const scene::Instance& instance);
526
527 namespace scene
528 {
529   class Instance
530   {
531     class AABBAccumulateWalker : public scene::Graph::Walker
532     {
533       AABB& m_aabb;
534       mutable std::size_t m_depth;
535     public:
536       AABBAccumulateWalker(AABB& aabb) : m_aabb(aabb), m_depth(0)
537       {
538       }
539       bool pre(const scene::Path& path, scene::Instance& instance) const
540       {
541         if(m_depth == 1)
542         {
543           aabb_extend_by_aabb_safe(m_aabb, instance.worldAABB());
544         }
545         return ++m_depth != 2;
546       }
547       void post(const scene::Path& path, scene::Instance& instance) const
548       {
549         --m_depth;
550       }
551     };
552
553
554     class TransformChangedWalker : public scene::Graph::Walker
555     {
556     public:
557       bool pre(const scene::Path& path, scene::Instance& instance) const
558       {
559         instance.transformChangedLocal();
560         return true;
561       }
562     };
563
564     class ParentSelectedChangedWalker : public scene::Graph::Walker
565     {
566     public:
567       bool pre(const scene::Path& path, scene::Instance& instance) const
568       {
569         instance.parentSelectedChanged();
570         return true;
571       }
572     };
573
574     class ChildSelectedWalker : public scene::Graph::Walker
575     {
576       bool& m_childSelected;
577       mutable std::size_t m_depth;
578     public:
579       ChildSelectedWalker(bool& childSelected) : m_childSelected(childSelected), m_depth(0)
580       {
581         m_childSelected = false;
582       }
583       bool pre(const scene::Path& path, scene::Instance& instance) const
584       {
585         if(m_depth == 1 && !m_childSelected)
586         {
587           m_childSelected = instance.isSelected() || instance.childSelected();
588         }
589         return ++m_depth != 2;
590       }
591       void post(const scene::Path& path, scene::Instance& instance) const
592       {
593         --m_depth;
594       }
595     };
596
597     Path m_path;
598     Instance* m_parent;
599     void* m_instance;
600     InstanceTypeCastTable& m_casts;
601
602     mutable Matrix4 m_local2world;
603     mutable AABB m_bounds;
604     mutable AABB m_childBounds;
605     mutable bool m_transformChanged;
606     mutable bool m_transformMutex;
607     mutable bool m_boundsChanged;
608     mutable bool m_boundsMutex;
609     mutable bool m_childBoundsChanged;
610     mutable bool m_childBoundsMutex;
611     mutable bool m_isSelected;
612     mutable bool m_isSelectedChanged;
613     mutable bool m_childSelected;
614     mutable bool m_childSelectedChanged;
615     mutable bool m_parentSelected;
616     mutable bool m_parentSelectedChanged;
617     Callback m_childSelectedChangedCallback;
618     Callback m_transformChangedCallback;
619
620
621     void evaluateTransform() const
622     {
623       if(m_transformChanged)
624       {
625         ASSERT_MESSAGE(!m_transformMutex, "re-entering transform evaluation");
626         m_transformMutex = true;
627
628         m_local2world = (m_parent != 0) ? m_parent->localToWorld() : g_matrix4_identity;
629         TransformNode* transformNode = Node_getTransformNode(m_path.top());
630         if(transformNode != 0)
631         {
632           matrix4_multiply_by_matrix4(m_local2world, transformNode->localToParent());
633         }
634
635         m_transformMutex = false;
636         m_transformChanged = false;
637       }
638     }
639     void evaluateChildBounds() const
640     {
641       if(m_childBoundsChanged)
642       {
643         ASSERT_MESSAGE(!m_childBoundsMutex, "re-entering bounds evaluation");
644         m_childBoundsMutex = true;
645
646         m_childBounds = AABB();
647
648         GlobalSceneGraph().traverse_subgraph(AABBAccumulateWalker(m_childBounds), m_path);
649
650         m_childBoundsMutex = false;
651         m_childBoundsChanged = false;
652       }
653     }
654     void evaluateBounds() const
655     {
656       if(m_boundsChanged)
657       {
658         ASSERT_MESSAGE(!m_boundsMutex, "re-entering bounds evaluation");
659         m_boundsMutex = true;
660
661         m_bounds = childBounds();
662
663         const Bounded* bounded = Instance_getBounded(*this);
664         if(bounded != 0)
665         {
666           aabb_extend_by_aabb_safe(
667             m_bounds,
668             aabb_for_oriented_aabb_safe(bounded->localAABB(), localToWorld())
669           );
670         }
671
672         m_boundsMutex = false;
673         m_boundsChanged = false;
674       }
675     }
676
677     Instance(const scene::Instance& other);
678     Instance& operator=(const scene::Instance& other);
679   public:
680
681     Instance(const scene::Path& path, Instance* parent, void* instance, InstanceTypeCastTable& casts) :
682       m_path(path),
683       m_parent(parent),
684       m_instance(instance),
685       m_casts(casts),
686       m_local2world(g_matrix4_identity),
687       m_transformChanged(true),
688       m_transformMutex(false),
689       m_boundsChanged(true),
690       m_boundsMutex(false),
691       m_childBoundsChanged(true),
692       m_childBoundsMutex(false),
693       m_isSelectedChanged(true),
694       m_childSelectedChanged(true),
695       m_parentSelectedChanged(true)
696     {
697       ASSERT_MESSAGE((parent == 0) == (path.size() == 1), "instance has invalid parent");
698     }
699     virtual ~Instance()
700     {
701     }
702
703     const scene::Path& path() const
704     {
705       return m_path;
706     }
707
708     void* cast(TypeId typeId) const
709     {
710       return m_casts.cast(typeId, m_instance);
711     }
712
713     const Matrix4& localToWorld() const
714     {
715       evaluateTransform();
716       return m_local2world;
717     }
718     void transformChangedLocal()
719     {
720       ASSERT_NOTNULL(m_parent);
721       m_transformChanged = true;
722       m_boundsChanged = true;
723       m_childBoundsChanged = true;
724       m_transformChangedCallback();
725     }
726     void transformChanged()
727     {
728       GlobalSceneGraph().traverse_subgraph(TransformChangedWalker(), m_path);
729       boundsChanged();
730     }
731     void setTransformChangedCallback(const Callback& callback)
732     {
733       m_transformChangedCallback = callback;
734     }
735
736
737     const AABB& worldAABB() const
738     {
739       evaluateBounds();
740       return m_bounds;
741     }
742     const AABB& childBounds() const
743     {
744       evaluateChildBounds();
745       return m_childBounds;
746     }
747     void boundsChanged()
748     {
749       m_boundsChanged = true;
750       m_childBoundsChanged = true;
751       if(m_parent != 0)
752       {
753         m_parent->boundsChanged();
754       }
755       GlobalSceneGraph().boundsChanged();
756     }
757
758     void childSelectedChanged()
759     {
760       m_childSelectedChanged = true;
761       m_childSelectedChangedCallback();
762       if(m_parent != 0)
763       {
764         m_parent->childSelectedChanged();
765       }
766     }
767     bool childSelected() const
768     {
769       if(m_childSelectedChanged)
770       {
771         m_childSelectedChanged = false;
772         GlobalSceneGraph().traverse_subgraph(ChildSelectedWalker(m_childSelected), m_path);
773       }
774       return m_childSelected;
775     }
776
777     void setChildSelectedChangedCallback(const Callback& callback)
778     {
779       m_childSelectedChangedCallback = callback;
780     }
781     void selectedChanged()
782     {
783       m_isSelectedChanged = true;
784       if(m_parent != 0)
785       {
786         m_parent->childSelectedChanged();
787       }
788       GlobalSceneGraph().traverse_subgraph(ParentSelectedChangedWalker(), m_path);
789     }
790     bool isSelected() const
791     {
792       if(m_isSelectedChanged)
793       {
794         m_isSelectedChanged = false;
795         const Selectable* selectable = Instance_getSelectable(*this);
796         m_isSelected = selectable != 0 && selectable->isSelected();
797       }
798       return m_isSelected;
799     }
800
801     void parentSelectedChanged()
802     {
803       m_parentSelectedChanged = true;
804     }
805     bool parentSelected() const
806     {
807       if(m_parentSelectedChanged)
808       {
809         m_parentSelectedChanged = false;
810         m_parentSelected = m_parent != 0 && (m_parent->isSelected() || m_parent->parentSelected());
811       }
812       return m_parentSelected;
813     }
814   };
815 }
816
817 template<typename Type>
818 class InstanceTypeCast
819 {
820 public:
821   static Type* cast(scene::Instance& instance)
822   {
823     return static_cast<Type*>(instance.cast(StaticInstanceType<Type>::getTypeId()));
824   }
825   static const Type* cast(const scene::Instance& instance)
826   {
827     return static_cast<const Type*>(instance.cast(StaticInstanceType<Type>::getTypeId()));
828   }
829 };
830
831 template<typename Functor>
832 class InstanceWalker : public scene::Graph::Walker
833 {
834   const Functor& m_functor;
835 public:
836   InstanceWalker(const Functor& functor) : m_functor(functor)
837   {
838   }
839   bool pre(const scene::Path& path, scene::Instance& instance) const
840   {
841     m_functor(instance);
842     return true;
843   }
844 };
845
846 template<typename Functor>
847 class ChildInstanceWalker : public scene::Graph::Walker
848 {
849   const Functor& m_functor;
850   mutable std::size_t m_depth;
851 public:
852   ChildInstanceWalker(const Functor& functor) : m_functor(functor), m_depth(0)
853   {
854   }
855   bool pre(const scene::Path& path, scene::Instance& instance) const
856   {
857     if(m_depth == 1)
858     {
859       m_functor(instance);
860     }
861     return ++m_depth != 2;
862   }
863   void post(const scene::Path& path, scene::Instance& instance) const
864   {
865     --m_depth;
866   }
867 };
868
869 template<typename Type, typename Functor>
870 class InstanceApply : public Functor
871 {
872 public:
873   InstanceApply(const Functor& functor) : Functor(functor)
874   {
875   }
876   void operator()(scene::Instance& instance) const
877   {
878     Type* result = InstanceTypeCast<Type>::cast(instance);
879     if(result != 0)
880     {
881       Functor::operator()(*result);
882     }
883   }
884 };
885
886 inline Selectable* Instance_getSelectable(scene::Instance& instance)
887 {
888   return InstanceTypeCast<Selectable>::cast(instance);
889 }
890 inline const Selectable* Instance_getSelectable(const scene::Instance& instance)
891 {
892   return InstanceTypeCast<Selectable>::cast(instance);
893 }
894
895 template<typename Functor>
896 inline void Scene_forEachChildSelectable(const Functor& functor, const scene::Path& path)
897 {
898   GlobalSceneGraph().traverse_subgraph(ChildInstanceWalker< InstanceApply<Selectable, Functor> >(functor), path);
899 }
900
901 class SelectableSetSelected
902 {
903   bool m_selected;
904 public:
905   SelectableSetSelected(bool selected) : m_selected(selected)
906   {
907   }
908   void operator()(Selectable& selectable) const
909   {
910     selectable.setSelected(m_selected);
911   }
912 };
913
914 inline Bounded* Instance_getBounded(scene::Instance& instance)
915 {
916   return InstanceTypeCast<Bounded>::cast(instance);
917 }
918 inline const Bounded* Instance_getBounded(const scene::Instance& instance)
919 {
920   return InstanceTypeCast<Bounded>::cast(instance);
921 }
922
923 inline Transformable* Instance_getTransformable(scene::Instance& instance)
924 {
925   return InstanceTypeCast<Transformable>::cast(instance);
926 }
927 inline const Transformable* Instance_getTransformable(const scene::Instance& instance)
928 {
929   return InstanceTypeCast<Transformable>::cast(instance);
930 }
931
932
933 inline ComponentSelectionTestable* Instance_getComponentSelectionTestable(scene::Instance& instance)
934 {
935   return InstanceTypeCast<ComponentSelectionTestable>::cast(instance);
936 }
937
938 inline ComponentEditable* Instance_getComponentEditable(scene::Instance& instance)
939 {
940   return InstanceTypeCast<ComponentEditable>::cast(instance);
941 }
942
943 inline ComponentSnappable* Instance_getComponentSnappable(scene::Instance& instance)
944 {
945   return InstanceTypeCast<ComponentSnappable>::cast(instance);
946 }
947
948
949 inline void Instance_setSelected(scene::Instance& instance, bool selected)
950 {
951   Selectable* selectable = Instance_getSelectable(instance);
952   if(selectable != 0)
953   {
954     selectable->setSelected(selected);
955   }
956 }
957
958 inline bool Instance_isSelected(scene::Instance& instance)
959 {
960   Selectable* selectable = Instance_getSelectable(instance);
961   if(selectable != 0)
962   {
963     return selectable->isSelected();
964   }
965   return false;
966 }
967
968 inline scene::Instance& findInstance(const scene::Path& path)
969 {
970   scene::Instance* instance = GlobalSceneGraph().find(path);
971   ASSERT_MESSAGE(instance != 0, "findInstance: path not found in scene-graph");
972   return *instance;
973 }
974
975 inline void selectPath(const scene::Path& path, bool selected)
976 {
977   Instance_setSelected(findInstance(path), selected);
978 }
979
980 class SelectChildren : public scene::Traversable::Walker
981 {
982   mutable scene::Path m_path;
983 public:
984   SelectChildren(const scene::Path& root)
985     : m_path(root)
986   {
987   }
988   bool pre(scene::Node& node) const
989   {
990     m_path.push(makeReference(node));
991     selectPath(m_path, true);
992     return false;
993   }
994   void post(scene::Node& node) const
995   {
996     m_path.pop();
997   }
998 };
999
1000 inline void Entity_setSelected(scene::Instance& entity, bool selected)
1001 {
1002   scene::Node& node = entity.path().top();
1003   if(node_is_group(node))
1004   {
1005     Node_getTraversable(node)->traverse(SelectChildren(entity.path()));
1006   }
1007   else
1008   {
1009     Instance_setSelected(entity, selected);
1010   }
1011 }
1012
1013 inline bool Entity_isSelected(scene::Instance& entity)
1014 {
1015   if(node_is_group(entity.path().top()))
1016   {
1017     return entity.childSelected();
1018   }
1019   return Instance_isSelected(entity);
1020 }
1021
1022
1023
1024 class InstanceCounter
1025 {
1026 public:
1027   unsigned int m_count;
1028   InstanceCounter() : m_count(0)
1029   {
1030   }
1031 };
1032
1033
1034 class Counter
1035 {
1036 public:
1037   virtual void increment() = 0;
1038   virtual void decrement() = 0;
1039 };
1040
1041 #include "generic/callback.h"
1042
1043 class SimpleCounter : public Counter
1044 {
1045   Callback m_countChanged;
1046   std::size_t m_count;
1047 public:
1048   void setCountChangedCallback(const Callback& countChanged)
1049   {
1050     m_countChanged = countChanged;
1051   }
1052   void increment()
1053   {
1054     ++m_count;
1055     m_countChanged();
1056   }
1057   void decrement()
1058   {
1059     --m_count;
1060     m_countChanged();
1061   }
1062   std::size_t get() const
1063   {
1064     return m_count;
1065   }
1066 };
1067
1068
1069 template<typename Contained>
1070 class ConstReference;
1071 typedef ConstReference<scene::Path> PathConstReference;
1072
1073 #include "generic/referencecounted.h"
1074 typedef SmartReference<scene::Node, IncRefDecRefCounter<scene::Node> > NodeSmartReference;
1075
1076
1077 #endif