X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=libs%2Fscenelib.h;h=e1c05d464d8ba5ee096c55f6f08c2a122db47e9e;hb=HEAD;hp=71d4963b9da45584743f1c0d9d1f4ce62a5a1c76;hpb=12b372f89ce109a4db9d510884fbe7d05af79870;p=xonotic%2Fnetradiant.git diff --git a/libs/scenelib.h b/libs/scenelib.h index 71d4963b..d15ce802 100644 --- a/libs/scenelib.h +++ b/libs/scenelib.h @@ -1,27 +1,28 @@ /* -Copyright (C) 2001-2006, William Joseph. -All Rights Reserved. + Copyright (C) 2001-2006, William Joseph. + All Rights Reserved. -This file is part of GtkRadiant. + This file is part of GtkRadiant. -GtkRadiant is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -GtkRadiant is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ -#if !defined (INCLUDED_SCENELIB_H) +#if !defined ( INCLUDED_SCENELIB_H ) #define INCLUDED_SCENELIB_H +#include "globaldefs.h" #include "iscenegraph.h" #include "iselection.h" @@ -50,43 +51,43 @@ class AABB; class ComponentSelectionTestable { public: - STRING_CONSTANT(Name, "ComponentSelectionTestable"); +STRING_CONSTANT( Name, "ComponentSelectionTestable" ); - virtual bool isSelectedComponents() const = 0; - virtual void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) = 0; - virtual void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) = 0; +virtual bool isSelectedComponents() const = 0; +virtual void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ) = 0; +virtual void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ) = 0; }; class ComponentEditable { public: - STRING_CONSTANT(Name, "ComponentEditable"); +STRING_CONSTANT( Name, "ComponentEditable" ); - virtual const AABB& getSelectedComponentsBounds() const = 0; +virtual const AABB& getSelectedComponentsBounds() const = 0; }; class ComponentSnappable { public: - STRING_CONSTANT(Name, "ComponentSnappable"); +STRING_CONSTANT( Name, "ComponentSnappable" ); - virtual void snapComponents(float snap) = 0; +virtual void snapComponents( float snap ) = 0; }; class Bounded { public: - STRING_CONSTANT(Name, "Bounded"); +STRING_CONSTANT( Name, "Bounded" ); - virtual const AABB& localAABB() const = 0; +virtual const AABB& localAABB() const = 0; }; class BrushDoom3 { public: - STRING_CONSTANT(Name, "BrushDoom3"); +STRING_CONSTANT( Name, "BrushDoom3" ); - virtual void setDoom3GroupOrigin(const Vector3& origin) = 0; +virtual void setDoom3GroupOrigin( const Vector3& origin ) = 0; }; @@ -97,234 +98,204 @@ typedef TypeCastTable NodeTypeCastTable; template class NodeType : public StaticTypeSystemInitialiser { - TypeId m_typeId; +TypeId m_typeId; public: - typedef typename Type::Name Name; - NodeType() : m_typeId(NODETYPEID_NONE) - { - StaticTypeSystemInitialiser::instance().addInitialiser(InitialiseCaller(*this)); - } - void initialise() - { - m_typeId = GlobalSceneGraph().getNodeTypeId(Name()); - } - typedef MemberCaller, &NodeType::initialise> InitialiseCaller; - TypeId getTypeId() - { -#if defined(_DEBUG) - ASSERT_MESSAGE(m_typeId != NODETYPEID_NONE, "node-type " << makeQuoted(Name()) << " used before being initialised"); +typedef typename Type::Name Name; +NodeType() : m_typeId( NODETYPEID_NONE ){ + StaticTypeSystemInitialiser::instance().addInitialiser( InitialiseCaller( *this ) ); +} +void initialise(){ + m_typeId = GlobalSceneGraph().getNodeTypeId( Name() ); +} +typedef MemberCaller, void(), &NodeType::initialise> InitialiseCaller; +TypeId getTypeId(){ +#if GDEF_DEBUG + ASSERT_MESSAGE( m_typeId != NODETYPEID_NONE, "node-type " << makeQuoted( Name() ) << " used before being initialised" ); #endif - return m_typeId; - } + return m_typeId; +} }; template class StaticNodeType { public: - static const int SIZE = NODETYPEID_MAX; - static TypeId getTypeId() - { - return Static< NodeType >::instance().getTypeId(); - } +enum unnamed0 { SIZE = NODETYPEID_MAX }; +static TypeId getTypeId(){ + return Static< NodeType >::instance().getTypeId(); +} }; template class NodeStaticCast : - public CastInstaller< - StaticNodeType, - StaticCast - > + public CastInstaller< + StaticNodeType, + StaticCast + > { }; template class NodeContainedCast : - public CastInstaller< - StaticNodeType, - ContainedCast - > + public CastInstaller< + StaticNodeType, + ContainedCast + > { }; template class NodeIdentityCast : - public CastInstaller< - StaticNodeType, - IdentityCast - > + public CastInstaller< + StaticNodeType, + IdentityCast + > { }; namespace scene { - class Node - { - public: - static const int eVisible = 0; - static const int eHidden = 1 << 0; - static const int eFiltered = 1 << 1; - static const int eExcluded = 1 << 2; - - class Symbiot - { - public: - virtual void release() = 0; - }; - - private: - unsigned int m_state; - std::size_t m_refcount; - Symbiot* m_symbiot; - void* m_node; - NodeTypeCastTable& m_casts; - - public: - bool m_isRoot; - - bool isRoot() - { - return m_isRoot; - } - - Node(Symbiot* symbiot, void* node, NodeTypeCastTable& casts) : - m_state(eVisible), - m_refcount(0), - m_symbiot(symbiot), - m_node(node), - m_casts(casts), - m_isRoot(false) - { - } - ~Node() - { - } - - void IncRef() - { - ASSERT_MESSAGE(m_refcount < (1 << 24), "Node::decref: uninitialised refcount"); - ++m_refcount; - } - void DecRef() - { - ASSERT_MESSAGE(m_refcount < (1 << 24), "Node::decref: uninitialised refcount"); - if(--m_refcount == 0) - { - m_symbiot->release(); - } - } - std::size_t getReferenceCount() const - { - return m_refcount; - } - - void* cast(TypeId typeId) const - { - return m_casts.cast(typeId, m_node); - } - - void enable(unsigned int state) - { - m_state |= state; - } - void disable(unsigned int state) - { - m_state &= ~state; - } - bool visible() - { - return m_state == eVisible; - } - bool excluded() - { - return (m_state & eExcluded) != 0; - } - }; - - class NullNode : public Node::Symbiot - { - NodeTypeCastTable m_casts; - Node m_node; - public: - NullNode() : m_node(this, 0, m_casts) - { - } - void release() - { - delete this; - } - scene::Node& node() - { - return m_node; - } - }; -} +class Node +{ +public: +enum unnamed0 { eVisible = 0 }; +enum unnamed1 { eHidden = 1 << 0 }; +enum unnamed2 { eFiltered = 1 << 1 }; +enum unnamed3 { eExcluded = 1 << 2 }; -template -class NodeTypeCast +class Symbiot { public: - static Type* cast(scene::Node& node) - { - return static_cast(node.cast(StaticNodeType::getTypeId())); - } - static const Type* cast(const scene::Node& node) - { - return static_cast(node.cast(StaticNodeType::getTypeId())); - } +virtual void release() = 0; +virtual ~Symbiot(){ +} }; +private: +unsigned int m_state; +std::size_t m_refcount; +Symbiot* m_symbiot; +void* m_node; +NodeTypeCastTable& m_casts; -inline scene::Instantiable* Node_getInstantiable(scene::Node& node) -{ - return NodeTypeCast::cast(node); +public: +bool m_isRoot; + +bool isRoot(){ + return m_isRoot; } -inline scene::Traversable* Node_getTraversable(scene::Node& node) -{ - return NodeTypeCast::cast(node); +Node( Symbiot* symbiot, void* node, NodeTypeCastTable& casts ) : + m_state( eVisible ), + m_refcount( 0 ), + m_symbiot( symbiot ), + m_node( node ), + m_casts( casts ), + m_isRoot( false ){ +} +~Node(){ } -inline void Node_traverseSubgraph(scene::Node& node, const scene::Traversable::Walker& walker) -{ - if(walker.pre(node)) - { - scene::Traversable* traversable = Node_getTraversable(node); - if(traversable != 0) - { - traversable->traverse(walker); - } - } - walker.post(node); -} - -inline TransformNode* Node_getTransformNode(scene::Node& node) -{ - return NodeTypeCast::cast(node); +void IncRef(){ + ASSERT_MESSAGE( m_refcount < ( 1 << 24 ), "Node::decref: uninitialised refcount" ); + ++m_refcount; +} +void DecRef(){ + ASSERT_MESSAGE( m_refcount < ( 1 << 24 ), "Node::decref: uninitialised refcount" ); + if ( --m_refcount == 0 ) { + m_symbiot->release(); + } +} +std::size_t getReferenceCount() const { + return m_refcount; } -inline bool operator<(scene::Node& node, scene::Node& other) -{ - return &node < &other; +void* cast( TypeId typeId ) const { + return m_casts.cast( typeId, m_node ); } -inline bool operator==(scene::Node& node, scene::Node& other) -{ - return &node == &other; + +void enable( unsigned int state ){ + m_state |= state; } -inline bool operator!=(scene::Node& node, scene::Node& other) -{ - return !::operator==(node, other); +void disable( unsigned int state ){ + m_state &= ~state; +} +bool visible(){ + return m_state == eVisible; +} +bool excluded(){ + return ( m_state & eExcluded ) != 0; +} +bool operator<( const scene::Node& other ){ + return this < &other; +} +bool operator==( const scene::Node& other ){ + return this == &other; +} +bool operator!=( const scene::Node& other ){ + return this != &other; } +}; -inline scene::Node& NewNullNode() +class NullNode : public Node::Symbiot { - return (new scene::NullNode)->node(); +NodeTypeCastTable m_casts; +Node m_node; +public: +NullNode() : m_node( this, 0, m_casts ){ +} +void release(){ + delete this; +} +scene::Node& node(){ + return m_node; +} +}; } -inline void Path_deleteTop(const scene::Path& path) +template +class NodeTypeCast { - Node_getTraversable(path.parent())->erase(path.top()); +public: +static Type* cast( scene::Node& node ){ + return static_cast( node.cast( StaticNodeType::getTypeId() ) ); +} +static const Type* cast( const scene::Node& node ){ + return static_cast( node.cast( StaticNodeType::getTypeId() ) ); +} +}; + + +inline scene::Instantiable* Node_getInstantiable( scene::Node& node ){ + return NodeTypeCast::cast( node ); +} + +inline scene::Traversable* Node_getTraversable( scene::Node& node ){ + return NodeTypeCast::cast( node ); +} + +inline void Node_traverseSubgraph( scene::Node& node, const scene::Traversable::Walker& walker ){ + if ( walker.pre( node ) ) { + scene::Traversable* traversable = Node_getTraversable( node ); + if ( traversable != 0 ) { + traversable->traverse( walker ); + } + } + walker.post( node ); +} + +inline TransformNode* Node_getTransformNode( scene::Node& node ){ + return NodeTypeCast::cast( node ); +} + + +inline scene::Node& NewNullNode(){ + return ( new scene::NullNode )->node(); +} + +inline void Path_deleteTop( const scene::Path& path ){ + Node_getTraversable( path.parent() )->erase( path.top() ); } @@ -333,124 +304,128 @@ inline void Path_deleteTop(const scene::Path& path) class delete_all : public scene::Traversable::Walker { - scene::Node& m_parent; +scene::Node& m_parent; public: - delete_all(scene::Node& parent) : m_parent(parent) - { - } - bool pre(scene::Node& node) const - { - return false; - } - void post(scene::Node& node) const - { - Node_getTraversable(m_parent)->erase(node); - } +delete_all( scene::Node& parent ) : m_parent( parent ){ +} +bool pre( scene::Node& node ) const { + return false; +} +void post( scene::Node& node ) const { + Node_getTraversable( m_parent )->erase( node ); +} }; -inline void DeleteSubgraph(scene::Node& subgraph) -{ - Node_getTraversable(subgraph)->traverse(delete_all(subgraph)); +inline void DeleteSubgraph( scene::Node& subgraph ){ + Node_getTraversable( subgraph )->traverse( delete_all( subgraph ) ); } class EntityUndefined { public: - STRING_CONSTANT(Name, "Entity"); +STRING_CONSTANT( Name, "Entity" ); }; -inline bool Node_isEntity(scene::Node& node) +inline bool Node_isEntity( scene::Node& node ){ + return NodeTypeCast::cast( node ) != 0; +} + +template +class EntityWalker : public scene::Graph::Walker { - return NodeTypeCast::cast(node) != 0; +const Functor& functor; +public: +EntityWalker( const Functor& functor ) : functor( functor ){ +} +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( Node_isEntity( path.top() ) ) { + functor( instance ); + return false; + } + return true; +} +}; + +template +inline const Functor& Scene_forEachEntity( const Functor& functor ){ + GlobalSceneGraph().traverse( EntityWalker( functor ) ); + return functor; } class BrushUndefined { public: - STRING_CONSTANT(Name, "Brush"); +STRING_CONSTANT( Name, "Brush" ); }; -inline bool Node_isBrush(scene::Node& node) -{ - return NodeTypeCast::cast(node) != 0; +inline bool Node_isBrush( scene::Node& node ){ + return NodeTypeCast::cast( node ) != 0; } class PatchUndefined { public: - STRING_CONSTANT(Name, "Patch"); +STRING_CONSTANT( Name, "Patch" ); }; -inline bool Node_isPatch(scene::Node& node) -{ - return NodeTypeCast::cast(node) != 0; +inline bool Node_isPatch( scene::Node& node ){ + return NodeTypeCast::cast( node ) != 0; } -inline bool Node_isPrimitive(scene::Node& node) -{ +inline bool Node_isPrimitive( scene::Node& node ){ #if 1 - return Node_isBrush(node) || Node_isPatch(node); + return Node_isBrush( node ) || Node_isPatch( node ); #else - return !node.isRoot(); + return !node.isRoot(); #endif } class ParentBrushes : public scene::Traversable::Walker { - scene::Node& m_parent; +scene::Node& m_parent; public: - ParentBrushes(scene::Node& parent) - : m_parent(parent) - { - } - bool pre(scene::Node& node) const - { - return false; - } - void post(scene::Node& node) const - { - if(Node_isPrimitive(node)) - { - Node_getTraversable(m_parent)->insert(node); - } - } +ParentBrushes( scene::Node& parent ) + : m_parent( parent ){ +} +bool pre( scene::Node& node ) const { + return false; +} +void post( scene::Node& node ) const { + if ( Node_isPrimitive( node ) ) { + Node_getTraversable( m_parent )->insert( node ); + } +} }; -inline void parentBrushes(scene::Node& subgraph, scene::Node& parent) -{ - Node_getTraversable(subgraph)->traverse(ParentBrushes(parent)); +inline void parentBrushes( scene::Node& subgraph, scene::Node& parent ){ + Node_getTraversable( subgraph )->traverse( ParentBrushes( parent ) ); } class HasBrushes : public scene::Traversable::Walker { - bool& m_hasBrushes; +bool& m_hasBrushes; public: - HasBrushes(bool& hasBrushes) - : m_hasBrushes(hasBrushes) - { - m_hasBrushes = true; - } - bool pre(scene::Node& node) const - { - if(!Node_isPrimitive(node)) - { - m_hasBrushes = false; - } - return false; - } +HasBrushes( bool& hasBrushes ) + : m_hasBrushes( hasBrushes ){ + m_hasBrushes = true; +} +bool pre( scene::Node& node ) const { + if ( !Node_isPrimitive( node ) ) { + m_hasBrushes = false; + } + return false; +} }; -inline bool node_is_group(scene::Node& node) -{ - scene::Traversable* traversable = Node_getTraversable(node); - if(traversable != 0) - { - bool hasBrushes = false; - traversable->traverse(HasBrushes(hasBrushes)); - return hasBrushes; - } - return false; +inline bool node_is_group( scene::Node& node ){ + scene::Traversable* traversable = Node_getTraversable( node ); + if ( traversable != 0 ) { + bool hasBrushes = false; + traversable->traverse( HasBrushes( hasBrushes ) ); + return hasBrushes; + } + return false; } typedef TypeCastTable InstanceTypeCastTable; @@ -458,565 +433,494 @@ typedef TypeCastTable InstanceTypeCastTable; template class InstanceType : public StaticTypeSystemInitialiser { - TypeId m_typeId; +TypeId m_typeId; public: - typedef typename Type::Name Name; - InstanceType() : m_typeId(INSTANCETYPEID_NONE) - { - StaticTypeSystemInitialiser::instance().addInitialiser(InitialiseCaller(*this)); - } - void initialise() - { - m_typeId = GlobalSceneGraph().getInstanceTypeId(Name()); - } - typedef MemberCaller, &InstanceType::initialise> InitialiseCaller; - TypeId getTypeId() - { -#if defined(_DEBUG) - ASSERT_MESSAGE(m_typeId != INSTANCETYPEID_NONE, "instance-type " << makeQuoted(Name()) << " used before being initialised"); +typedef typename Type::Name Name; +InstanceType() : m_typeId( INSTANCETYPEID_NONE ){ + StaticTypeSystemInitialiser::instance().addInitialiser( InitialiseCaller( *this ) ); +} +void initialise(){ + m_typeId = GlobalSceneGraph().getInstanceTypeId( Name() ); +} +typedef MemberCaller, void(), &InstanceType::initialise> InitialiseCaller; +TypeId getTypeId(){ +#if GDEF_DEBUG + ASSERT_MESSAGE( m_typeId != INSTANCETYPEID_NONE, "instance-type " << makeQuoted( Name() ) << " used before being initialised" ); #endif - return m_typeId; - } + return m_typeId; +} }; template class StaticInstanceType { public: - static const int SIZE = INSTANCETYPEID_MAX; - static TypeId getTypeId() - { - return Static< InstanceType >::instance().getTypeId(); - } +enum unnamed0 { SIZE = INSTANCETYPEID_MAX }; +static TypeId getTypeId(){ + return Static< InstanceType >::instance().getTypeId(); +} }; template class InstanceStaticCast : - public CastInstaller< - StaticInstanceType, - StaticCast - > + public CastInstaller< + StaticInstanceType, + StaticCast + > { }; template class InstanceContainedCast : - public CastInstaller< - StaticInstanceType, - ContainedCast - > + public CastInstaller< + StaticInstanceType, + ContainedCast + > { }; template class InstanceIdentityCast : - public CastInstaller< - StaticInstanceType, - IdentityCast - > + public CastInstaller< + StaticInstanceType, + IdentityCast + > { }; -inline Selectable* Instance_getSelectable(scene::Instance& instance); -inline const Selectable* Instance_getSelectable(const scene::Instance& instance); +inline Selectable* Instance_getSelectable( scene::Instance& instance ); +inline const Selectable* Instance_getSelectable( const scene::Instance& instance ); -inline Bounded* Instance_getBounded(scene::Instance& instance); -inline const Bounded* Instance_getBounded(const scene::Instance& instance); +inline Bounded* Instance_getBounded( scene::Instance& instance ); +inline const Bounded* Instance_getBounded( const scene::Instance& instance ); namespace scene { - class Instance - { - class AABBAccumulateWalker : public scene::Graph::Walker - { - AABB& m_aabb; - mutable std::size_t m_depth; - public: - AABBAccumulateWalker(AABB& aabb) : m_aabb(aabb), m_depth(0) - { - } - bool pre(const scene::Path& path, scene::Instance& instance) const - { - if(m_depth == 1) - { - aabb_extend_by_aabb_safe(m_aabb, instance.worldAABB()); - } - return ++m_depth != 2; - } - void post(const scene::Path& path, scene::Instance& instance) const - { - --m_depth; - } - }; - - - class TransformChangedWalker : public scene::Graph::Walker - { - public: - bool pre(const scene::Path& path, scene::Instance& instance) const - { - instance.transformChangedLocal(); - return true; - } - }; - - class ParentSelectedChangedWalker : public scene::Graph::Walker - { - public: - bool pre(const scene::Path& path, scene::Instance& instance) const - { - instance.parentSelectedChanged(); - return true; - } - }; - - class ChildSelectedWalker : public scene::Graph::Walker - { - bool& m_childSelected; - mutable std::size_t m_depth; - public: - ChildSelectedWalker(bool& childSelected) : m_childSelected(childSelected), m_depth(0) - { - m_childSelected = false; - } - bool pre(const scene::Path& path, scene::Instance& instance) const - { - if(m_depth == 1 && !m_childSelected) - { - m_childSelected = instance.isSelected() || instance.childSelected(); - } - return ++m_depth != 2; - } - void post(const scene::Path& path, scene::Instance& instance) const - { - --m_depth; - } - }; - - Path m_path; - Instance* m_parent; - void* m_instance; - InstanceTypeCastTable& m_casts; - - mutable Matrix4 m_local2world; - mutable AABB m_bounds; - mutable AABB m_childBounds; - mutable bool m_transformChanged; - mutable bool m_transformMutex; - mutable bool m_boundsChanged; - mutable bool m_boundsMutex; - mutable bool m_childBoundsChanged; - mutable bool m_childBoundsMutex; - mutable bool m_isSelected; - mutable bool m_isSelectedChanged; - mutable bool m_childSelected; - mutable bool m_childSelectedChanged; - mutable bool m_parentSelected; - mutable bool m_parentSelectedChanged; - Callback m_childSelectedChangedCallback; - Callback m_transformChangedCallback; - - - void evaluateTransform() const - { - if(m_transformChanged) - { - ASSERT_MESSAGE(!m_transformMutex, "re-entering transform evaluation"); - m_transformMutex = true; - - m_local2world = (m_parent != 0) ? m_parent->localToWorld() : g_matrix4_identity; - TransformNode* transformNode = Node_getTransformNode(m_path.top()); - if(transformNode != 0) - { - matrix4_multiply_by_matrix4(m_local2world, transformNode->localToParent()); - } - - m_transformMutex = false; - m_transformChanged = false; - } - } - void evaluateChildBounds() const - { - if(m_childBoundsChanged) - { - ASSERT_MESSAGE(!m_childBoundsMutex, "re-entering bounds evaluation"); - m_childBoundsMutex = true; - - m_childBounds = AABB(); - - GlobalSceneGraph().traverse_subgraph(AABBAccumulateWalker(m_childBounds), m_path); - - m_childBoundsMutex = false; - m_childBoundsChanged = false; - } - } - void evaluateBounds() const - { - if(m_boundsChanged) - { - ASSERT_MESSAGE(!m_boundsMutex, "re-entering bounds evaluation"); - m_boundsMutex = true; - - m_bounds = childBounds(); - - const Bounded* bounded = Instance_getBounded(*this); - if(bounded != 0) - { - aabb_extend_by_aabb_safe( - m_bounds, - aabb_for_oriented_aabb_safe(bounded->localAABB(), localToWorld()) - ); - } - - m_boundsMutex = false; - m_boundsChanged = false; - } - } - - Instance(const scene::Instance& other); - Instance& operator=(const scene::Instance& other); - public: - - Instance(const scene::Path& path, Instance* parent, void* instance, InstanceTypeCastTable& casts) : - m_path(path), - m_parent(parent), - m_instance(instance), - m_casts(casts), - m_local2world(g_matrix4_identity), - m_transformChanged(true), - m_transformMutex(false), - m_boundsChanged(true), - m_boundsMutex(false), - m_childBoundsChanged(true), - m_childBoundsMutex(false), - m_isSelectedChanged(true), - m_childSelectedChanged(true), - m_parentSelectedChanged(true) - { - ASSERT_MESSAGE((parent == 0) == (path.size() == 1), "instance has invalid parent"); - } - virtual ~Instance() - { - } - - const scene::Path& path() const - { - return m_path; - } - - void* cast(TypeId typeId) const - { - return m_casts.cast(typeId, m_instance); - } - - const Matrix4& localToWorld() const - { - evaluateTransform(); - return m_local2world; - } - void transformChangedLocal() - { - ASSERT_NOTNULL(m_parent); - m_transformChanged = true; - m_boundsChanged = true; - m_childBoundsChanged = true; - m_transformChangedCallback(); - } - void transformChanged() - { - GlobalSceneGraph().traverse_subgraph(TransformChangedWalker(), m_path); - boundsChanged(); - } - void setTransformChangedCallback(const Callback& callback) - { - m_transformChangedCallback = callback; - } - - - const AABB& worldAABB() const - { - evaluateBounds(); - return m_bounds; - } - const AABB& childBounds() const - { - evaluateChildBounds(); - return m_childBounds; - } - void boundsChanged() - { - m_boundsChanged = true; - m_childBoundsChanged = true; - if(m_parent != 0) - { - m_parent->boundsChanged(); - } - GlobalSceneGraph().boundsChanged(); - } - - void childSelectedChanged() - { - m_childSelectedChanged = true; - m_childSelectedChangedCallback(); - if(m_parent != 0) - { - m_parent->childSelectedChanged(); - } - } - bool childSelected() const - { - if(m_childSelectedChanged) - { - m_childSelectedChanged = false; - GlobalSceneGraph().traverse_subgraph(ChildSelectedWalker(m_childSelected), m_path); - } - return m_childSelected; - } - - void setChildSelectedChangedCallback(const Callback& callback) - { - m_childSelectedChangedCallback = callback; - } - void selectedChanged() - { - m_isSelectedChanged = true; - if(m_parent != 0) - { - m_parent->childSelectedChanged(); - } - GlobalSceneGraph().traverse_subgraph(ParentSelectedChangedWalker(), m_path); - } - bool isSelected() const - { - if(m_isSelectedChanged) - { - m_isSelectedChanged = false; - const Selectable* selectable = Instance_getSelectable(*this); - m_isSelected = selectable != 0 && selectable->isSelected(); - } - return m_isSelected; - } - - void parentSelectedChanged() - { - m_parentSelectedChanged = true; - } - bool parentSelected() const - { - if(m_parentSelectedChanged) - { - m_parentSelectedChanged = false; - m_parentSelected = m_parent != 0 && (m_parent->isSelected() || m_parent->parentSelected()); - } - return m_parentSelected; - } - }; +class Instance +{ +class AABBAccumulateWalker : public scene::Graph::Walker +{ +AABB& m_aabb; +mutable std::size_t m_depth; +public: +AABBAccumulateWalker( AABB& aabb ) : m_aabb( aabb ), m_depth( 0 ){ +} +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( m_depth == 1 ) { + aabb_extend_by_aabb_safe( m_aabb, instance.worldAABB() ); + } + return ++m_depth != 2; +} +void post( const scene::Path& path, scene::Instance& instance ) const { + --m_depth; +} +}; + + +class TransformChangedWalker : public scene::Graph::Walker +{ +public: +bool pre( const scene::Path& path, scene::Instance& instance ) const { + instance.transformChangedLocal(); + return true; +} +}; + +class ParentSelectedChangedWalker : public scene::Graph::Walker +{ +public: +bool pre( const scene::Path& path, scene::Instance& instance ) const { + instance.parentSelectedChanged(); + return true; +} +}; + +class ChildSelectedWalker : public scene::Graph::Walker +{ +bool& m_childSelected; +mutable std::size_t m_depth; +public: +ChildSelectedWalker( bool& childSelected ) : m_childSelected( childSelected ), m_depth( 0 ){ + m_childSelected = false; +} +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( m_depth == 1 && !m_childSelected ) { + m_childSelected = instance.isSelected() || instance.childSelected(); + } + return ++m_depth != 2; +} +void post( const scene::Path& path, scene::Instance& instance ) const { + --m_depth; +} +}; + +Path m_path; +Instance* m_parent; +void* m_instance; +InstanceTypeCastTable& m_casts; + +mutable Matrix4 m_local2world; +mutable AABB m_bounds; +mutable AABB m_childBounds; +mutable bool m_transformChanged; +mutable bool m_transformMutex; +mutable bool m_boundsChanged; +mutable bool m_boundsMutex; +mutable bool m_childBoundsChanged; +mutable bool m_childBoundsMutex; +mutable bool m_isSelected; +mutable bool m_isSelectedChanged; +mutable bool m_childSelected; +mutable bool m_childSelectedChanged; +mutable bool m_parentSelected; +mutable bool m_parentSelectedChanged; +Callback m_childSelectedChangedCallback; +Callback m_transformChangedCallback; + + +void evaluateTransform() const { + if ( m_transformChanged ) { + ASSERT_MESSAGE( !m_transformMutex, "re-entering transform evaluation" ); + m_transformMutex = true; + + m_local2world = ( m_parent != 0 ) ? m_parent->localToWorld() : g_matrix4_identity; + TransformNode* transformNode = Node_getTransformNode( m_path.top() ); + if ( transformNode != 0 ) { + matrix4_multiply_by_matrix4( m_local2world, transformNode->localToParent() ); + } + + m_transformMutex = false; + m_transformChanged = false; + } +} +void evaluateChildBounds() const { + if ( m_childBoundsChanged ) { + ASSERT_MESSAGE( !m_childBoundsMutex, "re-entering bounds evaluation" ); + m_childBoundsMutex = true; + + m_childBounds = AABB(); + + GlobalSceneGraph().traverse_subgraph( AABBAccumulateWalker( m_childBounds ), m_path ); + + m_childBoundsMutex = false; + m_childBoundsChanged = false; + } +} +void evaluateBounds() const { + if ( m_boundsChanged ) { + ASSERT_MESSAGE( !m_boundsMutex, "re-entering bounds evaluation" ); + m_boundsMutex = true; + + m_bounds = childBounds(); + + const Bounded* bounded = Instance_getBounded( *this ); + if ( bounded != 0 ) { + aabb_extend_by_aabb_safe( + m_bounds, + aabb_for_oriented_aabb_safe( bounded->localAABB(), localToWorld() ) + ); + } + + m_boundsMutex = false; + m_boundsChanged = false; + } +} + +Instance( const scene::Instance& other ); +Instance& operator=( const scene::Instance& other ); +public: + +Instance( const scene::Path& path, Instance* parent, void* instance, InstanceTypeCastTable& casts ) : + m_path( path ), + m_parent( parent ), + m_instance( instance ), + m_casts( casts ), + m_local2world( g_matrix4_identity ), + m_transformChanged( true ), + m_transformMutex( false ), + m_boundsChanged( true ), + m_boundsMutex( false ), + m_childBoundsChanged( true ), + m_childBoundsMutex( false ), + m_isSelectedChanged( true ), + m_childSelectedChanged( true ), + m_parentSelectedChanged( true ){ + ASSERT_MESSAGE( ( parent == 0 ) == ( path.size() == 1 ), "instance has invalid parent" ); +} +virtual ~Instance(){ +} + +const scene::Path& path() const { + return m_path; +} + +void* cast( TypeId typeId ) const { + return m_casts.cast( typeId, m_instance ); +} + +const Matrix4& localToWorld() const { + evaluateTransform(); + return m_local2world; +} +void transformChangedLocal(){ + ASSERT_NOTNULL( m_parent ); + m_transformChanged = true; + m_boundsChanged = true; + m_childBoundsChanged = true; + m_transformChangedCallback(); +} +void transformChanged(){ + GlobalSceneGraph().traverse_subgraph( TransformChangedWalker(), m_path ); + boundsChanged(); +} +void setTransformChangedCallback( const Callback& callback ){ + m_transformChangedCallback = callback; +} + + +const AABB& worldAABB() const { + evaluateBounds(); + return m_bounds; +} +const AABB& childBounds() const { + evaluateChildBounds(); + return m_childBounds; +} +void boundsChanged(){ + m_boundsChanged = true; + m_childBoundsChanged = true; + if ( m_parent != 0 ) { + m_parent->boundsChanged(); + } + GlobalSceneGraph().boundsChanged(); +} + +void childSelectedChanged(){ + m_childSelectedChanged = true; + m_childSelectedChangedCallback(); + if ( m_parent != 0 ) { + m_parent->childSelectedChanged(); + } +} +bool childSelected() const { + if ( m_childSelectedChanged ) { + m_childSelectedChanged = false; + GlobalSceneGraph().traverse_subgraph( ChildSelectedWalker( m_childSelected ), m_path ); + } + return m_childSelected; +} + +void setChildSelectedChangedCallback( const Callback& callback ){ + m_childSelectedChangedCallback = callback; +} +void selectedChanged(){ + m_isSelectedChanged = true; + if ( m_parent != 0 ) { + m_parent->childSelectedChanged(); + } + GlobalSceneGraph().traverse_subgraph( ParentSelectedChangedWalker(), m_path ); +} +bool isSelected() const { + if ( m_isSelectedChanged ) { + m_isSelectedChanged = false; + const Selectable* selectable = Instance_getSelectable( *this ); + m_isSelected = selectable != 0 && selectable->isSelected(); + } + return m_isSelected; +} + +void parentSelectedChanged(){ + m_parentSelectedChanged = true; +} +bool parentSelected() const { + if ( m_parentSelectedChanged ) { + m_parentSelectedChanged = false; + m_parentSelected = m_parent != 0 && ( m_parent->isSelected() || m_parent->parentSelected() ); + } + return m_parentSelected; +} +Instance* parent() const +{ + return m_parent; +} +}; } template class InstanceTypeCast { public: - static Type* cast(scene::Instance& instance) - { - return static_cast(instance.cast(StaticInstanceType::getTypeId())); - } - static const Type* cast(const scene::Instance& instance) - { - return static_cast(instance.cast(StaticInstanceType::getTypeId())); - } +static Type* cast( scene::Instance& instance ){ + return static_cast( instance.cast( StaticInstanceType::getTypeId() ) ); +} +static const Type* cast( const scene::Instance& instance ){ + return static_cast( instance.cast( StaticInstanceType::getTypeId() ) ); +} }; template class InstanceWalker : public scene::Graph::Walker { - const Functor& m_functor; +const Functor& m_functor; public: - InstanceWalker(const Functor& functor) : m_functor(functor) - { - } - bool pre(const scene::Path& path, scene::Instance& instance) const - { - m_functor(instance); - return true; - } +InstanceWalker( const Functor& functor ) : m_functor( functor ){ +} +bool pre( const scene::Path& path, scene::Instance& instance ) const { + //m_functor( instance ); + //return true; + if ( path.top().get().visible() ) { + m_functor( instance ); + } + else{ + return false; + } + return true; +} }; template class ChildInstanceWalker : public scene::Graph::Walker { - const Functor& m_functor; - mutable std::size_t m_depth; +const Functor& m_functor; +mutable std::size_t m_depth; public: - ChildInstanceWalker(const Functor& functor) : m_functor(functor), m_depth(0) - { - } - bool pre(const scene::Path& path, scene::Instance& instance) const - { - if(m_depth == 1) - { - m_functor(instance); - } - return ++m_depth != 2; - } - void post(const scene::Path& path, scene::Instance& instance) const - { - --m_depth; - } +ChildInstanceWalker( const Functor& functor ) : m_functor( functor ), m_depth( 0 ){ +} +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( m_depth == 1 ) { + m_functor( instance ); + } + return ++m_depth != 2; +} +void post( const scene::Path& path, scene::Instance& instance ) const { + --m_depth; +} }; template class InstanceApply : public Functor { public: - InstanceApply(const Functor& functor) : Functor(functor) - { - } - void operator()(scene::Instance& instance) const - { - Type* result = InstanceTypeCast::cast(instance); - if(result != 0) - { - Functor::operator()(*result); - } - } +InstanceApply( const Functor& functor ) : Functor( functor ){ +} +void operator()( scene::Instance& instance ) const { + Type* result = InstanceTypeCast::cast( instance ); + if ( result != 0 ) { + Functor::operator()( *result ); + } +} }; -inline Selectable* Instance_getSelectable(scene::Instance& instance) -{ - return InstanceTypeCast::cast(instance); +inline Selectable* Instance_getSelectable( scene::Instance& instance ){ + return InstanceTypeCast::cast( instance ); } -inline const Selectable* Instance_getSelectable(const scene::Instance& instance) -{ - return InstanceTypeCast::cast(instance); +inline const Selectable* Instance_getSelectable( const scene::Instance& instance ){ + return InstanceTypeCast::cast( instance ); } template -inline void Scene_forEachChildSelectable(const Functor& functor, const scene::Path& path) -{ - GlobalSceneGraph().traverse_subgraph(ChildInstanceWalker< InstanceApply >(functor), path); +inline void Scene_forEachChildSelectable( const Functor& functor, const scene::Path& path ){ + GlobalSceneGraph().traverse_subgraph( ChildInstanceWalker< InstanceApply >( functor ), path ); } class SelectableSetSelected { - bool m_selected; +bool m_selected; public: - SelectableSetSelected(bool selected) : m_selected(selected) - { - } - void operator()(Selectable& selectable) const - { - selectable.setSelected(m_selected); - } +SelectableSetSelected( bool selected ) : m_selected( selected ){ +} +void operator()( Selectable& selectable ) const { + selectable.setSelected( m_selected ); +} }; -inline Bounded* Instance_getBounded(scene::Instance& instance) -{ - return InstanceTypeCast::cast(instance); +inline Bounded* Instance_getBounded( scene::Instance& instance ){ + return InstanceTypeCast::cast( instance ); } -inline const Bounded* Instance_getBounded(const scene::Instance& instance) -{ - return InstanceTypeCast::cast(instance); +inline const Bounded* Instance_getBounded( const scene::Instance& instance ){ + return InstanceTypeCast::cast( instance ); } -inline Transformable* Instance_getTransformable(scene::Instance& instance) -{ - return InstanceTypeCast::cast(instance); +inline Transformable* Instance_getTransformable( scene::Instance& instance ){ + return InstanceTypeCast::cast( instance ); } -inline const Transformable* Instance_getTransformable(const scene::Instance& instance) -{ - return InstanceTypeCast::cast(instance); +inline const Transformable* Instance_getTransformable( const scene::Instance& instance ){ + return InstanceTypeCast::cast( instance ); } -inline ComponentSelectionTestable* Instance_getComponentSelectionTestable(scene::Instance& instance) -{ - return InstanceTypeCast::cast(instance); +inline ComponentSelectionTestable* Instance_getComponentSelectionTestable( scene::Instance& instance ){ + return InstanceTypeCast::cast( instance ); } -inline ComponentEditable* Instance_getComponentEditable(scene::Instance& instance) -{ - return InstanceTypeCast::cast(instance); +inline ComponentEditable* Instance_getComponentEditable( scene::Instance& instance ){ + return InstanceTypeCast::cast( instance ); } -inline ComponentSnappable* Instance_getComponentSnappable(scene::Instance& instance) -{ - return InstanceTypeCast::cast(instance); +inline ComponentSnappable* Instance_getComponentSnappable( scene::Instance& instance ){ + return InstanceTypeCast::cast( instance ); } -inline void Instance_setSelected(scene::Instance& instance, bool selected) -{ - Selectable* selectable = Instance_getSelectable(instance); - if(selectable != 0) - { - selectable->setSelected(selected); - } +inline void Instance_setSelected( scene::Instance& instance, bool selected ){ + Selectable* selectable = Instance_getSelectable( instance ); + if ( selectable != 0 ) { + selectable->setSelected( selected ); + } } -inline bool Instance_isSelected(scene::Instance& instance) -{ - Selectable* selectable = Instance_getSelectable(instance); - if(selectable != 0) - { - return selectable->isSelected(); - } - return false; +inline bool Instance_isSelected( scene::Instance& instance ){ + Selectable* selectable = Instance_getSelectable( instance ); + if ( selectable != 0 ) { + return selectable->isSelected(); + } + return false; } -inline scene::Instance& findInstance(const scene::Path& path) -{ - scene::Instance* instance = GlobalSceneGraph().find(path); - ASSERT_MESSAGE(instance != 0, "findInstance: path not found in scene-graph"); - return *instance; +inline scene::Instance& findInstance( const scene::Path& path ){ + scene::Instance* instance = GlobalSceneGraph().find( path ); + ASSERT_MESSAGE( instance != 0, "findInstance: path not found in scene-graph" ); + return *instance; } -inline void selectPath(const scene::Path& path, bool selected) -{ - Instance_setSelected(findInstance(path), selected); +inline void selectPath( const scene::Path& path, bool selected ){ + Instance_setSelected( findInstance( path ), selected ); } class SelectChildren : public scene::Traversable::Walker { - mutable scene::Path m_path; +mutable scene::Path m_path; public: - SelectChildren(const scene::Path& root) - : m_path(root) - { - } - bool pre(scene::Node& node) const - { - m_path.push(makeReference(node)); - selectPath(m_path, true); - return false; - } - void post(scene::Node& node) const - { - m_path.pop(); - } +SelectChildren( const scene::Path& root ) + : m_path( root ){ +} +bool pre( scene::Node& node ) const { + m_path.push( makeReference( node ) ); + selectPath( m_path, true ); + return false; +} +void post( scene::Node& node ) const { + m_path.pop(); +} }; -inline void Entity_setSelected(scene::Instance& entity, bool selected) -{ - scene::Node& node = entity.path().top(); - if(node_is_group(node)) - { - Node_getTraversable(node)->traverse(SelectChildren(entity.path())); - } - else - { - Instance_setSelected(entity, selected); - } -} - -inline bool Entity_isSelected(scene::Instance& entity) -{ - if(node_is_group(entity.path().top())) - { - return entity.childSelected(); - } - return Instance_isSelected(entity); +inline void Entity_setSelected( scene::Instance& entity, bool selected ){ + scene::Node& node = entity.path().top(); + if ( node_is_group( node ) ) { + Node_getTraversable( node )->traverse( SelectChildren( entity.path() ) ); + } + else + { + Instance_setSelected( entity, selected ); + } +} + +inline bool Entity_isSelected( scene::Instance& entity ){ + if ( node_is_group( entity.path().top() ) ) { + return entity.childSelected(); + } + return Instance_isSelected( entity ); } @@ -1024,45 +928,40 @@ inline bool Entity_isSelected(scene::Instance& entity) class InstanceCounter { public: - unsigned int m_count; - InstanceCounter() : m_count(0) - { - } +unsigned int m_count; +InstanceCounter() : m_count( 0 ){ +} }; class Counter { public: - virtual void increment() = 0; - virtual void decrement() = 0; +virtual void increment() = 0; +virtual void decrement() = 0; }; #include "generic/callback.h" class SimpleCounter : public Counter { - Callback m_countChanged; - std::size_t m_count; +Callback m_countChanged; +std::size_t m_count; public: - void setCountChangedCallback(const Callback& countChanged) - { - m_countChanged = countChanged; - } - void increment() - { - ++m_count; - m_countChanged(); - } - void decrement() - { - --m_count; - m_countChanged(); - } - std::size_t get() const - { - return m_count; - } +void setCountChangedCallback( const Callback& countChanged ){ + m_countChanged = countChanged; +} +void increment(){ + ++m_count; + m_countChanged(); +} +void decrement(){ + --m_count; + m_countChanged(); +} +std::size_t get() const { + return m_count; +} };