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 Flora License, Version 1.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://floralicense.org/license/
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/internal/common/event-to-update.h>
26 #include <dali/internal/common/message.h>
27 #include <dali/internal/event/common/proxy-object.h>
28 #include <dali/internal/event/common/thread-local-storage.h>
29 #include <dali/internal/event/common/stage-impl.h>
30 #include <dali/internal/event/animation/active-constraint-base.h>
31 #include <dali/internal/event/animation/constraint-source-impl.h>
32 #include <dali/internal/event/animation/property-constraint-ptr.h>
33 #include <dali/internal/update/common/animatable-property.h>
34 #include <dali/internal/update/common/property-owner.h>
35 #include <dali/internal/update/common/property-owner-messages.h>
36 #include <dali/internal/update/animation/scene-graph-constraint.h>
37 #include <dali/internal/update/animation/property-accessor.h>
38 #include <dali/internal/update/animation/property-component-accessor.h>
46 typedef std::set<ProxyObject*> ProxyObjectContainer;
47 typedef ProxyObjectContainer::iterator ProxyObjectIter;
50 * Connects a constraint which takes another property as an input.
52 template < typename PropertyType >
53 class ActiveConstraint : public ActiveConstraintBase, public ProxyObject::Observer
57 typedef SceneGraph::Constraint< PropertyType, PropertyAccessor<PropertyType> > SceneGraphConstraint;
58 typedef const SceneGraph::AnimatableProperty<PropertyType>* ScenePropertyPtr;
59 typedef typename PropertyConstraintPtr<PropertyType>::Type ConstraintFunctionPtr;
60 typedef boost::function< PropertyType (const PropertyType&, const PropertyType&, float) > InterpolatorFunction;
63 * Construct a new active-constraint.
64 * @param[in] targetIndex The index of the property to constrain.
65 * @param[in] sources The sources of the input properties passed to func.
66 * @param[in] func The constraint function.
67 * @param[in] interpolator The interpolator function.
68 * @return A newly allocated active-constraint.
70 static ActiveConstraintBase* New( Property::Index targetIndex,
71 SourceContainer& sources,
72 ConstraintFunctionPtr func,
73 InterpolatorFunction interpolator )
75 ThreadLocalStorage& tls = ThreadLocalStorage::Get();
77 return new ActiveConstraint< PropertyType >( tls.GetEventToUpdate(), targetIndex, sources, sources.size(), func, interpolator );
83 virtual ~ActiveConstraint()
87 // This is not responsible for removing constraints.
91 * @copydoc ActiveConstraintBase::Clone()
93 virtual ActiveConstraintBase* Clone()
95 ActiveConstraintBase* clone( NULL );
97 ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
99 clone = new ActiveConstraint< PropertyType >( mEventToUpdate,
104 mInterpolatorFunction );
106 clone->SetRemoveTime(mRemoveTime);
107 clone->SetAlphaFunction(mAlphaFunction);
108 clone->SetRemoveAction(mRemoveAction);
109 clone->SetTag( mTag );
115 * @copydoc ActiveConstraintBase::OnFirstApply()
117 virtual void OnFirstApply( ProxyObject& parent )
119 DALI_ASSERT_ALWAYS( NULL == mTargetProxy && "Parent of ActiveConstraint already set" );
121 // No need to do anything, if the source objects are gone
122 if( mSources.size() == mSourceCount )
124 mTargetProxy = &parent;
126 ObserveProxy( parent );
133 * @copydoc ActiveConstraintBase::OnBeginRemove()
135 virtual void OnBeginRemove()
137 // Stop observing the remaining proxies
140 // Discard all proxy pointers
145 * @copydoc ProxyObject::Observer::SceneObjectAdded()
147 virtual void SceneObjectAdded( ProxyObject& proxy )
149 // Should not be getting callbacks when mSources has been cleared
150 DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
159 * @copydoc ProxyObject::Observer::SceneObjectRemoved()
161 virtual void SceneObjectRemoved( ProxyObject& proxy )
163 // Notify base class that the scene-graph constraint is being removed
164 OnSceneObjectRemove();
166 if ( mSceneGraphConstraint )
168 // Preserve the previous weight
169 mOffstageWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
171 // This is not responsible for removing constraints.
172 mSceneGraphConstraint = NULL;
177 * @copydoc ProxyObject::Observer::ProxyDestroyed()
179 virtual void ProxyDestroyed( ProxyObject& proxy )
181 // Remove proxy pointer from observation set
182 ProxyObjectIter iter = mObservedProxies.find( &proxy );
183 DALI_ASSERT_DEBUG( mObservedProxies.end() != iter );
184 mObservedProxies.erase( iter );
186 // Stop observing the remaining proxies
189 // Discard all proxy pointers
197 * Private constructor; see also ActiveConstraint::New().
199 ActiveConstraint( EventToUpdate& eventToUpdate,
200 Property::Index targetIndex,
201 SourceContainer& sources,
202 unsigned int sourceCount,
203 ConstraintFunctionPtr& func,
204 InterpolatorFunction& interpolator )
205 : ActiveConstraintBase( eventToUpdate, targetIndex ),
206 mTargetIndex( targetIndex ),
208 mSourceCount( sourceCount ),
209 mUserFunction( func ),
210 mInterpolatorFunction( interpolator )
212 // Skip init when any of the proxy objects have been destroyed
213 if ( mSources.size() != mSourceCount )
215 // Discard all proxy pointers
220 // Observe the objects providing properties
221 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
223 if ( OBJECT_PROPERTY == iter->sourceType )
225 DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" );
227 ObserveProxy( *(iter->object) );
233 ActiveConstraint( const ActiveConstraint& );
236 ActiveConstraint& operator=( const ActiveConstraint& rhs );
239 * Helper to observe a proxy, if not already observing it
241 void ObserveProxy( ProxyObject& proxy )
243 if ( mObservedProxies.end() == mObservedProxies.find(&proxy) )
245 proxy.AddObserver( *this );
246 mObservedProxies.insert( &proxy );
251 * Helper to stop observing proxies
253 void StopObservation()
255 for( ProxyObjectIter iter = mObservedProxies.begin(); mObservedProxies.end() != iter; ++iter )
257 (*iter)->RemoveObserver( *this );
260 mObservedProxies.clear();
264 * Create and connect a constraint for a scene-object.
266 void ConnectConstraint()
268 // Should not come here any proxies have been destroyed
269 DALI_ASSERT_DEBUG( NULL != mTargetProxy );
270 DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
272 // Guard against double connections
273 DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
275 // Short-circuit until the target scene-object exists
276 SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetProxy->GetSceneObject() );
277 if ( NULL == targetObject )
282 // Build a set of property-owners, providing the scene-graph properties
283 SceneGraph::PropertyOwnerSet propertyOwners;
284 propertyOwners.insert( targetObject );
286 // Build the constraint function; this requires a scene-graph property from each source
287 ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
291 // Create the SceneGraphConstraint, and connect to the scene-graph
293 const SceneGraph::PropertyBase* targetProperty = mTargetProxy->GetSceneObjectAnimatableProperty( mTargetIndex );
295 // The targetProperty should exist, when targetObject exists
296 DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
298 // Connect the constraint
299 SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
302 mInterpolatorFunction );
303 DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
304 sceneGraphConstraint->SetInitialWeight( mOffstageWeight );
305 sceneGraphConstraint->SetRemoveAction( mRemoveAction );
307 // object is being used in a separate thread; queue a message to apply the constraint
308 ApplyConstraintMessage( Stage::GetCurrent()->GetUpdateInterface(), *targetObject, *sceneGraphConstraint );
310 // Keep a raw-pointer to the scene-graph constraint
311 mSceneGraphConstraint = sceneGraphConstraint;
313 // Notify ProxyObject base-class that the scene-graph constraint has been added
319 * Helper for ConnectConstraint. Creates a connected constraint-function.
320 * Also populates the property-owner set, for each input connected to the constraint-function.
321 * @param[out] propertyOwners The set of property-owners providing the scene-graph properties.
322 * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
324 PropertyConstraintBase<PropertyType>* ConnectConstraintFunction( SceneGraph::PropertyOwnerSet& propertyOwners )
326 PropertyConstraintBase<PropertyType>* func = mUserFunction->Clone();
327 bool usingComponentFunc( false );
329 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
331 Source& source = *iter;
333 PropertyInputImpl* inputProperty( NULL );
334 int componentIndex( Property::INVALID_COMPONENT_INDEX );
336 if ( OBJECT_PROPERTY == source.sourceType )
338 DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
340 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
342 // The property owner will not exist, if the target proxy-object is off-stage
345 propertyOwners.insert( owner );
346 inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
347 componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
349 // The scene-object property should exist, when the property owner exists
350 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
353 else if ( LOCAL_PROPERTY == source.sourceType )
355 DALI_ASSERT_ALWAYS( mTargetProxy->IsPropertyAConstraintInput( source.propertyIndex ) );
357 inputProperty = const_cast< PropertyInputImpl* >( mTargetProxy->GetSceneObjectInputProperty( source.propertyIndex ) );
358 componentIndex = mTargetProxy->GetPropertyComponentIndex( source.propertyIndex );
360 // The target scene-object should provide this property
361 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
365 DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
367 ProxyObject* proxyParent = dynamic_cast< Actor& >( *mTargetProxy ).GetParent();
369 // This will not exist, if the target proxy-object is off-stage
370 if ( NULL != proxyParent )
372 DALI_ASSERT_ALWAYS( proxyParent->IsPropertyAConstraintInput( source.propertyIndex ) );
374 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( proxyParent->GetSceneObject() );
376 // The property owner will not exist, if the parent proxy-object is off-stage
379 propertyOwners.insert( owner );
380 inputProperty = const_cast< PropertyInputImpl* >( proxyParent->GetSceneObjectInputProperty( source.propertyIndex ) );
381 componentIndex = proxyParent->GetPropertyComponentIndex( source.propertyIndex );
383 // The scene-object property should exist, when the property owner exists
384 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
389 if ( NULL == inputProperty )
394 // Exit if a scene-graph object is not available from one of the sources
397 else if ( Property::INVALID_COMPONENT_INDEX != componentIndex )
399 // Special case where component indices are required
400 if ( !usingComponentFunc )
402 PropertyConstraintBase<PropertyType>* componentFunc = func->CloneComponentFunc();
403 usingComponentFunc = true;
405 // Switch to function supporting component indices
407 func = componentFunc;
411 func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
419 Property::Index mTargetIndex;
421 SourceContainer mSources;
422 unsigned int mSourceCount;
424 ProxyObjectContainer mObservedProxies; // We don't observe the same object twice
426 ConstraintFunctionPtr mUserFunction;
427 InterpolatorFunction mInterpolatorFunction;
431 * Variant which allows float components to be animated individually.
434 class ActiveConstraint<float> : public ActiveConstraintBase, public ProxyObject::Observer
438 typedef typename PropertyConstraintPtr<float>::Type ConstraintFunctionPtr;
439 typedef boost::function< float (const float&, const float&, float) > InterpolatorFunction;
442 * Construct a new active-constraint.
443 * @param[in] targetIndex The index of the property to constrain.
444 * @param[in] sources The sources of the input properties passed to func.
445 * @param[in] func The constraint function.
446 * @param[in] interpolator The interpolator function.
447 * @return A newly allocated active-constraint.
449 static ActiveConstraintBase* New( Property::Index targetIndex,
450 SourceContainer& sources,
451 ConstraintFunctionPtr func,
452 InterpolatorFunction interpolator )
454 ThreadLocalStorage& tls = ThreadLocalStorage::Get();
456 return new ActiveConstraint< float >( tls.GetEventToUpdate(), targetIndex, sources, sources.size(), func, interpolator );
460 * Virtual destructor.
462 virtual ~ActiveConstraint()
466 // This is not responsible for removing constraints.
470 * @copydoc ActiveConstraintBase::Clone()
472 virtual ActiveConstraintBase* Clone()
474 ActiveConstraintBase* clone( NULL );
476 ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
478 clone = new ActiveConstraint< float >( mEventToUpdate,
483 mInterpolatorFunction );
485 clone->SetRemoveTime(mRemoveTime);
486 clone->SetAlphaFunction(mAlphaFunction);
487 clone->SetRemoveAction(mRemoveAction);
488 clone->SetTag( mTag );
494 * @copydoc ActiveConstraintBase::OnFirstApply()
496 virtual void OnFirstApply( ProxyObject& parent )
498 DALI_ASSERT_ALWAYS( NULL == mTargetProxy && "Parent of ActiveConstraint already set" );
500 // No need to do anything, if the source objects are gone
501 if( mSources.size() == mSourceCount )
503 mTargetProxy = &parent;
505 ObserveProxy( parent );
512 * @copydoc ActiveConstraintBase::OnBeginRemove()
514 virtual void OnBeginRemove()
516 // Stop observing the remaining proxies
519 // Discard all proxy pointers
524 * @copydoc ProxyObject::Observer::SceneObjectAdded()
526 virtual void SceneObjectAdded( ProxyObject& proxy )
528 // Should not be getting callbacks when mSources has been cleared
529 DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
538 * @copydoc ProxyObject::Observer::SceneObjectRemoved()
540 virtual void SceneObjectRemoved( ProxyObject& proxy )
542 // Notify base class that the scene-graph constraint is being removed
543 OnSceneObjectRemove();
545 if ( mSceneGraphConstraint )
547 // Preserve the previous weight
548 mOffstageWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
550 // This is not responsible for removing constraints.
551 mSceneGraphConstraint = NULL;
556 * @copydoc ProxyObject::Observer::ProxyDestroyed()
558 virtual void ProxyDestroyed( ProxyObject& proxy )
560 // Remove proxy pointer from observation set
561 ProxyObjectIter iter = mObservedProxies.find( &proxy );
562 DALI_ASSERT_DEBUG( mObservedProxies.end() != iter );
563 mObservedProxies.erase( iter );
565 // Stop observing the remaining proxies
568 // Discard all proxy pointers
576 * Private constructor; see also ActiveConstraint::New().
578 ActiveConstraint( EventToUpdate& eventToUpdate,
579 Property::Index targetIndex,
580 SourceContainer& sources,
581 unsigned int sourceCount,
582 ConstraintFunctionPtr& func,
583 InterpolatorFunction& interpolator )
584 : ActiveConstraintBase( eventToUpdate, targetIndex ),
585 mTargetIndex( targetIndex ),
587 mSourceCount( sourceCount ),
588 mUserFunction( func ),
589 mInterpolatorFunction( interpolator )
591 // Skip init when any of the proxy objects have been destroyed
592 if ( mSources.size() != mSourceCount )
594 // Discard all proxy pointers
599 // Observe the objects providing properties
600 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
602 if ( OBJECT_PROPERTY == iter->sourceType )
604 DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" );
606 ObserveProxy( *(iter->object) );
612 ActiveConstraint( const ActiveConstraint& );
615 ActiveConstraint& operator=( const ActiveConstraint& rhs );
618 * Helper to observe a proxy, if not already observing it
620 void ObserveProxy( ProxyObject& proxy )
622 if ( mObservedProxies.end() == mObservedProxies.find(&proxy) )
624 proxy.AddObserver( *this );
625 mObservedProxies.insert( &proxy );
630 * Helper to stop observing proxies
632 void StopObservation()
634 for( ProxyObjectIter iter = mObservedProxies.begin(); mObservedProxies.end() != iter; ++iter )
636 (*iter)->RemoveObserver( *this );
639 mObservedProxies.clear();
643 * Create and connect a constraint for a scene-object.
645 void ConnectConstraint()
647 // Should not come here any proxies have been destroyed
648 DALI_ASSERT_DEBUG( NULL != mTargetProxy );
649 DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
651 // Guard against double connections
652 DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
654 // Short-circuit until the target scene-object exists
655 SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetProxy->GetSceneObject() );
656 if ( NULL == targetObject )
661 // Build a set of property-owners, providing the scene-graph properties
662 SceneGraph::PropertyOwnerSet propertyOwners;
663 propertyOwners.insert( targetObject );
665 // Build the constraint function; this requires a scene-graph property from each source
666 ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
670 // Create the SceneGraphConstraint, and connect to the scene-graph
672 const SceneGraph::PropertyBase* targetProperty = mTargetProxy->GetSceneObjectAnimatableProperty( mTargetIndex );
674 // The targetProperty should exist, when targetObject exists
675 DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
677 const int componentIndex = mTargetProxy->GetPropertyComponentIndex( mTargetIndex );
679 SceneGraph::ConstraintBase* sceneGraphConstraint( NULL );
681 if ( Property::INVALID_COMPONENT_INDEX == componentIndex )
683 // Not a Vector3 or Vector4 component, expecting float type
684 DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() );
686 typedef SceneGraph::Constraint< float, PropertyAccessor<float> > SceneGraphConstraint;
688 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
691 mInterpolatorFunction );
695 // Expecting Vector3 or Vector4 type
697 if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
699 // Constrain float component of Vector3 property
701 if ( 0 == componentIndex )
703 typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
704 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
706 else if ( 1 == componentIndex )
708 typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
709 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
711 else if ( 2 == componentIndex )
713 typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
714 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
717 else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
719 // Constrain float component of Vector4 property
721 if ( 0 == componentIndex )
723 typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> > SceneGraphConstraint;
724 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
726 else if ( 1 == componentIndex )
728 typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> > SceneGraphConstraint;
729 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
731 else if ( 2 == componentIndex )
733 typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> > SceneGraphConstraint;
734 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
736 else if ( 3 == componentIndex )
738 typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
739 sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
744 DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
745 sceneGraphConstraint->SetInitialWeight( mOffstageWeight );
746 sceneGraphConstraint->SetRemoveAction( mRemoveAction );
748 // object is being used in a separate thread; queue a message to apply the constraint
749 ApplyConstraintMessage( Stage::GetCurrent()->GetUpdateInterface(), *targetObject, *sceneGraphConstraint );
751 // Keep a raw-pointer to the scene-graph constraint
752 mSceneGraphConstraint = sceneGraphConstraint;
754 // Notify ProxyObject base-class that the scene-graph constraint has been added
760 * Helper for ConnectConstraint. Creates a connected constraint-function.
761 * Also populates the property-owner set, for each input connected to the constraint-function.
762 * @param[out] propertyOwners The set of property-owners providing the scene-graph properties.
763 * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
765 PropertyConstraintBase<float>* ConnectConstraintFunction( SceneGraph::PropertyOwnerSet& propertyOwners )
767 PropertyConstraintBase<float>* func = mUserFunction->Clone();
768 bool usingComponentFunc( false );
770 for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
772 Source& source = *iter;
774 PropertyInputImpl* inputProperty( NULL );
775 int componentIndex( Property::INVALID_COMPONENT_INDEX );
777 if ( OBJECT_PROPERTY == source.sourceType )
779 DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
781 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
783 // The property owner will not exist, if the target proxy-object is off-stage
786 propertyOwners.insert( owner );
787 inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
788 componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
790 // The scene-object property should exist, when the property owner exists
791 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
794 else if ( LOCAL_PROPERTY == source.sourceType )
796 DALI_ASSERT_ALWAYS( mTargetProxy->IsPropertyAConstraintInput( source.propertyIndex ) );
798 inputProperty = const_cast< PropertyInputImpl* >( mTargetProxy->GetSceneObjectInputProperty( source.propertyIndex ) );
799 componentIndex = mTargetProxy->GetPropertyComponentIndex( source.propertyIndex );
801 // The target scene-object should provide this property
802 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
806 DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
808 ProxyObject* proxyParent = dynamic_cast< Actor& >( *mTargetProxy ).GetParent();
810 // This will not exist, if the target proxy-object is off-stage
811 if ( NULL != proxyParent )
813 DALI_ASSERT_ALWAYS( proxyParent->IsPropertyAConstraintInput( source.propertyIndex ) );
815 SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( proxyParent->GetSceneObject() );
817 // The property owner will not exist, if the parent proxy-object is off-stage
820 propertyOwners.insert( owner );
821 inputProperty = const_cast< PropertyInputImpl* >( proxyParent->GetSceneObjectInputProperty( source.propertyIndex ) );
822 componentIndex = proxyParent->GetPropertyComponentIndex( source.propertyIndex );
824 // The scene-object property should exist, when the property owner exists
825 DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
830 if ( NULL == inputProperty )
835 // Exit if a scene-graph object is not available from one of the sources
838 else if ( Property::INVALID_COMPONENT_INDEX != componentIndex )
840 // Special case where component indices are required
841 if ( !usingComponentFunc )
843 PropertyConstraintBase<float>* componentFunc = func->CloneComponentFunc();
844 usingComponentFunc = true;
846 // Switch to function supporting component indices
848 func = componentFunc;
852 func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
860 Property::Index mTargetIndex;
862 SourceContainer mSources;
863 unsigned int mSourceCount;
865 ProxyObjectContainer mObservedProxies; // We don't observe the same object twice
867 ConstraintFunctionPtr mUserFunction;
868 InterpolatorFunction mInterpolatorFunction;
871 } // namespace Internal
875 #endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__