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 "container/stack.h"
36 #include "typesystem.h"
37
38 class Selector;
39 class SelectionTest;
40 class VolumeTest;
41 template<typename Element> class BasicVector3;
42 typedef BasicVector3<float> Vector3;
43 template<typename Element> class BasicVector4;
44 typedef BasicVector4<float> Vector4;
45 class Matrix4;
46 typedef Vector4 Quaternion;
47 class AABB;
48
49 class ComponentSelectionTestable
50 {
51 public:
52 STRING_CONSTANT( Name, "ComponentSelectionTestable" );
53
54 virtual bool isSelectedComponents() const = 0;
55 virtual void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ) = 0;
56 virtual void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ) = 0;
57 };
58
59 class ComponentEditable
60 {
61 public:
62 STRING_CONSTANT( Name, "ComponentEditable" );
63
64 virtual const AABB& getSelectedComponentsBounds() const = 0;
65 };
66
67 class ComponentSnappable
68 {
69 public:
70 STRING_CONSTANT( Name, "ComponentSnappable" );
71
72 virtual void snapComponents( float snap ) = 0;
73 };
74
75 class Bounded
76 {
77 public:
78 STRING_CONSTANT( Name, "Bounded" );
79
80 virtual const AABB& localAABB() const = 0;
81 };
82
83 class BrushDoom3
84 {
85 public:
86 STRING_CONSTANT( Name, "BrushDoom3" );
87
88 virtual void setDoom3GroupOrigin( const Vector3& origin ) = 0;
89 };
90
91
92
93
94 typedef TypeCastTable<NODETYPEID_MAX> NodeTypeCastTable;
95
96 template<typename Type>
97 class NodeType : public StaticTypeSystemInitialiser
98 {
99 TypeId m_typeId;
100 public:
101 typedef typename Type::Name Name;
NodeType()102 NodeType() : m_typeId( NODETYPEID_NONE ){
103 StaticTypeSystemInitialiser::instance().addInitialiser( InitialiseCaller( *this ) );
104 }
initialise()105 void initialise(){
106 m_typeId = GlobalSceneGraph().getNodeTypeId( Name() );
107 }
108 typedef MemberCaller<NodeType<Type>, &NodeType<Type>::initialise> InitialiseCaller;
getTypeId()109 TypeId getTypeId(){
110 #if defined( _DEBUG )
111 ASSERT_MESSAGE( m_typeId != NODETYPEID_NONE, "node-type " << makeQuoted( Name() ) << " used before being initialised" );
112 #endif
113 return m_typeId;
114 }
115 };
116
117 template<typename Type>
118 class StaticNodeType
119 {
120 public:
121 enum unnamed0 { SIZE = NODETYPEID_MAX };
getTypeId()122 static TypeId getTypeId(){
123 return Static< NodeType<Type> >::instance().getTypeId();
124 }
125 };
126
127 template<typename Type, typename Base>
128 class NodeStaticCast :
129 public CastInstaller<
130 StaticNodeType<Base>,
131 StaticCast<Type, Base>
132 >
133 {
134 };
135
136 template<typename Type, typename Contained>
137 class NodeContainedCast :
138 public CastInstaller<
139 StaticNodeType<Contained>,
140 ContainedCast<Type, Contained>
141 >
142 {
143 };
144
145 template<typename Type>
146 class NodeIdentityCast :
147 public CastInstaller<
148 StaticNodeType<Type>,
149 IdentityCast<Type>
150 >
151 {
152 };
153
154 namespace scene
155 {
156 class Node
157 {
158 public:
159 enum unnamed0 { eVisible = 0 };
160 enum unnamed1 { eHidden = 1 << 0 };
161 enum unnamed2 { eFiltered = 1 << 1 };
162 enum unnamed3 { eExcluded = 1 << 2 };
163
164 class Symbiot
165 {
166 public:
167 virtual void release() = 0;
~Symbiot()168 virtual ~Symbiot(){
169 }
170 };
171
172 private:
173 unsigned int m_state;
174 std::size_t m_refcount;
175 Symbiot* m_symbiot;
176 void* m_node;
177 NodeTypeCastTable& m_casts;
178
179 public:
180 bool m_isRoot;
181
isRoot()182 bool isRoot(){
183 return m_isRoot;
184 }
185
Node(Symbiot * symbiot,void * node,NodeTypeCastTable & casts)186 Node( Symbiot* symbiot, void* node, NodeTypeCastTable& casts ) :
187 m_state( eVisible ),
188 m_refcount( 0 ),
189 m_symbiot( symbiot ),
190 m_node( node ),
191 m_casts( casts ),
192 m_isRoot( false ){
193 }
~Node()194 ~Node(){
195 }
196
IncRef()197 void IncRef(){
198 ASSERT_MESSAGE( m_refcount < ( 1 << 24 ), "Node::decref: uninitialised refcount" );
199 ++m_refcount;
200 }
DecRef()201 void DecRef(){
202 ASSERT_MESSAGE( m_refcount < ( 1 << 24 ), "Node::decref: uninitialised refcount" );
203 if ( --m_refcount == 0 ) {
204 m_symbiot->release();
205 }
206 }
getReferenceCount()207 std::size_t getReferenceCount() const {
208 return m_refcount;
209 }
210
cast(TypeId typeId)211 void* cast( TypeId typeId ) const {
212 return m_casts.cast( typeId, m_node );
213 }
214
enable(unsigned int state)215 void enable( unsigned int state ){
216 m_state |= state;
217 }
disable(unsigned int state)218 void disable( unsigned int state ){
219 m_state &= ~state;
220 }
visible()221 bool visible(){
222 return m_state == eVisible;
223 }
excluded()224 bool excluded(){
225 return ( m_state & eExcluded ) != 0;
226 }
227 bool operator<( const scene::Node& other ){
228 return this < &other;
229 }
230 bool operator==( const scene::Node& other ){
231 return this == &other;
232 }
233 bool operator!=( const scene::Node& other ){
234 return this != &other;
235 }
236 };
237
238
239 class NullNode : public Node::Symbiot
240 {
241 NodeTypeCastTable m_casts;
242 Node m_node;
243 public:
NullNode()244 NullNode() : m_node( this, 0, m_casts ){
245 }
release()246 void release(){
247 delete this;
248 }
node()249 scene::Node& node(){
250 return m_node;
251 }
252 };
253 }
254
255 template<typename Type>
256 class NodeTypeCast
257 {
258 public:
cast(scene::Node & node)259 static Type* cast( scene::Node& node ){
260 return static_cast<Type*>( node.cast( StaticNodeType<Type>::getTypeId() ) );
261 }
cast(const scene::Node & node)262 static const Type* cast( const scene::Node& node ){
263 return static_cast<const Type*>( node.cast( StaticNodeType<Type>::getTypeId() ) );
264 }
265 };
266
267
Node_getInstantiable(scene::Node & node)268 inline scene::Instantiable* Node_getInstantiable( scene::Node& node ){
269 return NodeTypeCast<scene::Instantiable>::cast( node );
270 }
271
Node_getTraversable(scene::Node & node)272 inline scene::Traversable* Node_getTraversable( scene::Node& node ){
273 return NodeTypeCast<scene::Traversable>::cast( node );
274 }
275
Node_traverseSubgraph(scene::Node & node,const scene::Traversable::Walker & walker)276 inline void Node_traverseSubgraph( scene::Node& node, const scene::Traversable::Walker& walker ){
277 if ( walker.pre( node ) ) {
278 scene::Traversable* traversable = Node_getTraversable( node );
279 if ( traversable != 0 ) {
280 traversable->traverse( walker );
281 }
282 }
283 walker.post( node );
284 }
285
Node_getTransformNode(scene::Node & node)286 inline TransformNode* Node_getTransformNode( scene::Node& node ){
287 return NodeTypeCast<TransformNode>::cast( node );
288 }
289
290 #include "generic/reference.h"
291
NewNullNode()292 inline scene::Node& NewNullNode(){
293 return ( new scene::NullNode )->node();
294 }
295
Path_deleteTop(const scene::Path & path)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:
delete_all(scene::Node & parent)308 delete_all( scene::Node& parent ) : m_parent( parent ){
309 }
pre(scene::Node & node)310 bool pre( scene::Node& node ) const {
311 return false;
312 }
post(scene::Node & node)313 void post( scene::Node& node ) const {
314 Node_getTraversable( m_parent )->erase( node );
315 }
316 };
317
DeleteSubgraph(scene::Node & subgraph)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
Node_isEntity(scene::Node & node)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:
EntityWalker(const Functor & functor)338 EntityWalker( const Functor& functor ) : functor( functor ){
339 }
pre(const scene::Path & path,scene::Instance & instance)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>
Scene_forEachEntity(const Functor & 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
Node_isBrush(scene::Node & node)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
Node_isPatch(scene::Node & node)371 inline bool Node_isPatch( scene::Node& node ){
372 return NodeTypeCast<PatchUndefined>::cast( node ) != 0;
373 }
374
Node_isPrimitive(scene::Node & node)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:
ParentBrushes(scene::Node & parent)387 ParentBrushes( scene::Node& parent )
388 : m_parent( parent ){
389 }
pre(scene::Node & node)390 bool pre( scene::Node& node ) const {
391 return false;
392 }
post(scene::Node & node)393 void post( scene::Node& node ) const {
394 if ( Node_isPrimitive( node ) ) {
395 Node_getTraversable( m_parent )->insert( node );
396 }
397 }
398 };
399
parentBrushes(scene::Node & subgraph,scene::Node & parent)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:
HasBrushes(bool & hasBrushes)408 HasBrushes( bool& hasBrushes )
409 : m_hasBrushes( hasBrushes ){
410 m_hasBrushes = true;
411 }
pre(scene::Node & node)412 bool pre( scene::Node& node ) const {
413 if ( !Node_isPrimitive( node ) ) {
414 m_hasBrushes = false;
415 }
416 return false;
417 }
418 };
419
node_is_group(scene::Node & node)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;
InstanceType()438 InstanceType() : m_typeId( INSTANCETYPEID_NONE ){
439 StaticTypeSystemInitialiser::instance().addInitialiser( InitialiseCaller( *this ) );
440 }
initialise()441 void initialise(){
442 m_typeId = GlobalSceneGraph().getInstanceTypeId( Name() );
443 }
444 typedef MemberCaller<InstanceType<Type>, &InstanceType<Type>::initialise> InitialiseCaller;
getTypeId()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 };
getTypeId()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:
AABBAccumulateWalker(AABB & aabb)506 AABBAccumulateWalker( AABB& aabb ) : m_aabb( aabb ), m_depth( 0 ){
507 }
pre(const scene::Path & path,scene::Instance & instance)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 }
post(const scene::Path & path,scene::Instance & instance)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:
pre(const scene::Path & path,scene::Instance & instance)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:
pre(const scene::Path & path,scene::Instance & instance)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:
ChildSelectedWalker(bool & childSelected)543 ChildSelectedWalker( bool& childSelected ) : m_childSelected( childSelected ), m_depth( 0 ){
544 m_childSelected = false;
545 }
pre(const scene::Path & path,scene::Instance & instance)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 }
post(const scene::Path & path,scene::Instance & instance)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
evaluateTransform()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 }
evaluateChildBounds()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 }
evaluateBounds()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
Instance(const scene::Path & path,Instance * parent,void * instance,InstanceTypeCastTable & casts)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 }
~Instance()650 virtual ~Instance(){
651 }
652
path()653 const scene::Path& path() const {
654 return m_path;
655 }
656
cast(TypeId typeId)657 void* cast( TypeId typeId ) const {
658 return m_casts.cast( typeId, m_instance );
659 }
660
localToWorld()661 const Matrix4& localToWorld() const {
662 evaluateTransform();
663 return m_local2world;
664 }
transformChangedLocal()665 void transformChangedLocal(){
666 ASSERT_NOTNULL( m_parent );
667 m_transformChanged = true;
668 m_boundsChanged = true;
669 m_childBoundsChanged = true;
670 m_transformChangedCallback();
671 }
transformChanged()672 void transformChanged(){
673 GlobalSceneGraph().traverse_subgraph( TransformChangedWalker(), m_path );
674 boundsChanged();
675 }
setTransformChangedCallback(const Callback & callback)676 void setTransformChangedCallback( const Callback& callback ){
677 m_transformChangedCallback = callback;
678 }
679
680
worldAABB()681 const AABB& worldAABB() const {
682 evaluateBounds();
683 return m_bounds;
684 }
childBounds()685 const AABB& childBounds() const {
686 evaluateChildBounds();
687 return m_childBounds;
688 }
boundsChanged()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
childSelectedChanged()698 void childSelectedChanged(){
699 m_childSelectedChanged = true;
700 m_childSelectedChangedCallback();
701 if ( m_parent != 0 ) {
702 m_parent->childSelectedChanged();
703 }
704 }
childSelected()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
setChildSelectedChangedCallback(const Callback & callback)713 void setChildSelectedChangedCallback( const Callback& callback ){
714 m_childSelectedChangedCallback = callback;
715 }
selectedChanged()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 }
isSelected()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
parentSelectedChanged()732 void parentSelectedChanged(){
733 m_parentSelectedChanged = true;
734 }
parentSelected()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:
cast(scene::Instance & instance)749 static Type* cast( scene::Instance& instance ){
750 return static_cast<Type*>( instance.cast( StaticInstanceType<Type>::getTypeId() ) );
751 }
cast(const scene::Instance & instance)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:
InstanceWalker(const Functor & functor)762 InstanceWalker( const Functor& functor ) : m_functor( functor ){
763 }
pre(const scene::Path & path,scene::Instance & instance)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:
ChildInstanceWalker(const Functor & functor)776 ChildInstanceWalker( const Functor& functor ) : m_functor( functor ), m_depth( 0 ){
777 }
pre(const scene::Path & path,scene::Instance & instance)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 }
post(const scene::Path & path,scene::Instance & instance)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:
InstanceApply(const Functor & functor)793 InstanceApply( const Functor& functor ) : Functor( functor ){
794 }
operator()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
Instance_getSelectable(scene::Instance & instance)803 inline Selectable* Instance_getSelectable( scene::Instance& instance ){
804 return InstanceTypeCast<Selectable>::cast( instance );
805 }
Instance_getSelectable(const scene::Instance & instance)806 inline const Selectable* Instance_getSelectable( const scene::Instance& instance ){
807 return InstanceTypeCast<Selectable>::cast( instance );
808 }
809
810 template<typename Functor>
Scene_forEachChildSelectable(const Functor & functor,const scene::Path & path)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:
SelectableSetSelected(bool selected)819 SelectableSetSelected( bool selected ) : m_selected( selected ){
820 }
operator()821 void operator()( Selectable& selectable ) const {
822 selectable.setSelected( m_selected );
823 }
824 };
825
Instance_getBounded(scene::Instance & instance)826 inline Bounded* Instance_getBounded( scene::Instance& instance ){
827 return InstanceTypeCast<Bounded>::cast( instance );
828 }
Instance_getBounded(const scene::Instance & instance)829 inline const Bounded* Instance_getBounded( const scene::Instance& instance ){
830 return InstanceTypeCast<Bounded>::cast( instance );
831 }
832
Instance_getTransformable(scene::Instance & instance)833 inline Transformable* Instance_getTransformable( scene::Instance& instance ){
834 return InstanceTypeCast<Transformable>::cast( instance );
835 }
Instance_getTransformable(const scene::Instance & instance)836 inline const Transformable* Instance_getTransformable( const scene::Instance& instance ){
837 return InstanceTypeCast<Transformable>::cast( instance );
838 }
839
840
Instance_getComponentSelectionTestable(scene::Instance & instance)841 inline ComponentSelectionTestable* Instance_getComponentSelectionTestable( scene::Instance& instance ){
842 return InstanceTypeCast<ComponentSelectionTestable>::cast( instance );
843 }
844
Instance_getComponentEditable(scene::Instance & instance)845 inline ComponentEditable* Instance_getComponentEditable( scene::Instance& instance ){
846 return InstanceTypeCast<ComponentEditable>::cast( instance );
847 }
848
Instance_getComponentSnappable(scene::Instance & instance)849 inline ComponentSnappable* Instance_getComponentSnappable( scene::Instance& instance ){
850 return InstanceTypeCast<ComponentSnappable>::cast( instance );
851 }
852
853
Instance_setSelected(scene::Instance & instance,bool selected)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
Instance_isSelected(scene::Instance & instance)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
findInstance(const scene::Path & path)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
selectPath(const scene::Path & path,bool selected)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:
SelectChildren(const scene::Path & root)883 SelectChildren( const scene::Path& root )
884 : m_path( root ){
885 }
pre(scene::Node & node)886 bool pre( scene::Node& node ) const {
887 m_path.push( makeReference( node ) );
888 selectPath( m_path, true );
889 return false;
890 }
post(scene::Node & node)891 void post( scene::Node& node ) const {
892 m_path.pop();
893 }
894 };
895
Entity_setSelected(scene::Instance & entity,bool selected)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
Entity_isSelected(scene::Instance & entity)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;
InstanceCounter()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:
setCountChangedCallback(const Callback & countChanged)939 void setCountChangedCallback( const Callback& countChanged ){
940 m_countChanged = countChanged;
941 }
increment()942 void increment(){
943 ++m_count;
944 m_countChanged();
945 }
decrement()946 void decrement(){
947 --m_count;
948 m_countChanged();
949 }
get()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
965