2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
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.
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.
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
22 #if !defined ( INCLUDED_SCENELIB_H )
23 #define INCLUDED_SCENELIB_H
25 #include "globaldefs.h"
26 #include "iscenegraph.h"
27 #include "iselection.h"
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"
43 template<typename Element> class BasicVector3;
44 typedef BasicVector3<float> Vector3;
45 template<typename Element> class BasicVector4;
46 typedef BasicVector4<float> Vector4;
48 typedef Vector4 Quaternion;
51 class ComponentSelectionTestable
54 STRING_CONSTANT( Name, "ComponentSelectionTestable" );
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;
61 class ComponentEditable
64 STRING_CONSTANT( Name, "ComponentEditable" );
66 virtual const AABB& getSelectedComponentsBounds() const = 0;
69 class ComponentSnappable
72 STRING_CONSTANT( Name, "ComponentSnappable" );
74 virtual void snapComponents( float snap ) = 0;
80 STRING_CONSTANT( Name, "Bounded" );
82 virtual const AABB& localAABB() const = 0;
88 STRING_CONSTANT( Name, "BrushDoom3" );
90 virtual void setDoom3GroupOrigin( const Vector3& origin ) = 0;
96 typedef TypeCastTable<NODETYPEID_MAX> NodeTypeCastTable;
98 template<typename Type>
99 class NodeType : public StaticTypeSystemInitialiser
103 typedef typename Type::Name Name;
104 NodeType() : m_typeId( NODETYPEID_NONE ){
105 StaticTypeSystemInitialiser::instance().addInitialiser( InitialiseCaller( *this ) );
108 m_typeId = GlobalSceneGraph().getNodeTypeId( Name() );
110 typedef MemberCaller<NodeType<Type>, void(), &NodeType<Type>::initialise> InitialiseCaller;
113 ASSERT_MESSAGE( m_typeId != NODETYPEID_NONE, "node-type " << makeQuoted( Name() ) << " used before being initialised" );
119 template<typename Type>
123 enum unnamed0 { SIZE = NODETYPEID_MAX };
124 static TypeId getTypeId(){
125 return Static< NodeType<Type> >::instance().getTypeId();
129 template<typename Type, typename Base>
130 class NodeStaticCast :
131 public CastInstaller<
132 StaticNodeType<Base>,
133 StaticCast<Type, Base>
138 template<typename Type, typename Contained>
139 class NodeContainedCast :
140 public CastInstaller<
141 StaticNodeType<Contained>,
142 ContainedCast<Type, Contained>
147 template<typename Type>
148 class NodeIdentityCast :
149 public CastInstaller<
150 StaticNodeType<Type>,
161 enum unnamed0 { eVisible = 0 };
162 enum unnamed1 { eHidden = 1 << 0 };
163 enum unnamed2 { eFiltered = 1 << 1 };
164 enum unnamed3 { eExcluded = 1 << 2 };
169 virtual void release() = 0;
175 unsigned int m_state;
176 std::size_t m_refcount;
179 NodeTypeCastTable& m_casts;
188 Node( Symbiot* symbiot, void* node, NodeTypeCastTable& casts ) :
191 m_symbiot( symbiot ),
200 ASSERT_MESSAGE( m_refcount < ( 1 << 24 ), "Node::decref: uninitialised refcount" );
204 ASSERT_MESSAGE( m_refcount < ( 1 << 24 ), "Node::decref: uninitialised refcount" );
205 if ( --m_refcount == 0 ) {
206 m_symbiot->release();
209 std::size_t getReferenceCount() const {
213 void* cast( TypeId typeId ) const {
214 return m_casts.cast( typeId, m_node );
217 void enable( unsigned int state ){
220 void disable( unsigned int state ){
224 return m_state == eVisible;
227 return ( m_state & eExcluded ) != 0;
229 bool operator<( const scene::Node& other ){
230 return this < &other;
232 bool operator==( const scene::Node& other ){
233 return this == &other;
235 bool operator!=( const scene::Node& other ){
236 return this != &other;
241 class NullNode : public Node::Symbiot
243 NodeTypeCastTable m_casts;
246 NullNode() : m_node( this, 0, m_casts ){
257 template<typename Type>
261 static Type* cast( scene::Node& node ){
262 return static_cast<Type*>( node.cast( StaticNodeType<Type>::getTypeId() ) );
264 static const Type* cast( const scene::Node& node ){
265 return static_cast<const Type*>( node.cast( StaticNodeType<Type>::getTypeId() ) );
270 inline scene::Instantiable* Node_getInstantiable( scene::Node& node ){
271 return NodeTypeCast<scene::Instantiable>::cast( node );
274 inline scene::Traversable* Node_getTraversable( scene::Node& node ){
275 return NodeTypeCast<scene::Traversable>::cast( node );
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 );
288 inline TransformNode* Node_getTransformNode( scene::Node& node ){
289 return NodeTypeCast<TransformNode>::cast( node );
293 inline scene::Node& NewNullNode(){
294 return ( new scene::NullNode )->node();
297 inline void Path_deleteTop( const scene::Path& path ){
298 Node_getTraversable( path.parent() )->erase( path.top() );
305 class delete_all : public scene::Traversable::Walker
307 scene::Node& m_parent;
309 delete_all( scene::Node& parent ) : m_parent( parent ){
311 bool pre( scene::Node& node ) const {
314 void post( scene::Node& node ) const {
315 Node_getTraversable( m_parent )->erase( node );
319 inline void DeleteSubgraph( scene::Node& subgraph ){
320 Node_getTraversable( subgraph )->traverse( delete_all( subgraph ) );
324 class EntityUndefined
327 STRING_CONSTANT( Name, "Entity" );
330 inline bool Node_isEntity( scene::Node& node ){
331 return NodeTypeCast<EntityUndefined>::cast( node ) != 0;
334 template<typename Functor>
335 class EntityWalker : public scene::Graph::Walker
337 const Functor& functor;
339 EntityWalker( const Functor& functor ) : functor( functor ){
341 bool pre( const scene::Path& path, scene::Instance& instance ) const {
342 if ( Node_isEntity( path.top() ) ) {
350 template<typename Functor>
351 inline const Functor& Scene_forEachEntity( const Functor& functor ){
352 GlobalSceneGraph().traverse( EntityWalker<Functor>( functor ) );
359 STRING_CONSTANT( Name, "Brush" );
362 inline bool Node_isBrush( scene::Node& node ){
363 return NodeTypeCast<BrushUndefined>::cast( node ) != 0;
369 STRING_CONSTANT( Name, "Patch" );
372 inline bool Node_isPatch( scene::Node& node ){
373 return NodeTypeCast<PatchUndefined>::cast( node ) != 0;
376 inline bool Node_isPrimitive( scene::Node& node ){
378 return Node_isBrush( node ) || Node_isPatch( node );
380 return !node.isRoot();
384 class ParentBrushes : public scene::Traversable::Walker
386 scene::Node& m_parent;
388 ParentBrushes( scene::Node& parent )
389 : m_parent( parent ){
391 bool pre( scene::Node& node ) const {
394 void post( scene::Node& node ) const {
395 if ( Node_isPrimitive( node ) ) {
396 Node_getTraversable( m_parent )->insert( node );
401 inline void parentBrushes( scene::Node& subgraph, scene::Node& parent ){
402 Node_getTraversable( subgraph )->traverse( ParentBrushes( parent ) );
405 class HasBrushes : public scene::Traversable::Walker
409 HasBrushes( bool& hasBrushes )
410 : m_hasBrushes( hasBrushes ){
413 bool pre( scene::Node& node ) const {
414 if ( !Node_isPrimitive( node ) ) {
415 m_hasBrushes = false;
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 ) );
431 typedef TypeCastTable<INSTANCETYPEID_MAX> InstanceTypeCastTable;
433 template<typename Type>
434 class InstanceType : public StaticTypeSystemInitialiser
438 typedef typename Type::Name Name;
439 InstanceType() : m_typeId( INSTANCETYPEID_NONE ){
440 StaticTypeSystemInitialiser::instance().addInitialiser( InitialiseCaller( *this ) );
443 m_typeId = GlobalSceneGraph().getInstanceTypeId( Name() );
445 typedef MemberCaller<InstanceType<Type>, void(), &InstanceType<Type>::initialise> InitialiseCaller;
448 ASSERT_MESSAGE( m_typeId != INSTANCETYPEID_NONE, "instance-type " << makeQuoted( Name() ) << " used before being initialised" );
454 template<typename Type>
455 class StaticInstanceType
458 enum unnamed0 { SIZE = INSTANCETYPEID_MAX };
459 static TypeId getTypeId(){
460 return Static< InstanceType<Type> >::instance().getTypeId();
464 template<typename Type, typename Base>
465 class InstanceStaticCast :
466 public CastInstaller<
467 StaticInstanceType<Base>,
468 StaticCast<Type, Base>
473 template<typename Type, typename Contained>
474 class InstanceContainedCast :
475 public CastInstaller<
476 StaticInstanceType<Contained>,
477 ContainedCast<Type, Contained>
482 template<typename Type>
483 class InstanceIdentityCast :
484 public CastInstaller<
485 StaticInstanceType<Type>,
492 inline Selectable* Instance_getSelectable( scene::Instance& instance );
493 inline const Selectable* Instance_getSelectable( const scene::Instance& instance );
495 inline Bounded* Instance_getBounded( scene::Instance& instance );
496 inline const Bounded* Instance_getBounded( const scene::Instance& instance );
502 class AABBAccumulateWalker : public scene::Graph::Walker
505 mutable std::size_t m_depth;
507 AABBAccumulateWalker( AABB& aabb ) : m_aabb( aabb ), m_depth( 0 ){
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() );
513 return ++m_depth != 2;
515 void post( const scene::Path& path, scene::Instance& instance ) const {
521 class TransformChangedWalker : public scene::Graph::Walker
524 bool pre( const scene::Path& path, scene::Instance& instance ) const {
525 instance.transformChangedLocal();
530 class ParentSelectedChangedWalker : public scene::Graph::Walker
533 bool pre( const scene::Path& path, scene::Instance& instance ) const {
534 instance.parentSelectedChanged();
539 class ChildSelectedWalker : public scene::Graph::Walker
541 bool& m_childSelected;
542 mutable std::size_t m_depth;
544 ChildSelectedWalker( bool& childSelected ) : m_childSelected( childSelected ), m_depth( 0 ){
545 m_childSelected = false;
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();
551 return ++m_depth != 2;
553 void post( const scene::Path& path, scene::Instance& instance ) const {
561 InstanceTypeCastTable& m_casts;
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<void()> m_childSelectedChangedCallback;
579 Callback<void()> m_transformChangedCallback;
582 void evaluateTransform() const {
583 if ( m_transformChanged ) {
584 ASSERT_MESSAGE( !m_transformMutex, "re-entering transform evaluation" );
585 m_transformMutex = true;
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() );
593 m_transformMutex = false;
594 m_transformChanged = false;
597 void evaluateChildBounds() const {
598 if ( m_childBoundsChanged ) {
599 ASSERT_MESSAGE( !m_childBoundsMutex, "re-entering bounds evaluation" );
600 m_childBoundsMutex = true;
602 m_childBounds = AABB();
604 GlobalSceneGraph().traverse_subgraph( AABBAccumulateWalker( m_childBounds ), m_path );
606 m_childBoundsMutex = false;
607 m_childBoundsChanged = false;
610 void evaluateBounds() const {
611 if ( m_boundsChanged ) {
612 ASSERT_MESSAGE( !m_boundsMutex, "re-entering bounds evaluation" );
613 m_boundsMutex = true;
615 m_bounds = childBounds();
617 const Bounded* bounded = Instance_getBounded( *this );
618 if ( bounded != 0 ) {
619 aabb_extend_by_aabb_safe(
621 aabb_for_oriented_aabb_safe( bounded->localAABB(), localToWorld() )
625 m_boundsMutex = false;
626 m_boundsChanged = false;
630 Instance( const scene::Instance& other );
631 Instance& operator=( const scene::Instance& other );
634 Instance( const scene::Path& path, Instance* parent, void* instance, InstanceTypeCastTable& casts ) :
637 m_instance( instance ),
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" );
654 const scene::Path& path() const {
658 void* cast( TypeId typeId ) const {
659 return m_casts.cast( typeId, m_instance );
662 const Matrix4& localToWorld() const {
664 return m_local2world;
666 void transformChangedLocal(){
667 ASSERT_NOTNULL( m_parent );
668 m_transformChanged = true;
669 m_boundsChanged = true;
670 m_childBoundsChanged = true;
671 m_transformChangedCallback();
673 void transformChanged(){
674 GlobalSceneGraph().traverse_subgraph( TransformChangedWalker(), m_path );
677 void setTransformChangedCallback( const Callback<void()>& callback ){
678 m_transformChangedCallback = callback;
682 const AABB& worldAABB() const {
686 const AABB& childBounds() const {
687 evaluateChildBounds();
688 return m_childBounds;
690 void boundsChanged(){
691 m_boundsChanged = true;
692 m_childBoundsChanged = true;
693 if ( m_parent != 0 ) {
694 m_parent->boundsChanged();
696 GlobalSceneGraph().boundsChanged();
699 void childSelectedChanged(){
700 m_childSelectedChanged = true;
701 m_childSelectedChangedCallback();
702 if ( m_parent != 0 ) {
703 m_parent->childSelectedChanged();
706 bool childSelected() const {
707 if ( m_childSelectedChanged ) {
708 m_childSelectedChanged = false;
709 GlobalSceneGraph().traverse_subgraph( ChildSelectedWalker( m_childSelected ), m_path );
711 return m_childSelected;
714 void setChildSelectedChangedCallback( const Callback<void()>& callback ){
715 m_childSelectedChangedCallback = callback;
717 void selectedChanged(){
718 m_isSelectedChanged = true;
719 if ( m_parent != 0 ) {
720 m_parent->childSelectedChanged();
722 GlobalSceneGraph().traverse_subgraph( ParentSelectedChangedWalker(), m_path );
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();
733 void parentSelectedChanged(){
734 m_parentSelectedChanged = true;
736 bool parentSelected() const {
737 if ( m_parentSelectedChanged ) {
738 m_parentSelectedChanged = false;
739 m_parentSelected = m_parent != 0 && ( m_parent->isSelected() || m_parent->parentSelected() );
741 return m_parentSelected;
746 template<typename Type>
747 class InstanceTypeCast
750 static Type* cast( scene::Instance& instance ){
751 return static_cast<Type*>( instance.cast( StaticInstanceType<Type>::getTypeId() ) );
753 static const Type* cast( const scene::Instance& instance ){
754 return static_cast<const Type*>( instance.cast( StaticInstanceType<Type>::getTypeId() ) );
758 template<typename Functor>
759 class InstanceWalker : public scene::Graph::Walker
761 const Functor& m_functor;
763 InstanceWalker( const Functor& functor ) : m_functor( functor ){
765 bool pre( const scene::Path& path, scene::Instance& instance ) const {
766 m_functor( instance );
771 template<typename Functor>
772 class ChildInstanceWalker : public scene::Graph::Walker
774 const Functor& m_functor;
775 mutable std::size_t m_depth;
777 ChildInstanceWalker( const Functor& functor ) : m_functor( functor ), m_depth( 0 ){
779 bool pre( const scene::Path& path, scene::Instance& instance ) const {
780 if ( m_depth == 1 ) {
781 m_functor( instance );
783 return ++m_depth != 2;
785 void post( const scene::Path& path, scene::Instance& instance ) const {
790 template<typename Type, typename Functor>
791 class InstanceApply : public Functor
794 InstanceApply( const Functor& functor ) : Functor( functor ){
796 void operator()( scene::Instance& instance ) const {
797 Type* result = InstanceTypeCast<Type>::cast( instance );
799 Functor::operator()( *result );
804 inline Selectable* Instance_getSelectable( scene::Instance& instance ){
805 return InstanceTypeCast<Selectable>::cast( instance );
807 inline const Selectable* Instance_getSelectable( const scene::Instance& instance ){
808 return InstanceTypeCast<Selectable>::cast( instance );
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 );
816 class SelectableSetSelected
820 SelectableSetSelected( bool selected ) : m_selected( selected ){
822 void operator()( Selectable& selectable ) const {
823 selectable.setSelected( m_selected );
827 inline Bounded* Instance_getBounded( scene::Instance& instance ){
828 return InstanceTypeCast<Bounded>::cast( instance );
830 inline const Bounded* Instance_getBounded( const scene::Instance& instance ){
831 return InstanceTypeCast<Bounded>::cast( instance );
834 inline Transformable* Instance_getTransformable( scene::Instance& instance ){
835 return InstanceTypeCast<Transformable>::cast( instance );
837 inline const Transformable* Instance_getTransformable( const scene::Instance& instance ){
838 return InstanceTypeCast<Transformable>::cast( instance );
842 inline ComponentSelectionTestable* Instance_getComponentSelectionTestable( scene::Instance& instance ){
843 return InstanceTypeCast<ComponentSelectionTestable>::cast( instance );
846 inline ComponentEditable* Instance_getComponentEditable( scene::Instance& instance ){
847 return InstanceTypeCast<ComponentEditable>::cast( instance );
850 inline ComponentSnappable* Instance_getComponentSnappable( scene::Instance& instance ){
851 return InstanceTypeCast<ComponentSnappable>::cast( instance );
855 inline void Instance_setSelected( scene::Instance& instance, bool selected ){
856 Selectable* selectable = Instance_getSelectable( instance );
857 if ( selectable != 0 ) {
858 selectable->setSelected( selected );
862 inline bool Instance_isSelected( scene::Instance& instance ){
863 Selectable* selectable = Instance_getSelectable( instance );
864 if ( selectable != 0 ) {
865 return selectable->isSelected();
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" );
876 inline void selectPath( const scene::Path& path, bool selected ){
877 Instance_setSelected( findInstance( path ), selected );
880 class SelectChildren : public scene::Traversable::Walker
882 mutable scene::Path m_path;
884 SelectChildren( const scene::Path& root )
887 bool pre( scene::Node& node ) const {
888 m_path.push( makeReference( node ) );
889 selectPath( m_path, true );
892 void post( scene::Node& node ) const {
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() ) );
904 Instance_setSelected( entity, selected );
908 inline bool Entity_isSelected( scene::Instance& entity ){
909 if ( node_is_group( entity.path().top() ) ) {
910 return entity.childSelected();
912 return Instance_isSelected( entity );
917 class InstanceCounter
920 unsigned int m_count;
921 InstanceCounter() : m_count( 0 ){
929 virtual void increment() = 0;
930 virtual void decrement() = 0;
933 #include "generic/callback.h"
935 class SimpleCounter : public Counter
937 Callback<void()> m_countChanged;
940 void setCountChangedCallback( const Callback<void()>& countChanged ){
941 m_countChanged = countChanged;
951 std::size_t get() const {
957 template<typename Contained>
958 class ConstReference;
959 typedef ConstReference<scene::Path> PathConstReference;
961 #include "generic/referencecounted.h"
962 typedef SmartReference<scene::Node, IncRefDecRefCounter<scene::Node> > NodeSmartReference;