(Vector) Support dynamic properties 52/278252/5
authorHeeyong Song <heeyong.song@samsung.com>
Mon, 18 Jul 2022 06:13:17 +0000 (15:13 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Thu, 21 Jul 2022 09:52:32 +0000 (18:52 +0900)
Change-Id: I562e33197a9515dcdd6ce76ea7805cddc2e7f131

13 files changed:
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp
automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp
dali-toolkit/devel-api/controls/control-devel.cpp
dali-toolkit/devel-api/controls/control-devel.h
dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h
dali-toolkit/internal/visuals/visual-base-impl.cpp
dali-toolkit/internal/visuals/visual-base-impl.h

index e6456ec..a8f3ab8 100644 (file)
@@ -129,6 +129,11 @@ public:
       mNeedDroppedFrames = false;
     }
 
       mNeedDroppedFrames = false;
     }
 
+    if(mDynamicPropertyCallback)
+    {
+      CallbackBase::ExecuteReturn<Property::Value>(*mDynamicPropertyCallback, 0, 0, frameNumber);
+    }
+
     if(mNeedTrigger)
     {
       mEventThreadCallback->Trigger();
     if(mNeedTrigger)
     {
       mEventThreadCallback->Trigger();
@@ -190,6 +195,11 @@ public:
     }
   }
 
     }
   }
 
+  void AddPropertyValueCallback(const std::string& keyPath, Dali::VectorAnimationRenderer::VectorProperty property, CallbackBase* callback, int32_t id)
+  {
+    mDynamicPropertyCallback = std::unique_ptr<CallbackBase>(callback);
+  }
+
   Dali::VectorAnimationRenderer::UploadCompletedSignalType& UploadCompletedSignal()
   {
     return mUploadCompletedSignal;
   Dali::VectorAnimationRenderer::UploadCompletedSignalType& UploadCompletedSignal()
   {
     return mUploadCompletedSignal;
@@ -216,23 +226,25 @@ public:
 public:
   static uint32_t mCount;
 
 public:
   static uint32_t mCount;
 
-  std::string    mUrl;
-  Dali::Renderer mRenderer;
-  Dali::Mutex    mMutex;
-  uint32_t       mWidth;
-  uint32_t       mHeight;
-  uint32_t       mDefaultWidth;
-  uint32_t       mDefaultHeight;
-  uint32_t       mTotalFrameNumber;
-  uint32_t       mPreviousFrame;
-  uint32_t       mDelayTime;
-  uint32_t       mDroppedFrames;
-  float          mFrameRate;
-  bool           mTestFrameDrop;
-  bool           mNeedDroppedFrames;
-  bool           mLoadFailed{false};
-  bool           mResourceReady{false};
-  bool           mNeedTrigger{true};
+  std::string                   mUrl;
+  Dali::Renderer                mRenderer;
+  Dali::Mutex                   mMutex;
+  std::unique_ptr<CallbackBase> mDynamicPropertyCallback{nullptr};
+
+  uint32_t mWidth;
+  uint32_t mHeight;
+  uint32_t mDefaultWidth;
+  uint32_t mDefaultHeight;
+  uint32_t mTotalFrameNumber;
+  uint32_t mPreviousFrame;
+  uint32_t mDelayTime;
+  uint32_t mDroppedFrames;
+  float    mFrameRate;
+  bool     mTestFrameDrop;
+  bool     mNeedDroppedFrames;
+  bool     mLoadFailed{false};
+  bool     mResourceReady{false};
+  bool     mNeedTrigger{true};
 
   Dali::VectorAnimationRenderer::UploadCompletedSignalType mUploadCompletedSignal;
   std::unique_ptr<EventThreadCallback>                     mEventThreadCallback;
 
   Dali::VectorAnimationRenderer::UploadCompletedSignalType mUploadCompletedSignal;
   std::unique_ptr<EventThreadCallback>                     mEventThreadCallback;
@@ -348,6 +360,11 @@ void VectorAnimationRenderer::InvalidateBuffer()
   return Internal::Adaptor::GetImplementation(*this).InvalidateBuffer();
 }
 
   return Internal::Adaptor::GetImplementation(*this).InvalidateBuffer();
 }
 
+void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPath, VectorProperty property, CallbackBase* callback, int32_t id)
+{
+  Internal::Adaptor::GetImplementation(*this).AddPropertyValueCallback(keyPath, property, callback, id);
+}
+
 VectorAnimationRenderer::UploadCompletedSignalType& VectorAnimationRenderer::UploadCompletedSignal()
 {
   return Internal::Adaptor::GetImplementation(*this).UploadCompletedSignal();
 VectorAnimationRenderer::UploadCompletedSignalType& VectorAnimationRenderer::UploadCompletedSignal()
 {
   return Internal::Adaptor::GetImplementation(*this).UploadCompletedSignal();
index 6299c0c..4ca6308 100644 (file)
@@ -34,6 +34,8 @@
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
+
+#include <dali/devel-api/adaptor-framework/vector-animation-renderer.h>
 #include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
 
 #include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
 
@@ -1898,3 +1900,63 @@ int UtcDaliAnimatedVectorImageVisualSize(void)
 
   END_TEST;
 }
 
   END_TEST;
 }
+
+namespace
+{
+bool gDynamicPropertyCallbackFired = false;
+
+Property::Value FillColorCallback(int32_t id, VectorAnimationRenderer::VectorProperty property, uint32_t frameNumber)
+{
+  gDynamicPropertyCallbackFired = true;
+
+  if(frameNumber < 3)
+  {
+    return Vector3(0, 0, 1);
+  }
+  else
+  {
+    return Vector3(1, 0, 0);
+  }
+}
+} // namespace
+
+int UtcDaliAnimatedVectorImageVisualDynamicProperty(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliAnimatedVectorImageVisualDynamicProperty");
+
+  VisualFactory factory = VisualFactory::Get();
+  Visual::Base  visual  = factory.CreateVisual(TEST_VECTOR_IMAGE_FILE_NAME, ImageDimensions());
+  DALI_TEST_CHECK(visual);
+
+  DummyControl      actor     = DummyControl::New(true);
+  DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual);
+
+  application.GetScene().Add(actor);
+
+  gDynamicPropertyCallbackFired = false;
+
+  // Set dynamic property
+  DevelAnimatedVectorImageVisual::DynamicPropertyInfo info;
+  info.id       = 1;
+  info.keyPath  = "Test.Path";
+  info.property = static_cast<int>(VectorAnimationRenderer::VectorProperty::FILL_COLOR);
+  info.callback = MakeCallback(FillColorCallback);
+
+  DevelControl::DoActionExtension(actor, DummyControl::Property::TEST_VISUAL, DevelAnimatedVectorImageVisual::Action::SET_DYNAMIC_PROPERTY, Any(info));
+
+  Property::Map attributes;
+  DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes);
+
+  application.SendNotification();
+  application.Render();
+
+  // Trigger count is 2 - load & render a frame
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+
+  // Test whether the property callback is called
+  DALI_TEST_EQUALS(gDynamicPropertyCallbackFired, true, TEST_LOCATION);
+
+  END_TEST;
+}
index 51e0564..ef1265b 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -114,6 +114,13 @@ void DoAction(Control& control, Dali::Property::Index visualIndex, Dali::Propert
   controlDataImpl.DoAction(visualIndex, actionId, attributes);
 }
 
   controlDataImpl.DoAction(visualIndex, actionId, attributes);
 }
 
+void DoActionExtension(Control& control, Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
+{
+  Internal::Control&       controlInternal = Toolkit::Internal::GetImplementation(control);
+  Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(controlInternal);
+  controlDataImpl.DoActionExtension(visualIndex, actionId, attributes);
+}
+
 void SetInputMethodContext(Internal::Control& control, InputMethodContext& inputMethodContext)
 {
   Internal::Control::Impl::Get(control).SetInputMethodContext(inputMethodContext);
 void SetInputMethodContext(Internal::Control& control, InputMethodContext& inputMethodContext)
 {
   Internal::Control::Impl::Get(control).SetInputMethodContext(inputMethodContext);
index 34b733b..abfba65 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_CONTROL_DEVEL_H
 
 /*
 #define DALI_TOOLKIT_CONTROL_DEVEL_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -360,6 +360,18 @@ DALI_TOOLKIT_API Dali::Animation CreateTransition(Internal::Control&
 DALI_TOOLKIT_API void DoAction(Control& control, Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes);
 
 /**
 DALI_TOOLKIT_API void DoAction(Control& control, Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes);
 
 /**
+ * @brief Perform an action on a visual registered to this control.
+ *
+ * Visuals will have actions, this API is used to perform one of these actions with the given attributes.
+ *
+ * @param[in] control The control.
+ * @param[in] visualIndex The Property index of the visual.
+ * @param[in] actionId The action to perform.  See Visual to find supported actions.
+ * @param[in] attributes Optional attributes for the action.
+ */
+DALI_TOOLKIT_API void DoActionExtension(Control& control, Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes);
+
+/**
  * @brief Set input method context.
  *
  * @param[in] control The control.
  * @brief Set input method context.
  *
  * @param[in] control The control.
index ecb91ae..33c88e0 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_DEVEL_API_VISUALS_ANIMATED_VECTOR_IMAGE_VISUAL_ACTIONS_DEVEL_H
 
 /*
 #define DALI_TOOLKIT_DEVEL_API_VISUALS_ANIMATED_VECTOR_IMAGE_VISUAL_ACTIONS_DEVEL_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  *
  */
  * limitations under the License.
  *
  */
+
+// EXTERNAL INCLUDES
 #include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
 #include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
+#include <dali/public-api/signals/callback.h>
+#include <string>
 
 namespace Dali
 {
 
 namespace Dali
 {
@@ -39,10 +43,35 @@ enum Type
   PAUSE,                            ///< Pause the animated vector image.
   STOP,                             ///< Stop the animated vector image. This is also Default playback mode.
   JUMP_TO,                          ///< Jump to the specified frame. Property::INTEGER value should be passed.
   PAUSE,                            ///< Pause the animated vector image.
   STOP,                             ///< Stop the animated vector image. This is also Default playback mode.
   JUMP_TO,                          ///< Jump to the specified frame. Property::INTEGER value should be passed.
+  SET_DYNAMIC_PROPERTY              ///< Set the dynamic property.
 };
 
 } // namespace Action
 
 };
 
 } // namespace Action
 
+/**
+ * @brief The dynamic property info
+ *
+ * @note A callback of the following type may be used:
+ * @code
+ *   Property::Value MyFunction(int32_t id, VectorAnimationRenderer::VectorProperty property, uint32_t frameNumber);
+ * @endcode
+ *
+ * id  The id to specify the callback.
+ * property The property that represent what you are trying to change.
+ * frameNumber The current frame number.
+ * It returns a Property::Value to set according to the property type.
+ *
+ * The callback will be called on the worker thread. You MUST not call other DALi methods in the callback.
+ * And the object must still be alive when the callback occurs if you make the callback from a class member function.
+ */
+struct DynamicPropertyInfo
+{
+  int32_t       id;       ///< The Id to specify the callback. It should be unique and will be passed when the callback is called.
+  std::string   keyPath;  ///< The key path used to target a specific content or a set of contents that will be updated.
+  int32_t       property; ///< The property to set.
+  CallbackBase* callback; ///< The callback that gets called every time the animation is rendered. Ownership of the callback is passed onto the visual.
+};
+
 } // namespace DevelAnimatedVectorImageVisual
 
 } // namespace Toolkit
 } // namespace DevelAnimatedVectorImageVisual
 
 } // namespace Toolkit
index d4de79a..5b638e8 100644 (file)
@@ -1095,6 +1095,15 @@ void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::
   }
 }
 
   }
 }
 
+void Control::Impl::DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes)
+{
+  RegisteredVisualContainer::Iterator iter;
+  if(FindVisual(visualIndex, mVisuals, iter))
+  {
+    Toolkit::GetImplementation((*iter)->visual).DoActionExtension(actionId, attributes);
+  }
+}
+
 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
 {
   Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
 void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
 {
   Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
index 593ab7d..f72d121 100644 (file)
@@ -224,6 +224,11 @@ public:
   void DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes);
 
   /**
   void DoAction(Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes);
 
   /**
+   * @copydoc Dali::Toolkit::DevelControl::DoActionExtension()
+   */
+  void DoActionExtension(Dali::Property::Index visualIndex, Dali::Property::Index actionId, Dali::Any attributes);
+
+  /**
    * @brief Function used to set control properties.
    * @param[in] object The object whose property to set
    * @param[in] index The index of the property to set
    * @brief Function used to set control properties.
    * @param[in] object The object whose property to set
    * @param[in] index The index of the property to set
index 4b547b4..1f73f80 100644 (file)
@@ -489,6 +489,22 @@ void AnimatedVectorImageVisual::OnDoAction(const Property::Index actionId, const
   TriggerVectorRasterization();
 }
 
   TriggerVectorRasterization();
 }
 
+void AnimatedVectorImageVisual::OnDoActionExtension(const Property::Index actionId, Dali::Any attributes)
+{
+  switch(actionId)
+  {
+    case DevelAnimatedVectorImageVisual::Action::SET_DYNAMIC_PROPERTY:
+    {
+      DevelAnimatedVectorImageVisual::DynamicPropertyInfo info = AnyCast<DevelAnimatedVectorImageVisual::DynamicPropertyInfo>(attributes);
+      mAnimationData.dynamicProperties.push_back(info);
+      mAnimationData.resendFlag |= VectorAnimationTask::RESEND_DYNAMIC_PROPERTY;
+      break;
+    }
+  }
+
+  TriggerVectorRasterization();
+}
+
 void AnimatedVectorImageVisual::OnResourceReady(VectorAnimationTask::ResourceStatus status)
 {
   if(status == VectorAnimationTask::ResourceStatus::LOADED)
 void AnimatedVectorImageVisual::OnResourceReady(VectorAnimationTask::ResourceStatus status)
 {
   if(status == VectorAnimationTask::ResourceStatus::LOADED)
index 221cf23..72c8e60 100644 (file)
@@ -159,6 +159,11 @@ protected:
    */
   void OnDoAction(const Property::Index actionId, const Property::Value& attributes) override;
 
    */
   void OnDoAction(const Property::Index actionId, const Property::Value& attributes) override;
 
+  /**
+   * @copydoc Visual::Base::OnDoActionExtension
+   */
+  void OnDoActionExtension(const Property::Index actionId, Dali::Any attributes) override;
+
 private:
   /**
    * Helper method to set individual values by index key.
 private:
   /**
    * Helper method to set individual values by index key.
index 302fce7..a202747 100644 (file)
@@ -631,6 +631,14 @@ void VectorAnimationTask::ApplyAnimationData()
     mVectorRenderer.InvalidateBuffer();
   }
 
     mVectorRenderer.InvalidateBuffer();
   }
 
+  if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_DYNAMIC_PROPERTY)
+  {
+    for(auto&& iter : mAnimationData[index].dynamicProperties)
+    {
+      mVectorRenderer.AddPropertyValueCallback(iter.keyPath, static_cast<VectorAnimationRenderer::VectorProperty>(iter.property), iter.callback, iter.id);
+    }
+  }
+
   if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_PLAY_STATE)
   {
     if(mAnimationData[index].playState == DevelImageVisual::PlayState::PLAYING)
   if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_PLAY_STATE)
   {
     if(mAnimationData[index].playState == DevelImageVisual::PlayState::PLAYING)
@@ -647,6 +655,8 @@ void VectorAnimationTask::ApplyAnimationData()
     }
   }
 
     }
   }
 
+  // reset data
+  mAnimationData[index].dynamicProperties.clear();
   mAnimationData[index].resendFlag = 0;
 }
 
   mAnimationData[index].resendFlag = 0;
 }
 
index 0ca2295..42d13f8 100644 (file)
 #include <dali/devel-api/adaptor-framework/event-thread-callback.h>
 #include <dali/devel-api/adaptor-framework/vector-animation-renderer.h>
 #include <dali/devel-api/threading/conditional-wait.h>
 #include <dali/devel-api/adaptor-framework/event-thread-callback.h>
 #include <dali/devel-api/adaptor-framework/vector-animation-renderer.h>
 #include <dali/devel-api/threading/conditional-wait.h>
+#include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/object/property-array.h>
 #include <chrono>
 #include <memory>
 
 // INTERNAL INCLUDES
 #include <dali/public-api/object/property-array.h>
 #include <chrono>
 #include <memory>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 
 namespace Dali
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 
 namespace Dali
@@ -54,7 +56,8 @@ public:
 
   using ResourceReadySignalType = Signal<void(ResourceStatus)>;
 
 
   using ResourceReadySignalType = Signal<void(ResourceStatus)>;
 
-  using TimePoint = std::chrono::time_point<std::chrono::steady_clock>;
+  using TimePoint           = std::chrono::time_point<std::chrono::steady_clock>;
+  using DynamicPropertyType = std::vector<DevelAnimatedVectorImageVisual::DynamicPropertyInfo>;
 
   /**
    * Flags for re-sending data to the vector animation thread
 
   /**
    * Flags for re-sending data to the vector animation thread
@@ -68,7 +71,8 @@ public:
     RESEND_CURRENT_FRAME       = 1 << 4,
     RESEND_SIZE                = 1 << 5,
     RESEND_PLAY_STATE          = 1 << 6,
     RESEND_CURRENT_FRAME       = 1 << 4,
     RESEND_SIZE                = 1 << 5,
     RESEND_PLAY_STATE          = 1 << 6,
-    RESEND_NEED_RESOURCE_READY = 1 << 7
+    RESEND_NEED_RESOURCE_READY = 1 << 7,
+    RESEND_DYNAMIC_PROPERTY    = 1 << 8
   };
 
   /**
   };
 
   /**
@@ -79,6 +83,7 @@ public:
     AnimationData()
     : resendFlag(0),
       playRange(),
     AnimationData()
     : resendFlag(0),
       playRange(),
+      dynamicProperties(),
       playState(),
       stopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME),
       loopingMode(DevelImageVisual::LoopingMode::RESTART),
       playState(),
       stopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME),
       loopingMode(DevelImageVisual::LoopingMode::RESTART),
@@ -100,11 +105,13 @@ public:
       width        = rhs.width;
       height       = rhs.height;
       loopCount    = rhs.loopCount;
       width        = rhs.width;
       height       = rhs.height;
       loopCount    = rhs.loopCount;
+      dynamicProperties.insert(dynamicProperties.end(), rhs.dynamicProperties.begin(), rhs.dynamicProperties.end());
       return *this;
     }
 
     uint32_t                             resendFlag;
     Property::Array                      playRange;
       return *this;
     }
 
     uint32_t                             resendFlag;
     Property::Array                      playRange;
+    DynamicPropertyType                  dynamicProperties;
     DevelImageVisual::PlayState::Type    playState;
     DevelImageVisual::StopBehavior::Type stopBehavior;
     DevelImageVisual::LoopingMode::Type  loopingMode;
     DevelImageVisual::PlayState::Type    playState;
     DevelImageVisual::StopBehavior::Type stopBehavior;
     DevelImageVisual::LoopingMode::Type  loopingMode;
index 99b6c38..ce78b7e 100644 (file)
@@ -517,6 +517,11 @@ void Visual::Base::DoAction(const Property::Index actionId, const Property::Valu
   }
 }
 
   }
 }
 
+void Visual::Base::DoActionExtension(const Dali::Property::Index actionId, const Dali::Any attributes)
+{
+  OnDoActionExtension(actionId, attributes);
+}
+
 void Visual::Base::SetDepthIndex(int index)
 {
   mImpl->mDepthIndex = index;
 void Visual::Base::SetDepthIndex(int index)
 {
   mImpl->mDepthIndex = index;
@@ -698,6 +703,11 @@ void Visual::Base::OnDoAction(const Property::Index actionId, const Property::Va
   // May be overriden by derived class
 }
 
   // May be overriden by derived class
 }
 
+void Visual::Base::OnDoActionExtension(const Property::Index actionId, const Dali::Any attributes)
+{
+  // May be overriden by derived class
+}
+
 void Visual::Base::RegisterMixColor()
 {
   if(mImpl->mRenderer)
 void Visual::Base::RegisterMixColor()
 {
   if(mImpl->mRenderer)
index bdcb193..7ebf239 100644 (file)
@@ -100,6 +100,14 @@ public:
   void DoAction(const Dali::Property::Index actionId, const Dali::Property::Value attributes);
 
   /**
   void DoAction(const Dali::Property::Index actionId, const Dali::Property::Value attributes);
 
   /**
+   * @brief Performs an action on the visual with the given action id and attributes.
+   *
+   * @param[in] actionId The id of the action to perform this API only takes an Index
+   * @param[in] attributes The list of attributes for the action. ( optional for this data structure to have content )
+   */
+  void DoActionExtension(const Dali::Property::Index actionId, const Dali::Any attributes);
+
+  /**
    * @copydoc Toolkit::Visual::Base::GetHeightForWidth
    */
   virtual float GetHeightForWidth(float width);
    * @copydoc Toolkit::Visual::Base::GetHeightForWidth
    */
   virtual float GetHeightForWidth(float width);
@@ -363,6 +371,14 @@ protected:
   virtual void OnDoAction(const Property::Index actionId, const Property::Value& attributes);
 
   /**
   virtual void OnDoAction(const Property::Index actionId, const Property::Value& attributes);
 
   /**
+   * @brief Called by DoActionExtension() allowing sub classes to do the given action.
+   *
+   * @param[in] actionId The action to perform
+   * @param[in] attributes The list of attributes for the action. ( optional for this data structure to have content )
+   */
+  virtual void OnDoActionExtension(const Property::Index actionId, Dali::Any attributes);
+
+  /**
    * @brief Update the shader when some properties are changed.
    */
   virtual void UpdateShader()
    * @brief Update the shader when some properties are changed.
    */
   virtual void UpdateShader()