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