1 #ifndef DALI_CONSTRAINT_H
2 #define DALI_CONSTRAINT_H
5 * Copyright (c) 2020 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 <cstdint> // uint32_t
25 #include <dali/public-api/animation/constraint-source.h>
26 #include <dali/public-api/common/dali-vector.h>
27 #include <dali/public-api/object/base-handle.h>
28 #include <dali/public-api/object/property-input.h>
29 #include <dali/public-api/object/property.h>
30 #include <dali/public-api/signals/callback.h>
35 * @addtogroup dali_core_animation
41 namespace Internal DALI_INTERNAL
46 using PropertyInputContainer = Vector<PropertyInput*>;
49 * @brief An abstract base class for Constraints.
51 * This can be used to constrain a property of an object, after animations have been applied.
52 * Constraints are applied in the following order:
53 * - Constraints are applied to on-stage actors in a depth-first traversal.
54 * - For each actor, the constraints are applied in the same order as the calls to Apply().
55 * - Constraints are not applied to off-stage actors.
57 * Create a constraint using one of the New methods depending on the type of callback function used.
58 * Try to use a C function unless some data needs to be stored, otherwise functors and class methods
61 * A constraint can be applied to an object in the following manner:
64 * Handle handle = CreateMyObject();
65 * Constraint constraint = Constraint::New< Vector3 >( handle, CONSTRAINING_PROPERTY_INDEX, &MyFunction );
66 * constraint.AddSource( LocalSource( INPUT_PROPERTY_INDEX ) );
71 class DALI_CORE_API Constraint : public BaseHandle
75 * @brief Template for the Function that is called by the Constraint system.
79 * - Static member methods of an object
80 * - Member functions of a particular class
81 * - Functors of a particular class
82 * - If a functor or method is provided, then a copy of the object is made.
84 * The expected signature of the callback should be:
86 * void Function( P&, const PropertyInputContainer& );
89 * The P& parameter is an in,out parameter which stores the current value of the property. The callback
90 * should change this value to the desired one. The PropertyInputContainer is a const reference to the property inputs
91 * added to the Constraint in the order they were added via AddSource().
94 * @tparam P The property type to constrain
97 class DALI_INTERNAL Function : public CallbackBase
101 * @brief Constructor which connects to the provided C function (or a static member function).
103 * The expected signature of the function is:
105 * void MyFunction( P&, const PropertyInputContainer& );
109 * @param[in] function The function to call
111 Function(void (*function)(P&, const PropertyInputContainer&))
112 : CallbackBase(reinterpret_cast<CallbackBase::Function>(function)),
113 mCopyConstructorDispatcher(NULL)
118 * @brief Constructor which copies a function object and connects to the functor of that object.
120 * The function object should have a functor with the following signature:
122 * void operator()( P&, const PropertyInputContainer& );
126 * @param[in] object The object to copy
127 * @tparam T The type of the object
130 Function(const T& object)
131 : CallbackBase(reinterpret_cast<void*>(new T(object)), // copy the object
132 nullptr, // uses operator() instead of member function
133 reinterpret_cast<CallbackBase::Dispatcher>(&FunctorDispatcher2<T, P&, const PropertyInputContainer&>::Dispatch),
134 reinterpret_cast<CallbackBase::Destructor>(&Destroyer<T>::Delete)),
135 mCopyConstructorDispatcher(reinterpret_cast<CopyConstructorDispatcher>(&ObjectCopyConstructorDispatcher<T>::Copy))
140 * @brief Constructor which copies a function object and allows a connection to a member method.
142 * The object should have a method with the signature:
144 * void MyObject::MyMethod( P&, const PropertyInputContainer& );
148 * @param[in] object The object to copy
149 * @param[in] memberFunction The member function to call. This has to be a member of the same class
150 * @tparam T The type of the object
153 Function(const T& object, void (T::*memberFunction)(P&, const PropertyInputContainer&))
154 : CallbackBase(reinterpret_cast<void*>(new T(object)), // copy the object
155 reinterpret_cast<CallbackBase::MemberFunction>(memberFunction),
156 reinterpret_cast<CallbackBase::Dispatcher>(&Dispatcher2<T, P&, const PropertyInputContainer&>::Dispatch),
157 reinterpret_cast<CallbackBase::Destructor>(&Destroyer<T>::Delete)),
158 mCopyConstructorDispatcher(reinterpret_cast<CopyConstructorDispatcher>(&ObjectCopyConstructorDispatcher<T>::Copy))
163 * @brief Clones the Function object.
165 * The object, if held by this object, is also copied.
168 * @return A pointer to a newly-allocated Function
170 CallbackBase* Clone()
172 CallbackBase* callback = nullptr;
173 if(mImpl.mObjectPointer && mCopyConstructorDispatcher)
175 callback = new Function(mCopyConstructorDispatcher(reinterpret_cast<UndefinedClass*>(mImpl.mObjectPointer)) /* Copy the object */,
177 mImpl.mMemberFunctionDispatcher,
178 mImpl.mDestructorDispatcher,
179 mCopyConstructorDispatcher);
183 callback = new Function(mFunction);
190 * @brief Must not be declared.
192 * This is used so that no optimisations are done by the compiler when using void*.
194 class UndefinedClass;
197 * @brief Used to call the function to copy the stored object.
200 using CopyConstructorDispatcher = UndefinedClass* (*)(UndefinedClass*);
203 * @brief Copies the actual object in Constraint::Function.
206 * @tparam T The type of the object
209 struct ObjectCopyConstructorDispatcher
212 * @brief Copies the object stored in Constraint::Function.
215 * @param[in] object The object to copy
216 * @return Newly allocated clone of the object
218 static UndefinedClass* Copy(const UndefinedClass* object)
220 T* copy = new T(*(reinterpret_cast<const T*>(object)));
221 return reinterpret_cast<UndefinedClass*>(copy);
225 Function(const Function&) = delete; ///< Deleted copy constructor. @SINCE_1_0.0
226 Function(Function&&) = delete; ///< Deleted move constructor. @SINCE_1_9.25
227 Function& operator=(const Function&) = delete; ///< Deleted copy assignment operator. @SINCE_1_0.0
228 Function& operator=(Function&&) = delete; ///< Deleted move assignment operator. @SINCE_1_9.25
231 * @brief Constructor used when copying the stored object.
234 * @param[in] object A newly copied object
235 * @param[in] memberFunction The member function of the object
236 * @param[in] dispatcher Used to call the actual object
237 * @param[in] destructor Used to delete the owned object
238 * @param[in] copyConstructorDispatcher Used to create a copy of the owned object
240 Function(void* object,
241 CallbackBase::MemberFunction memberFunction,
242 CallbackBase::Dispatcher dispatcher,
243 CallbackBase::Destructor destructor,
244 CopyConstructorDispatcher copyConstructorDispatcher)
245 : CallbackBase(object, memberFunction, dispatcher, destructor),
246 mCopyConstructorDispatcher(copyConstructorDispatcher)
251 * @brief Constructor used when copying a simple stored function.
254 * @param[in] function The function to call
256 Function(CallbackBase::Function function)
257 : CallbackBase(function),
258 mCopyConstructorDispatcher(nullptr)
264 CopyConstructorDispatcher mCopyConstructorDispatcher; ///< Function to call to copy the stored object
268 * @brief Enumeration for the action that will happen when the constraint is removed.
270 * The final value may be "baked" i.e. saved permanently.
271 * Alternatively the constrained value may be discarded when the constraint is removed.
276 BAKE, ///< When the constraint is fully-applied, the constrained value is saved. @SINCE_1_9.28
277 DISCARD ///< When the constraint is removed, the constrained value is discarded. @SINCE_1_9.28
280 static const RemoveAction DEFAULT_REMOVE_ACTION; ///< BAKE
283 * @brief Creates an uninitialized Constraint; this can be initialized with Constraint::New().
285 * Calling member functions with an uninitialized Constraint handle is not allowed.
291 * @brief Creates a constraint which targets a property using a function or a static class member.
293 * The expected signature, for a Vector3 type for example, of the function is:
295 * void MyFunction( Vector3&, const PropertyInputContainer& );
298 * Create the constraint with this function as follows:
301 * Constraint constraint = Constraint::New< Vector3 >( handle, CONSTRAINING_PROPERTY_INDEX, &MyFunction );
305 * @param[in] handle The handle to the property-owning object
306 * @param[in] targetIndex The index of the property to constrain
307 * @param[in] function The function to call to set the constrained property value
309 * @tparam P The type of the property to constrain
310 * @return The new constraint
313 static Constraint New(Handle handle, Property::Index targetIndex, void (*function)(P&, const PropertyInputContainer&))
315 CallbackBase* callback = new Constraint::Function<P>(function);
316 return New(handle, targetIndex, PropertyTypes::Get<P>(), callback);
320 * @brief Creates a constraint which targets a property using a functor object.
322 * The expected structure, for a Vector3 type for example, of the functor object is:
326 * void operator() ( Vector3&, const PropertyInputContainer& );
330 * Create the constraint with this object as follows:
333 * Constraint constraint = Constraint::New< Vector3 >( handle, CONSTRAINING_PROPERTY_INDEX, MyObject() );
337 * @param[in] handle The handle to the property-owning object
338 * @param[in] targetIndex The index of the property to constraint
339 * @param[in] object The functor object whose functor is called to set the constrained property value
341 * @tparam P The type of the property to constrain
342 * @tparam T The type of the object
343 * @return The new constraint
345 template<class P, class T>
346 static Constraint New(Handle handle, Property::Index targetIndex, const T& object)
348 CallbackBase* function = new Constraint::Function<P>(object);
349 return New(handle, targetIndex, PropertyTypes::Get<P>(), function);
353 * @brief Creates a constraint which targets a property using an object method.
355 * The expected structure, for a Vector3 type for example, of the object is:
359 * void MyMethod( Vector3&, const PropertyInputContainer& );
363 * Create the constraint with this object as follows:
366 * Constraint constraint = Constraint::New< Vector3 >( handle, CONSTRAINING_PROPERTY_INDEX, MyObject(), &MyObject::MyMethod );
370 * @param[in] handle The handle to the property-owning object
371 * @param[in] targetIndex The index of the property to constraint
372 * @param[in] object The object whose member function is called to set the constrained property value
373 * @param[in] memberFunction The member function to call to set the constrained property value
374 * @return The new constraint
376 * @tparam P The type of the property to constrain
377 * @tparam T The type of the object
379 template<class P, class T>
380 static Constraint New(Handle handle, Property::Index targetIndex, const T& object, void (T::*memberFunction)(P&, const PropertyInputContainer&))
382 CallbackBase* function = new Constraint::Function<P>(object, memberFunction);
383 return New(handle, targetIndex, PropertyTypes::Get<P>(), function);
387 * @brief Creates a clone of this constraint for another object.
390 * @param[in] handle The handle to the property-owning object this constraint is to be cloned for
391 * @return The new constraint
393 Constraint Clone(Handle handle);
398 * This is non-virtual since derived Handle types must not contain data or virtual methods.
404 * @brief This copy constructor is required for (smart) pointer semantics.
407 * @param[in] constraint A reference to the copied handle
409 Constraint(const Constraint& constraint);
412 * @brief This assignment operator is required for (smart) pointer semantics.
415 * @param[in] rhs A reference to the copied handle
416 * @return A reference to this
418 Constraint& operator=(const Constraint& rhs);
421 * @brief Move constructor.
424 * @param[in] rhs A reference to the moved handle
426 Constraint(Constraint&& rhs);
429 * @brief Move assignment operator.
432 * @param[in] rhs A reference to the moved handle
433 * @return A reference to this handle
435 Constraint& operator=(Constraint&& rhs);
438 * @brief Downcasts a handle to Constraint handle.
440 * If handle points to a Constraint object, the downcast produces valid handle.
441 * If not, the returned handle is left uninitialized.
443 * @param[in] baseHandle BaseHandle to an object
444 * @return Handle to a Constraint object or an uninitialized handle
446 static Constraint DownCast(BaseHandle baseHandle);
449 * @brief Adds a constraint source to the constraint.
452 * @param[in] source The constraint source input to add
454 void AddSource(ConstraintSource source);
457 * @brief Applies this constraint.
460 * @pre The constraint must be initialized.
461 * @pre The target object must still be alive.
462 * @pre The source inputs should not have been destroyed.
467 * @brief Removes this constraint.
473 * @brief Retrieves the object which this constraint is targeting.
476 * @return The target object
478 Handle GetTargetObject();
481 * @brief Retrieves the property which this constraint is targeting.
484 * @return The target property
486 Dali::Property::Index GetTargetProperty();
489 * @brief Sets the remove action. Constraint::BAKE will "bake" a value when fully-applied.
491 * In case of Constraint::DISCARD, the constrained value will be discarded, when the constraint is removed.
492 * The default value is Constraint::BAKE.
494 * @param[in] action The remove-action
496 void SetRemoveAction(RemoveAction action);
499 * @brief Retrieves the remove action that will happen when the constraint is removed.
502 * @return The remove-action
504 RemoveAction GetRemoveAction() const;
507 * @brief Sets a tag for the constraint so it can be identified later.
510 * @param[in] tag An integer to identify the constraint
512 void SetTag(const uint32_t tag);
515 * @brief Gets the tag.
520 uint32_t GetTag() const;
522 public: // Not intended for use by Application developers
525 * @brief This constructor is used by Constraint::New() methods.
527 * @param[in] constraint A pointer to a newly allocated Dali resource
529 explicit DALI_INTERNAL Constraint(Internal::ConstraintBase* constraint);
532 private: // Not intended for use by Application developers
535 * @brief Constructs a new constraint which targets a property.
538 * @param[in] handle The handle to the property-owning object
539 * @param[in] targetIndex The index of the property to constrain
540 * @param[in] targetType Type The type of the constrained property
541 * @param[in] function The constraint function
542 * @return The new constraint
544 static Constraint New(Handle handle, Property::Index targetIndex, Property::Type targetType, CallbackBase* function);
553 #endif // DALI_CONSTRAINT_H