Share a single weight property between constraints 87/20287/1
authorPaul Wisbey <p.wisbey@samsung.com>
Mon, 14 Apr 2014 17:35:26 +0000 (18:35 +0100)
committerDavid Steele <david.steele@partner.samsung.com>
Thu, 1 May 2014 14:28:39 +0000 (15:28 +0100)
[Issue#]   (N/A)
[Problem]  Not easy to blend between layouts using Constraints
[Cause]    Each constraint weight has to be animated individually
[Solution] Provide an API for sharing a single weight property
between many Constraints

Change-Id: Icd81656930d85a8335ca8ee334843df6d2fdf179
Signed-off-by: David Steele <david.steele@partner.samsung.com>
capi/dali/public-api/object/constrainable.h
dali/internal/event/animation/active-constraint-base.cpp
dali/internal/event/animation/active-constraint-base.h
dali/internal/event/animation/active-constraint-impl.h
dali/internal/event/common/proxy-object.cpp
dali/internal/event/common/proxy-object.h
dali/internal/update/animation/scene-graph-constraint.h
dali/public-api/object/constrainable.cpp

index 7bc68d1..6073a40 100644 (file)
@@ -98,12 +98,24 @@ public:
    * @note The constraint will be copied by the Actor. This means that modifying the apply-time etc.
    * of the constraint, will not affect actors which are already being constrained.
    * @pre The Actor has been initialized.
-   * @param[in] constraint The constraint to add.
+   * @param[in] constraint The constraint to apply.
    * @return The active-constraint being applied to the actor.
    */
   ActiveConstraint ApplyConstraint( Constraint constraint );
 
   /**
+   * @brief Constrain one of the properties of an Actor, using a custom weight property.
+   *
+   * This overload is intended to allow a single weight property to be shared by many constraints
+   * e.g. call WeightObject::New() once, and pass the return value into every call to ApplyConstraint().
+   * @pre The Actor has been initialized.
+   * @param[in] constraint The constraint to apply.
+   * @param[in] weightObject An object which is expected to have a float property named "weight".
+   * @return The active-constraint being applied to the actor.
+   */
+  ActiveConstraint ApplyConstraint( Constraint constraint, Constrainable weightObject );
+
+  /**
    * @brief Remove one constraint from an Object.
    *
    * @pre The Object has been intialized.
@@ -119,16 +131,15 @@ public:
   void RemoveConstraints();
 
   /**
-     * @brief Remove all the constraint from the Object with a matching tag.
-     *
-     * @pre The Object has been intialized.
-     * @param[in] tag The tag of the constraints which will be removed
-     */
+   * @brief Remove all the constraint from the Object with a matching tag.
+   *
+   * @pre The Object has been intialized.
+   * @param[in] tag The tag of the constraints which will be removed
+   */
   void RemoveConstraints( unsigned int tag );
 
 public:
 
-
   /**
    * @brief This constructor is used by Dali New() methods.
    *
@@ -137,6 +148,20 @@ public:
   explicit DALI_INTERNAL Constrainable(Dali::Internal::Object* handle);
 };
 
+namespace WeightObject
+{
+
+extern const Property::Index WEIGHT; ///< name "weight", type FLOAT
+
+/**
+ * @brief Convenience function to create an object with a custom "weight" property.
+ *
+ * @return A handle to a newly allocated object.
+ */
+Constrainable New();
+
+} // namespace WeightObject
+
 } // namespace Dali
 
 /**
index 7f29377..ca99221 100644 (file)
@@ -78,6 +78,7 @@ ActiveConstraintBase::ActiveConstraintBase( EventToUpdate& eventToUpdate, Proper
   mTargetPropertyIndex( targetPropertyIndex ),
   mTargetProxy( NULL ),
   mSceneGraphConstraint( NULL ),
+  mCustomWeight( NULL ),
   mOffstageWeight( Dali::ActiveConstraint::DEFAULT_WEIGHT ),
   mRemoveTime( 0.0f ),
   mAlphaFunction( Dali::Constraint::DEFAULT_ALPHA_FUNCTION ),
@@ -103,7 +104,20 @@ ActiveConstraintBase::~ActiveConstraintBase()
   }
 }
 
-void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime, ActiveConstraintCallbackType* callback )
+void ActiveConstraintBase::SetCustomWeightObject( ProxyObject& weightObject, Property::Index weightIndex )
+{
+  const SceneGraph::PropertyBase* base = weightObject.GetSceneObjectAnimatableProperty( weightIndex );
+  const SceneGraph::AnimatableProperty<float>* sceneProperty = dynamic_cast< const SceneGraph::AnimatableProperty<float>* >( base );
+
+  if( sceneProperty )
+  {
+    mCustomWeight = sceneProperty;
+
+    OnCustomWeightSet( weightObject );
+  }
+}
+
+void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime )
 {
   // Notify derived classes
   OnFirstApply( parent );
index 2f0090e..38775ad 100644 (file)
@@ -39,6 +39,9 @@ class ProxyObject;
 namespace SceneGraph
 {
 class ConstraintBase;
+
+template <typename T>
+class AnimatableProperty;
 }
 
 /**
@@ -70,13 +73,19 @@ public:
   virtual ActiveConstraintBase* Clone() = 0;
 
   /**
+   * Set a custom "weight" property.
+   * @param[in] weightObject An object with a "weight" float property.
+   * @param[in] weightIndex The index of the weight property.
+   */
+  void SetCustomWeightObject( ProxyObject& weightObject, Property::Index weightIndex );
+
+  /**
    * Called when the ActiveConstraint is first applied.
    * @pre The active-constraint does not already have a parent.
    * @param[in] parent The parent object.
    * @param[in] applyTime The apply-time for this constraint.
-   * @param[in] callback A pointer to a callback for the applied signal, or NULL.
    */
-  void FirstApply( ProxyObject& parent, TimePeriod applyTime, ActiveConstraintCallbackType* callback );
+  void FirstApply( ProxyObject& parent, TimePeriod applyTime );
 
   /**
    * Called when the ActiveConstraint is removed.
@@ -278,6 +287,12 @@ private:
   // To be implemented in derived classes
 
   /**
+   * Used to observe the lifetime of an object with custom "weight" property
+   * @param [in] weightObject The object.
+   */
+  virtual void OnCustomWeightSet( ProxyObject& weightObject ) = 0;
+
+  /**
    * Set the parent of the active-constraint; called during OnFirstApply().
    * @param [in] parent The parent object.
    */
@@ -298,6 +313,8 @@ protected:
 
   const SceneGraph::ConstraintBase* mSceneGraphConstraint;
 
+  const SceneGraph::AnimatableProperty<float>* mCustomWeight;
+
   float mOffstageWeight;
 
   TimePeriod mRemoveTime;
index 7d3c7a5..843f860 100644 (file)
@@ -112,6 +112,14 @@ public:
   }
 
   /**
+   * @copydoc ActiveConstraintBase::OnCustomWeightSet()
+   */
+  virtual void OnCustomWeightSet( ProxyObject& weightObject )
+  {
+    ObserveProxy( weightObject );
+  }
+
+  /**
    * @copydoc ActiveConstraintBase::OnFirstApply()
    */
   virtual void OnFirstApply( ProxyObject& parent )
@@ -299,7 +307,8 @@ private:
       SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
                                                                                      propertyOwners,
                                                                                      func,
-                                                                                     mInterpolatorFunction );
+                                                                                     mInterpolatorFunction,
+                                                                                     mCustomWeight );
       DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
       sceneGraphConstraint->SetInitialWeight( mOffstageWeight );
       sceneGraphConstraint->SetRemoveAction( mRemoveAction );
@@ -491,6 +500,14 @@ public:
   }
 
   /**
+   * @copydoc ActiveConstraintBase::OnCustomWeightSet()
+   */
+  virtual void OnCustomWeightSet( ProxyObject& weightObject )
+  {
+    ObserveProxy( weightObject );
+  }
+
+  /**
    * @copydoc ActiveConstraintBase::OnFirstApply()
    */
   virtual void OnFirstApply( ProxyObject& parent )
@@ -688,7 +705,8 @@ private:
         sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
                                                            propertyOwners,
                                                            func,
-                                                           mInterpolatorFunction );
+                                                           mInterpolatorFunction,
+                                                           mCustomWeight );
       }
       else
       {
@@ -701,17 +719,17 @@ private:
           if ( 0 == componentIndex )
           {
             typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
-            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
           }
           else if ( 1 == componentIndex )
           {
             typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
-            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
           }
           else if ( 2 == componentIndex )
           {
             typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
-            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
           }
         }
         else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
@@ -721,22 +739,22 @@ private:
           if ( 0 == componentIndex )
           {
             typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> > SceneGraphConstraint;
-            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
           }
           else if ( 1 == componentIndex )
           {
             typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> > SceneGraphConstraint;
-            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
           }
           else if ( 2 == componentIndex )
           {
             typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> > SceneGraphConstraint;
-            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
           }
           else if ( 3 == componentIndex )
           {
             typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
-            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction );
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func, mInterpolatorFunction, mCustomWeight );
           }
         }
       }
index 1f311bd..c1fe6c9 100644 (file)
@@ -728,28 +728,39 @@ void ProxyObject::DisablePropertyNotifications()
 
 Dali::ActiveConstraint ProxyObject::ApplyConstraint( Constraint& constraint )
 {
-  return Dali::ActiveConstraint(DoApplyConstraint( constraint, NULL/*callback is optional*/ ));
+  return Dali::ActiveConstraint( DoApplyConstraint( constraint, Dali::Constrainable() ) );
 }
 
-Dali::ActiveConstraint ProxyObject::ApplyConstraint( Constraint& constraint, ActiveConstraintCallbackType callback )
+Dali::ActiveConstraint ProxyObject::ApplyConstraint( Constraint& constraint, Dali::Constrainable weightObject )
 {
-  return Dali::ActiveConstraint(DoApplyConstraint( constraint, &callback ));
+  return Dali::ActiveConstraint( DoApplyConstraint( constraint, weightObject ) );
 }
 
-ActiveConstraintBase* ProxyObject::DoApplyConstraint( Constraint& constraint, ActiveConstraintCallbackType* callback )
+ActiveConstraintBase* ProxyObject::DoApplyConstraint( Constraint& constraint, Dali::Constrainable weightObject )
 {
   ActiveConstraintBase* activeConstraintImpl = constraint.CreateActiveConstraint();
   DALI_ASSERT_DEBUG( NULL != activeConstraintImpl );
 
   Dali::ActiveConstraint activeConstraint( activeConstraintImpl );
 
+  if( weightObject )
+  {
+    ProxyObject& weightObjectImpl = GetImplementation( weightObject );
+    Property::Index weightIndex = weightObjectImpl.GetPropertyIndex( "weight" );
+
+    if( Property::INVALID_INDEX != weightIndex )
+    {
+      activeConstraintImpl->SetCustomWeightObject( weightObjectImpl, weightIndex );
+    }
+  }
+
   if( !mConstraints )
   {
     mConstraints = new ActiveConstraintContainer;
   }
   mConstraints->push_back( activeConstraint );
 
-  activeConstraintImpl->FirstApply( *this, constraint.GetApplyTime(), callback );
+  activeConstraintImpl->FirstApply( *this, constraint.GetApplyTime() );
 
   return activeConstraintImpl;
 }
index 056720c..4f4bfd3 100644 (file)
@@ -261,9 +261,9 @@ public: // Constraints
   /**
    * Apply a constraint to a ProxyObject.
    * @param[in] constraint The constraint to apply.
-   * @param[in] callback This method will be called at the end of the constraint apply-time.
+   * @param[in] weightObject An object with a "weight" float property.
    */
-  Dali::ActiveConstraint ApplyConstraint( Constraint& constraint, ActiveConstraintCallbackType callback );
+  Dali::ActiveConstraint ApplyConstraint( Constraint& constraint, Dali::Constrainable weightObject );
 
   /**
    * Remove one constraint from a ProxyObject.
@@ -308,9 +308,11 @@ private:
 
   /**
    * Helper for ApplyConstraint overloads.
+   * @param[in] constraint The constraint to apply.
+   * @param[in] weightObject An object with a "weight" float property, or an empty handle.
    * @return The new active-constraint which is owned by ProxyObject.
    */
-  ActiveConstraintBase* DoApplyConstraint( Constraint& constraint, ActiveConstraintCallbackType* callback );
+  ActiveConstraintBase* DoApplyConstraint( Constraint& constraint, Dali::Constrainable weightObject );
 
   /**
    * Helper to delete removed constraints
index 74ca32a..ba9f660 100644 (file)
@@ -57,12 +57,14 @@ public:
    * @param[in] ownerSet A set of property owners; func is connected to the properties provided by these objects.
    * @param[in] func The function to calculate the final constrained value.
    * @param[in] interpolator The function to interpolate between start & final value.
+   * @param[in] customWeight A custom weight property, or NULL if the constraint is using its own.
    * @return A smart-pointer to a newly allocated constraint.
    */
   static ConstraintBase* New( const PropertyBase& targetProperty,
                               PropertyOwnerSet& ownerSet,
                               ConstraintFunctionPtr func,
-                              InterpolatorFunc interpolator )
+                              InterpolatorFunc interpolator,
+                              const AnimatableProperty<float>* customWeight )
   {
     // Scene-graph thread can edit these objects
     PropertyBase& property = const_cast< PropertyBase& >( targetProperty );
@@ -70,7 +72,8 @@ public:
     return new Constraint< PropertyType, PropertyAccessorType >( property,
                                                                  ownerSet,
                                                                  func,
-                                                                 interpolator );
+                                                                 interpolator,
+                                                                 customWeight );
   }
 
   /**
@@ -94,7 +97,7 @@ public:
 
     if ( ! mTargetProperty.IsClean() ||
            mFunc->InputsChanged()    ||
-         ! mWeight.IsClean() )
+         ! mWeightInput->IsClean() )
     {
       return true;
     }
@@ -119,12 +122,12 @@ public:
       const PropertyType& current = mTargetProperty.Get( updateBufferIndex );
 
       // FINAL_WEIGHT means the constraint is fully-applied, unless weight is still being animated
-      if ( ! mWeight.IsClean() ||
-           ! Equals( Dali::ActiveConstraint::FINAL_WEIGHT, mWeight[updateBufferIndex] ) )
+      if ( ! mWeightInput->IsClean() ||
+           ! Equals( Dali::ActiveConstraint::FINAL_WEIGHT, (*mWeightInput)[updateBufferIndex] ) )
       {
         // Constraint is not fully-applied; interpolation between start & final values
         mTargetProperty.Set( updateBufferIndex,
-                             mInterpolator( current, mFunc->Apply( updateBufferIndex, current ), mWeight[updateBufferIndex] ) );
+                             mInterpolator( current, mFunc->Apply( updateBufferIndex, current ), (*mWeightInput)[updateBufferIndex] ) );
       }
       else
       {
@@ -155,11 +158,13 @@ private:
   Constraint( PropertyBase& targetProperty,
               PropertyOwnerSet& ownerSet,
               ConstraintFunctionPtr func,
-              InterpolatorFunc interpolator )
+              InterpolatorFunc interpolator,
+              const AnimatableProperty<float>* customWeight )
   : ConstraintBase( ownerSet ),
     mTargetProperty( &targetProperty ),
     mFunc( func ),
-    mInterpolator( interpolator )
+    mInterpolator( interpolator ),
+    mWeightInput( customWeight ? customWeight : &mWeight)
   {
   }
 
@@ -186,6 +191,8 @@ protected:
   ConstraintFunctionPtr mFunc;
 
   InterpolatorFunc mInterpolator;
+
+  const AnimatableProperty<float>* mWeightInput;
 };
 
 } // namespace SceneGraph
index edb0a45..f0053b1 100644 (file)
 // limitations under the License.
 //
 
+// CLASS HEADER
 #include <dali/public-api/object/constrainable.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-index.h>
 #include <dali/public-api/animation/constraint.h>
 #include <dali/public-api/animation/active-constraint.h>
 #include <dali/internal/event/common/proxy-object.h>
@@ -54,7 +58,12 @@ Constrainable::Constrainable(const Constrainable& handle)
 
 ActiveConstraint Constrainable::ApplyConstraint( Constraint constraint )
 {
-  return GetImplementation(*this).ApplyConstraint(GetImplementation(constraint));
+  return GetImplementation(*this).ApplyConstraint( GetImplementation( constraint ) );
+}
+
+ActiveConstraint Constrainable::ApplyConstraint( Constraint constraint, Constrainable weightObject )
+{
+  return GetImplementation(*this).ApplyConstraint( GetImplementation( constraint ), weightObject );
 }
 
 void Constrainable::RemoveConstraint(ActiveConstraint activeConstraint)
@@ -72,6 +81,20 @@ void Constrainable::RemoveConstraints( unsigned int tag )
   GetImplementation(*this).RemoveConstraints( tag );
 }
 
+namespace WeightObject
+{
+
+const Property::Index WEIGHT = PROPERTY_CUSTOM_START_INDEX;
+
+Constrainable New()
+{
+  Constrainable handle = Constrainable::New();
+
+  handle.RegisterProperty( "weight", 0.0f );
+
+  return handle;
+}
 
+} // namespace WeightObject
 
-} // Dali
+} // namespace Dali