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