mNeedDroppedFrames = false;
}
+ if(mDynamicPropertyCallback)
+ {
+ CallbackBase::ExecuteReturn<Property::Value>(*mDynamicPropertyCallback, 0, 0, frameNumber);
+ }
+
if(mNeedTrigger)
{
mEventThreadCallback->Trigger();
}
}
+ 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;
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;
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();
#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>
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;
+}
/*
- * 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.
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);
#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.
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.
#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.
* limitations under the License.
*
*/
+
+// EXTERNAL INCLUDES
#include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
+#include <dali/public-api/signals/callback.h>
+#include <string>
namespace Dali
{
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
+/**
+ * @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
}
}
+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 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
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 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.
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)
}
}
+ // reset data
+ mAnimationData[index].dynamicProperties.clear();
mAnimationData[index].resendFlag = 0;
}
#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-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
namespace Dali
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
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
};
/**
AnimationData()
: resendFlag(0),
playRange(),
+ dynamicProperties(),
playState(),
stopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME),
loopingMode(DevelImageVisual::LoopingMode::RESTART),
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;
+ DynamicPropertyType dynamicProperties;
DevelImageVisual::PlayState::Type playState;
DevelImageVisual::StopBehavior::Type stopBehavior;
DevelImageVisual::LoopingMode::Type loopingMode;
}
}
+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;
// 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 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);
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()