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