{
public:
- VectorAnimationRenderer( const std::string& url, Dali::Renderer renderer, uint32_t width, uint32_t height )
+ VectorAnimationRenderer( const std::string& url )
: mUrl( url ),
- mRenderer( renderer ),
- mWidth( width ),
- mHeight( height )
+ mRenderer(),
+ mWidth( 0 ),
+ mHeight( 0 )
{
}
+ void SetRenderer( Dali::Renderer renderer )
+ {
+ mRenderer = renderer;
+ }
+
void SetSize( uint32_t width, uint32_t height )
{
mWidth = width;
/********************************* PUBLIC CLASS *******************************/
/********************************************************************************/
-VectorAnimationRenderer VectorAnimationRenderer::New( const std::string& url, Renderer renderer, uint32_t width, uint32_t height )
+VectorAnimationRenderer VectorAnimationRenderer::New( const std::string& url )
{
- Internal::Adaptor::VectorAnimationRenderer* animationRenderer = new Internal::Adaptor::VectorAnimationRenderer( url, renderer, width, height );
+ Internal::Adaptor::VectorAnimationRenderer* animationRenderer = new Internal::Adaptor::VectorAnimationRenderer( url );
return VectorAnimationRenderer( animationRenderer );
}
return *this;
}
+void VectorAnimationRenderer::SetRenderer( Renderer renderer )
+{
+ Internal::Adaptor::GetImplementation( *this ).SetRenderer( renderer );
+}
+
void VectorAnimationRenderer::SetSize( uint32_t width, uint32_t height )
{
Internal::Adaptor::GetImplementation( *this ).SetSize( width, height );
value = map.Find( DevelImageVisual::Property::PLAY_STATE );
DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::PLAYING ) );
+ tet_infoline( "Off stage" );
+ dummyControl.Unparent();
+
+ application.SendNotification();
+ application.Render(16);
+
+ map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL );
+ value = map.Find( DevelImageVisual::Property::PLAY_STATE );
+ DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::PAUSED ) );
+
+ tet_infoline( "On stage again" );
+ Stage::GetCurrent().Add( dummyControl );
+
+ application.SendNotification();
+ application.Render(16);
+
+ map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL );
+ value = map.Find( DevelImageVisual::Property::PLAY_STATE );
+ DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::PAUSED ) );
+
+ tet_infoline( "Test Play action" );
+ DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes );
+
+ application.SendNotification();
+ application.Render(16);
+
+ map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL );
+ value = map.Find( DevelImageVisual::Property::PLAY_STATE );
+ DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::PLAYING ) );
+
// Change Size
Vector3 newSize( 100.0f, 100.0f, 0.0f );
dummyControl.SetSize( newSize );
// EXTERNAL INCLUDES
#include <dali/public-api/common/stage.h>
-#include <dali/devel-api/common/stage-devel.h>
+#include <dali/devel-api/rendering/renderer-devel.h>
#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
#include <dali-toolkit/internal/visuals/visual-string-constants.h>
#include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
-#include <dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h>
namespace Dali
{
{
const Dali::Vector4 FULL_TEXTURE_RECT( 0.f, 0.f, 1.f, 1.f );
-constexpr auto LOOP_FOREVER = -1;
} // unnamed namespace
: Visual::Base( factoryCache, Visual::FittingMode::FILL ),
mImageVisualShaderFactory( shaderFactory ),
mUrl( imageUrl ),
+ mVectorRasterizeThread( imageUrl.GetUrl() ),
mVisualSize(),
- mPlayRange( 0.0f, 1.0f ),
mPlacementActor(),
- mVectorRasterizeThread(),
- mLoopCount( LOOP_FOREVER ),
mActionStatus( DevelAnimatedVectorImageVisual::Action::STOP )
{
// the rasterized image is with pre-multiplied alpha format
mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
+
+ mVectorRasterizeThread.SetResourceReadyCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnResourceReady ) ) );
+ mVectorRasterizeThread.SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) );
+
+ mVectorRasterizeThread.Start();
}
AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
{
map.Insert( Toolkit::ImageVisual::Property::URL, mUrl.GetUrl() );
}
- map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast< int >( mLoopCount ) );
- map.Insert( Toolkit::DevelImageVisual::Property::PLAY_RANGE, static_cast< Vector2 >( mPlayRange ) );
-
- if( mVectorRasterizeThread )
- {
- map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int >( mVectorRasterizeThread->GetPlayState() ) );
- }
- else
- {
- map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int >( DevelImageVisual::PlayState::STOPPED ) );
- }
+ map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast< int >( mVectorRasterizeThread.GetLoopCount() ) );
+ map.Insert( Toolkit::DevelImageVisual::Property::PLAY_RANGE, static_cast< Vector2 >( mVectorRasterizeThread.GetPlayRange() ) );
+ map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int >( mVectorRasterizeThread.GetPlayState() ) );
}
void AnimatedVectorImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
int32_t loopCount;
if( value.Get( loopCount ) )
{
- mLoopCount = loopCount;
- if( mVectorRasterizeThread )
- {
- mVectorRasterizeThread->SetLoopCount( loopCount );
- }
+ mVectorRasterizeThread.SetLoopCount( loopCount );
}
break;
}
Vector2 range;
if( value.Get( range ) )
{
- // Make sure the range specified is between 0.0 and 1.0
- if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
- {
- Vector2 orderedRange( range );
- // If the range is not in order swap values
- if( range.x > range.y )
- {
- orderedRange = Vector2( range.y, range.x );
- }
-
- mPlayRange = orderedRange;
-
- if( mVectorRasterizeThread )
- {
- mVectorRasterizeThread->SetPlayRange( mPlayRange );
- }
- }
+ mVectorRasterizeThread.SetPlayRange( range );
}
break;
}
// Hold the weak handle of the placement actor and delay the adding of renderer until the rasterization is finished.
mPlacementActor = actor;
- // This visual needs it's size set before it can be rasterized hence set ResourceReady once on stage
- ResourceReady( Toolkit::Visual::ResourceStatus::READY );
+ mVectorRasterizeThread.SetRenderer( mImpl->mRenderer );
}
void AnimatedVectorImageVisual::DoSetOffStage( Actor& actor )
{
- if( mVectorRasterizeThread )
- {
- mVectorRasterizeThread->PauseAnimation();
- DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
- mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE;
- }
+ mVectorRasterizeThread.PauseAnimation();
+
+ mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE;
if( mImpl->mRenderer )
{
+ mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED );
+
actor.RemoveRenderer( mImpl->mRenderer );
mImpl->mRenderer.Reset();
}
{
mVisualSize = visualSize;
- if( !mVectorRasterizeThread )
+ uint32_t width = static_cast< uint32_t >( visualSize.width );
+ uint32_t height = static_cast< uint32_t >( visualSize.height );
+
+ mVectorRasterizeThread.SetSize( width, height );
+ }
+
+ if( mActionStatus == DevelAnimatedVectorImageVisual::Action::PLAY )
+ {
+ mVectorRasterizeThread.PlayAnimation();
+
+ mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY );
+ }
+ else
+ {
+ // Render one frame
+ mVectorRasterizeThread.RenderFrame();
+ }
+
+ if( mVectorRasterizeThread.IsResourceReady() )
+ {
+ Actor actor = mPlacementActor.GetHandle();
+ if( actor )
{
- uint32_t width = static_cast< uint32_t >( visualSize.width );
- uint32_t height = static_cast< uint32_t >( visualSize.height );
-
- mVectorRasterizeThread = std::unique_ptr< VectorRasterizeThread >( new VectorRasterizeThread( mUrl.GetUrl(), mImpl->mRenderer, width, height ) );
-
- mVectorRasterizeThread->SetResourceReadyCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnResourceReady ) ) );
- mVectorRasterizeThread->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) );
- mVectorRasterizeThread->SetLoopCount( mLoopCount );
- mVectorRasterizeThread->SetPlayRange( mPlayRange );
-
- mVectorRasterizeThread->Start();
-
- if( mActionStatus == DevelAnimatedVectorImageVisual::Action::PLAY )
- {
- mVectorRasterizeThread->StartAnimation();
- DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::CONTINUOUSLY );
- }
- else
- {
- // Render one frame
- mVectorRasterizeThread->RenderFrame();
- }
+ actor.AddRenderer( mImpl->mRenderer );
+ mPlacementActor.Reset();
}
- else
- {
- uint32_t width = static_cast< uint32_t >( visualSize.width );
- uint32_t height = static_cast< uint32_t >( visualSize.height );
- mVectorRasterizeThread->SetSize( width, height );
- }
+ ResourceReady( Toolkit::Visual::ResourceStatus::READY );
}
}
}
{
case DevelAnimatedVectorImageVisual::Action::PLAY:
{
- if( IsOnStage())
+ if( IsOnStage() )
{
- if( mVectorRasterizeThread )
- {
- mVectorRasterizeThread->StartAnimation();
- DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::CONTINUOUSLY ); //TODO: Should manage this globally
- }
+ mVectorRasterizeThread.PlayAnimation();
+
+ mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY );
}
mActionStatus = DevelAnimatedVectorImageVisual::Action::PLAY;
break;
}
case DevelAnimatedVectorImageVisual::Action::PAUSE:
{
- if( mVectorRasterizeThread )
+ mVectorRasterizeThread.PauseAnimation();
+
+ if( mImpl->mRenderer )
{
- mVectorRasterizeThread->PauseAnimation();
- DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
+ mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED );
}
+
mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE;
break;
}
case DevelAnimatedVectorImageVisual::Action::STOP:
{
- if( mVectorRasterizeThread )
+ if( mVectorRasterizeThread.GetPlayState() != DevelImageVisual::PlayState::STOPPED )
{
- bool emitSignal = false;
- if( mVectorRasterizeThread->GetPlayState() != DevelImageVisual::PlayState::STOPPED )
- {
- emitSignal = true;
- }
-
- mVectorRasterizeThread->StopAnimation();
- DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED );
-
- if( emitSignal )
- {
- OnAnimationFinished();
- }
+ mVectorRasterizeThread.StopAnimation();
+
+ OnAnimationFinished();
}
mActionStatus = DevelAnimatedVectorImageVisual::Action::STOP;
break;
actor.AddRenderer( mImpl->mRenderer );
// reset the weak handle so that the renderer only get added to actor once
mPlacementActor.Reset();
-
- Stage::GetCurrent().KeepRendering( 0.0f );
}
+
+ ResourceReady( Toolkit::Visual::ResourceStatus::READY );
}
void AnimatedVectorImageVisual::OnAnimationFinished()
{
mImpl->mEventObserver->NotifyVisualEvent( *this, DevelAnimatedVectorImageVisual::Signal::ANIMATION_FINISHED );
}
+
+ mActionStatus = DevelAnimatedVectorImageVisual::Action::STOP;
+
+ if( mImpl->mRenderer )
+ {
+ mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED );
+ }
}
} // namespace Internal
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
#include <dali-toolkit/internal/visuals/visual-url.h>
#include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h>
+#include <dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h>
namespace Dali
{
private:
ImageVisualShaderFactory& mImageVisualShaderFactory;
VisualUrl mUrl;
+ VectorRasterizeThread mVectorRasterizeThread;
Vector2 mVisualSize;
- Vector2 mPlayRange;
WeakHandle< Actor > mPlacementActor;
- std::unique_ptr< VectorRasterizeThread > mVectorRasterizeThread;
-
- int32_t mLoopCount;
DevelAnimatedVectorImageVisual::Action::Type mActionStatus;
};
} // unnamed namespace
-VectorRasterizeThread::VectorRasterizeThread( const std::string& url, Renderer renderer, uint32_t width, uint32_t height )
+VectorRasterizeThread::VectorRasterizeThread( const std::string& url )
: mUrl( url ),
mVectorRenderer(),
mConditionalWait(),
mAnimationFinishedTrigger(),
mPlayRange( 0.0f, 1.0f ),
mPlayState( DevelImageVisual::PlayState::STOPPED ),
+ mProgress( 0.0f ),
mCurrentFrame( 0 ),
mTotalFrame( 0 ),
mStartFrame( 0 ),
mEndFrame( 0 ),
- mWidth( width ),
- mHeight( height ),
+ mWidth( 0 ),
+ mHeight( 0 ),
mLoopCount( LOOP_FOREVER ),
mCurrentLoop( 0 ),
mNeedRender( false ),
mResourceReady( false ),
mLogFactory( Dali::Adaptor::Get().GetLogFactory() )
{
- mVectorRenderer = VectorAnimationRenderer::New( mUrl, renderer, width, height );
+ mVectorRenderer = VectorAnimationRenderer::New( mUrl );
}
VectorRasterizeThread::~VectorRasterizeThread()
}
}
-void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height )
+void VectorRasterizeThread::SetRenderer( Renderer renderer )
{
ConditionalWait::ScopedLock lock( mConditionalWait );
- mVectorRenderer.SetSize( width, height );
- DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetSize: width = %d, height = %d\n", width, height );
+ mVectorRenderer.SetRenderer( renderer );
+
+ DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetRenderer\n" );
+}
+
+void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height )
+{
+ if( mWidth != width || mHeight != height )
+ {
+ ConditionalWait::ScopedLock lock( mConditionalWait );
+ mVectorRenderer.SetSize( width, height );
+
+ mWidth = width;
+ mHeight = height;
+
+ mResourceReady = false;
+
+ DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetSize: width = %d, height = %d\n", width, height );
+ }
}
-void VectorRasterizeThread::StartAnimation()
+void VectorRasterizeThread::PlayAnimation()
{
ConditionalWait::ScopedLock lock( mConditionalWait );
if( mPlayState != DevelImageVisual::PlayState::PLAYING )
mPlayState = DevelImageVisual::PlayState::PLAYING;
mConditionalWait.Notify( lock );
- DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartAnimation: Start\n" );
+ DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PlayAnimation: Start\n" );
}
}
mAnimationFinishedTrigger = std::unique_ptr< EventThreadCallback >( callback );
}
-void VectorRasterizeThread::SetLoopCount( int16_t count )
+void VectorRasterizeThread::SetLoopCount( int32_t count )
{
ConditionalWait::ScopedLock lock( mConditionalWait );
mCurrentFrame = mStartFrame;
}
+int32_t VectorRasterizeThread::GetLoopCount() const
+{
+ return mLoopCount;
+}
+
void VectorRasterizeThread::SetPlayRange( Vector2 range )
{
ConditionalWait::ScopedLock lock( mConditionalWait );
- mPlayRange = range;
-
- if( mTotalFrame != 0 )
+ // Make sure the range specified is between 0.0 and 1.0
+ if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
{
- mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
- mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
+ Vector2 orderedRange( range );
+ // If the range is not in order swap values
+ if( range.x > range.y )
+ {
+ orderedRange = Vector2( range.y, range.x );
+ }
+
+ mPlayRange = orderedRange;
+
+ if( mTotalFrame != 0 )
+ {
+ mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
+ mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
+ }
}
}
-DevelImageVisual::PlayState VectorRasterizeThread::GetPlayState()
+Vector2 VectorRasterizeThread::GetPlayRange() const
+{
+ return mPlayRange;
+}
+
+DevelImageVisual::PlayState VectorRasterizeThread::GetPlayState() const
{
return mPlayState;
}
+bool VectorRasterizeThread::IsResourceReady() const
+{
+ return mResourceReady;
+}
+
bool VectorRasterizeThread::IsThreadReady()
{
ConditionalWait::ScopedLock lock( mConditionalWait );
* @brief Constructor.
*
* @param[in] url The url of the vector animation file
- * @param[in] renderer The renderer used to render the image
- * @param[in] width The width of the content
- * @param[in] height The height of the content
*/
- VectorRasterizeThread( const std::string& url, Renderer renderer, uint32_t width, uint32_t height );
+ VectorRasterizeThread( const std::string& url );
/**
* @brief Destructor.
virtual ~VectorRasterizeThread();
/**
+ * @brief Sets the renderer used to display the result image.
+ *
+ * @param[in] renderer The renderer used to display the result image
+ */
+ void SetRenderer( Renderer renderer );
+
+ /**
* @brief Sets the target image size.
*
* @param[in] width The target image width
/**
* @brief Play the vector animation.
*/
- void StartAnimation();
+ void PlayAnimation();
/**
* @brief Stop the vector animation.
* @brief Enable looping for 'count' repeats. -1 means to repeat forever.
* @param[in] count The number of times to loop
*/
- void SetLoopCount( int16_t count );
+ void SetLoopCount( int32_t count );
+
+ /**
+ * @brief Gets the loop count. -1 means to repeat forever.
+ * @return The number of times to loop
+ */
+ int32_t GetLoopCount() const;
/**
* @brief Set the playing range.
void SetPlayRange( Vector2 range );
/**
+ * @brief Gets the playing range.
+ * @return The play range defined for the animation
+ */
+ Vector2 GetPlayRange() const;
+
+ /**
* @brief Get the play state
* @return The play state
*/
- DevelImageVisual::PlayState GetPlayState();
+ DevelImageVisual::PlayState GetPlayState() const;
+
+ /**
+ * @brief Queries whether the resource is ready.
+ * @return true if ready, false otherwise
+ */
+ bool IsResourceReady() const;
protected:
std::unique_ptr< EventThreadCallback > mAnimationFinishedTrigger;
Vector2 mPlayRange;
DevelImageVisual::PlayState mPlayState;
+ float mProgress;
uint32_t mCurrentFrame;
uint32_t mTotalFrame;
uint32_t mStartFrame;
uint32_t mEndFrame;
uint32_t mWidth;
uint32_t mHeight;
- int16_t mLoopCount;
- int16_t mCurrentLoop;
+ int32_t mLoopCount;
+ int32_t mCurrentLoop;
bool mNeedRender;
bool mDestroyThread; ///< Whether the thread be destroyed
bool mResourceReady;