From: Heeyong Song Date: Tue, 17 Nov 2020 10:16:33 +0000 (+0900) Subject: Add GetVisualProperty to Control X-Git-Tag: dali_2.0.6~10 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=798ef5fa1591aa78851e9e3d08fe37411192176a Add GetVisualProperty to Control Change-Id: I099bb989dfc5808907c6ebe7cc260727b39faaa4 --- diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index fde1197..c135c9f 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -3934,3 +3934,261 @@ int UtcDaliVisualGetType(void) END_TEST; } + +int UtcDaliVisualGetVisualProperty01(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliVisualGetVisualProperty01: Test animatable property, Visual::Base, ColorVisual" ); + + VisualFactory factory = VisualFactory::Get(); + Property::Map propertyMap; + propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR); + propertyMap.Insert(Visual::Property::MIX_COLOR, Color::BLUE); + propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS, 10.0f); + propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS_POLICY, Toolkit::Visual::Transform::Policy::RELATIVE); + propertyMap.Insert(DevelColorVisual::Property::BLUR_RADIUS, 20.0f); + Visual::Base colorVisual = factory.CreateVisual(propertyMap); + + DummyControl dummyControl = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(dummyControl.GetImplementation()); + dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, colorVisual); + dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f); + application.GetScene().Add(dummyControl); + + application.SendNotification(); + application.Render(); + + Vector3 targetColor(1.0f, 1.0f, 1.0f); + float targetOpacity = 0.5f; + float targetCornerRadius = 20.0f; + float targetBlurRadius = 10.0f; + + Animation animation = Animation::New(1.0f); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::MIX_COLOR), targetColor); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::OPACITY), targetOpacity); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::CORNER_RADIUS), targetCornerRadius); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelColorVisual::Property::BLUR_RADIUS), targetBlurRadius); + animation.Play(); + + application.SendNotification(); + application.Render(); + application.Render(1001u); // End of animation + + Property::Map resultMap; + colorVisual.CreatePropertyMap( resultMap ); + + // Test property values: they should be updated + Property::Value* colorValue = resultMap.Find(ColorVisual::Property::MIX_COLOR, Property::VECTOR4); + DALI_TEST_CHECK(colorValue); + DALI_TEST_EQUALS(colorValue->Get(), Vector4(targetColor.r, targetColor.g, targetColor.b, targetOpacity), TEST_LOCATION); + + Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::FLOAT); + DALI_TEST_CHECK(cornerRadiusValue); + DALI_TEST_EQUALS(cornerRadiusValue->Get< float >(), targetCornerRadius, TEST_LOCATION); + + Property::Value* blurRadiusValue = resultMap.Find(DevelColorVisual::Property::BLUR_RADIUS, Property::FLOAT); + DALI_TEST_CHECK(blurRadiusValue); + DALI_TEST_EQUALS(blurRadiusValue->Get< float >(), targetBlurRadius, TEST_LOCATION); + + // Test uniform values + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("mixColor", targetColor), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("cornerRadius", targetCornerRadius), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("blurRadius", targetBlurRadius), true, TEST_LOCATION); + + // Test not-supported property + Property property1 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::PREMULTIPLIED_ALPHA); + DALI_TEST_CHECK(!property1.object); + DALI_TEST_CHECK(property1.propertyIndex == Property::INVALID_INDEX); + + // Test not-supported property + Property property2 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelColorVisual::Property::RENDER_IF_TRANSPARENT); + DALI_TEST_CHECK(!property2.object); + DALI_TEST_CHECK(property2.propertyIndex == Property::INVALID_INDEX); + + // Test unregistered visual + Property property3 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL2, Visual::Property::MIX_COLOR); + DALI_TEST_CHECK(!property3.object); + DALI_TEST_CHECK(property3.propertyIndex == Property::INVALID_INDEX); + + // Test after the control is unparented + dummyControl.Unparent(); + + Property property4 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::MIX_COLOR); + DALI_TEST_CHECK(!property4.object); + DALI_TEST_CHECK(property4.propertyIndex == Property::INVALID_INDEX); + + END_TEST; +} + +int UtcDaliVisualGetVisualProperty02(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliVisualGetVisualProperty02: Test animatable property" ); + + VisualFactory factory = VisualFactory::Get(); + Property::Map propertyMap; + propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR); + Visual::Base colorVisual = factory.CreateVisual(propertyMap); + + DummyControl dummyControl = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(dummyControl.GetImplementation()); + dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, colorVisual); + dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f); + application.GetScene().Add(dummyControl); + + application.SendNotification(); + application.Render(); + + Vector3 targetColor(1.0f, 1.0f, 1.0f); + float targetOpacity = 0.5f; + float targetCornerRadius = 20.0f; + float targetBlurRadius = 10.0f; + + // Should work when the properties are not set before + Animation animation = Animation::New(1.0f); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "mixColor"), targetColor); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "opacity"), targetOpacity); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "cornerRadius"), targetCornerRadius); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "blurRadius"), targetBlurRadius); + animation.Play(); + + application.SendNotification(); + application.Render(); + application.Render(1001u); // End of animation + + Property::Map resultMap; + colorVisual.CreatePropertyMap(resultMap); + + // Test property values: they should be updated + Property::Value* colorValue = resultMap.Find(ColorVisual::Property::MIX_COLOR, Property::VECTOR4); + DALI_TEST_CHECK(colorValue); + DALI_TEST_EQUALS(colorValue->Get(), Vector4(targetColor.r, targetColor.g, targetColor.b, targetOpacity), TEST_LOCATION); + + Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::FLOAT); + DALI_TEST_CHECK(cornerRadiusValue); + DALI_TEST_EQUALS(cornerRadiusValue->Get< float >(), targetCornerRadius, TEST_LOCATION); + + Property::Value* blurRadiusValue = resultMap.Find(DevelColorVisual::Property::BLUR_RADIUS, Property::FLOAT); + DALI_TEST_CHECK(blurRadiusValue); + DALI_TEST_EQUALS(blurRadiusValue->Get< float >(), targetBlurRadius, TEST_LOCATION); + + // Test uniform values + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("mixColor", targetColor), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("cornerRadius", targetCornerRadius), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("blurRadius", targetBlurRadius), true, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVisualGetVisualProperty03(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliVisualGetVisualProperty01: Test animatable property, ImageVisual" ); + + VisualFactory factory = VisualFactory::Get(); + Property::Map propertyMap; + propertyMap.Insert(Visual::Property::TYPE, Visual::IMAGE); + propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME); + Visual::Base imageVisual = factory.CreateVisual(propertyMap); + + DummyControl dummyControl = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(dummyControl.GetImplementation()); + dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, imageVisual); + dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f); + application.GetScene().Add(dummyControl); + + // Wait for image loading + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + application.SendNotification(); + application.Render(); + + float targetOpacity = 0.5f; + float targetCornerRadius = 20.0f; + + Animation animation = Animation::New(1.0f); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::OPACITY), targetOpacity); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::CORNER_RADIUS), targetCornerRadius); + animation.Play(); + + application.SendNotification(); + application.Render(); + application.Render(1001u); // End of animation + + Property::Map resultMap; + imageVisual.CreatePropertyMap( resultMap ); + + // Test property values: they should be updated + Property::Value* colorValue = resultMap.Find(Visual::Property::MIX_COLOR, Property::VECTOR4); + DALI_TEST_CHECK(colorValue); + DALI_TEST_EQUALS(colorValue->Get(), Vector4(1.0f, 1.0f, 1.0f, targetOpacity), TEST_LOCATION); + + Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::FLOAT); + DALI_TEST_CHECK(cornerRadiusValue); + DALI_TEST_EQUALS(cornerRadiusValue->Get< float >(), targetCornerRadius, TEST_LOCATION); + + // Test uniform value + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("cornerRadius", targetCornerRadius), true, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVisualGetVisualProperty04(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliVisualGetVisualProperty01: Test animatable property, GradientVisual" ); + + Vector2 start(-1.f, -1.f); + Vector2 end(1.f, 1.f); + Property::Array stopColors; + stopColors.PushBack( Color::RED ); + stopColors.PushBack( Color::GREEN ); + + VisualFactory factory = VisualFactory::Get(); + Property::Map propertyMap; + propertyMap.Insert(Visual::Property::TYPE, Visual::GRADIENT); + propertyMap.Insert(GradientVisual::Property::START_POSITION, start); + propertyMap.Insert(GradientVisual::Property::END_POSITION, end); + propertyMap.Insert(GradientVisual::Property::STOP_OFFSET, Vector2(0.f, 1.f)); + propertyMap.Insert(GradientVisual::Property::SPREAD_METHOD, GradientVisual::SpreadMethod::REPEAT); + propertyMap.Insert(GradientVisual::Property::STOP_COLOR, stopColors); + Visual::Base gradientVisual = factory.CreateVisual(propertyMap); + + DummyControl dummyControl = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(dummyControl.GetImplementation()); + dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, gradientVisual); + dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f); + application.GetScene().Add(dummyControl); + + application.SendNotification(); + application.Render(); + + float targetOpacity = 0.5f; + float targetCornerRadius = 20.0f; + + Animation animation = Animation::New(1.0f); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::OPACITY), targetOpacity); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::CORNER_RADIUS), targetCornerRadius); + animation.Play(); + + application.SendNotification(); + application.Render(); + application.Render(1001u); // End of animation + + Property::Map resultMap; + gradientVisual.CreatePropertyMap( resultMap ); + + // Test property values: they should be updated + Property::Value* colorValue = resultMap.Find(Visual::Property::MIX_COLOR, Property::VECTOR4); + DALI_TEST_CHECK(colorValue); + DALI_TEST_EQUALS(colorValue->Get(), Vector4(1.0f, 1.0f, 1.0f, targetOpacity), TEST_LOCATION); + + Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::FLOAT); + DALI_TEST_CHECK(cornerRadiusValue); + DALI_TEST_EQUALS(cornerRadiusValue->Get< float >(), targetCornerRadius, TEST_LOCATION); + + // Test uniform value + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("cornerRadius", targetCornerRadius), true, TEST_LOCATION); + + END_TEST; +} diff --git a/dali-toolkit/devel-api/controls/control-devel.cpp b/dali-toolkit/devel-api/controls/control-devel.cpp index a855b2d..0670e68 100644 --- a/dali-toolkit/devel-api/controls/control-devel.cpp +++ b/dali-toolkit/devel-api/controls/control-devel.cpp @@ -115,6 +115,13 @@ VisualEventSignalType& VisualEventSignal(Control control) return controlDataImpl.VisualEventSignal(); } +Dali::Property GetVisualProperty(Control control, Dali::Property::Index index, Dali::Property::Key visualPropertyKey) +{ + Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control); + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(internalControl); + return controlDataImpl.GetVisualProperty(index, visualPropertyKey); +} + static Toolkit::Internal::Control::Impl *GetControlImplementationIfAny( Dali::Actor actor) { Dali::Toolkit::Control c = Toolkit::Control::DownCast( actor ); diff --git a/dali-toolkit/devel-api/controls/control-devel.h b/dali-toolkit/devel-api/controls/control-devel.h index 5753a69..af6c76c 100644 --- a/dali-toolkit/devel-api/controls/control-devel.h +++ b/dali-toolkit/devel-api/controls/control-devel.h @@ -358,6 +358,18 @@ using VisualEventSignalType = Signalindex == index) + { + visualHandle = (*iter)->visual; + break; + } + } + return visualHandle; +} + /** * Move visual from source to destination container */ @@ -1820,6 +1838,19 @@ void Control::Impl::ClearShadow() mControlImpl.RelayoutRequest(); } +Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey) +{ + Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index); + if(visual) + { + Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual); + return visualImpl.GetPropertyObject(visualPropertyKey); + } + + Handle handle; + return Dali::Property(handle, Property::INVALID_INDEX); +} + void Control::Impl::EmitResourceReadySignal() { if(!mIsEmittingResourceReadySignal) diff --git a/dali-toolkit/internal/controls/control/control-data-impl.h b/dali-toolkit/internal/controls/control/control-data-impl.h index aefb484..aa16060 100755 --- a/dali-toolkit/internal/controls/control/control-data-impl.h +++ b/dali-toolkit/internal/controls/control/control-data-impl.h @@ -391,6 +391,11 @@ public: */ void ClearShadow(); + /** + * @copydoc DevelControl::GetVisualProperty() + */ + Dali::Property GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey); + private: /** diff --git a/dali-toolkit/internal/visuals/color/color-visual.cpp b/dali-toolkit/internal/visuals/color/color-visual.cpp index edebccf..68dc04a 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.cpp +++ b/dali-toolkit/internal/visuals/color/color-visual.cpp @@ -187,10 +187,12 @@ ColorVisualPtr ColorVisual::New( VisualFactoryCache& factoryCache, const Propert return colorVisualPtr; } -ColorVisual::ColorVisual( VisualFactoryCache& factoryCache ) -: Visual::Base( factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::COLOR ), - mBlurRadius( 0.0f ), - mRenderIfTransparent( false ) +ColorVisual::ColorVisual(VisualFactoryCache& factoryCache) +: Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::COLOR), + mBlurRadius(0.0f), + mBlurRadiusIndex(Property::INVALID_INDEX), + mRenderIfTransparent(false), + mNeedBlurRadius(false) { } @@ -259,13 +261,36 @@ void ColorVisual::DoSetOnScene( Actor& actor ) ResourceReady( Toolkit::Visual::ResourceStatus::READY ); } +void ColorVisual::DoSetOffScene(Actor& actor) +{ + if(mImpl->mRenderer && mBlurRadiusIndex != Property::INVALID_INDEX) + { + // Update values from Renderer + mBlurRadius = mImpl->mRenderer.GetProperty(mBlurRadiusIndex); + } + + actor.RemoveRenderer(mImpl->mRenderer); + mImpl->mRenderer.Reset(); + mBlurRadiusIndex = Property::INVALID_INDEX; +} + void ColorVisual::DoCreatePropertyMap( Property::Map& map ) const { map.Clear(); map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR ); map.Insert( Toolkit::ColorVisual::Property::MIX_COLOR, mImpl->mMixColor ); map.Insert( Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT, mRenderIfTransparent ); - map.Insert( Toolkit::DevelColorVisual::Property::BLUR_RADIUS, mBlurRadius ); + + if(mImpl->mRenderer && mBlurRadiusIndex != Property::INVALID_INDEX) + { + // Update values from Renderer + float blurRadius = mImpl->mRenderer.GetProperty(mBlurRadiusIndex); + map.Insert(Toolkit::DevelColorVisual::Property::BLUR_RADIUS, blurRadius); + } + else + { + map.Insert(Toolkit::DevelColorVisual::Property::BLUR_RADIUS, mBlurRadius); + } } void ColorVisual::DoCreateInstancePropertyMap( Property::Map& map ) const @@ -273,7 +298,6 @@ void ColorVisual::DoCreateInstancePropertyMap( Property::Map& map ) const // Do nothing } - void ColorVisual::OnSetTransform() { if( mImpl->mRenderer ) @@ -299,12 +323,42 @@ void ColorVisual::OnDoAction( const Property::Index actionId, const Property::Va } } +void ColorVisual::UpdateShader() +{ + if(mImpl->mRenderer) + { + Shader shader = GetShader(); + mImpl->mRenderer.SetShader(shader); + } +} + void ColorVisual::InitializeRenderer() { Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); + Shader shader = GetShader(); + + mImpl->mRenderer = Renderer::New(geometry, shader); + + // ColorVisual has it's own index key for mix color - use this instead + // of using the new base index to avoid changing existing applications + // String keys will get to this property. + mImpl->mMixColorIndex = mImpl->mRenderer.RegisterProperty(Toolkit::ColorVisual::Property::MIX_COLOR, MIX_COLOR, Vector3(mImpl->mMixColor)); + + if(!EqualsZero(mBlurRadius)) + { + mBlurRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius); + mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON); + } + + // Register transform properties + mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT); +} + +Shader ColorVisual::GetShader() +{ Shader shader; - if( !EqualsZero( mBlurRadius ) ) + if(!EqualsZero(mBlurRadius) || mNeedBlurRadius) { shader = mFactoryCache.GetShader( VisualFactoryCache::COLOR_SHADER_BLUR_EDGE ); if( !shader ) @@ -332,22 +386,33 @@ void ColorVisual::InitializeRenderer() } } - mImpl->mRenderer = Renderer::New( geometry, shader ); - - // ColorVisual has it's own index key for mix color - use this instead - // of using the new base index to avoid changing existing applications - // String keys will get to this property. - mImpl->mMixColorIndex = mImpl->mRenderer.RegisterProperty( Toolkit::ColorVisual::Property::MIX_COLOR, MIX_COLOR, Vector3(mImpl->mMixColor) ); + return shader; +} - mImpl->mRenderer.RegisterProperty( BLUR_RADIUS_NAME, mBlurRadius ); +Dali::Property ColorVisual::OnGetPropertyObject(Dali::Property::Key key) +{ + if(!mImpl->mRenderer) + { + Handle handle; + return Dali::Property(handle, Property::INVALID_INDEX); + } - if( !EqualsZero( mBlurRadius ) ) + if((key.type == Property::Key::INDEX && key.indexKey == DevelColorVisual::Property::BLUR_RADIUS) || (key.type == Property::Key::STRING && key.stringKey == BLUR_RADIUS_NAME)) { - mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON ); + mBlurRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius); + + mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON); + + mNeedBlurRadius = true; + + // Change shader + UpdateShader(); + + return Dali::Property(mImpl->mRenderer, mBlurRadiusIndex); } - // Register transform properties - mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); + Handle handle; + return Dali::Property(handle, Property::INVALID_INDEX); } } // namespace Internal diff --git a/dali-toolkit/internal/visuals/color/color-visual.h b/dali-toolkit/internal/visuals/color/color-visual.h index d5b2a6f..bf28d25 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.h +++ b/dali-toolkit/internal/visuals/color/color-visual.h @@ -95,6 +95,11 @@ protected: void DoSetOnScene( Actor& actor ) override; /** + * @copydoc Visual::Base::DoSetOffScene + */ + void DoSetOffScene(Actor& actor) override; + + /** * @copydoc Visual::Base::OnSetTransform */ void OnSetTransform() override; @@ -104,12 +109,28 @@ protected: */ void OnDoAction( const Property::Index actionId, const Property::Value& attributes ) override; + /** + * @copydoc Visual::Base::UpdateShader + */ + void UpdateShader() override; + + /** + * @copydoc Visual::Base::OnGetPropertyObject + */ + Dali::Property OnGetPropertyObject(Dali::Property::Key key) override; + private: /** * @brief Initialize the renderer with the geometry and shader from the cache, if not available, create and save to the cache for sharing. */ void InitializeRenderer(); + /** + * @brief Get a shader for the current properties. + * @return The shader for the current properties. + */ + Shader GetShader(); + private: // Undefined @@ -119,9 +140,10 @@ private: ColorVisual& operator=( const ColorVisual& colorRenderer ); private: - - float mBlurRadius; ///< The blur radius - bool mRenderIfTransparent; ///< Whether we should render even if the mix-color is transparent. + float mBlurRadius; ///< The blur radius + Property::Index mBlurRadiusIndex; ///< The blur radius property index + bool mRenderIfTransparent; ///< Whether we should render even if the mix-color is transparent. + bool mNeedBlurRadius; ///< Whether we need the blur radius in shader. }; } // namespace Internal diff --git a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp index d0807df..b86f9a7 100644 --- a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp +++ b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp @@ -385,6 +385,15 @@ void GradientVisual::DoSetOnScene( Actor& actor ) ResourceReady( Toolkit::Visual::ResourceStatus::READY ); } +void GradientVisual::UpdateShader() +{ + if(mImpl->mRenderer) + { + Shader shader = GetShader(); + mImpl->mRenderer.SetShader(shader); + } +} + void GradientVisual::DoCreatePropertyMap( Property::Map& map ) const { map.Clear(); @@ -436,16 +445,7 @@ void GradientVisual::DoCreateInstancePropertyMap( Property::Map& map ) const void GradientVisual::InitializeRenderer() { Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); - - Toolkit::GradientVisual::Units::Type gradientUnits = mGradient->GetGradientUnits(); - int roundedCorner = IsRoundedCornerRequired() ? 1 : 0; - VisualFactoryCache::ShaderType shaderType = SHADER_TYPE_TABLE[mGradientType][gradientUnits + roundedCorner * 2]; - Shader shader = mFactoryCache.GetShader( shaderType ); - if( !shader ) - { - shader = Shader::New( VERTEX_SHADER[gradientUnits + roundedCorner * 2], FRAGMENT_SHADER[ mGradientType + roundedCorner * 2 ] ); - mFactoryCache.SaveShader( shaderType, shader ); - } + Shader shader = GetShader(); //Set up the texture set TextureSet textureSet = TextureSet::New(); @@ -554,6 +554,21 @@ bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propert return true; } +Shader GradientVisual::GetShader() +{ + Toolkit::GradientVisual::Units::Type gradientUnits = mGradient->GetGradientUnits(); + int roundedCorner = IsRoundedCornerRequired() ? 1 : 0; + VisualFactoryCache::ShaderType shaderType = SHADER_TYPE_TABLE[mGradientType][gradientUnits + roundedCorner * 2]; + Shader shader = mFactoryCache.GetShader(shaderType); + if(!shader) + { + shader = Shader::New(VERTEX_SHADER[gradientUnits + roundedCorner * 2], FRAGMENT_SHADER[mGradientType + roundedCorner * 2]); + mFactoryCache.SaveShader(shaderType, shader); + } + + return shader; +} + void GradientVisual::GetStopOffsets(const Property::Value* value, Vector& stopOffsets) { diff --git a/dali-toolkit/internal/visuals/gradient/gradient-visual.h b/dali-toolkit/internal/visuals/gradient/gradient-visual.h index 70cdb4e..71ae1d6 100644 --- a/dali-toolkit/internal/visuals/gradient/gradient-visual.h +++ b/dali-toolkit/internal/visuals/gradient/gradient-visual.h @@ -134,6 +134,11 @@ protected: */ void DoSetOnScene( Actor& actor ) override; + /** + * @copydoc Visual::Base::UpdateShader + */ + void UpdateShader() override; + private: /** @@ -149,6 +154,12 @@ private: bool NewGradient(Type gradientType, const Property::Map& propertyMap); /** + * @brief Get a shader for the current properties. + * @return The shader for the current properties. + */ + Shader GetShader(); + + /** * Get the stop-offsets from the property. * The valid property type are ARRAY, VECTOR2, VECTOR3, VECTOR4. * diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index ec130e2..22a54e6 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -513,7 +513,6 @@ void ImageVisual::GetNaturalSize( Vector2& naturalSize ) void ImageVisual::CreateRenderer( TextureSet& textureSet ) { Geometry geometry; - Shader shader; // Get the geometry if( mImpl->mCustomShader ) @@ -534,65 +533,7 @@ void ImageVisual::CreateRenderer( TextureSet& textureSet ) } } - std::string vertexShader; - bool usesWholeTexture = true; - if(mImpl->mCustomShader && !mImpl->mCustomShader->mVertexShader.empty()) - { - vertexShader = mImpl->mCustomShader->mVertexShader; - usesWholeTexture = false; // Impossible to tell. - } - else - { - vertexShader = mImageVisualShaderFactory.GetVertexShaderSource().data(); - } - - std::string fragmentShader; - if(mImpl->mCustomShader && !mImpl->mCustomShader->mFragmentShader.empty()) - { - fragmentShader = mImpl->mCustomShader->mFragmentShader; - } - else - { - fragmentShader = mImageVisualShaderFactory.GetFragmentShaderSource().data(); - } - - // If the texture is native, we may need to change prefix and sampler in - // the fragment shader - bool modifiedFragmentShader = false; - if(mTextures && DevelTexture::IsNative(mTextures.GetTexture(0))) - { - Texture nativeTexture = mTextures.GetTexture(0); - modifiedFragmentShader = DevelTexture::ApplyNativeFragmentShader(nativeTexture, fragmentShader); - } - - const bool useStandardShader = !mImpl->mCustomShader && !modifiedFragmentShader; - if(useStandardShader) - { - // Create and cache the standard shader - shader = mImageVisualShaderFactory.GetShader( - mFactoryCache, - mImpl->mFlags & Impl::IS_ATLASING_APPLIED, - mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE, - IsRoundedCornerRequired() ); - } - else if(mImpl->mCustomShader) - { - shader = Shader::New(vertexShader, fragmentShader, mImpl->mCustomShader->mHints); - } - else - { - shader = Shader::New(vertexShader, fragmentShader); - } - - if(usesWholeTexture) - { - shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT ); - } - - // Set pixel align off as default. - // ToDo: Pixel align causes issues such as rattling image animation. - // We should trun it off until issues are resolved - shader.RegisterProperty( PIXEL_ALIGNED_UNIFORM_NAME, PIXEL_ALIGN_OFF ); + Shader shader = GetShader(); // Create the renderer mImpl->mRenderer = Renderer::New( geometry, shader ); @@ -828,6 +769,15 @@ bool ImageVisual::IsResourceReady() const mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::FAILED ); } +void ImageVisual::UpdateShader() +{ + if(mImpl->mRenderer) + { + Shader shader = GetShader(); + mImpl->mRenderer.SetShader(shader); + } +} + // From existing atlas manager void ImageVisual::UploadCompleted() { @@ -962,6 +912,73 @@ void ImageVisual::RemoveTexture() } } +Shader ImageVisual::GetShader() +{ + Shader shader; + + std::string vertexShader; + bool usesWholeTexture = true; + if(mImpl->mCustomShader && !mImpl->mCustomShader->mVertexShader.empty()) + { + vertexShader = mImpl->mCustomShader->mVertexShader; + usesWholeTexture = false; // Impossible to tell. + } + else + { + vertexShader = mImageVisualShaderFactory.GetVertexShaderSource().data(); + } + + std::string fragmentShader; + if(mImpl->mCustomShader && !mImpl->mCustomShader->mFragmentShader.empty()) + { + fragmentShader = mImpl->mCustomShader->mFragmentShader; + } + else + { + fragmentShader = mImageVisualShaderFactory.GetFragmentShaderSource().data(); + } + + // If the texture is native, we may need to change prefix and sampler in + // the fragment shader + bool modifiedFragmentShader = false; + if(mTextures && DevelTexture::IsNative(mTextures.GetTexture(0))) + { + Texture nativeTexture = mTextures.GetTexture(0); + modifiedFragmentShader = DevelTexture::ApplyNativeFragmentShader(nativeTexture, fragmentShader); + } + + const bool useStandardShader = !mImpl->mCustomShader && !modifiedFragmentShader; + if(useStandardShader) + { + // Create and cache the standard shader + shader = mImageVisualShaderFactory.GetShader( + mFactoryCache, + mImpl->mFlags & Impl::IS_ATLASING_APPLIED, + mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE, + IsRoundedCornerRequired()); + } + else if(mImpl->mCustomShader) + { + shader = Shader::New(vertexShader, fragmentShader, mImpl->mCustomShader->mHints); + } + else + { + shader = Shader::New(vertexShader, fragmentShader); + } + + if(usesWholeTexture) + { + shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT); + } + + // Set pixel align off as default. + // ToDo: Pixel align causes issues such as rattling image animation. + // We should trun it off until issues are resolved + shader.RegisterProperty(PIXEL_ALIGNED_UNIFORM_NAME, PIXEL_ALIGN_OFF); + + return shader; +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/visuals/image/image-visual.h b/dali-toolkit/internal/visuals/image/image-visual.h index f52bd69..9ae50df 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.h +++ b/dali-toolkit/internal/visuals/image/image-visual.h @@ -229,6 +229,11 @@ protected: */ bool IsResourceReady() const override; + /** + * @copydoc Visual::Base::UpdateShader + */ + void UpdateShader() override; + public: /** @@ -318,6 +323,12 @@ private: */ void DoSetProperty( Property::Index index, const Property::Value& value ); + /** + * @brief Get a shader for the current properties. + * @return The shader for the current properties. + */ + Shader GetShader(); + private: Vector4 mPixelArea; diff --git a/dali-toolkit/internal/visuals/visual-base-data-impl.cpp b/dali-toolkit/internal/visuals/visual-base-data-impl.cpp index c7b8a14..fc962bd 100644 --- a/dali-toolkit/internal/visuals/visual-base-data-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-data-impl.cpp @@ -115,21 +115,22 @@ bool GetPolicyFromValue( const Property::Value& value, Vector2& policy ) } // unnamed namespace -Internal::Visual::Base::Impl::Impl( FittingMode fittingMode, Toolkit::Visual::Type type ) -: mCustomShader( NULL ), - mEventObserver( NULL ), +Internal::Visual::Base::Impl::Impl(FittingMode fittingMode, Toolkit::Visual::Type type) +: mCustomShader(NULL), + mEventObserver(NULL), mTransform(), - mMixColor( Color::WHITE ), - mControlSize( Vector2::ZERO ), - mCornerRadius( 0.0f ), - mCornerRadiusPolicy( 1.0f ), - mDepthIndex( 0.0f ), - mMixColorIndex( Property::INVALID_INDEX ), - mCornerRadiusIndex( Property::INVALID_INDEX ), - mFittingMode( fittingMode ), - mFlags( 0 ), - mResourceStatus( Toolkit::Visual::ResourceStatus::PREPARING ), - mType( type ) + mMixColor(Color::WHITE), + mControlSize(Vector2::ZERO), + mCornerRadius(0.0f), + mCornerRadiusPolicy(1.0f), + mDepthIndex(0.0f), + mMixColorIndex(Property::INVALID_INDEX), + mCornerRadiusIndex(Property::INVALID_INDEX), + mFittingMode(fittingMode), + mFlags(0), + mResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING), + mType(type), + mNeedCornerRadius(false) { } diff --git a/dali-toolkit/internal/visuals/visual-base-data-impl.h b/dali-toolkit/internal/visuals/visual-base-data-impl.h index ae7a93e..a1056ac 100644 --- a/dali-toolkit/internal/visuals/visual-base-data-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-data-impl.h @@ -134,6 +134,7 @@ struct Base::Impl int mFlags; Toolkit::Visual::ResourceStatus mResourceStatus; const Toolkit::Visual::Type mType; + bool mNeedCornerRadius; }; } // namespace Visual diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index aca317e..6e04f0a 100755 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -323,7 +323,7 @@ void Visual::Base::SetOnScene( Actor& actor ) if( IsRoundedCornerRequired() ) { - mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty( CORNER_RADIUS, mImpl->mCornerRadius ); + mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS, mImpl->mCornerRadius); mImpl->mRenderer.RegisterProperty( CORNER_RADIUS_POLICY, mImpl->mCornerRadiusPolicy ); mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON ); @@ -340,6 +340,17 @@ void Visual::Base::SetOffScene( Actor& actor ) { if( IsOnScene() ) { + if(mImpl->mRenderer) + { + // Update values from Renderer + mImpl->mMixColor = mImpl->mRenderer.GetProperty(mImpl->mMixColorIndex); + mImpl->mMixColor.a = mImpl->mRenderer.GetProperty(DevelRenderer::Property::OPACITY); + if(mImpl->mCornerRadiusIndex != Property::INVALID_INDEX) + { + mImpl->mCornerRadius = mImpl->mRenderer.GetProperty(mImpl->mCornerRadiusIndex); + } + } + DoSetOffScene( actor ); mImpl->mMixColorIndex = Property::INVALID_INDEX; mImpl->mCornerRadiusIndex = Property::INVALID_INDEX; @@ -349,11 +360,22 @@ void Visual::Base::SetOffScene( Actor& actor ) void Visual::Base::CreatePropertyMap( Property::Map& map ) const { - DoCreatePropertyMap( map ); + if(mImpl->mRenderer) + { + // Update values from Renderer + mImpl->mMixColor = mImpl->mRenderer.GetProperty(mImpl->mMixColorIndex); + mImpl->mMixColor.a = mImpl->mRenderer.GetProperty(DevelRenderer::Property::OPACITY); + if(mImpl->mCornerRadiusIndex != Property::INVALID_INDEX) + { + mImpl->mCornerRadius = mImpl->mRenderer.GetProperty(mImpl->mCornerRadiusIndex); + } + } - if( mImpl->mCustomShader ) + DoCreatePropertyMap(map); + + if(mImpl->mCustomShader) { - mImpl->mCustomShader->CreatePropertyMap( map ); + mImpl->mCustomShader->CreatePropertyMap(map); } Property::Map transform; @@ -426,7 +448,12 @@ bool Visual::Base::IsOnScene() const bool Visual::Base::IsRoundedCornerRequired() const { - return !EqualsZero( mImpl->mCornerRadius ); + if(mImpl->mRenderer && mImpl->mCornerRadiusIndex != Property::INVALID_INDEX) + { + // Update values from Renderer + mImpl->mCornerRadius = mImpl->mRenderer.GetProperty(mImpl->mCornerRadiusIndex); + } + return !EqualsZero(mImpl->mCornerRadius) || mImpl->mNeedCornerRadius; } void Visual::Base::OnDoAction( const Property::Index actionId, const Property::Value& attributes ) @@ -479,11 +506,6 @@ void Visual::Base::SetMixColor( const Vector3& color ) } } -const Vector4& Visual::Base::GetMixColor() const -{ - return mImpl->mMixColor; -} - void Visual::Base::AddEventObserver( Visual::EventObserver& observer) { mImpl->mEventObserver = &observer; @@ -624,21 +646,12 @@ void Visual::Base::AnimateProperty( } #endif - Property::Map map; - DoCreatePropertyMap( map ); - Property::Value* valuePtr = map.Find( Toolkit::Visual::Property::TYPE ); - int visualType = -1; - if( valuePtr ) - { - valuePtr->Get( visualType ); - } - - if( animator.propertyKey == Toolkit::Visual::Property::MIX_COLOR || - animator.propertyKey == MIX_COLOR || - ( visualType == Toolkit::Visual::COLOR && - animator.propertyKey == ColorVisual::Property::MIX_COLOR ) || - ( visualType == Toolkit::Visual::PRIMITIVE && - animator.propertyKey == PrimitiveVisual::Property::MIX_COLOR ) ) + if(animator.propertyKey == Toolkit::Visual::Property::MIX_COLOR || + animator.propertyKey == MIX_COLOR || + (mImpl->mType == Toolkit::Visual::COLOR && + animator.propertyKey == ColorVisual::Property::MIX_COLOR) || + (mImpl->mType == Toolkit::Visual::PRIMITIVE && + animator.propertyKey == PrimitiveVisual::Property::MIX_COLOR)) { AnimateMixColorProperty( transition, animator ); } @@ -745,6 +758,65 @@ void Visual::Base::AnimateMixColorProperty( } } +Dali::Property Visual::Base::GetPropertyObject(Dali::Property::Key key) +{ + if(!mImpl->mRenderer) + { + Handle handle; + return Dali::Property(handle, Property::INVALID_INDEX); + } + + // Mix color or opacity cases + if(key.type == Property::Key::INDEX) + { + if(key.indexKey == Toolkit::Visual::Property::MIX_COLOR || (mImpl->mType == Toolkit::Visual::COLOR && key.indexKey == ColorVisual::Property::MIX_COLOR) || (mImpl->mType == Toolkit::Visual::PRIMITIVE && key.indexKey == PrimitiveVisual::Property::MIX_COLOR)) + { + return Dali::Property(mImpl->mRenderer, mImpl->mMixColorIndex); + } + else if(key.indexKey == Toolkit::Visual::Property::OPACITY) + { + return Dali::Property(mImpl->mRenderer, DevelRenderer::Property::OPACITY); + } + } + else + { + if(key.stringKey == MIX_COLOR) + { + return Dali::Property(mImpl->mRenderer, mImpl->mMixColorIndex); + } + else if(key.stringKey == OPACITY) + { + return Dali::Property(mImpl->mRenderer, DevelRenderer::Property::OPACITY); + } + } + + // Other cases + Property::Index index = GetPropertyIndex(key); + if(index == Property::INVALID_INDEX) + { + if((key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::CORNER_RADIUS) || (key.type == Property::Key::STRING && key.stringKey == CORNER_RADIUS)) + { + // Register CORNER_RADIUS property + mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS, mImpl->mCornerRadius); + mImpl->mRenderer.RegisterProperty(CORNER_RADIUS_POLICY, mImpl->mCornerRadiusPolicy); + index = mImpl->mCornerRadiusIndex; + + mImpl->mNeedCornerRadius = true; + + // Change shader + UpdateShader(); + } + else + { + // We can't find the property in the base class. + // Request to child class + return OnGetPropertyObject(key); + } + } + + return Dali::Property(mImpl->mRenderer, index); +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/visuals/visual-base-impl.h b/dali-toolkit/internal/visuals/visual-base-impl.h index b925e46..8b0132e 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-impl.h @@ -203,12 +203,6 @@ public: void SetMixColor( const Vector3& color ); /** - * Gets the mix color of the visual. - * @return The mix color - */ - const Vector4& GetMixColor() const; - - /** * Animate the property if it exists in the visual or renderer. * * If it's a visual property such as mix color or a transform property, @@ -279,8 +273,15 @@ public: */ Toolkit::Visual::Type GetType() const; - protected: + /** + * @brief Retrieve the property object associated with the property key. + * + * @param[in] key The Property key of the visual. + * @return The Property object + */ + Dali::Property GetPropertyObject(Dali::Property::Key key); +protected: /** * @brief Constructor. * @@ -350,6 +351,25 @@ protected: */ virtual void OnDoAction( const Property::Index actionId, const Property::Value& attributes ); + /** + * @brief Update the shader when some properties are changed. + */ + virtual void UpdateShader() + { + } + + /** + * @brief Called by GetPropertyObject() allowing sub classes to respond to the GetPropertyObject event + * @note The derived class is required to register the given property. + * @param[in] key The key of the visual's property. + * @return The Property object + */ + virtual Dali::Property OnGetPropertyObject(Dali::Property::Key key) + { + Handle handle; + return Dali::Property(handle, Property::INVALID_INDEX); + } + protected: /** diff --git a/dali-toolkit/public-api/visuals/visual-properties.h b/dali-toolkit/public-api/visuals/visual-properties.h index be3aead..bea661d 100644 --- a/dali-toolkit/public-api/visuals/visual-properties.h +++ b/dali-toolkit/public-api/visuals/visual-properties.h @@ -107,15 +107,16 @@ enum /** * @brief Mix color is a blend color for any visual. - * @details Name "mixColor", type Property::VECTOR3 or Property::VECTOR4. + * @details Name "mixColor", type Property::VECTOR3 or Property::VECTOR4, animatable * @SINCE_1_2.60 * @note Optional + * @note To animate an opacity, OPACITY property should be used. */ MIX_COLOR, /** * @brief Opacity is the alpha component of the mixColor, above. - * @details Name "opacity", type Property::FLOAT. + * @details Name "opacity", type Property::FLOAT, animatable * @SINCE_1_2.60 * @note Optional */