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 )
78 : mEventToUpdate( eventToUpdate ),
79 mTargetPropertyIndex( targetPropertyIndex ),
81 mSceneGraphConstraint( NULL ),
82 mCustomWeight( NULL ),
83 mOffstageWeight( Dali::ActiveConstraint::DEFAULT_WEIGHT ),
85 mAlphaFunction( Dali::Constraint::DEFAULT_ALPHA_FUNCTION ),
86 mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
93 ActiveConstraintBase::~ActiveConstraintBase()
95 // Disconnect from internal animation signals
97 if ( mApplyAnimation )
99 GetImplementation(mApplyAnimation).SetFinishedCallback( NULL, NULL );
102 if( mRemoveAnimation )
104 GetImplementation(mRemoveAnimation).SetFinishedCallback( NULL, NULL );
108 void ActiveConstraintBase::SetCustomWeightObject( ProxyObject& weightObject, Property::Index weightIndex )
110 const SceneGraph::PropertyBase* base = weightObject.GetSceneObjectAnimatableProperty( weightIndex );
111 const SceneGraph::AnimatableProperty<float>* sceneProperty = dynamic_cast< const SceneGraph::AnimatableProperty<float>* >( base );
115 mCustomWeight = sceneProperty;
117 OnCustomWeightSet( weightObject );
121 void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime )
123 // Notify derived classes
124 OnFirstApply( parent );
126 if ( applyTime.durationSeconds > 0.0f )
128 DALI_ASSERT_DEBUG( !mApplyAnimation );
133 // Automatically animate (increase) the weight, until the constraint is fully applied
134 mApplyAnimation = Dali::Animation::New( applyTime.delaySeconds + applyTime.durationSeconds );
135 Dali::ActiveConstraint self( this );
136 mApplyAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::WEIGHT ), Dali::ActiveConstraint::FINAL_WEIGHT, mAlphaFunction, applyTime );
137 mApplyAnimation.Play();
139 // Chain "Finish" to "Applied" signal
140 GetImplementation(mApplyAnimation).SetFinishedCallback( &ActiveConstraintBase::FirstApplyFinished, this );
144 void ActiveConstraintBase::BeginRemove()
146 // Notify derived classes
149 // Remove gradually by animating weight down to zero
150 if ( mRemoveTime.durationSeconds > 0.0f )
152 // Stop baking behaviour from interfering with remove animation
153 if ( mSceneGraphConstraint )
155 // Immediately remove from scene-graph
156 SetRemoveActionMessage( mEventToUpdate, *mSceneGraphConstraint, Dali::Constraint::Discard );
159 // Interrupt ongoing apply-animations
160 if ( mApplyAnimation )
162 mApplyAnimation.Stop();
165 // Reduce the weight to zero
166 mRemoveAnimation = Dali::Animation::New( mRemoveTime.delaySeconds + mRemoveTime.durationSeconds );
167 Dali::ActiveConstraint self( this );
168 mRemoveAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::WEIGHT ), 0.0f, mAlphaFunction, mRemoveTime );
169 mRemoveAnimation.Play();
171 // Finish removal when animation ends
172 GetImplementation(mRemoveAnimation).SetFinishedCallback( &ActiveConstraintBase::OnRemoveFinished, this );
176 OnRemoveFinished( this );
180 bool ActiveConstraintBase::IsRemoving()
182 return mRemoveAnimation;
185 ProxyObject* ActiveConstraintBase::GetParent()
190 bool ActiveConstraintBase::Supports( Capability capability ) const
192 return false; // switch-off support for dynamic properties
195 Dali::Handle ActiveConstraintBase::GetTargetObject()
197 return Dali::Handle( mTargetProxy );
200 Property::Index ActiveConstraintBase::GetTargetProperty()
202 return mTargetPropertyIndex;
205 void ActiveConstraintBase::SetWeight( float weight )
207 if ( mSceneGraphConstraint )
209 BakeWeightMessage( mEventToUpdate, *mSceneGraphConstraint, weight );
213 mOffstageWeight = weight;
217 float ActiveConstraintBase::GetCurrentWeight() const
219 float currentWeight( mOffstageWeight );
221 if ( mSceneGraphConstraint )
223 currentWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
226 return currentWeight;
229 ActiveConstraintSignalV2& ActiveConstraintBase::AppliedSignal()
231 return mAppliedSignal;
234 bool ActiveConstraintBase::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
236 bool connected( true );
237 ActiveConstraintBase* constraint = dynamic_cast<ActiveConstraintBase*>(object);
239 if ( Dali::ActiveConstraint::SIGNAL_APPLIED == signalName )
241 constraint->AppliedSignal().Connect( tracker, functor );
245 // signalName does not match any signal
252 void ActiveConstraintBase::SetRemoveTime( TimePeriod removeTime )
254 mRemoveTime = removeTime;
257 TimePeriod ActiveConstraintBase::GetRemoveTime() const
262 void ActiveConstraintBase::SetAlphaFunction( AlphaFunction alphaFunc )
264 mAlphaFunction = alphaFunc;
267 AlphaFunction ActiveConstraintBase::GetAlphaFunction() const
269 return mAlphaFunction;
272 void ActiveConstraintBase::SetRemoveAction( ActiveConstraintBase::RemoveAction action )
274 mRemoveAction = action;
277 ActiveConstraintBase::RemoveAction ActiveConstraintBase::GetRemoveAction() const
279 return mRemoveAction;
282 void ActiveConstraintBase::SetTag(const unsigned int tag)
287 unsigned int ActiveConstraintBase::GetTag() const
293 bool ActiveConstraintBase::IsSceneObjectRemovable() const
295 return true; // The constraint removed when target SceneGraph::PropertyOwner is destroyed
298 unsigned int ActiveConstraintBase::GetDefaultPropertyCount() const
300 return DEFAULT_PROPERTY_COUNT;
303 void ActiveConstraintBase::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
305 indices.reserve( DEFAULT_PROPERTY_COUNT );
307 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
309 indices.push_back( i );
313 const std::string& ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const
315 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
317 return DEFAULT_PROPERTY_NAMES[index];
321 // index out of range..return empty string
322 static const std::string INVALID_PROPERTY_NAME;
323 return INVALID_PROPERTY_NAME;
327 Property::Index ActiveConstraintBase::GetDefaultPropertyIndex( const std::string& name ) const
329 Property::Index index = Property::INVALID_INDEX;
331 // Only one name to compare with...
332 if ( name == DEFAULT_PROPERTY_NAMES[0] )
340 bool ActiveConstraintBase::IsDefaultPropertyWritable( Property::Index index ) const
342 return true; // All default properties are currently writable
345 bool ActiveConstraintBase::IsDefaultPropertyAnimatable( Property::Index index ) const
347 return true; // All default properties are currently animatable
350 bool ActiveConstraintBase::IsDefaultPropertyAConstraintInput( Property::Index index ) const
352 return true; // All default properties can currently be used as a constraint input
355 Property::Type ActiveConstraintBase::GetDefaultPropertyType( Property::Index index ) const
357 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
359 return DEFAULT_PROPERTY_TYPES[index];
363 // Index out-of-range
364 return Property::NONE;
368 void ActiveConstraintBase::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
372 case Dali::ActiveConstraint::WEIGHT:
374 SetWeight( propertyValue.Get<float>() );
380 DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
386 void ActiveConstraintBase::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
388 DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties"); // should not come here
391 Property::Value ActiveConstraintBase::GetDefaultProperty( Property::Index index ) const
393 Property::Value value;
397 case Dali::ActiveConstraint::WEIGHT:
399 value = GetCurrentWeight();
405 DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
413 void ActiveConstraintBase::InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
415 DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties" ); // should not come here
418 const SceneGraph::PropertyOwner* ActiveConstraintBase::GetSceneObject() const
420 return mSceneGraphConstraint;
423 const SceneGraph::PropertyBase* ActiveConstraintBase::GetSceneObjectAnimatableProperty( Property::Index index ) const
425 DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
427 // This method should only return a property which is part of the scene-graph
428 if ( !mSceneGraphConstraint )
433 return &mSceneGraphConstraint->mWeight;
436 const PropertyInputImpl* ActiveConstraintBase::GetSceneObjectInputProperty( Property::Index index ) const
438 DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
440 // This method should only return a property which is part of the scene-graph
441 if ( !mSceneGraphConstraint )
446 return &mSceneGraphConstraint->mWeight;
449 void ActiveConstraintBase::FirstApplyFinished( Object* object )
451 ActiveConstraintBase& self = dynamic_cast<ActiveConstraintBase&>( *object );
453 // This is necessary when the constraint was not added to scene-graph during the animation
454 self.SetWeight( Dali::ActiveConstraint::FINAL_WEIGHT );
456 // The animation is no longer needed
457 GetImplementation(self.mApplyAnimation).SetFinishedCallback( NULL, NULL );
458 self.mApplyAnimation.Reset();
460 // Chain "Finish" to "Applied" signal
462 if ( !self.mAppliedSignal.Empty() )
464 Dali::ActiveConstraint handle( &self );
466 self.mAppliedSignal.Emit( handle );
469 // WARNING - this constraint may now have been deleted; don't do anything else here
472 void ActiveConstraintBase::OnRemoveFinished( Object* object )
474 ActiveConstraintBase& self = dynamic_cast<ActiveConstraintBase&>( *object );
476 const SceneGraph::PropertyOwner* propertyOwner = self.mTargetProxy ? self.mTargetProxy->GetSceneObject() : NULL;
478 if ( propertyOwner &&
479 self.mSceneGraphConstraint )
481 // Notify base class that the scene-graph constraint is being removed
482 self.OnSceneObjectRemove();
484 // Remove from scene-graph
485 RemoveConstraintMessage( self.mEventToUpdate, *propertyOwner, *(self.mSceneGraphConstraint) );
487 // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
488 self.mSceneGraphConstraint = NULL;
491 // The animation is no longer needed
492 self.mRemoveAnimation.Reset();
495 } // namespace Internal