Refactor SceneGraphProperty handling code in event side to make RegisterProperty...
[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) 2018 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  * Helper to add only unique entries to the propertyOwner container
47  * @param propertyOwners to add the entries to
48  * @param object to add
49  */
50 inline void AddUnique( SceneGraph::PropertyOwnerContainer& propertyOwners, SceneGraph::PropertyOwner* object )
51 {
52   const SceneGraph::PropertyOwnerIter iter = std::find( propertyOwners.Begin(), propertyOwners.End(), object );
53   if( iter == propertyOwners.End() )
54   {
55     // each owner should only be added once
56     propertyOwners.PushBack( object );
57   }
58 }
59
60 /**
61  * Connects a constraint which takes another property as an input.
62  */
63 template < typename PropertyType >
64 class Constraint : public ConstraintBase
65 {
66 public:
67
68   typedef SceneGraph::Constraint< PropertyType, PropertyAccessor<PropertyType> > SceneGraphConstraint;
69   typedef const SceneGraph::AnimatableProperty<PropertyType>* ScenePropertyPtr;
70   typedef typename PropertyConstraintPtr<PropertyType>::Type ConstraintFunctionPtr;
71   typedef const SceneGraph::TransformManagerPropertyHandler<PropertyType> TransformManagerProperty;
72
73   /**
74    * Construct a new constraint.
75    * @param[in] object The property-owning object.
76    * @param[in] targetIndex The index of the property to constrain.
77    * @param[in] sources The sources of the input properties passed to func.
78    * @param[in] func The constraint function.
79    * @return A newly allocated active-constraint.
80    */
81   static ConstraintBase* New( Object& object,
82                               Property::Index targetIndex,
83                               SourceContainer& sources,
84                               ConstraintFunctionPtr func )
85   {
86     return new Constraint< PropertyType >( object, targetIndex, sources, func );
87   }
88
89   /**
90    * @copydoc ConstraintBase::Clone()
91    */
92   virtual ConstraintBase* Clone( Object& object )
93   {
94     DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
95
96     ConstraintBase* clone( NULL );
97
98     ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
99
100     clone = new Constraint< PropertyType >( object,
101                                             mTargetIndex,
102                                             mSources,
103                                             funcPtr );
104
105     clone->SetRemoveAction(mRemoveAction);
106     clone->SetTag( mTag );
107
108     return clone;
109   }
110
111
112   /**
113    * Virtual destructor.
114    */
115   virtual ~Constraint()
116   {
117     // This is not responsible for removing constraints.
118   }
119
120 private:
121
122   /**
123    * Private constructor; see also Constraint::New().
124    */
125   Constraint( Object& object,
126               Property::Index targetIndex,
127               SourceContainer& sources,
128               ConstraintFunctionPtr& func )
129   : ConstraintBase( object, targetIndex, sources ),
130     mTargetIndex( targetIndex ),
131     mUserFunction( func )
132   {
133   }
134
135   // Undefined
136   Constraint( const Constraint& );
137
138   // Undefined
139   Constraint& operator=( const Constraint& rhs );
140
141   /**
142    * Create and connect a constraint and property resetter for a scene-graph property
143    */
144   void ConnectConstraint()
145   {
146     // Should not come here if target object has been destroyed
147     DALI_ASSERT_DEBUG( NULL != mTargetObject );
148
149     // Guard against double connections
150     DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
151
152     SceneGraph::PropertyOwner& targetObject = const_cast< SceneGraph::PropertyOwner& >( mTargetObject->GetSceneObject() );
153
154     // Build a container of property-owners, providing the scene-graph properties
155     SceneGraph::PropertyOwnerContainer propertyOwners;
156     propertyOwners.PushBack( &targetObject );
157
158     // Build the constraint function; this requires a scene-graph property from each source
159     ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
160
161     if ( func )
162     {
163       // Create the SceneGraphConstraint and PropertyResetter, and connect them to the scene-graph
164
165       const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
166       OwnerPointer<SceneGraph::PropertyResetterBase> resetter;
167
168       // The targetProperty should exist, when targetObject exists
169       DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
170
171       if( targetProperty->IsTransformManagerProperty() )  //It is a property managed by the transform manager
172       {
173         // Connect the constraint
174         mSceneGraphConstraint =
175           SceneGraph::Constraint<PropertyType, TransformManagerPropertyAccessor<PropertyType> >::New( *targetProperty,
176                                                                                                       propertyOwners,
177                                                                                                       func,
178                                                                                                       mRemoveAction );
179         // Don't create a resetter for transform manager property, it's less efficient
180       }
181       else  //SceneGraph property
182       {
183         // Connect the constraint
184         mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
185                                                            propertyOwners,
186                                                            func,
187                                                            mRemoveAction );
188         // Connect the resetter
189         resetter = SceneGraph::ConstraintResetter::New( targetObject, *targetProperty, *mSceneGraphConstraint );
190
191       }
192       OwnerPointer< SceneGraph::ConstraintBase > transferOwnership( const_cast< SceneGraph::ConstraintBase* >( mSceneGraphConstraint ) );
193       ApplyConstraintMessage( GetEventThreadServices(), targetObject, transferOwnership );
194
195       if( resetter != nullptr )
196       {
197         AddResetterMessage( GetEventThreadServices().GetUpdateManager(), resetter );
198       }
199     }
200   }
201
202   /**
203    * Helper for ConnectConstraint. Creates a connected constraint-function.
204    * Also populates the property-owner container, for each input connected to the constraint-function.
205    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
206    * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
207    */
208   PropertyConstraint<PropertyType>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
209   {
210     PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
211
212     for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
213     {
214       Source& source = *iter;
215
216       PropertyInputImpl* inputProperty( NULL );
217       int componentIndex( Property::INVALID_COMPONENT_INDEX );
218
219       if ( OBJECT_PROPERTY == source.sourceType )
220       {
221         DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
222
223         SceneGraph::PropertyOwner& owner = const_cast< SceneGraph::PropertyOwner& >( source.object->GetSceneObject() );
224
225         AddUnique( propertyOwners, &owner );
226         inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
227         componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
228
229         // The scene-object property should exist, when the property owner exists
230         DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
231       }
232       else if ( LOCAL_PROPERTY == source.sourceType )
233       {
234         DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
235
236         inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
237         componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
238
239         // The target scene-object should provide this property
240         DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
241       }
242       else
243       {
244         DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
245
246         Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
247
248         // This will not exist, if the target object is off-stage
249         if ( NULL != objectParent )
250         {
251           DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
252
253           SceneGraph::PropertyOwner& owner = const_cast< SceneGraph::PropertyOwner& >( objectParent->GetSceneObject() );
254
255           AddUnique( propertyOwners, &owner );
256           inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
257           componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
258
259           // The scene-object property should exist, when the property owner exists
260           DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
261         }
262       }
263
264       if ( NULL == inputProperty )
265       {
266         delete func;
267         func = NULL;
268
269         // Exit if a scene-graph object is not available from one of the sources
270         break;
271       }
272
273       func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
274     }
275
276     return func;
277   }
278
279 protected:
280
281   Property::Index mTargetIndex;
282
283   ConstraintFunctionPtr mUserFunction;
284 };
285
286 /**
287  * Variant which allows float components to be animated individually.
288  */
289 template <>
290 class Constraint<float> : public ConstraintBase
291 {
292 public:
293
294   typedef typename PropertyConstraintPtr<float>::Type ConstraintFunctionPtr;
295
296   /**
297    * Construct a new constraint.
298    * @param[in] object The property-owning object.
299    * @param[in] targetIndex The index of the property to constrain.
300    * @param[in] sources The sources of the input properties passed to func.
301    * @param[in] func The constraint function.
302    * @return A newly allocated constraint.
303    */
304   static ConstraintBase* New( Object& object,
305                               Property::Index targetIndex,
306                               SourceContainer& sources,
307                               ConstraintFunctionPtr func )
308   {
309     return new Constraint< float >( object, targetIndex, sources, func );
310   }
311
312   /**
313    * @copydoc ConstraintBase::Clone()
314    */
315   virtual ConstraintBase* Clone( Object& object )
316   {
317     DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
318
319     ConstraintBase* clone( NULL );
320
321     ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
322
323     clone = new Constraint< float >( object,
324                                      mTargetIndex,
325                                      mSources,
326                                      funcPtr );
327
328     clone->SetRemoveAction(mRemoveAction);
329     clone->SetTag( mTag );
330
331     return clone;
332   }
333
334   /**
335    * Virtual destructor.
336    */
337   virtual ~Constraint()
338   {
339     // This is not responsible for removing constraints.
340   }
341
342 private:
343
344   /**
345    * Private constructor; see also Constraint::New().
346    */
347   Constraint( Object& object,
348               Property::Index targetIndex,
349               SourceContainer& sources,
350               ConstraintFunctionPtr& func )
351   : ConstraintBase( object, targetIndex, sources ),
352     mTargetIndex( targetIndex ),
353     mUserFunction( func )
354   {
355   }
356
357   // Undefined
358   Constraint( const Constraint& );
359
360   // Undefined
361   Constraint& operator=( const Constraint& rhs );
362
363   /**
364    * Create and connect a constraint for a scene-object.
365    */
366   void ConnectConstraint()
367   {
368     // Should not come here if target-object has been destroyed
369     DALI_ASSERT_DEBUG( NULL != mTargetObject );
370
371     // Guard against double connections
372     DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
373
374     // Short-circuit until the target scene-object exists
375     SceneGraph::PropertyOwner& targetObject = const_cast< SceneGraph::PropertyOwner& >( mTargetObject->GetSceneObject() );
376
377     // Build a container of property-owners, providing the scene-graph properties
378     SceneGraph::PropertyOwnerContainer propertyOwners;
379     propertyOwners.PushBack( &targetObject );
380
381     // Build the constraint function; this requires a scene-graph property from each source
382     ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
383
384     if ( func )
385     {
386       // Create the SceneGraphConstraint, and connect to the scene-graph
387
388       const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
389       OwnerPointer<SceneGraph::PropertyResetterBase> resetter;
390
391       // The targetProperty should exist, when targetObject exists
392       DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
393
394       const int componentIndex = mTargetObject->GetPropertyComponentIndex( mTargetIndex );
395
396       if ( Property::INVALID_COMPONENT_INDEX == componentIndex )
397       {
398         // Not a Vector2, Vector3 or Vector4 component, expecting float type
399         DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() );
400
401         typedef SceneGraph::Constraint< float, PropertyAccessor<float> > SceneGraphConstraint;
402
403         mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
404         resetter = SceneGraph::ConstraintResetter::New( targetObject, *targetProperty, *mSceneGraphConstraint );
405       }
406       else
407       {
408         // Expecting Vector2, Vector3 or Vector4 type
409
410         if ( PropertyTypes::Get< Vector2 >() == targetProperty->GetType() )
411         {
412           // Constrain float component of Vector2 property
413
414           if ( 0 == componentIndex )
415           {
416             typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector2> > SceneGraphConstraint;
417             mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
418           }
419           else if ( 1 == componentIndex )
420           {
421             typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector2> > SceneGraphConstraint;
422             mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
423           }
424           if( mSceneGraphConstraint )
425           {
426             resetter = SceneGraph::ConstraintResetter::New( targetObject, *targetProperty, *mSceneGraphConstraint );
427           }
428         }
429         else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
430         {
431           // Constrain float component of Vector3 property
432           if( targetProperty->IsTransformManagerProperty() )
433           {
434             if ( 0 == componentIndex )
435             {
436               typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,0> > SceneGraphConstraint;
437               mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
438             }
439             else if ( 1 == componentIndex )
440             {
441               typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,1> > SceneGraphConstraint;
442               mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
443             }
444             else if ( 2 == componentIndex )
445             {
446               typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,2> > SceneGraphConstraint;
447               mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
448             }
449             // Do not create a resetter for transform manager property
450           }
451           else
452           {
453             if ( 0 == componentIndex )
454             {
455               typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
456               mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
457             }
458             else if ( 1 == componentIndex )
459             {
460               typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
461               mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
462             }
463             else if ( 2 == componentIndex )
464             {
465               typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
466               mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
467             }
468             if( mSceneGraphConstraint )
469             {
470               resetter = SceneGraph::ConstraintResetter::New( targetObject, *targetProperty, *mSceneGraphConstraint );
471             }
472           }
473         }
474         else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
475         {
476           // Constrain float component of Vector4 property
477
478           if ( 0 == componentIndex )
479           {
480             typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> > SceneGraphConstraint;
481             mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
482           }
483           else if ( 1 == componentIndex )
484           {
485             typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> > SceneGraphConstraint;
486             mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
487           }
488           else if ( 2 == componentIndex )
489           {
490             typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> > SceneGraphConstraint;
491             mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
492           }
493           else if ( 3 == componentIndex )
494           {
495             typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
496             mSceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mRemoveAction );
497           }
498
499           if( mSceneGraphConstraint )
500           {
501             resetter = SceneGraph::ConstraintResetter::New( targetObject, *targetProperty, *mSceneGraphConstraint );
502           }
503         }
504       }
505
506       if( mSceneGraphConstraint )
507       {
508         OwnerPointer< SceneGraph::ConstraintBase > transferOwnership( const_cast< SceneGraph::ConstraintBase* >( mSceneGraphConstraint ) );
509         ApplyConstraintMessage( GetEventThreadServices(), targetObject, transferOwnership );
510       }
511       if( resetter != nullptr )
512       {
513         AddResetterMessage( GetEventThreadServices().GetUpdateManager(), resetter );
514       }
515     }
516   }
517
518   /**
519    * Helper for ConnectConstraint. Creates a connected constraint-function.
520    * Also populates the property-owner container, for each input connected to the constraint-function.
521    * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
522    * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
523    */
524   PropertyConstraint<float>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
525   {
526     PropertyConstraint<float>* func = mUserFunction->Clone();
527
528     for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
529     {
530       Source& source = *iter;
531
532       PropertyInputImpl* inputProperty( NULL );
533       int componentIndex( Property::INVALID_COMPONENT_INDEX );
534
535       if ( OBJECT_PROPERTY == source.sourceType )
536       {
537         DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
538
539         SceneGraph::PropertyOwner& owner = const_cast< SceneGraph::PropertyOwner& >( source.object->GetSceneObject() );
540
541         // The property owner will not exist, if the target object is off-stage
542         AddUnique( propertyOwners, &owner );
543         inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
544         componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
545
546         // The scene-object property should exist, when the property owner exists
547         DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
548       }
549       else if ( LOCAL_PROPERTY == source.sourceType )
550       {
551         DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
552
553         inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
554         componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
555
556         // The target scene-object should provide this property
557         DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
558       }
559       else
560       {
561         DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
562
563         Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
564
565         // This will not exist, if the target object is off-stage
566         if ( NULL != objectParent )
567         {
568           DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
569
570           SceneGraph::PropertyOwner& owner = const_cast< SceneGraph::PropertyOwner& >( objectParent->GetSceneObject() );
571
572           // The property owner will not exist, if the parent object is off-stage
573           AddUnique( propertyOwners, &owner );
574           inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
575           componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
576
577           // The scene-object property should exist, when the property owner exists
578           DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
579         }
580       }
581
582       if ( NULL == inputProperty )
583       {
584         delete func;
585         func = NULL;
586
587         // Exit if a scene-graph object is not available from one of the sources
588         break;
589       }
590
591       func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
592     }
593
594     return func;
595   }
596
597 protected:
598
599   Property::Index mTargetIndex;
600
601   ConstraintFunctionPtr mUserFunction;
602 };
603
604 } // namespace Internal
605
606 } // namespace Dali
607
608 #endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__