b3ae1e524653c55b7f16357a7a39def2ccd9788f
[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) 2018 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 // INTERNAL INCLUDES
22 #include <dali/internal/event/animation/animator-connector-base.h>
23 #include <dali/internal/event/animation/animation-impl.h>
24 #include <dali/internal/update/common/property-owner.h>
25 #include <dali/internal/update/animation/property-accessor.h>
26 #include <dali/internal/update/animation/property-component-accessor.h>
27 #include <dali/internal/update/common/property-resetter.h>
28 #include <dali/internal/update/manager/update-manager.h>
29
30 namespace Dali
31 {
32
33 namespace Internal
34 {
35
36 /**
37  * AnimatorConnector is used to connect SceneGraph::Animators and
38  * PropertyResetters for newly created scene-graph objects.
39  *
40  * SceneGraph::Animators weakly reference scene objects, and are automatically deleted when orphaned.
41  * Therefore the AnimatorConnector is NOT responsible for disconnecting animators.
42  */
43 template < typename PropertyType >
44 class AnimatorConnector : public AnimatorConnectorBase
45 {
46 public:
47
48   typedef SceneGraph::Animator< PropertyType, PropertyAccessor<PropertyType> > AnimatorType;
49   typedef SceneGraph::AnimatableProperty< PropertyType > PropertyInterfaceType;
50
51   /**
52    * Construct a new animator connector.
53    * @param[in] object The object for a scene-graph object to animate.
54    * @param[in] propertyIndex The index of a property provided by the object.
55    * @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)
56    * @param[in] animatorFunction A function used to animate the property.
57    * @param[in] alpha The alpha function to apply.
58    * @param[in] period The time period of the animator.
59    * @return A pointer to a newly allocated animator connector.
60    */
61   static AnimatorConnectorBase* New( Object& object,
62                                      Property::Index propertyIndex,
63                                      int componentIndex,
64                                      AnimatorFunctionBase* animatorFunction,
65                                      AlphaFunction alpha,
66                                      const TimePeriod& period )
67   {
68     return new AnimatorConnector< PropertyType >( object,
69                                                   propertyIndex,
70                                                   componentIndex,
71                                                   animatorFunction,
72                                                   alpha,
73                                                   period );
74   }
75
76   /**
77    * Virtual destructor.
78    */
79   virtual ~AnimatorConnector()
80   {
81     if( mObject )
82     {
83       mObject->RemoveObserver( *this );
84     }
85
86     // If there is not a SceneGraph::Animator, the AnimatorConnector is responsible for deleting the mAnimatorFunction
87     // otherwise, the animator function ownership is transferred to the SceneGraph::Animator
88     if( !mAnimator )
89     {
90       delete mAnimatorFunction;
91       mAnimatorFunction = 0;
92     }
93   }
94
95   /**
96    * From AnimatorConnectorBase.
97    * This is only expected to be called once, when added to an Animation.
98    */
99   void SetParent( Animation& parent )
100   {
101     DALI_ASSERT_ALWAYS( mParent == NULL && "AnimationConnector already has a parent" );
102     mParent = &parent;
103
104     if( mObject )
105     {
106       CreateAnimator();
107     }
108   }
109
110 private:
111
112   /**
113    * Private constructor; see also AnimatorConnector::New().
114    */
115   AnimatorConnector( Object& object,
116                      Property::Index propertyIndex,
117                      int componentIndex,
118                      Internal::AnimatorFunctionBase* animatorFunction,
119                      AlphaFunction alpha,
120                      const TimePeriod& period )
121   : AnimatorConnectorBase( object, propertyIndex, componentIndex, alpha, period ),
122     mAnimator(0),
123     mAnimatorFunction( animatorFunction )
124   {
125   }
126
127   // Undefined
128   AnimatorConnector( const AnimatorConnector& );
129
130   // Undefined
131   AnimatorConnector& operator=( const AnimatorConnector& rhs );
132
133   /**
134    * From Object::Observer
135    */
136   virtual void SceneObjectAdded( Object& object )
137   {
138     //If the animator has not been created yet, create it now.
139     if( !mAnimator && mObject )
140     {
141       CreateAnimator();
142     }
143   }
144
145    /**
146    * Helper function to create a Scenegraph::Animator and PropertyResetter and add it to its correspondent
147    * SceneGraph::Animation.
148    *
149    * @note This function will only be called the first time the object is added to the scene or at creation time if
150    * the object was already in the scene
151    */
152   void CreateAnimator()
153   {
154     DALI_ASSERT_DEBUG( mAnimator == NULL );
155     DALI_ASSERT_DEBUG( mAnimatorFunction != NULL );
156     DALI_ASSERT_DEBUG( mParent != NULL );
157
158     //Get the PropertyOwner the animator is going to animate
159     const SceneGraph::PropertyOwner& propertyOwner = mObject->GetSceneObject();
160
161     // Get SceneGraph::BaseProperty
162     const SceneGraph::PropertyBase* baseProperty = mObject->GetSceneObjectAnimatableProperty( mPropertyIndex );
163     DALI_ASSERT_ALWAYS( baseProperty && "Property is not animatable" );
164
165     OwnerPointer<SceneGraph::PropertyResetterBase> resetter;
166
167     // Check if property is a component of another property
168     const int32_t componentIndex = mObject->GetPropertyComponentIndex( mPropertyIndex );
169     if( componentIndex != Property::INVALID_COMPONENT_INDEX )
170     {
171       mComponentIndex = componentIndex;
172     }
173
174     if( mComponentIndex == Property::INVALID_COMPONENT_INDEX )
175     {
176       // Animating the whole property
177
178       // Cast to AnimatableProperty
179       const PropertyInterfaceType* animatableProperty = dynamic_cast< const PropertyInterfaceType* >( baseProperty );
180
181       if( animatableProperty == NULL )
182       {
183         if( baseProperty->IsTransformManagerProperty() )
184         {
185           mAnimator = SceneGraph::AnimatorTransformProperty< PropertyType,TransformManagerPropertyAccessor<PropertyType> >::New( propertyOwner, *baseProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
186           // Don't reset transform manager properties - TransformManager will do it more efficiently
187         }
188         else
189         {
190           DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
191         }
192
193       }
194       else
195       {
196         // Create the animator and resetter
197         mAnimator = AnimatorType::New( propertyOwner, *animatableProperty, mAnimatorFunction,
198                                        mAlphaFunction, mTimePeriod );
199         resetter = SceneGraph::AnimatorResetter::New( propertyOwner, *baseProperty, *mAnimator );
200       }
201     }
202     else
203     {
204       {
205         // Animating a component of the property
206         if ( PropertyTypes::Get< Vector2 >() == baseProperty->GetType() )
207         {
208           // Animate float component of Vector2 property
209
210           // Cast to AnimatableProperty of type Vector2
211           const SceneGraph::AnimatableProperty<Vector2>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector2>* >( baseProperty );
212           DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
213
214           switch( mComponentIndex )
215           {
216             case 0:
217             {
218               mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector2> >::New( propertyOwner,
219                                                                                                    *animatableProperty,
220                                                                                                    mAnimatorFunction,
221                                                                                                    mAlphaFunction,
222                                                                                                    mTimePeriod );
223               break;
224             }
225             case 1:
226             {
227               mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector2> >::New( propertyOwner,
228                                                                                                    *animatableProperty,
229                                                                                                    mAnimatorFunction,
230                                                                                                    mAlphaFunction,
231                                                                                                    mTimePeriod );
232               break;
233             }
234             default:
235             {
236               break;
237             }
238           }
239
240           if( mAnimator != nullptr )
241           {
242             resetter = SceneGraph::AnimatorResetter::New( propertyOwner, *baseProperty, *mAnimator );
243           }
244         }
245
246         else if ( PropertyTypes::Get< Vector3 >() == baseProperty->GetType() )
247         {
248           // Animate float component of Vector3 property
249           // Cast to AnimatableProperty of type Vector3
250           const SceneGraph::AnimatableProperty<Vector3>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector3>* >( baseProperty );
251
252           if( animatableProperty == NULL )
253           {
254             if( baseProperty->IsTransformManagerProperty() )
255             {
256               if( mComponentIndex == 0 )
257               {
258                 mAnimator = SceneGraph::AnimatorTransformProperty< float,TransformManagerPropertyComponentAccessor<Vector3,0> >::New( propertyOwner, *baseProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
259               }
260               else if( mComponentIndex == 1 )
261               {
262                 mAnimator = SceneGraph::AnimatorTransformProperty< float,TransformManagerPropertyComponentAccessor<Vector3,1> >::New( propertyOwner, *baseProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
263               }
264               else if( mComponentIndex == 2 )
265               {
266                 mAnimator = SceneGraph::AnimatorTransformProperty< float,TransformManagerPropertyComponentAccessor<Vector3,2> >::New( propertyOwner, *baseProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
267               }
268             }
269             else
270             {
271               DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
272             }
273             // Don't manually reset transform property - TransformManager will do it more efficiently
274           }
275           else
276           {
277             // Dynamic cast will fail if BaseProperty is not a Vector3 AnimatableProperty
278             DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
279
280             switch( mComponentIndex )
281             {
282               case 0:
283               {
284                 mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector3> >::New( propertyOwner,
285                                                                                                      *animatableProperty,
286                                                                                                      mAnimatorFunction,
287                                                                                                      mAlphaFunction,
288                                                                                                      mTimePeriod );
289                 break;
290               }
291               case 1:
292               {
293                 mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector3> >::New( propertyOwner,
294                                                                                                      *animatableProperty,
295                                                                                                      mAnimatorFunction,
296                                                                                                      mAlphaFunction,
297                                                                                                      mTimePeriod );
298                 break;
299               }
300               case 2:
301               {
302                 mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorZ<Vector3> >::New( propertyOwner,
303                                                                                                      *animatableProperty,
304                                                                                                      mAnimatorFunction,
305                                                                                                      mAlphaFunction,
306                                                                                                      mTimePeriod );
307                 break;
308               }
309               default:
310               {
311                 break;
312               }
313             }
314
315             if( mAnimator != nullptr )
316             {
317               resetter = SceneGraph::AnimatorResetter::New( propertyOwner, *baseProperty, *mAnimator );
318             }
319           }
320         }
321         else if ( PropertyTypes::Get< Vector4 >() == baseProperty->GetType() )
322         {
323           // Animate float component of Vector4 property
324
325           // Cast to AnimatableProperty of type Vector4
326           const SceneGraph::AnimatableProperty<Vector4>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector4>* >( baseProperty );
327
328           //Dynamic cast will fail if BaseProperty is not a Vector4 AnimatableProperty
329           DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
330
331           switch( mComponentIndex )
332           {
333             case 0:
334             {
335               mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector4> >::New( propertyOwner,
336                                                                                                    *animatableProperty,
337                                                                                                    mAnimatorFunction,
338                                                                                                    mAlphaFunction,
339                                                                                                    mTimePeriod );
340               break;
341             }
342             case 1:
343             {
344               mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector4> >::New( propertyOwner,
345                                                                                                    *animatableProperty,
346                                                                                                    mAnimatorFunction,
347                                                                                                    mAlphaFunction,
348                                                                                                    mTimePeriod );
349               break;
350             }
351             case 2:
352             {
353               mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorZ<Vector4> >::New( propertyOwner,
354                                                                                                    *animatableProperty,
355                                                                                                    mAnimatorFunction,
356                                                                                                    mAlphaFunction,
357                                                                                                    mTimePeriod );
358               break;
359             }
360             case 3:
361             {
362               mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorW<Vector4> >::New( propertyOwner,
363                                                                                                    *animatableProperty,
364                                                                                                    mAnimatorFunction,
365                                                                                                    mAlphaFunction,
366                                                                                                    mTimePeriod );
367               break;
368             }
369
370             default:
371             {
372               break;
373             }
374           }
375           if( mAnimator != nullptr )
376           {
377             resetter = SceneGraph::AnimatorResetter::New( propertyOwner, *baseProperty, *mAnimator );
378           }
379         }
380       }
381     }
382
383     DALI_ASSERT_DEBUG( mAnimator != NULL );
384
385     // Add the new SceneGraph::Animator to its correspondent SceneGraph::Animation via message
386     const SceneGraph::Animation* animation = mParent->GetSceneObject();
387     DALI_ASSERT_DEBUG( NULL != animation );
388     AddAnimatorMessage( mParent->GetEventThreadServices(), *animation, *mAnimator );
389
390     // Add the new SceneGraph::PropertyResetter to the update manager via message
391     if( resetter != nullptr )
392     {
393       AddResetterMessage( mParent->GetEventThreadServices().GetUpdateManager(), resetter );
394     }
395   }
396
397 protected:
398
399   SceneGraph::AnimatorBase* mAnimator;
400
401   Internal::AnimatorFunctionBase* mAnimatorFunction;  ///< Owned by the animator connector until an Scenegraph::Animator is created
402 };
403
404
405 } // namespace Internal
406
407 } // namespace Dali
408
409 #endif // __DALI_INTERNAL_ANIMATOR_CONNECTOR_H__