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/common/event-to-update.h>
26 #include <dali/internal/event/animation/animation-impl.h>
27 #include <dali/internal/update/common/animatable-property.h>
28 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
29 #include <dali/internal/update/common/property-owner-messages.h>
31 using Dali::Internal::SceneGraph::AnimatableProperty;
36 const Property::Index ActiveConstraint::WEIGHT = 0;
41 namespace // unnamed namespace
46 const char* const SIGNAL_APPLIED = "applied";
50 // not directly creatable
54 TypeRegistration mType( typeid(Dali::ActiveConstraint), typeid(Dali::Handle), Create );
56 SignalConnectorType signalConnector1( mType, SIGNAL_APPLIED, &ActiveConstraintBase::DoConnectSignal );
61 namespace // unnamed namespace
65 * We want to discourage the use of property strings (minimize string comparisons),
66 * particularly for the default properties.
68 const char* DEFAULT_PROPERTY_NAMES[] =
72 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_NAMES ) / sizeof( std::string );
74 const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
76 Property::FLOAT // WEIGHT
79 } // unnamed namespace
81 ActiveConstraintBase::ActiveConstraintBase( EventToUpdate& eventToUpdate, Property::Index targetPropertyIndex, SourceContainer& sources, unsigned int sourceCount )
82 : mEventToUpdate( eventToUpdate ),
83 mTargetPropertyIndex( targetPropertyIndex ),
85 mSourceCount( sourceCount ),
88 mSceneGraphConstraint( NULL ),
89 mCustomWeight( NULL ),
90 mOffstageWeight( Dali::ActiveConstraint::DEFAULT_WEIGHT ),
91 mAlphaFunction( Dali::Constraint::DEFAULT_ALPHA_FUNCTION ),
92 mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
96 // Skip init when any of the proxy objects have been destroyed
97 if ( mSources.size() != mSourceCount )
99 // Discard all proxy pointers
104 // Observe the objects providing properties
105 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
107 if ( OBJECT_PROPERTY == iter->sourceType )
109 DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" );
111 ObserveProxy( *(iter->object) );
116 ActiveConstraintBase::~ActiveConstraintBase()
120 // Disconnect from internal animation signals
121 if ( mApplyAnimation )
123 GetImplementation(mApplyAnimation).SetFinishedCallback( NULL, NULL );
127 void ActiveConstraintBase::SetCustomWeightObject( ProxyObject& weightObject, Property::Index weightIndex )
129 const SceneGraph::PropertyBase* base = weightObject.GetSceneObjectAnimatableProperty( weightIndex );
130 const SceneGraph::AnimatableProperty<float>* sceneProperty = dynamic_cast< const SceneGraph::AnimatableProperty<float>* >( base );
134 mCustomWeight = sceneProperty;
136 ObserveProxy( weightObject );
140 void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime )
142 DALI_ASSERT_ALWAYS( NULL == mTargetProxy && "Parent of ActiveConstraint already set" );
144 // No need to do anything, if the source objects are gone
145 if( mSources.size() == mSourceCount )
147 mTargetProxy = &parent;
152 if ( applyTime.durationSeconds > 0.0f )
154 DALI_ASSERT_DEBUG( !mApplyAnimation );
159 // Automatically animate (increase) the weight, until the constraint is fully applied
160 mApplyAnimation = Dali::Animation::New( applyTime.delaySeconds + applyTime.durationSeconds );
161 Dali::ActiveConstraint self( this );
162 mApplyAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::WEIGHT ), Dali::ActiveConstraint::FINAL_WEIGHT, mAlphaFunction, applyTime );
163 mApplyAnimation.Play();
165 // Chain "Finish" to "Applied" signal
166 GetImplementation(mApplyAnimation).SetFinishedCallback( &ActiveConstraintBase::FirstApplyFinished, this );
170 void ActiveConstraintBase::OnParentDestroyed()
172 // Stop observing the remaining proxies
175 // Discard all proxy pointers
180 void ActiveConstraintBase::OnParentSceneObjectAdded()
182 if ( NULL == mSceneGraphConstraint &&
189 void ActiveConstraintBase::OnParentSceneObjectRemoved()
191 if ( mSceneGraphConstraint )
193 // Notify base class that the scene-graph constraint is being removed
194 OnSceneObjectRemove();
196 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
197 mSceneGraphConstraint = NULL;
201 void ActiveConstraintBase::BeginRemove()
203 // Stop observing the remaining proxies
206 // Discard all proxy pointers
209 const SceneGraph::PropertyOwner* propertyOwner = mTargetProxy ? mTargetProxy->GetSceneObject() : NULL;
211 if ( propertyOwner &&
212 mSceneGraphConstraint )
214 // Notify base class that the scene-graph constraint is being removed
215 OnSceneObjectRemove();
217 // Remove from scene-graph
218 RemoveConstraintMessage( mEventToUpdate, *propertyOwner, *(mSceneGraphConstraint) );
220 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
221 mSceneGraphConstraint = NULL;
225 ProxyObject* ActiveConstraintBase::GetParent()
230 bool ActiveConstraintBase::Supports( Capability capability ) const
232 return false; // switch-off support for dynamic properties
235 Dali::Handle ActiveConstraintBase::GetTargetObject()
237 return Dali::Handle( mTargetProxy );
240 Property::Index ActiveConstraintBase::GetTargetProperty()
242 return mTargetPropertyIndex;
245 void ActiveConstraintBase::SetWeight( float weight )
247 if ( mSceneGraphConstraint )
249 BakeWeightMessage( mEventToUpdate, *mSceneGraphConstraint, weight );
253 mOffstageWeight = weight;
257 float ActiveConstraintBase::GetCurrentWeight() const
259 float currentWeight( mOffstageWeight );
261 if ( mSceneGraphConstraint )
263 currentWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
266 return currentWeight;
269 ActiveConstraintSignalType& ActiveConstraintBase::AppliedSignal()
271 return mAppliedSignal;
274 bool ActiveConstraintBase::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
276 bool connected( true );
277 ActiveConstraintBase* constraint = dynamic_cast<ActiveConstraintBase*>(object);
279 if ( 0 == strcmp( signalName.c_str(), SIGNAL_APPLIED ) )
281 constraint->AppliedSignal().Connect( tracker, functor );
285 // signalName does not match any signal
292 void ActiveConstraintBase::SetAlphaFunction( AlphaFunction alphaFunc )
294 mAlphaFunction = alphaFunc;
297 AlphaFunction ActiveConstraintBase::GetAlphaFunction() const
299 return mAlphaFunction;
302 void ActiveConstraintBase::SetRemoveAction( ActiveConstraintBase::RemoveAction action )
304 mRemoveAction = action;
307 ActiveConstraintBase::RemoveAction ActiveConstraintBase::GetRemoveAction() const
309 return mRemoveAction;
312 void ActiveConstraintBase::SetTag(const unsigned int tag)
317 unsigned int ActiveConstraintBase::GetTag() const
322 unsigned int ActiveConstraintBase::GetDefaultPropertyCount() const
324 return DEFAULT_PROPERTY_COUNT;
327 void ActiveConstraintBase::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
329 indices.reserve( DEFAULT_PROPERTY_COUNT );
331 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
333 indices.push_back( i );
337 const char* ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const
339 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
341 return DEFAULT_PROPERTY_NAMES[index];
349 Property::Index ActiveConstraintBase::GetDefaultPropertyIndex( const std::string& name ) const
351 Property::Index index = Property::INVALID_INDEX;
353 // Only one name to compare with...
354 if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_NAMES[0] ) ) // dont want to convert rhs to string
362 bool ActiveConstraintBase::IsDefaultPropertyWritable( Property::Index index ) const
364 return true; // All default properties are currently writable
367 bool ActiveConstraintBase::IsDefaultPropertyAnimatable( Property::Index index ) const
369 return true; // All default properties are currently animatable
372 bool ActiveConstraintBase::IsDefaultPropertyAConstraintInput( Property::Index index ) const
374 return true; // All default properties can currently be used as a constraint input
377 Property::Type ActiveConstraintBase::GetDefaultPropertyType( Property::Index index ) const
379 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
381 return DEFAULT_PROPERTY_TYPES[index];
385 // Index out-of-range
386 return Property::NONE;
390 void ActiveConstraintBase::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
392 if( Dali::ActiveConstraint::WEIGHT == index )
394 SetWeight( propertyValue.Get<float>() );
398 Property::Value ActiveConstraintBase::GetDefaultProperty( Property::Index index ) const
400 Property::Value value;
402 if( Dali::ActiveConstraint::WEIGHT == index )
404 value = GetCurrentWeight();
410 const SceneGraph::PropertyOwner* ActiveConstraintBase::GetSceneObject() const
412 return mSceneGraphConstraint;
415 const SceneGraph::PropertyBase* ActiveConstraintBase::GetSceneObjectAnimatableProperty( Property::Index index ) const
417 DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
419 // This method should only return a property which is part of the scene-graph
420 if ( !mSceneGraphConstraint )
425 return &mSceneGraphConstraint->mWeight;
428 const PropertyInputImpl* ActiveConstraintBase::GetSceneObjectInputProperty( Property::Index index ) const
430 DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
432 // This method should only return a property which is part of the scene-graph
433 if ( !mSceneGraphConstraint )
438 return &mSceneGraphConstraint->mWeight;
441 void ActiveConstraintBase::SceneObjectAdded( ProxyObject& proxy )
443 // Should not be getting callbacks when mSources has been cleared
444 DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
446 if ( NULL == mSceneGraphConstraint &&
453 void ActiveConstraintBase::SceneObjectRemoved( ProxyObject& proxy )
455 // Notify base class that the scene-graph constraint is being removed
456 OnSceneObjectRemove();
458 if ( mSceneGraphConstraint )
460 // Preserve the previous weight
461 mOffstageWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
463 const SceneGraph::PropertyOwner* propertyOwner = mTargetProxy ? mTargetProxy->GetSceneObject() : NULL;
467 // Remove from scene-graph
468 RemoveConstraintMessage( mEventToUpdate, *propertyOwner, *(mSceneGraphConstraint) );
471 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
472 mSceneGraphConstraint = NULL;
476 void ActiveConstraintBase::ProxyDestroyed( ProxyObject& proxy )
478 // Remove proxy pointer from observation set
479 ProxyObjectIter iter = std::find( mObservedProxies.Begin(), mObservedProxies.End(), &proxy );
480 DALI_ASSERT_DEBUG( mObservedProxies.End() != iter );
481 mObservedProxies.Erase( iter );
483 // Stop observing the remaining proxies
486 // Discard all proxy & scene-graph pointers
487 mSceneGraphConstraint = NULL;
492 void ActiveConstraintBase::ObserveProxy( ProxyObject& proxy )
494 ProxyObjectIter iter = std::find( mObservedProxies.Begin(), mObservedProxies.End(), &proxy );
495 if ( mObservedProxies.End() == iter )
497 proxy.AddObserver( *this );
498 mObservedProxies.PushBack( &proxy );
502 void ActiveConstraintBase::StopObservation()
504 const ProxyObjectIter end = mObservedProxies.End();
505 for( ProxyObjectIter iter = mObservedProxies.Begin(); iter != end; ++iter )
507 (*iter)->RemoveObserver( *this );
510 mObservedProxies.Clear();
513 void ActiveConstraintBase::FirstApplyFinished( Object* object )
515 // trust the object is correct as its set in FirstApply (in this same file)
516 ActiveConstraintBase* self = static_cast<ActiveConstraintBase*>( object );
518 // This is necessary when the constraint was not added to scene-graph during the animation
519 self->SetWeight( Dali::ActiveConstraint::FINAL_WEIGHT );
521 // The animation is no longer needed
522 GetImplementation(self->mApplyAnimation).SetFinishedCallback( NULL, NULL );
523 self->mApplyAnimation.Reset();
525 // Chain "Finish" to "Applied" signal
527 if ( !self->mAppliedSignal.Empty() )
529 Dali::ActiveConstraint handle( self );
530 self->mAppliedSignal.Emit( handle );
533 // WARNING - this constraint may now have been deleted; don't do anything else here
536 } // namespace Internal