[dali_2.3.27] Merge branch 'devel/master'
[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(bool isPreConstraint) 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       if(isPreConstraint)
152       {
153         ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
154       }
155       else
156       {
157         ApplyPostConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
158       }
159       if(resetter)
160       {
161         AddResetterMessage(GetEventThreadServices().GetUpdateManager(), resetter);
162       }
163     }
164   }
165
166   /**
167    * Helper for ConnectConstraint. Creates a connected constraint-function.
168    * Also populates the property-owner container, for each input connected to the constraint-function.
169    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
170    * @return A connected constraint-function, or nullptr if the scene-graph properties are not available.
171    */
172   PropertyConstraint<PropertyType>* ConnectConstraintFunction(SceneGraph::PropertyOwnerContainer& propertyOwners)
173   {
174     PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
175
176     for(auto&& source : mSources)
177     {
178       int32_t            componentIndex = Property::INVALID_COMPONENT_INDEX;
179       PropertyInputImpl* inputProperty  = AddInputProperty(source, propertyOwners, componentIndex);
180
181       if(nullptr == inputProperty)
182       {
183         delete func;
184         func = nullptr;
185
186         // Exit if a scene-graph object is not available from one of the sources
187         break;
188       }
189
190       func->AddInput(inputProperty, componentIndex);
191     }
192
193     return func;
194   }
195
196 protected:
197   ConstraintFunctionPtr mUserFunction;
198 };
199
200 /**
201  * Variant which allows float components to be constrained individually.
202  */
203 template<>
204 class Constraint<float> : public ConstraintBase
205 {
206 public:
207   using ConstraintFunctionPtr = typename PropertyConstraintPtr<float>::Type;
208
209   /**
210    * Construct a new constraint.
211    * @param[in] object The property-owning object.
212    * @param[in] targetIndex The index of the property to constrain.
213    * @param[in] sources The sources of the input properties passed to func.
214    * @param[in] func The constraint function.
215    * @return A newly allocated constraint.
216    */
217   static ConstraintBase* New(Object&               object,
218                              Property::Index       targetIndex,
219                              SourceContainer&      sources,
220                              ConstraintFunctionPtr func)
221   {
222     return new Constraint(object, targetIndex, sources, func);
223   }
224
225   /**
226    * Virtual destructor.
227    */
228   ~Constraint() override
229   {
230     // This is not responsible for removing constraints.
231   }
232
233 private:
234   /**
235    * @copydoc ConstraintBase::DoClone()
236    */
237   ConstraintBase* DoClone(Object& object) final
238   {
239     ConstraintFunctionPtr funcPtr(mUserFunction->Clone());
240     return new Constraint(object,
241                           mTargetPropertyIndex,
242                           mSources,
243                           funcPtr);
244   }
245
246   /**
247    * Private constructor; see also Constraint::New().
248    */
249   Constraint(Object&                object,
250              Property::Index        targetIndex,
251              SourceContainer&       sources,
252              ConstraintFunctionPtr& func)
253   : ConstraintBase(object, targetIndex, sources),
254     mUserFunction(func)
255   {
256   }
257
258   // Undefined
259   Constraint()                  = delete;
260   Constraint(const Constraint&) = delete;
261   Constraint& operator=(const Constraint& rhs) = delete;
262
263   /**
264    * @copydoc ConstraintBase::ConnectConstraint()
265    */
266   void ConnectConstraint(bool isPreConstraint) final
267   {
268     // Should not come here if target object has been destroyed
269     DALI_ASSERT_DEBUG(nullptr != mTargetObject);
270     // Guard against double connections
271     DALI_ASSERT_DEBUG(nullptr == mSceneGraphConstraint);
272
273     SceneGraph::PropertyOwner& targetObject = const_cast<SceneGraph::PropertyOwner&>(mTargetObject->GetSceneObject());
274
275     // Build a container of property-owners, providing the scene-graph properties
276     SceneGraph::PropertyOwnerContainer propertyOwners;
277     propertyOwners.PushBack(&targetObject);
278
279     // Build the constraint function; this requires a scene-graph property from each source
280     ConstraintFunctionPtr func(ConnectConstraintFunction(propertyOwners));
281
282     if(func)
283     {
284       // Create the SceneGraphConstraint, and connect to the scene-graph
285       bool                            resetterRequired = false;
286       const SceneGraph::PropertyBase* targetProperty   = mTargetObject->GetSceneObjectAnimatableProperty(mTargetPropertyIndex);
287       // The targetProperty should exist, when targetObject exists
288       DALI_ASSERT_ALWAYS(nullptr != targetProperty && "Constraint target property does not exist");
289       const int32_t componentIndex = mTargetObject->GetPropertyComponentIndex(mTargetPropertyIndex);
290       if(Property::INVALID_COMPONENT_INDEX == componentIndex)
291       {
292         // Not a Vector2, Vector3 or Vector4 component, expecting float type
293         DALI_ASSERT_DEBUG(PropertyTypes::Get<float>() == targetProperty->GetType());
294
295         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyAccessor<float> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
296         resetterRequired      = true;
297       }
298       else
299       {
300         CreateComponentConstraint(targetProperty, componentIndex, propertyOwners, func, resetterRequired);
301       }
302       if(mSceneGraphConstraint)
303       {
304         OwnerPointer<SceneGraph::ConstraintBase> transferOwnership(const_cast<SceneGraph::ConstraintBase*>(mSceneGraphConstraint));
305         if(isPreConstraint)
306         {
307           ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
308         }
309         else
310         {
311           ApplyPostConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
312         }
313         if(resetterRequired)
314         {
315           OwnerPointer<SceneGraph::PropertyResetterBase> resetter = SceneGraph::ConstraintResetter::New(targetObject, *targetProperty, *mSceneGraphConstraint);
316           AddResetterMessage(GetEventThreadServices().GetUpdateManager(), resetter);
317         }
318       }
319     }
320   }
321
322   /**
323    * Helper for ConnectConstraint. Creates a connected constraint-function.
324    * Also populates the property-owner container, for each input connected to the constraint-function.
325    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
326    * @return A connected constraint-function, or nullptr if the scene-graph properties are not available.
327    */
328   PropertyConstraint<float>* ConnectConstraintFunction(SceneGraph::PropertyOwnerContainer& propertyOwners)
329   {
330     PropertyConstraint<float>* func = mUserFunction->Clone();
331
332     for(auto&& source : mSources)
333     {
334       int32_t            componentIndex = Property::INVALID_COMPONENT_INDEX;
335       PropertyInputImpl* inputProperty  = AddInputProperty(source, propertyOwners, componentIndex);
336
337       if(nullptr == inputProperty)
338       {
339         delete func;
340         func = nullptr;
341
342         // Exit if a scene-graph object is not available from one of the sources
343         break;
344       }
345
346       func->AddInput(inputProperty, componentIndex);
347     }
348
349     return func;
350   }
351
352   /**
353    * Creates a component property constraint.
354    * @param[in] targetProperty The target property
355    * @param[in] componentIndex The index of the component
356    * @param[in] propertyOwners The owners of the property
357    * @param[in] func The constraint function
358    * @param[in/out] resetterRequired Set to true if a property resetter is required after creating this constraint
359    */
360   void CreateComponentConstraint(const SceneGraph::PropertyBase* targetProperty, const int32_t componentIndex, SceneGraph::PropertyOwnerContainer& propertyOwners, ConstraintFunctionPtr& func, bool& resetterRequired)
361   {
362     // Expecting Vector2, Vector3 or Vector4 type
363     if(PropertyTypes::Get<Vector2>() == targetProperty->GetType())
364     {
365       // Constrain float component of Vector2 property
366       if(0 == componentIndex)
367       {
368         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
369       }
370       else if(1 == componentIndex)
371       {
372         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
373       }
374       resetterRequired = (mSceneGraphConstraint != nullptr);
375     }
376     else if(PropertyTypes::Get<Vector3>() == targetProperty->GetType())
377     {
378       // Constrain float component of Vector3 property
379       if(targetProperty->IsTransformManagerProperty())
380       {
381         if(0 == componentIndex)
382         {
383           mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 0> >::New(*targetProperty,
384                                                                                                                              propertyOwners,
385                                                                                                                              func,
386                                                                                                                              mRemoveAction);
387         }
388         else if(1 == componentIndex)
389         {
390           mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 1> >::New(*targetProperty,
391                                                                                                                              propertyOwners,
392                                                                                                                              func,
393                                                                                                                              mRemoveAction);
394         }
395         else if(2 == componentIndex)
396         {
397           mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 2> >::New(*targetProperty,
398                                                                                                                              propertyOwners,
399                                                                                                                              func,
400                                                                                                                              mRemoveAction);
401         }
402         // Do not create a resetter for transform manager property
403       }
404       else
405       {
406         if(0 == componentIndex)
407         {
408           mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
409         }
410         else if(1 == componentIndex)
411         {
412           mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
413         }
414         else if(2 == componentIndex)
415         {
416           mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
417         }
418         resetterRequired = (mSceneGraphConstraint != nullptr);
419       }
420     }
421     else if(PropertyTypes::Get<Vector4>() == targetProperty->GetType())
422     {
423       // Constrain float component of Vector4 property
424       if(0 == componentIndex)
425       {
426         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
427       }
428       else if(1 == componentIndex)
429       {
430         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
431       }
432       else if(2 == componentIndex)
433       {
434         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
435       }
436       else if(3 == componentIndex)
437       {
438         mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorW<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
439       }
440
441       resetterRequired = (mSceneGraphConstraint != nullptr);
442     }
443   }
444
445 protected:
446   ConstraintFunctionPtr mUserFunction;
447 };
448
449 } // namespace Internal
450
451 } // namespace Dali
452
453 #endif // DALI_INTERNAL_ACTIVE_CONSTRAINT_H