Added tag ( id ) to Constraints so they can be identified ( and removed ) by its...
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / active-constraint-base.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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
7 //
8 //     http://floralicense.org/license/
9 //
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.
15 //
16
17 // CLASS HEADER
18 #include <dali/internal/event/animation/active-constraint-base.h>
19
20 // INTERNAL INCLUDES
21 #include <dali/public-api/animation/active-constraint.h>
22 #include <dali/public-api/object/handle.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/internal/common/event-to-update.h>
25 #include <dali/internal/event/animation/animation-impl.h>
26 #include <dali/internal/update/common/animatable-property.h>
27 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
28 #include <dali/internal/update/common/property-owner-messages.h>
29
30 using Dali::Internal::SceneGraph::AnimatableProperty;
31
32 namespace Dali
33 {
34
35 const Property::Index ActiveConstraint::WEIGHT = 0;
36
37 namespace Internal
38 {
39
40 namespace // unnamed namespace
41 {
42
43 BaseHandle Create()
44 {
45   // not directly creatable
46   return BaseHandle();
47 }
48
49 TypeRegistration mType( typeid(Dali::ActiveConstraint), typeid(Dali::Handle), Create );
50
51 SignalConnectorType signalConnector1( mType, Dali::ActiveConstraint::SIGNAL_APPLIED, &ActiveConstraintBase::DoConnectSignal );
52
53 }
54
55
56 namespace // unnamed namespace
57 {
58
59 /**
60  * We want to discourage the use of property strings (minimize string comparisons),
61  * particularly for the default properties.
62  */
63 const std::string DEFAULT_PROPERTY_NAMES[] =
64 {
65   "weight"
66 };
67 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_NAMES ) / sizeof( std::string );
68
69 const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
70 {
71   Property::FLOAT // WEIGHT
72 };
73
74 } // unnamed namespace
75
76 ActiveConstraintBase::ActiveConstraintBase( EventToUpdate& eventToUpdate, Property::Index targetPropertyIndex )
77 : mEventToUpdate( eventToUpdate ),
78   mTargetPropertyIndex( targetPropertyIndex ),
79   mTargetProxy( NULL ),
80   mSceneGraphConstraint( NULL ),
81   mOffstageWeight( Dali::ActiveConstraint::DEFAULT_WEIGHT ),
82   mRemoveTime( 0.0f ),
83   mAlphaFunction( Dali::Constraint::DEFAULT_ALPHA_FUNCTION ),
84   mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
85   mTag(0),
86   mApplyAnimation(),
87   mRemoveAnimation()
88 {
89 }
90
91 ActiveConstraintBase::~ActiveConstraintBase()
92 {
93   // Disconnect from internal animation signals
94
95   if ( mApplyAnimation )
96   {
97     GetImplementation(mApplyAnimation).SetFinishedCallback( NULL, NULL );
98   }
99
100   if( mRemoveAnimation )
101   {
102     GetImplementation(mRemoveAnimation).SetFinishedCallback( NULL, NULL );
103   }
104 }
105
106 void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime, ActiveConstraintCallbackType* callback )
107 {
108   // Notify derived classes
109   OnFirstApply( parent );
110
111   if ( applyTime.durationSeconds > 0.0f )
112   {
113     DALI_ASSERT_DEBUG( !mApplyAnimation );
114
115     // Set start weight
116     SetWeight( 0.0f );
117
118     // Automatically animate (increase) the weight, until the constraint is fully applied
119     mApplyAnimation = Dali::Animation::New( applyTime.delaySeconds + applyTime.durationSeconds );
120     Dali::ActiveConstraint self( this );
121     mApplyAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::WEIGHT ), Dali::ActiveConstraint::FINAL_WEIGHT, mAlphaFunction, applyTime );
122     mApplyAnimation.Play();
123
124     // Chain "Finish" to "Applied" signal
125     GetImplementation(mApplyAnimation).SetFinishedCallback( &ActiveConstraintBase::FirstApplyFinished, this );
126   }
127 }
128
129 void ActiveConstraintBase::BeginRemove()
130 {
131   // Notify derived classes
132   OnBeginRemove();
133
134   // Remove gradually by animating weight down to zero
135   if ( mRemoveTime.durationSeconds > 0.0f )
136   {
137     // Stop baking behaviour from interfering with remove animation
138     if ( mSceneGraphConstraint )
139     {
140       // Immediately remove from scene-graph
141       SetRemoveActionMessage( mEventToUpdate, *mSceneGraphConstraint, Dali::Constraint::Discard );
142     }
143
144     // Interrupt ongoing apply-animations
145     if ( mApplyAnimation )
146     {
147       mApplyAnimation.Stop();
148     }
149
150     // Reduce the weight to zero
151     mRemoveAnimation = Dali::Animation::New( mRemoveTime.delaySeconds + mRemoveTime.durationSeconds );
152     Dali::ActiveConstraint self( this );
153     mRemoveAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::WEIGHT ), 0.0f, mAlphaFunction, mRemoveTime );
154     mRemoveAnimation.Play();
155
156     // Finish removal when animation ends
157     GetImplementation(mRemoveAnimation).SetFinishedCallback( &ActiveConstraintBase::OnRemoveFinished, this );
158   }
159   else
160   {
161     OnRemoveFinished( this );
162   }
163 }
164
165 bool ActiveConstraintBase::IsRemoving()
166 {
167   return mRemoveAnimation;
168 }
169
170 ProxyObject* ActiveConstraintBase::GetParent()
171 {
172   return mTargetProxy;
173 }
174
175 bool ActiveConstraintBase::Supports( Capability capability ) const
176 {
177   return false; // switch-off support for dynamic properties
178 }
179
180 Dali::Handle ActiveConstraintBase::GetTargetObject()
181 {
182   return Dali::Handle( mTargetProxy );
183 }
184
185 Property::Index ActiveConstraintBase::GetTargetProperty()
186 {
187   return mTargetPropertyIndex;
188 }
189
190 void ActiveConstraintBase::SetWeight( float weight )
191 {
192   if ( mSceneGraphConstraint )
193   {
194     BakeWeightMessage( mEventToUpdate, *mSceneGraphConstraint, weight );
195   }
196   else
197   {
198     mOffstageWeight = weight;
199   }
200 }
201
202 float ActiveConstraintBase::GetCurrentWeight() const
203 {
204   float currentWeight( mOffstageWeight );
205
206   if ( mSceneGraphConstraint )
207   {
208     currentWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
209   }
210
211   return currentWeight;
212 }
213
214 ActiveConstraintSignalV2& ActiveConstraintBase::AppliedSignal()
215 {
216   return mAppliedSignal;
217 }
218
219 bool ActiveConstraintBase::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
220 {
221   bool connected( true );
222   ActiveConstraintBase* constraint = dynamic_cast<ActiveConstraintBase*>(object);
223
224   if ( Dali::ActiveConstraint::SIGNAL_APPLIED == signalName )
225   {
226     constraint->AppliedSignal().Connect( tracker, functor );
227   }
228   else
229   {
230     // signalName does not match any signal
231     connected = false;
232   }
233
234   return connected;
235 }
236
237 void ActiveConstraintBase::SetRemoveTime( TimePeriod removeTime )
238 {
239   mRemoveTime = removeTime;
240 }
241
242 TimePeriod ActiveConstraintBase::GetRemoveTime() const
243 {
244   return mRemoveTime;
245 }
246
247 void ActiveConstraintBase::SetAlphaFunction( AlphaFunction alphaFunc )
248 {
249   mAlphaFunction = alphaFunc;
250 }
251
252 AlphaFunction ActiveConstraintBase::GetAlphaFunction() const
253 {
254   return mAlphaFunction;
255 }
256
257 void ActiveConstraintBase::SetRemoveAction( ActiveConstraintBase::RemoveAction action )
258 {
259   mRemoveAction = action;
260 }
261
262 ActiveConstraintBase::RemoveAction ActiveConstraintBase::GetRemoveAction() const
263 {
264   return mRemoveAction;
265 }
266
267 void ActiveConstraintBase::SetTag(const unsigned int tag)
268 {
269   mTag = tag;
270 }
271
272 unsigned int ActiveConstraintBase::GetTag() const
273 {
274   return mTag;
275 }
276
277
278 bool ActiveConstraintBase::IsSceneObjectRemovable() const
279 {
280   return true; // The constraint removed when target SceneGraph::PropertyOwner is destroyed
281 }
282
283 unsigned int ActiveConstraintBase::GetDefaultPropertyCount() const
284 {
285   return DEFAULT_PROPERTY_COUNT;
286 }
287
288 void ActiveConstraintBase::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
289 {
290   indices.reserve( DEFAULT_PROPERTY_COUNT );
291
292   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
293   {
294     indices.push_back( i );
295   }
296 }
297
298 const std::string& ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const
299 {
300   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
301   {
302     return DEFAULT_PROPERTY_NAMES[index];
303   }
304   else
305   {
306     // index out of range..return empty string
307     static const std::string INVALID_PROPERTY_NAME;
308     return INVALID_PROPERTY_NAME;
309   }
310 }
311
312 Property::Index ActiveConstraintBase::GetDefaultPropertyIndex( const std::string& name ) const
313 {
314   Property::Index index = Property::INVALID_INDEX;
315
316   // Only one name to compare with...
317   if ( name == DEFAULT_PROPERTY_NAMES[0] )
318   {
319     index = 0;
320   }
321
322   return index;
323 }
324
325 bool ActiveConstraintBase::IsDefaultPropertyWritable( Property::Index index ) const
326 {
327   return true; // All default properties are currently writable
328 }
329
330 bool ActiveConstraintBase::IsDefaultPropertyAnimatable( Property::Index index ) const
331 {
332   return true; // All default properties are currently animatable
333 }
334
335 bool ActiveConstraintBase::IsDefaultPropertyAConstraintInput( Property::Index index ) const
336 {
337   return true; // All default properties can currently be used as a constraint input
338 }
339
340 Property::Type ActiveConstraintBase::GetDefaultPropertyType( Property::Index index ) const
341 {
342   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
343   {
344     return DEFAULT_PROPERTY_TYPES[index];
345   }
346   else
347   {
348     // Index out-of-range
349     return Property::NONE;
350   }
351 }
352
353 void ActiveConstraintBase::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
354 {
355   switch ( index )
356   {
357     case Dali::ActiveConstraint::WEIGHT:
358     {
359       SetWeight( propertyValue.Get<float>() );
360       break;
361     }
362
363     default:
364     {
365       DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
366       break;
367     }
368   }
369 }
370
371 void ActiveConstraintBase::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
372 {
373   DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties"); // should not come here
374 }
375
376 Property::Value ActiveConstraintBase::GetDefaultProperty( Property::Index index ) const
377 {
378   Property::Value value;
379
380   switch ( index )
381   {
382     case Dali::ActiveConstraint::WEIGHT:
383     {
384       value = GetCurrentWeight();
385       break;
386     }
387
388     default:
389     {
390       DALI_ASSERT_ALWAYS( false && "ActiveConstraint property out of bounds" ); // should not come here
391       break;
392     }
393   }
394
395   return value;
396 }
397
398 void ActiveConstraintBase::InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
399 {
400   DALI_ASSERT_ALWAYS( false && "ActiveConstraintBase does not have custom properties" ); // should not come here
401 }
402
403 const SceneGraph::PropertyOwner* ActiveConstraintBase::GetSceneObject() const
404 {
405   return mSceneGraphConstraint;
406 }
407
408 const SceneGraph::PropertyBase* ActiveConstraintBase::GetSceneObjectAnimatableProperty( Property::Index index ) const
409 {
410   DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
411
412   // This method should only return a property which is part of the scene-graph
413   if ( !mSceneGraphConstraint )
414   {
415     return NULL;
416   }
417
418   return &mSceneGraphConstraint->mWeight;
419 }
420
421 const PropertyInputImpl* ActiveConstraintBase::GetSceneObjectInputProperty( Property::Index index ) const
422 {
423   DALI_ASSERT_DEBUG( 0 == index ); // only 1 property supported
424
425   // This method should only return a property which is part of the scene-graph
426   if ( !mSceneGraphConstraint )
427   {
428     return NULL;
429   }
430
431   return &mSceneGraphConstraint->mWeight;
432 }
433
434 void ActiveConstraintBase::FirstApplyFinished( Object* object )
435 {
436   ActiveConstraintBase& self = dynamic_cast<ActiveConstraintBase&>( *object );
437
438   // This is necessary when the constraint was not added to scene-graph during the animation
439   self.SetWeight( Dali::ActiveConstraint::FINAL_WEIGHT );
440
441   // The animation is no longer needed
442   GetImplementation(self.mApplyAnimation).SetFinishedCallback( NULL, NULL );
443   self.mApplyAnimation.Reset();
444
445   // Chain "Finish" to "Applied" signal
446
447   if ( !self.mAppliedSignal.Empty() )
448   {
449     Dali::ActiveConstraint handle( &self );
450
451     self.mAppliedSignal.Emit( handle );
452   }
453
454   // WARNING - this constraint may now have been deleted; don't do anything else here
455 }
456
457 void ActiveConstraintBase::OnRemoveFinished( Object* object )
458 {
459   ActiveConstraintBase& self = dynamic_cast<ActiveConstraintBase&>( *object );
460
461   const SceneGraph::PropertyOwner* propertyOwner = self.mTargetProxy ? self.mTargetProxy->GetSceneObject() : NULL;
462
463   if ( propertyOwner &&
464        self.mSceneGraphConstraint )
465   {
466     // Notify base class that the scene-graph constraint is being removed
467     self.OnSceneObjectRemove();
468
469     // Remove from scene-graph
470     RemoveConstraintMessage( self.mEventToUpdate, *propertyOwner, *(self.mSceneGraphConstraint) );
471
472     // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
473     self.mSceneGraphConstraint = NULL;
474   }
475
476   // The animation is no longer needed
477   self.mRemoveAnimation.Reset();
478 }
479
480 } // namespace Internal
481
482 } // namespace Dali