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