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