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