- 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<void()> m_childSelectedChangedCallback;
+Callback<void()> 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<void()>& 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<void()>& 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;
+}
+};