1 #ifndef __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
2 #define __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
5 * Copyright (c) 2014 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 <boost/function.hpp>
25 #include <dali/public-api/common/set-wrapper.h>
26 #include <dali/internal/common/event-to-update.h>
27 #include <dali/internal/common/message.h>
28 #include <dali/internal/event/common/proxy-object.h>
29 #include <dali/internal/event/common/thread-local-storage.h>
30 #include <dali/internal/event/common/stage-impl.h>
31 #include <dali/internal/event/animation/active-constraint-base.h>
32 #include <dali/internal/event/animation/constraint-source-impl.h>
33 #include <dali/internal/event/animation/property-constraint-ptr.h>
34 #include <dali/internal/update/common/animatable-property.h>
35 #include <dali/internal/update/common/property-owner.h>
36 #include <dali/internal/update/common/property-owner-messages.h>
37 #include <dali/internal/update/animation/scene-graph-constraint.h>
38 #include <dali/internal/update/animation/property-accessor.h>
39 #include <dali/internal/update/animation/property-component-accessor.h>
47 typedef std::set<ProxyObject*> ProxyObjectContainer;
48 typedef ProxyObjectContainer::iterator ProxyObjectIter;
51 * Connects a constraint which takes another property as an input.
53 template < typename PropertyType >
54 class ActiveConstraint : public ActiveConstraintBase, public ProxyObject::Observer
58 typedef SceneGraph::Constraint< PropertyType, PropertyAccessor<PropertyType> > SceneGraphConstraint;
59 typedef const SceneGraph::AnimatableProperty<PropertyType>* ScenePropertyPtr;
60 typedef typename PropertyConstraintPtr<PropertyType>::Type ConstraintFunctionPtr;
61 typedef boost::function< PropertyType (const PropertyType&, const PropertyType&, float) > InterpolatorFunction;
64 * Construct a new active-constraint.
65 * @param[in] targetIndex The index of the property to constrain.
66 * @param[in] sources The sources of the input properties passed to func.
67 * @param[in] func The constraint function.
68 * @param[in] interpolator The interpolator function.
69 * @return A newly allocated active-constraint.
71 static ActiveConstraintBase* New( Property::Index targetIndex,
72 SourceContainer& sources,
73 ConstraintFunctionPtr func,
74 InterpolatorFunction interpolator )
76 ThreadLocalStorage& tls = ThreadLocalStorage::Get();
78 return new ActiveConstraint< PropertyType >( tls.GetEventToUpdate(), targetIndex, sources, sources.size(), func, interpolator );
84 virtual ~ActiveConstraint()
88 // This is not responsible for removing constraints.
92 * @copydoc ActiveConstraintBase::Clone()
94 virtual ActiveConstraintBase* Clone()
96 ActiveConstraintBase* clone( NULL );
98 ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
100 clone = new ActiveConstraint< PropertyType >( mEventToUpdate,
105 mInterpolatorFunction );
107 clone->SetRemoveTime(mRemoveTime);
108 clone->SetAlphaFunction(mAlphaFunction);
109 clone->SetRemoveAction(mRemoveAction);
110 clone->SetTag( mTag );
116 * @copydoc ActiveConstraintBase::OnCustomWeightSet()
118 virtual void OnCustomWeightSet( ProxyObject& weightObject )
120 ObserveProxy( weightObject );
124 * @copydoc ActiveConstraintBase::OnFirstApply()
126 virtual void OnFirstApply( ProxyObject& parent )
128 DALI_ASSERT_ALWAYS( NULL == mTargetProxy && "Parent of ActiveConstraint already set" );
130 // No need to do anything, if the source objects are gone
131 if( mSources.size() == mSourceCount )
133 mTargetProxy = &parent;
135 ObserveProxy( parent );
142 * @copydoc ActiveConstraintBase::OnBeginRemove()
144 virtual void OnBeginRemove()
146 // Stop observing the remaining proxies
149 // Discard all proxy pointers
154 * @copydoc ProxyObject::Observer::SceneObjectAdded()
156 virtual void SceneObjectAdded( ProxyObject& proxy )
158 // Should not be getting callbacks when mSources has been cleared
159 DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
168 * @copydoc ProxyObject::Observer::SceneObjectRemoved()
170 virtual void SceneObjectRemoved( ProxyObject& proxy )
172 // Notify base class that the scene-graph constraint is being removed
173 OnSceneObjectRemove();
175 if ( mSceneGraphConstraint )
177 // Preserve the previous weight
178 mOffstageWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
180 // This is not responsible for removing constraints.
181 mSceneGraphConstraint = NULL;
186 * @copydoc ProxyObject::Observer::ProxyDestroyed()
188 virtual void ProxyDestroyed( ProxyObject& proxy )
190 // Remove proxy pointer from observation set
191 ProxyObjectIter iter = mObservedProxies.find( &proxy );
192 DALI_ASSERT_DEBUG( mObservedProxies.end() != iter );
193 mObservedProxies.erase( iter );
195 // Stop observing the remaining proxies
198 // Discard all proxy pointers
206 * Private constructor; see also ActiveConstraint::New().
208 ActiveConstraint( EventToUpdate& eventToUpdate,
209 Property::Index targetIndex,
210 SourceContainer& sources,
211 unsigned int sourceCount,
212 ConstraintFunctionPtr& func,
213 InterpolatorFunction& interpolator )
214 : ActiveConstraintBase( eventToUpdate, targetIndex ),
215 mTargetIndex( targetIndex ),
217 mSourceCount( sourceCount ),
218 mUserFunction( func ),
219 mInterpolatorFunction( interpolator )
221 // Skip init when any of the proxy objects have been destroyed
222 if ( mSources.size() != mSourceCount )
224 // Discard all proxy pointers
229 // Observe the objects providing properties
230 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
232 if ( OBJECT_PROPERTY == iter->sourceType )
234 DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" );
236 ObserveProxy( *(iter->object) );
242 ActiveConstraint( const ActiveConstraint& );
245 ActiveConstraint& operator=( const ActiveConstraint& rhs );
248 * Helper to observe a proxy, if not already observing it
250 void ObserveProxy( ProxyObject& proxy )
252 if ( mObservedProxies.end() == mObservedProxies.find(&proxy) )
254 proxy.AddObserver( *this );
255 mObservedProxies.insert( &proxy );
260 * Helper to stop observing proxies
262 void StopObservation()
264 for( ProxyObjectIter iter = mObservedProxies.begin(); mObservedProxies.end() != iter; ++iter )
266 (*iter)->RemoveObserver( *this );
269 mObservedProxies.clear();
273 * Create and connect a constraint for a scene-object.
275 void ConnectConstraint()
277 // Should not come here any proxies have been destroyed
278 DALI_ASSERT_DEBUG( NULL != mTargetProxy );
279 DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
281 // Guard against double connections
282 DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
284 // Short-circuit until the target scene-object exists
285 SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetProxy->GetSceneObject() );
286 if ( NULL == targetObject )
291 // Build a set of property-owners, providing the scene-graph properties
292 SceneGraph::PropertyOwnerSet propertyOwners;
293 propertyOwners.insert( targetObject );
295 // Build the constraint function; this requires a scene-graph property from each source
296 ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
300 // Create the SceneGraphConstraint, and connect to the scene-graph
302 const SceneGraph::PropertyBase* targetProperty = mTargetProxy->GetSceneObjectAnimatableProperty( mTargetIndex );
304 // The targetProperty should exist, when targetObject exists
305 DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
307 // Connect the constraint
308 SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
311 mInterpolatorFunction,
313 DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
314 sceneGraphConstraint->SetInitialWeight( mOffstageWeight );
315 sceneGraphConstraint->SetRemoveAction( mRemoveAction );
317 // object is being used in a separate thread; queue a message to apply the constraint
318 ApplyConstraintMessage( Stage::GetCurrent()->GetUpdateInterface(), *targetObject, *sceneGraphConstraint );
320 // Keep a raw-pointer to the scene-graph constraint
321 mSceneGraphConstraint = sceneGraphConstraint;
323 // Notify ProxyObject base-class that the scene-graph constraint has been added
329 * Helper for ConnectConstraint. Creates a connected constraint-function.
330 * Also populates the property-owner set, for each input connected to the constraint-function.
331 * @param[out] propertyOwners The set of property-owners providing the scene-graph properties.
332 * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
334 PropertyConstraintBase<PropertyType>* ConnectConstraintFunction( SceneGraph::PropertyOwnerSet& propertyOwners )
336 PropertyConstraintBase<PropertyType>* func = mUserFunction->Clone();
337 bool usingComponentFunc( false );
339 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
341 Source& source = *iter;
343 PropertyInputImpl* inputProperty( NULL );
344 int componentIndex( Property::INVALID_COMPONENT_INDEX );
346 if ( OBJECT_PROPERTY == source.sourceType )
348 DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
350 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
352 // The property owner will not exist, if the target proxy-object is off-stage
355 propertyOwners.insert( owner );
356 inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
357 componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
359 // The scene-object property should exist, when the property owner exists
360 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
363 else if ( LOCAL_PROPERTY == source.sourceType )
365 DALI_ASSERT_ALWAYS( mTargetProxy->IsPropertyAConstraintInput( source.propertyIndex ) );
367 inputProperty = const_cast< PropertyInputImpl* >( mTargetProxy->GetSceneObjectInputProperty( source.propertyIndex ) );
368 componentIndex = mTargetProxy->GetPropertyComponentIndex( source.propertyIndex );
370 // The target scene-object should provide this property
371 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
375 DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
377 ProxyObject* proxyParent = dynamic_cast< Actor& >( *mTargetProxy ).GetParent();
379 // This will not exist, if the target proxy-object is off-stage
380 if ( NULL != proxyParent )
382 DALI_ASSERT_ALWAYS( proxyParent->IsPropertyAConstraintInput( source.propertyIndex ) );
384 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( proxyParent->GetSceneObject() );
386 // The property owner will not exist, if the parent proxy-object is off-stage
389 propertyOwners.insert( owner );
390 inputProperty = const_cast< PropertyInputImpl* >( proxyParent->GetSceneObjectInputProperty( source.propertyIndex ) );
391 componentIndex = proxyParent->GetPropertyComponentIndex( source.propertyIndex );
393 // The scene-object property should exist, when the property owner exists
394 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
399 if ( NULL == inputProperty )
404 // Exit if a scene-graph object is not available from one of the sources
407 else if ( Property::INVALID_COMPONENT_INDEX != componentIndex )
409 // Special case where component indices are required
410 if ( !usingComponentFunc )
412 PropertyConstraintBase<PropertyType>* componentFunc = func->CloneComponentFunc();
413 usingComponentFunc = true;
415 // Switch to function supporting component indices
417 func = componentFunc;
421 func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
429 Property::Index mTargetIndex;
431 SourceContainer mSources;
432 unsigned int mSourceCount;
434 ProxyObjectContainer mObservedProxies; // We don't observe the same object twice
436 ConstraintFunctionPtr mUserFunction;
437 InterpolatorFunction mInterpolatorFunction;
441 * Variant which allows float components to be animated individually.
444 class ActiveConstraint<float> : public ActiveConstraintBase, public ProxyObject::Observer
448 typedef typename PropertyConstraintPtr<float>::Type ConstraintFunctionPtr;
449 typedef boost::function< float (const float&, const float&, float) > InterpolatorFunction;
452 * Construct a new active-constraint.
453 * @param[in] targetIndex The index of the property to constrain.
454 * @param[in] sources The sources of the input properties passed to func.
455 * @param[in] func The constraint function.
456 * @param[in] interpolator The interpolator function.
457 * @return A newly allocated active-constraint.
459 static ActiveConstraintBase* New( Property::Index targetIndex,
460 SourceContainer& sources,
461 ConstraintFunctionPtr func,
462 InterpolatorFunction interpolator )
464 ThreadLocalStorage& tls = ThreadLocalStorage::Get();
466 return new ActiveConstraint< float >( tls.GetEventToUpdate(), targetIndex, sources, sources.size(), func, interpolator );
470 * Virtual destructor.
472 virtual ~ActiveConstraint()
476 // This is not responsible for removing constraints.
480 * @copydoc ActiveConstraintBase::Clone()
482 virtual ActiveConstraintBase* Clone()
484 ActiveConstraintBase* clone( NULL );
486 ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
488 clone = new ActiveConstraint< float >( mEventToUpdate,
493 mInterpolatorFunction );
495 clone->SetRemoveTime(mRemoveTime);
496 clone->SetAlphaFunction(mAlphaFunction);
497 clone->SetRemoveAction(mRemoveAction);
498 clone->SetTag( mTag );
504 * @copydoc ActiveConstraintBase::OnCustomWeightSet()
506 virtual void OnCustomWeightSet( ProxyObject& weightObject )
508 ObserveProxy( weightObject );
512 * @copydoc ActiveConstraintBase::OnFirstApply()
514 virtual void OnFirstApply( ProxyObject& parent )
516 DALI_ASSERT_ALWAYS( NULL == mTargetProxy && "Parent of ActiveConstraint already set" );
518 // No need to do anything, if the source objects are gone
519 if( mSources.size() == mSourceCount )
521 mTargetProxy = &parent;
523 ObserveProxy( parent );
530 * @copydoc ActiveConstraintBase::OnBeginRemove()
532 virtual void OnBeginRemove()
534 // Stop observing the remaining proxies
537 // Discard all proxy pointers
542 * @copydoc ProxyObject::Observer::SceneObjectAdded()
544 virtual void SceneObjectAdded( ProxyObject& proxy )
546 // Should not be getting callbacks when mSources has been cleared
547 DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
556 * @copydoc ProxyObject::Observer::SceneObjectRemoved()
558 virtual void SceneObjectRemoved( ProxyObject& proxy )
560 // Notify base class that the scene-graph constraint is being removed
561 OnSceneObjectRemove();
563 if ( mSceneGraphConstraint )
565 // Preserve the previous weight
566 mOffstageWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
568 // This is not responsible for removing constraints.
569 mSceneGraphConstraint = NULL;
574 * @copydoc ProxyObject::Observer::ProxyDestroyed()
576 virtual void ProxyDestroyed( ProxyObject& proxy )
578 // Remove proxy pointer from observation set
579 ProxyObjectIter iter = mObservedProxies.find( &proxy );
580 DALI_ASSERT_DEBUG( mObservedProxies.end() != iter );
581 mObservedProxies.erase( iter );
583 // Stop observing the remaining proxies
586 // Discard all proxy pointers
594 * Private constructor; see also ActiveConstraint::New().
596 ActiveConstraint( EventToUpdate& eventToUpdate,
597 Property::Index targetIndex,
598 SourceContainer& sources,
599 unsigned int sourceCount,
600 ConstraintFunctionPtr& func,
601 InterpolatorFunction& interpolator )
602 : ActiveConstraintBase( eventToUpdate, targetIndex ),
603 mTargetIndex( targetIndex ),
605 mSourceCount( sourceCount ),
606 mUserFunction( func ),
607 mInterpolatorFunction( interpolator )
609 // Skip init when any of the proxy objects have been destroyed
610 if ( mSources.size() != mSourceCount )
612 // Discard all proxy pointers
617 // Observe the objects providing properties
618 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
620 if ( OBJECT_PROPERTY == iter->sourceType )
622 DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" );
624 ObserveProxy( *(iter->object) );
630 ActiveConstraint( const ActiveConstraint& );
633 ActiveConstraint& operator=( const ActiveConstraint& rhs );
636 * Helper to observe a proxy, if not already observing it
638 void ObserveProxy( ProxyObject& proxy )
640 if ( mObservedProxies.end() == mObservedProxies.find(&proxy) )
642 proxy.AddObserver( *this );
643 mObservedProxies.insert( &proxy );
648 * Helper to stop observing proxies
650 void StopObservation()
652 for( ProxyObjectIter iter = mObservedProxies.begin(); mObservedProxies.end() != iter; ++iter )
654 (*iter)->RemoveObserver( *this );
657 mObservedProxies.clear();
661 * Create and connect a constraint for a scene-object.
663 void ConnectConstraint()
665 // Should not come here any proxies have been destroyed
666 DALI_ASSERT_DEBUG( NULL != mTargetProxy );
667 DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
669 // Guard against double connections
670 DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
672 // Short-circuit until the target scene-object exists
673 SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetProxy->GetSceneObject() );
674 if ( NULL == targetObject )
679 // Build a set of property-owners, providing the scene-graph properties
680 SceneGraph::PropertyOwnerSet propertyOwners;
681 propertyOwners.insert( targetObject );
683 // Build the constraint function; this requires a scene-graph property from each source
684 ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
688 // Create the SceneGraphConstraint, and connect to the scene-graph
690 const SceneGraph::PropertyBase* targetProperty = mTargetProxy->GetSceneObjectAnimatableProperty( mTargetIndex );
692 // The targetProperty should exist, when targetObject exists
693 DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
695 const int componentIndex = mTargetProxy->GetPropertyComponentIndex( mTargetIndex );
697 SceneGraph::ConstraintBase* sceneGraphConstraint( NULL );
699 if ( Property::INVALID_COMPONENT_INDEX == componentIndex )
701 // Not a Vector3 or Vector4 component, expecting float type
702 DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() );
704 typedef SceneGraph::Constraint< float, PropertyAccessor<float> > SceneGraphConstraint;
706 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
709 mInterpolatorFunction,
714 // Expecting Vector3 or Vector4 type
716 if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
718 // Constrain float component of Vector3 property
720 if ( 0 == componentIndex )
722 typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
723 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
725 else if ( 1 == componentIndex )
727 typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
728 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
730 else if ( 2 == componentIndex )
732 typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
733 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
736 else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
738 // Constrain float component of Vector4 property
740 if ( 0 == componentIndex )
742 typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> > SceneGraphConstraint;
743 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
745 else if ( 1 == componentIndex )
747 typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> > SceneGraphConstraint;
748 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
750 else if ( 2 == componentIndex )
752 typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> > SceneGraphConstraint;
753 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
755 else if ( 3 == componentIndex )
757 typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
758 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
763 DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
764 sceneGraphConstraint->SetInitialWeight( mOffstageWeight );
765 sceneGraphConstraint->SetRemoveAction( mRemoveAction );
767 // object is being used in a separate thread; queue a message to apply the constraint
768 ApplyConstraintMessage( Stage::GetCurrent()->GetUpdateInterface(), *targetObject, *sceneGraphConstraint );
770 // Keep a raw-pointer to the scene-graph constraint
771 mSceneGraphConstraint = sceneGraphConstraint;
773 // Notify ProxyObject base-class that the scene-graph constraint has been added
779 * Helper for ConnectConstraint. Creates a connected constraint-function.
780 * Also populates the property-owner set, for each input connected to the constraint-function.
781 * @param[out] propertyOwners The set of property-owners providing the scene-graph properties.
782 * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
784 PropertyConstraintBase<float>* ConnectConstraintFunction( SceneGraph::PropertyOwnerSet& propertyOwners )
786 PropertyConstraintBase<float>* func = mUserFunction->Clone();
787 bool usingComponentFunc( false );
789 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
791 Source& source = *iter;
793 PropertyInputImpl* inputProperty( NULL );
794 int componentIndex( Property::INVALID_COMPONENT_INDEX );
796 if ( OBJECT_PROPERTY == source.sourceType )
798 DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
800 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
802 // The property owner will not exist, if the target proxy-object is off-stage
805 propertyOwners.insert( owner );
806 inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
807 componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
809 // The scene-object property should exist, when the property owner exists
810 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
813 else if ( LOCAL_PROPERTY == source.sourceType )
815 DALI_ASSERT_ALWAYS( mTargetProxy->IsPropertyAConstraintInput( source.propertyIndex ) );
817 inputProperty = const_cast< PropertyInputImpl* >( mTargetProxy->GetSceneObjectInputProperty( source.propertyIndex ) );
818 componentIndex = mTargetProxy->GetPropertyComponentIndex( source.propertyIndex );
820 // The target scene-object should provide this property
821 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
825 DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
827 ProxyObject* proxyParent = dynamic_cast< Actor& >( *mTargetProxy ).GetParent();
829 // This will not exist, if the target proxy-object is off-stage
830 if ( NULL != proxyParent )
832 DALI_ASSERT_ALWAYS( proxyParent->IsPropertyAConstraintInput( source.propertyIndex ) );
834 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( proxyParent->GetSceneObject() );
836 // The property owner will not exist, if the parent proxy-object is off-stage
839 propertyOwners.insert( owner );
840 inputProperty = const_cast< PropertyInputImpl* >( proxyParent->GetSceneObjectInputProperty( source.propertyIndex ) );
841 componentIndex = proxyParent->GetPropertyComponentIndex( source.propertyIndex );
843 // The scene-object property should exist, when the property owner exists
844 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
849 if ( NULL == inputProperty )
854 // Exit if a scene-graph object is not available from one of the sources
857 else if ( Property::INVALID_COMPONENT_INDEX != componentIndex )
859 // Special case where component indices are required
860 if ( !usingComponentFunc )
862 PropertyConstraintBase<float>* componentFunc = func->CloneComponentFunc();
863 usingComponentFunc = true;
865 // Switch to function supporting component indices
867 func = componentFunc;
871 func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
879 Property::Index mTargetIndex;
881 SourceContainer mSources;
882 unsigned int mSourceCount;
884 ProxyObjectContainer mObservedProxies; // We don't observe the same object twice
886 ConstraintFunctionPtr mUserFunction;
887 InterpolatorFunction mInterpolatorFunction;
890 } // namespace Internal
894 #endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__