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