2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/animation/active-constraint-base.h>
22 #include <dali/public-api/animation/active-constraint.h>
23 #include <dali/public-api/object/handle.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/internal/event/common/event-thread-services.h>
26 #include <dali/internal/event/common/property-helper.h>
27 #include <dali/internal/event/animation/animation-impl.h>
28 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
29 #include <dali/internal/update/common/animatable-property.h>
30 #include <dali/internal/update/common/property-owner-messages.h>
32 using Dali::Internal::SceneGraph::AnimatableProperty;
40 namespace // unnamed namespace
45 // Name Type writable animatable constraint-input enum for index-checking
46 DALI_PROPERTY_TABLE_BEGIN
47 DALI_PROPERTY( "weight", FLOAT, true, true, true, Dali::ActiveConstraint::Property::WEIGHT )
48 DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
52 const char* const SIGNAL_APPLIED = "applied";
56 // not directly creatable
60 TypeRegistration mType( typeid(Dali::ActiveConstraint), typeid(Dali::Handle), Create );
62 SignalConnectorType signalConnector1( mType, SIGNAL_APPLIED, &ActiveConstraintBase::DoConnectSignal );
64 } // unnamed namespace
66 ActiveConstraintBase::ActiveConstraintBase( Property::Index targetPropertyIndex, SourceContainer& sources, unsigned int sourceCount )
67 : mTargetPropertyIndex( targetPropertyIndex ),
69 mSourceCount( sourceCount ),
70 mTargetObject( NULL ),
72 mSceneGraphConstraint( NULL ),
73 mCustomWeight( NULL ),
74 mOffstageWeight( Dali::ActiveConstraint::DEFAULT_WEIGHT ),
75 mAlphaFunction( Dali::Constraint::DEFAULT_ALPHA_FUNCTION ),
76 mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
80 // Skip init when any of the objects have been destroyed
81 if ( mSources.size() != mSourceCount )
83 // Discard all object pointers
88 // Observe the objects providing properties
89 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
91 if ( OBJECT_PROPERTY == iter->sourceType )
93 DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" );
95 ObserveObject( *(iter->object) );
100 ActiveConstraintBase::~ActiveConstraintBase()
104 // Disconnect from internal animation signals
105 if ( mApplyAnimation )
107 GetImplementation(mApplyAnimation).SetFinishedCallback( NULL, NULL );
111 void ActiveConstraintBase::SetCustomWeightObject( Object& weightObject, Property::Index weightIndex )
113 const SceneGraph::PropertyBase* base = weightObject.GetSceneObjectAnimatableProperty( weightIndex );
114 const SceneGraph::AnimatableProperty<float>* sceneProperty = dynamic_cast< const SceneGraph::AnimatableProperty<float>* >( base );
118 mCustomWeight = sceneProperty;
120 ObserveObject( weightObject );
124 void ActiveConstraintBase::FirstApply( Object& parent, TimePeriod applyTime )
126 DALI_ASSERT_ALWAYS( NULL == mTargetObject && "Parent of ActiveConstraint already set" );
128 // No need to do anything, if the source objects are gone
129 if( mSources.size() == mSourceCount )
131 mTargetObject = &parent;
136 if ( applyTime.durationSeconds > 0.0f )
138 DALI_ASSERT_DEBUG( !mApplyAnimation );
143 // Automatically animate (increase) the weight, until the constraint is fully applied
144 mApplyAnimation = Dali::Animation::New( applyTime.delaySeconds + applyTime.durationSeconds );
145 Dali::ActiveConstraint self( this );
146 mApplyAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::Property::WEIGHT ), Dali::ActiveConstraint::FINAL_WEIGHT, mAlphaFunction, applyTime );
147 mApplyAnimation.Play();
149 // Chain "Finish" to "Applied" signal
150 GetImplementation(mApplyAnimation).SetFinishedCallback( &ActiveConstraintBase::FirstApplyFinished, this );
154 void ActiveConstraintBase::OnParentDestroyed()
156 // Stop observing the remaining objects
159 // Discard all object pointers
160 mTargetObject = NULL;
164 void ActiveConstraintBase::OnParentSceneObjectAdded()
166 if ( NULL == mSceneGraphConstraint &&
173 void ActiveConstraintBase::OnParentSceneObjectRemoved()
175 if ( mSceneGraphConstraint )
177 // Notify base class that the scene-graph constraint is being removed
178 OnSceneObjectRemove();
180 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
181 mSceneGraphConstraint = NULL;
185 void ActiveConstraintBase::BeginRemove()
187 // Stop observing the remaining objects
190 // Discard all object pointers
193 const SceneGraph::PropertyOwner* propertyOwner = mTargetObject ? mTargetObject->GetSceneObject() : NULL;
195 if ( propertyOwner &&
196 mSceneGraphConstraint )
198 // Notify base class that the scene-graph constraint is being removed
199 OnSceneObjectRemove();
201 // Remove from scene-graph
202 RemoveConstraintMessage( GetEventThreadServices(), *propertyOwner, *(mSceneGraphConstraint) );
204 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
205 mSceneGraphConstraint = NULL;
209 Object* ActiveConstraintBase::GetParent()
211 return mTargetObject;
214 bool ActiveConstraintBase::Supports( Capability capability ) const
216 return false; // switch-off support for dynamic properties
219 Dali::Handle ActiveConstraintBase::GetTargetObject()
221 return Dali::Handle( mTargetObject );
224 Property::Index ActiveConstraintBase::GetTargetProperty()
226 return mTargetPropertyIndex;
229 void ActiveConstraintBase::SetWeight( float weight )
231 if ( mSceneGraphConstraint )
233 BakeWeightMessage( GetEventThreadServices(), *mSceneGraphConstraint, weight );
237 mOffstageWeight = weight;
241 float ActiveConstraintBase::GetCurrentWeight() const
243 float currentWeight( mOffstageWeight );
245 if ( mSceneGraphConstraint )
247 currentWeight = mSceneGraphConstraint->GetWeight( GetEventThreadServices().GetEventBufferIndex() );
250 return currentWeight;
253 ActiveConstraintSignalType& ActiveConstraintBase::AppliedSignal()
255 return mAppliedSignal;
258 bool ActiveConstraintBase::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
260 bool connected( true );
261 ActiveConstraintBase* constraint = dynamic_cast<ActiveConstraintBase*>(object);
263 if ( 0 == strcmp( signalName.c_str(), SIGNAL_APPLIED ) )
265 constraint->AppliedSignal().Connect( tracker, functor );
269 // signalName does not match any signal
276 void ActiveConstraintBase::SetAlphaFunction( AlphaFunction alphaFunc )
278 mAlphaFunction = alphaFunc;
281 AlphaFunction ActiveConstraintBase::GetAlphaFunction() const
283 return mAlphaFunction;
286 void ActiveConstraintBase::SetRemoveAction( ActiveConstraintBase::RemoveAction action )
288 mRemoveAction = action;
291 ActiveConstraintBase::RemoveAction ActiveConstraintBase::GetRemoveAction() const
293 return mRemoveAction;
296 void ActiveConstraintBase::SetTag(const unsigned int tag)
301 unsigned int ActiveConstraintBase::GetTag() const
306 unsigned int ActiveConstraintBase::GetDefaultPropertyCount() const
308 return DEFAULT_PROPERTY_COUNT;
311 void ActiveConstraintBase::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
313 indices.reserve( DEFAULT_PROPERTY_COUNT );
315 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
317 indices.push_back( i );
321 const char* ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const
323 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
325 return DEFAULT_PROPERTY_DETAILS[index].name;
333 Property::Index ActiveConstraintBase::GetDefaultPropertyIndex( const std::string& name ) const
335 Property::Index index = Property::INVALID_INDEX;
337 // Only one name to compare with...
338 if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[0].name ) ) // Don't want to convert rhs to string
346 bool ActiveConstraintBase::IsDefaultPropertyWritable( Property::Index index ) const
348 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
351 bool ActiveConstraintBase::IsDefaultPropertyAnimatable( Property::Index index ) const
353 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
356 bool ActiveConstraintBase::IsDefaultPropertyAConstraintInput( Property::Index index ) const
358 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
361 Property::Type ActiveConstraintBase::GetDefaultPropertyType( Property::Index index ) const
363 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
365 return DEFAULT_PROPERTY_DETAILS[index].type;
368 // Index out-of-range
369 return Property::NONE;
372 void ActiveConstraintBase::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
374 if( Dali::ActiveConstraint::Property::WEIGHT == index )
376 SetWeight( propertyValue.Get<float>() );
380 Property::Value ActiveConstraintBase::GetDefaultProperty( Property::Index index ) const
382 Property::Value value;
384 if( Dali::ActiveConstraint::Property::WEIGHT == index )
386 value = GetCurrentWeight();
392 const SceneGraph::PropertyOwner* ActiveConstraintBase::GetSceneObject() const
394 return mSceneGraphConstraint;
397 const SceneGraph::PropertyBase* ActiveConstraintBase::GetSceneObjectAnimatableProperty( Property::Index index ) const
399 DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
401 // This method should only return a property which is part of the scene-graph
402 if ( !mSceneGraphConstraint )
407 return &mSceneGraphConstraint->mWeight;
410 const PropertyInputImpl* ActiveConstraintBase::GetSceneObjectInputProperty( Property::Index index ) const
412 DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
414 // This method should only return a property which is part of the scene-graph
415 if ( !mSceneGraphConstraint )
420 return &mSceneGraphConstraint->mWeight;
423 void ActiveConstraintBase::SceneObjectAdded( Object& object )
425 // Should not be getting callbacks when mSources has been cleared
426 DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
428 if ( NULL == mSceneGraphConstraint &&
435 void ActiveConstraintBase::SceneObjectRemoved( Object& object )
437 // Notify base class that the scene-graph constraint is being removed
438 OnSceneObjectRemove();
440 if ( mSceneGraphConstraint )
442 // Preserve the previous weight
443 mOffstageWeight = mSceneGraphConstraint->GetWeight( GetEventThreadServices().GetEventBufferIndex() );
445 const SceneGraph::PropertyOwner* propertyOwner = mTargetObject ? mTargetObject->GetSceneObject() : NULL;
449 // Remove from scene-graph
450 RemoveConstraintMessage( GetEventThreadServices(), *propertyOwner, *(mSceneGraphConstraint) );
453 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
454 mSceneGraphConstraint = NULL;
458 void ActiveConstraintBase::ObjectDestroyed( Object& object )
460 // Remove object pointer from observation set
461 ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object );
462 DALI_ASSERT_DEBUG( mObservedObjects.End() != iter );
463 mObservedObjects.Erase( iter );
465 // Stop observing the remaining objects
468 // Discard all object & scene-graph pointers
469 mSceneGraphConstraint = NULL;
470 mTargetObject = NULL;
474 void ActiveConstraintBase::ObserveObject( Object& object )
476 ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object );
477 if ( mObservedObjects.End() == iter )
479 object.AddObserver( *this );
480 mObservedObjects.PushBack( &object );
484 void ActiveConstraintBase::StopObservation()
486 const ObjectIter end = mObservedObjects.End();
487 for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
489 (*iter)->RemoveObserver( *this );
492 mObservedObjects.Clear();
495 void ActiveConstraintBase::FirstApplyFinished( Object* object )
497 // trust the object is correct as its set in FirstApply (in this same file)
498 ActiveConstraintBase* self = static_cast<ActiveConstraintBase*>( object );
500 // This is necessary when the constraint was not added to scene-graph during the animation
501 self->SetWeight( Dali::ActiveConstraint::FINAL_WEIGHT );
503 // The animation is no longer needed
504 GetImplementation(self->mApplyAnimation).SetFinishedCallback( NULL, NULL );
505 self->mApplyAnimation.Reset();
507 // Chain "Finish" to "Applied" signal
509 if ( !self->mAppliedSignal.Empty() )
511 Dali::ActiveConstraint handle( self );
512 self->mAppliedSignal.Emit( handle );
515 // WARNING - this constraint may now have been deleted; don't do anything else here
518 } // namespace Internal