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