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() 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));
151 ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
154 AddResetterMessage(GetEventThreadServices().GetUpdateManager(), resetter);
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.
165 PropertyConstraint<PropertyType>* ConnectConstraintFunction(SceneGraph::PropertyOwnerContainer& propertyOwners)
167 PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
169 for(auto&& source : mSources)
171 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
172 PropertyInputImpl* inputProperty = AddInputProperty(source, propertyOwners, componentIndex);
174 if(nullptr == inputProperty)
179 // Exit if a scene-graph object is not available from one of the sources
183 func->AddInput(inputProperty, componentIndex);
190 ConstraintFunctionPtr mUserFunction;
194 * Variant which allows float components to be constrained individually.
197 class Constraint<float> : public ConstraintBase
200 using ConstraintFunctionPtr = typename PropertyConstraintPtr<float>::Type;
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.
210 static ConstraintBase* New(Object& object,
211 Property::Index targetIndex,
212 SourceContainer& sources,
213 ConstraintFunctionPtr func)
215 return new Constraint(object, targetIndex, sources, func);
219 * Virtual destructor.
221 ~Constraint() override
223 // This is not responsible for removing constraints.
228 * @copydoc ConstraintBase::DoClone()
230 ConstraintBase* DoClone(Object& object) final
232 ConstraintFunctionPtr funcPtr(mUserFunction->Clone());
233 return new Constraint(object,
234 mTargetPropertyIndex,
240 * Private constructor; see also Constraint::New().
242 Constraint(Object& object,
243 Property::Index targetIndex,
244 SourceContainer& sources,
245 ConstraintFunctionPtr& func)
246 : ConstraintBase(object, targetIndex, sources),
252 Constraint() = delete;
253 Constraint(const Constraint&) = delete;
254 Constraint& operator=(const Constraint& rhs) = delete;
257 * @copydoc ConstraintBase::ConnectConstraint()
259 void ConnectConstraint() final
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);
266 SceneGraph::PropertyOwner& targetObject = const_cast<SceneGraph::PropertyOwner&>(mTargetObject->GetSceneObject());
268 // Build a container of property-owners, providing the scene-graph properties
269 SceneGraph::PropertyOwnerContainer propertyOwners;
270 propertyOwners.PushBack(&targetObject);
272 // Build the constraint function; this requires a scene-graph property from each source
273 ConstraintFunctionPtr func(ConnectConstraintFunction(propertyOwners));
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)
285 // Not a Vector2, Vector3 or Vector4 component, expecting float type
286 DALI_ASSERT_DEBUG(PropertyTypes::Get<float>() == targetProperty->GetType());
288 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyAccessor<float> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
289 resetterRequired = true;
293 CreateComponentConstraint(targetProperty, componentIndex, propertyOwners, func, resetterRequired);
295 if(mSceneGraphConstraint)
297 OwnerPointer<SceneGraph::ConstraintBase> transferOwnership(const_cast<SceneGraph::ConstraintBase*>(mSceneGraphConstraint));
298 ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
301 OwnerPointer<SceneGraph::PropertyResetterBase> resetter = SceneGraph::ConstraintResetter::New(targetObject, *targetProperty, *mSceneGraphConstraint);
302 AddResetterMessage(GetEventThreadServices().GetUpdateManager(), resetter);
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.
314 PropertyConstraint<float>* ConnectConstraintFunction(SceneGraph::PropertyOwnerContainer& propertyOwners)
316 PropertyConstraint<float>* func = mUserFunction->Clone();
318 for(auto&& source : mSources)
320 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
321 PropertyInputImpl* inputProperty = AddInputProperty(source, propertyOwners, componentIndex);
323 if(nullptr == inputProperty)
328 // Exit if a scene-graph object is not available from one of the sources
332 func->AddInput(inputProperty, componentIndex);
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
346 void CreateComponentConstraint(const SceneGraph::PropertyBase* targetProperty, const int32_t componentIndex, SceneGraph::PropertyOwnerContainer& propertyOwners, ConstraintFunctionPtr& func, bool& resetterRequired)
348 // Expecting Vector2, Vector3 or Vector4 type
349 if(PropertyTypes::Get<Vector2>() == targetProperty->GetType())
351 // Constrain float component of Vector2 property
352 if(0 == componentIndex)
354 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
356 else if(1 == componentIndex)
358 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
360 resetterRequired = (mSceneGraphConstraint != nullptr);
362 else if(PropertyTypes::Get<Vector3>() == targetProperty->GetType())
364 // Constrain float component of Vector3 property
365 if(targetProperty->IsTransformManagerProperty())
367 if(0 == componentIndex)
369 mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 0> >::New(*targetProperty,
374 else if(1 == componentIndex)
376 mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 1> >::New(*targetProperty,
381 else if(2 == componentIndex)
383 mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 2> >::New(*targetProperty,
388 // Do not create a resetter for transform manager property
392 if(0 == componentIndex)
394 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
396 else if(1 == componentIndex)
398 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
400 else if(2 == componentIndex)
402 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
404 resetterRequired = (mSceneGraphConstraint != nullptr);
407 else if(PropertyTypes::Get<Vector4>() == targetProperty->GetType())
409 // Constrain float component of Vector4 property
410 if(0 == componentIndex)
412 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
414 else if(1 == componentIndex)
416 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
418 else if(2 == componentIndex)
420 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
422 else if(3 == componentIndex)
424 mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorW<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
427 resetterRequired = (mSceneGraphConstraint != nullptr);
432 ConstraintFunctionPtr mUserFunction;
435 } // namespace Internal
439 #endif // DALI_INTERNAL_ACTIVE_CONSTRAINT_H