1 #ifndef DALI_INTERNAL_ACTIVE_CONSTRAINT_H
2 #define DALI_INTERNAL_ACTIVE_CONSTRAINT_H
5 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
44 * Connects a constraint which takes another property as an input.
46 template<typename PropertyType>
47 class Constraint : public ConstraintBase
50 using ConstraintFunctionPtr = typename PropertyConstraintPtr<PropertyType>::Type;
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.
60 static ConstraintBase* New(Object& object,
61 Property::Index targetIndex,
62 SourceContainer& sources,
63 ConstraintFunctionPtr func)
65 return new Constraint(object, targetIndex, sources, func);
71 ~Constraint() override
73 // This is not responsible for removing constraints.
78 * @copydoc ConstraintBase::DoClone()
80 ConstraintBase* DoClone(Object& object) final
82 ConstraintFunctionPtr funcPtr(mUserFunction->Clone());
83 return new Constraint(object,
90 * Private constructor; see also Constraint::New().
92 Constraint(Object& object,
93 Property::Index targetIndex,
94 SourceContainer& sources,
95 ConstraintFunctionPtr& func)
96 : ConstraintBase(object, targetIndex, sources),
102 Constraint() = delete;
103 Constraint(const Constraint&) = delete;
104 Constraint& operator=(const Constraint& rhs) = delete;
107 * @copydoc ConstraintBase::ConnectConstraint()
109 void ConnectConstraint(bool isPreConstraint) final
111 // Should not come here if target object has been destroyed
112 DALI_ASSERT_DEBUG(nullptr != mTargetObject);
114 // Guard against double connections
115 DALI_ASSERT_DEBUG(nullptr == mSceneGraphConstraint);
117 SceneGraph::PropertyOwner& targetObject = const_cast<SceneGraph::PropertyOwner&>(mTargetObject->GetSceneObject());
119 // Build a container of property-owners, providing the scene-graph properties
120 SceneGraph::PropertyOwnerContainer propertyOwners;
121 propertyOwners.PushBack(&targetObject);
123 // Build the constraint function; this requires a scene-graph property from each source
124 ConstraintFunctionPtr func(ConnectConstraintFunction(propertyOwners));
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
134 // Connect the constraint
135 mSceneGraphConstraint = SceneGraph::Constraint<PropertyType, TransformManagerPropertyAccessor<PropertyType> >::New(*targetProperty,
139 // Don't create a resetter for transform manager property, it's less efficient
141 else //SceneGraph property
143 // Connect the constraint
144 mSceneGraphConstraint = SceneGraph::Constraint<PropertyType, PropertyAccessor<PropertyType> >::New(*targetProperty,
148 resetter = SceneGraph::ConstraintResetter::New(targetObject, *targetProperty, *mSceneGraphConstraint);
150 OwnerPointer<SceneGraph::ConstraintBase> transferOwnership(const_cast<SceneGraph::ConstraintBase*>(mSceneGraphConstraint));
153 ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
157 ApplyPostConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
161 AddResetterMessage(GetEventThreadServices().GetUpdateManager(), resetter);
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.
172 PropertyConstraint<PropertyType>* ConnectConstraintFunction(SceneGraph::PropertyOwnerContainer& propertyOwners)
174 PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
176 for(auto&& source : mSources)
178 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
179 PropertyInputImpl* inputProperty = AddInputProperty(source, propertyOwners, componentIndex);
181 if(nullptr == inputProperty)
186 // Exit if a scene-graph object is not available from one of the sources
190 func->AddInput(inputProperty, componentIndex);
197 ConstraintFunctionPtr mUserFunction;
201 * Variant which allows float components to be constrained individually.
204 class Constraint<float> : public ConstraintBase
207 using ConstraintFunctionPtr = typename PropertyConstraintPtr<float>::Type;
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.
217 static ConstraintBase* New(Object& object,
218 Property::Index targetIndex,
219 SourceContainer& sources,
220 ConstraintFunctionPtr func)
222 return new Constraint(object, targetIndex, sources, func);
226 * Virtual destructor.
228 ~Constraint() override
230 // This is not responsible for removing constraints.
235 * @copydoc ConstraintBase::DoClone()
237 ConstraintBase* DoClone(Object& object) final
239 ConstraintFunctionPtr funcPtr(mUserFunction->Clone());
240 return new Constraint(object,
241 mTargetPropertyIndex,
247 * Private constructor; see also Constraint::New().
249 Constraint(Object& object,
250 Property::Index targetIndex,
251 SourceContainer& sources,
252 ConstraintFunctionPtr& func)
253 : ConstraintBase(object, targetIndex, sources),
259 Constraint() = delete;
260 Constraint(const Constraint&) = delete;
261 Constraint& operator=(const Constraint& rhs) = delete;
264 * @copydoc ConstraintBase::ConnectConstraint()
266 void ConnectConstraint(bool isPreConstraint) final
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);
273 SceneGraph::PropertyOwner& targetObject = const_cast<SceneGraph::PropertyOwner&>(mTargetObject->GetSceneObject());
275 // Build a container of property-owners, providing the scene-graph properties
276 SceneGraph::PropertyOwnerContainer propertyOwners;
277 propertyOwners.PushBack(&targetObject);
279 // Build the constraint function; this requires a scene-graph property from each source
280 ConstraintFunctionPtr func(ConnectConstraintFunction(propertyOwners));
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)
292 // Not a Vector2, Vector3 or Vector4 component, expecting float type
293 DALI_ASSERT_DEBUG(PropertyTypes::Get<float>() == targetProperty->GetType());
295 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyAccessor<float> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
296 resetterRequired = true;
300 CreateComponentConstraint(targetProperty, componentIndex, propertyOwners, func, resetterRequired);
302 if(mSceneGraphConstraint)
304 OwnerPointer<SceneGraph::ConstraintBase> transferOwnership(const_cast<SceneGraph::ConstraintBase*>(mSceneGraphConstraint));
307 ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
311 ApplyPostConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
315 OwnerPointer<SceneGraph::PropertyResetterBase> resetter = SceneGraph::ConstraintResetter::New(targetObject, *targetProperty, *mSceneGraphConstraint);
316 AddResetterMessage(GetEventThreadServices().GetUpdateManager(), resetter);
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.
328 PropertyConstraint<float>* ConnectConstraintFunction(SceneGraph::PropertyOwnerContainer& propertyOwners)
330 PropertyConstraint<float>* func = mUserFunction->Clone();
332 for(auto&& source : mSources)
334 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
335 PropertyInputImpl* inputProperty = AddInputProperty(source, propertyOwners, componentIndex);
337 if(nullptr == inputProperty)
342 // Exit if a scene-graph object is not available from one of the sources
346 func->AddInput(inputProperty, componentIndex);
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
360 void CreateComponentConstraint(const SceneGraph::PropertyBase* targetProperty, const int32_t componentIndex, SceneGraph::PropertyOwnerContainer& propertyOwners, ConstraintFunctionPtr& func, bool& resetterRequired)
362 // Expecting Vector2, Vector3 or Vector4 type
363 if(PropertyTypes::Get<Vector2>() == targetProperty->GetType())
365 // Constrain float component of Vector2 property
366 if(0 == componentIndex)
368 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
370 else if(1 == componentIndex)
372 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
374 resetterRequired = (mSceneGraphConstraint != nullptr);
376 else if(PropertyTypes::Get<Vector3>() == targetProperty->GetType())
378 // Constrain float component of Vector3 property
379 if(targetProperty->IsTransformManagerProperty())
381 if(0 == componentIndex)
383 mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 0> >::New(*targetProperty,
388 else if(1 == componentIndex)
390 mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 1> >::New(*targetProperty,
395 else if(2 == componentIndex)
397 mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 2> >::New(*targetProperty,
402 // Do not create a resetter for transform manager property
406 if(0 == componentIndex)
408 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
410 else if(1 == componentIndex)
412 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
414 else if(2 == componentIndex)
416 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
418 resetterRequired = (mSceneGraphConstraint != nullptr);
421 else if(PropertyTypes::Get<Vector4>() == targetProperty->GetType())
423 // Constrain float component of Vector4 property
424 if(0 == componentIndex)
426 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
428 else if(1 == componentIndex)
430 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
432 else if(2 == componentIndex)
434 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
436 else if(3 == componentIndex)
438 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorW<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
441 resetterRequired = (mSceneGraphConstraint != nullptr);
446 ConstraintFunctionPtr mUserFunction;
449 } // namespace Internal
453 #endif // DALI_INTERNAL_ACTIVE_CONSTRAINT_H