X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fanimation%2Factive-constraint-base.cpp;h=121ed807677a4c49cdcae1a90aa1f95cd2487d20;hb=23bced0a72d755b404c456644c3220800a5a55dd;hp=bb67c2d8834c991bfc9fe02274fb560cf2b9bc24;hpb=24a826711c9b42968089e6ad54faead44a5df376;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/animation/active-constraint-base.cpp b/dali/internal/event/animation/active-constraint-base.cpp index bb67c2d..121ed80 100644 --- a/dali/internal/event/animation/active-constraint-base.cpp +++ b/dali/internal/event/animation/active-constraint-base.cpp @@ -1,18 +1,19 @@ -// -// Copyright (c) 2014 Samsung Electronics Co., Ltd. -// -// Licensed under the Flora License, Version 1.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://floralicense.org/license/ -// -// 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. -// +/* + * 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. + * + */ // CLASS HEADER #include @@ -60,7 +61,7 @@ namespace // unnamed namespace * We want to discourage the use of property strings (minimize string comparisons), * particularly for the default properties. */ -const std::string DEFAULT_PROPERTY_NAMES[] = +const char* DEFAULT_PROPERTY_NAMES[] = { "weight" }; @@ -73,39 +74,76 @@ 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 ), - mApplyAnimation(), - mRemoveAnimation() + mTag(0), + 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 ); } +} + +void ActiveConstraintBase::SetCustomWeightObject( ProxyObject& weightObject, Property::Index weightIndex ) +{ + const SceneGraph::PropertyBase* base = weightObject.GetSceneObjectAnimatableProperty( weightIndex ); + const SceneGraph::AnimatableProperty* sceneProperty = dynamic_cast< const SceneGraph::AnimatableProperty* >( base ); - if( mRemoveAnimation ) + if( sceneProperty ) { - GetImplementation(mRemoveAnimation).SetFinishedCallback( NULL, NULL ); + mCustomWeight = sceneProperty; + + ObserveProxy( weightObject ); } } -void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime, ActiveConstraintCallbackType* callback ) +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 ) { @@ -125,45 +163,59 @@ void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime } } -void ActiveConstraintBase::BeginRemove() +void ActiveConstraintBase::OnParentDestroyed() { - // Notify derived classes - OnBeginRemove(); - - // 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(); - } + // Stop observing the remaining proxies + StopObservation(); - // 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() @@ -233,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; @@ -263,9 +305,14 @@ ActiveConstraintBase::RemoveAction ActiveConstraintBase::GetRemoveAction() const return mRemoveAction; } -bool ActiveConstraintBase::IsSceneObjectRemovable() const +void ActiveConstraintBase::SetTag(const unsigned int tag) +{ + mTag = tag; +} + +unsigned int ActiveConstraintBase::GetTag() const { - return true; // The constraint removed when target SceneGraph::PropertyOwner is destroyed + return mTag; } unsigned int ActiveConstraintBase::GetDefaultPropertyCount() const @@ -283,7 +330,7 @@ void ActiveConstraintBase::GetDefaultPropertyIndices( Property::IndexContainer& } } -const std::string& ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const +const char* ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const { if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) { @@ -291,9 +338,7 @@ const std::string& ActiveConstraintBase::GetDefaultPropertyName( Property::Index } else { - // index out of range..return empty string - static const std::string INVALID_PROPERTY_NAME; - return INVALID_PROPERTY_NAME; + return NULL; } } @@ -302,7 +347,7 @@ Property::Index ActiveConstraintBase::GetDefaultPropertyIndex( const std::string Property::Index index = Property::INVALID_INDEX; // Only one name to compare with... - if ( name == DEFAULT_PROPERTY_NAMES[0] ) + if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_NAMES[0] ) ) // dont want to convert rhs to string { index = 0; } @@ -320,6 +365,11 @@ bool ActiveConstraintBase::IsDefaultPropertyAnimatable( Property::Index index ) return true; // All default properties are currently animatable } +bool ActiveConstraintBase::IsDefaultPropertyAConstraintInput( Property::Index index ) const +{ + return true; // All default properties can currently be used as a constraint input +} + Property::Type ActiveConstraintBase::GetDefaultPropertyType( Property::Index index ) const { if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) @@ -414,50 +464,99 @@ const PropertyInputImpl* ActiveConstraintBase::GetSceneObjectInputProperty( Prop return &mSceneGraphConstraint->mWeight; } -void ActiveConstraintBase::FirstApplyFinished( Object* object ) +void ActiveConstraintBase::SceneObjectAdded( ProxyObject& proxy ) { - ActiveConstraintBase& self = dynamic_cast( *object ); + // Should not be getting callbacks when mSources has been cleared + DALI_ASSERT_DEBUG( mSources.size() == mSourceCount ); - // This is necessary when the constraint was not added to scene-graph during the animation - self.SetWeight( Dali::ActiveConstraint::FINAL_WEIGHT ); + if ( NULL == mSceneGraphConstraint && + mTargetProxy ) + { + ConnectConstraint(); + } +} - // The animation is no longer needed - GetImplementation(self.mApplyAnimation).SetFinishedCallback( NULL, NULL ); - self.mApplyAnimation.Reset(); +void ActiveConstraintBase::SceneObjectRemoved( ProxyObject& proxy ) +{ + // Notify base class that the scene-graph constraint is being removed + OnSceneObjectRemove(); - // Chain "Finish" to "Applied" signal + 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; + } +} - if ( !self.mAppliedSignal.Empty() ) +void ActiveConstraintBase::ProxyDestroyed( ProxyObject& proxy ) +{ + // Remove proxy pointer from observation set + ProxyObjectIter iter = std::find( mObservedProxies.Begin(), mObservedProxies.End(), &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 ) +{ + ProxyObjectIter iter = std::find( mObservedProxies.Begin(), mObservedProxies.End(), &proxy ); + if ( mObservedProxies.End() == iter ) { - Dali::ActiveConstraint handle( &self ); + proxy.AddObserver( *this ); + mObservedProxies.PushBack( &proxy ); + } +} - self.mAppliedSignal.Emit( handle ); +void ActiveConstraintBase::StopObservation() +{ + const ProxyObjectIter end = mObservedProxies.End(); + for( ProxyObjectIter iter = mObservedProxies.Begin(); iter != end; ++iter ) + { + (*iter)->RemoveObserver( *this ); } - // WARNING - this constraint may now have been deleted; don't do anything else here + mObservedProxies.Clear(); } -void ActiveConstraintBase::OnRemoveFinished( Object* object ) +void ActiveConstraintBase::FirstApplyFinished( Object* object ) { - ActiveConstraintBase& self = dynamic_cast( *object ); + // trust the object is correct as its set in FirstApply (in this same file) + ActiveConstraintBase* self = static_cast( object ); - const SceneGraph::PropertyOwner* propertyOwner = self.mTargetProxy ? self.mTargetProxy->GetSceneObject() : NULL; + // This is necessary when the constraint was not added to scene-graph during the animation + self->SetWeight( Dali::ActiveConstraint::FINAL_WEIGHT ); - if ( propertyOwner && - self.mSceneGraphConstraint ) - { - // Notify base class that the scene-graph constraint is being removed - self.OnSceneObjectRemove(); + // The animation is no longer needed + GetImplementation(self->mApplyAnimation).SetFinishedCallback( NULL, NULL ); + self->mApplyAnimation.Reset(); - // Remove from scene-graph - RemoveConstraintMessage( self.mEventToUpdate, *propertyOwner, *(self.mSceneGraphConstraint) ); + // Chain "Finish" to "Applied" signal - // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer - self.mSceneGraphConstraint = NULL; + if ( !self->mAppliedSignal.Empty() ) + { + Dali::ActiveConstraint handle( self ); + self->mAppliedSignal.Emit( handle ); } - // The animation is no longer needed - self.mRemoveAnimation.Reset(); + // WARNING - this constraint may now have been deleted; don't do anything else here } } // namespace Internal