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