From 2aca6c3748a55a07b3fb937aae35117e7207ddcf Mon Sep 17 00:00:00 2001 From: Paul Wisbey Date: Mon, 15 Sep 2014 11:36:03 +0100 Subject: [PATCH] Simplified the Constraint removal logic [problem] Memory corruption caused by unsafe calls to SetWeight [cause] The root cause is the Constraint using the ProxyObject::Observer interface for two different purposes; firstly to find out about parent on/off stage behavior, and also to track the objects providing property inputs. [solution] Reduced the complexity of the constraint logic; removed observer usage for the parent object, moved code from templates to common base class. Deprecated the (unused) SetRemoveTime API bloat. Change-Id: I4d789143f4dc36767cbc91adf63d47f488c37e1b --- automated-tests/src/dali-internal/CMakeLists.txt | 1 + .../dali-internal/utc-Dali-Internal-Constraint.cpp | 98 +++++++ automated-tests/src/dali/utc-Dali-Constraint.cpp | 205 +------------- .../event/animation/active-constraint-base.cpp | 226 ++++++++++------ .../event/animation/active-constraint-base.h | 87 +++--- .../event/animation/active-constraint-impl.h | 293 +-------------------- dali/internal/event/animation/constraint-impl.cpp | 10 - dali/internal/event/animation/constraint-impl.h | 10 - dali/internal/event/common/proxy-object.cpp | 89 +++---- dali/internal/event/common/proxy-object.h | 6 - .../animation/scene-graph-constraint-base.cpp | 36 ++- .../update/animation/scene-graph-constraint-base.h | 17 ++ dali/public-api/animation/constraint.cpp | 5 +- dali/public-api/animation/constraint.h | 9 +- 14 files changed, 392 insertions(+), 700 deletions(-) create mode 100644 automated-tests/src/dali-internal/utc-Dali-Internal-Constraint.cpp diff --git a/automated-tests/src/dali-internal/CMakeLists.txt b/automated-tests/src/dali-internal/CMakeLists.txt index 08fbd2c..39598b8 100644 --- a/automated-tests/src/dali-internal/CMakeLists.txt +++ b/automated-tests/src/dali-internal/CMakeLists.txt @@ -15,6 +15,7 @@ SET(TC_SOURCES utc-Dali-Internal-ResourceClient.cpp utc-Dali-Internal-Image-Culling.cpp utc-Dali-Internal-Text-Culling.cpp + utc-Dali-Internal-Constraint.cpp ) LIST(APPEND TC_SOURCES diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-Constraint.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-Constraint.cpp new file mode 100644 index 0000000..983aec3 --- /dev/null +++ b/automated-tests/src/dali-internal/utc-Dali-Internal-Constraint.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include +#include + +using namespace Dali; + +using Dali::Internal::SceneGraph::ConstraintBase; + +int UtcDaliConstraintNewInput1OffStage(void) +{ + /** + * Test that the Constraint is correctly added/removed when an object + * providing the input property is added/removed from the stage + */ + TestApplication application; + + Actor parent = Actor::New(); + Stage::GetCurrent().Add( parent ); + + Actor actor = Actor::New(); + parent.Add( actor ); + + Actor sibling1 = Actor::New(); + sibling1.SetPosition( Vector3(1.0f, 2.0f, 3.0f) ); + parent.Add( sibling1 ); + + Vector3 startValue( 0.0f, 0.0f, 0.0f ); + DALI_TEST_EQUALS( 0u, ConstraintBase::GetCurrentInstanceCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( 0u, ConstraintBase::GetTotalInstanceCount(), TEST_LOCATION ); + + /** + * Test that the Constraint is correctly applied on a clean Node + */ + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty( Actor::POSITION ), startValue, TEST_LOCATION ); + + // Apply constraint with a parent input property + + Constraint constraint = Constraint::New( Actor::POSITION, + Source( sibling1, Actor::POSITION ), + EqualToConstraint() ); + + actor.ApplyConstraint( constraint ); + DALI_TEST_EQUALS( actor.GetProperty( Actor::POSITION ), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty( Actor::POSITION ), Vector3(1.0f, 2.0f, 3.0f)/*from sibling1*/, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, ConstraintBase::GetCurrentInstanceCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, ConstraintBase::GetTotalInstanceCount(), TEST_LOCATION ); + + // Remove sibling1 providing the input property + + parent.Remove( sibling1 ); + actor.SetPosition( Vector3(2.0f, 2.0f, 2.0f) ); // This should be effective + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty( Actor::POSITION ), Vector3(2.0f, 2.0f, 2.0f)/*from SetPosition*/, TEST_LOCATION ); + DALI_TEST_EQUALS( 0u/*should have been removed*/, ConstraintBase::GetCurrentInstanceCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, ConstraintBase::GetTotalInstanceCount(), TEST_LOCATION ); + + // Add sibling1 back again (re-enables constraint) + + parent.Add( sibling1 ); + actor.SetPosition( Vector3(3.0f, 3.0f, 3.0f) ); // This should NOT be effective + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty( Actor::POSITION ), Vector3(1.0f, 2.0f, 3.0f)/*from sibling1*/, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, ConstraintBase::GetCurrentInstanceCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( 2u/*recreated once*/, ConstraintBase::GetTotalInstanceCount(), TEST_LOCATION ); + + END_TEST; +} + diff --git a/automated-tests/src/dali/utc-Dali-Constraint.cpp b/automated-tests/src/dali/utc-Dali-Constraint.cpp index 56d773e..a1d0a37 100644 --- a/automated-tests/src/dali/utc-Dali-Constraint.cpp +++ b/automated-tests/src/dali/utc-Dali-Constraint.cpp @@ -2412,99 +2412,6 @@ int UtcDaliConstraintGetApplyTime(void) END_TEST; } -int UtcDaliConstraintSetRemoveTime(void) -{ - TestApplication application; - - Vector3 sourcePosition(0.0f, 0.0f, 0.0f); - Vector3 targetPosition(100.0f, 100.0f, 100.0f); - - // Build constraint - - Constraint constraint = Constraint::New( Actor::POSITION, TestPositionConstraint(targetPosition) ); - DALI_TEST_EQUALS(constraint.GetRemoveTime(), TimePeriod(0.0f), TEST_LOCATION); - - float removeSeconds(8.0f); - constraint.SetRemoveTime(removeSeconds); - DALI_TEST_EQUALS(constraint.GetRemoveTime(), TimePeriod(removeSeconds), TEST_LOCATION); - - // Apply to an actor - - Actor actor = Actor::New(); - Stage::GetCurrent().Add(actor); - - actor.ApplyConstraint( constraint ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), sourcePosition, TEST_LOCATION ); - - application.SendNotification(); - application.Render(100u/*0.1 seconds*/); - - // Constraint should be fully applied - DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); - - // Check that nothing has changed after a couple of buffer swaps - application.Render(0); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); - application.Render(0); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); - - // Remove from the actor, and set to alternative position - - actor.RemoveConstraints(); - - Vector3 thirdPosition(200.0f, 200.0f, 200.0f); - actor.SetPosition(thirdPosition); // Go back to 3rd position - - application.SendNotification(); - application.Render(static_cast(removeSeconds*200.0f)/* 20% removal progress */); - - // Constraint shouldn't be fully removed yet - Vector3 twentyPercentBack( targetPosition + (thirdPosition - targetPosition)*0.2f ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), twentyPercentBack, TEST_LOCATION ); - - application.Render(static_cast(removeSeconds*200.0f)/* 40% removal progress */); - - // Constraint shouldn't be fully removed yet - Vector3 fourtyPercentBack( targetPosition + (thirdPosition - targetPosition)*0.4f ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), fourtyPercentBack, TEST_LOCATION ); - - application.Render(static_cast(removeSeconds*200.0f)/* 60% removal progress */); - - // Constraint shouldn't be fully removed yet - Vector3 sixtyPercentBack( targetPosition + (thirdPosition - targetPosition)*0.6f ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), sixtyPercentBack, TEST_LOCATION ); - - application.Render(static_cast(removeSeconds*200.0f)/* 80% removal progress */); - - // Constraint shouldn't be fully removed yet - Vector3 eightyPercentBack( targetPosition + (thirdPosition - targetPosition)*0.8f ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), eightyPercentBack, TEST_LOCATION ); - - // Constraint should be fully removed - application.Render(static_cast(removeSeconds*200.0f)/* 100% removal progress */); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), thirdPosition, TEST_LOCATION ); - - // Constraint should still be fully applied - application.Render(static_cast(removeSeconds*200.0f)/* Still 100% removal progress */); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), thirdPosition, TEST_LOCATION ); - - // Check that nothing has changed after a couple of buffer swaps - application.Render(0); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), thirdPosition, TEST_LOCATION ); - application.Render(0); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), thirdPosition, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliConstraintGetRemoveTime(void) -{ - TestApplication application; - - Constraint constraint = Constraint::New( Actor::COLOR, TestConstraint() ); - DALI_TEST_EQUALS(constraint.GetRemoveTime(), TimePeriod(0.0f), TEST_LOCATION); - END_TEST; -} - int UtcDaliConstraintSetAlphaFunction(void) { TestApplication application; @@ -2634,10 +2541,6 @@ int UtcDaliConstraintSetRemoveAction(void) constraint.SetRemoveAction(Constraint::Discard); DALI_TEST_EQUALS((unsigned int)constraint.GetRemoveAction(), (unsigned int)Constraint::Discard, TEST_LOCATION); - float removeSeconds(8.0f); - constraint.SetRemoveTime(removeSeconds); - DALI_TEST_EQUALS(constraint.GetRemoveTime(), TimePeriod(removeSeconds), TEST_LOCATION); - // Apply to an actor Actor actor = Actor::New(); @@ -2659,40 +2562,16 @@ int UtcDaliConstraintSetRemoveAction(void) DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); // Remove from the actor - actor.RemoveConstraints(); // should go back to source position application.SendNotification(); - application.Render(static_cast(removeSeconds*200.0f)/* 20% removal progress */); - - // Constraint shouldn't be fully removed yet - Vector3 twentyPercentBack( targetPosition * 0.8f ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), twentyPercentBack, TEST_LOCATION ); - - application.Render(static_cast(removeSeconds*200.0f)/* 40% removal progress */); - - // Constraint shouldn't be fully removed yet - Vector3 fourtyPercentBack( targetPosition * 0.6f ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), fourtyPercentBack, TEST_LOCATION ); - - application.Render(static_cast(removeSeconds*200.0f)/* 60% removal progress */); - - // Constraint shouldn't be fully removed yet - Vector3 sixtyPercentBack( targetPosition * 0.4f ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), sixtyPercentBack, TEST_LOCATION ); - - application.Render(static_cast(removeSeconds*200.0f)/* 80% removal progress */); - - // Constraint shouldn't be fully removed yet - Vector3 eightyPercentBack( targetPosition * 0.2f ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), eightyPercentBack, TEST_LOCATION ); + application.Render(static_cast(1000.0f)); // Constraint should be fully removed - application.Render(static_cast(removeSeconds*200.0f)/* 100% removal progress */); DALI_TEST_EQUALS( actor.GetCurrentPosition(), sourcePosition, TEST_LOCATION ); - // Constraint should still be fully applied - application.Render(static_cast(removeSeconds*200.0f)/* Still 100% removal progress */); + // Constraint should still be fully removed + application.Render(static_cast(1000.0f)/* Still 100% removal progress */); DALI_TEST_EQUALS( actor.GetCurrentPosition(), sourcePosition, TEST_LOCATION ); // Check that nothing has changed after a couple of buffer swaps @@ -2719,83 +2598,6 @@ int UtcDaliConstraintGetRemoveAction(void) } /** - * Test a constraint with non-zero apply-time and remove-time, where the constraint is removed during the apply-time - */ -int UtcDaliConstraintRemoveDuringApply(void) -{ - TestApplication application; - - Vector3 sourcePosition(0.0f, 0.0f, 0.0f); - Vector3 targetPosition(100.0f, 100.0f, 100.0f); - Vector3 halfwayPosition(targetPosition * 0.5f); - - // Build constraint - - Constraint constraint = Constraint::New( Actor::POSITION, TestPositionConstraint(targetPosition) ); - DALI_TEST_EQUALS((unsigned int)constraint.GetRemoveAction(), (unsigned int)Constraint::Bake, TEST_LOCATION); - - float applySeconds(4.0f); - constraint.SetApplyTime(applySeconds); - DALI_TEST_EQUALS(constraint.GetApplyTime(), TimePeriod(applySeconds), TEST_LOCATION); - - float removeSeconds(8.0f); - constraint.SetRemoveTime(removeSeconds); - DALI_TEST_EQUALS(constraint.GetRemoveTime(), TimePeriod(removeSeconds), TEST_LOCATION); - - // Apply to an actor - - Actor actor = Actor::New(); - Stage::GetCurrent().Add(actor); - - actor.ApplyConstraint( constraint ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), sourcePosition, TEST_LOCATION ); - - application.SendNotification(); - application.Render(static_cast(applySeconds*250.0f)/* 25% progress */); - - // Constraint shouldn't be fully applied yet - Vector3 twentyFivePercent( targetPosition * 0.25f ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), twentyFivePercent, TEST_LOCATION ); - - application.Render(static_cast(applySeconds*250.0f)/* 50% progress */); - - // Constraint shouldn't be fully applied yet - Vector3 fiftyPercent( targetPosition * 0.5f ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercent, TEST_LOCATION ); - - // Remove from the actor - - actor.RemoveConstraints(); // should go back to source position - - application.SendNotification(); - application.Render(static_cast(removeSeconds*100.0f)/* 50% - 5% = 45% progress */); - - // Constraint shouldn't be fully removed yet - Vector3 fourtyFivePercent( targetPosition * 0.45f ); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), fourtyFivePercent, TEST_LOCATION ); - - application.Render(static_cast(removeSeconds*400.0f)/* 50% - 25% = 25% progress */); - - // Constraint shouldn't be fully removed yet - DALI_TEST_EQUALS( actor.GetCurrentPosition(), twentyFivePercent, TEST_LOCATION ); - - // Constraint should be fully removed - application.Render(static_cast(removeSeconds*500.0f)/* 0% progress */); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), sourcePosition, TEST_LOCATION ); - - // Constraint should still be fully applied - application.Render(static_cast(removeSeconds*200.0f)/* Still 0% progress */); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), sourcePosition, TEST_LOCATION ); - - // Check that nothing has changed after a couple of buffer swaps - application.Render(0); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), sourcePosition, TEST_LOCATION ); - application.Render(0); - DALI_TEST_EQUALS( actor.GetCurrentPosition(), sourcePosition, TEST_LOCATION ); - END_TEST; -} - -/** * Test a constraint with non-zero apply-time & zero (immediate) remove-time, where the constraint is removed during the apply-time */ int UtcDaliConstraintImmediateRemoveDuringApply(void) @@ -2813,7 +2615,6 @@ int UtcDaliConstraintImmediateRemoveDuringApply(void) float applySeconds(4.0f); constraint.SetApplyTime(applySeconds); DALI_TEST_EQUALS(constraint.GetApplyTime(), TimePeriod(applySeconds), TEST_LOCATION); - DALI_TEST_EQUALS(constraint.GetRemoveTime(), TimePeriod(0.0f), TEST_LOCATION); // Apply to an actor diff --git a/dali/internal/event/animation/active-constraint-base.cpp b/dali/internal/event/animation/active-constraint-base.cpp index 047aa0f..9accd09 100644 --- a/dali/internal/event/animation/active-constraint-base.cpp +++ b/dali/internal/event/animation/active-constraint-base.cpp @@ -74,35 +74,50 @@ const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] = } // unnamed namespace -ActiveConstraintBase::ActiveConstraintBase( EventToUpdate& eventToUpdate, Property::Index targetPropertyIndex ) +ActiveConstraintBase::ActiveConstraintBase( EventToUpdate& eventToUpdate, Property::Index targetPropertyIndex, SourceContainer& sources, unsigned int sourceCount ) : mEventToUpdate( eventToUpdate ), mTargetPropertyIndex( targetPropertyIndex ), + mSources( sources ), + mSourceCount( sourceCount ), mTargetProxy( NULL ), + mObservedProxies(), mSceneGraphConstraint( NULL ), mCustomWeight( NULL ), mOffstageWeight( Dali::ActiveConstraint::DEFAULT_WEIGHT ), - mRemoveTime( 0.0f ), mAlphaFunction( Dali::Constraint::DEFAULT_ALPHA_FUNCTION ), mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ), mTag(0), - mApplyAnimation(), - mRemoveAnimation() + mApplyAnimation() { + // Skip init when any of the proxy objects have been destroyed + if ( mSources.size() != mSourceCount ) + { + // Discard all proxy pointers + mTargetProxy = NULL; + mSources.clear(); + } + + // Observe the objects providing properties + for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter ) + { + if ( OBJECT_PROPERTY == iter->sourceType ) + { + DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" ); + + ObserveProxy( *(iter->object) ); + } + } } ActiveConstraintBase::~ActiveConstraintBase() { - // Disconnect from internal animation signals + StopObservation(); + // Disconnect from internal animation signals if ( mApplyAnimation ) { GetImplementation(mApplyAnimation).SetFinishedCallback( NULL, NULL ); } - - if( mRemoveAnimation ) - { - GetImplementation(mRemoveAnimation).SetFinishedCallback( NULL, NULL ); - } } void ActiveConstraintBase::SetCustomWeightObject( ProxyObject& weightObject, Property::Index weightIndex ) @@ -114,14 +129,21 @@ void ActiveConstraintBase::SetCustomWeightObject( ProxyObject& weightObject, Pro { mCustomWeight = sceneProperty; - OnCustomWeightSet( weightObject ); + ObserveProxy( weightObject ); } } void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime ) { - // Notify derived classes - OnFirstApply( parent ); + DALI_ASSERT_ALWAYS( NULL == mTargetProxy && "Parent of ActiveConstraint already set" ); + + // No need to do anything, if the source objects are gone + if( mSources.size() == mSourceCount ) + { + mTargetProxy = &parent; + + ConnectConstraint(); + } if ( applyTime.durationSeconds > 0.0f ) { @@ -141,45 +163,59 @@ void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime } } -void ActiveConstraintBase::BeginRemove() +void ActiveConstraintBase::OnParentDestroyed() { - // Notify derived classes - OnBeginRemove(); + // Stop observing the remaining proxies + StopObservation(); - // Remove gradually by animating weight down to zero - if ( mRemoveTime.durationSeconds > 0.0f ) - { - // Stop baking behaviour from interfering with remove animation - if ( mSceneGraphConstraint ) - { - // Immediately remove from scene-graph - SetRemoveActionMessage( mEventToUpdate, *mSceneGraphConstraint, Dali::Constraint::Discard ); - } - - // Interrupt ongoing apply-animations - if ( mApplyAnimation ) - { - mApplyAnimation.Stop(); - } - - // Reduce the weight to zero - mRemoveAnimation = Dali::Animation::New( mRemoveTime.delaySeconds + mRemoveTime.durationSeconds ); - Dali::ActiveConstraint self( this ); - mRemoveAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::WEIGHT ), 0.0f, mAlphaFunction, mRemoveTime ); - mRemoveAnimation.Play(); + // Discard all proxy pointers + mTargetProxy = NULL; + mSources.clear(); +} - // Finish removal when animation ends - GetImplementation(mRemoveAnimation).SetFinishedCallback( &ActiveConstraintBase::OnRemoveFinished, this ); +void ActiveConstraintBase::OnParentSceneObjectAdded() +{ + if ( NULL == mSceneGraphConstraint && + mTargetProxy ) + { + ConnectConstraint(); } - else +} + +void ActiveConstraintBase::OnParentSceneObjectRemoved() +{ + if ( mSceneGraphConstraint ) { - OnRemoveFinished( this ); + // Notify base class that the scene-graph constraint is being removed + OnSceneObjectRemove(); + + // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer + mSceneGraphConstraint = NULL; } } -bool ActiveConstraintBase::IsRemoving() +void ActiveConstraintBase::BeginRemove() { - return mRemoveAnimation; + // Stop observing the remaining proxies + StopObservation(); + + // Discard all proxy pointers + mSources.clear(); + + const SceneGraph::PropertyOwner* propertyOwner = mTargetProxy ? mTargetProxy->GetSceneObject() : NULL; + + if ( propertyOwner && + mSceneGraphConstraint ) + { + // Notify base class that the scene-graph constraint is being removed + OnSceneObjectRemove(); + + // Remove from scene-graph + RemoveConstraintMessage( mEventToUpdate, *propertyOwner, *(mSceneGraphConstraint) ); + + // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer + mSceneGraphConstraint = NULL; + } } ProxyObject* ActiveConstraintBase::GetParent() @@ -249,16 +285,6 @@ bool ActiveConstraintBase::DoConnectSignal( BaseObject* object, ConnectionTracke return connected; } -void ActiveConstraintBase::SetRemoveTime( TimePeriod removeTime ) -{ - mRemoveTime = removeTime; -} - -TimePeriod ActiveConstraintBase::GetRemoveTime() const -{ - return mRemoveTime; -} - void ActiveConstraintBase::SetAlphaFunction( AlphaFunction alphaFunc ) { mAlphaFunction = alphaFunc; @@ -289,7 +315,6 @@ unsigned int ActiveConstraintBase::GetTag() const return mTag; } - bool ActiveConstraintBase::IsSceneObjectRemovable() const { return true; // The constraint removed when target SceneGraph::PropertyOwner is destroyed @@ -446,6 +471,76 @@ const PropertyInputImpl* ActiveConstraintBase::GetSceneObjectInputProperty( Prop return &mSceneGraphConstraint->mWeight; } +void ActiveConstraintBase::SceneObjectAdded( ProxyObject& proxy ) +{ + // Should not be getting callbacks when mSources has been cleared + DALI_ASSERT_DEBUG( mSources.size() == mSourceCount ); + + if ( NULL == mSceneGraphConstraint && + mTargetProxy ) + { + ConnectConstraint(); + } +} + +void ActiveConstraintBase::SceneObjectRemoved( ProxyObject& proxy ) +{ + // Notify base class that the scene-graph constraint is being removed + OnSceneObjectRemove(); + + if ( mSceneGraphConstraint ) + { + // Preserve the previous weight + mOffstageWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() ); + + const SceneGraph::PropertyOwner* propertyOwner = mTargetProxy ? mTargetProxy->GetSceneObject() : NULL; + + if( propertyOwner ) + { + // Remove from scene-graph + RemoveConstraintMessage( mEventToUpdate, *propertyOwner, *(mSceneGraphConstraint) ); + } + + // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer + mSceneGraphConstraint = NULL; + } +} + +void ActiveConstraintBase::ProxyDestroyed( ProxyObject& proxy ) +{ + // Remove proxy pointer from observation set + ProxyObjectIter iter = mObservedProxies.find( &proxy ); + DALI_ASSERT_DEBUG( mObservedProxies.end() != iter ); + mObservedProxies.erase( iter ); + + // Stop observing the remaining proxies + StopObservation(); + + // Discard all proxy & scene-graph pointers + mSceneGraphConstraint = NULL; + mTargetProxy = NULL; + mSources.clear(); +} + +void ActiveConstraintBase::ObserveProxy( ProxyObject& proxy ) +{ + if ( mObservedProxies.end() == mObservedProxies.find(&proxy) ) + { + proxy.AddObserver( *this ); + mObservedProxies.insert( &proxy ); + } +} + +void ActiveConstraintBase::StopObservation() +{ + for( ProxyObjectIter iter = mObservedProxies.begin(); mObservedProxies.end() != iter; ++iter ) + { + (*iter)->RemoveObserver( *this ); + } + + mObservedProxies.clear(); +} + void ActiveConstraintBase::FirstApplyFinished( Object* object ) { ActiveConstraintBase& self = dynamic_cast( *object ); @@ -469,29 +564,6 @@ void ActiveConstraintBase::FirstApplyFinished( Object* object ) // WARNING - this constraint may now have been deleted; don't do anything else here } -void ActiveConstraintBase::OnRemoveFinished( Object* object ) -{ - ActiveConstraintBase& self = dynamic_cast( *object ); - - const SceneGraph::PropertyOwner* propertyOwner = self.mTargetProxy ? self.mTargetProxy->GetSceneObject() : NULL; - - if ( propertyOwner && - self.mSceneGraphConstraint ) - { - // Notify base class that the scene-graph constraint is being removed - self.OnSceneObjectRemove(); - - // Remove from scene-graph - RemoveConstraintMessage( self.mEventToUpdate, *propertyOwner, *(self.mSceneGraphConstraint) ); - - // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer - self.mSceneGraphConstraint = NULL; - } - - // The animation is no longer needed - self.mRemoveAnimation.Reset(); -} - } // namespace Internal } // namespace Dali diff --git a/dali/internal/event/animation/active-constraint-base.h b/dali/internal/event/animation/active-constraint-base.h index 2ebc1b7..d17912e 100644 --- a/dali/internal/event/animation/active-constraint-base.h +++ b/dali/internal/event/animation/active-constraint-base.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include namespace Dali { @@ -35,7 +37,8 @@ namespace Internal { class EventToUpdate; -class ProxyObject; +typedef std::set ProxyObjectContainer; +typedef ProxyObjectContainer::iterator ProxyObjectIter; namespace SceneGraph { @@ -48,7 +51,7 @@ class AnimatableProperty; /** * An abstract base class for active constraints. */ -class ActiveConstraintBase : public ProxyObject +class ActiveConstraintBase : public ProxyObject, public ProxyObject::Observer { public: @@ -59,8 +62,10 @@ public: * Constructor. * @param[in] messageController Used to send messages to the update-thread. * @param[in] targetPropertyIndex The index of the property being constrained. + * @param[in] sources The sources of the input properties. + * @param[in] sourceCount The original number of sources; this may not match sources.size() if objects have died. */ - ActiveConstraintBase( EventToUpdate& messageController, Property::Index targetPropertyIndex ); + ActiveConstraintBase( EventToUpdate& messageController, Property::Index targetPropertyIndex, SourceContainer& sources, unsigned int sourceCount ); /** * Virtual destructor. @@ -94,11 +99,19 @@ public: void BeginRemove(); /** - * Query whether the constraint is being removed. - * This is only possible if mRemoveTime.durationSeconds is non-zero. - * @return True if constraint is being removed. + * Called when the target object is destroyed. */ - bool IsRemoving(); + void OnParentDestroyed(); + + /** + * Called when the target object is connected to the scene-graph + */ + void OnParentSceneObjectAdded(); + + /** + * Called when the target object is disconnected from the scene-graph + */ + void OnParentSceneObjectRemoved(); /** * Retrieve the parent of the active-constraint. @@ -137,16 +150,6 @@ public: ActiveConstraintSignalV2& AppliedSignal(); /** - * @copydoc Dali::Constraint::SetRemoveTime() - */ - void SetRemoveTime( TimePeriod timePeriod ); - - /** - * @copydoc Dali::Constraint::GetRemoveTime() - */ - TimePeriod GetRemoveTime() const; - - /** * @copydoc Dali::Constraint::SetAlphaFunction() */ void SetAlphaFunction(AlphaFunction func); @@ -176,8 +179,6 @@ public: */ unsigned int GetTag() const; - - /** * Connects a callback function with the object's signals. * @param[in] object The object providing the signal. @@ -271,46 +272,58 @@ public: // Default property extensions from ProxyObject */ virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const; -private: +public: // ProxyObject::Observer methods /** - * Helper called after the first apply animation. - * @param [in] object The active constraint. + * @copydoc ProxyObject::Observer::SceneObjectAdded() */ - static void FirstApplyFinished( Object* object ); + virtual void SceneObjectAdded( ProxyObject& proxy ); /** - * Helper called after the remove animation. - * @param [in] object The active constraint. + * @copydoc ProxyObject::Observer::SceneObjectRemoved() */ - static void OnRemoveFinished( Object* object ); + virtual void SceneObjectRemoved( ProxyObject& proxy ); - // To be implemented in derived classes + /** + * @copydoc ProxyObject::Observer::ProxyDestroyed() + */ + virtual void ProxyDestroyed( ProxyObject& proxy ); + +private: /** - * Used to observe the lifetime of an object with custom "weight" property - * @param [in] weightObject The object. + * Helper to observe a proxy, if not already observing it */ - virtual void OnCustomWeightSet( ProxyObject& weightObject ) = 0; + void ObserveProxy( ProxyObject& proxy ); /** - * Set the parent of the active-constraint; called during OnFirstApply(). - * @param [in] parent The parent object. + * Helper to stop observing proxies */ - virtual void OnFirstApply( ProxyObject& parent ) = 0; + void StopObservation(); /** - * Notification for the derived class, when BeginRemove() is called. + * Helper called after the first apply animation. + * @param [in] object The active constraint. */ - virtual void OnBeginRemove() = 0; + static void FirstApplyFinished( Object* object ); + + // To be implemented in derived classes + + /** + * Create and connect a constraint for a scene-object. + */ + virtual void ConnectConstraint() = 0; protected: EventToUpdate& mEventToUpdate; Property::Index mTargetPropertyIndex; + SourceContainer mSources; + const unsigned int mSourceCount; ProxyObject* mTargetProxy; ///< The proxy-object owns the active-constraint. + ProxyObjectContainer mObservedProxies; // We don't observe the same object twice const SceneGraph::ConstraintBase* mSceneGraphConstraint; @@ -318,8 +331,6 @@ protected: float mOffstageWeight; - TimePeriod mRemoveTime; - AlphaFunction mAlphaFunction; RemoveAction mRemoveAction; @@ -330,8 +341,6 @@ private: ActiveConstraintSignalV2 mAppliedSignal; Dali::Animation mApplyAnimation; ///< Used to automatically animate weight from 0.0f -> 1.0f - Dali::Animation mRemoveAnimation; ///< Used to automatically animate weight back to 0.0f - }; diff --git a/dali/internal/event/animation/active-constraint-impl.h b/dali/internal/event/animation/active-constraint-impl.h index 6cf822c..a0d9253 100644 --- a/dali/internal/event/animation/active-constraint-impl.h +++ b/dali/internal/event/animation/active-constraint-impl.h @@ -44,14 +44,11 @@ namespace Dali namespace Internal { -typedef std::set ProxyObjectContainer; -typedef ProxyObjectContainer::iterator ProxyObjectIter; - /** * Connects a constraint which takes another property as an input. */ template < typename PropertyType > -class ActiveConstraint : public ActiveConstraintBase, public ProxyObject::Observer +class ActiveConstraint : public ActiveConstraintBase { public: @@ -83,8 +80,6 @@ public: */ virtual ~ActiveConstraint() { - StopObservation(); - // This is not responsible for removing constraints. } @@ -104,7 +99,6 @@ public: funcPtr, mInterpolatorFunction ); - clone->SetRemoveTime(mRemoveTime); clone->SetAlphaFunction(mAlphaFunction); clone->SetRemoveAction(mRemoveAction); clone->SetTag( mTag ); @@ -112,94 +106,6 @@ public: return clone; } - /** - * @copydoc ActiveConstraintBase::OnCustomWeightSet() - */ - virtual void OnCustomWeightSet( ProxyObject& weightObject ) - { - ObserveProxy( weightObject ); - } - - /** - * @copydoc ActiveConstraintBase::OnFirstApply() - */ - virtual void OnFirstApply( ProxyObject& parent ) - { - DALI_ASSERT_ALWAYS( NULL == mTargetProxy && "Parent of ActiveConstraint already set" ); - - // No need to do anything, if the source objects are gone - if( mSources.size() == mSourceCount ) - { - mTargetProxy = &parent; - - ObserveProxy( parent ); - - ConnectConstraint(); - } - } - - /** - * @copydoc ActiveConstraintBase::OnBeginRemove() - */ - virtual void OnBeginRemove() - { - // Stop observing the remaining proxies - StopObservation(); - - // Discard all proxy pointers - mSources.clear(); - } - - /** - * @copydoc ProxyObject::Observer::SceneObjectAdded() - */ - virtual void SceneObjectAdded( ProxyObject& proxy ) - { - // Should not be getting callbacks when mSources has been cleared - DALI_ASSERT_DEBUG( mSources.size() == mSourceCount ); - - if ( mTargetProxy ) - { - ConnectConstraint(); - } - } - - /** - * @copydoc ProxyObject::Observer::SceneObjectRemoved() - */ - virtual void SceneObjectRemoved( ProxyObject& proxy ) - { - // Notify base class that the scene-graph constraint is being removed - OnSceneObjectRemove(); - - if ( mSceneGraphConstraint ) - { - // Preserve the previous weight - mOffstageWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() ); - - // This is not responsible for removing constraints. - mSceneGraphConstraint = NULL; - } - } - - /** - * @copydoc ProxyObject::Observer::ProxyDestroyed() - */ - virtual void ProxyDestroyed( ProxyObject& proxy ) - { - // Remove proxy pointer from observation set - ProxyObjectIter iter = mObservedProxies.find( &proxy ); - DALI_ASSERT_DEBUG( mObservedProxies.end() != iter ); - mObservedProxies.erase( iter ); - - // Stop observing the remaining proxies - StopObservation(); - - // Discard all proxy pointers - mTargetProxy = NULL; - mSources.clear(); - } - private: /** @@ -211,31 +117,11 @@ private: unsigned int sourceCount, ConstraintFunctionPtr& func, InterpolatorFunction& interpolator ) - : ActiveConstraintBase( eventToUpdate, targetIndex ), + : ActiveConstraintBase( eventToUpdate, targetIndex, sources, sourceCount ), mTargetIndex( targetIndex ), - mSources( sources ), - mSourceCount( sourceCount ), mUserFunction( func ), mInterpolatorFunction( interpolator ) { - // Skip init when any of the proxy objects have been destroyed - if ( mSources.size() != mSourceCount ) - { - // Discard all proxy pointers - mTargetProxy = NULL; - mSources.clear(); - } - - // Observe the objects providing properties - for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter ) - { - if ( OBJECT_PROPERTY == iter->sourceType ) - { - DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" ); - - ObserveProxy( *(iter->object) ); - } - } } // Undefined @@ -245,31 +131,6 @@ private: ActiveConstraint& operator=( const ActiveConstraint& rhs ); /** - * Helper to observe a proxy, if not already observing it - */ - void ObserveProxy( ProxyObject& proxy ) - { - if ( mObservedProxies.end() == mObservedProxies.find(&proxy) ) - { - proxy.AddObserver( *this ); - mObservedProxies.insert( &proxy ); - } - } - - /** - * Helper to stop observing proxies - */ - void StopObservation() - { - for( ProxyObjectIter iter = mObservedProxies.begin(); mObservedProxies.end() != iter; ++iter ) - { - (*iter)->RemoveObserver( *this ); - } - - mObservedProxies.clear(); - } - - /** * Create and connect a constraint for a scene-object. */ void ConnectConstraint() @@ -428,11 +289,6 @@ protected: Property::Index mTargetIndex; - SourceContainer mSources; - unsigned int mSourceCount; - - ProxyObjectContainer mObservedProxies; // We don't observe the same object twice - ConstraintFunctionPtr mUserFunction; InterpolatorFunction mInterpolatorFunction; }; @@ -441,7 +297,7 @@ protected: * Variant which allows float components to be animated individually. */ template <> -class ActiveConstraint : public ActiveConstraintBase, public ProxyObject::Observer +class ActiveConstraint : public ActiveConstraintBase { public: @@ -471,8 +327,6 @@ public: */ virtual ~ActiveConstraint() { - StopObservation(); - // This is not responsible for removing constraints. } @@ -492,7 +346,6 @@ public: funcPtr, mInterpolatorFunction ); - clone->SetRemoveTime(mRemoveTime); clone->SetAlphaFunction(mAlphaFunction); clone->SetRemoveAction(mRemoveAction); clone->SetTag( mTag ); @@ -500,94 +353,6 @@ public: return clone; } - /** - * @copydoc ActiveConstraintBase::OnCustomWeightSet() - */ - virtual void OnCustomWeightSet( ProxyObject& weightObject ) - { - ObserveProxy( weightObject ); - } - - /** - * @copydoc ActiveConstraintBase::OnFirstApply() - */ - virtual void OnFirstApply( ProxyObject& parent ) - { - DALI_ASSERT_ALWAYS( NULL == mTargetProxy && "Parent of ActiveConstraint already set" ); - - // No need to do anything, if the source objects are gone - if( mSources.size() == mSourceCount ) - { - mTargetProxy = &parent; - - ObserveProxy( parent ); - - ConnectConstraint(); - } - } - - /** - * @copydoc ActiveConstraintBase::OnBeginRemove() - */ - virtual void OnBeginRemove() - { - // Stop observing the remaining proxies - StopObservation(); - - // Discard all proxy pointers - mSources.clear(); - } - - /** - * @copydoc ProxyObject::Observer::SceneObjectAdded() - */ - virtual void SceneObjectAdded( ProxyObject& proxy ) - { - // Should not be getting callbacks when mSources has been cleared - DALI_ASSERT_DEBUG( mSources.size() == mSourceCount ); - - if ( mTargetProxy ) - { - ConnectConstraint(); - } - } - - /** - * @copydoc ProxyObject::Observer::SceneObjectRemoved() - */ - virtual void SceneObjectRemoved( ProxyObject& proxy ) - { - // Notify base class that the scene-graph constraint is being removed - OnSceneObjectRemove(); - - if ( mSceneGraphConstraint ) - { - // Preserve the previous weight - mOffstageWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() ); - - // This is not responsible for removing constraints. - mSceneGraphConstraint = NULL; - } - } - - /** - * @copydoc ProxyObject::Observer::ProxyDestroyed() - */ - virtual void ProxyDestroyed( ProxyObject& proxy ) - { - // Remove proxy pointer from observation set - ProxyObjectIter iter = mObservedProxies.find( &proxy ); - DALI_ASSERT_DEBUG( mObservedProxies.end() != iter ); - mObservedProxies.erase( iter ); - - // Stop observing the remaining proxies - StopObservation(); - - // Discard all proxy pointers - mTargetProxy = NULL; - mSources.clear(); - } - private: /** @@ -599,31 +364,11 @@ private: unsigned int sourceCount, ConstraintFunctionPtr& func, InterpolatorFunction& interpolator ) - : ActiveConstraintBase( eventToUpdate, targetIndex ), + : ActiveConstraintBase( eventToUpdate, targetIndex, sources, sourceCount ), mTargetIndex( targetIndex ), - mSources( sources ), - mSourceCount( sourceCount ), mUserFunction( func ), mInterpolatorFunction( interpolator ) { - // Skip init when any of the proxy objects have been destroyed - if ( mSources.size() != mSourceCount ) - { - // Discard all proxy pointers - mTargetProxy = NULL; - mSources.clear(); - } - - // Observe the objects providing properties - for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter ) - { - if ( OBJECT_PROPERTY == iter->sourceType ) - { - DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" ); - - ObserveProxy( *(iter->object) ); - } - } } // Undefined @@ -633,31 +378,6 @@ private: ActiveConstraint& operator=( const ActiveConstraint& rhs ); /** - * Helper to observe a proxy, if not already observing it - */ - void ObserveProxy( ProxyObject& proxy ) - { - if ( mObservedProxies.end() == mObservedProxies.find(&proxy) ) - { - proxy.AddObserver( *this ); - mObservedProxies.insert( &proxy ); - } - } - - /** - * Helper to stop observing proxies - */ - void StopObservation() - { - for( ProxyObjectIter iter = mObservedProxies.begin(); mObservedProxies.end() != iter; ++iter ) - { - (*iter)->RemoveObserver( *this ); - } - - mObservedProxies.clear(); - } - - /** * Create and connect a constraint for a scene-object. */ void ConnectConstraint() @@ -878,11 +598,6 @@ protected: Property::Index mTargetIndex; - SourceContainer mSources; - unsigned int mSourceCount; - - ProxyObjectContainer mObservedProxies; // We don't observe the same object twice - ConstraintFunctionPtr mUserFunction; InterpolatorFunction mInterpolatorFunction; }; diff --git a/dali/internal/event/animation/constraint-impl.cpp b/dali/internal/event/animation/constraint-impl.cpp index c8ce5d9..1b7fc86 100644 --- a/dali/internal/event/animation/constraint-impl.cpp +++ b/dali/internal/event/animation/constraint-impl.cpp @@ -251,16 +251,6 @@ TimePeriod Constraint::GetApplyTime() const return mApplyTime; } -void Constraint::SetRemoveTime( TimePeriod timePeriod ) -{ - GetImplementation( mActiveConstraintTemplate ).SetRemoveTime( timePeriod ); -} - -TimePeriod Constraint::GetRemoveTime() const -{ - return GetImplementation( mActiveConstraintTemplate ).GetRemoveTime(); -} - void Constraint::SetAlphaFunction( Dali::AlphaFunction func ) { GetImplementation( mActiveConstraintTemplate ).SetAlphaFunction( func ); diff --git a/dali/internal/event/animation/constraint-impl.h b/dali/internal/event/animation/constraint-impl.h index 2a0fabf..1de3625 100644 --- a/dali/internal/event/animation/constraint-impl.h +++ b/dali/internal/event/animation/constraint-impl.h @@ -69,16 +69,6 @@ public: TimePeriod GetApplyTime() const; /** - * @copydoc Dali::Constraint::SetRemoveTime() - */ - void SetRemoveTime( TimePeriod timePeriod ); - - /** - * @copydoc Dali::Constraint::GetRemoveTime() - */ - TimePeriod GetRemoveTime() const; - - /** * @copydoc Dali::Constraint::SetAlphaFunction( AlphaFunction func ) */ void SetAlphaFunction( AlphaFunction func ); diff --git a/dali/internal/event/common/proxy-object.cpp b/dali/internal/event/common/proxy-object.cpp index 98910f5..0085d20 100644 --- a/dali/internal/event/common/proxy-object.cpp +++ b/dali/internal/event/common/proxy-object.cpp @@ -61,7 +61,6 @@ ProxyObject::ProxyObject() mCustomProperties( NULL ), mTypeInfo( NULL ), mConstraints( NULL ), - mRemovedConstraints( NULL ), mPropertyNotifications( NULL ) { } @@ -92,6 +91,17 @@ void ProxyObject::RemoveObserver(Observer& observer) void ProxyObject::OnSceneObjectAdd() { + // Notification for this object's constraints + if( mConstraints ) + { + const ActiveConstraintConstIter endIter = mConstraints->end(); + for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter ) + { + ActiveConstraintBase& baseConstraint = GetImplementation( *iter ); + baseConstraint.OnParentSceneObjectAdded(); + } + } + // Notification for observers for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter) { @@ -104,6 +114,17 @@ void ProxyObject::OnSceneObjectAdd() void ProxyObject::OnSceneObjectRemove() { + // Notification for this object's constraints + if( mConstraints ) + { + const ActiveConstraintConstIter endIter = mConstraints->end(); + for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter ) + { + ActiveConstraintBase& baseConstraint = GetImplementation( *iter ); + baseConstraint.OnParentSceneObjectRemoved(); + } + } + // Notification for observers for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter ) { @@ -781,27 +802,6 @@ ActiveConstraintBase* ProxyObject::DoApplyConstraint( Constraint& constraint, Da return activeConstraintImpl; } -void ProxyObject::DeleteRemovedConstraints() -{ - if( ! mRemovedConstraints ) - { - return; - } - - // Discard constraints which are fully removed - for ( ActiveConstraintIter iter = mRemovedConstraints->begin(); mRemovedConstraints->end() != iter ;) - { - if ( !( GetImplementation( *iter ).IsRemoving() ) ) - { - iter = mRemovedConstraints->erase( iter ); - } - else - { - ++iter; - } - } -} - void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value ) { switch ( entry.type ) @@ -940,20 +940,6 @@ void ProxyObject::RemoveConstraint( ActiveConstraint& constraint, bool isInScene { ActiveConstraintBase& baseConstraint = GetImplementation( constraint ); baseConstraint.BeginRemove(); - if ( baseConstraint.IsRemoving() ) - { - if( !mRemovedConstraints ) - { - mRemovedConstraints = new ActiveConstraintContainer; - } - // Wait for remove animation before destroying active-constraints - mRemovedConstraints->push_back( constraint ); - } - } - else if( mRemovedConstraints ) - { - delete mRemovedConstraints; - mRemovedConstraints = NULL; } } } @@ -964,10 +950,6 @@ void ProxyObject::RemoveConstraint( Dali::ActiveConstraint activeConstraint ) if( mConstraints && Stage::IsInstalled() ) { bool isInSceneGraph( NULL != GetSceneObject() ); - if( isInSceneGraph ) - { - DeleteRemovedConstraints(); - } ActiveConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), activeConstraint ) ); if( it != mConstraints->end() ) @@ -984,10 +966,6 @@ void ProxyObject::RemoveConstraints( unsigned int tag ) if( mConstraints && Stage::IsInstalled() ) { bool isInSceneGraph( NULL != GetSceneObject() ); - if( isInSceneGraph ) - { - DeleteRemovedConstraints(); - } ActiveConstraintIter iter( mConstraints->begin() ); while(iter != mConstraints->end() ) @@ -1013,16 +991,8 @@ void ProxyObject::RemoveConstraints() { // If we have nothing in the scene-graph, just clear constraint containers const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject(); - if ( NULL == propertyOwner ) + if ( NULL != propertyOwner ) { - delete mRemovedConstraints; - mRemovedConstraints = NULL; - } - else - { - // Discard constraints which are fully removed - DeleteRemovedConstraints(); - const ActiveConstraintConstIter endIter = mConstraints->end(); for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter ) { @@ -1042,6 +1012,18 @@ void ProxyObject::SetTypeInfo( const TypeInfo* typeInfo ) ProxyObject::~ProxyObject() { + // Notification for this object's constraints + // (note that the ActiveConstraint handles may outlive the ProxyObject) + if( mConstraints ) + { + const ActiveConstraintConstIter endIter = mConstraints->end(); + for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter ) + { + ActiveConstraintBase& baseConstraint = GetImplementation( *iter ); + baseConstraint.OnParentDestroyed(); + } + } + // Notification for observers for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter) { @@ -1050,7 +1032,6 @@ ProxyObject::~ProxyObject() delete mCustomProperties; delete mConstraints; - delete mRemovedConstraints; delete mPropertyNotifications; } diff --git a/dali/internal/event/common/proxy-object.h b/dali/internal/event/common/proxy-object.h index 14fb561..fcc658d 100644 --- a/dali/internal/event/common/proxy-object.h +++ b/dali/internal/event/common/proxy-object.h @@ -324,11 +324,6 @@ private: ActiveConstraintBase* DoApplyConstraint( Constraint& constraint, Dali::Constrainable weightObject ); /** - * Helper to delete removed constraints - */ - void DeleteRemovedConstraints(); - - /** * Helper to remove active constraints */ void RemoveConstraint( ActiveConstraint& constraint, bool isInScenegraph ); @@ -449,7 +444,6 @@ private: Dali::Vector mObservers; ActiveConstraintContainer* mConstraints; ///< Container of owned active-constraints. - ActiveConstraintContainer* mRemovedConstraints; ///< Container of owned active-constraints, which are being removed. typedef std::vector< Dali::PropertyNotification > PropertyNotificationContainer; typedef PropertyNotificationContainer::iterator PropertyNotificationContainerIter; diff --git a/dali/internal/update/animation/scene-graph-constraint-base.cpp b/dali/internal/update/animation/scene-graph-constraint-base.cpp index 9e80267..19b0373 100644 --- a/dali/internal/update/animation/scene-graph-constraint-base.cpp +++ b/dali/internal/update/animation/scene-graph-constraint-base.cpp @@ -30,6 +30,11 @@ namespace Internal namespace SceneGraph { +#ifdef DEBUG_ENABLED + unsigned int ConstraintBase::mCurrentInstanceCount = 0; + unsigned int ConstraintBase::mTotalInstanceCount = 0; +#endif + ConstraintBase::ConstraintBase( PropertyOwnerSet& ownerSet ) : mWeight( Dali::ActiveConstraint::DEFAULT_WEIGHT ), mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ), @@ -37,6 +42,10 @@ ConstraintBase::ConstraintBase( PropertyOwnerSet& ownerSet ) mDisconnected( true ), mObservedOwners( ownerSet ) { +#ifdef DEBUG_ENABLED + ++mCurrentInstanceCount; + ++mTotalInstanceCount; +#endif } ConstraintBase::~ConstraintBase() @@ -46,10 +55,11 @@ ConstraintBase::~ConstraintBase() StopObservation(); } -// TODO - Override new & delete to provide this for everything -#if defined(DEBUG_ENABLED) && !defined(EMSCRIPTEN) - // Fill with garbage pattern to help detect invalid memory access - memset ( &mWeight, 0xFA, sizeof(mWeight) ); +#ifdef DEBUG_ENABLED + --mCurrentInstanceCount; +#ifndef EMSCRIPTEN + memset ( &mWeight, 0xFA, sizeof(mWeight) ); // Fill with garbage pattern to help detect invalid memory access +#endif #endif } @@ -59,6 +69,24 @@ void ConstraintBase::ResetDefaultProperties( BufferIndex updateBufferIndex ) DALI_ASSERT_DEBUG( false ); } +unsigned int ConstraintBase::GetCurrentInstanceCount() +{ +#ifdef DEBUG_ENABLED + return mCurrentInstanceCount; +#else + return 0u; +#endif +} + +unsigned int ConstraintBase::GetTotalInstanceCount() +{ +#ifdef DEBUG_ENABLED + return mTotalInstanceCount; +#else + return 0u; +#endif +} + } // namespace SceneGraph } // namespace Internal diff --git a/dali/internal/update/animation/scene-graph-constraint-base.h b/dali/internal/update/animation/scene-graph-constraint-base.h index 3a292c1..355b8b3 100644 --- a/dali/internal/update/animation/scene-graph-constraint-base.h +++ b/dali/internal/update/animation/scene-graph-constraint-base.h @@ -124,6 +124,18 @@ public: */ virtual void Apply( BufferIndex updateBufferIndex ) = 0; + /** + * Helper for internal test cases; only available for debug builds. + * @return The current number of Constraint instances in existence. + */ + static unsigned int GetCurrentInstanceCount(); + + /** + * Helper for internal test cases; only available for debug builds. + * @return The total number of Constraint instances created during the Dali core lifetime. + */ + static unsigned int GetTotalInstanceCount(); + private: /** @@ -193,6 +205,11 @@ protected: private: PropertyOwnerSet mObservedOwners; ///< A set of pointers to each observed object. Not owned. + +#ifdef DEBUG_ENABLED + static unsigned int mCurrentInstanceCount; ///< The current number of Constraint instances in existence. + static unsigned int mTotalInstanceCount; ///< The total number of Constraint instances created during the Dali core lifetime. +#endif }; // Messages for ConstraintBase diff --git a/dali/public-api/animation/constraint.cpp b/dali/public-api/animation/constraint.cpp index 4b7df23..2c8cc98 100644 --- a/dali/public-api/animation/constraint.cpp +++ b/dali/public-api/animation/constraint.cpp @@ -72,12 +72,13 @@ TimePeriod Constraint::GetApplyTime() const void Constraint::SetRemoveTime( TimePeriod timePeriod ) { - GetImplementation(*this).SetRemoveTime( timePeriod ); + // TODO - Remove this deprecated method } TimePeriod Constraint::GetRemoveTime() const { - return GetImplementation(*this).GetRemoveTime(); + // TODO - Remove this deprecated method + return TimePeriod(0.0f); } void Constraint::SetAlphaFunction( AlphaFunction func ) diff --git a/dali/public-api/animation/constraint.h b/dali/public-api/animation/constraint.h index c5cfe90..583fe43 100644 --- a/dali/public-api/animation/constraint.h +++ b/dali/public-api/animation/constraint.h @@ -563,17 +563,12 @@ public: TimePeriod GetApplyTime() const; /** - * @brief Set the time taken for the constraint to be fully removed. - * - * The default is zero, meaning that the constraint is removed immediately. - * @param [in] timePeriod The constraint will be removed during this time period. + * @deprecated Use animation API directly instead. */ void SetRemoveTime( TimePeriod timePeriod ); /** - * @brief Retrieve the time taken for the constraint to be fully removed. - * - * @return The remove time. + * @deprecated Use animation API directly instead. */ TimePeriod GetRemoveTime() const; -- 2.7.4