From: David Steele Date: Mon, 9 Jan 2017 19:17:59 +0000 (+0000) Subject: Updated visual property animator to handle shader properties X-Git-Tag: dali_1.2.23~13^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=984fcbe3031a3ce3142515c515ccef9112c33c65 Updated visual property animator to handle shader properties If the AnimateProperty() method cannot find the requested property in the renderer, it now checks the shader. If it finds a registered uniform, then it registers the same uniform on the renderer, and sets up the appropriate transition. Change-Id: I0f5ae27deec005f406d18ca9de28ed9cf57f96a3 Signed-off-by: David Steele --- diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index b6478a0..6d88a51 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -1459,6 +1459,69 @@ int UtcDaliVisualAnimateImageVisualMixColor(void) END_TEST; } +int UtcDaliVisualAnimateImageVisualPixelArea(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliAnimateImageVisual pixel area" ); + + application.GetPlatform().SetClosestImageSize( Vector2(100, 100) ); + + VisualFactory factory = VisualFactory::Get(); + Property::Map propertyMap; + propertyMap.Insert(Visual::Property::TYPE, Visual::IMAGE); + propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME ); + propertyMap.Insert("mixColor", Color::BLUE); + propertyMap.Insert(ImageVisual::Property::SYNCHRONOUS_LOADING, true); + Visual::Base visual = factory.CreateVisual( propertyMap ); + + DummyControl actor = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + actor.SetSize(2000, 2000); + actor.SetParentOrigin(ParentOrigin::CENTER); + actor.SetColor(Color::BLACK); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION); + + Renderer renderer = actor.GetRendererAt(0); + Property::Index index = DevelHandle::GetPropertyIndex( renderer, DevelVisual::Property::MIX_COLOR ); + + tet_infoline("Test that the renderer has the mixColor property"); + DALI_TEST_CHECK( index != Property::INVALID_INDEX ); + + // TransitionData only takes string keys + Property::Map map; + map["target"] = "testVisual"; + map["property"] = "pixelArea"; + map["initialValue"] = Vector4( 0,0,0,1 ); + map["targetValue"] = Vector4( 0,0,1,1 ); // Animate width from zero to full + map["animator"] = Property::Map() + .Add("alphaFunction", "LINEAR") + .Add("timePeriod", Property::Map() + .Add("delay", 0.0f) + .Add("duration", 4.0f)); + + Dali::Toolkit::TransitionData transition = TransitionData::New( map ); + + Animation animation = dummyImpl.CreateTransition( transition ); + animation.AnimateTo( Property(actor, Actor::Property::COLOR), Color::WHITE ); + animation.Play(); + + application.SendNotification(); + application.Render(0); + application.Render(2000u); // halfway point + + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue("pixelArea", Vector4(0.0f, 0.0f, 0.5f, 1.0f )), true, TEST_LOCATION ); + + application.Render(2000u); + + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue("pixelArea", Vector4( 0.0f, 0.0f, 1.0f, 1.0f )), true, TEST_LOCATION ); + + END_TEST; +} + int UtcDaliVisualWireframeVisual(void) { diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index 719a0fb..68620ea 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -349,7 +349,77 @@ Renderer Visual::Base::GetRenderer() return mImpl->mRenderer; } -void Visual::Base::AnimateProperty( Dali::Animation& transition, Internal::TransitionData::Animator& animator ) + +Property::Index Visual::Base::GetPropertyIndex( Property::Key key ) +{ + Property::Index index = DevelHandle::GetPropertyIndex( mImpl->mRenderer, key ); + + if( index == Property::INVALID_INDEX ) + { + // Is it a shader property? + Shader shader = mImpl->mRenderer.GetShader(); + index = DevelHandle::GetPropertyIndex( shader, key ); + if( index != Property::INVALID_INDEX ) + { + // Yes - we should register it in the Renderer so it can be set / animated + // independently, as shaders are shared across multiple renderers. + std::string keyName; + Property::Index keyIndex( Property::INVALID_KEY ); + if( key.type == Property::Key::INDEX ) + { + keyName = shader.GetPropertyName( index ); + keyIndex = key.indexKey; + } + else + { + keyName = key.stringKey; + // Leave keyIndex as INVALID_KEY - it can still be registered against the string key. + } + Property::Value value = shader.GetProperty( index ); + index = DevelHandle::RegisterProperty( mImpl->mRenderer, keyIndex, keyName, value ); + } + } + return index; +} + +void Visual::Base::SetupTransition( + Dali::Animation& transition, + Internal::TransitionData::Animator& animator, + Property::Index index ) +{ + if( index != Property::INVALID_INDEX ) + { + if( mImpl->mRenderer ) + { + if( animator.animate == false ) + { + mImpl->mRenderer.SetProperty( index, animator.targetValue ); + } + else + { + if( animator.initialValue.GetType() != Property::NONE ) + { + mImpl->mRenderer.SetProperty( index, animator.initialValue ); + } + + if( ! transition ) + { + transition = Dali::Animation::New( 0.1f ); + } + + transition.AnimateTo( Property( mImpl->mRenderer, index ), + animator.targetValue, + animator.alphaFunction, + TimePeriod( animator.timePeriodDelay, + animator.timePeriodDuration ) ); + } + } + } +} + +void Visual::Base::AnimateProperty( + Dali::Animation& transition, + Internal::TransitionData::Animator& animator ) { #if defined(DEBUG_ENABLED) { @@ -361,21 +431,31 @@ void Visual::Base::AnimateProperty( Dali::Animation& transition, Internal::Trans Property::Index index = Property::INVALID_INDEX; - // Get the property index bool isMixColor = false; + bool isMixColorOpaque = true; + + // Get the property index if( animator.propertyKey == Toolkit::DevelVisual::Property::MIX_COLOR || animator.propertyKey == MIX_COLOR ) { isMixColor = true; index = mImpl->mMixColorIndex; + + Vector4 initialColor; + if( animator.initialValue.Get(initialColor) ) // if there is an initial color, test it + { + isMixColorOpaque = initialColor.a >= 1.0f; + } + else + { + isMixColorOpaque = mImpl->mMixColor.a >= 1.0f; // otherwise, test the current color + } } else if( mImpl->mRenderer ) { - index = DevelHandle::GetPropertyIndex( mImpl->mRenderer, animator.propertyKey ); + index = GetPropertyIndex( animator.propertyKey ); } - Vector4 currentMixColor( mImpl->mMixColor ); - // Set target value into data store if( animator.targetValue.GetType() != Property::NONE ) { @@ -385,7 +465,8 @@ void Visual::Base::AnimateProperty( Dali::Animation& transition, Internal::Trans } else { - // Note: there may be several of these calls if more than one transform property is animated. + // Note: there may be several of these calls if more than one + // transform property is animated. Property::Map map; if( animator.propertyKey.type == Property::Key::INDEX ) { @@ -402,69 +483,23 @@ void Visual::Base::AnimateProperty( Dali::Animation& transition, Internal::Trans if( index != Property::INVALID_INDEX ) { - if( mImpl->mRenderer ) - { - if( animator.animate == false ) - { - mImpl->mRenderer.SetProperty( index, animator.targetValue ); - if( isMixColor ) - { - mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, mImpl->mMixColor.a < 1.0 ? BlendMode::ON : BlendMode::AUTO ); - } - } - else - { - if( animator.initialValue.GetType() != Property::NONE ) - { - if( isMixColor ) - { - animator.initialValue.Get( currentMixColor ); - } - -#if defined(DEBUG_ENABLED) - { - std::ostringstream oss; - oss << animator.initialValue; - DALI_LOG_INFO( gVisualBaseLogFilter, Debug::General, " Setting Initial Value - %s\n", oss.str().c_str() ); - } -#endif - mImpl->mRenderer.SetProperty( index, animator.initialValue ); - } - - if( isMixColor ) - { - mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, - ( currentMixColor.a < 1.0 || mImpl->mMixColor.a < 1.0 ) ? BlendMode::ON : BlendMode::AUTO ); - } - - if( ! transition ) - { - transition = Dali::Animation::New( 0.1f ); - } + SetupTransition( transition, animator, index ); -#if defined(DEBUG_ENABLED) - { - std::ostringstream oss; - oss << animator.targetValue; - DALI_LOG_INFO( gVisualBaseLogFilter, Debug::General, " Animating to Value - %s\n", oss.str().c_str() ); - } -#endif - - transition.AnimateTo( Property( mImpl->mRenderer, index ), - animator.targetValue, - animator.alphaFunction, - TimePeriod( animator.timePeriodDelay, - animator.timePeriodDuration ) ); + // For mix color, ensure the blend mode is on if the initial or final values are not opaque, + // and that it is turned off after the animation ends if the final value is opaque + if( isMixColor && (!isMixColorOpaque || mImpl->mMixColor.a < 1.0f) ) + { + mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON ); - if( isMixColor && currentMixColor.a < 1.0f && mImpl->mMixColor.a >= 1.0f ) + if( animator.animate == true && mImpl->mMixColor.a >= 1.0f ) + { + // When it becomes opaque, set the blend mode back to automatically + if( ! mImpl->mBlendSlotDelegate ) { - // When it becomes opaque, set the blend mode back to automatically - if( ! mImpl->mBlendSlotDelegate ) - { - mImpl->mBlendSlotDelegate = new SlotDelegate(this); - } - transition.FinishedSignal().Connect( *(mImpl->mBlendSlotDelegate), &Visual::Base::OnMixColorFinished ); + mImpl->mBlendSlotDelegate = new SlotDelegate(this); } + transition.FinishedSignal().Connect( *(mImpl->mBlendSlotDelegate), + &Visual::Base::OnMixColorFinished ); } } } diff --git a/dali-toolkit/internal/visuals/visual-base-impl.h b/dali-toolkit/internal/visuals/visual-base-impl.h index 054708f..1722964 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-impl.h @@ -270,6 +270,27 @@ private: void RegisterMixColor(); /** + * Find the matching property on the renderer or shader. If it's a shader + * property, register it on the renderer in order to animate it for this + * visual independently. + * @param[in] key The key to match. + * @return the matching index, or INVALID_INDEX if it's not found + */ + Property::Index GetPropertyIndex( Property::Key key ); + + /** + * Set up the transition. If no animation is required, then + * transition will be untouched. + * + * @param[in] transition The transition to use or set up. + * @param[in] animator The animation data to use + * @param[in] index The property index on the renderer to animate + */ + void SetupTransition( Dali::Animation& transition, + Internal::TransitionData::Animator& animator, + Property::Index index ); + + /** * When a mix color animation has finished, ensure the blend mode is set back * to the right value for the target opacity. */ diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index a0796ec..18dd3fd 100644 --- a/dali-toolkit/public-api/controls/control-impl.cpp +++ b/dali-toolkit/public-api/controls/control-impl.cpp @@ -79,8 +79,10 @@ struct RegisteredVisual Toolkit::Visual::Base visual; bool enabled; - RegisteredVisual( Property::Index aIndex, Toolkit::Visual::Base &aVisual, bool aEnabled) : - index(aIndex), visual(aVisual), enabled(aEnabled) {} + RegisteredVisual( Property::Index aIndex, Toolkit::Visual::Base &aVisual, bool aEnabled) + : index(aIndex), visual(aVisual), enabled(aEnabled) + { + } }; typedef Dali::OwnerContainer< RegisteredVisual* > RegisteredVisualContainer; @@ -793,8 +795,8 @@ void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visu { Toolkit::GetImplementation(visual).SetOnStage( self ); } - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual number of registered visuals(%d)\n", mImpl->mVisuals.Size() ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n", visual.GetName().c_str(), index, enabled?"T":"F" ); } void Control::UnregisterVisual( Property::Index index ) @@ -827,7 +829,7 @@ void Control::EnableVisual( Property::Index index, bool enable ) { if ( (*iter)->enabled == enable ) { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual Already enabled set (%s) \n", enable?"enabled":"disabled"); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled"); return; } @@ -837,12 +839,12 @@ void Control::EnableVisual( Property::Index index, bool enable ) { if ( enable ) { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting Visual(%d) on stage \n", index ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index ); Toolkit::GetImplementation((*iter)->visual).SetOnStage( parentActor ); } else { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting Visual(%d) off stage \n", index ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index ); Toolkit::GetImplementation((*iter)->visual).SetOffStage( parentActor ); // No need to call if control not staged. } }