X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fanimated-image%2Fanimated-image-visual.cpp;h=fcb3811501037777838531f4949b74f22a867467;hp=2512baf66a5c30b819ae1525f1ca115466a58565;hb=e3a661ed9b8268e1ebac5ab26088673de706c509;hpb=e40a68da97d5a5564be9a194c4e02949ad5313cb diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp old mode 100644 new mode 100755 index 2512baf..fcb3811 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 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. @@ -19,17 +19,23 @@ #include "animated-image-visual.h" // EXTERNAL INCLUDES -#include +#include +#include +#include // INTERNAL INCLUDES #include -#include +#include #include #include #include #include +#include +#include +#include #include #include +#include namespace Dali { @@ -51,46 +57,150 @@ DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, MIRRORED_REPEAT ) DALI_ENUM_TO_STRING_TABLE_END( WRAP_MODE ) const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); +constexpr auto LOOP_FOREVER = -1; +#if defined(DEBUG_ENABLED) +Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ANIMATED_IMAGE"); +#endif } -AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const std::string& imageUrl, const Property::Map& properties ) + +/** + * Multi-image Flow of execution + * + * | New + * | DoSetProperties() + * | LoadFirstBatch() + * | new cache + * | cache->LoadBatch() + * | + * | DoSetOnStage() + * | PrepareTextureSet() + * | cache->FirstFrame() + * | CreateRenderer() (Doesn't become ready until first frame loads) + * | StartFirstFrame() + * | + * | FrameReady(textureSet) + * | start first frame: + * | actor.AddRenderer + * | start timer + * | mRenderer.SetTextures(textureSet) + * | + * | Timer ticks + * | DisplayNextFrame() + * | if front frame is ready, + * | mRenderer.SetTextures( front frame's texture ) + * | else + * | mWaitingForTexture=true + * | cache->LoadBatch() + * | + * | FrameReady(textureSet) + * | mRenderer.SetTextures(textureSet) + * V + * Time + */ + +AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl, const Property::Map& properties ) { - AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache ); - visual->mImageUrl = imageUrl; + AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache ) ); + visual->InitializeGif( imageUrl ); visual->SetProperties( properties ); + if( visual->mFrameCount > 0 ) + { + visual->LoadFirstBatch(); + } + return visual; } -AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const std::string& imageUrl ) +AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const Property::Array& imageUrls, const Property::Map& properties ) { - AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache ); - visual->mImageUrl = imageUrl; + AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache ) ); + visual->mImageUrls = new ImageCache::UrlList(); + visual->mImageUrls->reserve( imageUrls.Count() ); + + for( unsigned int i=0; i < imageUrls.Count(); ++i) + { + ImageCache::UrlStore urlStore; + urlStore.mTextureId = TextureManager::INVALID_TEXTURE_ID; + urlStore.mUrl = imageUrls[i].Get(); + visual->mImageUrls->push_back( urlStore ); + } + visual->mFrameCount = imageUrls.Count(); + visual->SetProperties( properties ); + + if( visual->mFrameCount > 0 ) + { + visual->LoadFirstBatch(); + } return visual; } +AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl ) +{ + AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache ) ); + visual->InitializeGif( imageUrl ); + + if( visual->mFrameCount > 0 ) + { + visual->LoadFirstBatch(); + } + + return visual; +} + +void AnimatedImageVisual::InitializeGif( const VisualUrl& imageUrl ) +{ + mImageUrl = imageUrl; + mGifLoading = GifLoading::New( imageUrl.GetUrl(), imageUrl.IsLocalResource() ); + mFrameCount = mGifLoading->GetImageCount(); + mGifLoading->LoadFrameDelays( mFrameDelayContainer ); +} + AnimatedImageVisual::AnimatedImageVisual( VisualFactoryCache& factoryCache ) -: Visual::Base( factoryCache ), +: Visual::Base( factoryCache, Visual::FittingMode::FIT_KEEP_ASPECT_RATIO ), mFrameDelayTimer(), + mPlacementActor(), mPixelArea( FULL_TEXTURE_RECT ), mImageUrl(), - mImageSize(), + mGifLoading( nullptr ), mCurrentFrameIndex( 0 ), + mImageUrls( NULL ), + mImageCache( NULL ), + mCacheSize( 1 ), + mBatchSize( 1 ), + mFrameDelay( 100 ), + mLoopCount( LOOP_FOREVER ), + mCurrentLoopIndex( 0 ), + mUrlIndex( 0 ), + mFrameCount( 0 ), + mImageSize(), mWrapModeU( WrapMode::DEFAULT ), - mWrapModeV( WrapMode::DEFAULT ) + mWrapModeV( WrapMode::DEFAULT ), + mActionStatus( DevelAnimatedImageVisual::Action::PLAY ), + mStartFirstFrame(false) {} AnimatedImageVisual::~AnimatedImageVisual() { + delete mImageCache; + delete mImageUrls; } void AnimatedImageVisual::GetNaturalSize( Vector2& naturalSize ) { if( mImageSize.GetWidth() == 0 && mImageSize.GetHeight() == 0) { - mImageSize = Dali::GetGifImageSize( mImageUrl ); + if( mImageUrl.IsValid() ) + { + mImageSize = mGifLoading->GetImageSize(); + } + else if( mImageUrls && mImageUrls->size() > 0 ) + { + mImageSize = Dali::GetClosestImageSize( (*mImageUrls)[0].mUrl ); + } } naturalSize.width = mImageSize.GetWidth(); @@ -101,16 +211,31 @@ void AnimatedImageVisual::DoCreatePropertyMap( Property::Map& map ) const { map.Clear(); - map.Insert( Toolkit::DevelVisual::Property::TYPE, Toolkit::DevelVisual::ANIMATED_IMAGE ); + map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::ANIMATED_IMAGE ); - if( !mImageUrl.empty() ) + if( mImageUrl.IsValid() ) { - map.Insert( Toolkit::ImageVisual::Property::URL, mImageUrl ); + map.Insert( Toolkit::ImageVisual::Property::URL, mImageUrl.GetUrl() ); + } + if( mImageUrls != NULL && ! mImageUrls->empty() ) + { + Property::Array urls; + for( unsigned int i=0; isize(); ++i) + { + urls.Add( (*mImageUrls)[i].mUrl ); + } + Property::Value value( const_cast(urls) ); + map.Insert( Toolkit::ImageVisual::Property::URL, value ); } map.Insert( Toolkit::ImageVisual::Property::PIXEL_AREA, mPixelArea ); map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_U, mWrapModeU ); map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_V, mWrapModeV ); + + map.Insert( Toolkit::ImageVisual::Property::BATCH_SIZE, static_cast(mBatchSize) ); + map.Insert( Toolkit::ImageVisual::Property::CACHE_SIZE, static_cast(mCacheSize) ); + map.Insert( Toolkit::ImageVisual::Property::FRAME_DELAY, static_cast(mFrameDelay) ); + map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast(mLoopCount) ); } void AnimatedImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const @@ -118,83 +243,181 @@ void AnimatedImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) cons // Do nothing } -void AnimatedImageVisual::DoSetProperties( const Property::Map& propertyMap ) +void AnimatedImageVisual::OnDoAction( const Dali::Property::Index actionId, const Dali::Property::Value& attributes ) { - // url already passed in from constructor + // Check if action is valid for this visual type and perform action if possible - Property::Value* pixelAreaValue = propertyMap.Find( Toolkit::ImageVisual::Property::PIXEL_AREA, PIXEL_AREA_UNIFORM_NAME ); - if( pixelAreaValue ) + switch ( actionId ) { - pixelAreaValue->Get( mPixelArea ); + case DevelAnimatedImageVisual::Action::PAUSE: + { + // Pause will be executed on next timer tick + mActionStatus = DevelAnimatedImageVisual::Action::PAUSE; + break; + } + case DevelAnimatedImageVisual::Action::PLAY: + { + if( IsOnStage() && mActionStatus != DevelAnimatedImageVisual::Action::PLAY ) + { + mFrameDelayTimer.Start(); + } + mActionStatus = DevelAnimatedImageVisual::Action::PLAY; + break; + } + case DevelAnimatedImageVisual::Action::STOP: + { + // STOP reset functionality will actually be done in a future change + // Stop will be executed on next timer tick + mCurrentFrameIndex = 0; + mActionStatus = DevelAnimatedImageVisual::Action::STOP; + break; + } } +} - Property::Value* wrapModeValueU = propertyMap.Find( Toolkit::ImageVisual::Property::WRAP_MODE_U, IMAGE_WRAP_MODE_U ); - if( wrapModeValueU ) - { - int value; - Scripting::GetEnumerationProperty( *wrapModeValueU, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, value ); - mWrapModeU = Dali::WrapMode::Type( value ); - } +void AnimatedImageVisual::DoSetProperties( const Property::Map& propertyMap ) +{ + // url[s] already passed in from constructor - Property::Value* wrapModeValueV = propertyMap.Find( Toolkit::ImageVisual::Property::WRAP_MODE_V, IMAGE_WRAP_MODE_V ); - if( wrapModeValueV ) + for( Property::Map::SizeType iter = 0; iter < propertyMap.Count(); ++iter ) { - int value; - Scripting::GetEnumerationProperty( *wrapModeValueV, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, value ); - mWrapModeV = Dali::WrapMode::Type( value ); + KeyValuePair keyValue = propertyMap.GetKeyValue( iter ); + if( keyValue.first.type == Property::Key::INDEX ) + { + DoSetProperty( keyValue.first.indexKey, keyValue.second ); + } + else + { + if( keyValue.first == PIXEL_AREA_UNIFORM_NAME ) + { + DoSetProperty( Toolkit::ImageVisual::Property::PIXEL_AREA, keyValue.second ); + } + else if( keyValue.first == IMAGE_WRAP_MODE_U ) + { + DoSetProperty( Toolkit::ImageVisual::Property::WRAP_MODE_U, keyValue.second ); + } + else if( keyValue.first == IMAGE_WRAP_MODE_V ) + { + DoSetProperty( Toolkit::ImageVisual::Property::WRAP_MODE_V, keyValue.second ); + } + else if( keyValue.first == BATCH_SIZE_NAME ) + { + DoSetProperty( Toolkit::ImageVisual::Property::BATCH_SIZE, keyValue.second ); + } + else if( keyValue.first == CACHE_SIZE_NAME ) + { + DoSetProperty( Toolkit::ImageVisual::Property::CACHE_SIZE, keyValue.second ); + } + else if( keyValue.first == FRAME_DELAY_NAME ) + { + DoSetProperty( Toolkit::ImageVisual::Property::FRAME_DELAY, keyValue.second ); + } + else if( keyValue.first == LOOP_COUNT_NAME ) + { + DoSetProperty( Toolkit::DevelImageVisual::Property::LOOP_COUNT, keyValue.second ); + } + } } } -void AnimatedImageVisual::DoSetOnStage( Actor& actor ) +void AnimatedImageVisual::DoSetProperty( Property::Index index, + const Property::Value& value ) { - Texture texture = PrepareAnimatedImage(); - if( texture ) // if the image loading is successful + switch(index) { - bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE; - Shader shader = ImageVisual::GetImageShader( mFactoryCache, true, defaultWrapMode ); - - Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); - - TextureSet textureSet = TextureSet::New(); - textureSet.SetTexture( 0u, texture ); - - mImpl->mRenderer = Renderer::New( geometry, shader ); - mImpl->mRenderer.SetTextures( textureSet ); - - // Register transform properties - mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); + case Toolkit::ImageVisual::Property::PIXEL_AREA: + { + value.Get( mPixelArea ); + break; + } + case Toolkit::ImageVisual::Property::WRAP_MODE_U: + { + int wrapMode = 0; + if(Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode )) + { + mWrapModeU = Dali::WrapMode::Type(wrapMode); + } + else + { + mWrapModeU = Dali::WrapMode::Type::DEFAULT; + } + break; + } + case Toolkit::ImageVisual::Property::WRAP_MODE_V: + { + int wrapMode = 0; + if(Scripting::GetEnumerationProperty( value, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, wrapMode )) + { + mWrapModeV = Dali::WrapMode::Type(wrapMode); + } + else + { + mWrapModeV = Dali::WrapMode::Type::DEFAULT; + } + break; + } - if( !defaultWrapMode ) // custom wrap mode + case Toolkit::ImageVisual::Property::BATCH_SIZE: { - Vector2 wrapMode(mWrapModeU-WrapMode::CLAMP_TO_EDGE, mWrapModeV-WrapMode::CLAMP_TO_EDGE); - wrapMode.Clamp( Vector2::ZERO, Vector2( 2.f, 2.f ) ); - mImpl->mRenderer.RegisterProperty( WRAP_MODE_UNIFORM_NAME, wrapMode ); + int batchSize; + if( value.Get( batchSize ) ) + { + mBatchSize = batchSize; + } + break; } - if( mPixelArea != FULL_TEXTURE_RECT ) + case Toolkit::ImageVisual::Property::CACHE_SIZE: { - mImpl->mRenderer.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, mPixelArea ); + int cacheSize; + if( value.Get( cacheSize ) ) + { + mCacheSize = cacheSize; + } + break; } - mCurrentFrameIndex = 0; - mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mTextureRectContainer[mCurrentFrameIndex] ); - if( mFrameDelayContainer.Count() > 1 ) + case Toolkit::ImageVisual::Property::FRAME_DELAY: { - mFrameDelayTimer = Timer::New( mFrameDelayContainer[0] ); - mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame ); - mFrameDelayTimer.Start(); + int frameDelay; + if( value.Get( frameDelay ) ) + { + mFrameDelay = frameDelay; + } + break; } - actor.AddRenderer( mImpl->mRenderer ); + case Toolkit::DevelImageVisual::Property::LOOP_COUNT: + { + int loopCount; + if( value.Get( loopCount ) ) + { + mLoopCount = loopCount; + } + break; + } } } -void AnimatedImageVisual::DoSetOffStage( Actor& actor ) +void AnimatedImageVisual::DoSetOnStage( Actor& actor ) { - if( !mImpl->mRenderer ) + mPlacementActor = actor; + TextureSet textureSet = PrepareTextureSet(); + CreateRenderer(); // Always create a renderer when on stage + + if( textureSet ) // if the image loading is successful + { + StartFirstFrame( textureSet ); + } + else { - return; + mStartFirstFrame = true; } +} + +void AnimatedImageVisual::DoSetOffStage( Actor& actor ) +{ + DALI_ASSERT_DEBUG( (bool)mImpl->mRenderer && "There should always be a renderer whilst on stage"); if( mFrameDelayTimer ) { @@ -202,11 +425,9 @@ void AnimatedImageVisual::DoSetOffStage( Actor& actor ) mFrameDelayTimer.Reset(); } - mTextureRectContainer.Clear(); - mFrameDelayContainer.Clear(); - actor.RemoveRenderer( mImpl->mRenderer ); mImpl->mRenderer.Reset(); + mPlacementActor.Reset(); } void AnimatedImageVisual::OnSetTransform() @@ -217,30 +438,213 @@ void AnimatedImageVisual::OnSetTransform() } } -Texture AnimatedImageVisual::PrepareAnimatedImage() +void AnimatedImageVisual::CreateRenderer() { - // load from image file - std::vector pixelDataList; - if( Dali::LoadAnimatedGifFromFile( mImageUrl.c_str() , pixelDataList, mFrameDelayContainer ) ) + bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE; + bool atlasing = false; + Shader shader = ImageVisual::GetImageShader( mFactoryCache, atlasing, defaultWrapMode ); + + Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); + + mImpl->mRenderer = Renderer::New( geometry, shader ); + + // Register transform properties + mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); + + if( !defaultWrapMode ) // custom wrap mode { - mImageSize.SetWidth( pixelDataList[0].GetWidth() ); - mImageSize.SetHeight( pixelDataList[0].GetHeight() ); + Vector2 wrapMode(mWrapModeU-WrapMode::CLAMP_TO_EDGE, mWrapModeV-WrapMode::CLAMP_TO_EDGE); + wrapMode.Clamp( Vector2::ZERO, Vector2( 2.f, 2.f ) ); + mImpl->mRenderer.RegisterProperty( WRAP_MODE_UNIFORM_NAME, wrapMode ); + } - return Toolkit::ImageAtlas::PackToAtlas( pixelDataList, mTextureRectContainer ); + if( mPixelArea != FULL_TEXTURE_RECT ) + { + mImpl->mRenderer.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, mPixelArea ); } - return Texture(); + mCurrentFrameIndex = 0; +} + +void AnimatedImageVisual::LoadFirstBatch() +{ + // Ensure the batch size and cache size are no bigger than the number of URLs, + // and that the cache is at least as big as the batch size. + uint16_t numUrls = 0; + uint16_t batchSize = 1; + uint16_t cacheSize = 1; + + if( mImageUrls ) + { + numUrls = mImageUrls->size(); + } + else + { + numUrls = mFrameCount; + } + + batchSize = std::min( mBatchSize, numUrls ); + cacheSize = std::min( std::max( batchSize, mCacheSize ), numUrls ); + + DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::LoadFirstBatch() batchSize:%d cacheSize:%d\n", batchSize, cacheSize); + + mUrlIndex = 0; + TextureManager& textureManager = mFactoryCache.GetTextureManager(); + + if( mGifLoading != nullptr ) + { + mImageCache = new RollingGifImageCache( textureManager, *mGifLoading, mFrameCount, *this, cacheSize, batchSize ); + } + else if( mImageUrls ) + { + if( batchSize > 0 && cacheSize > 0 ) + { + if( cacheSize < numUrls ) + { + mImageCache = new RollingImageCache( textureManager, *mImageUrls, *this, cacheSize, batchSize ); + } + else + { + mImageCache = new FixedImageCache( textureManager, *mImageUrls, *this, batchSize ); + } + } + else + { + mImageCache = new RollingImageCache( textureManager, *mImageUrls, *this, 1, 1 ); + } + } + + if (!mImageCache) + { + DALI_LOG_ERROR("mImageCache is null"); + } +} + +void AnimatedImageVisual::StartFirstFrame( TextureSet& textureSet ) +{ + DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::StartFirstFrame()\n"); + + mStartFirstFrame = false; + mImpl->mRenderer.SetTextures( textureSet ); + Actor actor = mPlacementActor.GetHandle(); + if( actor ) + { + actor.AddRenderer( mImpl->mRenderer ); + mPlacementActor.Reset(); + } + + mCurrentFrameIndex = 0; + + if( mFrameCount > 1 ) + { + int frameDelay = mFrameDelay; // from URL array + if( mFrameDelayContainer.Count() > 0 ) // from GIF + { + frameDelay = mFrameDelayContainer[0]; + } + + mFrameDelayTimer = Timer::New( frameDelay ); + mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame ); + mFrameDelayTimer.Start(); + } + DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"ResourceReady(ResourceStatus::READY)\n"); + ResourceReady( Toolkit::Visual::ResourceStatus::READY ); +} + +TextureSet AnimatedImageVisual::PrepareTextureSet() +{ + TextureSet textureSet; + if (mImageCache) + textureSet = mImageCache->FirstFrame(); + if( textureSet ) + { + SetImageSize( textureSet ); + } + else + { + DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"ResourceReady(ResourceStatus::FAILED)\n"); + ResourceReady( Toolkit::Visual::ResourceStatus::FAILED ); + } + + return textureSet; +} + +void AnimatedImageVisual::SetImageSize( TextureSet& textureSet ) +{ + if( textureSet ) + { + Texture texture = textureSet.GetTexture( 0 ); + if( texture ) + { + mImageSize.SetWidth( texture.GetWidth() ); + mImageSize.SetHeight( texture.GetHeight() ); + } + } +} + +void AnimatedImageVisual::FrameReady( TextureSet textureSet ) +{ + SetImageSize( textureSet ); + + if( mStartFirstFrame ) + { + StartFirstFrame( textureSet ); + } + else + { + mImpl->mRenderer.SetTextures( textureSet ); + } } bool AnimatedImageVisual::DisplayNextFrame() { - mCurrentFrameIndex = (mCurrentFrameIndex+1) % mFrameDelayContainer.Count(); - mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mTextureRectContainer[mCurrentFrameIndex] ); - if( mFrameDelayTimer.GetInterval() != mFrameDelayContainer[mCurrentFrameIndex] ) + if( mActionStatus == DevelAnimatedImageVisual::Action::STOP || mActionStatus == DevelAnimatedImageVisual::Action::PAUSE ) + { + return false; + } + if( mFrameCount > 1 ) + { + // Wrap the frame index + ++mCurrentFrameIndex; + + if( mLoopCount < 0 || mCurrentLoopIndex <= mLoopCount) + { + mCurrentFrameIndex %= mFrameCount; + if( mCurrentFrameIndex == 0 ) + { + ++mCurrentLoopIndex; + } + } + else + { + // This will stop timer + return false; + } + } + DALI_LOG_INFO( gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::DisplayNextFrame(this:%p) FrameCount:%d\n", this, mCurrentFrameIndex); + + if( mFrameDelayContainer.Count() > 0 ) + { + unsigned int delay = mFrameDelayContainer[mCurrentFrameIndex]; + + if( mFrameDelayTimer.GetInterval() != delay ) + { + mFrameDelayTimer.SetInterval( delay ); + } + } + + TextureSet textureSet; + if( mImageCache ) { - mFrameDelayTimer.SetInterval( mFrameDelayContainer[mCurrentFrameIndex] ); + textureSet = mImageCache->NextFrame(); + if( textureSet ) + { + SetImageSize( textureSet ); + mImpl->mRenderer.SetTextures( textureSet ); + } } + // Keep timer ticking return true; }