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 "iscenegraph.h"
26 #include "iselection.h"
32 #include "math/aabb.h"
33 #include "transformlib.h"
34 #include "generic/callback.h"
35 #include "generic/reference.h"
36 #include "container/stack.h"
37 #include "typesystem.h"
42 template<typename Element> class BasicVector3;
43 typedef BasicVector3<float> Vector3;
44 template<typename Element> class BasicVector4;
45 typedef BasicVector4<float> Vector4;
47 typedef Vector4 Quaternion;
50 class ComponentSelectionTestable
53 STRING_CONSTANT( Name, "ComponentSelectionTestable" );
55 virtual bool isSelectedComponents() const = 0;
56 virtual void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ) = 0;
57 virtual void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ) = 0;
60 class ComponentEditable
63 STRING_CONSTANT( Name, "ComponentEditable" );
65 virtual const AABB& getSelectedComponentsBounds() const = 0;
68 class ComponentSnappable
71 STRING_CONSTANT( Name, "ComponentSnappable" );
73 virtual void snapComponents( float snap ) = 0;
79 STRING_CONSTANT( Name, "Bounded" );
81 virtual const AABB& localAABB() const = 0;
87 STRING_CONSTANT( Name, "BrushDoom3" );
89 virtual void setDoom3GroupOrigin( const Vector3& origin ) = 0;
95 typedef TypeCastTable<NODETYPEID_MAX> NodeTypeCastTable;
97 template<typename Type>
98 class NodeType : public StaticTypeSystemInitialiser
102 typedef typename Type::Name Name;
103 NodeType() : m_typeId( NODETYPEID_NONE ){
104 StaticTypeSystemInitialiser::instance().addInitialiser( InitialiseCaller( *this ) );
107 m_typeId = GlobalSceneGraph().getNodeTypeId( Name() );
109 typedef MemberCaller<NodeType<Type>, &NodeType<Type>::initialise> InitialiseCaller;
111 #if defined( _DEBUG )
112 ASSERT_MESSAGE( m_typeId != NODETYPEID_NONE, "node-type " << makeQuoted( Name() ) << " used before being initialised" );
118 template<typename Type>
122 enum unnamed0 { SIZE = NODETYPEID_MAX };
123 static TypeId getTypeId(){
124 return Static< NodeType<Type> >::instance().getTypeId();
128 template<typename Type, typename Base>
129 class NodeStaticCast :
130 public CastInstaller<
131 StaticNodeType<Base>,
132 StaticCast<Type, Base>
137 template<typename Type, typename Contained>
138 class NodeContainedCast :
139 public CastInstaller<
140 StaticNodeType<Contained>,
141 ContainedCast<Type, Contained>
146 template<typename Type>
147 class NodeIdentityCast :
148 public CastInstaller<
149 StaticNodeType<Type>,
160 enum unnamed0 { eVisible = 0 };
161 enum unnamed1 { eHidden = 1 << 0 };
162 enum unnamed2 { eFiltered = 1 << 1 };
163 enum unnamed3 { eExcluded = 1 << 2 };
168 virtual void release() = 0;
174 unsigned int m_state;
175 std::size_t m_refcount;
178 NodeTypeCastTable& m_casts;
187 Node( Symbiot* symbiot, void* node, NodeTypeCastTable& casts ) :
190 m_symbiot( symbiot ),
199 ASSERT_MESSAGE( m_refcount < ( 1 << 24 ), "Node::decref: uninitialised refcount" );
203 ASSERT_MESSAGE( m_refcount < ( 1 << 24 ), "Node::decref: uninitialised refcount" );
204 if ( --m_refcount == 0 ) {
205 m_symbiot->release();
208 std::size_t getReferenceCount() const {
212 void* cast( TypeId typeId ) const {
213 return m_casts.cast( typeId, m_node );
216 void enable( unsigned int state ){
219 void disable( unsigned int state ){
223 return m_state == eVisible;
226 return ( m_state & eExcluded ) != 0;
228 bool operator<( const scene::Node& other ){
229 return this < &other;
231 bool operator==( const scene::Node& other ){
232 return this == &other;
234 bool operator!=( const scene::Node& other ){
235 return this != &other;
240 class NullNode : public Node::Symbiot
242 NodeTypeCastTable m_casts;
245 NullNode() : m_node( this, 0, m_casts ){
256 template<typename Type>
260 static Type* cast( scene::Node& node ){
261 return static_cast<Type*>( node.cast( StaticNodeType<Type>::getTypeId() ) );
263 static const Type* cast( const scene::Node& node ){
264 return static_cast<const Type*>( node.cast( StaticNodeType<Type>::getTypeId() ) );
269 inline scene::Instantiable* Node_getInstantiable( scene::Node& node ){
270 return NodeTypeCast<scene::Instantiable>::cast( node );
273 inline scene::Traversable* Node_getTraversable( scene::Node& node ){
274 return NodeTypeCast<scene::Traversable>::cast( node );
277 inline void Node_traverseSubgraph( scene::Node& node, const scene::Traversable::Walker& walker ){
278 if ( walker.pre( node ) ) {
279 scene::Traversable* traversable = Node_getTraversable( node );
280 if ( traversable != 0 ) {
281 traversable->traverse( walker );
287 inline TransformNode* Node_getTransformNode( scene::Node& node ){
288 return NodeTypeCast<TransformNode>::cast( node );
292 inline scene::Node& NewNullNode(){
293 return ( new scene::NullNode )->node();
296 inline void Path_deleteTop( const scene::Path& path ){
297 Node_getTraversable( path.parent() )->erase( path.top() );
304 class delete_all : public scene::Traversable::Walker
306 scene::Node& m_parent;
308 delete_all( scene::Node& parent ) : m_parent( parent ){
310 bool pre( scene::Node& node ) const {
313 void post( scene::Node& node ) const {
314 Node_getTraversable( m_parent )->erase( node );
318 inline void DeleteSubgraph( scene::Node& subgraph ){
319 Node_getTraversable( subgraph )->traverse( delete_all( subgraph ) );
323 class EntityUndefined
326 STRING_CONSTANT( Name, "Entity" );
329 inline bool Node_isEntity( scene::Node& node ){
330 return NodeTypeCast<EntityUndefined>::cast( node ) != 0;
333 template<typename Functor>
334 class EntityWalker : public scene::Graph::Walker
336 const Functor& functor;
338 EntityWalker( const Functor& functor ) : functor( functor ){
340 bool pre( const scene::Path& path, scene::Instance& instance ) const {
341 if ( Node_isEntity( path.top() ) ) {
349 template<typename Functor>
350 inline const Functor& Scene_forEachEntity( const Functor& functor ){
351 GlobalSceneGraph().traverse( EntityWalker<Functor>( functor ) );
358 STRING_CONSTANT( Name, "Brush" );
361 inline bool Node_isBrush( scene::Node& node ){
362 return NodeTypeCast<BrushUndefined>::cast( node ) != 0;
368 STRING_CONSTANT( Name, "Patch" );
371 inline bool Node_isPatch( scene::Node& node ){
372 return NodeTypeCast<PatchUndefined>::cast( node ) != 0;
375 inline bool Node_isPrimitive( scene::Node& node ){
377 return Node_isBrush( node ) || Node_isPatch( node );
379 return !node.isRoot();
383 class ParentBrushes : public scene::Traversable::Walker
385 scene::Node& m_parent;
387 ParentBrushes( scene::Node& parent )
388 : m_parent( parent ){
390 bool pre( scene::Node& node ) const {
393 void post( scene::Node& node ) const {
394 if ( Node_isPrimitive( node ) ) {
395 Node_getTraversable( m_parent )->insert( node );
400 inline void parentBrushes( scene::Node& subgraph, scene::Node& parent ){
401 Node_getTraversable( subgraph )->traverse( ParentBrushes( parent ) );
404 class HasBrushes : public scene::Traversable::Walker
408 HasBrushes( bool& hasBrushes )
409 : m_hasBrushes( hasBrushes ){
412 bool pre( scene::Node& node ) const {
413 if ( !Node_isPrimitive( node ) ) {
414 m_hasBrushes = false;
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 ) );
430 typedef TypeCastTable<INSTANCETYPEID_MAX> InstanceTypeCastTable;
432 template<typename Type>
433 class InstanceType : public StaticTypeSystemInitialiser
437 typedef typename Type::Name Name;
438 InstanceType() : m_typeId( INSTANCETYPEID_NONE ){
439 StaticTypeSystemInitialiser::instance().addInitialiser( InitialiseCaller( *this ) );
442 m_typeId = GlobalSceneGraph().getInstanceTypeId( Name() );
444 typedef MemberCaller<InstanceType<Type>, &InstanceType<Type>::initialise> InitialiseCaller;
446 #if defined( _DEBUG )
447 ASSERT_MESSAGE( m_typeId != INSTANCETYPEID_NONE, "instance-type " << makeQuoted( Name() ) << " used before being initialised" );
453 template<typename Type>
454 class StaticInstanceType
457 enum unnamed0 { SIZE = INSTANCETYPEID_MAX };
458 static TypeId getTypeId(){
459 return Static< InstanceType<Type> >::instance().getTypeId();
463 template<typename Type, typename Base>
464 class InstanceStaticCast :
465 public CastInstaller<
466 StaticInstanceType<Base>,
467 StaticCast<Type, Base>
472 template<typename Type, typename Contained>
473 class InstanceContainedCast :
474 public CastInstaller<
475 StaticInstanceType<Contained>,
476 ContainedCast<Type, Contained>
481 template<typename Type>
482 class InstanceIdentityCast :
483 public CastInstaller<
484 StaticInstanceType<Type>,
491 inline Selectable* Instance_getSelectable( scene::Instance& instance );
492 inline const Selectable* Instance_getSelectable( const scene::Instance& instance );
494 inline Bounded* Instance_getBounded( scene::Instance& instance );
495 inline const Bounded* Instance_getBounded( const scene::Instance& instance );
501 class AABBAccumulateWalker : public scene::Graph::Walker
504 mutable std::size_t m_depth;
506 AABBAccumulateWalker( AABB& aabb ) : m_aabb( aabb ), m_depth( 0 ){
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() );
512 return ++m_depth != 2;
514 void post( const scene::Path& path, scene::Instance& instance ) const {
520 class TransformChangedWalker : public scene::Graph::Walker
523 bool pre( const scene::Path& path, scene::Instance& instance ) const {
524 instance.transformChangedLocal();
529 class ParentSelectedChangedWalker : public scene::Graph::Walker
532 bool pre( const scene::Path& path, scene::Instance& instance ) const {
533 instance.parentSelectedChanged();
538 class ChildSelectedWalker : public scene::Graph::Walker
540 bool& m_childSelected;
541 mutable std::size_t m_depth;
543 ChildSelectedWalker( bool& childSelected ) : m_childSelected( childSelected ), m_depth( 0 ){
544 m_childSelected = false;
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();
550 return ++m_depth != 2;
552 void post( const scene::Path& path, scene::Instance& instance ) const {
560 InstanceTypeCastTable& m_casts;
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;
581 void evaluateTransform() const {
582 if ( m_transformChanged ) {
583 ASSERT_MESSAGE( !m_transformMutex, "re-entering transform evaluation" );
584 m_transformMutex = true;
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() );
592 m_transformMutex = false;
593 m_transformChanged = false;
596 void evaluateChildBounds() const {
597 if ( m_childBoundsChanged ) {
598 ASSERT_MESSAGE( !m_childBoundsMutex, "re-entering bounds evaluation" );
599 m_childBoundsMutex = true;
601 m_childBounds = AABB();
603 GlobalSceneGraph().traverse_subgraph( AABBAccumulateWalker( m_childBounds ), m_path );
605 m_childBoundsMutex = false;
606 m_childBoundsChanged = false;
609 void evaluateBounds() const {
610 if ( m_boundsChanged ) {
611 ASSERT_MESSAGE( !m_boundsMutex, "re-entering bounds evaluation" );
612 m_boundsMutex = true;
614 m_bounds = childBounds();
616 const Bounded* bounded = Instance_getBounded( *this );
617 if ( bounded != 0 ) {
618 aabb_extend_by_aabb_safe(
620 aabb_for_oriented_aabb_safe( bounded->localAABB(), localToWorld() )
624 m_boundsMutex = false;
625 m_boundsChanged = false;
629 Instance( const scene::Instance& other );
630 Instance& operator=( const scene::Instance& other );
633 Instance( const scene::Path& path, Instance* parent, void* instance, InstanceTypeCastTable& casts ) :
636 m_instance( instance ),
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" );
653 const scene::Path& path() const {
657 void* cast( TypeId typeId ) const {
658 return m_casts.cast( typeId, m_instance );
661 const Matrix4& localToWorld() const {
663 return m_local2world;
665 void transformChangedLocal(){
666 ASSERT_NOTNULL( m_parent );
667 m_transformChanged = true;
668 m_boundsChanged = true;
669 m_childBoundsChanged = true;
670 m_transformChangedCallback();
672 void transformChanged(){
673 GlobalSceneGraph().traverse_subgraph( TransformChangedWalker(), m_path );
676 void setTransformChangedCallback( const Callback& callback ){
677 m_transformChangedCallback = callback;
681 const AABB& worldAABB() const {
685 const AABB& childBounds() const {
686 evaluateChildBounds();
687 return m_childBounds;
689 void boundsChanged(){
690 m_boundsChanged = true;
691 m_childBoundsChanged = true;
692 if ( m_parent != 0 ) {
693 m_parent->boundsChanged();
695 GlobalSceneGraph().boundsChanged();
698 void childSelectedChanged(){
699 m_childSelectedChanged = true;
700 m_childSelectedChangedCallback();
701 if ( m_parent != 0 ) {
702 m_parent->childSelectedChanged();
705 bool childSelected() const {
706 if ( m_childSelectedChanged ) {
707 m_childSelectedChanged = false;
708 GlobalSceneGraph().traverse_subgraph( ChildSelectedWalker( m_childSelected ), m_path );
710 return m_childSelected;
713 void setChildSelectedChangedCallback( const Callback& callback ){
714 m_childSelectedChangedCallback = callback;
716 void selectedChanged(){
717 m_isSelectedChanged = true;
718 if ( m_parent != 0 ) {
719 m_parent->childSelectedChanged();
721 GlobalSceneGraph().traverse_subgraph( ParentSelectedChangedWalker(), m_path );
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();
732 void parentSelectedChanged(){
733 m_parentSelectedChanged = true;
735 bool parentSelected() const {
736 if ( m_parentSelectedChanged ) {
737 m_parentSelectedChanged = false;
738 m_parentSelected = m_parent != 0 && ( m_parent->isSelected() || m_parent->parentSelected() );
740 return m_parentSelected;
742 Instance* parent() const
749 template<typename Type>
750 class InstanceTypeCast
753 static Type* cast( scene::Instance& instance ){
754 return static_cast<Type*>( instance.cast( StaticInstanceType<Type>::getTypeId() ) );
756 static const Type* cast( const scene::Instance& instance ){
757 return static_cast<const Type*>( instance.cast( StaticInstanceType<Type>::getTypeId() ) );
761 template<typename Functor>
762 class InstanceWalker : public scene::Graph::Walker
764 const Functor& m_functor;
766 InstanceWalker( const Functor& functor ) : m_functor( functor ){
768 bool pre( const scene::Path& path, scene::Instance& instance ) const {
769 //m_functor( instance );
771 if ( path.top().get().visible() ) {
772 m_functor( instance );
781 template<typename Functor>
782 class ChildInstanceWalker : public scene::Graph::Walker
784 const Functor& m_functor;
785 mutable std::size_t m_depth;
787 ChildInstanceWalker( const Functor& functor ) : m_functor( functor ), m_depth( 0 ){
789 bool pre( const scene::Path& path, scene::Instance& instance ) const {
790 if ( m_depth == 1 ) {
791 m_functor( instance );
793 return ++m_depth != 2;
795 void post( const scene::Path& path, scene::Instance& instance ) const {
800 template<typename Type, typename Functor>
801 class InstanceApply : public Functor
804 InstanceApply( const Functor& functor ) : Functor( functor ){
806 void operator()( scene::Instance& instance ) const {
807 Type* result = InstanceTypeCast<Type>::cast( instance );
809 Functor::operator()( *result );
814 inline Selectable* Instance_getSelectable( scene::Instance& instance ){
815 return InstanceTypeCast<Selectable>::cast( instance );
817 inline const Selectable* Instance_getSelectable( const scene::Instance& instance ){
818 return InstanceTypeCast<Selectable>::cast( instance );
821 template<typename Functor>
822 inline void Scene_forEachChildSelectable( const Functor& functor, const scene::Path& path ){
823 GlobalSceneGraph().traverse_subgraph( ChildInstanceWalker< InstanceApply<Selectable, Functor> >( functor ), path );
826 class SelectableSetSelected
830 SelectableSetSelected( bool selected ) : m_selected( selected ){
832 void operator()( Selectable& selectable ) const {
833 selectable.setSelected( m_selected );
837 inline Bounded* Instance_getBounded( scene::Instance& instance ){
838 return InstanceTypeCast<Bounded>::cast( instance );
840 inline const Bounded* Instance_getBounded( const scene::Instance& instance ){
841 return InstanceTypeCast<Bounded>::cast( instance );
844 inline Transformable* Instance_getTransformable( scene::Instance& instance ){
845 return InstanceTypeCast<Transformable>::cast( instance );
847 inline const Transformable* Instance_getTransformable( const scene::Instance& instance ){
848 return InstanceTypeCast<Transformable>::cast( instance );
852 inline ComponentSelectionTestable* Instance_getComponentSelectionTestable( scene::Instance& instance ){
853 return InstanceTypeCast<ComponentSelectionTestable>::cast( instance );
856 inline ComponentEditable* Instance_getComponentEditable( scene::Instance& instance ){
857 return InstanceTypeCast<ComponentEditable>::cast( instance );
860 inline ComponentSnappable* Instance_getComponentSnappable( scene::Instance& instance ){
861 return InstanceTypeCast<ComponentSnappable>::cast( instance );
865 inline void Instance_setSelected( scene::Instance& instance, bool selected ){
866 Selectable* selectable = Instance_getSelectable( instance );
867 if ( selectable != 0 ) {
868 selectable->setSelected( selected );
872 inline bool Instance_isSelected( scene::Instance& instance ){
873 Selectable* selectable = Instance_getSelectable( instance );
874 if ( selectable != 0 ) {
875 return selectable->isSelected();
880 inline scene::Instance& findInstance( const scene::Path& path ){
881 scene::Instance* instance = GlobalSceneGraph().find( path );
882 ASSERT_MESSAGE( instance != 0, "findInstance: path not found in scene-graph" );
886 inline void selectPath( const scene::Path& path, bool selected ){
887 Instance_setSelected( findInstance( path ), selected );
890 class SelectChildren : public scene::Traversable::Walker
892 mutable scene::Path m_path;
894 SelectChildren( const scene::Path& root )
897 bool pre( scene::Node& node ) const {
898 m_path.push( makeReference( node ) );
899 selectPath( m_path, true );
902 void post( scene::Node& node ) const {
907 inline void Entity_setSelected( scene::Instance& entity, bool selected ){
908 scene::Node& node = entity.path().top();
909 if ( node_is_group( node ) ) {
910 Node_getTraversable( node )->traverse( SelectChildren( entity.path() ) );
914 Instance_setSelected( entity, selected );
918 inline bool Entity_isSelected( scene::Instance& entity ){
919 if ( node_is_group( entity.path().top() ) ) {
920 return entity.childSelected();
922 return Instance_isSelected( entity );
927 class InstanceCounter
930 unsigned int m_count;
931 InstanceCounter() : m_count( 0 ){
939 virtual void increment() = 0;
940 virtual void decrement() = 0;
943 #include "generic/callback.h"
945 class SimpleCounter : public Counter
947 Callback m_countChanged;
950 void setCountChangedCallback( const Callback& countChanged ){
951 m_countChanged = countChanged;
961 std::size_t get() const {
967 template<typename Contained>
968 class ConstReference;
969 typedef ConstReference<scene::Path> PathConstReference;
971 #include "generic/referencecounted.h"
972 typedef SmartReference<scene::Node, IncRefDecRefCounter<scene::Node> > NodeSmartReference;