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 // not directly creatable
50 TypeRegistration mType( typeid(Dali::ActiveConstraint), typeid(Dali::Handle), Create );
52 SignalConnectorType signalConnector1( mType, Dali::ActiveConstraint::SIGNAL_APPLIED, &ActiveConstraintBase::DoConnectSignal );
57 namespace // unnamed namespace
61 * We want to discourage the use of property strings (minimize string comparisons),
62 * particularly for the default properties.
64 const std::string DEFAULT_PROPERTY_NAMES[] =
68 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_NAMES ) / sizeof( std::string );
70 const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
72 Property::FLOAT // WEIGHT
75 } // unnamed namespace
77 ActiveConstraintBase::ActiveConstraintBase( EventToUpdate& eventToUpdate, Property::Index targetPropertyIndex, SourceContainer& sources, unsigned int sourceCount )
78 : mEventToUpdate( eventToUpdate ),
79 mTargetPropertyIndex( targetPropertyIndex ),
81 mSourceCount( sourceCount ),
84 mSceneGraphConstraint( NULL ),
85 mCustomWeight( NULL ),
86 mOffstageWeight( Dali::ActiveConstraint::DEFAULT_WEIGHT ),
87 mAlphaFunction( Dali::Constraint::DEFAULT_ALPHA_FUNCTION ),
88 mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
92 // Skip init when any of the proxy objects have been destroyed
93 if ( mSources.size() != mSourceCount )
95 // Discard all proxy pointers
100 // Observe the objects providing properties
101 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
103 if ( OBJECT_PROPERTY == iter->sourceType )
105 DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" );
107 ObserveProxy( *(iter->object) );
112 ActiveConstraintBase::~ActiveConstraintBase()
116 // Disconnect from internal animation signals
117 if ( mApplyAnimation )
119 GetImplementation(mApplyAnimation).SetFinishedCallback( NULL, NULL );
123 void ActiveConstraintBase::SetCustomWeightObject( ProxyObject& weightObject, Property::Index weightIndex )
125 const SceneGraph::PropertyBase* base = weightObject.GetSceneObjectAnimatableProperty( weightIndex );
126 const SceneGraph::AnimatableProperty<float>* sceneProperty = dynamic_cast< const SceneGraph::AnimatableProperty<float>* >( base );
130 mCustomWeight = sceneProperty;
132 ObserveProxy( weightObject );
136 void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime )
138 DALI_ASSERT_ALWAYS( NULL == mTargetProxy && "Parent of ActiveConstraint already set" );
140 // No need to do anything, if the source objects are gone
141 if( mSources.size() == mSourceCount )
143 mTargetProxy = &parent;
148 if ( applyTime.durationSeconds > 0.0f )
150 DALI_ASSERT_DEBUG( !mApplyAnimation );
155 // Automatically animate (increase) the weight, until the constraint is fully applied
156 mApplyAnimation = Dali::Animation::New( applyTime.delaySeconds + applyTime.durationSeconds );
157 Dali::ActiveConstraint self( this );
158 mApplyAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::WEIGHT ), Dali::ActiveConstraint::FINAL_WEIGHT, mAlphaFunction, applyTime );
159 mApplyAnimation.Play();
161 // Chain "Finish" to "Applied" signal
162 GetImplementation(mApplyAnimation).SetFinishedCallback( &ActiveConstraintBase::FirstApplyFinished, this );
166 void ActiveConstraintBase::OnParentDestroyed()
168 // Stop observing the remaining proxies
171 // Discard all proxy pointers
176 void ActiveConstraintBase::OnParentSceneObjectAdded()
178 if ( NULL == mSceneGraphConstraint &&
185 void ActiveConstraintBase::OnParentSceneObjectRemoved()
187 if ( mSceneGraphConstraint )
189 // Notify base class that the scene-graph constraint is being removed
190 OnSceneObjectRemove();
192 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
193 mSceneGraphConstraint = NULL;
197 void ActiveConstraintBase::BeginRemove()
199 // Stop observing the remaining proxies
202 // Discard all proxy pointers
205 const SceneGraph::PropertyOwner* propertyOwner = mTargetProxy ? mTargetProxy->GetSceneObject() : NULL;
207 if ( propertyOwner &&
208 mSceneGraphConstraint )
210 // Notify base class that the scene-graph constraint is being removed
211 OnSceneObjectRemove();
213 // Remove from scene-graph
214 RemoveConstraintMessage( mEventToUpdate, *propertyOwner, *(mSceneGraphConstraint) );
216 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
217 mSceneGraphConstraint = NULL;
221 ProxyObject* ActiveConstraintBase::GetParent()
226 bool ActiveConstraintBase::Supports( Capability capability ) const
228 return false; // switch-off support for dynamic properties
231 Dali::Handle ActiveConstraintBase::GetTargetObject()
233 return Dali::Handle( mTargetProxy );
236 Property::Index ActiveConstraintBase::GetTargetProperty()
238 return mTargetPropertyIndex;
241 void ActiveConstraintBase::SetWeight( float weight )
243 if ( mSceneGraphConstraint )
245 BakeWeightMessage( mEventToUpdate, *mSceneGraphConstraint, weight );
249 mOffstageWeight = weight;
253 float ActiveConstraintBase::GetCurrentWeight() const
255 float currentWeight( mOffstageWeight );
257 if ( mSceneGraphConstraint )
259 currentWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
262 return currentWeight;
265 ActiveConstraintSignalV2& ActiveConstraintBase::AppliedSignal()
267 return mAppliedSignal;
270 bool ActiveConstraintBase::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
272 bool connected( true );
273 ActiveConstraintBase* constraint = dynamic_cast<ActiveConstraintBase*>(object);
275 if ( Dali::ActiveConstraint::SIGNAL_APPLIED == signalName )
277 constraint->AppliedSignal().Connect( tracker, functor );
281 // signalName does not match any signal
288 void ActiveConstraintBase::SetAlphaFunction( AlphaFunction alphaFunc )
290 mAlphaFunction = alphaFunc;
293 AlphaFunction ActiveConstraintBase::GetAlphaFunction() const
295 return mAlphaFunction;
298 void ActiveConstraintBase::SetRemoveAction( ActiveConstraintBase::RemoveAction action )
300 mRemoveAction = action;
303 ActiveConstraintBase::RemoveAction ActiveConstraintBase::GetRemoveAction() const
305 return mRemoveAction;
308 void ActiveConstraintBase::SetTag(const unsigned int tag)
313 unsigned int ActiveConstraintBase::GetTag() const
318 bool ActiveConstraintBase::IsSceneObjectRemovable() const
320 return true; // The constraint removed when target SceneGraph::PropertyOwner is destroyed
323 unsigned int ActiveConstraintBase::GetDefaultPropertyCount() const
325 return DEFAULT_PROPERTY_COUNT;
328 void ActiveConstraintBase::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
330 indices.reserve( DEFAULT_PROPERTY_COUNT );
332 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
334 indices.push_back( i );
338 const std::string& ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const
340 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
342 return DEFAULT_PROPERTY_NAMES[index];
346 // index out of range..return empty string
347 static const std::string INVALID_PROPERTY_NAME;
348 return INVALID_PROPERTY_NAME;
352 Property::Index ActiveConstraintBase::GetDefaultPropertyIndex( const std::string& name ) const
354 Property::Index index = Property::INVALID_INDEX;
356 // Only one name to compare with...
357 if ( name == DEFAULT_PROPERTY_NAMES[0] )
365 bool ActiveConstraintBase::IsDefaultPropertyWritable( Property::Index index ) const
367 return true; // All default properties are currently writable
370 bool ActiveConstraintBase::IsDefaultPropertyAnimatable( Property::Index index ) const
372 return true; // All default properties are currently animatable
375 bool ActiveConstraintBase::IsDefaultPropertyAConstraintInput( Property::Index index ) const
377 return true; // All default properties can currently be used as a constraint input
380 Property::Type ActiveConstraintBase::GetDefaultPropertyType( Property::Index index ) const
382 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
384 return DEFAULT_PROPERTY_TYPES[index];
388 // Index out-of-range
389 return Property::NONE;
393 void ActiveConstraintBase::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
397 case Dali::ActiveConstraint::WEIGHT:
399 SetWeight( propertyValue.Get<float>() );
405 DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
411 void ActiveConstraintBase::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
413 DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties"); // should not come here
416 Property::Value ActiveConstraintBase::GetDefaultProperty( Property::Index index ) const
418 Property::Value value;
422 case Dali::ActiveConstraint::WEIGHT:
424 value = GetCurrentWeight();
430 DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
438 void ActiveConstraintBase::InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
440 DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties" ); // should not come here
443 const SceneGraph::PropertyOwner* ActiveConstraintBase::GetSceneObject() const
445 return mSceneGraphConstraint;
448 const SceneGraph::PropertyBase* ActiveConstraintBase::GetSceneObjectAnimatableProperty( Property::Index index ) const
450 DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
452 // This method should only return a property which is part of the scene-graph
453 if ( !mSceneGraphConstraint )
458 return &mSceneGraphConstraint->mWeight;
461 const PropertyInputImpl* ActiveConstraintBase::GetSceneObjectInputProperty( Property::Index index ) const
463 DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
465 // This method should only return a property which is part of the scene-graph
466 if ( !mSceneGraphConstraint )
471 return &mSceneGraphConstraint->mWeight;
474 void ActiveConstraintBase::SceneObjectAdded( ProxyObject& proxy )
476 // Should not be getting callbacks when mSources has been cleared
477 DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
479 if ( NULL == mSceneGraphConstraint &&
486 void ActiveConstraintBase::SceneObjectRemoved( ProxyObject& proxy )
488 // Notify base class that the scene-graph constraint is being removed
489 OnSceneObjectRemove();
491 if ( mSceneGraphConstraint )
493 // Preserve the previous weight
494 mOffstageWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
496 const SceneGraph::PropertyOwner* propertyOwner = mTargetProxy ? mTargetProxy->GetSceneObject() : NULL;
500 // Remove from scene-graph
501 RemoveConstraintMessage( mEventToUpdate, *propertyOwner, *(mSceneGraphConstraint) );
504 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
505 mSceneGraphConstraint = NULL;
509 void ActiveConstraintBase::ProxyDestroyed( ProxyObject& proxy )
511 // Remove proxy pointer from observation set
512 ProxyObjectIter iter = std::find( mObservedProxies.Begin(), mObservedProxies.End(), &proxy );
513 DALI_ASSERT_DEBUG( mObservedProxies.End() != iter );
514 mObservedProxies.Erase( iter );
516 // Stop observing the remaining proxies
519 // Discard all proxy & scene-graph pointers
520 mSceneGraphConstraint = NULL;
525 void ActiveConstraintBase::ObserveProxy( ProxyObject& proxy )
527 ProxyObjectIter iter = std::find( mObservedProxies.Begin(), mObservedProxies.End(), &proxy );
528 if ( mObservedProxies.End() == iter )
530 proxy.AddObserver( *this );
531 mObservedProxies.PushBack( &proxy );
535 void ActiveConstraintBase::StopObservation()
537 const ProxyObjectIter end = mObservedProxies.End();
538 for( ProxyObjectIter iter = mObservedProxies.Begin(); iter != end; ++iter )
540 (*iter)->RemoveObserver( *this );
543 mObservedProxies.Clear();
546 void ActiveConstraintBase::FirstApplyFinished( Object* object )
548 // trust the object is correct as its set in FirstApply (in this same file)
549 ActiveConstraintBase* self = static_cast<ActiveConstraintBase*>( object );
551 // This is necessary when the constraint was not added to scene-graph during the animation
552 self->SetWeight( Dali::ActiveConstraint::FINAL_WEIGHT );
554 // The animation is no longer needed
555 GetImplementation(self->mApplyAnimation).SetFinishedCallback( NULL, NULL );
556 self->mApplyAnimation.Reset();
558 // Chain "Finish" to "Applied" signal
560 if ( !self->mAppliedSignal.Empty() )
562 Dali::ActiveConstraint handle( self );
563 self->mAppliedSignal.Emit( handle );
566 // WARNING - this constraint may now have been deleted; don't do anything else here
569 } // namespace Internal