(Animation) Added component index to allow animation of separate components of a...
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / animator-connector.h
1 #ifndef __DALI_INTERNAL_ANIMATOR_CONNECTOR_H__
2 #define __DALI_INTERNAL_ANIMATOR_CONNECTOR_H__
3
4 //
5 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
6 //
7 // Licensed under the Flora License, Version 1.0 (the License);
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //     http://floralicense.org/license/
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an AS IS BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19
20 // EXTERNAL INCLUDES
21 #include <boost/function.hpp>
22
23 // INTERNAL INCLUDES
24 #include <dali/internal/event/common/proxy-object.h>
25 #include <dali/internal/event/animation/animator-connector-base.h>
26 #include <dali/internal/event/animation/animation-impl.h>
27 #include <dali/internal/update/common/property-owner.h>
28 #include <dali/internal/update/animation/property-accessor.h>
29 #include <dali/internal/update/animation/property-component-accessor.h>
30 #include <dali/internal/update/animation/scene-graph-animator.h>
31 #include <dali/internal/update/manager/update-manager.h>
32
33 namespace Dali
34 {
35
36 namespace Internal
37 {
38
39 /**
40  * AnimatorConnector is used to connect SceneGraph::Animators for newly created scene-graph objects.
41  *
42  * The scene-graph objects are created by a ProxyObject e.g. Actor is a proxy for SceneGraph::Node.
43  * AnimatorConnector observes the proxy object, in order to detect when a scene-graph object is created.
44  *
45  * SceneGraph::Animators weakly reference scene objects, and are automatically deleted when orphaned.
46  * Therefore the AnimatorConnector is NOT responsible for disconnecting animators.
47  */
48 template < typename PropertyType >
49 class AnimatorConnector : public AnimatorConnectorBase, public ProxyObject::Observer
50 {
51 public:
52
53   typedef boost::function< PropertyType (float, const PropertyType&) > AnimatorFunction;
54   typedef SceneGraph::Animator< PropertyType, PropertyAccessor<PropertyType> > AnimatorType;
55   typedef SceneGraph::AnimatableProperty< PropertyType > PropertyInterfaceType;
56
57   /**
58    * Construct a new animator connector.
59    * @param[in] proxy The proxy for a scene-graph object to animate.
60    * @param[in] propertyIndex The index of a property provided by the object.
61    * @param[in] componentIndex Index to a sub component of a property, for use with Vector2, Vector3 and Vector4 (INVALID_PROPERTY_COMPONENTINDEX to use the whole property)
62    * @param[in] animatorFunction A function used to animate the property.
63    * @param[in] alpha The alpha function to apply.
64    * @param[in] period The time period of the animator.
65    * @return A pointer to a newly allocated animator connector.
66    */
67   static AnimatorConnectorBase* New( ProxyObject& proxy,
68                                      Property::Index propertyIndex,
69                                      int componentIndex,
70                                      const AnimatorFunction& animatorFunction,
71                                      AlphaFunction alpha,
72                                      const TimePeriod& period )
73   {
74     return new AnimatorConnector< PropertyType >( proxy,
75                                                   propertyIndex,
76                                                   componentIndex,
77                                                   animatorFunction,
78                                                   alpha,
79                                                   period );
80   }
81
82   /**
83    * Virtual destructor.
84    */
85   virtual ~AnimatorConnector()
86   {
87     if( mProxy )
88     {
89       mProxy->RemoveObserver( *this );
90     }
91
92     // Removing animators via Animation is not necessary.
93     // The corresponding scene graph animation will destroy any animators that become disconnected.
94   }
95
96   /**
97    * From AnimatorConnectorBase.
98    * This is only expected to be called once, when added to an Animation.
99    */
100   void SetParent( Animation& parent )
101   {
102     DALI_ASSERT_ALWAYS( mParent == NULL && "AnimationConnector already has a parent" );
103     mParent = &parent;
104
105     if( mProxy )
106     {
107       // Connect an animator, if the proxy has added an object to the scene-graph
108       const SceneGraph::PropertyOwner* object = mProxy->GetSceneObject();
109       if( object )
110       {
111         ConnectAnimator( *object );
112       }
113     }
114   }
115
116 private:
117
118   /**
119    * Private constructor; see also AnimatorConnector::New().
120    */
121   AnimatorConnector( ProxyObject& proxy,
122                      Property::Index propertyIndex,
123                      int componentIndex,
124                      const AnimatorFunction& animatorFunction,
125                      AlphaFunction alpha,
126                      const TimePeriod& period )
127   : AnimatorConnectorBase( alpha, period ),
128     mProxy( &proxy ),
129     mPropertyIndex( propertyIndex ),
130     mComponentIndex( componentIndex ),
131     mAnimatorFunction( animatorFunction ),
132     mConnected( false )
133   {
134     proxy.AddObserver( *this );
135   }
136
137   // Undefined
138   AnimatorConnector( const AnimatorConnector& );
139
140   // Undefined
141   AnimatorConnector& operator=( const AnimatorConnector& rhs );
142
143   /**
144    * From ProxyObject::Observer
145    */
146   virtual void SceneObjectAdded( ProxyObject& proxy )
147   {
148     const SceneGraph::PropertyOwner* object = mProxy->GetSceneObject();
149     DALI_ASSERT_DEBUG( NULL != object );
150
151     ConnectAnimator( *object );
152   }
153
154   /**
155    * From ProxyObject::Observer
156    */
157   virtual void SceneObjectRemoved( ProxyObject& proxy )
158   {
159     // Removing animators via Animation is not necessary.
160     // The corresponding scene graph animation will destroy any animators that become disconnected.
161     mConnected = false;
162   }
163
164   /**
165    * From ProxyObject::Observer
166    */
167   virtual void ProxyDestroyed( ProxyObject& proxy )
168   {
169     mConnected = false;
170     mProxy = NULL;
171   }
172
173   /**
174    * Create and connect an animator via update manager
175    */
176   void ConnectAnimator( const SceneGraph::PropertyOwner& object )
177   {
178     DALI_ASSERT_DEBUG( false == mConnected ); // Guard against double connections
179     DALI_ASSERT_DEBUG( NULL != mParent );
180
181     const SceneGraph::PropertyBase* base = mProxy->GetSceneObjectAnimatableProperty( mPropertyIndex );
182
183     const PropertyInterfaceType* sceneProperty = dynamic_cast< const PropertyInterfaceType* >( base );
184     DALI_ASSERT_DEBUG( NULL != sceneProperty && "Animating property with invalid type" );
185
186     SceneGraph::AnimatorBase* animator = AnimatorType::New( *sceneProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
187     DALI_ASSERT_DEBUG( NULL != animator );
188
189     const SceneGraph::Animation* animation = mParent->GetSceneObject();
190     DALI_ASSERT_DEBUG( NULL != animation );
191
192     AddAnimatorMessage( mParent->GetUpdateManager().GetEventToUpdate(), *animation, *animator, object );
193
194     mConnected = true; // not really necessary, but useful for asserts
195   }
196
197 protected:
198
199   ProxyObject* mProxy; ///< Not owned by the animator connector. Valid until ProxyDestroyed() is called.
200
201   Property::Index mPropertyIndex;
202
203   int mComponentIndex;
204
205   AnimatorFunction mAnimatorFunction;
206
207   bool mConnected; ///< Used to guard against double connections
208 };
209
210 /**
211  * Variant which allows float components to be animated individually.
212  */
213 template <>
214 class AnimatorConnector<float> : public AnimatorConnectorBase, public ProxyObject::Observer
215 {
216 public:
217
218   typedef boost::function< float (float, const float&) > AnimatorFunction;
219   typedef SceneGraph::Animator< float, PropertyAccessor<float> > AnimatorType;
220
221   /**
222    * Construct a new animator connector.
223    * @param[in] proxy The proxy for a scene-graph object to animate.
224    * @param[in] propertyIndex The index of a property provided by the object.
225    * @param[in] componentIndex Index to a sub component of a property, for use with Vector2, Vector3 and Vector4
226    * @param[in] animatorFunction A function used to animate the property.
227    * @param[in] alpha The alpha function to apply.
228    * @param[in] period The time period of the animator.
229    * @return A pointer to a newly allocated animator connector.
230    */
231   static AnimatorConnectorBase* New( ProxyObject& proxy,
232                                      Property::Index propertyIndex,
233                                      int componentIndex,
234                                      const AnimatorFunction& animatorFunction,
235                                      AlphaFunction alpha,
236                                      const TimePeriod& period )
237   {
238     return new AnimatorConnector<float>( proxy,
239                                          propertyIndex,
240                                          componentIndex,
241                                          animatorFunction,
242                                          alpha,
243                                          period );
244   }
245
246   /**
247    * Virtual destructor.
248    */
249   virtual ~AnimatorConnector()
250   {
251     if( mProxy )
252     {
253       mProxy->RemoveObserver( *this );
254     }
255
256     // Removing animators via Animation is not necessary.
257     // The corresponding scene graph animation will destroy any animators that become disconnected.
258   }
259
260   /**
261    * From AnimatorConnectorBase.
262    * This is only expected to be called once, when added to an Animation.
263    */
264   void SetParent( Animation& parent )
265   {
266     DALI_ASSERT_ALWAYS( mParent == NULL && "AnimationConnector already has a parent");
267     mParent = &parent;
268
269     if( mProxy )
270     {
271       // Connect an animator, if the proxy has added an object to the scene-graph
272       const SceneGraph::PropertyOwner* object = mProxy->GetSceneObject();
273       if( object )
274       {
275         ConnectAnimator( *object );
276       }
277     }
278   }
279
280 private:
281
282   /**
283    * Private constructor; see also AnimatorConnector::New().
284    */
285   AnimatorConnector( ProxyObject& proxy,
286                      Property::Index propertyIndex,
287                      int componentIndex,
288                      const AnimatorFunction& animatorFunction,
289                      AlphaFunction alpha,
290                      const TimePeriod& period )
291   : AnimatorConnectorBase( alpha, period ),
292     mProxy( &proxy ),
293     mPropertyIndex( propertyIndex ),
294     mComponentIndex( componentIndex ),
295     mAnimatorFunction( animatorFunction ),
296     mConnected( false )
297   {
298     proxy.AddObserver( *this );
299   }
300
301   // Undefined
302   AnimatorConnector( const AnimatorConnector& );
303
304   // Undefined
305   AnimatorConnector& operator=( const AnimatorConnector& rhs );
306
307   /**
308    * From ProxyObject::Observer
309    */
310   virtual void SceneObjectAdded( ProxyObject& proxy )
311   {
312     const SceneGraph::PropertyOwner* object = mProxy->GetSceneObject();
313     DALI_ASSERT_DEBUG( NULL != object );
314
315     ConnectAnimator( *object );
316   }
317
318   /**
319    * From ProxyObject::Observer
320    */
321   virtual void SceneObjectRemoved( ProxyObject& proxy )
322   {
323     // Removing animators via Animation is not necessary.
324     // The corresponding scene graph animation will destroy any animators that become disconnected.
325     mConnected = false;
326   }
327
328   /**
329    * From ProxyObject::Observer
330    */
331   virtual void ProxyDestroyed( ProxyObject& proxy )
332   {
333     mConnected = false;
334     mProxy = NULL;
335   }
336
337   /**
338    * Create and connect an animator via update manager
339    */
340   void ConnectAnimator( const SceneGraph::PropertyOwner& object )
341   {
342     DALI_ASSERT_DEBUG( false == mConnected ); // Guard against double connections
343     DALI_ASSERT_DEBUG( NULL != mParent );
344
345     const SceneGraph::PropertyBase* base = mProxy->GetSceneObjectAnimatableProperty( mPropertyIndex );
346     DALI_ASSERT_DEBUG( NULL != base );
347
348     SceneGraph::AnimatorBase* animator( NULL );
349
350     const int componentIndex = mProxy->GetPropertyComponentIndex( mPropertyIndex );
351     if( componentIndex != Property::INVALID_COMPONENT_INDEX )
352     {
353       mComponentIndex = componentIndex;
354     }
355
356     if ( Property::INVALID_COMPONENT_INDEX == mComponentIndex )
357     {
358       // Not a Vector3 or Vector4 component, expecting float type
359       DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == base->GetType() );
360
361       typedef SceneGraph::AnimatableProperty< float > PropertyInterfaceType;
362
363       const PropertyInterfaceType* sceneProperty = dynamic_cast< const PropertyInterfaceType* >( base );
364       DALI_ASSERT_DEBUG( NULL != sceneProperty );
365
366       animator = AnimatorType::New( *sceneProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
367     }
368     else
369     {
370       // Expecting Vector3 or Vector4 type
371
372       if ( PropertyTypes::Get< Vector3 >() == base->GetType() )
373       {
374         // Animate float component of Vector3 property
375         typedef SceneGraph::AnimatableProperty< Vector3 > PropertyInterfaceType;
376
377         const PropertyInterfaceType* sceneProperty = dynamic_cast< const PropertyInterfaceType* >( base );
378         DALI_ASSERT_DEBUG( NULL != sceneProperty );
379
380         if ( 0 == mComponentIndex )
381         {
382           typedef SceneGraph::Animator< float, PropertyComponentAccessorX<Vector3> > Vector3AnimatorType;
383           animator = Vector3AnimatorType::New( *sceneProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
384         }
385         else if ( 1 == mComponentIndex )
386         {
387           typedef SceneGraph::Animator< float, PropertyComponentAccessorY<Vector3> > Vector3AnimatorType;
388           animator = Vector3AnimatorType::New( *sceneProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
389         }
390         else if ( 2 == mComponentIndex )
391         {
392           typedef SceneGraph::Animator< float, PropertyComponentAccessorZ<Vector3> > Vector3AnimatorType;
393           animator = Vector3AnimatorType::New( *sceneProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
394         }
395       }
396       else if ( PropertyTypes::Get< Vector4 >() == base->GetType() )
397       {
398         // Animate float component of Vector4 property
399         typedef SceneGraph::AnimatableProperty< Vector4 > PropertyInterfaceType;
400
401         const PropertyInterfaceType* sceneProperty = dynamic_cast< const PropertyInterfaceType* >( base );
402         DALI_ASSERT_DEBUG( NULL != sceneProperty );
403
404         if ( 0 == mComponentIndex )
405         {
406           typedef SceneGraph::Animator< float, PropertyComponentAccessorX<Vector4> > Vector4AnimatorType;
407           animator = Vector4AnimatorType::New( *sceneProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
408         }
409         else if ( 1 == mComponentIndex )
410         {
411           typedef SceneGraph::Animator< float, PropertyComponentAccessorY<Vector4> > Vector4AnimatorType;
412           animator = Vector4AnimatorType::New( *sceneProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
413         }
414         else if ( 2 == mComponentIndex )
415         {
416           typedef SceneGraph::Animator< float, PropertyComponentAccessorZ<Vector4> > Vector4AnimatorType;
417           animator = Vector4AnimatorType::New( *sceneProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
418         }
419         else if ( 3 == mComponentIndex )
420         {
421           typedef SceneGraph::Animator< float, PropertyComponentAccessorW<Vector4> > Vector4AnimatorType;
422           animator = Vector4AnimatorType::New( *sceneProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
423         }
424       }
425     }
426
427     DALI_ASSERT_DEBUG( NULL != animator && "Animating property with invalid type" );
428
429     const SceneGraph::Animation* animation = mParent->GetSceneObject();
430     DALI_ASSERT_DEBUG( NULL != animation );
431
432     AddAnimatorMessage( mParent->GetUpdateManager().GetEventToUpdate(), *animation, *animator, object );
433
434     mConnected = true; // not really necessary, but useful for asserts
435   }
436
437 protected:
438
439   ProxyObject* mProxy; ///< Not owned by the animator connector. Valid until ProxyDestroyed() is called.
440
441   Property::Index mPropertyIndex;
442
443   int mComponentIndex;
444
445   AnimatorFunction mAnimatorFunction;
446
447   bool mConnected; ///< Used to guard against double connections
448 };
449
450 } // namespace Internal
451
452 } // namespace Dali
453
454 #endif // __DALI_INTERNAL_ANIMATOR_CONNECTOR_H__