* 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 ),
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 )
{
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 )
{
}
}
-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 );
- }
+ // Stop observing the remaining proxies
+ StopObservation();
- // 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()
return connected;
}
-void ActiveConstraintBase::SetRemoveTime( TimePeriod removeTime )
-{
- mRemoveTime = removeTime;
-}
-
-TimePeriod ActiveConstraintBase::GetRemoveTime() const
-{
- return mRemoveTime;
-}
-
void ActiveConstraintBase::SetAlphaFunction( AlphaFunction alphaFunc )
{
mAlphaFunction = alphaFunc;
return mTag;
}
-
-bool ActiveConstraintBase::IsSceneObjectRemovable() const
-{
- return true; // The constraint removed when target SceneGraph::PropertyOwner is destroyed
-}
-
unsigned int ActiveConstraintBase::GetDefaultPropertyCount() const
{
return DEFAULT_PROPERTY_COUNT;
}
}
-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;
}
void ActiveConstraintBase::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
{
- switch ( index )
+ if( Dali::ActiveConstraint::WEIGHT == index )
{
- case Dali::ActiveConstraint::WEIGHT:
- {
- SetWeight( propertyValue.Get<float>() );
- break;
- }
-
- default:
- {
- DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
- break;
- }
+ SetWeight( propertyValue.Get<float>() );
}
}
-void ActiveConstraintBase::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
-{
- DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties"); // should not come here
-}
-
Property::Value ActiveConstraintBase::GetDefaultProperty( Property::Index index ) const
{
Property::Value value;
- switch ( index )
+ if( Dali::ActiveConstraint::WEIGHT == index )
{
- case Dali::ActiveConstraint::WEIGHT:
- {
- value = GetCurrentWeight();
- break;
- }
-
- default:
- {
- DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
- break;
- }
+ value = GetCurrentWeight();
}
return value;
}
-void ActiveConstraintBase::InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
-{
- DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties" ); // should not come here
-}
-
const SceneGraph::PropertyOwner* ActiveConstraintBase::GetSceneObject() const
{
return mSceneGraphConstraint;
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;
+ }
+}
+
+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 );
- if ( !self.mAppliedSignal.Empty() )
+ // 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