-//
-// 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 <dali/internal/event/animation/active-constraint-base.h>
* 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"
};
} // 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<float>* sceneProperty = dynamic_cast< const SceneGraph::AnimatableProperty<float>* >( 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 )
{
}
}
-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()
return connected;
}
-void ActiveConstraintBase::SetRemoveTime( TimePeriod removeTime )
-{
- mRemoveTime = removeTime;
-}
-
-TimePeriod ActiveConstraintBase::GetRemoveTime() const
-{
- return mRemoveTime;
-}
-
void ActiveConstraintBase::SetAlphaFunction( AlphaFunction alphaFunc )
{
mAlphaFunction = alphaFunc;
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
}
}
-const std::string& ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const
+const char* ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const
{
if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
{
}
else
{
- // index out of range..return empty string
- static const std::string INVALID_PROPERTY_NAME;
- return INVALID_PROPERTY_NAME;
+ return NULL;
}
}
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;
}
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 ) )
return &mSceneGraphConstraint->mWeight;
}
-void ActiveConstraintBase::FirstApplyFinished( Object* object )
+void ActiveConstraintBase::SceneObjectAdded( ProxyObject& proxy )
{
- ActiveConstraintBase& self = dynamic_cast<ActiveConstraintBase&>( *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<ActiveConstraintBase&>( *object );
+ // trust the object is correct as its set in FirstApply (in this same file)
+ ActiveConstraintBase* self = static_cast<ActiveConstraintBase*>( 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