[dali_1.2.35] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / constraint-impl.h
index d9b2d30..78f86f1 100644 (file)
@@ -1,8 +1,8 @@
-#ifndef __DALI_INTERNAL_CONSTRAINT_H__
-#define __DALI_INTERNAL_CONSTRAINT_H__
+#ifndef __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
+#define __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
 
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 
 // INTERNAL INCLUDES
-#include <dali/public-api/animation/active-constraint.h>
-#include <dali/public-api/animation/alpha-functions.h>
-#include <dali/public-api/animation/constraint.h>
-#include <dali/public-api/animation/time-period.h>
-#include <dali/public-api/object/base-object.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/object-impl.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/animation/constraint-base.h>
 #include <dali/internal/event/animation/constraint-source-impl.h>
+#include <dali/internal/event/animation/property-constraint-ptr.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/property-owner-messages.h>
+#include <dali/internal/update/animation/scene-graph-constraint.h>
+#include <dali/internal/update/animation/property-accessor.h>
+#include <dali/internal/update/animation/property-component-accessor.h>
 
 namespace Dali
 {
@@ -32,124 +40,581 @@ namespace Dali
 namespace Internal
 {
 
-class ActiveConstraintBase;
-class Object;
+/**
+ * Helper to add only unique entries to the propertyOwner container
+ * @param propertyOwners to add the entries to
+ * @param object to add
+ */
+inline void AddUnique( SceneGraph::PropertyOwnerContainer& propertyOwners, SceneGraph::PropertyOwner* object )
+{
+  const SceneGraph::PropertyOwnerIter iter = std::find( propertyOwners.Begin(), propertyOwners.End(), object );
+  if( iter == propertyOwners.End() )
+  {
+    // each owner should only be added once
+    propertyOwners.PushBack( object );
+  }
+}
 
 /**
- * Constraints are used to constrain a property of an object, after animations have been applied.
+ * Connects a constraint which takes another property as an input.
  */
-class Constraint : public BaseObject
+template < typename PropertyType >
+class Constraint : public ConstraintBase
 {
 public:
 
-  typedef Any AnyFunction;
+  typedef SceneGraph::Constraint< PropertyType, PropertyAccessor<PropertyType> > SceneGraphConstraint;
+  typedef const SceneGraph::AnimatableProperty<PropertyType>* ScenePropertyPtr;
+  typedef typename PropertyConstraintPtr<PropertyType>::Type ConstraintFunctionPtr;
+  typedef const SceneGraph::TransformManagerPropertyHandler<PropertyType> TransformManagerProperty;
 
   /**
-   * Construct a new constraint which targets a property.
-   * @param [in] target The index of the property to constrain.
-   * @param [in] targetType The type of the constrained property.
-   * @param [in] sources The objects which provide parameters for func.
-   * @param [in] func The constraint function.
+   * Construct a new constraint.
+   * @param[in] object The property-owning object.
+   * @param[in] targetIndex The index of the property to constrain.
+   * @param[in] sources The sources of the input properties passed to func.
+   * @param[in] func The constraint function.
+   * @return A newly allocated active-constraint.
    */
-  Constraint( Property::Index target,
-              Property::Type targetType,
-              SourceContainer& sources,
-              AnyFunction& func );
+  static ConstraintBase* New( Object& object,
+                              Property::Index targetIndex,
+                              SourceContainer& sources,
+                              ConstraintFunctionPtr func )
+  {
+    return new Constraint< PropertyType >( object, targetIndex, sources, func );
+  }
 
   /**
-   * @copydoc Dali::Constraint::SetApplyTime()
+   * @copydoc ConstraintBase::Clone()
    */
-  void SetApplyTime( TimePeriod timePeriod );
+  virtual ConstraintBase* Clone( Object& object )
+  {
+    DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
+
+    ConstraintBase* clone( NULL );
+
+    ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
+
+    clone = new Constraint< PropertyType >( object,
+                                            mTargetIndex,
+                                            mSources,
+                                            funcPtr );
+
+    clone->SetRemoveAction(mRemoveAction);
+    clone->SetTag( mTag );
+
+    return clone;
+  }
 
-  /**
-   * @copydoc Dali::Constraint::GetApplyTime()
-   */
-  TimePeriod GetApplyTime() const;
 
   /**
-   * @copydoc Dali::Constraint::SetAlphaFunction( AlphaFunction func )
+   * Virtual destructor.
    */
-  void SetAlphaFunction( AlphaFunction func );
+  virtual ~Constraint()
+  {
+    // This is not responsible for removing constraints.
+  }
+
+private:
 
   /**
-   * @copydoc Dali::Constraint::GetAlphaFunction()
+   * Private constructor; see also Constraint::New().
    */
-  AlphaFunction GetAlphaFunction() const;
+  Constraint( Object& object,
+              Property::Index targetIndex,
+              SourceContainer& sources,
+              ConstraintFunctionPtr& func )
+  : ConstraintBase( object, targetIndex, sources ),
+    mTargetIndex( targetIndex ),
+    mUserFunction( func )
+  {
+  }
+
+  // Undefined
+  Constraint( const Constraint& );
+
+  // Undefined
+  Constraint& operator=( const Constraint& rhs );
 
   /**
-   * @copydoc Dali::Constraint::SetRemoveAction()
+   * Create and connect a constraint for a scene-object.
    */
-  void SetRemoveAction(Dali::Constraint::RemoveAction action);
+  void ConnectConstraint()
+  {
+    // Should not come here if target-object has been destroyed
+    DALI_ASSERT_DEBUG( NULL != mTargetObject );
+
+    // Guard against double connections
+    DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
+
+    // Short-circuit until the target scene-object exists
+    SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
+    if ( NULL == targetObject )
+    {
+      return;
+    }
+
+    // Build a container of property-owners, providing the scene-graph properties
+    SceneGraph::PropertyOwnerContainer propertyOwners;
+    propertyOwners.PushBack( targetObject );
+
+    // Build the constraint function; this requires a scene-graph property from each source
+    ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
+
+    if ( func )
+    {
+      // Create the SceneGraphConstraint, and connect to the scene-graph
+
+      const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
+
+      // The targetProperty should exist, when targetObject exists
+      DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
+
+      if( targetProperty->IsTransformManagerProperty() )  //It is a property managed by the transform manager
+      {
+        // Connect the constraint
+        SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraph::Constraint<PropertyType,TransformManagerPropertyAccessor<PropertyType> >::New( *targetProperty,
+                                                                                      propertyOwners,
+                                                                                      func );
+        DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
+        sceneGraphConstraint->SetRemoveAction( mRemoveAction );
+
+        // object is being used in a separate thread; queue a message to apply the constraint
+        ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
+
+        // Keep a raw-pointer to the scene-graph constraint
+        mSceneGraphConstraint = sceneGraphConstraint;
+      }
+      else  //SceneGraph property
+      {
+        // Connect the constraint
+        SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
+                                                                                      propertyOwners,
+                                                                                      func );
+        DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
+        sceneGraphConstraint->SetRemoveAction( mRemoveAction );
+
+        // object is being used in a separate thread; queue a message to apply the constraint
+        ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
+
+        // Keep a raw-pointer to the scene-graph constraint
+        mSceneGraphConstraint = sceneGraphConstraint;
+      }
+    }
+  }
 
   /**
-   * @copydoc Dali::Constraint::GetRemoveAction()
+   * Helper for ConnectConstraint. Creates a connected constraint-function.
+   * Also populates the property-owner container, for each input connected to the constraint-function.
+   * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
+   * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
    */
-  Dali::Constraint::RemoveAction GetRemoveAction() const;
+  PropertyConstraint<PropertyType>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
+  {
+    PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
+
+    for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
+    {
+      Source& source = *iter;
+
+      PropertyInputImpl* inputProperty( NULL );
+      int componentIndex( Property::INVALID_COMPONENT_INDEX );
+
+      if ( OBJECT_PROPERTY == source.sourceType )
+      {
+        DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+        SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
+
+        // The property owner will not exist, if the target object is off-stage
+        if( NULL != owner )
+        {
+          AddUnique( propertyOwners, owner );
+          inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
+          componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
+
+          // The scene-object property should exist, when the property owner exists
+          DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+        }
+      }
+      else if ( LOCAL_PROPERTY == source.sourceType )
+      {
+        DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+        inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
+        componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
+
+        // The target scene-object should provide this property
+        DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+      }
+      else
+      {
+        DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
+
+        Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
+
+        // This will not exist, if the target object is off-stage
+        if ( NULL != objectParent )
+        {
+          DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+          SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
+
+          // The property owner will not exist, if the parent object is off-stage
+          if ( NULL != owner )
+          {
+            AddUnique( propertyOwners, owner );
+            inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
+            componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
+
+            // The scene-object property should exist, when the property owner exists
+            DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+          }
+        }
+      }
+
+      if ( NULL == inputProperty )
+      {
+        delete func;
+        func = NULL;
+
+        // Exit if a scene-graph object is not available from one of the sources
+        break;
+      }
+
+      func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
+    }
+
+    return func;
+  }
+
+protected:
+
+  Property::Index mTargetIndex;
+
+  ConstraintFunctionPtr mUserFunction;
+};
+
+/**
+ * Variant which allows float components to be animated individually.
+ */
+template <>
+class Constraint<float> : public ConstraintBase
+{
+public:
+
+  typedef typename PropertyConstraintPtr<float>::Type ConstraintFunctionPtr;
 
   /**
-   * @copydoc Dali::Constraint::SetTag()
+   * Construct a new constraint.
+   * @param[in] object The property-owning object.
+   * @param[in] targetIndex The index of the property to constrain.
+   * @param[in] sources The sources of the input properties passed to func.
+   * @param[in] func The constraint function.
+   * @return A newly allocated constraint.
    */
-  void SetTag( const unsigned int tag);
+  static ConstraintBase* New( Object& object,
+                              Property::Index targetIndex,
+                              SourceContainer& sources,
+                              ConstraintFunctionPtr func )
+  {
+    return new Constraint< float >( object, targetIndex, sources, func );
+  }
 
   /**
-   * @copydoc Dali::Constraint::GetTag()
+   * @copydoc ConstraintBase::Clone()
    */
-  unsigned int GetTag() const;
+  virtual ConstraintBase* Clone( Object& object )
+  {
+    DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
 
+    ConstraintBase* clone( NULL );
 
+    ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
 
+    clone = new Constraint< float >( object,
+                                     mTargetIndex,
+                                     mSources,
+                                     funcPtr );
 
-  /**
-   * Create an active constraint.
-   * An active constraint is created each time the constraint is applied to an object.
-   * @return A newly allocated active-constraint.
-   */
-  ActiveConstraintBase* CreateActiveConstraint();
+    clone->SetRemoveAction(mRemoveAction);
+    clone->SetTag( mTag );
 
-protected:
+    return clone;
+  }
 
   /**
-   * A reference counted object may only be deleted by calling Unreference()
+   * Virtual destructor.
    */
-  virtual ~Constraint();
+  virtual ~Constraint()
+  {
+    // This is not responsible for removing constraints.
+  }
 
 private:
 
+  /**
+   * Private constructor; see also Constraint::New().
+   */
+  Constraint( Object& object,
+              Property::Index targetIndex,
+              SourceContainer& sources,
+              ConstraintFunctionPtr& func )
+  : ConstraintBase( object, targetIndex, sources ),
+    mTargetIndex( targetIndex ),
+    mUserFunction( func )
+  {
+  }
+
   // Undefined
-  Constraint(const Constraint&);
+  Constraint( const Constraint& );
 
   // Undefined
-  Constraint& operator=(const Constraint& rhs);
+  Constraint& operator=( const Constraint& rhs );
+
+  /**
+   * Create and connect a constraint for a scene-object.
+   */
+  void ConnectConstraint()
+  {
+    // Should not come here if target-object has been destroyed
+    DALI_ASSERT_DEBUG( NULL != mTargetObject );
+
+    // Guard against double connections
+    DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
+
+    // Short-circuit until the target scene-object exists
+    SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
+    if ( NULL == targetObject )
+    {
+      return;
+    }
+
+    // Build a container of property-owners, providing the scene-graph properties
+    SceneGraph::PropertyOwnerContainer propertyOwners;
+    propertyOwners.PushBack( targetObject );
+
+    // Build the constraint function; this requires a scene-graph property from each source
+    ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
+
+    if ( func )
+    {
+      // Create the SceneGraphConstraint, and connect to the scene-graph
+
+      const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
+
+      // The targetProperty should exist, when targetObject exists
+      DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
+
+      const int componentIndex = mTargetObject->GetPropertyComponentIndex( mTargetIndex );
+
+      SceneGraph::ConstraintBase* sceneGraphConstraint( NULL );
+
+      if ( Property::INVALID_COMPONENT_INDEX == componentIndex )
+      {
+        // Not a Vector2, Vector3 or Vector4 component, expecting float type
+        DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() );
+
+        typedef SceneGraph::Constraint< float, PropertyAccessor<float> > SceneGraphConstraint;
+
+        sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
+                                                           propertyOwners,
+                                                           func );
+      }
+      else
+      {
+        // Expecting Vector2, Vector3 or Vector4 type
+
+        if ( PropertyTypes::Get< Vector2 >() == targetProperty->GetType() )
+        {
+          // Constrain float component of Vector2 property
+
+          if ( 0 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector2> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+          else if ( 1 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector2> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+        }
+        else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
+        {
+          // Constrain float component of Vector3 property
+          if( targetProperty->IsTransformManagerProperty() )
+          {
+            if ( 0 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,0> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
+            else if ( 1 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,1> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
+            else if ( 2 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, TransformManagerPropertyComponentAccessor<Vector3,2> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
+          }
+          else
+          {
+            if ( 0 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
+            else if ( 1 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
+            else if ( 2 == componentIndex )
+            {
+              typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
+              sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+            }
+          }
+        }
+        else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
+        {
+          // Constrain float component of Vector4 property
+
+          if ( 0 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+          else if ( 1 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+          else if ( 2 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+          else if ( 3 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+        }
+      }
+
+      DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
+      if( NULL != sceneGraphConstraint )
+      {
+        sceneGraphConstraint->SetRemoveAction( mRemoveAction );
+
+        // object is being used in a separate thread; queue a message to apply the constraint
+        ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
+
+        // Keep a raw-pointer to the scene-graph constraint
+        mSceneGraphConstraint = sceneGraphConstraint;
+      }
+    }
+  }
+
+  /**
+   * Helper for ConnectConstraint. Creates a connected constraint-function.
+   * Also populates the property-owner container, for each input connected to the constraint-function.
+   * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
+   * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
+   */
+  PropertyConstraint<float>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
+  {
+    PropertyConstraint<float>* func = mUserFunction->Clone();
+
+    for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
+    {
+      Source& source = *iter;
+
+      PropertyInputImpl* inputProperty( NULL );
+      int componentIndex( Property::INVALID_COMPONENT_INDEX );
+
+      if ( OBJECT_PROPERTY == source.sourceType )
+      {
+        DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+        SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
+
+        // The property owner will not exist, if the target object is off-stage
+        if( NULL != owner )
+        {
+          AddUnique( propertyOwners, owner );
+          inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
+          componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
+
+          // The scene-object property should exist, when the property owner exists
+          DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+        }
+      }
+      else if ( LOCAL_PROPERTY == source.sourceType )
+      {
+        DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+        inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
+        componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
+
+        // The target scene-object should provide this property
+        DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+      }
+      else
+      {
+        DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
+
+        Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
+
+        // This will not exist, if the target object is off-stage
+        if ( NULL != objectParent )
+        {
+          DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+          SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
+
+          // The property owner will not exist, if the parent object is off-stage
+          if ( NULL != owner )
+          {
+            AddUnique( propertyOwners, owner );
+            inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
+            componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
+
+            // The scene-object property should exist, when the property owner exists
+            DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+          }
+        }
+      }
+
+      if ( NULL == inputProperty )
+      {
+        delete func;
+        func = NULL;
+
+        // Exit if a scene-graph object is not available from one of the sources
+        break;
+      }
+
+      func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
+    }
+
+    return func;
+  }
 
 protected:
 
-  Dali::ActiveConstraint mActiveConstraintTemplate; ///< Used to create active constraints
+  Property::Index mTargetIndex;
 
-  TimePeriod mApplyTime;
+  ConstraintFunctionPtr mUserFunction;
 };
 
 } // namespace Internal
 
-// Helpers for public-api forwarding methods
-
-inline Internal::Constraint& GetImplementation(Dali::Constraint& constraint)
-{
-  DALI_ASSERT_ALWAYS( constraint && "Constraint handle is empty" );
-
-  BaseObject& handle = constraint.GetBaseObject();
-
-  return static_cast<Internal::Constraint&>(handle);
-}
-
-inline const Internal::Constraint& GetImplementation(const Dali::Constraint& constraint)
-{
-  DALI_ASSERT_ALWAYS( constraint && "Constraint handle is empty" );
-
-  const BaseObject& handle = constraint.GetBaseObject();
-
-  return static_cast<const Internal::Constraint&>(handle);
-}
-
 } // namespace Dali
 
-#endif // __DALI_INTERNAL_CONSTRAINT_H__
+#endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__