Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / constraint-impl.h
1 #ifndef DALI_INTERNAL_ACTIVE_CONSTRAINT_H
2 #define DALI_INTERNAL_ACTIVE_CONSTRAINT_H
3
4 /*
5  * Copyright (c) 2022 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/common/message.h>
23 #include <dali/internal/event/animation/constraint-base.h>
24 #include <dali/internal/event/animation/constraint-source-impl.h>
25 #include <dali/internal/event/animation/property-constraint-ptr.h>
26 #include <dali/internal/event/common/event-thread-services.h>
27 #include <dali/internal/event/common/object-impl.h>
28 #include <dali/internal/event/common/stage-impl.h>
29 #include <dali/internal/event/common/thread-local-storage.h>
30 #include <dali/internal/update/animation/property-accessor.h>
31 #include <dali/internal/update/animation/property-component-accessor.h>
32 #include <dali/internal/update/animation/scene-graph-constraint.h>
33 #include <dali/internal/update/common/animatable-property.h>
34 #include <dali/internal/update/common/property-owner-messages.h>
35 #include <dali/internal/update/common/property-owner.h>
36 #include <dali/internal/update/common/property-resetter.h>
37 #include <memory>
38
39 namespace Dali
40 {
41 namespace Internal
42 {
43 /**
44  * Connects a constraint which takes another property as an input.
45  */
46 template<typename PropertyType>
47 class Constraint : public ConstraintBase
48 {
49 public:
50   using ConstraintFunctionPtr = typename PropertyConstraintPtr<PropertyType>::Type;
51
52   /**
53    * Construct a new constraint.
54    * @param[in] object The property-owning object.
55    * @param[in] targetIndex The index of the property to constrain.
56    * @param[in] sources The sources of the input properties passed to func.
57    * @param[in] func The constraint function.
58    * @return A newly allocated active-constraint.
59    */
60   static ConstraintBase* New(Object&               object,
61                              Property::Index       targetIndex,
62                              SourceContainer&      sources,
63                              ConstraintFunctionPtr func)
64   {
65     return new Constraint(object, targetIndex, sources, func);
66   }
67
68   /**
69    * Virtual destructor.
70    */
71   ~Constraint() override
72   {
73     // This is not responsible for removing constraints.
74   }
75
76 private:
77   /**
78    * @copydoc ConstraintBase::DoClone()
79    */
80   ConstraintBase* DoClone(Object& object) final
81   {
82     ConstraintFunctionPtr funcPtr(mUserFunction->Clone());
83     return new Constraint(object,
84                           mTargetPropertyIndex,
85                           mSources,
86                           funcPtr);
87   }
88
89   /**
90    * Private constructor; see also Constraint::New().
91    */
92   Constraint(Object&                object,
93              Property::Index        targetIndex,
94              SourceContainer&       sources,
95              ConstraintFunctionPtr& func)
96   : ConstraintBase(object, targetIndex, sources),
97     mUserFunction(func)
98   {
99   }
100
101   // Undefined
102   Constraint()                  = delete;
103   Constraint(const Constraint&) = delete;
104   Constraint& operator=(const Constraint& rhs) = delete;
105
106   /**
107    * @copydoc ConstraintBase::ConnectConstraint()
108    */
109   void ConnectConstraint() final
110   {
111     // Should not come here if target object has been destroyed
112     DALI_ASSERT_DEBUG(nullptr != mTargetObject);
113
114     // Guard against double connections
115     DALI_ASSERT_DEBUG(nullptr == mSceneGraphConstraint);
116
117     SceneGraph::PropertyOwner& targetObject = const_cast<SceneGraph::PropertyOwner&>(mTargetObject->GetSceneObject());
118
119     // Build a container of property-owners, providing the scene-graph properties
120     SceneGraph::PropertyOwnerContainer propertyOwners;
121     propertyOwners.PushBack(&targetObject);
122
123     // Build the constraint function; this requires a scene-graph property from each source
124     ConstraintFunctionPtr func(ConnectConstraintFunction(propertyOwners));
125
126     if(func)
127     {
128       OwnerPointer<SceneGraph::PropertyResetterBase> resetter;
129       // Create the SceneGraphConstraint and PropertyResetter, and connect them to the scene-graph
130       const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty(mTargetPropertyIndex);
131       DALI_ASSERT_ALWAYS(targetProperty && "Constraint target property does not exist");
132       if(targetProperty->IsTransformManagerProperty()) //It is a property managed by the transform manager
133       {
134         // Connect the constraint
135         mSceneGraphConstraint = SceneGraph::Constraint<PropertyType, TransformManagerPropertyAccessor<PropertyType> >::New(*targetProperty,
136                                                                                                                            propertyOwners,
137                                                                                                                            func,
138                                                                                                                            mRemoveAction);
139         // Don't create a resetter for transform manager property, it's less efficient
140       }
141       else //SceneGraph property
142       {
143         // Connect the constraint
144         mSceneGraphConstraint = SceneGraph::Constraint<PropertyType, PropertyAccessor<PropertyType> >::New(*targetProperty,
145                                                                                                            propertyOwners,
146                                                                                                            func,
147                                                                                                            mRemoveAction);
148         resetter              = SceneGraph::ConstraintResetter::New(targetObject, *targetProperty, *mSceneGraphConstraint);
149       }
150       OwnerPointer<SceneGraph::ConstraintBase> transferOwnership(const_cast<SceneGraph::ConstraintBase*>(mSceneGraphConstraint));
151       ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
152       if(resetter)
153       {
154         AddResetterMessage(GetEventThreadServices().GetUpdateManager(), resetter);
155       }
156     }
157   }
158
159   /**
160    * Helper for ConnectConstraint. Creates a connected constraint-function.
161    * Also populates the property-owner container, for each input connected to the constraint-function.
162    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
163    * @return A connected constraint-function, or nullptr if the scene-graph properties are not available.
164    */
165   PropertyConstraint<PropertyType>* ConnectConstraintFunction(SceneGraph::PropertyOwnerContainer& propertyOwners)
166   {
167     PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
168
169     for(auto&& source : mSources)
170     {
171       int32_t            componentIndex = Property::INVALID_COMPONENT_INDEX;
172       PropertyInputImpl* inputProperty  = AddInputProperty(source, propertyOwners, componentIndex);
173
174       if(nullptr == inputProperty)
175       {
176         delete func;
177         func = nullptr;
178
179         // Exit if a scene-graph object is not available from one of the sources
180         break;
181       }
182
183       func->AddInput(inputProperty, componentIndex);
184     }
185
186     return func;
187   }
188
189 protected:
190   ConstraintFunctionPtr mUserFunction;
191 };
192
193 /**
194  * Variant which allows float components to be constrained individually.
195  */
196 template<>
197 class Constraint<float> : public ConstraintBase
198 {
199 public:
200   using ConstraintFunctionPtr = typename PropertyConstraintPtr<float>::Type;
201
202   /**
203    * Construct a new constraint.
204    * @param[in] object The property-owning object.
205    * @param[in] targetIndex The index of the property to constrain.
206    * @param[in] sources The sources of the input properties passed to func.
207    * @param[in] func The constraint function.
208    * @return A newly allocated constraint.
209    */
210   static ConstraintBase* New(Object&               object,
211                              Property::Index       targetIndex,
212                              SourceContainer&      sources,
213                              ConstraintFunctionPtr func)
214   {
215     return new Constraint(object, targetIndex, sources, func);
216   }
217
218   /**
219    * Virtual destructor.
220    */
221   ~Constraint() override
222   {
223     // This is not responsible for removing constraints.
224   }
225
226 private:
227   /**
228    * @copydoc ConstraintBase::DoClone()
229    */
230   ConstraintBase* DoClone(Object& object) final
231   {
232     ConstraintFunctionPtr funcPtr(mUserFunction->Clone());
233     return new Constraint(object,
234                           mTargetPropertyIndex,
235                           mSources,
236                           funcPtr);
237   }
238
239   /**
240    * Private constructor; see also Constraint::New().
241    */
242   Constraint(Object&                object,
243              Property::Index        targetIndex,
244              SourceContainer&       sources,
245              ConstraintFunctionPtr& func)
246   : ConstraintBase(object, targetIndex, sources),
247     mUserFunction(func)
248   {
249   }
250
251   // Undefined
252   Constraint()                  = delete;
253   Constraint(const Constraint&) = delete;
254   Constraint& operator=(const Constraint& rhs) = delete;
255
256   /**
257    * @copydoc ConstraintBase::ConnectConstraint()
258    */
259   void ConnectConstraint() final
260   {
261     // Should not come here if target object has been destroyed
262     DALI_ASSERT_DEBUG(nullptr != mTargetObject);
263     // Guard against double connections
264     DALI_ASSERT_DEBUG(nullptr == mSceneGraphConstraint);
265
266     SceneGraph::PropertyOwner& targetObject = const_cast<SceneGraph::PropertyOwner&>(mTargetObject->GetSceneObject());
267
268     // Build a container of property-owners, providing the scene-graph properties
269     SceneGraph::PropertyOwnerContainer propertyOwners;
270     propertyOwners.PushBack(&targetObject);
271
272     // Build the constraint function; this requires a scene-graph property from each source
273     ConstraintFunctionPtr func(ConnectConstraintFunction(propertyOwners));
274
275     if(func)
276     {
277       // Create the SceneGraphConstraint, and connect to the scene-graph
278       bool                            resetterRequired = false;
279       const SceneGraph::PropertyBase* targetProperty   = mTargetObject->GetSceneObjectAnimatableProperty(mTargetPropertyIndex);
280       // The targetProperty should exist, when targetObject exists
281       DALI_ASSERT_ALWAYS(nullptr != targetProperty && "Constraint target property does not exist");
282       const int32_t componentIndex = mTargetObject->GetPropertyComponentIndex(mTargetPropertyIndex);
283       if(Property::INVALID_COMPONENT_INDEX == componentIndex)
284       {
285         // Not a Vector2, Vector3 or Vector4 component, expecting float type
286         DALI_ASSERT_DEBUG(PropertyTypes::Get<float>() == targetProperty->GetType());
287
288         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyAccessor<float> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
289         resetterRequired      = true;
290       }
291       else
292       {
293         CreateComponentConstraint(targetProperty, componentIndex, propertyOwners, func, resetterRequired);
294       }
295       if(mSceneGraphConstraint)
296       {
297         OwnerPointer<SceneGraph::ConstraintBase> transferOwnership(const_cast<SceneGraph::ConstraintBase*>(mSceneGraphConstraint));
298         ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
299         if(resetterRequired)
300         {
301           OwnerPointer<SceneGraph::PropertyResetterBase> resetter = SceneGraph::ConstraintResetter::New(targetObject, *targetProperty, *mSceneGraphConstraint);
302           AddResetterMessage(GetEventThreadServices().GetUpdateManager(), resetter);
303         }
304       }
305     }
306   }
307
308   /**
309    * Helper for ConnectConstraint. Creates a connected constraint-function.
310    * Also populates the property-owner container, for each input connected to the constraint-function.
311    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
312    * @return A connected constraint-function, or nullptr if the scene-graph properties are not available.
313    */
314   PropertyConstraint<float>* ConnectConstraintFunction(SceneGraph::PropertyOwnerContainer& propertyOwners)
315   {
316     PropertyConstraint<float>* func = mUserFunction->Clone();
317
318     for(auto&& source : mSources)
319     {
320       int32_t            componentIndex = Property::INVALID_COMPONENT_INDEX;
321       PropertyInputImpl* inputProperty  = AddInputProperty(source, propertyOwners, componentIndex);
322
323       if(nullptr == inputProperty)
324       {
325         delete func;
326         func = nullptr;
327
328         // Exit if a scene-graph object is not available from one of the sources
329         break;
330       }
331
332       func->AddInput(inputProperty, componentIndex);
333     }
334
335     return func;
336   }
337
338   /**
339    * Creates a component property constraint.
340    * @param[in] targetProperty The target property
341    * @param[in] componentIndex The index of the component
342    * @param[in] propertyOwners The owners of the property
343    * @param[in] func The constraint function
344    * @param[in/out] resetterRequired Set to true if a property resetter is required after creating this constraint
345    */
346   void CreateComponentConstraint(const SceneGraph::PropertyBase* targetProperty, const int32_t componentIndex, SceneGraph::PropertyOwnerContainer& propertyOwners, ConstraintFunctionPtr& func, bool& resetterRequired)
347   {
348     // Expecting Vector2, Vector3 or Vector4 type
349     if(PropertyTypes::Get<Vector2>() == targetProperty->GetType())
350     {
351       // Constrain float component of Vector2 property
352       if(0 == componentIndex)
353       {
354         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
355       }
356       else if(1 == componentIndex)
357       {
358         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
359       }
360       resetterRequired = (mSceneGraphConstraint != nullptr);
361     }
362     else if(PropertyTypes::Get<Vector3>() == targetProperty->GetType())
363     {
364       // Constrain float component of Vector3 property
365       if(targetProperty->IsTransformManagerProperty())
366       {
367         if(0 == componentIndex)
368         {
369           mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 0> >::New(*targetProperty,
370                                                                                                                              propertyOwners,
371                                                                                                                              func,
372                                                                                                                              mRemoveAction);
373         }
374         else if(1 == componentIndex)
375         {
376           mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 1> >::New(*targetProperty,
377                                                                                                                              propertyOwners,
378                                                                                                                              func,
379                                                                                                                              mRemoveAction);
380         }
381         else if(2 == componentIndex)
382         {
383           mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 2> >::New(*targetProperty,
384                                                                                                                              propertyOwners,
385                                                                                                                              func,
386                                                                                                                              mRemoveAction);
387         }
388         // Do not create a resetter for transform manager property
389       }
390       else
391       {
392         if(0 == componentIndex)
393         {
394           mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
395         }
396         else if(1 == componentIndex)
397         {
398           mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
399         }
400         else if(2 == componentIndex)
401         {
402           mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
403         }
404         resetterRequired = (mSceneGraphConstraint != nullptr);
405       }
406     }
407     else if(PropertyTypes::Get<Vector4>() == targetProperty->GetType())
408     {
409       // Constrain float component of Vector4 property
410       if(0 == componentIndex)
411       {
412         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
413       }
414       else if(1 == componentIndex)
415       {
416         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
417       }
418       else if(2 == componentIndex)
419       {
420         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
421       }
422       else if(3 == componentIndex)
423       {
424         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorW<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
425       }
426
427       resetterRequired = (mSceneGraphConstraint != nullptr);
428     }
429   }
430
431 protected:
432   ConstraintFunctionPtr mUserFunction;
433 };
434
435 } // namespace Internal
436
437 } // namespace Dali
438
439 #endif // DALI_INTERNAL_ACTIVE_CONSTRAINT_H