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