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