From: joogab yun Date: Tue, 15 Jun 2021 05:35:22 +0000 (+0000) Subject: Merge "Add TOUCH_FOCUSABLE property" into devel/master X-Git-Tag: dali_2.0.31~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=6ae6f36998b3be4efa1114e2df856e51628bf812;hp=c14e39b4db65670dcc6c17f03a95035f364c80e5 Merge "Add TOUCH_FOCUSABLE property" into devel/master --- diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp index fdd8f10..808cc7a 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp @@ -937,3 +937,117 @@ int UtcDaliAccessibilitySignals(void) END_TEST; } + +static void Wait(ToolkitTestApplication& application) +{ + application.SendNotification(); + application.Render(16); +} + +int UtcDaliAccessibilityScrollToChildScrollView(void) +{ + ToolkitTestApplication application; + Dali::Accessibility::TestEnableSC( true ); + + ScrollView scrollView = ScrollView::New(); + application.GetScene().Add( scrollView ); + + PushButton actorA = PushButton::New(); + const Dali::Vector3 positionA = Vector3(100.0f, 400.0f, 0.0f); + actorA.SetProperty( Dali::Actor::Property::POSITION, positionA ); + scrollView.Add(actorA); + + PushButton actorB = PushButton::New(); + const Dali::Vector3 positionB = Vector3(500.0f, 200.0f, 0.0f); + actorB.SetProperty( Dali::Actor::Property::POSITION, positionB ); + scrollView.Add(actorB); + + Wait(application); + + auto* accessibleParent = dynamic_cast(Dali::Accessibility::Accessible::Get(scrollView)); + DALI_TEST_CHECK(accessibleParent); + auto* accessibleA = dynamic_cast(Dali::Accessibility::Accessible::Get(actorA)); + DALI_TEST_CHECK(accessibleA); + auto* accessibleB = dynamic_cast(Dali::Accessibility::Accessible::Get(actorB)); + DALI_TEST_CHECK(accessibleB); + + accessibleA->GrabHighlight(); // == scrollView.ScrollTo(actorA) + Wait(application); + accessibleB->GrabHighlight(); // == scrollView.ScrollTo(actorB) + Wait(application); + + Dali::Accessibility::TestEnableSC( false ); + END_TEST; +} + +namespace { + class TestItemFactory : public ItemFactory + { + public: + TestItemFactory() + { + } + + unsigned int GetNumberOfItems() override + { + return 2; + } + + Dali::Actor NewItem(unsigned int itemId) override + { + return TextLabel::New(std::to_string(itemId)); + } + }; +} + +int UtcDaliAccessibilityScrollToChildItemView(void) +{ + ToolkitTestApplication application; + Dali::Accessibility::TestEnableSC( true ); + + TestItemFactory factory; + ItemView view = ItemView::New(factory); + Dali::Vector3 vec(480.0f, 800.0f, 0.0f); + ItemLayoutPtr layout = DefaultItemLayout::New( DefaultItemLayout::DEPTH ); + + view.AddLayout(*layout); + view.SetProperty( Actor::Property::SIZE, vec ); + + application.GetScene().Add(view); + layout->SetOrientation(ControlOrientation::Down); + view.ActivateLayout(0, vec, 0.0f); + + Wait(application); + + auto* accessibleParent = dynamic_cast(Dali::Accessibility::Accessible::Get(view)); + DALI_TEST_CHECK(accessibleParent); + auto* accessibleA = dynamic_cast(Dali::Accessibility::Accessible::Get(view.GetItem(0))); + DALI_TEST_CHECK(accessibleA); + auto* accessibleB = dynamic_cast(Dali::Accessibility::Accessible::Get(view.GetItem(1))); + DALI_TEST_CHECK(accessibleB); + + accessibleA->GrabHighlight(); // == view.ScrollToItem(view.GetItemId(actorA)) + Wait(application); + accessibleB->GrabHighlight(); // == view.ScrollToItem(view.GetItemId(actorB)) + Wait(application); + + Dali::Accessibility::TestEnableSC( false ); + END_TEST; +} + +int UtcDaliAccessibilityScrollToChildNonScrollable(void) +{ + ToolkitTestApplication application; + Dali::Accessibility::TestEnableSC( true ); + + TextLabel label = TextLabel::New("123"); + + auto* accessible = dynamic_cast(Dali::Accessibility::Accessible::Get(label)); + DALI_TEST_CHECK(accessible); + + DALI_TEST_EQUALS(accessible->IsScrollable(), false, TEST_LOCATION); + DALI_TEST_EQUALS(accessible->ScrollToChild({}), false, TEST_LOCATION); + + Dali::Accessibility::TestEnableSC( false ); + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/CMakeLists.txt b/automated-tests/src/dali-toolkit/CMakeLists.txt index 2983fd7..2b73142 100755 --- a/automated-tests/src/dali-toolkit/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit/CMakeLists.txt @@ -44,6 +44,7 @@ SET(TC_SOURCES utc-Dali-TextureManager.cpp utc-Dali-ToolBar.cpp utc-Dali-Tooltip.cpp + utc-Dali-Transition.cpp utc-Dali-TransitionData.cpp utc-Dali-Button.cpp utc-Dali-CameraView.cpp diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp index 6d74b7c..56d67f4 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp @@ -77,7 +77,10 @@ int UtcDaliAnimatedImageVisualGetPropertyMap01(void) .Add( ImageVisual::Property::WRAP_MODE_U, WrapMode::REPEAT ) .Add( ImageVisual::Property::WRAP_MODE_V, WrapMode::DEFAULT ) .Add( DevelVisual::Property::CORNER_RADIUS, 22.2f ) - .Add( DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::ABSOLUTE )); + .Add( DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::ABSOLUTE ) + .Add( DevelVisual::Property::BORDERLINE_WIDTH, 33.3f ) + .Add( DevelVisual::Property::BORDERLINE_COLOR, Color::RED ) + .Add( DevelVisual::Property::BORDERLINE_OFFSET, 0.3f )); Property::Map resultMap; animatedImageVisual.CreatePropertyMap( resultMap ); @@ -98,6 +101,18 @@ int UtcDaliAnimatedImageVisualGetPropertyMap01(void) DALI_TEST_CHECK( value ); DALI_TEST_CHECK( value->Get() == Visual::Transform::Policy::ABSOLUTE ); + value = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 33.3f, TEST_LOCATION ); + + value = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), Color::RED, TEST_LOCATION ); + + value = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 0.3f, TEST_LOCATION ); + // request AnimatedImageVisual with an URL Visual::Base animatedImageVisual2 = factory.CreateVisual( TEST_GIF_FILE_NAME, ImageDimensions() ); resultMap.Clear(); @@ -137,7 +152,10 @@ int UtcDaliAnimatedImageVisualGetPropertyMap02(void) .Add( "wrapModeU", WrapMode::REPEAT ) .Add( "wrapModeV", WrapMode::DEFAULT ) .Add( "cornerRadius", Vector4(50.0f, 25.0f, 12.5f, 33.0f) ) - .Add( "cornerRadiusPolicy", Visual::Transform::Policy::RELATIVE )); + .Add( "cornerRadiusPolicy", Visual::Transform::Policy::RELATIVE ) + .Add( "borderlineWidth", 20.0f ) + .Add( "borderlineColor", Vector4() ) + .Add( "borderlineOffset", -1.0f)); Property::Map resultMap; animatedImageVisual.CreatePropertyMap( resultMap ); @@ -180,6 +198,18 @@ int UtcDaliAnimatedImageVisualGetPropertyMap02(void) DALI_TEST_CHECK( value ); DALI_TEST_CHECK( value->Get() == Visual::Transform::Policy::RELATIVE ); + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 20.0f, TEST_LOCATION ); + + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_COLOR, "borderlineColor" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), Vector4::ZERO, TEST_LOCATION ); + + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, "borderlineOffset" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), -1.0f, TEST_LOCATION ); + END_TEST; } @@ -248,6 +278,18 @@ int UtcDaliAnimatedImageVisualGetPropertyMap03(void) DALI_TEST_CHECK( value ); DALI_TEST_CHECK( value->Get() == Visual::Transform::Policy::ABSOLUTE ); + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 0.0f, TEST_LOCATION ); + + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_COLOR, "borderlineColor" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), Color::BLACK, TEST_LOCATION ); + + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, "borderlineOffset" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 0.0f, TEST_LOCATION ); + END_TEST; } @@ -264,7 +306,8 @@ int UtcDaliAnimatedImageVisualGetPropertyMap04(void) .Add( ImageVisual::Property::URL, TEST_GIF_FILE_NAME ) .Add( ImageVisual::Property::BATCH_SIZE, 1 ) .Add( ImageVisual::Property::CACHE_SIZE, 1 ) - .Add( ImageVisual::Property::SYNCHRONOUS_LOADING, false )); + .Add( ImageVisual::Property::SYNCHRONOUS_LOADING, false ) + .Add( DevelVisual::Property::BORDERLINE_WIDTH, 0.4f )); Property::Map resultMap; animatedImageVisual.CreatePropertyMap( resultMap ); @@ -290,6 +333,18 @@ int UtcDaliAnimatedImageVisualGetPropertyMap04(void) DALI_TEST_CHECK( value ); DALI_TEST_EQUALS( value->Get(), 4, TEST_LOCATION ); + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 0.4f, TEST_LOCATION ); + + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_COLOR, "borderlineColor" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), Vector4(0.0f, 0.0f, 0.0f, 1.0f), TEST_LOCATION ); + + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, "borderlineOffset" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 0.0f, TEST_LOCATION ); + END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp index 83c6a09..6159e71 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp @@ -145,7 +145,8 @@ int UtcDaliVisualFactoryGetAnimatedVectorImageVisual03(void) .Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME ) .Add( DevelImageVisual::Property::LOOP_COUNT, 3 ) .Add( DevelImageVisual::Property::PLAY_RANGE, playRange ) - .Add( DevelVisual::Property::CORNER_RADIUS, 50.0f ); + .Add( DevelVisual::Property::CORNER_RADIUS, 50.0f ) + .Add( DevelVisual::Property::BORDERLINE_WIDTH, 20.0f ); Visual::Base visual = VisualFactory::Get().CreateVisual( propertyMap ); DALI_TEST_CHECK( visual ); @@ -177,6 +178,9 @@ int UtcDaliVisualFactoryGetAnimatedVectorImageVisual04(void) int startFrame = 1, endFrame = 3; float cornerRadius = 22.0f; + float borderlineWidth = 2.0f; + Vector4 borderlineColor = Vector4(1.0f, 1.0f, 1.0f, 1.0f); + float borderlineOffset = 0.1f; Property::Array playRange; playRange.PushBack( startFrame ); playRange.PushBack( endFrame ); @@ -189,7 +193,10 @@ int UtcDaliVisualFactoryGetAnimatedVectorImageVisual04(void) .Add( "stopBehavior", DevelImageVisual::StopBehavior::FIRST_FRAME ) .Add( "loopingMode", DevelImageVisual::LoopingMode::AUTO_REVERSE ) .Add( "redrawInScalingDown", false ) - .Add( "cornerRadius", cornerRadius ); + .Add( "cornerRadius", cornerRadius ) + .Add( "borderlineWidth", borderlineWidth ) + .Add( "borderlineColor", borderlineColor ) + .Add( "borderlineOffset", borderlineOffset ); Visual::Base visual = VisualFactory::Get().CreateVisual( propertyMap ); DALI_TEST_CHECK( visual ); @@ -253,6 +260,18 @@ int UtcDaliVisualFactoryGetAnimatedVectorImageVisual04(void) DALI_TEST_CHECK( value ); DALI_TEST_CHECK( value->Get< int >() == Visual::Transform::Policy::ABSOLUTE ); + value = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get< float >(), borderlineWidth, TEST_LOCATION ); + + value = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get< Vector4 >(), borderlineColor, TEST_LOCATION ); + + value = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get< float >(), borderlineOffset, TEST_LOCATION ); + actor.Unparent( ); DALI_TEST_CHECK( actor.GetRendererCount() == 0u ); @@ -266,6 +285,9 @@ int UtcDaliAnimatedVectorImageVisualGetPropertyMap01(void) int startFrame = 1, endFrame = 3; Vector4 cornerRadius(50.0f, 22.0f, 0.0f, 3.0f); + float borderlineWidth = 2.3f; + Vector4 borderlineColor = Vector4(0.3f, 0.3f, 1.0f, 1.0f); + float borderlineOffset = 0.3f; Property::Array playRange; playRange.PushBack( startFrame ); playRange.PushBack( endFrame ); @@ -276,7 +298,10 @@ int UtcDaliAnimatedVectorImageVisualGetPropertyMap01(void) .Add( DevelImageVisual::Property::LOOP_COUNT, 3 ) .Add( DevelImageVisual::Property::PLAY_RANGE, playRange ) .Add( DevelVisual::Property::CORNER_RADIUS, cornerRadius ) - .Add( DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::RELATIVE); + .Add( DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::RELATIVE) + .Add( DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth ) + .Add( DevelVisual::Property::BORDERLINE_COLOR, borderlineColor ) + .Add( DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset ); // request AnimatedVectorImageVisual with a property map VisualFactory factory = VisualFactory::Get(); @@ -344,6 +369,18 @@ int UtcDaliAnimatedVectorImageVisualGetPropertyMap01(void) DALI_TEST_CHECK( value ); DALI_TEST_CHECK( value->Get< int >() == Visual::Transform::Policy::RELATIVE ); + value = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get< float >(), borderlineWidth, TEST_LOCATION ); + + value = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get< Vector4 >(), borderlineColor, TEST_LOCATION ); + + value = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get< float >(), borderlineOffset, TEST_LOCATION ); + // request AnimatedVectorImageVisual with an URL Visual::Base visual2 = factory.CreateVisual( TEST_VECTOR_IMAGE_FILE_NAME, ImageDimensions() ); @@ -1774,4 +1811,4 @@ int UtcDaliAnimatedVectorImageVisualPlaybackRiveFile(void) } END_TEST; -} \ No newline at end of file +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index fa48c76..675e2c7 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -3519,6 +3519,49 @@ int utcDaliTextEditorGetHeightForWidthDoesNotChangeLineCountLineWrapCharCase(voi END_TEST; } +int utcDaliTextEditorGetHeightForWidthChangeLineCountWhenTextChanged(void) +{ + ToolkitTestApplication application; + + tet_infoline(" utcDaliTextEditorGetHeightForWidthChangeLineCountWhenTextChanged "); + + int lineCountBefore =0 ; + int lineCountAfter =0 ; + + // Create a text editor + TextEditor textEditor = TextEditor::New(); + //Set very large font-size using point-size + textEditor.SetProperty( TextEditor::Property::POINT_SIZE, 10) ; + //Specify font-family + textEditor.SetProperty( TextEditor::Property::FONT_FAMILY, "DejaVu Sans"); + //Specify size + textEditor.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 100.f ) ); + //Set text longer than width of textEditor + textEditor.SetProperty( TextEditor::Property::TEXT, "Short text"); + //Set line wrap mode Character + textEditor.SetProperty(TextEditor::Property::LINE_WRAP_MODE, "CHARACTER"); + + application.GetScene().Add( textEditor ); + + application.SendNotification(); + application.Render(); + + + lineCountBefore = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + + textEditor.SetProperty( TextEditor::Property::TEXT, "This is very loooooooooooooooooooooooooooooooooooong text for test"); + lineCountAfter = textEditor.GetProperty( TextEditor::Property::LINE_COUNT ); + + // When the text changed, the Line-count should be updated according to new text. + // Because the GetHeightForWidth is called in Controller::GetLineCount(float width) + DALI_TEST_EQUALS( lineCountBefore ,1, TEST_LOCATION ); + DALI_TEST_GREATER( lineCountAfter,1, TEST_LOCATION ); + + + END_TEST; +} + + int utcDaliTextEditorGetNaturalSizeDoesNotChangeLineCountScrollingCase(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index ac7403b..9a187d6 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -1885,3 +1885,47 @@ int UtcDaliTextLabelHyphenWrapMode(void) END_TEST; } + + +int utcDaliTextLabelGetHeightForWidthChangeLineCountWhenTextChanged(void) +{ + ToolkitTestApplication application; + + tet_infoline(" utcDaliTextLabelGetHeightForWidthChangeLineCountWhenTextChanged "); + + int lineCountBefore =0 ; + int lineCountAfter =0 ; + + // Create a text editor + TextLabel textLabel = TextLabel::New(); + //Set very large font-size using point-size + textLabel.SetProperty( TextLabel::Property::POINT_SIZE, 10) ; + //Specify font-family + textLabel.SetProperty( TextLabel::Property::FONT_FAMILY, "DejaVu Sans"); + //Specify size + textLabel.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 100.f ) ); + //Set text longer than width of textLabel + textLabel.SetProperty( TextLabel::Property::TEXT, "Short text"); + //Set line wrap mode Character + textLabel.SetProperty(TextLabel::Property::LINE_WRAP_MODE, "CHARACTER"); + textLabel.SetProperty(TextLabel::Property::MULTI_LINE, true); + + application.GetScene().Add( textLabel ); + + application.SendNotification(); + application.Render(); + + + lineCountBefore = textLabel.GetProperty( TextLabel::Property::LINE_COUNT ); + + textLabel.SetProperty( TextLabel::Property::TEXT, "This is very loooooooooooooooooooooooooooooooooooong text for test"); + lineCountAfter = textLabel.GetProperty( TextLabel::Property::LINE_COUNT ); + + // When the text changed, the Line-count should be updated according to new text. + // Because the GetHeightForWidth is called in Controller::GetLineCount(float width) + DALI_TEST_EQUALS( lineCountBefore ,1, TEST_LOCATION ); + DALI_TEST_GREATER( lineCountAfter,1, TEST_LOCATION ); + + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp new file mode 100755 index 0000000..b694a69 --- /dev/null +++ b/automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp @@ -0,0 +1,929 @@ +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Toolkit; +namespace +{ + +const char* TEST_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/gallery-small-1.jpg"; + +} + +// Functor to test whether a Finish signal is emitted +struct TransitionFinishCheck +{ + TransitionFinishCheck(bool& signalReceived) + : mSignalReceived(signalReceived) + { + } + + void operator()(TransitionSet& transitionSet) + { + mSignalReceived = true; + } + + void Reset() + { + mSignalReceived = false; + } + + void CheckSignalReceived() + { + if(!mSignalReceived) + { + tet_printf("Expected Finish signal was not received\n"); + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } + } + + void CheckSignalNotReceived() + { + if(mSignalReceived) + { + tet_printf("Unexpected Finish signal was received\n"); + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } + } + + bool& mSignalReceived; // owned by individual tests +}; + +int UtcDaliTransitionSetGetProperty01(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionSetGetProperty01"); + + Control control1 = Control::New(); + control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + control1.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0)); + Property::Map controlProperty1; + controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 50.f); + control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1); + + Control control2 = Control::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::ANCHOR_POINT, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::POSITION, Vector3(50, 50, 0)); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f)); + controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 30.f); + control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2); + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + + application.SendNotification(); + application.Render(20); + + Transition transition = Transition::New(control1, control2, TimePeriod(-0.1f, -0.1f)); + TimePeriod timePeriod = transition.GetTimePeriod(); + DALI_TEST_EQUALS(0.0f, timePeriod.durationSeconds, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, timePeriod.delaySeconds, TEST_LOCATION); + + transition.SetTimePeriod(TimePeriod(0.5f, 1.0f)); + timePeriod = transition.GetTimePeriod(); + DALI_TEST_EQUALS(1.0f, timePeriod.durationSeconds, TEST_LOCATION); + DALI_TEST_EQUALS(0.5f, timePeriod.delaySeconds, TEST_LOCATION); + + DALI_TEST_EQUALS(Dali::AlphaFunction::DEFAULT, transition.GetAlphaFunction().GetBuiltinFunction(), TEST_LOCATION); + transition.SetAlphaFunction(Dali::AlphaFunction::EASE_IN_OUT); + DALI_TEST_EQUALS(Dali::AlphaFunction::EASE_IN_OUT, transition.GetAlphaFunction().GetBuiltinFunction(), TEST_LOCATION); + + TransitionSet transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + + DALI_TEST_EQUALS(1, transitionSet.GetTransitionCount(), TEST_LOCATION); + DALI_TEST_EQUALS(transition, transitionSet.GetTransitionAt(0), TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTransitionSetGetProperty02(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionSetGetProperty02"); + + Control control1 = Control::New(); + control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + control1.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0)); + Property::Map controlProperty1; + controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, Vector4(50.0f, 30.0f, 40.0f, 20.0f)); + control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1); + + Control control2 = Control::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::ANCHOR_POINT, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::POSITION, Vector3(50, 50, 0)); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f)); + controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, Vector4(32.f, 54.0f, 24.0f, 42.0f)); + control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2); + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + + application.SendNotification(); + application.Render(20); + + Transition transition = Transition::New(control1, control2, TimePeriod(-0.1f)); + TimePeriod timePeriod = transition.GetTimePeriod(); + DALI_TEST_EQUALS(0.0f, timePeriod.durationSeconds, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, timePeriod.delaySeconds, TEST_LOCATION); + + transition.SetTimePeriod(TimePeriod(0.5f, 1.0f)); + timePeriod = transition.GetTimePeriod(); + DALI_TEST_EQUALS(1.0f, timePeriod.durationSeconds, TEST_LOCATION); + DALI_TEST_EQUALS(0.5f, timePeriod.delaySeconds, TEST_LOCATION); + + DALI_TEST_EQUALS(Dali::AlphaFunction::DEFAULT, transition.GetAlphaFunction().GetBuiltinFunction(), TEST_LOCATION); + transition.SetAlphaFunction(Dali::AlphaFunction::EASE_IN_OUT); + DALI_TEST_EQUALS(Dali::AlphaFunction::EASE_IN_OUT, transition.GetAlphaFunction().GetBuiltinFunction(), TEST_LOCATION); + + TransitionSet transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + + DALI_TEST_EQUALS(1, transitionSet.GetTransitionCount(), TEST_LOCATION); + DALI_TEST_EQUALS(transition, transitionSet.GetTransitionAt(0), TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTransitionBetweenControlPair(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionBetweenControlPair"); + + Vector3 destinationPosition(50, 50, 0); + Vector3 destinationSize(120, 120, 0); + Vector3 destinationScale(2, 1, 0); + Vector4 destinationColor(1.0f, 0.5f, 1.0f, 0.8f); + float destinationOpacity(0.8f); + float destinationRadius(50.f); + Vector4 destinationRadiusV4 = Vector4(destinationRadius, destinationRadius, destinationRadius, destinationRadius); + + Control control1 = Control::New(); + control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + control1.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0)); + control1.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0)); + control1.SetProperty(Actor::Property::SCALE, Vector3(1, 2, 0)); + control1.SetProperty(Actor::Property::COLOR, Vector4(1.0f, 1.0f, 1.0f, 0.5f)); + control1.SetProperty(Actor::Property::OPACITY, 0.5f); + Property::Map controlProperty1; + controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 30.f); + control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1); + + Control control2 = Control::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::ANCHOR_POINT, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::POSITION, destinationPosition); + control2.SetProperty(Actor::Property::SIZE, destinationSize); + control2.SetProperty(Actor::Property::SCALE, destinationScale); + control2.SetProperty(Actor::Property::COLOR, destinationColor); + control2.SetProperty(Actor::Property::OPACITY, destinationOpacity); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f)); + controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, destinationRadius); + control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2); + + DALI_TEST_EQUALS(destinationPosition, control2.GetProperty(Actor::Property::POSITION), TEST_LOCATION); + Property::Map backgroundMap = control2.GetProperty(Toolkit::Control::Property::BACKGROUND); + Vector4 cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get(); + DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION); + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + + application.SendNotification(); + application.Render(20); + + Transition transition = Transition::New(control1, control2, TimePeriod(0.5f)); + TransitionSet transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + transitionSet.Play(); + + bool signalReceived(false); + TransitionFinishCheck finishCheck(signalReceived); + transitionSet.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(50); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + DALI_TEST_NOT_EQUALS(destinationPosition, control2.GetCurrentProperty(Actor::Property::POSITION), 0.00001f, TEST_LOCATION); + DALI_TEST_EQUALS(1, control2.GetRendererCount(), TEST_LOCATION); + Dali::Renderer renderer = control2.GetRendererAt(0); + Property::Index index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS); + cornerRadius = renderer.GetCurrentProperty(index); + DALI_TEST_NOT_EQUALS(destinationRadiusV4, cornerRadius, 0.00001f, TEST_LOCATION); + + application.SendNotification(); + application.Render(700); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + + application.SendNotification(); + application.Render(20); + + DALI_TEST_EQUALS(destinationPosition, control2.GetCurrentProperty(Actor::Property::POSITION), TEST_LOCATION); + DALI_TEST_EQUALS(destinationSize, control2.GetCurrentProperty(Actor::Property::SIZE), TEST_LOCATION); + DALI_TEST_EQUALS(destinationScale, control2.GetCurrentProperty(Actor::Property::SCALE), TEST_LOCATION); + DALI_TEST_EQUALS(destinationColor, control2.GetCurrentProperty(Actor::Property::COLOR), TEST_LOCATION); + DALI_TEST_EQUALS(destinationOpacity, control2.GetCurrentProperty(Actor::Property::OPACITY), TEST_LOCATION); + DALI_TEST_EQUALS(1, control2.GetRendererCount(), TEST_LOCATION); + renderer = control2.GetRendererAt(0); + index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS); + cornerRadius = renderer.GetCurrentProperty(index); + DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTransitionBetweenControlPairWithoutEmptySourceBackground(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionBetweenControlPair"); + + Vector4 destinationRadius(50.f, 30.f, 40.f, 0.f); + + Control control1 = Control::New(); + control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + control1.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0)); + + Control control2 = Control::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::ANCHOR_POINT, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::POSITION, Vector3(50, 50, 0)); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f)); + controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, destinationRadius); + control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2); + + Property::Map backgroundMap = control2.GetProperty(Toolkit::Control::Property::BACKGROUND); + Vector4 cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get(); + DALI_TEST_EQUALS(destinationRadius, cornerRadius, TEST_LOCATION); + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + + application.SendNotification(); + application.Render(20); + + Transition transition = Transition::New(control1, control2, TimePeriod(0.5f)); + TransitionSet transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + transitionSet.Play(); + + bool signalReceived(false); + TransitionFinishCheck finishCheck(signalReceived); + transitionSet.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(50); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + backgroundMap = control2.GetProperty(Toolkit::Control::Property::BACKGROUND); + cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get(); + DALI_TEST_EQUALS(destinationRadius, cornerRadius, TEST_LOCATION); + + application.SendNotification(); + application.Render(700); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + + application.SendNotification(); + application.Render(20); + + backgroundMap = control2.GetProperty(Toolkit::Control::Property::BACKGROUND); + cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get(); + DALI_TEST_EQUALS(destinationRadius, cornerRadius, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTransitionBetweenImageViewPair(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionBetweenControlPair"); + + Vector3 destinationPosition(50, 50, 0); + + ImageView control1 = ImageView::New(); + control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + control1.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0)); + control1.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0)); + Property::Map controlProperty1; + controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE); + controlProperty1.Insert(Toolkit::ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME); + controlProperty1.Insert(Toolkit::Visual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.5f, 0.5f)); + controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 50.f); + control1.SetProperty(Toolkit::ImageView::Property::IMAGE, controlProperty1); + + ImageView control2 = ImageView::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::ANCHOR_POINT, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::POSITION, destinationPosition); + control2.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE); + controlProperty2.Insert(Toolkit::ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME); + controlProperty2.Insert(Toolkit::Visual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); + controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 30.f); + control2.SetProperty(Toolkit::ImageView::Property::IMAGE, controlProperty2); + + DALI_TEST_EQUALS(destinationPosition, control2.GetProperty(Actor::Property::POSITION), TEST_LOCATION); + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + + application.SendNotification(); + application.Render(20); + + Vector3 startWorldPosition = control1.GetProperty(Actor::Property::WORLD_POSITION); + Vector3 finishWorldPosition = control2.GetProperty(Actor::Property::WORLD_POSITION); + + Transition transition = Transition::New(control1, control2, TimePeriod(0.5f)); + TransitionSet transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + transitionSet.Play(); + + bool signalReceived(false); + TransitionFinishCheck finishCheck(signalReceived); + transitionSet.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(400); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // control2 moved about 80% + Vector3 currentPosition = control2.GetCurrentProperty(Actor::Property::POSITION); + Vector3 expectedPosition_0_7 = startWorldPosition + (finishWorldPosition - startWorldPosition) * 0.7; + Vector3 expectedPosition_0_9 = startWorldPosition + (finishWorldPosition - startWorldPosition) * 0.9; + DALI_TEST_CHECK(currentPosition.x <= expectedPosition_0_7.x && currentPosition.x >= expectedPosition_0_9.x); + DALI_TEST_CHECK(currentPosition.y <= expectedPosition_0_7.y && currentPosition.y >= expectedPosition_0_9.y); + + application.SendNotification(); + application.Render(200); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + + DALI_TEST_NOT_EQUALS(destinationPosition, control2.GetCurrentProperty(Actor::Property::POSITION), 0.00001f, TEST_LOCATION); + + application.SendNotification(); + application.Render(20); + + DALI_TEST_EQUALS(destinationPosition, control2.GetCurrentProperty(Actor::Property::POSITION), TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTransitionBetweenImageViewPairWithDelay(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionBetweenControlPair"); + + Vector3 destinationPosition(50, 50, 0); + + ImageView control1 = ImageView::New(); + control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + control1.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0)); + control1.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0)); + Property::Map controlProperty1; + controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE); + controlProperty1.Insert(Toolkit::ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME); + controlProperty1.Insert(Toolkit::Visual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.5f, 0.5f)); + controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 50.f); + control1.SetProperty(Toolkit::ImageView::Property::IMAGE, controlProperty1); + + ImageView control2 = ImageView::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::ANCHOR_POINT, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::POSITION, destinationPosition); + control2.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE); + controlProperty2.Insert(Toolkit::ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME); + controlProperty2.Insert(Toolkit::Visual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); + controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 30.f); + control2.SetProperty(Toolkit::ImageView::Property::IMAGE, controlProperty2); + + DALI_TEST_EQUALS(destinationPosition, control2.GetProperty(Actor::Property::POSITION), TEST_LOCATION); + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + + application.SendNotification(); + application.Render(20); + + Vector3 startWorldPosition = control1.GetProperty(Actor::Property::WORLD_POSITION); + Vector3 finishWorldPosition = control2.GetProperty(Actor::Property::WORLD_POSITION); + + Transition transition = Transition::New(control1, control2, TimePeriod(0.5f, 0.5f)); + TransitionSet transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + transitionSet.Play(); + + bool signalReceived(false); + TransitionFinishCheck finishCheck(signalReceived); + transitionSet.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(400); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + DALI_TEST_EQUALS(startWorldPosition, control2.GetCurrentProperty(Actor::Property::POSITION), TEST_LOCATION); + + + application.SendNotification(); + application.Render(400); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // control2 moved about 60% (800ms) + Vector3 currentPosition = control2.GetCurrentProperty(Actor::Property::POSITION); + Vector3 expectedPosition_0_5 = startWorldPosition + (finishWorldPosition - startWorldPosition) * 0.5; + Vector3 expectedPosition_0_7 = startWorldPosition + (finishWorldPosition - startWorldPosition) * 0.7; + DALI_TEST_CHECK(currentPosition.x <= expectedPosition_0_5.x && currentPosition.x >= expectedPosition_0_7.x); + DALI_TEST_CHECK(currentPosition.y <= expectedPosition_0_5.y && currentPosition.y >= expectedPosition_0_7.y); + + application.SendNotification(); + application.Render(400); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + + DALI_TEST_NOT_EQUALS(destinationPosition, control2.GetCurrentProperty(Actor::Property::POSITION), 0.00001f, TEST_LOCATION); + + application.SendNotification(); + application.Render(20); + + DALI_TEST_EQUALS(destinationPosition, control2.GetCurrentProperty(Actor::Property::POSITION), TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTransitionBetweenControlPairWithTree(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionBetweenControlPairWithTree"); + + Vector3 destinationPosition(50, 50, 0); + Vector3 destinationWorldPosition(-130, -290, 0); + + Control control1 = Control::New(); + control1.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0)); + control1.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0)); + Property::Map controlProperty1; + controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1); + + Control control2 = Control::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + control2.SetProperty(Actor::Property::POSITION, destinationPosition); + control2.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2); + + Control control3 = Control::New(); + control3.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control3.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control3.SetProperty(Actor::Property::POSITION, Vector3(50, 50, 0)); + control3.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty3; + controlProperty3.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty3.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control3.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty3); + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + control2.Add(control3); + + application.SendNotification(); + application.Render(20); + + Transition transition = Transition::New(control1, control2, TimePeriod(0.5f)); + TransitionSet transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + transitionSet.Play(); + + bool signalReceived(false); + TransitionFinishCheck finishCheck(signalReceived); + transitionSet.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(600); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalReceived(); + + application.SendNotification(); + application.Render(20); + + DALI_TEST_EQUALS(destinationPosition, control2.GetCurrentProperty(Actor::Property::POSITION), TEST_LOCATION); + DALI_TEST_EQUALS(destinationWorldPosition, control2.GetProperty(Actor::Property::WORLD_POSITION), TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTransitionBetweenControlPairWithTreeWithChild(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionBetweenControlPairWithTreeWithChild"); + + Vector3 destinationWorldPosition(-80, -240, 0); + + Control control1 = Control::New(); + control1.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0)); + control1.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0)); + Property::Map controlProperty1; + controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1); + + Control control2 = Control::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + control2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + control2.SetProperty(Actor::Property::POSITION, Vector3(50, 50, 0)); + control2.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2); + + Control control3 = Control::New(); + control3.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control3.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control3.SetProperty(Actor::Property::POSITION, Vector3(50, 50, 0)); + control3.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty3; + controlProperty3.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty3.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control3.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty3); + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + control2.Add(control3); + + application.SendNotification(); + application.Render(20); + + Transition transition = Transition::New(control1, control2, TimePeriod(0.5f)); + transition.TransitionWithChild(true); + TransitionSet transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + transitionSet.Play(); + + bool signalReceived(false); + TransitionFinishCheck finishCheck(signalReceived); + transitionSet.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(600); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalReceived(); + + application.SendNotification(); + application.Render(20); + + DALI_TEST_EQUALS(destinationWorldPosition, control3.GetProperty(Actor::Property::WORLD_POSITION), TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTransitionBetweenControlPairWithTreeWithoutPositionInheritance(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionBetweenControlPairWithTreeWithoutPositionInheritance"); + + Vector3 sourcePosition(50, 50, 0); + Vector3 destinationPosition(100, 100, 0); + + Control control1 = Control::New(); + control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control1.SetProperty(Actor::Property::POSITION, sourcePosition); + control1.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0)); + Property::Map controlProperty1; + controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1); + + Control control2 = Control::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control2.SetProperty(Actor::Property::POSITION, Vector3(150, 150, 0)); + control2.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2); + + Control control3 = Control::New(); + control3.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control3.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control3.SetProperty(Actor::Property::POSITION, destinationPosition); + control3.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty3; + controlProperty3.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty3.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control3.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty3); + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + control2.Add(control3); + + application.SendNotification(); + application.Render(20); + + Transition transition; + TransitionSet transitionSet; + bool signalReceived(false); + TransitionFinishCheck finishCheck(signalReceived); + + // not inherit Position. + control3.SetProperty(Actor::Property::INHERIT_POSITION, false); + control3.SetProperty(Actor::Property::INHERIT_ORIENTATION, true); + control3.SetProperty(Actor::Property::INHERIT_SCALE, true); + + transition = Transition::New(control1, control3, TimePeriod(0.5f)); + transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + transitionSet.Play(); + transitionSet.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(300); + + Vector3 currentPosition = control3.GetProperty(Actor::Property::WORLD_POSITION); + DALI_TEST_CHECK(currentPosition.x <= destinationPosition.x && currentPosition.x >= sourcePosition.x); + DALI_TEST_CHECK(currentPosition.y <= destinationPosition.y && currentPosition.y >= sourcePosition.y); + DALI_TEST_CHECK(currentPosition.z <= destinationPosition.z && currentPosition.z >= sourcePosition.z); + + application.SendNotification(); + application.Render(300); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalReceived(); + + application.SendNotification(); + application.Render(20); + + DALI_TEST_EQUALS(destinationPosition, control3.GetProperty(Actor::Property::WORLD_POSITION), TEST_LOCATION); + END_TEST; +} + +int UtcDaliTransitionBetweenControlPairWithTreeWithoutOrientationInheritance(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionBetweenControlPairWithTreeWithoutOrientationInheritance"); + + Radian sourceAngle(1.0f); + Radian destinationAngle(2.0f); + Quaternion sourceOrientation(sourceAngle, Vector3::XAXIS); + Quaternion destinationOrientation(destinationAngle, Vector3::XAXIS); + + Control control1 = Control::New(); + control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control1.SetProperty(Actor::Property::ORIENTATION, sourceOrientation); + control1.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0)); + Property::Map controlProperty1; + controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1); + + Control control2 = Control::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control2.SetProperty(Actor::Property::ORIENTATION, Quaternion(Radian(2.0f), Vector3::XAXIS)); + control2.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2); + + Control control3 = Control::New(); + control3.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control3.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control3.SetProperty(Actor::Property::ORIENTATION, destinationOrientation); + control3.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty3; + controlProperty3.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty3.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control3.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty3); + + // not inherit Orientation. + control3.SetProperty(Actor::Property::INHERIT_POSITION, true); + control3.SetProperty(Actor::Property::INHERIT_ORIENTATION, false); + control3.SetProperty(Actor::Property::INHERIT_SCALE, true); + + Vector3 currentAxis; + Radian currentRadian; + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + control2.Add(control3); + + application.SendNotification(); + application.Render(20); + + Quaternion currentOrientation = control3.GetProperty(Actor::Property::WORLD_ORIENTATION); + DALI_TEST_EQUALS(currentOrientation, destinationOrientation, 0.0001f, TEST_LOCATION); + + Transition transition; + TransitionSet transitionSet; + bool signalReceived(false); + TransitionFinishCheck finishCheck(signalReceived); + + transition = Transition::New(control1, control3, TimePeriod(0.5f)); + transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + transitionSet.Play(); + transitionSet.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(300); + + currentOrientation = control3.GetProperty(Actor::Property::WORLD_ORIENTATION); + DALI_TEST_NOT_EQUALS(currentOrientation, destinationOrientation, 0.0001f, TEST_LOCATION); + + application.SendNotification(); + application.Render(300); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalReceived(); + + application.SendNotification(); + application.Render(20); + + currentOrientation = control3.GetProperty(Actor::Property::WORLD_ORIENTATION); + DALI_TEST_EQUALS(currentOrientation, destinationOrientation, 0.0001f, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliTransitionBetweenControlPairWithTreeWithoutScaleInheritance(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTransitionBetweenControlPairWithTreeWithoutOrientationInheritance"); + + Vector3 sourceScale(1, 1, 1); + Vector3 destinationScale(2, 2, 1); + + Control control1 = Control::New(); + control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control1.SetProperty(Actor::Property::SCALE, sourceScale); + control1.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0)); + Property::Map controlProperty1; + controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1); + + Control control2 = Control::New(); + control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control2.SetProperty(Actor::Property::SCALE, Vector3(3, 3, 1)); + control2.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty2; + controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2); + + Control control3 = Control::New(); + control3.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control3.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + control3.SetProperty(Actor::Property::SCALE, destinationScale); + control3.SetProperty(Actor::Property::SIZE, Vector3(120, 120, 0)); + Property::Map controlProperty3; + controlProperty3.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + controlProperty3.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + control3.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty3); + + // not inherit Orientation. + control3.SetProperty(Actor::Property::INHERIT_POSITION, true); + control3.SetProperty(Actor::Property::INHERIT_ORIENTATION, true); + control3.SetProperty(Actor::Property::INHERIT_SCALE, false); + + application.GetScene().Add(control1); + application.GetScene().Add(control2); + control2.Add(control3); + + application.SendNotification(); + application.Render(20); + + Vector3 currentScale = control3.GetProperty(Actor::Property::WORLD_SCALE); + DALI_TEST_EQUALS(currentScale, destinationScale, 0.0001f, TEST_LOCATION); + + Transition transition; + TransitionSet transitionSet; + bool signalReceived(false); + TransitionFinishCheck finishCheck(signalReceived); + + transition = Transition::New(control1, control3, TimePeriod(0.5f)); + transitionSet = TransitionSet::New(); + transitionSet.AddTransition(transition); + transitionSet.Play(); + transitionSet.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(300); + + currentScale = control3.GetProperty(Actor::Property::WORLD_SCALE); + DALI_TEST_CHECK(currentScale.x <= destinationScale.x && currentScale.x >= sourceScale.x); + DALI_TEST_CHECK(currentScale.y <= destinationScale.y && currentScale.y >= sourceScale.y); + DALI_TEST_CHECK(currentScale.z <= destinationScale.z && currentScale.z >= sourceScale.z); + + application.SendNotification(); + application.Render(300); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalReceived(); + + application.SendNotification(); + application.Render(20); + + currentScale = control3.GetProperty(Actor::Property::WORLD_SCALE); + DALI_TEST_EQUALS(currentScale, destinationScale, 0.0001f, TEST_LOCATION); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index a0f5334..5864554 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -502,6 +502,9 @@ int UtcDaliVisualGetPropertyMap1(void) 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( DevelVisual::Property::BORDERLINE_WIDTH, 20.0f ); + propertyMap.Insert( DevelVisual::Property::BORDERLINE_COLOR, Color::RED ); + propertyMap.Insert( DevelVisual::Property::BORDERLINE_OFFSET, -1.0f ); propertyMap.Insert( DevelColorVisual::Property::BLUR_RADIUS, 20.0f ); Visual::Base colorVisual = factory.CreateVisual( propertyMap ); @@ -524,6 +527,18 @@ int UtcDaliVisualGetPropertyMap1(void) DALI_TEST_CHECK( cornerRadiusPolicyValue ); DALI_TEST_CHECK( cornerRadiusPolicyValue->Get< int >() == Toolkit::Visual::Transform::Policy::RELATIVE ); + Property::Value* borderlineWidthValue = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT ); + DALI_TEST_CHECK( borderlineWidthValue ); + DALI_TEST_CHECK( borderlineWidthValue->Get< float >() == 20.0f ); + + Property::Value* borderlineColorValue = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 ); + DALI_TEST_CHECK( borderlineColorValue ); + DALI_TEST_CHECK( borderlineColorValue->Get< Vector4 >() == Color::RED ); + + Property::Value* borderlineOffsetValue = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT ); + DALI_TEST_CHECK( borderlineOffsetValue ); + DALI_TEST_CHECK( borderlineOffsetValue->Get< float >() == -1.0f ); + Property::Value* blurRadiusValue = resultMap.Find( DevelColorVisual::Property::BLUR_RADIUS, Property::FLOAT ); DALI_TEST_CHECK( blurRadiusValue ); DALI_TEST_CHECK( blurRadiusValue->Get< float >() == 20.0f ); @@ -599,10 +614,23 @@ int UtcDaliVisualGetPropertyMap2(void) DALI_TEST_CHECK( colorValue ); DALI_TEST_CHECK( colorValue->Get() == Color::CYAN ); - colorValue = resultMap.Find( BorderVisual::Property::SIZE, Property::FLOAT ); + sizeValue = resultMap.Find( BorderVisual::Property::SIZE, Property::FLOAT ); + DALI_TEST_CHECK( sizeValue ); + DALI_TEST_CHECK( sizeValue->Get() == 10.f ); + + // Get default value of borderline values here + + sizeValue = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT ); + DALI_TEST_CHECK( sizeValue ); + DALI_TEST_CHECK( sizeValue->Get() == 0.0f ); + + colorValue = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 ); DALI_TEST_CHECK( colorValue ); - DALI_TEST_CHECK( colorValue->Get() == 10.f ); + DALI_TEST_CHECK( colorValue->Get() == Color::BLACK ); + sizeValue = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT ); + DALI_TEST_CHECK( sizeValue ); + DALI_TEST_CHECK( sizeValue->Get() == 0.0f ); END_TEST; } @@ -655,6 +683,11 @@ int UtcDaliVisualGetPropertyMap3(void) stopColors.PushBack( Color::GREEN ); propertyMap.Insert(GradientVisual::Property::STOP_COLOR, stopColors); + float borderlineWidth = 4.0f; + Vector4 cornerRadius(7.0f, 10.0f, 13.0f, 16.0f); + propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth); + propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS, cornerRadius); + Visual::Base gradientVisual = factory.CreateVisual(propertyMap); Property::Map resultMap; @@ -681,6 +714,14 @@ int UtcDaliVisualGetPropertyMap3(void) DALI_TEST_CHECK( value ); DALI_TEST_EQUALS( value->Get(), end , Math::MACHINE_EPSILON_100, TEST_LOCATION ); + value = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), borderlineWidth , Math::MACHINE_EPSILON_100, TEST_LOCATION ); + + value = resultMap.Find( DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4 ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), cornerRadius , Math::MACHINE_EPSILON_100, TEST_LOCATION ); + value = resultMap.Find( GradientVisual::Property::STOP_OFFSET, Property::ARRAY ); DALI_TEST_CHECK( value ); Property::Array* offsetArray = value->GetArray(); @@ -722,6 +763,11 @@ int UtcDaliVisualGetPropertyMap4(void) stopColors.PushBack( Color::GREEN ); propertyMap.Insert(GradientVisual::Property::STOP_COLOR, stopColors); + float borderlineWidth = 8.0f; + Vector4 cornerRadius(1.0f, 2.0f, 4.0f, 8.0f); + propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth); + propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS, cornerRadius); + Visual::Base gradientVisual = factory.CreateVisual(propertyMap); DALI_TEST_CHECK( gradientVisual ); @@ -749,6 +795,14 @@ int UtcDaliVisualGetPropertyMap4(void) DALI_TEST_CHECK( value ); DALI_TEST_EQUALS( value->Get(), radius , Math::MACHINE_EPSILON_100, TEST_LOCATION ); + value = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), borderlineWidth , Math::MACHINE_EPSILON_100, TEST_LOCATION ); + + value = resultMap.Find( DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4 ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), cornerRadius , Math::MACHINE_EPSILON_100, TEST_LOCATION ); + value = resultMap.Find( GradientVisual::Property::STOP_OFFSET, Property::ARRAY ); DALI_TEST_CHECK( value ); Property::Array* offsetArray = value->GetArray(); @@ -3910,6 +3964,361 @@ int UtcDaliVisualRoundedCorner(void) END_TEST; } +int UtcDaliVisualBorderline(void) +{ +#ifdef OLD_GRAPHICS_TEST + ToolkitTestApplication application; + tet_infoline( "UtcDaliVisualBorderline" ); + + static std::vector customUniforms = + { + UniformData("cornerRadius", Property::Type::VECTOR4), + UniformData("cornerRadiusPolicy", Property::Type::FLOAT), + UniformData("borderlineWidth", Property::Type::FLOAT), + UniformData("borderlineColor", Property::Type::VECTOR4), + UniformData("borderlineOffset", Property::Type::FLOAT), + }; + + TestGraphicsController& graphics = application.GetGraphicsController(); + graphics.AddCustomUniforms(customUniforms); + + // image visual + { + VisualFactory factory = VisualFactory::Get(); + Property::Map properties; + float cornerRadius = 5.0f; + float borderlineWidth = 30.0f; + Vector4 borderlineColor(1.0f, 0.0f, 0.0f, 1.0f); + float borderlineOffset = 1.0f; + + properties[Visual::Property::TYPE] = Visual::IMAGE; + properties[ImageVisual::Property::URL] = TEST_IMAGE_FILE_NAME; + properties[DevelVisual::Property::CORNER_RADIUS] = cornerRadius; + properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth; + properties[DevelVisual::Property::BORDERLINE_COLOR] = borderlineColor; + properties[DevelVisual::Property::BORDERLINE_OFFSET] = borderlineOffset; + + Visual::Base visual = factory.CreateVisual( properties ); + + // trigger creation through setting on stage + DummyControl dummy = DummyControl::New( true ); + Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) ); + dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + application.GetScene().Add( dummy ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "cornerRadius", Vector4(cornerRadius, cornerRadius, cornerRadius, cornerRadius) ), true, TEST_LOCATION ); + // Default corner radius policy is absolute. + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "cornerRadiusPolicy", Toolkit::Visual::Transform::Policy::ABSOLUTE ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", borderlineColor ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", borderlineOffset ), true, TEST_LOCATION ); + } + + // color visual 1 + { + VisualFactory factory = VisualFactory::Get(); + Property::Map properties; + Vector4 cornerRadius(23.0f, 2.0f, 3.0f, 2.3f); + float borderlineWidth = 30.0f; + Vector4 borderlineColor(0.5f, 0.4f, 0.3f, 0.2f); + float borderlineOffset = -0.4f; + + properties[Visual::Property::TYPE] = Visual::COLOR; + properties[ColorVisual::Property::MIX_COLOR] = Color::BLUE; + properties["cornerRadius"] = cornerRadius; + properties["borderlineWidth"] = borderlineWidth; + properties["borderlineColor"] = borderlineColor; + properties["borderlineOffset"] = borderlineOffset; + + Visual::Base visual = factory.CreateVisual( properties ); + + // trigger creation through setting on stage + DummyControl dummy = DummyControl::New( true ); + Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) ); + dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + application.GetScene().Add( dummy ); + + application.SendNotification(); + application.Render(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "cornerRadius", cornerRadius ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", borderlineColor ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", borderlineOffset ), true, TEST_LOCATION ); + } + + // color visual 2, default color, default offset + { + VisualFactory factory = VisualFactory::Get(); + Property::Map properties; + float borderlineWidth = 30.0f; + + properties[Visual::Property::TYPE] = Visual::COLOR; + properties[ColorVisual::Property::MIX_COLOR] = Color::BLUE; + properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth; + + Visual::Base visual = factory.CreateVisual( properties ); + + // trigger creation through setting on stage + DummyControl dummy = DummyControl::New( true ); + Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) ); + dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + application.GetScene().Add( dummy ); + + application.SendNotification(); + application.Render(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION ); + // Default borderline color is BLACK. + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", Color::BLACK ), true, TEST_LOCATION ); + // Default borderline offset is 0.0f. + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", 0.0f ), true, TEST_LOCATION ); + } + + // color visual 3, offset not [-1.0 ~ 1.0], but uniform value is same anyway + { + VisualFactory factory = VisualFactory::Get(); + Property::Map properties; + float borderlineWidth = 30.0f; + Vector4 borderlineColor(0.5f, 0.4f, 0.3f, 0.2f); + float borderlineOffset = 37.4f; + + properties[Visual::Property::TYPE] = Visual::COLOR; + properties[ColorVisual::Property::MIX_COLOR] = Color::BLUE; + properties["borderlineWidth"] = borderlineWidth; + properties["borderlineColor"] = borderlineColor; + properties["borderlineOffset"] = borderlineOffset; + + Visual::Base visual = factory.CreateVisual( properties ); + + // trigger creation through setting on stage + DummyControl dummy = DummyControl::New( true ); + Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) ); + dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + application.GetScene().Add( dummy ); + + application.SendNotification(); + application.Render(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", borderlineColor ), true, TEST_LOCATION ); + // NOTE : borderlineOffset will clamp in fragment shader. not visual itself + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", borderlineOffset ), true, TEST_LOCATION ); + } + + // gradient visual + { + VisualFactory factory = VisualFactory::Get(); + Property::Map properties; + float borderlineWidth = 30.0f; + float cornerRadius = 70.0f; + + properties[Visual::Property::TYPE] = Visual::GRADIENT; + properties[ColorVisual::Property::MIX_COLOR] = Color::BLUE; + properties[DevelVisual::Property::CORNER_RADIUS] = cornerRadius; + properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth; + properties[GradientVisual::Property::START_POSITION] = Vector2( 0.5f, 0.5f ); + properties[GradientVisual::Property::END_POSITION] = Vector2( -0.5f, -0.5f ); + properties[GradientVisual::Property::UNITS] = GradientVisual::Units::USER_SPACE; + + Property::Array stopOffsets; + stopOffsets.PushBack( 0.0f ); + stopOffsets.PushBack( 0.6f ); + stopOffsets.PushBack( 1.0f ); + properties[GradientVisual::Property::STOP_OFFSET] = stopOffsets; + + Property::Array stopColors; + stopColors.PushBack( Color::RED ); + stopColors.PushBack( Color::YELLOW ); + stopColors.PushBack( Color::GREEN ); + properties[GradientVisual::Property::STOP_COLOR] = stopColors; + + Visual::Base visual = factory.CreateVisual( properties ); + + // trigger creation through setting on stage + DummyControl dummy = DummyControl::New( true ); + Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) ); + dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + application.GetScene().Add( dummy ); + + application.SendNotification(); + application.Render(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "cornerRadius", Vector4(cornerRadius, cornerRadius, cornerRadius, cornerRadius) ), true, TEST_LOCATION ); + // Default corner radius policy is absolute. + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "cornerRadiusPolicy", Toolkit::Visual::Transform::Policy::ABSOLUTE ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION ); + // Default borderline color is BLACK. + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", Color::BLACK ), true, TEST_LOCATION ); + // Default borderline offset is 0.0f. + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", 0.0f ), true, TEST_LOCATION ); + } + + // animated image visual + { + VisualFactory factory = VisualFactory::Get(); + Property::Map properties; + float borderlineWidth = 24.0f; + float borderlineOffset = -1.0f; + + properties[Visual::Property::TYPE] = Visual::ANIMATED_IMAGE; + properties[ImageVisual::Property::URL] = TEST_GIF_FILE_NAME; + properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth + 10.0f; // Dummy Input + properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth; + properties["borderlineOffset"] = borderlineOffset; + + Visual::Base visual = factory.CreateVisual( properties ); + + // trigger creation through setting on stage + DummyControl dummy = DummyControl::New( true ); + Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) ); + dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + application.GetScene().Add( dummy ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION ); + // Default borderline color is BLACK. + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", Color::BLACK ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", borderlineOffset ), true, TEST_LOCATION ); + } + + // vector image visual + { + VisualFactory factory = VisualFactory::Get(); + Property::Map properties; + Vector4 cornerRadius(54.0f, 43.0f, 32.0f, 21.0f); + float borderlineWidth = 27.0f; + Vector4 borderlineColor(0.5f, 0.5f, 0.5f, 0.0f); + + properties[Visual::Property::TYPE] = Visual::SVG; + properties[ImageVisual::Property::URL] = TEST_SVG_FILE_NAME; + properties[DevelVisual::Property::CORNER_RADIUS] = cornerRadius; + properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth; + properties[DevelVisual::Property::BORDERLINE_COLOR] = borderlineColor; + + Visual::Base visual = factory.CreateVisual( properties ); + + // trigger creation through setting on stage + DummyControl dummy = DummyControl::New( true ); + Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) ); + dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + application.GetScene().Add( dummy ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "cornerRadius", cornerRadius ), true, TEST_LOCATION ); + // Default corner radius policy is absolute. + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "cornerRadiusPolicy", Toolkit::Visual::Transform::Policy::ABSOLUTE ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", borderlineColor ), true, TEST_LOCATION ); + // Default borderline offset is 0.0. + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", 0.0f ), true, TEST_LOCATION ); + } + + // animated vector image visual + { + VisualFactory factory = VisualFactory::Get(); + Property::Map properties; + Vector4 cornerRadius(1.3f, 0.0f, 0.4f, 0.2f); + float borderlineWidth = 13.0f; + Vector4 borderlineColor(0.3f, 0.3f, 0.3f, 1.0f); + float borderlineOffset = 13.0f; + + properties[Visual::Property::TYPE] = DevelVisual::ANIMATED_VECTOR_IMAGE; + properties[ImageVisual::Property::URL] = TEST_VECTOR_IMAGE_FILE_NAME; + properties["cornerRadius"] = cornerRadius; + properties[DevelVisual::Property::CORNER_RADIUS_POLICY] = Toolkit::Visual::Transform::Policy::RELATIVE; + properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth; + properties["borderlineColor"] = borderlineColor; + properties[DevelVisual::Property::BORDERLINE_OFFSET] = borderlineOffset; + + Visual::Base visual = factory.CreateVisual( properties ); + + // trigger creation through setting on stage + DummyControl dummy = DummyControl::New( true ); + Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) ); + dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + application.GetScene().Add( dummy ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "cornerRadius", cornerRadius ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "cornerRadiusPolicy", Toolkit::Visual::Transform::Policy::RELATIVE ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", borderlineColor ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", borderlineOffset ), true, TEST_LOCATION ); + } +#else + tet_result(TET_PASS); +#endif + + END_TEST; +} + + int UtcDaliColorVisualBlurRadius(void) { ToolkitTestApplication application; @@ -4101,6 +4510,9 @@ int UtcDaliVisualGetVisualProperty01(void) UniformData("size", Property::Type::VECTOR2), UniformData("cornerRadius", Property::Type::VECTOR4), UniformData("blurRadius", Property::Type::FLOAT), + UniformData("borderlineWidth", Property::Type::FLOAT), + UniformData("borderlineColor", Property::Type::VECTOR4), + UniformData("borderlineOffset", Property::Type::FLOAT), }; TestGraphicsController& graphics = application.GetGraphicsController(); @@ -4113,6 +4525,9 @@ int UtcDaliVisualGetVisualProperty01(void) propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS, Vector4(10.0f, 0.0f, 2.0f, 4.0f)); propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS_POLICY, Toolkit::Visual::Transform::Policy::RELATIVE); propertyMap.Insert(DevelColorVisual::Property::BLUR_RADIUS, 20.0f); + propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 20.0f); + propertyMap.Insert(DevelVisual::Property::BORDERLINE_COLOR, Color::RED); + propertyMap.Insert(DevelVisual::Property::BORDERLINE_OFFSET, 1.0f); Visual::Base colorVisual = factory.CreateVisual(propertyMap); DummyControl dummyControl = DummyControl::New(true); @@ -4130,6 +4545,9 @@ int UtcDaliVisualGetVisualProperty01(void) float targetOpacity = 0.5f; Vector4 targetCornerRadius(0.0f, 0.0f, 0.0f, 0.0f); float targetBlurRadius = 10.0f; + float targetBorderlineWidth = 25.0f; + Vector4 targetBorderlineColor(1.0f, 1.0f, 1.0f, 1.0f); + float targetBorderlineOffset = -1.0f; Animation animation = Animation::New(1.0f); animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::MIX_COLOR), targetColor); @@ -4138,6 +4556,9 @@ int UtcDaliVisualGetVisualProperty01(void) animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Transform::Property::SIZE), targetSize); 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.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_WIDTH), targetBorderlineWidth); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_COLOR), targetBorderlineColor); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_OFFSET), targetBorderlineOffset); animation.Play(); application.SendNotification(); @@ -4172,12 +4593,27 @@ int UtcDaliVisualGetVisualProperty01(void) DALI_TEST_CHECK(blurRadiusValue); DALI_TEST_EQUALS(blurRadiusValue->Get< float >(), targetBlurRadius, TEST_LOCATION); + Property::Value* borderlineWidthValue = resultMap.Find(DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT); + DALI_TEST_CHECK(borderlineWidthValue); + DALI_TEST_EQUALS(borderlineWidthValue->Get< float >(), targetBorderlineWidth, TEST_LOCATION); + + Property::Value* borderlineColorValue = resultMap.Find(DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4); + DALI_TEST_CHECK(borderlineColorValue); + DALI_TEST_EQUALS(borderlineColorValue->Get< Vector4 >(), targetBorderlineColor, TEST_LOCATION); + + Property::Value* borderlineOffsetValue = resultMap.Find(DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT); + DALI_TEST_CHECK(borderlineOffsetValue); + DALI_TEST_EQUALS(borderlineOffsetValue->Get< float >(), targetBorderlineOffset, TEST_LOCATION); + // Test uniform values DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("mixColor", targetColor), true, TEST_LOCATION); DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("offset", targetOffset), true, TEST_LOCATION); DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("size", targetSize), 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); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineWidth", targetBorderlineWidth), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineColor", targetBorderlineColor), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineOffset", targetBorderlineOffset), true, TEST_LOCATION); // Test not-supported property Property property1 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::PREMULTIPLIED_ALPHA); @@ -4203,6 +4639,9 @@ int UtcDaliVisualGetVisualProperty02(void) UniformData("offset", Property::Type::VECTOR2), UniformData("size", Property::Type::VECTOR2), UniformData("cornerRadius", Property::Type::VECTOR4), + UniformData("borderlineWidth", Property::Type::FLOAT), + UniformData("borderlineCOlor", Property::Type::VECTOR4), + UniformData("borderlineOffset", Property::Type::FLOAT), UniformData("blurRadius", Property::Type::FLOAT), }; @@ -4228,6 +4667,9 @@ int UtcDaliVisualGetVisualProperty02(void) Vector2 targetSize(1.1f, 1.1f); float targetOpacity = 0.5f; Vector4 targetCornerRadius(20.0f, 0.0f, 20.0f, 0.0f); + float targetBorderlineWidth = 77.7f; + Vector4 targetBorderlineColor(0.4f, 0.2f, 0.3f, 0.9f); + float targetBorderlineOffset = 1.0f; float targetBlurRadius = 10.0f; // Should work when the properties are not set before @@ -4237,6 +4679,9 @@ int UtcDaliVisualGetVisualProperty02(void) animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "offset"), targetOffset); animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "size"), targetSize); animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "cornerRadius"), targetCornerRadius); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "borderlineWidth"), targetBorderlineWidth); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "borderlineColor"), targetBorderlineColor); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "borderlineOffset"), targetBorderlineOffset); animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "blurRadius"), targetBlurRadius); animation.Play(); @@ -4268,6 +4713,18 @@ int UtcDaliVisualGetVisualProperty02(void) DALI_TEST_CHECK(cornerRadiusValue); DALI_TEST_EQUALS(cornerRadiusValue->Get< Vector4 >(), targetCornerRadius, TEST_LOCATION); + Property::Value* borderlineWidthValue = resultMap.Find(DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT); + DALI_TEST_CHECK(borderlineWidthValue); + DALI_TEST_EQUALS(borderlineWidthValue->Get< float >(), targetBorderlineWidth, TEST_LOCATION); + + Property::Value* borderlineColorValue = resultMap.Find(DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4); + DALI_TEST_CHECK(borderlineColorValue); + DALI_TEST_EQUALS(borderlineColorValue->Get< Vector4 >(), targetBorderlineColor, TEST_LOCATION); + + Property::Value* borderlineOffsetValue = resultMap.Find(DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT); + DALI_TEST_CHECK(borderlineOffsetValue); + DALI_TEST_EQUALS(borderlineOffsetValue->Get< float >(), targetBorderlineOffset, 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); @@ -4288,11 +4745,14 @@ int UtcDaliVisualGetVisualProperty03(void) { #ifdef OLD_GRAPHICS_TEST ToolkitTestApplication application; - tet_infoline( "UtcDaliVisualGetVisualProperty01: Test animatable property, ImageVisual" ); + tet_infoline( "UtcDaliVisualGetVisualProperty03: Test animatable property, ImageVisual" ); static std::vector customUniforms = { UniformData("cornerRadius", Property::Type::VECTOR4), + UniformData("borderlineWidth", Property::Type::FLOAT), + UniformData("borderlineColor", Property::Type::VECTOR4), + UniformData("borderlineOffset", Property::Type::FLOAT), }; TestGraphicsController& graphics = application.GetGraphicsController(); @@ -4302,6 +4762,10 @@ int UtcDaliVisualGetVisualProperty03(void) Property::Map propertyMap; propertyMap.Insert(Visual::Property::TYPE, Visual::IMAGE); propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME); + //We must set some value because application cannot notify shader changed + propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS, 1.0f); + propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 1.0f); + Visual::Base imageVisual = factory.CreateVisual(propertyMap); DummyControl dummyControl = DummyControl::New(true); @@ -4318,10 +4782,16 @@ int UtcDaliVisualGetVisualProperty03(void) float targetOpacity = 0.5f; Vector4 targetCornerRadius(20.0f, 20.0f, 0.0f, 0.0f); + float targetBorderlineWidth = 10.0f; + Vector4 targetBorderlineColor(1.0f, 0.0f, 1.0f, 0.5f); + float targetBorderlineOffset = -1.5f; 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.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_WIDTH), targetBorderlineWidth); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_COLOR), targetBorderlineColor); + animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_OFFSET), targetBorderlineOffset); animation.Play(); application.SendNotification(); @@ -4340,8 +4810,23 @@ int UtcDaliVisualGetVisualProperty03(void) DALI_TEST_CHECK(cornerRadiusValue); DALI_TEST_EQUALS(cornerRadiusValue->Get< Vector4 >(), targetCornerRadius, TEST_LOCATION); + Property::Value* borderlineWidthValue = resultMap.Find(DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT); + DALI_TEST_CHECK(borderlineWidthValue); + DALI_TEST_EQUALS(borderlineWidthValue->Get< float >(), targetBorderlineWidth, TEST_LOCATION); + + Property::Value* borderlineColorValue = resultMap.Find(DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4); + DALI_TEST_CHECK(borderlineColorValue); + DALI_TEST_EQUALS(borderlineColorValue->Get< Vector4 >(), targetBorderlineColor, TEST_LOCATION); + + Property::Value* borderlineOffsetValue = resultMap.Find(DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT); + DALI_TEST_CHECK(borderlineOffsetValue); + DALI_TEST_EQUALS(borderlineOffsetValue->Get< float >(), targetBorderlineOffset, TEST_LOCATION); + // Test uniform value DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("cornerRadius", targetCornerRadius), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineWidth", targetBorderlineWidth), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineColor", targetBorderlineColor), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineOffset", targetBorderlineOffset), true, TEST_LOCATION); #else tet_result(TET_PASS); #endif diff --git a/dali-toolkit/devel-api/controls/accessible-impl.cpp b/dali-toolkit/devel-api/controls/accessible-impl.cpp index 8756121..fd3e72e 100644 --- a/dali-toolkit/devel-api/controls/accessible-impl.cpp +++ b/dali-toolkit/devel-api/controls/accessible-impl.cpp @@ -266,6 +266,23 @@ static Dali::Actor CreateHighlightIndicatorActor() return actor; } +void AccessibleImpl::ScrollToSelf() +{ + auto* child = this; + auto* parent = dynamic_cast(child->GetParent()); + + while (parent) + { + if (parent->IsScrollable()) + { + parent->ScrollToChild(child->Self()); + } + + child = parent; + parent = dynamic_cast(parent->GetParent()); + } +} + bool AccessibleImpl::GrabHighlight() { Dali::Actor self = Self(); @@ -295,7 +312,7 @@ bool AccessibleImpl::GrabHighlight() // Remember the highlight actor, so that when the default is changed with // SetHighlightActor(), the currently displayed highlight can still be cleared. currentHighlightActor = highlight; - EnsureSelfVisible(); + ScrollToSelf(); self.Add(highlight); SetCurrentlyHighlightedActor(self); EmitHighlighted(true); @@ -402,17 +419,9 @@ std::vector AccessibleImpl::GetRelationSet() return ret; } -void AccessibleImpl::EnsureChildVisible(Actor child) -{ -} - -void AccessibleImpl::EnsureSelfVisible() +bool AccessibleImpl::ScrollToChild(Actor child) { - auto parent = dynamic_cast(GetParent()); - if(parent) - { - parent->EnsureChildVisible(Self()); - } + return false; } Dali::Property::Index AccessibleImpl::GetNamePropertyIndex() diff --git a/dali-toolkit/devel-api/controls/accessible-impl.h b/dali-toolkit/devel-api/controls/accessible-impl.h index ed09487..ab168c6 100644 --- a/dali-toolkit/devel-api/controls/accessible-impl.h +++ b/dali-toolkit/devel-api/controls/accessible-impl.h @@ -62,6 +62,8 @@ protected: return handle; } + void ScrollToSelf(); + public: AccessibleImpl(Dali::Actor self, Dali::Accessibility::Role role, bool modal = false); @@ -207,14 +209,9 @@ public: /** * @brief Makes sure that a given child of this container (e.g. ItemView) is visible + * @return false if scrolling is not supported or child is already visible */ - virtual void EnsureChildVisible(Actor child); - - /** - * @brief Makes sure this actor is visible (when moving the highlight frame to an - * actor that is scrolled out of the viewport) - */ - virtual void EnsureSelfVisible(); + virtual bool ScrollToChild(Actor child); /** * @brief Returns the index of the property that represents this actor's name diff --git a/dali-toolkit/devel-api/controls/control-devel.cpp b/dali-toolkit/devel-api/controls/control-devel.cpp index 157051b..487aa1b 100644 --- a/dali-toolkit/devel-api/controls/control-devel.cpp +++ b/dali-toolkit/devel-api/controls/control-devel.cpp @@ -122,6 +122,19 @@ Dali::Property GetVisualProperty(Control control, Dali::Property::Index index, D return controlDataImpl.GetVisualProperty(index, visualPropertyKey); } +void CreateTransitions(Control control, Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod) +{ + if(animation) + { + // make visual transition of control visual. + Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control); + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(internalControl); + controlDataImpl.MakeVisualTransition(animation, source, Toolkit::Control::Property::BACKGROUND, alphaFunction, timePeriod); + controlDataImpl.MakeVisualTransition(animation, source, Toolkit::DevelControl::Property::SHADOW, alphaFunction, timePeriod); + internalControl.OnCreateTransitions(animation, source, alphaFunction, timePeriod); + } +} + 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 4978e4d..d977c34 100644 --- a/dali-toolkit/devel-api/controls/control-devel.h +++ b/dali-toolkit/devel-api/controls/control-devel.h @@ -20,6 +20,8 @@ // EXTERNAL INCLUDES #include #include +#include +#include // INTERNAL INCLUDES #include @@ -362,6 +364,20 @@ DALI_TOOLKIT_API VisualEventSignalType& VisualEventSignal(Control control); DALI_TOOLKIT_API Dali::Property GetVisualProperty(Control control, Dali::Property::Index index, Dali::Property::Key visualPropertyKey); /** + * @brief Retrieve visual/renderer property animation between this Control and source control. + * Input animation must be created before this method called. + * And the animations between this method created are added the input animation. + * This method generates visual/renderer property animation but not creates Actor property animation. + * + * @param[in] control The control + * @param[in] animation generated animation + * @param[in] source source control of the animation. + * @param[in] alphaFunction AlphaFunction of the animation + * @param[in] timePeriod TimePeriod of the animation + */ +DALI_TOOLKIT_API void CreateTransitions(Control control, Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod); + +/** * @brief The signal is emmited as a succession of "activate" signal send by accessibility client. * @return The signal to connect to */ diff --git a/dali-toolkit/devel-api/layouting/flex-node.h b/dali-toolkit/devel-api/layouting/flex-node.h index d19c90b..a7349fe 100644 --- a/dali-toolkit/devel-api/layouting/flex-node.h +++ b/dali-toolkit/devel-api/layouting/flex-node.h @@ -55,7 +55,8 @@ enum class Justification CENTER, ///< Items are positioned at the center of the container FLEX_END, ///< Items are positioned at the end of the container SPACE_BETWEEN, ///< Items are positioned with equal space between the items - SPACE_AROUND ///< Items are positioned with equal space before, between, and after the items + SPACE_AROUND, ///< Items are positioned with equal space before, and after the items + SPACE_EVENLY ///< Items are positioned with equal space before, between, and after the items }; /** diff --git a/dali-toolkit/devel-api/visuals/visual-properties-devel.h b/dali-toolkit/devel-api/visuals/visual-properties-devel.h index 1098b7d..ddb02d5 100644 --- a/dali-toolkit/devel-api/visuals/visual-properties-devel.h +++ b/dali-toolkit/devel-api/visuals/visual-properties-devel.h @@ -94,6 +94,28 @@ enum Type * If it it RELATIVE, the corner radius value is relative to the smaller of the visual width and visual height. */ CORNER_RADIUS_POLICY = OPACITY + 3, + + /** + * @brief The width for the borderline of the visual + * @details Name "borderlineWidth", type Property::FLOAT, animatable + * @note Optional. Default value is 0.0f. + */ + BORDERLINE_WIDTH = OPACITY + 4, + + /** + * @brief The color for the borderline of the visual + * @details Name "borderlineColor", type Property::VECTOR4, animatable + * @note Default value is Color::BLACK + */ + BORDERLINE_COLOR = OPACITY + 5, + + /** + * @brief The offset from the visual borderline (recommend [-1.0f to 1.0f]). + * @details Name "borderlineOffset", type Property::FLOAT, animatable + * @note Default value is 0.0f. + * @note This value will be clipped by [-1.0f to 1.0f]. + */ + BORDERLINE_OFFSET = OPACITY + 6, }; } // namespace Property diff --git a/dali-toolkit/internal/controls/control/control-data-impl.cpp b/dali-toolkit/internal/controls/control/control-data-impl.cpp index c50cd20..06027de 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.cpp +++ b/dali-toolkit/internal/controls/control/control-data-impl.cpp @@ -1821,6 +1821,69 @@ Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dal return Dali::Property(handle, Property::INVALID_INDEX); } +void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod) +{ + Dali::Toolkit::Control sourceHandle = Dali::Toolkit::Control::DownCast(source); + Property::Map sourceMap = sourceHandle.GetProperty(visualIndex); + Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self()); + Property::Map destinationMap = destinationHandle.GetProperty(visualIndex); + + Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f); + Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f); + + if(!destinationMap.Empty()) + { + mixColor = destinationMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get(); + cornerRadius = destinationMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get(); + + if(sourceMap.Empty()) + { + sourceMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); + sourceMap.Insert(Dali::Toolkit::Visual::Property::MIX_COLOR, Color::TRANSPARENT); + sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius); + } + + Vector4 sourceMixColor = sourceMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get(); + Vector4 sourceCornerRadius = sourceMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get(); + + std::vector properties; + std::vector> values; + + if(Vector3(sourceMixColor) != Vector3(mixColor)) + { + properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::MIX_COLOR)); + values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(mixColor))); + } + + if(std::abs(sourceMixColor.a - mixColor.a) > Math::MACHINE_EPSILON_1) + { + properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::OPACITY)); + values.push_back(std::make_pair(sourceMixColor.a, mixColor.a)); + } + + if(sourceCornerRadius != cornerRadius) + { + properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS)); + values.push_back(std::make_pair(sourceCornerRadius, cornerRadius)); + } + + for(uint32_t i = 0; i < properties.size(); ++i) + { + if(timePeriod.delaySeconds > 0.0f) + { + Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New(); + initialKeyframes.Add(0.0f, values[i].first); + initialKeyframes.Add(1.0f, values[i].first); + animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds)); + } + Dali::KeyFrames keyframes = Dali::KeyFrames::New(); + keyframes.Add(0.0f, values[i].first); + keyframes.Add(1.0f, values[i].second); + animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod); + } + } +} + 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 45430c5..96290b7 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.h +++ b/dali-toolkit/internal/controls/control/control-data-impl.h @@ -393,6 +393,18 @@ public: */ Dali::Property GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey); + /** + * @brief Make visual transition from source control to this control about specific Property::Index + * If both of source and this control have Property::Index property, than create animation between them. + * + * @param[in] animation Return animation from source to this control. + * @param[in] source Source control to be used property animation. + * @param[in] visualIndex Property::Index to make animation. + * @param[in] alphaFunction alpha function of the animation. + * @param[in] timePeriod time period of the animation. + */ + void MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod); + private: /** * Used as an alternative to boolean so that it is obvious whether a visual is enabled/disabled. diff --git a/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp b/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp index 111e480..a3c092d 100644 --- a/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp +++ b/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp @@ -127,7 +127,8 @@ const Scripting::StringEnum JUSTIFY_CONTENT_STRING_TABLE[] = {"center", Toolkit::FlexContainer::JUSTIFY_CENTER}, {"flexEnd", Toolkit::FlexContainer::JUSTIFY_FLEX_END}, {"spaceBetween", Toolkit::FlexContainer::JUSTIFY_SPACE_BETWEEN}, - {"spaceAround", Toolkit::FlexContainer::JUSTIFY_SPACE_AROUND}}; + {"spaceAround", Toolkit::FlexContainer::JUSTIFY_SPACE_AROUND}, + {"spaceEvenly", Toolkit::FlexContainer::JUSTIFY_SPACE_EVENLY}}; const unsigned int JUSTIFY_CONTENT_STRING_TABLE_COUNT = sizeof(JUSTIFY_CONTENT_STRING_TABLE) / sizeof(JUSTIFY_CONTENT_STRING_TABLE[0]); const Scripting::StringEnum ALIGN_ITEMS_STRING_TABLE[] = diff --git a/dali-toolkit/internal/controls/image-view/image-view-impl.cpp b/dali-toolkit/internal/controls/image-view/image-view-impl.cpp index 513960f..031befd 100644 --- a/dali-toolkit/internal/controls/image-view/image-view-impl.cpp +++ b/dali-toolkit/internal/controls/image-view/image-view-impl.cpp @@ -287,6 +287,75 @@ void ImageView::OnRelayout(const Vector2& size, RelayoutContainer& container) } } +void ImageView::OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod) +{ + Dali::Toolkit::ImageView destinationHandle = Toolkit::ImageView(GetOwner()); + Toolkit::Visual::Base destinationVisual = DevelControl::GetVisual(GetImplementation(destinationHandle), Toolkit::ImageView::Property::IMAGE); + Property::Map destinationMap; + + if(!destinationVisual) + { + return; + } + + destinationVisual.CreatePropertyMap(destinationMap); + + Vector4 sourceMixColor(0.0f, 0.0f, 0.0f, 0.0f); + Vector4 sourceCornerRadius(0.0f, 0.0f, 0.0f, 0.0f); + Vector4 destinationMixColor = destinationMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get(); + Vector4 destinationCornerRadius = destinationMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get(); + + Dali::Toolkit::ImageView sourceHandle = Dali::Toolkit::ImageView::DownCast(source); + Toolkit::Visual::Base sourceVisual; + Property::Map sourceMap; + + if(sourceHandle) + { + sourceVisual = DevelControl::GetVisual(GetImplementation(sourceHandle), Toolkit::ImageView::Property::IMAGE); + } + + if(sourceVisual) + { + sourceVisual.CreatePropertyMap(sourceMap); + sourceMixColor = sourceMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get(); + sourceCornerRadius = sourceMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get(); + } + + std::vector properties; + std::vector> values; + + if(Vector3(sourceMixColor) != Vector3(destinationMixColor)) + { + properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::Visual::Property::MIX_COLOR)); + values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(destinationMixColor))); + } + if(std::abs(sourceMixColor.a - destinationMixColor.a) > Math::MACHINE_EPSILON_1) + { + properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::Visual::Property::OPACITY)); + values.push_back(std::make_pair(sourceMixColor.a, destinationMixColor.a)); + } + if(sourceCornerRadius != destinationCornerRadius) + { + properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::CORNER_RADIUS)); + values.push_back(std::make_pair(sourceCornerRadius, destinationCornerRadius)); + } + + for(uint32_t i = 0; i < properties.size(); ++i) + { + if(timePeriod.delaySeconds > 0.0f) + { + Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New(); + initialKeyframes.Add(0.0f, values[i].first); + initialKeyframes.Add(1.0f, values[i].first); + animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds)); + } + Dali::KeyFrames keyframes = Dali::KeyFrames::New(); + keyframes.Add(0.0f, values[i].first); + keyframes.Add(1.0f, values[i].second); + animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod); + } +} + void ImageView::OnResourceReady(Toolkit::Control control) { // Visual ready so update visual attached to this ImageView, following call to RelayoutRequest will use this visual. diff --git a/dali-toolkit/internal/controls/image-view/image-view-impl.h b/dali-toolkit/internal/controls/image-view/image-view-impl.h index 90dc192..023930e 100644 --- a/dali-toolkit/internal/controls/image-view/image-view-impl.h +++ b/dali-toolkit/internal/controls/image-view/image-view-impl.h @@ -133,6 +133,11 @@ private: // From Control */ void OnRelayout(const Vector2& size, RelayoutContainer& container) override; + /** + * @copydoc Toolkit::Control::OnCreateTransitions() + */ + virtual void OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod) override; + private: /** * @brief Callback for ResourceReadySignal diff --git a/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp b/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp index ecc25b2..e9b58c8 100644 --- a/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp @@ -1345,11 +1345,11 @@ void ItemView::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor) } } -void ItemView::AccessibleImpl::EnsureChildVisible(Actor child) +bool ItemView::AccessibleImpl::ScrollToChild(Actor child) { - EnsureSelfVisible(); auto itemView = Dali::Toolkit::ItemView::DownCast(Self()); Toolkit::GetImpl(itemView).OnKeyboardFocusChangeCommitted(child); + return true; } Animation ItemView::DoAnchoring() diff --git a/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h b/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h index 9b3d656..7e3d8c1 100644 --- a/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h +++ b/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h @@ -438,7 +438,7 @@ protected: { using Scrollable::AccessibleImpl::AccessibleImpl; - void EnsureChildVisible(Actor child) override; + bool ScrollToChild(Actor child) override; }; /** diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp index ac062ff..8ca6855 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp @@ -1823,10 +1823,17 @@ Toolkit::ScrollView::SnapStartedSignalType& ScrollView::SnapStartedSignal() return mSnapStartedSignal; } -void ScrollView::AccessibleImpl::EnsureChildVisible(Actor child) +bool ScrollView::AccessibleImpl::ScrollToChild(Actor child) { auto scrollView = Dali::Toolkit::ScrollView::DownCast(Self()); - scrollView.ScrollTo(child); + if (Toolkit::GetImpl(scrollView).FindClosestActor() == child) + { + return false; + } + + // FIXME: ScrollTo does not work (snaps back to original position) + scrollView.ScrollTo(child, scrollView.GetScrollFlickDuration()); + return true; } void ScrollView::FindAndUnbindActor(Actor child) diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h index 11ff969..aee050e 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h @@ -790,7 +790,7 @@ protected: { using Scrollable::AccessibleImpl::AccessibleImpl; - void EnsureChildVisible(Actor child) override; + bool ScrollToChild(Actor child) override; }; /** diff --git a/dali-toolkit/internal/controls/web-view/web-view-impl.cpp b/dali-toolkit/internal/controls/web-view/web-view-impl.cpp index 3342374..bf85d8d 100755 --- a/dali-toolkit/internal/controls/web-view/web-view-impl.cpp +++ b/dali-toolkit/internal/controls/web-view/web-view-impl.cpp @@ -130,7 +130,8 @@ WebView::WebView(const std::string& locale, const std::string& timezoneId) mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height), mVideoHoleEnabled(true), mMouseEventsEnabled(true), - mKeyEventsEnabled(true) + mKeyEventsEnabled(true), + mScreenshotCapturedCallback(nullptr) { mWebEngine = Dali::WebEngine::New(); @@ -154,7 +155,8 @@ WebView::WebView(uint32_t argc, char** argv) mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height), mVideoHoleEnabled(true), mMouseEventsEnabled(true), - mKeyEventsEnabled(true) + mKeyEventsEnabled(true), + mScreenshotCapturedCallback(nullptr) { mWebEngine = Dali::WebEngine::New(); diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index fc8edaf..aabd0c0 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -178,6 +178,10 @@ SET( toolkit_src_files ${toolkit_src_dir}/text/rendering/text-backend-impl.cpp ${toolkit_src_dir}/text/rendering/text-typesetter.cpp ${toolkit_src_dir}/text/rendering/view-model.cpp + ${toolkit_src_dir}/transition/transition-base-impl.cpp + ${toolkit_src_dir}/transition/transition-impl.cpp + ${toolkit_src_dir}/transition/transition-lifecycle-controller.cpp + ${toolkit_src_dir}/transition/transition-set-impl.cpp ${toolkit_src_dir}/transition-effects/cube-transition-effect-impl.cpp ${toolkit_src_dir}/transition-effects/cube-transition-cross-effect-impl.cpp ${toolkit_src_dir}/transition-effects/cube-transition-fold-effect-impl.cpp diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.frag b/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.frag deleted file mode 100644 index a3bb80a..0000000 --- a/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.frag +++ /dev/null @@ -1,74 +0,0 @@ -INPUT mediump vec2 vPosition; -INPUT mediump vec2 vRectSize; -INPUT mediump vec2 vOptRectSize; -INPUT mediump vec4 vCornerRadius; - -uniform lowp vec4 uColor; -uniform lowp vec3 mixColor; -uniform mediump float blurRadius; - -void main() -{ - OUT_COLOR = vec4(mixColor, 1.0) * uColor; - if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) - { - return; - } - - mediump float radius = - mix( - mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5), - mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5), - sign(vPosition.y) * 0.5 + 0.5 - ); - - mediump vec2 v = abs(vPosition) - vRectSize + radius; - mediump float cy = radius + blurRadius; - mediump float cr = radius + blurRadius; - - cy = min(cy, min(vRectSize.x, vRectSize.y) - radius); - v = vec2(min(v.x, v.y), max(v.x, v.y)); - v = v + cy; - - mediump float blur = 1.0; - mediump float potential = 0.0; - mediump float alias = min(radius, 1.0); - mediump float potentialMin = cy + radius - blurRadius - alias; - mediump float potentialMax = cy + radius + blurRadius + alias; - - // move center of circles for reduce defact - mediump float cyDiff = min(cy, 0.2 * blurRadius); - cy -= cyDiff; - cr += cyDiff; - - mediump float diffFromBaseline = cy * v.y - (cy + cr) * v.x; - - if(diffFromBaseline > 0.0) - { - // out of calculation bound. - potential = v.y; - - // for anti-alias when blurRaidus = 0.0 - mediump float heuristicBaselineScale = max(1.0 , cr * (cr + cy)); - mediump float potentialDiff = min(alias, diffFromBaseline / heuristicBaselineScale); - potentialMin += potentialDiff; - potentialMax -= potentialDiff; - } - else - { - // get some circle centered (x, x) and radius (r = cr / cy * x) - // s.t. point v is on that circle - // highest point of that circle is (x, x + r) and potential is x + r - - // solve (v.x - x)^2 + (v.y - x)^2 = (cr / cy * x)^2 - - mediump float A = (cr * cr - 2.0 * cy * cy); - mediump float B = cy * (v.x + v.y); - mediump float V = dot(v,v); - mediump float D = B * B + A * V; - potential = V * (cr + cy) / (sqrt(D) + B); - } - - blur = 1.0 - smoothstep(potentialMin, potentialMax, potential); - OUT_COLOR.a *= blur; -} diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.vert b/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.vert deleted file mode 100644 index 5306aef..0000000 --- a/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.vert +++ /dev/null @@ -1,40 +0,0 @@ -INPUT mediump vec2 aPosition; -OUTPUT mediump vec2 vPosition; -OUTPUT mediump vec2 vRectSize; -OUTPUT mediump vec2 vOptRectSize; -OUTPUT mediump vec4 vCornerRadius; - -uniform highp mat4 uMvpMatrix; -uniform highp vec3 uSize; - -//Visual size and offset -uniform mediump vec2 offset; -uniform highp vec2 size; -uniform mediump vec2 extraSize; -uniform mediump vec4 offsetSizeMode; -uniform mediump vec2 origin; -uniform mediump vec2 anchorPoint; -uniform mediump float blurRadius; -uniform mediump vec4 cornerRadius; -uniform mediump float cornerRadiusPolicy; - -vec4 ComputeVertexPosition() -{ - vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize; - vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy); - mediump float minSize = min( visualSize.x, visualSize.y ); - vCornerRadius = mix( cornerRadius * minSize, cornerRadius, cornerRadiusPolicy ); - vCornerRadius = min( vCornerRadius, minSize * 0.5 ); - vRectSize = visualSize / 2.0; - // optimize fragment shader - mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w)); - vOptRectSize = vRectSize - 0.2929 * maxRadius - 1.0 - blurRadius; - - vPosition = aPosition * (visualSize + 2.0 * blurRadius); - return vec4( vPosition + anchorPoint*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 ); -} - -void main() -{ - gl_Position = uMvpMatrix * ComputeVertexPosition(); -} diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.frag b/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.frag deleted file mode 100644 index 811dc1d..0000000 --- a/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.frag +++ /dev/null @@ -1,37 +0,0 @@ -INPUT mediump vec2 vPosition; -INPUT mediump vec2 vRectSize; -INPUT mediump vec2 vOptRectSize; -INPUT mediump vec4 vCornerRadius; - -uniform lowp vec4 uColor; -uniform lowp vec3 mixColor; - -void main() -{ - OUT_COLOR = vec4(mixColor, 1.0) * uColor; - if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) - { - return; - } - mediump float radius = - mix( - mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5), - mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5), - sign(vPosition.y) * 0.5 + 0.5 - ); - - mediump vec2 diff = abs(vPosition) - vRectSize + radius; - mediump float dist = length(max(diff, vec2(0.0))) - radius; - if(dist > 1.0) - { - OUT_COLOR.a = 0.0; - } - else if(dist > -1.0) - { - if(min(diff.x, diff.y) < 0.0) - { - dist += min(diff.x, diff.y) / max(radius, 1.0); - } - OUT_COLOR.a *= 1.0 - smoothstep(-1.0, 1.0, dist); - } -} diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.vert b/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.vert deleted file mode 100644 index 0a6a257..0000000 --- a/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.vert +++ /dev/null @@ -1,38 +0,0 @@ -INPUT mediump vec2 aPosition; -OUTPUT mediump vec2 vPosition; -OUTPUT mediump vec2 vRectSize; -OUTPUT mediump vec2 vOptRectSize; -OUTPUT mediump vec4 vCornerRadius; - -uniform highp mat4 uMvpMatrix; -uniform highp vec3 uSize; - -//Visual size and offset -uniform mediump vec2 offset; -uniform highp vec2 size; -uniform mediump vec2 extraSize; -uniform mediump vec4 offsetSizeMode; -uniform mediump vec2 origin; -uniform mediump vec2 anchorPoint; -uniform mediump vec4 cornerRadius; -uniform mediump float cornerRadiusPolicy; - -vec4 ComputeVertexPosition() -{ - vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize; - vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy); - mediump float minSize = min( visualSize.x, visualSize.y ); - vCornerRadius = mix( cornerRadius * minSize, cornerRadius, cornerRadiusPolicy); - vCornerRadius = min( vCornerRadius, minSize * 0.5 ); - vRectSize = visualSize / 2.0; - // optimize fragment shader - mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w)); - vOptRectSize = vRectSize - 0.2929 * maxRadius - 1.0; - vPosition = aPosition* visualSize; - return vec4( vPosition + anchorPoint*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 ); -} - -void main() -{ - gl_Position = uMvpMatrix * ComputeVertexPosition(); -} diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag index fef045b..bf93629 100644 --- a/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag +++ b/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag @@ -1,7 +1,265 @@ +#ifndef IS_REQUIRED_ROUNDED_CORNER +#define IS_REQUIRED_ROUNDED_CORNER 0 +#endif +#ifndef IS_REQUIRED_BORDERLINE +#define IS_REQUIRED_BORDERLINE 0 +#endif +#ifndef IS_REQUIRED_BLUR +#define IS_REQUIRED_BLUR 0 +#endif + +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR +INPUT mediump vec2 vPosition; +INPUT mediump vec2 vRectSize; +INPUT mediump vec2 vOptRectSize; +#if IS_REQUIRED_ROUNDED_CORNER +INPUT mediump vec4 vCornerRadius; +#endif +#endif + uniform lowp vec4 uColor; uniform lowp vec3 mixColor; +#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE +uniform mediump float borderlineWidth; +uniform mediump float borderlineOffset; +uniform lowp vec4 borderlineColor; +#endif +#if IS_REQUIRED_BLUR +uniform mediump float blurRadius; +#endif + + +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR +// Global values both rounded corner and borderline use + +// radius of rounded corner on this quadrant +mediump float gRadius = 0.0; + +// fragment coordinate. NOTE : vec2(0.0, 0.0) is vRectSize, the corner of visual +mediump vec2 gFragmentPosition = vec2(0.0, 0.0); +// center coordinate of rounded corner circle. vec2(gCenterPosition, gCenterPosition). +mediump float gCenterPosition = 0.0; +// relative coordinate of gFragmentPosition from gCenterPosition. +mediump vec2 gDiff = vec2(0.0, 0.0); +// potential value what our algorithm use. +mediump float gPotential = 0.0; + +// threshold of potential +mediump float gPotentialRange = 0.0; +mediump float gMaxOutlinePotential = 0.0; +mediump float gMinOutlinePotential = 0.0; +mediump float gMaxInlinePotential = 0.0; +mediump float gMinInlinePotential = 0.0; + +void calculateCornerRadius() +{ +#if IS_REQUIRED_ROUNDED_CORNER + gRadius = + mix( + mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5), + mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5), + sign(vPosition.y) * 0.5 + 0.5 + ); +#endif +} + +void calculatePosition() +{ + gFragmentPosition = abs(vPosition) - vRectSize; + gCenterPosition = -gRadius; +#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE + gCenterPosition += borderlineWidth * (clamp(borderlineOffset, -1.0, 1.0) + 1.0) * 0.5; +#endif + gDiff = gFragmentPosition - gCenterPosition; +} + +void calculatePotential() +{ + gPotential = length(max(gDiff, 0.0)) + min(0.0, max(gDiff.x, gDiff.y)); +} + +void setupMinMaxPotential() +{ + gPotentialRange = 1.0; + + gMaxOutlinePotential = gRadius + gPotentialRange; + gMinOutlinePotential = gRadius - gPotentialRange; + +#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE + gMaxInlinePotential = gMaxOutlinePotential - borderlineWidth; + gMinInlinePotential = gMinOutlinePotential - borderlineWidth; +#else + gMaxInlinePotential = gMaxOutlinePotential; + gMinInlinePotential = gMinOutlinePotential; +#endif + + // reduce defect near edge of rounded corner. + gMaxOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0); + gMinOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0); +} + +void PreprocessPotential() +{ + calculateCornerRadius(); + calculatePosition(); + calculatePotential(); + + setupMinMaxPotential(); +} +#endif + +#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE +lowp vec4 convertBorderlineColor(lowp vec4 textureColor) +{ + mediump float potential = gPotential; + + // default opacity of borderline is 0.0 + mediump float borderlineOpacity = 0.0; + + // calculate borderline opacity by potential + if(potential > gMinInlinePotential) + { + // potential is inside borderline range. + borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential); + } + + //calculate inside of borderline when outilneColor.a < 1.0 + if(borderlineColor.a < 1.0) + { + mediump float tCornerRadius = -gCenterPosition; + mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange; + mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange; + if(potential > MaxTexturelinePotential) + { + // potential is out of texture range. use borderline color instead of texture + textureColor = vec4(borderlineColor.xyz, 0.0); + } + else if(potential > MinTexturelinePotential) + { + // potential is in texture range + textureColor = mix(textureColor, vec4(borderlineColor.xyz, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential)); + } + borderlineOpacity *= borderlineColor.a; + } + return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity); +} +#endif + +#if !IS_REQUIRED_BLUR && IS_REQUIRED_ROUNDED_CORNER +mediump float calculateCornerOpacity() +{ + mediump float potential = gPotential; + + // default opacity is 1.0 + mediump float opacity = 1.0; + + // calculate borderline opacity by potential + if(potential > gMaxOutlinePotential) + { + // potential is out of borderline range + opacity = 0.0; + } + else if(potential > gMinOutlinePotential) + { + opacity = 1.0 - smoothstep(gMinOutlinePotential, gMaxOutlinePotential, potential); + } + return opacity; +} +#endif + +#if IS_REQUIRED_BLUR +mediump float calculateBlurOpacity() +{ +// Don't use borderline! + mediump vec2 v = gDiff; + mediump float cy = gRadius + blurRadius; + mediump float cr = gRadius + blurRadius; + +#if IS_REQUIRED_ROUNDED_CORNER + // This routine make perfect circle. If corner radius is not exist, we don't consider prefect circle. + cy = min(cy, min(vRectSize.x, vRectSize.y) - gRadius); +#endif + v = vec2(min(v.x, v.y), max(v.x, v.y)); + v = v + cy; + + mediump float potential = 0.0; + mediump float alias = min(gRadius, 1.0); + mediump float potentialMin = cy + gRadius - blurRadius - alias; + mediump float potentialMax = cy + gRadius + blurRadius + alias; + + // move center of circles for reduce defact + mediump float cyDiff = min(cy, 0.2 * blurRadius); + cy -= cyDiff; + cr += cyDiff; + + mediump float diffFromBaseline = cy * v.y - (cy + cr) * v.x; + + if(diffFromBaseline > 0.0) + { + // out of calculation bound. + potential = v.y; + + // for anti-alias when blurRaidus = 0.0 + mediump float heuristicBaselineScale = max(1.0 , cr * (cr + cy)); + mediump float potentialDiff = min(alias, diffFromBaseline / heuristicBaselineScale); + potentialMin += potentialDiff; + potentialMax -= potentialDiff; + } + else + { + // get some circle centered (x, x) and radius (r = cr / cy * x) + // s.t. point v is on that circle + // highest point of that circle is (x, x + r) and potential is x + r + + // solve (v.x - x)^2 + (v.y - x)^2 = (cr / cy * x)^2 +#if IS_REQUIRED_ROUNDED_CORNER + // NOTE : lowspec HW cannot calculate here. need to reduce numeric error + mediump float A = (cr * cr - 2.0 * cy * cy); + mediump float B = cy * (v.x + v.y); + mediump float V = dot(v,v); + mediump float D = B * B + A * V; + potential = V * (cr + cy) / (sqrt(D) + B); +#else + // We can simplify this value cause cy = 0.8 * blurRadius, cr = 1.2 * blurRadius + // potential = 5.0*(sqrt(4.0*(v.x+v.y)^2 + dot(v,v)) - 2.0*(v.x+v.y)); + // = 10.0*(v.x+v.y) * (sqrt(1.0 + (length(v) / (2.0*(v.x+v.y)))^2) - 1.0); + // = 10.0*(v.x+v.y) * (sqrt(1.25 - x + x^2) - 1.0); + // ~= 10.0*(v.x+v.y) * (0.11803399 - 0.44721360x + 0.35777088x^2 - 0.14310x^3 + O(x^4)) (Taylor series) + // ~= -1.0557281 * (v.x + v.y) + 2.236068 * length(v) - ~~~ (here, x <= 0.5 * (1.0 - sqrt(0.5)) < 0.1464467) + // Note : This simplify need cause we should use it on lowspec HW. + mediump float x = 0.5 * (1.0 - length(v) / (v.x + v.y)); + potential = -1.0557281 * (v.x + v.y) + 2.236068 * length(v) + 10.0 * (v.x + v.y) * (0.35777088 - 0.14310 * x) * x * x; +#endif + } + + return 1.0 - smoothstep(potentialMin, potentialMax, potential); +} +#endif void main() { - OUT_COLOR = vec4(mixColor, 1.0) * uColor; -} \ No newline at end of file + lowp vec4 targetColor = vec4(mixColor, 1.0) * uColor; + +#if IS_REQUIRED_BLUR || IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE + // skip most potential calculate for performance + if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) + { + OUT_COLOR = targetColor; + return; + } + PreprocessPotential(); +#endif + +#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE + targetColor = convertBorderlineColor(targetColor); +#endif + OUT_COLOR = targetColor; + +#if IS_REQUIRED_BLUR + mediump float opacity = calculateBlurOpacity(); + OUT_COLOR.a *= opacity; +#elif IS_REQUIRED_ROUNDED_CORNER + mediump float opacity = calculateCornerOpacity(); + OUT_COLOR.a *= opacity; +#endif +} diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-shader.vert b/dali-toolkit/internal/graphics/shaders/color-visual-shader.vert index 993d9d4..2798185 100644 --- a/dali-toolkit/internal/graphics/shaders/color-visual-shader.vert +++ b/dali-toolkit/internal/graphics/shaders/color-visual-shader.vert @@ -1,4 +1,22 @@ +#ifndef IS_REQUIRED_ROUNDED_CORNER +#define IS_REQUIRED_ROUNDED_CORNER 0 +#endif +#ifndef IS_REQUIRED_BORDERLINE +#define IS_REQUIRED_BORDERLINE 0 +#endif +#ifndef IS_REQUIRED_BLUR +#define IS_REQUIRED_BLUR 0 +#endif + INPUT mediump vec2 aPosition; +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR +OUTPUT mediump vec2 vPosition; +OUTPUT mediump vec2 vRectSize; +OUTPUT mediump vec2 vOptRectSize; +#if IS_REQUIRED_ROUNDED_CORNER +OUTPUT mediump vec4 vCornerRadius; +#endif +#endif uniform highp mat4 uMvpMatrix; uniform highp vec3 uSize; @@ -9,16 +27,57 @@ uniform highp vec2 size; uniform mediump vec4 offsetSizeMode; uniform mediump vec2 origin; uniform mediump vec2 anchorPoint; +#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE +uniform mediump float borderlineWidth; +uniform mediump float borderlineOffset; +#endif +#if IS_REQUIRED_BLUR +uniform mediump float blurRadius; +#endif +#if IS_REQUIRED_ROUNDED_CORNER +uniform mediump vec4 cornerRadius; +uniform mediump float cornerRadiusPolicy; +#endif uniform mediump vec2 extraSize; vec4 ComputeVertexPosition() { vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize; - vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy); - return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 ); + vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy); + +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR + vRectSize = visualSize * 0.5; + vOptRectSize = vRectSize; +#endif + +#if IS_REQUIRED_ROUNDED_CORNER +#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE + mediump float minSize = min(visualSize.x, visualSize.y) + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth; +#else + mediump float minSize = min(visualSize.x, visualSize.y); +#endif + vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy); + vCornerRadius = min(vCornerRadius, minSize * 0.5); + // Optimize fragment shader. 0.2929 ~= 1.0 - sqrt(0.5) + mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w)); + vOptRectSize -= 0.2929 * maxRadius + 1.0; +#endif + +#if IS_REQUIRED_BLUR + vPosition = aPosition * (visualSize + 2.0 * blurRadius); + vOptRectSize -= blurRadius + 1.0; +#elif IS_REQUIRED_BORDERLINE + vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0))* borderlineWidth); + vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0; +#elif IS_REQUIRED_ROUNDED_CORNER + vPosition = aPosition * visualSize; +#else + mediump vec2 vPosition = aPosition * visualSize; +#endif + return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0); } void main() { gl_Position = uMvpMatrix * ComputeVertexPosition(); -} \ No newline at end of file +} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-rounded-corner-shader.vert b/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-rounded-corner-shader.vert deleted file mode 100644 index bd08a63..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-rounded-corner-shader.vert +++ /dev/null @@ -1,41 +0,0 @@ -attribute mediump vec2 aPosition; -uniform highp mat4 uMvpMatrix; -uniform highp vec3 uSize; -uniform mediump mat3 uAlignmentMatrix; -varying mediump vec2 vTexCoord; -varying mediump vec2 vPosition; -varying mediump vec2 vRectSize; -varying mediump vec2 vOptRectSize; -varying mediump vec4 vCornerRadius; - -//Visual size and offset -uniform mediump vec2 offset; -uniform highp vec2 size; -uniform mediump vec4 offsetSizeMode; -uniform mediump vec2 origin; -uniform mediump vec2 anchorPoint; -uniform mediump vec4 cornerRadius; -uniform mediump float cornerRadiusPolicy; - -vec4 ComputeVertexPosition() -{ - vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw); - vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy); - mediump float minSize = min(visualSize.x, visualSize.y); - vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy); - vCornerRadius = min(vCornerRadius, minSize * 0.5); - vRectSize = visualSize * 0.5; - // Optimize fragment shader - mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w)); - vOptRectSize = vRectSize - 0.2929 * maxRadius - 1.0; - vPosition = aPosition * visualSize; - return vec4((aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0); -} - -void main() -{ - mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0); - vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy; - - gl_Position = uMvpMatrix * ComputeVertexPosition(); -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-shader.vert b/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-shader.vert deleted file mode 100644 index 018e260..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-shader.vert +++ /dev/null @@ -1,27 +0,0 @@ -attribute mediump vec2 aPosition; -uniform highp mat4 uMvpMatrix; -uniform highp vec3 uSize; -uniform mediump mat3 uAlignmentMatrix; -varying mediump vec2 vTexCoord; - -//Visual size and offset -uniform mediump vec2 offset; -uniform highp vec2 size; -uniform mediump vec4 offsetSizeMode; -uniform mediump vec2 origin; -uniform mediump vec2 anchorPoint; - -vec4 ComputeVertexPosition() -{ - vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ); - vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy); - return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 ); -} - -void main() -{ - mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0); - vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy; - - gl_Position = uMvpMatrix * ComputeVertexPosition(); -} \ No newline at end of file diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-rounded-corner-shader.frag b/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-rounded-corner-shader.frag deleted file mode 100644 index 1b29ae0..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-rounded-corner-shader.frag +++ /dev/null @@ -1,38 +0,0 @@ -uniform sampler2D sTexture; // sampler1D? -uniform lowp vec4 uColor; -uniform lowp vec3 mixColor; -varying mediump vec2 vTexCoord; -varying mediump vec2 vPosition; -varying mediump vec2 vRectSize; -varying mediump vec2 vOptRectSize; -varying mediump vec4 vCornerRadius; - -void main() -{ - gl_FragColor = texture2D( sTexture, vec2( vTexCoord.y, 0.5 ) ) * vec4(mixColor, 1.0) * uColor; - if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) - { - return; - } - mediump float radius = - mix( - mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5), - mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5), - sign(vPosition.y) * 0.5 + 0.5 - ); - - mediump vec2 diff = abs(vPosition) - vRectSize + radius; - mediump float dist = length(max(diff, vec2(0.0))) - radius; - if(dist > 1.0) - { - gl_FragColor = vec4(0.0); - } - else if(dist > -1.0) - { - if(min(diff.x, diff.y) < 0.0) - { - dist += min(diff.x, diff.y) / max(radius, 1.0); - } - gl_FragColor *= 1.0 - smoothstep(-1.0, 1.0, dist); - } -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-shader.frag b/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-shader.frag deleted file mode 100644 index 1ec04b2..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-shader.frag +++ /dev/null @@ -1,9 +0,0 @@ -uniform sampler2D sTexture; // sampler1D? -uniform lowp vec4 uColor; -uniform lowp vec3 mixColor; -varying mediump vec2 vTexCoord; - -void main() -{ - gl_FragColor = texture2D( sTexture, vec2( vTexCoord.y, 0.5 ) ) * vec4(mixColor, 1.0) * uColor; -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-rounded-corner-shader.frag b/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-rounded-corner-shader.frag deleted file mode 100644 index 68df0c5..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-rounded-corner-shader.frag +++ /dev/null @@ -1,38 +0,0 @@ -uniform sampler2D sTexture; // sampler1D? -uniform lowp vec4 uColor; -uniform lowp vec3 mixColor; -varying mediump vec2 vTexCoord; -varying mediump vec2 vPosition; -varying mediump vec2 vRectSize; -varying mediump vec2 vOptRectSize; -varying mediump vec4 vCornerRadius; - -void main() -{ - gl_FragColor = texture2D( sTexture, vec2( length(vTexCoord), 0.5 ) ) * vec4(mixColor, 1.0) * uColor; - if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) - { - return; - } - mediump float radius = - mix( - mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5), - mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5), - sign(vPosition.y) * 0.5 + 0.5 - ); - - mediump vec2 diff = abs(vPosition) - vRectSize + radius; - mediump float dist = length(max(diff, vec2(0.0))) - radius; - if(dist > 1.0) - { - gl_FragColor = vec4(0.0); - } - else if(dist > -1.0) - { - if(min(diff.x, diff.y) < 0.0) - { - dist += min(diff.x, diff.y) / max(radius, 1.0); - } - gl_FragColor *= 1.0 - smoothstep(-1.0, 1.0, dist); - } -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-shader.frag b/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-shader.frag deleted file mode 100644 index 8d37383..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-shader.frag +++ /dev/null @@ -1,9 +0,0 @@ -uniform sampler2D sTexture; // sampler1D? -uniform lowp vec4 uColor; -uniform lowp vec3 mixColor; -varying mediump vec2 vTexCoord; - -void main() -{ - gl_FragColor = texture2D( sTexture, vec2( length(vTexCoord), 0.5 ) ) * vec4(mixColor, 1.0) * uColor; -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag new file mode 100644 index 0000000..305ff92 --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag @@ -0,0 +1,196 @@ +#ifndef IS_REQUIRED_ROUNDED_CORNER +#define IS_REQUIRED_ROUNDED_CORNER 0 +#endif +#ifndef IS_REQUIRED_BORDERLINE +#define IS_REQUIRED_BORDERLINE 0 +#endif +#ifndef RADIAL +#define RADIAL 0 +#endif + +INPUT mediump vec2 vTexCoord; +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE +INPUT mediump vec2 vPosition; +INPUT mediump vec2 vRectSize; +INPUT mediump vec2 vOptRectSize; +#if IS_REQUIRED_ROUNDED_CORNER +INPUT mediump vec4 vCornerRadius; +#endif +#endif + +uniform sampler2D sTexture; // sampler1D? +uniform lowp vec4 uColor; +uniform lowp vec3 mixColor; +#if IS_REQUIRED_BORDERLINE +uniform mediump float borderlineWidth; +uniform mediump float borderlineOffset; +uniform lowp vec4 borderlineColor; +#endif + +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE +// Global values both rounded corner and borderline use + +// radius of rounded corner on this quadrant +mediump float gRadius = 0.0; + +// fragment coordinate. NOTE : vec2(0.0, 0.0) is vRectSize, the corner of visual +mediump vec2 gFragmentPosition = vec2(0.0, 0.0); +// center coordinate of rounded corner circle. vec2(gCenterPosition, gCenterPosition). +mediump float gCenterPosition = 0.0; +// relative coordinate of gFragmentPosition from gCenterPosition. +mediump vec2 gDiff = vec2(0.0, 0.0); +// potential value what our algorithm use. +mediump float gPotential = 0.0; + +// threshold of potential +mediump float gPotentialRange = 0.0; +mediump float gMaxOutlinePotential = 0.0; +mediump float gMinOutlinePotential = 0.0; +mediump float gMaxInlinePotential = 0.0; +mediump float gMinInlinePotential = 0.0; + +void calculateCornerRadius() +{ +#if IS_REQUIRED_ROUNDED_CORNER + gRadius = + mix( + mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5), + mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5), + sign(vPosition.y) * 0.5 + 0.5 + ); +#endif +} + +void calculatePosition() +{ + gFragmentPosition = abs(vPosition) - vRectSize; + gCenterPosition = -gRadius; +#if IS_REQUIRED_BORDERLINE + gCenterPosition += borderlineWidth * (clamp(borderlineOffset, -1.0, 1.0) + 1.0) * 0.5; +#endif + gDiff = gFragmentPosition - gCenterPosition; +} + +void calculatePotential() +{ + gPotential = length(max(gDiff, 0.0)) + min(0.0, max(gDiff.x, gDiff.y)); +} + +void setupMinMaxPotential() +{ + gPotentialRange = 1.0; + + gMaxOutlinePotential = gRadius + gPotentialRange; + gMinOutlinePotential = gRadius - gPotentialRange; + +#if IS_REQUIRED_BORDERLINE + gMaxInlinePotential = gMaxOutlinePotential - borderlineWidth; + gMinInlinePotential = gMinOutlinePotential - borderlineWidth; +#else + gMaxInlinePotential = gMaxOutlinePotential; + gMinInlinePotential = gMinOutlinePotential; +#endif + + // reduce defect near edge of rounded corner. + gMaxOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0); + gMinOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0); +} + +void PreprocessPotential() +{ + calculateCornerRadius(); + calculatePosition(); + calculatePotential(); + + setupMinMaxPotential(); +} +#endif + + +#if IS_REQUIRED_BORDERLINE +lowp vec4 convertBorderlineColor(lowp vec4 textureColor) +{ + mediump float potential = gPotential; + + // default opacity of borderline is 0.0 + mediump float borderlineOpacity = 0.0; + + // calculate borderline opacity by potential + if(potential > gMinInlinePotential) + { + // potential is inside borderline range. + borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential); + } + + //calculate inside of borderline when outilneColor.a < 1.0 + if(borderlineColor.a < 1.0) + { + mediump float tCornerRadius = -gCenterPosition; + mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange; + mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange; + if(potential > MaxTexturelinePotential) + { + // potential is out of texture range. use borderline color instead of texture + textureColor = vec4(borderlineColor.xyz, 0.0); + } + else if(potential > MinTexturelinePotential) + { + // potential is in texture range + textureColor = mix(textureColor, vec4(borderlineColor.xyz, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential)); + } + borderlineOpacity *= borderlineColor.a; + } + return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity); +} +#endif + +#if IS_REQUIRED_ROUNDED_CORNER +mediump float calculateCornerOpacity() +{ + mediump float potential = gPotential; + + // default opacity is 1.0 + mediump float opacity = 1.0; + + // calculate borderline opacity by potential + if(potential > gMaxOutlinePotential) + { + // potential is out of borderline range + opacity = 0.0; + } + else if(potential > gMinOutlinePotential) + { + opacity = 1.0 - smoothstep(gMinOutlinePotential, gMaxOutlinePotential, potential); + } + return opacity; +} +#endif + +void main() +{ +#if RADIAL + lowp vec4 textureColor = TEXTURE(sTexture, vec2(length(vTexCoord), 0.5)) * vec4(mixColor, 1.0) * uColor; +#else + lowp vec4 textureColor = TEXTURE(sTexture, vec2(vTexCoord.y, 0.5)) * vec4(mixColor, 1.0) * uColor; +#endif + +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE + // skip most potential calculate for performance + if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) + { + OUT_COLOR = textureColor; + return; + } + PreprocessPotential(); +#endif + +#if IS_REQUIRED_BORDERLINE + textureColor = convertBorderlineColor(textureColor); +#endif + OUT_COLOR = textureColor; + +#if IS_REQUIRED_ROUNDED_CORNER + mediump float opacity = calculateCornerOpacity(); + OUT_COLOR *= opacity; +#endif +} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.vert b/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.vert new file mode 100644 index 0000000..f9e80fe --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.vert @@ -0,0 +1,84 @@ +#ifndef IS_REQUIRED_ROUNDED_CORNER +#define IS_REQUIRED_ROUNDED_CORNER 0 +#endif +#ifndef IS_REQUIRED_BORDERLINE +#define IS_REQUIRED_BORDERLINE 0 +#endif +#ifndef USER_SPACE +#define USER_SPACE 0 +#endif + +INPUT mediump vec2 aPosition; +OUTPUT mediump vec2 vTexCoord; +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE +OUTPUT mediump vec2 vPosition; +OUTPUT mediump vec2 vRectSize; +OUTPUT mediump vec2 vOptRectSize; +#if IS_REQUIRED_ROUNDED_CORNER +OUTPUT mediump vec4 vCornerRadius; +#endif +#endif + +uniform highp mat4 uMvpMatrix; +uniform highp vec3 uSize; +uniform mediump mat3 uAlignmentMatrix; + +//Visual size and offset +uniform mediump vec2 offset; +uniform highp vec2 size; +uniform mediump vec4 offsetSizeMode; +uniform mediump vec2 origin; +uniform mediump vec2 anchorPoint; +#if IS_REQUIRED_BORDERLINE +uniform mediump float borderlineWidth; +uniform mediump float borderlineOffset; +#endif +#if IS_REQUIRED_ROUNDED_CORNER +uniform mediump vec4 cornerRadius; +uniform mediump float cornerRadiusPolicy; +#endif + +vec4 ComputeVertexPosition() +{ + vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ); + vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy); + +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE + vRectSize = visualSize * 0.5; + vOptRectSize = vRectSize; +#endif + +#if IS_REQUIRED_ROUNDED_CORNER +#if IS_REQUIRED_BORDERLINE + mediump float minSize = min(visualSize.x, visualSize.y) + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth; +#else + mediump float minSize = min(visualSize.x, visualSize.y); +#endif + vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy); + vCornerRadius = min(vCornerRadius, minSize * 0.5); + // Optimize fragment shader. 0.2929 ~= 1.0 - sqrt(0.5) + mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w)); + vOptRectSize -= 0.2929 * maxRadius + 1.0; +#endif + +#if IS_REQUIRED_BORDERLINE + vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth); + vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0; +#elif IS_REQUIRED_ROUNDED_CORNER + vPosition = aPosition * visualSize; +#else + mediump vec2 vPosition = aPosition * visualSize; +#endif + + return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0); +} + +void main() +{ + mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0); + gl_Position = uMvpMatrix * ComputeVertexPosition(); +#if USER_SPACE + vertexPosition.xyz *= uSize; +#endif + vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy; +} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-rounded-corner-shader.vert b/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-rounded-corner-shader.vert deleted file mode 100644 index 23ded26..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-rounded-corner-shader.vert +++ /dev/null @@ -1,43 +0,0 @@ -attribute mediump vec2 aPosition; -uniform highp mat4 uMvpMatrix; -uniform highp vec3 uSize; -uniform mediump mat3 uAlignmentMatrix; -varying mediump vec2 vTexCoord; -varying mediump vec2 vPosition; -varying mediump vec2 vRectSize; -varying mediump vec2 vOptRectSize; -varying mediump vec4 vCornerRadius; - -//Visual size and offset -uniform mediump vec2 offset; -uniform highp vec2 size; -uniform mediump vec4 offsetSizeMode; -uniform mediump vec2 origin; -uniform mediump vec2 anchorPoint; -uniform mediump vec4 cornerRadius; -uniform mediump float cornerRadiusPolicy; - -vec4 ComputeVertexPosition() -{ - vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw); - vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy); - mediump float minSize = min(visualSize.x, visualSize.y); - vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy); - vCornerRadius = min(vCornerRadius, minSize * 0.5); - vRectSize = visualSize * 0.5; - // Optimze fragment shader - mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w)); - vOptRectSize = vRectSize - 0.2929 * maxRadius - 1.0; - vCornerRadius = max(vCornerRadius, 1.0); - vPosition = aPosition * visualSize; - return vec4((aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0); -} - -void main() -{ - mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0); - vertexPosition.xyz *= uSize; - gl_Position = uMvpMatrix * ComputeVertexPosition(); - - vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy; -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-shader.vert b/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-shader.vert deleted file mode 100644 index ca1eab6..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-shader.vert +++ /dev/null @@ -1,28 +0,0 @@ -attribute mediump vec2 aPosition; -uniform highp mat4 uMvpMatrix; -uniform highp vec3 uSize; -uniform mediump mat3 uAlignmentMatrix; -varying mediump vec2 vTexCoord; - -//Visual size and offset -uniform mediump vec2 offset; -uniform highp vec2 size; -uniform mediump vec4 offsetSizeMode; -uniform mediump vec2 origin; -uniform mediump vec2 anchorPoint; - -vec4 ComputeVertexPosition() -{ - vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ); - vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy); - return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 ); -} - -void main() -{ - mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0); - vertexPosition.xyz *= uSize; - gl_Position = uMvpMatrix * ComputeVertexPosition(); - - vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy; -} diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-atlas-clamp-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-atlas-clamp-shader.frag deleted file mode 100644 index 0d87f9d..0000000 --- a/dali-toolkit/internal/graphics/shaders/image-visual-atlas-clamp-shader.frag +++ /dev/null @@ -1,13 +0,0 @@ -INPUT mediump vec2 vTexCoord; - -uniform sampler2D sTexture; -uniform mediump vec4 uAtlasRect; -uniform lowp vec4 uColor; -uniform lowp vec3 mixColor; -uniform lowp float preMultipliedAlpha; - -void main() -{ - mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw ); - OUT_COLOR = TEXTURE( sTexture, texCoord ) * uColor * vec4( mixColor, 1.0 ); -} \ No newline at end of file diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-atlas-various-wrap-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-atlas-various-wrap-shader.frag deleted file mode 100644 index eeb8a0c..0000000 --- a/dali-toolkit/internal/graphics/shaders/image-visual-atlas-various-wrap-shader.frag +++ /dev/null @@ -1,28 +0,0 @@ -INPUT mediump vec2 vTexCoord; - -uniform sampler2D sTexture; -uniform mediump vec4 uAtlasRect; - -// WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT; -uniform lowp vec2 wrapMode; - -uniform lowp vec4 uColor; -uniform lowp vec3 mixColor; -uniform lowp float preMultipliedAlpha; -mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp float wrap ) - -{ - mediump float coord; - if( wrap > 1.5 )\n // REFLECT - coord = 1.0-abs(fract(coordinate*0.5)*2.0 - 1.0); - else \n// warp == 0 or 1 - coord = mix(coordinate, fract( coordinate ), wrap); - return clamp( mix(range.x, range.y, coord), range.x, range.y ); -} - -void main() -{ - mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ), - wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) ); - OUT_COLOR = TEXTURE( sTexture, texCoord ) * uColor * vec4( mixColor, 1.0 ); -} \ No newline at end of file diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-no-atlas-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-no-atlas-shader.frag deleted file mode 100644 index ffc960c..0000000 --- a/dali-toolkit/internal/graphics/shaders/image-visual-no-atlas-shader.frag +++ /dev/null @@ -1,11 +0,0 @@ -INPUT mediump vec2 vTexCoord; - -uniform sampler2D sTexture; -uniform lowp vec4 uColor; -uniform lowp vec3 mixColor; -uniform lowp float preMultipliedAlpha; - -void main() -{ - OUT_COLOR = TEXTURE( sTexture, vTexCoord ) * uColor * vec4( mixColor, 1.0 ); -} diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.frag deleted file mode 100644 index 6eacb93..0000000 --- a/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.frag +++ /dev/null @@ -1,45 +0,0 @@ -INPUT mediump vec2 vTexCoord; -INPUT mediump vec2 vPosition; -INPUT mediump vec2 vRectSize; -INPUT mediump vec2 vOptRectSize; -INPUT mediump vec4 vCornerRadius; - -uniform sampler2D sTexture; -uniform lowp vec4 uColor; -uniform lowp vec3 mixColor; -uniform lowp float preMultipliedAlpha; - -void main() -{ - if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) - { - OUT_COLOR = TEXTURE(sTexture, vTexCoord) * uColor * vec4(mixColor, 1.0); - return; - } - mediump float radius = - mix( - mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5), - mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5), - sign(vPosition.y) * 0.5 + 0.5 - ); - - mediump vec2 diff = abs(vPosition) - vRectSize + radius; - mediump float dist = length(max(diff, vec2(0.0))) - radius; - mediump float opacity = 1.0; - if(dist > 1.0) - { - opacity = 0.0; - } - else if(dist > -1.0) - { - if(min(diff.x, diff.y) < 0.0) - { - dist += min(diff.x, diff.y) / max(radius, 1.0); - } - opacity = 1.0 - smoothstep(-1.0, 1.0, dist); - } - - OUT_COLOR = TEXTURE(sTexture, vTexCoord) * uColor * vec4(mixColor, 1.0); - OUT_COLOR.a *= opacity; - OUT_COLOR.rgb *= mix(1.0, opacity, preMultipliedAlpha); -} diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.vert b/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.vert deleted file mode 100644 index c35b1b6..0000000 --- a/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.vert +++ /dev/null @@ -1,41 +0,0 @@ -INPUT mediump vec2 aPosition; -OUTPUT mediump vec2 vTexCoord; -OUTPUT mediump vec2 vPosition; -OUTPUT mediump vec2 vRectSize; -OUTPUT mediump vec2 vOptRectSize; -OUTPUT mediump vec4 vCornerRadius; - -uniform highp mat4 uMvpMatrix; -uniform highp vec3 uSize; -uniform mediump vec4 pixelArea; - -//Visual size and offset -uniform mediump vec2 offset; -uniform highp vec2 size; -uniform mediump vec4 offsetSizeMode; -uniform mediump vec2 origin; -uniform mediump vec2 anchorPoint; -uniform mediump vec4 cornerRadius; -uniform mediump float cornerRadiusPolicy; -uniform mediump vec2 extraSize; - -vec4 ComputeVertexPosition() -{ - vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw) + extraSize; - vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy); - mediump float minSize = min(visualSize.x, visualSize.y); - vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy); - vCornerRadius = min(vCornerRadius, minSize * 0.5); - vRectSize = visualSize * 0.5; - // Optimize fragment shader - mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w)); - vOptRectSize = vRectSize - 0.2929 * maxRadius - 1.0; - vPosition = aPosition* visualSize; - return vec4(vPosition + anchorPoint*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0); -} - -void main() -{ - gl_Position = uMvpMatrix * ComputeVertexPosition(); - vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5)); -} diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag new file mode 100644 index 0000000..e83d463 --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag @@ -0,0 +1,224 @@ +#ifndef IS_REQUIRED_ROUNDED_CORNER +#define IS_REQUIRED_ROUNDED_CORNER 0 +#endif +#ifndef IS_REQUIRED_BORDERLINE +#define IS_REQUIRED_BORDERLINE 0 +#endif +#ifndef ATLAS_DEFAULT_WARP +#define ATLAS_DEFAULT_WARP 0 +#endif +#ifndef ATLAS_CUSTOM_WARP +#define ATLAS_CUSTOM_WARP 0 +#endif + +INPUT mediump vec2 vTexCoord; +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE +INPUT mediump vec2 vPosition; +INPUT mediump vec2 vRectSize; +INPUT mediump vec2 vOptRectSize; +#if IS_REQUIRED_ROUNDED_CORNER +INPUT mediump vec4 vCornerRadius; +#endif +#endif + +uniform sampler2D sTexture; +#if ATLAS_DEFAULT_WARP +uniform mediump vec4 uAtlasRect; +#elif ATLAS_CUSTOM_WARP +// WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT; +uniform lowp vec2 wrapMode; +#endif + +uniform lowp vec4 uColor; +uniform lowp vec3 mixColor; +uniform lowp float preMultipliedAlpha; +#if IS_REQUIRED_BORDERLINE +uniform mediump float borderlineWidth; +uniform mediump float borderlineOffset; +uniform lowp vec4 borderlineColor; +#endif + +#if ATLAS_CUSTOM_WARP +mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp float wrap ) +{ + mediump float coord; + if( wrap > 1.5 ) /* REFLECT */ + coord = 1.0 - abs(fract(coordinate*0.5)*2.0 - 1.0); + else /* warp is 0 or 1 */ + coord = mix(coordinate, fract(coordinate), wrap); + return clamp(mix(range.x, range.y, coord), range.x, range.y); +} +#endif + +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE +// Global values both rounded corner and borderline use + +// radius of rounded corner on this quadrant +mediump float gRadius = 0.0; + +// fragment coordinate. NOTE : vec2(0.0, 0.0) is vRectSize, the corner of visual +mediump vec2 gFragmentPosition = vec2(0.0, 0.0); +// center coordinate of rounded corner circle. vec2(gCenterPosition, gCenterPosition). +mediump float gCenterPosition = 0.0; +// relative coordinate of gFragmentPosition from gCenterPosition. +mediump vec2 gDiff = vec2(0.0, 0.0); +// potential value what our algorithm use. +mediump float gPotential = 0.0; + +// threshold of potential +mediump float gPotentialRange = 0.0; +mediump float gMaxOutlinePotential = 0.0; +mediump float gMinOutlinePotential = 0.0; +mediump float gMaxInlinePotential = 0.0; +mediump float gMinInlinePotential = 0.0; + +void calculateCornerRadius() +{ +#if IS_REQUIRED_ROUNDED_CORNER + gRadius = + mix( + mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5), + mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5), + sign(vPosition.y) * 0.5 + 0.5 + ); +#endif +} + +void calculatePosition() +{ + gFragmentPosition = abs(vPosition) - vRectSize; + gCenterPosition = -gRadius; +#if IS_REQUIRED_BORDERLINE + gCenterPosition += borderlineWidth * (clamp(borderlineOffset, -1.0, 1.0) + 1.0) * 0.5; +#endif + gDiff = gFragmentPosition - gCenterPosition; +} + +void calculatePotential() +{ + gPotential = length(max(gDiff, 0.0)) + min(0.0, max(gDiff.x, gDiff.y)); +} + +void setupMinMaxPotential() +{ + gPotentialRange = 1.0; + + gMaxOutlinePotential = gRadius + gPotentialRange; + gMinOutlinePotential = gRadius - gPotentialRange; + +#if IS_REQUIRED_BORDERLINE + gMaxInlinePotential = gMaxOutlinePotential - borderlineWidth; + gMinInlinePotential = gMinOutlinePotential - borderlineWidth; +#else + gMaxInlinePotential = gMaxOutlinePotential; + gMinInlinePotential = gMinOutlinePotential; +#endif + + // reduce defect near edge of rounded corner. + gMaxOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0); + gMinOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0); +} + +void PreprocessPotential() +{ + calculateCornerRadius(); + calculatePosition(); + calculatePotential(); + + setupMinMaxPotential(); +} +#endif + +#if IS_REQUIRED_BORDERLINE +lowp vec4 convertBorderlineColor(lowp vec4 textureColor) +{ + mediump float potential = gPotential; + + // default opacity of borderline is 0.0 + mediump float borderlineOpacity = 0.0; + + // calculate borderline opacity by potential + if(potential > gMinInlinePotential) + { + // potential is inside borderline range. + borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential); + } + + //calculate inside of borderline when outilneColor.a < 1.0 + if(borderlineColor.a < 1.0) + { + mediump float tCornerRadius = -gCenterPosition; + mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange; + mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange; + if(potential > MaxTexturelinePotential) + { + // potential is out of texture range. use borderline color instead of texture + textureColor = vec4(borderlineColor.xyz, 0.0); + } + else if(potential > MinTexturelinePotential) + { + // potential is in texture range + textureColor = mix(textureColor, vec4(borderlineColor.xyz, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential)); + } + borderlineOpacity *= borderlineColor.a; + } + return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity); +} +#endif + +#if IS_REQUIRED_ROUNDED_CORNER +mediump float calculateCornerOpacity() +{ + mediump float potential = gPotential; + + // default opacity is 1.0 + mediump float opacity = 1.0; + + // calculate borderline opacity by potential + if(potential > gMaxOutlinePotential) + { + // potential is out of borderline range + opacity = 0.0; + } + else if(potential > gMinOutlinePotential) + { + opacity = 1.0 - smoothstep(gMinOutlinePotential, gMaxOutlinePotential, potential); + } + return opacity; +} +#endif + +void main() +{ +#if ATLAS_DEFAULT_WARP + mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw ); +#elif ATLAS_CUSTOM_WARP + mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ), + wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) ); +#else + mediump vec2 texCoord = vTexCoord; +#endif + + lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * uColor * vec4( mixColor, 1.0 ); + +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE + // skip most potential calculate for performance + if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) + { + OUT_COLOR = textureColor; + return; + } + PreprocessPotential(); +#endif + +#if IS_REQUIRED_BORDERLINE + textureColor = convertBorderlineColor(textureColor); +#endif + OUT_COLOR = textureColor; + +#if IS_REQUIRED_ROUNDED_CORNER + mediump float opacity = calculateCornerOpacity(); + OUT_COLOR.a *= opacity; + OUT_COLOR.rgb *= mix(1.0, opacity, preMultipliedAlpha); +#endif +} diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert b/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert index fe0c35c..21d4084 100644 --- a/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert +++ b/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert @@ -1,5 +1,20 @@ +#ifndef IS_REQUIRED_ROUNDED_CORNER +#define IS_REQUIRED_ROUNDED_CORNER 0 +#endif +#ifndef IS_REQUIRED_BORDERLINE +#define IS_REQUIRED_BORDERLINE 0 +#endif + INPUT mediump vec2 aPosition; OUTPUT mediump vec2 vTexCoord; +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE +OUTPUT mediump vec2 vPosition; +OUTPUT mediump vec2 vRectSize; +OUTPUT mediump vec2 vOptRectSize; +#if IS_REQUIRED_ROUNDED_CORNER +OUTPUT mediump vec4 vCornerRadius; +#endif +#endif uniform highp mat4 uMvpMatrix; uniform highp vec3 uSize; @@ -11,17 +26,53 @@ uniform highp vec2 size; uniform mediump vec4 offsetSizeMode; uniform mediump vec2 origin; uniform mediump vec2 anchorPoint; +#if IS_REQUIRED_BORDERLINE +uniform mediump float borderlineWidth; +uniform mediump float borderlineOffset; +#endif +#if IS_REQUIRED_ROUNDED_CORNER +uniform mediump vec4 cornerRadius; +uniform mediump float cornerRadiusPolicy; +#endif uniform mediump vec2 extraSize; vec4 ComputeVertexPosition() { - vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize; - vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy); - return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 ); + vec2 visualSize = mix(uSize.xy * size, size, offsetSizeMode.zw) + extraSize; + vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy); + +#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE + vRectSize = visualSize * 0.5; + vOptRectSize = vRectSize; +#endif + +#if IS_REQUIRED_ROUNDED_CORNER +#if IS_REQUIRED_BORDERLINE + mediump float minSize = min(visualSize.x, visualSize.y) + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth; +#else + mediump float minSize = min(visualSize.x, visualSize.y); +#endif + vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy); + vCornerRadius = min(vCornerRadius, minSize * 0.5); + // Optimize fragment shader. 0.2929 ~= 1.0 - sqrt(0.5) + mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w)); + vOptRectSize -= 0.2929 * maxRadius + 1.0; +#endif + +#if IS_REQUIRED_BORDERLINE + vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth); + vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0; +#elif IS_REQUIRED_ROUNDED_CORNER + vPosition = aPosition * visualSize; +#else + mediump vec2 vPosition = aPosition * visualSize; +#endif + + vTexCoord = pixelArea.xy + pixelArea.zw * (vPosition.xy / max(vec2(1.0), visualSize) + vec2(0.5)); + return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0); } void main() { gl_Position = uMvpMatrix * ComputeVertexPosition(); - vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) ); -} \ No newline at end of file +} diff --git a/dali-toolkit/internal/text/text-controller-relayouter.cpp b/dali-toolkit/internal/text/text-controller-relayouter.cpp index 78e7331..134a327 100644 --- a/dali-toolkit/internal/text/text-controller-relayouter.cpp +++ b/dali-toolkit/internal/text/text-controller-relayouter.cpp @@ -291,7 +291,10 @@ float Controller::Relayouter::GetHeightForWidth(Controller& controller, float wi // The implementation of Get LineCount property depends on calling GetHeightForWidth then read mLines.Count() from visualModel direct. // If the LineCount property is requested before rendering and layouting then the value will be zero, which is incorrect. // So we will not restore the previously backed-up mLines and mGlyphPositions from visualModel in such case. - bool restoreLinesAndGlyphPositions = visualModel->mControlSize.width>0 && visualModel->mControlSize.height>0; + // Another case to skip restore is when the requested width equals the Control's width which means the caller need to update the old values. + // For example, when the text is changed. + bool restoreLinesAndGlyphPositions = (visualModel->mControlSize.width>0 && visualModel->mControlSize.height>0) + && (visualModel->mControlSize.width != width); layoutSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeRequestedWidthAndMaxHeight, requestedOperationsMask, restoreLinesAndGlyphPositions); diff --git a/dali-toolkit/internal/transition/transition-base-impl.cpp b/dali-toolkit/internal/transition/transition-base-impl.cpp new file mode 100644 index 0000000..42fb10d --- /dev/null +++ b/dali-toolkit/internal/transition/transition-base-impl.cpp @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +namespace +{ +const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION(Dali::AlphaFunction::DEFAULT); + +Property::Map GetOriginalProperties(Dali::Toolkit::Control control) +{ + Property::Map propertyMap; + propertyMap.Insert(Dali::Actor::Property::ANCHOR_POINT, control[Dali::Actor::Property::ANCHOR_POINT]); + propertyMap.Insert(Dali::Actor::Property::PARENT_ORIGIN, control[Dali::Actor::Property::PARENT_ORIGIN]); + propertyMap.Insert(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT, control[Dali::Actor::Property::POSITION_USES_ANCHOR_POINT]); + propertyMap.Insert(Dali::Actor::Property::INHERIT_POSITION, control[Dali::Actor::Property::INHERIT_POSITION]); + propertyMap.Insert(Dali::Actor::Property::INHERIT_ORIENTATION, control[Dali::Actor::Property::INHERIT_ORIENTATION]); + propertyMap.Insert(Dali::Actor::Property::INHERIT_SCALE, control[Dali::Actor::Property::INHERIT_SCALE]); + propertyMap.Insert(Dali::Actor::Property::COLOR_MODE, control[Dali::Actor::Property::COLOR_MODE]); + propertyMap.Insert(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, control[Dali::Actor::Property::HEIGHT_RESIZE_POLICY]); + propertyMap.Insert(Dali::Actor::Property::WIDTH_RESIZE_POLICY, control[Dali::Actor::Property::WIDTH_RESIZE_POLICY]); + propertyMap.Insert(Dali::Actor::Property::POSITION, control[Dali::Actor::Property::POSITION]); + propertyMap.Insert(Dali::Actor::Property::ORIENTATION, control[Dali::Actor::Property::ORIENTATION]); + propertyMap.Insert(Dali::Actor::Property::SCALE, control[Dali::Actor::Property::SCALE]); + propertyMap.Insert(Dali::Actor::Property::COLOR, control[Dali::Actor::Property::COLOR]); + + return propertyMap; +} + +/** + * @brief Computes and center position by using transform properties. + * @param[in] anchorPoint anchorPoint of an actor. + * @param[in] positionUsesAnchorPoint positionUsesAnchorPoint of an actor. + * @param[in] size size of an actor. + * @param[in] scale scale of an actor. + * @param[in] orientation orientation of an actor. + */ +Vector3 CalculateCenterPosition( + const Vector3& anchorPoint, + const bool positionUsesAnchorPoint, + const Vector3& size, + const Vector3& scale, + const Quaternion& orientation) +{ + Vector3 centerPosition; + const Vector3 half(0.5f, 0.5f, 0.5f); + const Vector3 topLeft(0.0f, 0.0f, 0.5f); + // Calculate the center-point by applying the scale and rotation on the anchor point. + centerPosition = (half - anchorPoint) * size * scale; + centerPosition *= orientation; + + // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position. + if(!positionUsesAnchorPoint) + { + centerPosition -= (topLeft - anchorPoint) * size; + } + return centerPosition; +} + +} // anonymous namespace + +TransitionBasePtr TransitionBase::New() +{ + TransitionBasePtr transition = new TransitionBase(); + + // Second-phase construction + transition->Initialize(); + + return transition; +} + +TransitionBase::TransitionBase() +: mAlphaFunction(DEFAULT_ALPHA_FUNCTION), + mTimePeriod(TimePeriod(0.0f)), + mTransitionWithChild(false), + mMoveTargetChildren(false) +{ +} + +void TransitionBase::Initialize() +{ + RegisterObject(); +} + +void TransitionBase::SetTimePeriod(const Dali::TimePeriod& timePeriod) +{ + if(timePeriod.durationSeconds < 0.0f) + { + DALI_LOG_WARNING("Duration should be greater than 0.0f.\n"); + } + else + { + mTimePeriod.durationSeconds = timePeriod.durationSeconds; + } + + if(timePeriod.delaySeconds < 0.0f) + { + DALI_LOG_WARNING("Delay should be greater than 0.0f.\n"); + return; + } + else + { + mTimePeriod.delaySeconds = timePeriod.delaySeconds; + } +} + +Dali::TimePeriod TransitionBase::GetTimePeriod() const +{ + return mTimePeriod; +} + +void TransitionBase::TransitionWithChild(bool transitionWithChild) +{ + mTransitionWithChild = transitionWithChild; +} + +void TransitionBase::PreProcess(Dali::Animation animation) +{ + mAnimation = animation; + // Retrieve original property map of mTarget to backup and to reset after transition is finished. + mOriginalPropertyMap = GetOriginalProperties(mTarget); + mMoveTargetChildren = false; + if(!mTransitionWithChild && mTarget.GetChildCount() > 0) + { + mMoveTargetChildren = true; + CopyTarget(); + } + GetImplementation(mTarget).SetTransparent(false); +} + +void TransitionBase::Play() +{ + if(!mTarget[Dali::Actor::Property::CONNECTED_TO_SCENE]) + { + DALI_LOG_ERROR("The target is not added on the window\n"); + return; + } + + OnPlay(); + + SetAnimation(); +} + +void TransitionBase::SetAnimation() +{ + if(!mAnimation) + { + DALI_LOG_ERROR("animation is not initialized\n"); + return; + } + + for(uint32_t i = 0; i < mStartPropertyMap.Count(); ++i) + { + Property::Value* initialValuePointer = mInitialPropertyMap.Find(mStartPropertyMap.GetKeyAt(i).indexKey); + Property::Value* finishValue = mFinishPropertyMap.Find(mStartPropertyMap.GetKeyAt(i).indexKey); + if(finishValue) + { + Property::Value initialValue = mStartPropertyMap.GetValue(i); + if(initialValuePointer) + { + initialValue = *initialValuePointer; + } + AnimateBetween(mTarget, mStartPropertyMap.GetKeyAt(i).indexKey, initialValue, mStartPropertyMap.GetValue(i), *finishValue); + } + } +} + +void TransitionBase::AnimateBetween(Dali::Toolkit::Control target, Property::Index index, Property::Value initialValue, Property::Value sourceValue, Property::Value destinationValue) +{ + if(mAnimation) + { + if(mTimePeriod.delaySeconds>0.0f) + { + Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New(); + initialKeyframes.Add(0.0f, initialValue); + initialKeyframes.Add(1.0f, initialValue); + mAnimation.AnimateBetween(Property(target, index), initialKeyframes, TimePeriod(mTimePeriod.delaySeconds)); + } + Dali::KeyFrames keyframes = Dali::KeyFrames::New(); + keyframes.Add(0.0f, sourceValue); + keyframes.Add(1.0f, destinationValue); + mAnimation.AnimateBetween(Property(target, index), keyframes, mAlphaFunction, mTimePeriod); + } +} + +void TransitionBase::CopyTarget() +{ + mCopiedActor = Dali::Actor::New(); + mTarget.GetParent().Add(mCopiedActor); + mCopiedActor[Dali::DevelActor::Property::SIBLING_ORDER] = static_cast(mTarget[Dali::DevelActor::Property::SIBLING_ORDER]) + 1; + for(uint32_t i = 0; i < mTarget.GetChildCount(); ++i) + { + Dali::Actor child = mTarget.GetChildAt(i); + Dali::DevelActor::SwitchParent(child, mCopiedActor); + } + + // Copy Size property to mCopiedActor because Size is not included mOriginalPropertyMap. + mCopiedActor[Dali::Actor::Property::SIZE] = mTarget.GetProperty(Dali::Actor::Property::SIZE); + mCopiedActor.SetProperties(mOriginalPropertyMap); +} + +void TransitionBase::TransitionFinished() +{ + OnFinished(); + + mTarget.SetProperties(mOriginalPropertyMap); + if(mMoveTargetChildren) + { + for(uint32_t i = 0; i < mCopiedActor.GetChildCount(); ++i) + { + Dali::Actor child = mCopiedActor.GetChildAt(i); + Dali::DevelActor::SwitchParent(child, mTarget); + } + mCopiedActor.Unparent(); + mCopiedActor.Reset(); + } + mAnimation.Reset(); +} + +Matrix TransitionBase::GetWorldTransform(Dali::Actor actor) +{ + enum InheritanceMode + { + DONT_INHERIT_TRANSFORM = 0, + INHERIT_POSITION = 1, + INHERIT_SCALE = 2, + INHERIT_ORIENTATION = 4, + INHERIT_ALL = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION, + }; + + std::vector descentList; + std::vector inheritanceModeList; + Dali::Actor currentActor = actor; + int inheritance = 0; + do + { + inheritance = (static_cast(currentActor.GetProperty(Dali::Actor::Property::INHERIT_ORIENTATION)) << 2) + + (static_cast(currentActor.GetProperty(Dali::Actor::Property::INHERIT_SCALE)) << 1) + + static_cast(currentActor.GetProperty(Dali::Actor::Property::INHERIT_POSITION)); + inheritanceModeList.push_back(static_cast(inheritance)); + descentList.push_back(currentActor); + currentActor = currentActor.GetParent(); + } while(inheritance != DONT_INHERIT_TRANSFORM && currentActor); + + Matrix worldMatrix; + Vector3 localPosition; + for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i) + { + Vector3 anchorPoint = descentList[i].GetProperty(Dali::Actor::Property::ANCHOR_POINT); + Vector3 parentOrigin = descentList[i].GetProperty(Dali::Actor::Property::PARENT_ORIGIN); + bool positionUsesAnchorPoint = descentList[i].GetProperty(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT); + Vector3 size = descentList[i].GetProperty(Dali::Actor::Property::SIZE); + Vector3 actorPosition = descentList[i].GetProperty(Dali::Actor::Property::POSITION); + Quaternion localOrientation = descentList[i].GetProperty(Dali::Actor::Property::ORIENTATION); + Vector3 localScale = descentList[i].GetProperty(Dali::Actor::Property::SCALE); + + Vector3 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation); + if(inheritanceModeList[i] != DONT_INHERIT_TRANSFORM && descentList[i].GetParent()) + { + Matrix localMatrix; + Vector3 parentSize = descentList[i + 1].GetProperty(Dali::Actor::Property::SIZE); + if(inheritanceModeList[i] == INHERIT_ALL) + { + localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize; + localMatrix.SetTransformComponents(localScale, localOrientation, localPosition); + + //Update the world matrix + Matrix tempMatrix; + Matrix::Multiply(tempMatrix, localMatrix, worldMatrix); + worldMatrix = tempMatrix; + } + else + { + Vector3 parentPosition, parentScale; + Quaternion parentOrientation; + worldMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale); + + if((inheritanceModeList[i] & INHERIT_SCALE) == 0) + { + //Don't inherit scale + localScale /= parentScale; + } + + if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0) + { + //Don't inherit orientation + parentOrientation.Invert(); + localOrientation = parentOrientation * localOrientation; + } + + if((inheritanceModeList[i] & INHERIT_POSITION) == 0) + { + localMatrix.SetTransformComponents(localScale, localOrientation, Vector3::ZERO); + Matrix tempMatrix; + Matrix::Multiply(tempMatrix, localMatrix, worldMatrix); + worldMatrix = tempMatrix; + worldMatrix.SetTranslation(actorPosition + centerPosition); + } + else + { + localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize; + localMatrix.SetTransformComponents(localScale, localOrientation, localPosition); + Matrix tempMatrix; + Matrix::Multiply(tempMatrix, localMatrix, worldMatrix); + worldMatrix = tempMatrix; + } + } + } + else + { + localPosition = actorPosition + centerPosition; + worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition); + } + } + + return worldMatrix; +} + +Vector4 TransitionBase::GetWorldColor(Dali::Actor actor) +{ + std::vector descentList; + std::vector inheritanceModeList; + Dali::Actor currentActor = actor; + Dali::ColorMode inheritance = Dali::ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA; + do + { + inheritance = currentActor.GetProperty(Dali::Actor::Property::COLOR_MODE); + inheritanceModeList.push_back(inheritance); + descentList.push_back(currentActor); + currentActor = currentActor.GetParent(); + } while(inheritance != Dali::ColorMode::USE_OWN_COLOR && currentActor); + + Vector4 worldColor; + for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i) + { + if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1) + { + worldColor = descentList[i].GetProperty(Dali::Actor::Property::COLOR); + } + else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA) + { + Vector4 ownColor = descentList[i].GetProperty(Dali::Actor::Property::COLOR); + worldColor = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a); + } + else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR) + { + Vector4 ownColor = descentList[i].GetProperty(Dali::Actor::Property::COLOR); + worldColor *= ownColor; + } + } + + return worldColor; +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/transition/transition-base-impl.h b/dali-toolkit/internal/transition/transition-base-impl.h new file mode 100644 index 0000000..84ef316 --- /dev/null +++ b/dali-toolkit/internal/transition/transition-base-impl.h @@ -0,0 +1,265 @@ +#ifndef DALI_TOOLKIT_INTERNAL_TRANSITION_BASE_H +#define DALI_TOOLKIT_INTERNAL_TRANSITION_BASE_H + +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +using TransitionBasePtr = IntrusivePtr; + +class TransitionBase : public BaseObject +{ +public: + /** + * @brief Create a new TransitionBase object. + * @return A smart-pointer to the newly allocated TransitionBase. + */ + static TransitionBasePtr New(); + + /** + * @copydoc Dali::Toolkit::TransitionBase::SetTimePeriod() + */ + void SetTimePeriod(const Dali::TimePeriod& timePeriod); + + /** + * @copydoc Dali::Toolkit::TransitionBase::GetTimePeriod() + */ + Dali::TimePeriod GetTimePeriod() const; + + /** + * @copydoc Dali::Toolkit::TransitionBase::SetAlphaFunction() + */ + void SetAlphaFunction(AlphaFunction alphaFunction) + { + mAlphaFunction = alphaFunction; + } + + /** + * @copydoc Dali::Toolkit::TransitionBase::GetAlphaFunction() + */ + AlphaFunction GetAlphaFunction() const + { + return mAlphaFunction; + } + + /** + * @copydoc Dali::Toolkit::TransitionBase::TransitionWithChild() + */ + void TransitionWithChild(bool transitionWithChild); + + /** + * @brief Run processes those are required done before size/position negotiation. + * @param[in] animation animation for the transition + */ + void PreProcess(Dali::Animation animation); + + /** + * @brief Make property animation for Transition + */ + void Play(); + + /** + * Emit the Finished signal + */ + void TransitionFinished(); + +protected: + /** + * @brief Set property map which will be used as a initial properties. + * @param[in] propertyMap propertyMap that will be used as a start value of transition. + */ + void SetInitialPropertyMap(const Property::Map& propertyMap) + { + mInitialPropertyMap = propertyMap; + } + /** + * @brief Set property map which will be used as a animation start properties. + * @param[in] propertyMap propertyMap that will be used as a start value of transition. + */ + void SetStartPropertyMap(const Property::Map& propertyMap) + { + mStartPropertyMap = propertyMap; + } + + /** + * @brief Set property map which will be used as a animation finish properties. + * @param[in] propertyMap propertyMap that will be used as a finish value of transition. + */ + void SetFinishPropertyMap(const Property::Map& propertyMap) + { + mFinishPropertyMap = propertyMap; + } + + /** + * @brief Retrieve animation. + */ + Dali::Animation GetAnimation() + { + return mAnimation; + } + + /** + * @brief Set target which will be transition. + * @param[in] target control that will be transition. + */ + void SetTarget(Dali::Toolkit::Control target) + { + mTarget = target; + } + + /** + * @brief Gets world transform of input Actor. + * @param[in] actor actor for get world transform. + */ + Matrix GetWorldTransform(Dali::Actor actor); + + /** + * @brief Gets world color of input Actor. + * @param[in] actor actor for get world color. + */ + Vector4 GetWorldColor(Dali::Actor actor); + + /** + * @brief Returns whether this transition will be applied to children of target or not. + */ + bool IsTransitionWithChild() + { + return mTransitionWithChild; + } + +protected: + /** + * Construct a new TransitionBase. + */ + TransitionBase(); + + /** + * Second-phase constructor. + */ + void Initialize(); + + /** + * Destructor + */ + ~TransitionBase() = default; + +private: + // Undefined + TransitionBase(const TransitionBase&); + + // Undefined + TransitionBase& operator=(const TransitionBase& rhs); + +private: + /** + * @brief Makes property animation for transition. + */ + void SetAnimation(); + + /** + * @brief Adds a property on an animation between sourceValue and destimationValue. + * @param[in] target target control to be animated. + * @param[in] index property index for animation. + * @param[in] initialValue initial value of animation. + * @param[in] sourceValue source value of animation. + * @param[in] destinationValue destination value of animation. + */ + void AnimateBetween(Dali::Toolkit::Control target, Property::Index index, Property::Value initialValue, Property::Value sourceValue, Property::Value destinationValue); + + /** + * @brief Copy target to make clone for the child Actors + */ + void CopyTarget(); + + /** + * @brief Make pair of Property::Map to be used for transition animation. + * Set the pair of Property::Map by using SetStartPropertyMap() and SetFinishPropertyMap(), + * then the properties of mTarget will be animated between them during transition duration. + * If the transition requires the information of world transform, let them be in this method. + * World transform and World color can be retrieved by using GetWorldTransform() and GetWorldColor() methods. + * And If it is needed to add additional custom animation than use GetAnimation() and add them. + * + * @note Do not set any properties in this methods. + */ + virtual void OnPlay() + { + } + + /** + * @brief If the transition is needed to do something after the transition is finished, let them be in this method. + */ + virtual void OnFinished() + { + } + +private: + Dali::Toolkit::Control mTarget; ///< Target that will be animated. + Dali::Actor mCopiedActor; ///< Copied View that will replace mTarget during transition + Dali::Animation mAnimation; ///< Property animations for the transition of mTarget + AlphaFunction mAlphaFunction; ///< Alpha function that will applied for the property animation + Property::Map mInitialPropertyMap; ///< Initial properties to be animated. (world transform) + Property::Map mStartPropertyMap; ///< Start properties to be animated. (world transform) + Property::Map mFinishPropertyMap; ///< Finish properties to be animated. (world transform) + Property::Map mOriginalPropertyMap; ///< Original properties of mTarget to be used to restore after the transition is finished. + Dali::TimePeriod mTimePeriod; ///< TimePeriod of transition + bool mTransitionWithChild; ///< True, if mTarget transition is inherit to its child Actors. + ///< If this is false, the child Actors are moved to the child of mCopiedActor that will have original properties of target Actor during Transition. + bool mMoveTargetChildren; ///< Flag, if mTransitionWithChild is false and mTarget has children than True. +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Internal::TransitionBase& GetImplementation(Dali::Toolkit::TransitionBase& animation) +{ + DALI_ASSERT_ALWAYS(animation && "TransitionBase handle is empty"); + + BaseObject& handle = animation.GetBaseObject(); + + return static_cast(handle); +} + +inline const Internal::TransitionBase& GetImplementation(const Dali::Toolkit::TransitionBase& animation) +{ + DALI_ASSERT_ALWAYS(animation && "TransitionBase handle is empty"); + + const BaseObject& handle = animation.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_INTERNAL_TRANSITION_BASE_H diff --git a/dali-toolkit/internal/transition/transition-impl.cpp b/dali-toolkit/internal/transition/transition-impl.cpp new file mode 100644 index 0000000..ef193f6 --- /dev/null +++ b/dali-toolkit/internal/transition/transition-impl.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +namespace +{ +const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION(Dali::AlphaFunction::DEFAULT); + +} // anonymous namespace + +TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod) +{ + float delaySeconds = timePeriod.delaySeconds; + if(delaySeconds < 0.0f) + { + DALI_LOG_WARNING("delay should be greater than 0.0f.\n"); + delaySeconds = 0.0f; + } + + float durationSeconds = timePeriod.durationSeconds; + if(durationSeconds < 0.0f) + { + DALI_LOG_WARNING("duration should be greater than 0.0f.\n"); + durationSeconds = 0.0f; + } + + TransitionPtr transition = new Transition(source, destination, TimePeriod(delaySeconds, durationSeconds)); + + // Second-phase construction + transition->Initialize(); + + return transition; +} + +Transition::Transition(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod) +: TransitionBase(), + mSourceControl(source), + mDestinationControl(destination) +{ + SetTarget(destination); + SetTimePeriod(timePeriod); +} + +Transition::~Transition() +{ +} + +void Transition::OnPlay() +{ + if(!mSourceControl[Dali::Actor::Property::CONNECTED_TO_SCENE] || + !mDestinationControl[Dali::Actor::Property::CONNECTED_TO_SCENE]) + { + DALI_LOG_ERROR("The source or destination is not added on the window\n"); + return; + } + + //Make startPropertyMap and finishPropertyMap to use for property animation. + Matrix sourceWorldTransform = mSourceControl[Dali::Actor::Property::WORLD_MATRIX]; + Vector3 sourcePosition, sourceScale; + Quaternion sourceOrientation; + sourceWorldTransform.GetTransformComponents(sourcePosition, sourceOrientation, sourceScale); + + Matrix destinationWorldTransform = GetWorldTransform(mDestinationControl); + Vector3 destinationPosition, destinationScale; + Quaternion destinationOrientation; + destinationWorldTransform.GetTransformComponents(destinationPosition, destinationOrientation, destinationScale); + + Vector3 targetSize = mDestinationControl[Dali::Actor::Property::SIZE]; + Vector4 targetColor = GetWorldColor(mDestinationControl); + Property::Map startPropertyMap; + Property::Map finishPropertyMap; + + // Use world transform if this transition requires animation of transform. + mDestinationControl[Dali::Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER; + mDestinationControl[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER; + mDestinationControl[Dali::Actor::Property::POSITION_USES_ANCHOR_POINT] = true; + mDestinationControl[Dali::Actor::Property::INHERIT_POSITION] = false; + mDestinationControl[Dali::Actor::Property::INHERIT_ORIENTATION] = false; + mDestinationControl[Dali::Actor::Property::INHERIT_SCALE] = false; + mDestinationControl[Dali::Actor::Property::COLOR_MODE] = Dali::ColorMode::USE_OWN_COLOR; + + // Set animation of Transform + startPropertyMap.Insert(Dali::Actor::Property::POSITION, sourcePosition); + finishPropertyMap.Insert(Dali::Actor::Property::POSITION, destinationPosition); + + startPropertyMap.Insert(Dali::Actor::Property::ORIENTATION, sourceOrientation); + finishPropertyMap.Insert(Dali::Actor::Property::ORIENTATION, destinationOrientation); + + startPropertyMap.Insert(Dali::Actor::Property::SCALE, sourceScale); + finishPropertyMap.Insert(Dali::Actor::Property::SCALE, destinationScale); + + Vector4 sourceColor = mSourceControl.GetCurrentProperty(Dali::Actor::Property::WORLD_COLOR); + startPropertyMap.Insert(Dali::Actor::Property::COLOR, sourceColor); + finishPropertyMap.Insert(Dali::Actor::Property::COLOR, targetColor); + + // Set animation for other properties if source and destination is different. + Vector3 sourceSize = mSourceControl.GetCurrentProperty(Dali::Actor::Property::SIZE); + if(sourceSize != targetSize) + { + startPropertyMap.Insert(Dali::Actor::Property::SIZE, sourceSize); + finishPropertyMap.Insert(Dali::Actor::Property::SIZE, targetSize); + } + + SetStartPropertyMap(startPropertyMap); + SetFinishPropertyMap(finishPropertyMap); + + // source View becomes transparent during transition. + if(IsTransitionWithChild()) + { + mSourceControl[Dali::Actor::Property::VISIBLE] = false; + } + else + { + GetImplementation(mSourceControl).SetTransparent(true); + } + + Dali::Animation animation = GetAnimation(); + if(!animation) + { + DALI_LOG_ERROR("animation is still not initialized\n"); + return; + } + Dali::Toolkit::DevelControl::CreateTransitions(mDestinationControl, animation, mSourceControl, GetAlphaFunction(), GetTimePeriod()); +} + +void Transition::OnFinished() +{ + if(IsTransitionWithChild()) + { + mSourceControl[Dali::Actor::Property::VISIBLE] = true; + } + else + { + GetImplementation(mSourceControl).SetTransparent(false); + } +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/transition/transition-impl.h b/dali-toolkit/internal/transition/transition-impl.h new file mode 100644 index 0000000..d9120bf --- /dev/null +++ b/dali-toolkit/internal/transition/transition-impl.h @@ -0,0 +1,108 @@ +#ifndef DALI_TOOLKIT_INTERNAL_TRANSITION_H +#define DALI_TOOLKIT_INTERNAL_TRANSITION_H + +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +using TransitionPtr = IntrusivePtr; + +class Transition : public TransitionBase +{ +public: + /** + * @brief Create a new Transition object. + * @param[in] source A source control of this transition. + * @param[in] destination A destination control of this transition. + * @param[in] durationSeconds The duration of the animation. + * @return A smart-pointer to the newly allocated Transition. + */ + static TransitionPtr New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod); + +protected: + /** + * @copydoc Dali::Toolkit::Transition::OnPlay() + */ + void OnPlay() override; + + /** + * @brief Emit the Finished signal + */ + void OnFinished() override; + +protected: + /** + * @brief Construct a new Transition. + */ + Transition(Dali::Toolkit::Control source, + Dali::Toolkit::Control destination, + TimePeriod timePeriod); + + /** + * @brief A reference counted object may only be deleted by calling Unreference() + */ + ~Transition() override; + +private: + // Undefined + Transition(const Transition&); + + // Undefined + Transition& operator=(const Transition& rhs); + +private: + Dali::Toolkit::Control mSourceControl; + Dali::Toolkit::Control mDestinationControl; +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Internal::Transition& GetImplementation(Dali::Toolkit::Transition& transition) +{ + DALI_ASSERT_ALWAYS(transition && "Transition handle is empty"); + + BaseObject& handle = transition.GetBaseObject(); + + return static_cast(handle); +} + +inline const Internal::Transition& GetImplementation(const Dali::Toolkit::Transition& transition) +{ + DALI_ASSERT_ALWAYS(transition && "Transition handle is empty"); + + const BaseObject& handle = transition.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_INTERNAL_TRANSITION_H diff --git a/dali-toolkit/internal/transition/transition-lifecycle-controller.cpp b/dali-toolkit/internal/transition/transition-lifecycle-controller.cpp new file mode 100644 index 0000000..1a8c238 --- /dev/null +++ b/dali-toolkit/internal/transition/transition-lifecycle-controller.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +void TransitionLifecycleController::AddTransitions(Dali::Toolkit::TransitionSet transitions) +{ + mTransitionList.push_back(transitions); + transitions.FinishedSignal().Connect(this, &TransitionLifecycleController::RemoveTransitions); +} + +void TransitionLifecycleController::RemoveTransitions(Dali::Toolkit::TransitionSet &transitions) +{ + mTransitionList.erase(std::remove(mTransitionList.begin(), mTransitionList.end(), transitions)); +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/transition/transition-lifecycle-controller.h b/dali-toolkit/internal/transition/transition-lifecycle-controller.h new file mode 100644 index 0000000..8511635 --- /dev/null +++ b/dali-toolkit/internal/transition/transition-lifecycle-controller.h @@ -0,0 +1,83 @@ +#ifndef DALI_TOOLKIT_INTERNAL_TRANSITION_PLAYLIST_H +#define DALI_TOOLKIT_INTERNAL_TRANSITION_PLAYLIST_H + +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +class TransitionLifecycleController; + +namespace +{ +std::unique_ptr instance = nullptr; +std::once_flag onceFlag; +} // namespace + +class TransitionLifecycleController : public ConnectionTracker +{ +public: + static TransitionLifecycleController& GetInstance() + { + std::call_once(onceFlag, []() { + instance.reset(new TransitionLifecycleController); + }); + return *(instance.get()); + } + + void AddTransitions(Dali::Toolkit::TransitionSet transitions); + +private: + + void RemoveTransitions(Dali::Toolkit::TransitionSet &transitions); + + /** + * Construct a new TransitionLifecycleController. + */ + TransitionLifecycleController() = default; + + // Undefined + TransitionLifecycleController(const TransitionLifecycleController&) = delete; + + // Undefined + TransitionLifecycleController& operator=(const TransitionLifecycleController& rhs) = delete; + +private: + std::vector mTransitionList; +}; + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_INTERNAL_TRANSITION_PLAYLIST_H +; \ No newline at end of file diff --git a/dali-toolkit/internal/transition/transition-set-impl.cpp b/dali-toolkit/internal/transition/transition-set-impl.cpp new file mode 100644 index 0000000..ad7ca62 --- /dev/null +++ b/dali-toolkit/internal/transition/transition-set-impl.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +namespace +{ +// Signals +static constexpr std::string_view SIGNAL_FINISHED = "finished"; + +BaseHandle Create() +{ + return Dali::Toolkit::TransitionSet::New(); +} + +TypeRegistration mType(typeid(Dali::Toolkit::TransitionSet), typeid(Dali::BaseHandle), Create); + +SignalConnectorType signalConnector1(mType, std::string(SIGNAL_FINISHED), &TransitionSet::DoConnectSignal); + +} // anonymous namespace + +TransitionSetPtr TransitionSet::New() +{ + TransitionSetPtr transitionSet = new TransitionSet(); + + return transitionSet; +} + +TransitionSet::TransitionSet() +{ +} + +TransitionSet::~TransitionSet() +{ + mTransitions.clear(); +} + +void TransitionSet::AddTransition(TransitionBasePtr transition) +{ + mTransitions.push_back(transition); +} + +TransitionBase* TransitionSet::GetTransitionAt(uint32_t index) const +{ + TransitionBase* result(nullptr); + if(index < GetTransitionCount()) + { + result = mTransitions[index].Get(); + } + else + { + DALI_LOG_ERROR("Error: Invalid index to TransitionSet::GetTransitionAt\n"); + } + + return result; +} + +uint32_t TransitionSet::GetTransitionCount() const +{ + return mTransitions.size(); +} + +void TransitionSet::Play() +{ + Adaptor::Get().RegisterProcessor(*this, true); + Adaptor::Get().RegisterProcessor(*this, false); + TransitionLifecycleController::GetInstance().AddTransitions(Dali::Toolkit::TransitionSet(this)); +} + +void TransitionSet::TransitionPreProcess() +{ + float lastDuration = 0.0f; + for(auto&& transition : mTransitions) + { + TimePeriod timePeriod = transition->GetTimePeriod(); + if(lastDuration <= timePeriod.durationSeconds + timePeriod.delaySeconds) + { + lastDuration = timePeriod.durationSeconds + timePeriod.delaySeconds; + } + } + mAnimation = Dali::Animation::New(lastDuration); + + for(auto&& transition : mTransitions) + { + transition->PreProcess(mAnimation); + } +} + +void TransitionSet::TransitionStart() +{ + for(auto&& transition : mTransitions) + { + transition->Play(); + } + + mAnimation.FinishedSignal().Connect(this, &TransitionSet::TransitionFinished); + mAnimation.Play(); +} + +void TransitionSet::TransitionFinished(Dali::Animation& source) +{ + for(auto&& transition : mTransitions) + { + transition->TransitionFinished(); + } + + EmitFinishedSignal(); +} + +Dali::Toolkit::TransitionSet::TransitionSetSignalType& TransitionSet::FinishedSignal() +{ + return mFinishedSignal; +} + +void TransitionSet::EmitFinishedSignal() +{ + if(!mFinishedSignal.Empty()) + { + Dali::Toolkit::TransitionSet handle(this); + mFinishedSignal.Emit(handle); + } +} + +bool TransitionSet::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor) +{ + bool connected(false); + TransitionSet* transitionSet = static_cast(object); // TypeRegistry guarantees that this is the correct type. + + if(SIGNAL_FINISHED == signalName) + { + transitionSet->FinishedSignal().Connect(tracker, functor); + connected = true; + } + + return connected; +} + +void TransitionSet::Process(bool postProcessor) +{ + if(!postProcessor) + { + TransitionPreProcess(); + } + else + { + TransitionStart(); + } + Adaptor::Get().UnregisterProcessor(*this, postProcessor); +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/transition/transition-set-impl.h b/dali-toolkit/internal/transition/transition-set-impl.h new file mode 100644 index 0000000..eb9962d --- /dev/null +++ b/dali-toolkit/internal/transition/transition-set-impl.h @@ -0,0 +1,163 @@ +#ifndef DALI_TOOLKIT_INTERNAL_TRANSITION_SET_H +#define DALI_TOOLKIT_INTERNAL_TRANSITION_SET_H + +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +using TransitionSetPtr = IntrusivePtr; + +class TransitionSet : public BaseObject, public ConnectionTracker, public Integration::Processor +{ +public: + /** + * Create a new TransitionSet object. + * @return A smart-pointer to the newly allocated TransitionSet. + */ + static TransitionSetPtr New(); + + /** + * @copydoc Dali::Toolkit::TransitionSet::AddTransition(TransitionPtr transition) + */ + void AddTransition(TransitionBasePtr transition); + + /** + * @copydoc Dali::Toolkit::TransitionSet::GetTransitionAt(uint32_t index) + */ + TransitionBase* GetTransitionAt(uint32_t index) const; + + /** + * @copydoc Dali::Toolkit::TransitionSet::GetTransitionCount() + */ + uint32_t GetTransitionCount() const; + + /** + * @brief Make ready this transition set to play. + * Transitions in this transition set will be create property animations at the end of this tick of main thread. + */ + void Play(); + + /** + * @copydoc Dali::Toolkit::TransitionSet::FinishedSignal() + */ + Dali::Toolkit::TransitionSet::TransitionSetSignalType& FinishedSignal(); + + /** + * Connects a callback function with the object's signals. + * @param[in] object The object providing the signal. + * @param[in] tracker Used to disconnect the signal. + * @param[in] signalName The signal to connect to. + * @param[in] functor A newly allocated FunctorDelegate. + * @return True if the signal was connected. + * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor. + */ + static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor); + +private: + /** + * @brief Set pre process of each transition. + */ + void TransitionPreProcess(); + + /** + * @brief Start to play each of Transition. + * This method called at the end of event thread tick, and this method call OnPlay method of TransitionBase internally. + */ + void TransitionStart(); + + /** + * @brief Remove each finished TransitionBase from play list. + * If all transitions are finished emit Finished signal. + */ + void TransitionFinished(Dali::Animation& source); + + /** + * Emit the Finished signal + */ + void EmitFinishedSignal(); + +protected: // Implementation of Processor + /** + * @copydoc Dali::Integration::Processor::Process() + */ + void Process(bool postProcessor) override; + +protected: + /** + * Construct a new TransitionSet. + */ + TransitionSet(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + ~TransitionSet() override; + +private: + // Undefined + TransitionSet(const TransitionSet&); + + // Undefined + TransitionSet& operator=(const TransitionSet& rhs); + +private: + Dali::Toolkit::TransitionSet::TransitionSetSignalType mFinishedSignal{}; + std::vector mTransitions; + Dali::Animation mAnimation; +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Internal::TransitionSet& GetImplementation(Dali::Toolkit::TransitionSet& transitionSet) +{ + DALI_ASSERT_ALWAYS(transitionSet && "TransitionSet handle is empty"); + + BaseObject& handle = transitionSet.GetBaseObject(); + + return static_cast(handle); +} + +inline const Internal::TransitionSet& GetImplementation(const Dali::Toolkit::TransitionSet& transitionSet) +{ + DALI_ASSERT_ALWAYS(transitionSet && "TransitionSet handle is empty"); + + const BaseObject& handle = transitionSet.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_INTERNAL_TRANSITION_SET_H diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp index c9623a6..58506fd 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -538,8 +538,12 @@ void AnimatedImageVisual::OnSetTransform() void AnimatedImageVisual::OnInitialize() { bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE; - bool atlasing = false; - Shader shader = mImageVisualShaderFactory.GetShader(mFactoryCache, atlasing, defaultWrapMode, IsRoundedCornerRequired()); + Shader shader = mImageVisualShaderFactory.GetShader( + mFactoryCache, + TextureAtlas::DISABLED, + defaultWrapMode ? DefaultTextureWrapMode::APPLY : DefaultTextureWrapMode::DO_NOT_APPLY, + IsRoundedCornerRequired() ? RoundedCorner::ENABLED : RoundedCorner::DISABLED, + IsBorderlineRequired() ? Borderline::ENABLED : Borderline::DISABLED); Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY); diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp index c6604ad..edd7b1b 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp @@ -295,7 +295,13 @@ void AnimatedVectorImageVisual::OnInitialize(void) } else { - shader = mImageVisualShaderFactory.GetShader(mFactoryCache, false, true, IsRoundedCornerRequired()); + shader = mImageVisualShaderFactory.GetShader( + mFactoryCache, + TextureAtlas::DISABLED, + DefaultTextureWrapMode::APPLY, + IsRoundedCornerRequired() ? RoundedCorner::ENABLED : RoundedCorner::DISABLED, + IsBorderlineRequired() ? Borderline::ENABLED : Borderline::DISABLED + ); } Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY); diff --git a/dali-toolkit/internal/visuals/color/color-visual.cpp b/dali-toolkit/internal/visuals/color/color-visual.cpp index cf6abd3..8f748cf 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.cpp +++ b/dali-toolkit/internal/visuals/color/color-visual.cpp @@ -39,6 +39,27 @@ namespace Toolkit { namespace Internal { +namespace +{ +VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[6] = +{ + VisualFactoryCache::COLOR_SHADER, + VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER, + VisualFactoryCache::COLOR_SHADER_BORDERLINE, + VisualFactoryCache::COLOR_SHADER_ROUNDED_BORDERLINE, + VisualFactoryCache::COLOR_SHADER_BLUR_EDGE, + VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER_BLUR_EDGE, +}; + +// enum of required list when we select shader +enum ColorVisualRequireFlag +{ + DEFAULT = 0, + ROUNDED_CORNER = 1 << 0, + BORDERLINE = 1 << 1, + BLUR = 1 << 2, +}; +} // unnamed namespace ColorVisualPtr ColorVisual::New(VisualFactoryCache& factoryCache, const Property::Map& properties) { ColorVisualPtr colorVisualPtr(new ColorVisual(factoryCache)); @@ -192,32 +213,52 @@ void ColorVisual::OnInitialize() Shader ColorVisual::GetShader() { Shader shader; - if(!EqualsZero(mBlurRadius) || mNeedBlurRadius) + VisualFactoryCache::ShaderType shaderType; + + bool roundedCorner = IsRoundedCornerRequired(); + bool borderline = IsBorderlineRequired(); + bool blur = !EqualsZero(mBlurRadius) || mNeedBlurRadius; + int shaderTypeFlag = ColorVisualRequireFlag::DEFAULT; + + if(roundedCorner) { - shader = mFactoryCache.GetShader(VisualFactoryCache::COLOR_SHADER_BLUR_EDGE); - if(!shader) - { - shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_COLOR_VISUAL_BLUR_EDGE_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_COLOR_VISUAL_BLUR_EDGE_SHADER_FRAG.data()); - mFactoryCache.SaveShader(VisualFactoryCache::COLOR_SHADER_BLUR_EDGE, shader); - } + shaderTypeFlag |= ColorVisualRequireFlag::ROUNDED_CORNER; } - else if(!IsRoundedCornerRequired()) + if(blur) { - shader = mFactoryCache.GetShader(VisualFactoryCache::COLOR_SHADER); - if(!shader) - { - shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_COLOR_VISUAL_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_COLOR_VISUAL_SHADER_FRAG.data()); - mFactoryCache.SaveShader(VisualFactoryCache::COLOR_SHADER, shader); - } + // If we use blur, just ignore borderline + borderline = false; + shaderTypeFlag |= ColorVisualRequireFlag::BLUR; } - else + if(borderline) + { + shaderTypeFlag |= ColorVisualRequireFlag::BORDERLINE; + } + + shaderType = SHADER_TYPE_TABLE[shaderTypeFlag]; + shader = mFactoryCache.GetShader(shaderType); + if(!shader) { - shader = mFactoryCache.GetShader(VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER); - if(!shader) + std::string vertexShaderPrefixList; + std::string fragmentShaderPrefixList; + if(roundedCorner) + { + vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n"; + fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n"; + } + if(blur) + { + vertexShaderPrefixList += "#define IS_REQUIRED_BLUR 1\n"; + fragmentShaderPrefixList += "#define IS_REQUIRED_BLUR 1\n"; + } + if(borderline) { - shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_COLOR_VISUAL_ROUNDED_CORNER_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_COLOR_VISUAL_ROUNDED_CORNER_SHADER_FRAG.data()); - mFactoryCache.SaveShader(VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER, shader); + vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n"; + fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n"; } + shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_COLOR_VISUAL_SHADER_VERT.data(), + Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_COLOR_VISUAL_SHADER_FRAG.data()); + mFactoryCache.SaveShader(shaderType, shader); } return shader; diff --git a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp index b122359..896b095 100644 --- a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp +++ b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp @@ -28,14 +28,7 @@ #include // INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include #include @@ -71,44 +64,35 @@ const char* const UNIFORM_ALIGNMENT_MATRIX_NAME("uAlignmentMatrix"); const unsigned int DEFAULT_OFFSET_MINIMUM = 0.0f; const unsigned int DEFAULT_OFFSET_MAXIMUM = 1.0f; -VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[][4] = - { - {VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE, - VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX, - VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_CORNER, - VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_CORNER}, - {VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE, - VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX, - VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_CORNER, - VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_CORNER}}; - -const std::string_view VERTEX_SHADER[] = - { - // vertex shader for gradient units as OBJECT_BOUNDING_BOX - SHADER_GRADIENT_VISUAL_BOUNDING_BOX_SHADER_VERT, - - // vertex shader for gradient units as USER_SPACE - SHADER_GRADIENT_VISUAL_USER_SPACE_SHADER_VERT, - - // vertex shader for gradient units as OBJECT_BOUNDING_BOX with corner radius - SHADER_GRADIENT_VISUAL_BOUNDING_BOX_ROUNDED_CORNER_SHADER_VERT, - - // vertex shader for gradient units as USER_SPACE with corner radius - SHADER_GRADIENT_VISUAL_USER_SPACE_ROUNDED_CORNER_SHADER_VERT}; - -const std::string_view FRAGMENT_SHADER[] = - { - // fragment shader for linear gradient - SHADER_GRADIENT_VISUAL_LINEAR_SHADER_FRAG, - - // fragment shader for radial gradient - SHADER_GRADIENT_VISUAL_RADIAL_SHADER_FRAG, - - // fragment shader for linear gradient with corner radius - SHADER_GRADIENT_VISUAL_LINEAR_ROUNDED_CORNER_SHADER_FRAG, - - // fragment shader for radial gradient with corner radius - SHADER_GRADIENT_VISUAL_RADIAL_ROUNDED_CORNER_SHADER_FRAG}; +VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[16] = +{ + VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_CORNER, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_CORNER, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_CORNER, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_CORNER, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_BORDERLINE, +}; + +// enum of required list when we select shader +enum GradientVisualRequireFlag +{ + DEFAULT = 0, + ROUNDED_CORNER = 1 << 0, + BORDERLINE = 1 << 1, + USER_SPACE = 1 << 2, + RADIAL = 1 << 3, +}; Dali::WrapMode::Type GetWrapMode(Toolkit::GradientVisual::SpreadMethod::Type spread) { @@ -162,10 +146,10 @@ void GradientVisual::DoSetProperties(const Property::Map& propertyMap) Scripting::GetEnumerationProperty(*unitsValue, UNITS_TABLE, UNITS_TABLE_COUNT, gradientUnits); } - mGradientType = LINEAR; + mGradientType = Type::LINEAR; if(propertyMap.Find(Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME)) { - mGradientType = RADIAL; + mGradientType = Type::RADIAL; } if(NewGradient(mGradientType, propertyMap)) @@ -283,7 +267,7 @@ void GradientVisual::OnInitialize() bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propertyMap) { - if(gradientType == LINEAR) + if(gradientType == Type::LINEAR) { Property::Value* startPositionValue = propertyMap.Find(Toolkit::GradientVisual::Property::START_POSITION, START_POSITION_NAME); Property::Value* endPositionValue = propertyMap.Find(Toolkit::GradientVisual::Property::END_POSITION, END_POSITION_NAME); @@ -299,7 +283,7 @@ bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propert return false; } } - else // type==RADIAL + else // type==Type::RADIAL { Property::Value* centerValue = propertyMap.Find(Toolkit::GradientVisual::Property::CENTER, CENTER_NAME); Property::Value* radiusValue = propertyMap.Find(Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME); @@ -363,13 +347,57 @@ bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propert 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); + bool userspaceUnit = (mGradient->GetGradientUnits() == Toolkit::GradientVisual::Units::USER_SPACE); + bool roundedCorner = IsRoundedCornerRequired(); + bool borderline = IsBorderlineRequired(); + bool radialGradient = (mGradientType == Type::RADIAL); + + int shaderTypeFlag = GradientVisualRequireFlag::DEFAULT; + if(roundedCorner) + { + shaderTypeFlag |= GradientVisualRequireFlag::ROUNDED_CORNER; + } + if(borderline) + { + shaderTypeFlag |= GradientVisualRequireFlag::BORDERLINE; + } + if(userspaceUnit) + { + shaderTypeFlag |= GradientVisualRequireFlag::USER_SPACE; + } + if(radialGradient) + { + shaderTypeFlag |= GradientVisualRequireFlag::RADIAL; + } + + VisualFactoryCache::ShaderType shaderType = SHADER_TYPE_TABLE[shaderTypeFlag]; + Shader shader = mFactoryCache.GetShader(shaderType); if(!shader) { - shader = Shader::New(VERTEX_SHADER[gradientUnits + roundedCorner * 2], FRAGMENT_SHADER[mGradientType + roundedCorner * 2]); + std::string vertexShaderPrefixList; + std::string fragmentShaderPrefixList; + + if(roundedCorner) + { + vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n"; + fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n"; + } + if(borderline) + { + vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n"; + fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n"; + } + if(radialGradient) + { + fragmentShaderPrefixList += "#define RADIAL 1\n"; + } + if(userspaceUnit) + { + vertexShaderPrefixList += "#define USER_SPACE 1\n"; + } + + shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_GRADIENT_VISUAL_SHADER_VERT.data(), + Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_GRADIENT_VISUAL_SHADER_FRAG.data()); mFactoryCache.SaveShader(shaderType, shader); } diff --git a/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp b/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp index f8f7e5e..7f2cac7 100644 --- a/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp +++ b/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp @@ -50,58 +50,77 @@ ImageVisualShaderFactory::~ImageVisualShaderFactory() { } -Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping, bool roundedCorner) +Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, TextureAtlas atlasing, DefaultTextureWrapMode defaultTextureWrapping, RoundedCorner roundedCorner, Borderline borderline) { Shader shader; - if(atlasing) + VisualFactoryCache::ShaderType shaderType = VisualFactoryCache::IMAGE_SHADER; + if(atlasing == TextureAtlas::ENABLED) { - if(defaultTextureWrapping) + if(defaultTextureWrapping == DefaultTextureWrapMode::APPLY) { - shader = factoryCache.GetShader(VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP); - if(!shader) + shaderType = VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP; + } + else + { + shaderType = VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP; + } + } + else + { + if(roundedCorner == RoundedCorner::ENABLED) + { + if(borderline == Borderline::ENABLED) { - shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data(), - Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_ATLAS_CLAMP_SHADER_FRAG.data()); - shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT); - factoryCache.SaveShader(VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader); + shaderType = VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE; + } + else + { + shaderType = VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER; } } else { - shader = factoryCache.GetShader(VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP); - if(!shader) + if(borderline == Borderline::ENABLED) { - shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data(), - Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_ATLAS_VARIOUS_WRAP_SHADER_FRAG.data()); - shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT); - factoryCache.SaveShader(VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP, shader); + shaderType = VisualFactoryCache::IMAGE_SHADER_BORDERLINE; } } } - else + + shader = factoryCache.GetShader(shaderType); + if(!shader) { - if(roundedCorner) + std::string vertexShaderPrefixList; + std::string fragmentShaderPrefixList; + if(atlasing == TextureAtlas::ENABLED) { - shader = factoryCache.GetShader(VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER); - if(!shader) + if(defaultTextureWrapping == DefaultTextureWrapMode::APPLY) + { + fragmentShaderPrefixList += "#define ATLAS_DEFAULT_WARP 1\n"; + } + else { - shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_ROUNDED_CORNER_SHADER_VERT.data(), - Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_ROUNDED_CORNER_SHADER_FRAG.data()); - shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT); - factoryCache.SaveShader(VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER, shader); + fragmentShaderPrefixList += "#define ATLAS_CUSTOM_WARP 1\n"; } } else { - shader = factoryCache.GetShader(VisualFactoryCache::IMAGE_SHADER); - if(!shader) + if(roundedCorner == RoundedCorner::ENABLED) + { + vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n"; + fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n"; + } + if(borderline == Borderline::ENABLED) { - shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data(), - Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_NO_ATLAS_SHADER_FRAG.data()); - shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT); - factoryCache.SaveShader(VisualFactoryCache::IMAGE_SHADER, shader); + vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n"; + fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n"; } } + + shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_VERT.data(), + Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_FRAG.data()); + shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT); + factoryCache.SaveShader(shaderType, shader); } return shader; @@ -121,7 +140,7 @@ std::string_view ImageVisualShaderFactory::GetFragmentShaderSource() { if(gFragmentShaderNoAtlas.empty()) { - gFragmentShaderNoAtlas = Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_NO_ATLAS_SHADER_FRAG.data(); + gFragmentShaderNoAtlas = Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_FRAG.data(); } return gFragmentShaderNoAtlas; } diff --git a/dali-toolkit/internal/visuals/image-visual-shader-factory.h b/dali-toolkit/internal/visuals/image-visual-shader-factory.h index 8ed50a6..604b49b 100644 --- a/dali-toolkit/internal/visuals/image-visual-shader-factory.h +++ b/dali-toolkit/internal/visuals/image-visual-shader-factory.h @@ -30,11 +30,48 @@ namespace Toolkit namespace Internal { /** + * @brief Whether use texture with atlas, or not + */ +enum class TextureAtlas +{ + DISABLED = 0, ///< Image visual use ATLAS + ENABLED ///< Image visual doesn't use ATLAS +}; + +/** + * @brief Whether apply to texture wraping in default, or not + */ +enum class DefaultTextureWrapMode +{ + DO_NOT_APPLY = 0, ///< Image visual doesn't apply to wraping texture in default + APPLY ///< Image visual apply to wraping texture in default +}; + +/** + * @brief Whether use rounded corner, or not + */ +enum class RoundedCorner +{ + DISABLED = 0, ///< Image visual doesn't use rounded corner + ENABLED ///< Image visual use rounded corner +}; + +/** + * @brief Whether use borderline, or not + */ +enum class Borderline +{ + DISABLED = 0, ///< Image visual doesn't use borderline + ENABLED ///< Image visual use borderline +}; + +/** * ImageVisualShaderFactory is an object that provides and shares shaders between image visuals */ class ImageVisualShaderFactory { public: + /** * @brief Constructor */ @@ -51,8 +88,9 @@ public: * @param[in] atlasing Whether texture atlasing is applied. * @param[in] defaultTextureWrapping Whether the default texture wrap mode is applied. * @param[in] roundedCorner Whether the rounded corder is applied. + * @param[in] borderline Whether the borderline of visual is applied. */ - Shader GetShader(VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping, bool roundedCorner); + Shader GetShader(VisualFactoryCache& factoryCache, TextureAtlas atlasing, DefaultTextureWrapMode defaultTextureWrapping, RoundedCorner roundedCorner, Borderline borderline); /** * Request the default vertex shader source. diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index 1c5f5e7..bbbab23 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -978,9 +978,11 @@ Shader ImageVisual::GetShader() // 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()); + mImpl->mFlags & Impl::IS_ATLASING_APPLIED ? TextureAtlas::ENABLED : TextureAtlas::DISABLED, + mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE ? DefaultTextureWrapMode::APPLY : DefaultTextureWrapMode::DO_NOT_APPLY, + IsRoundedCornerRequired() ? RoundedCorner::ENABLED : RoundedCorner::DISABLED, + IsBorderlineRequired() ? Borderline::ENABLED : Borderline::DISABLED + ); } else if(mImpl->mCustomShader) { diff --git a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp index bb8571d..bbee1d4 100644 --- a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp +++ b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp @@ -376,7 +376,13 @@ void NPatchVisual::OnInitialize() { // Get basic geometry and shader Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY); - Shader shader = mImageVisualShaderFactory.GetShader(mFactoryCache, false, true, false); + Shader shader = mImageVisualShaderFactory.GetShader( + mFactoryCache, + TextureAtlas::DISABLED, + DefaultTextureWrapMode::APPLY, + RoundedCorner::DISABLED, + Borderline::DISABLED + ); mImpl->mRenderer = Renderer::New(geometry, shader); diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.cpp b/dali-toolkit/internal/visuals/svg/svg-visual.cpp index dc148a2..b6f9520 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-visual.cpp @@ -87,7 +87,13 @@ void SvgVisual::OnInitialize() Shader shader; if(!mImpl->mCustomShader) { - shader = mImageVisualShaderFactory.GetShader(mFactoryCache, mAttemptAtlasing, true, IsRoundedCornerRequired()); + shader = mImageVisualShaderFactory.GetShader( + mFactoryCache, + mAttemptAtlasing ? TextureAtlas::ENABLED : TextureAtlas::DISABLED, + DefaultTextureWrapMode::APPLY, + IsRoundedCornerRequired() ? RoundedCorner::ENABLED : RoundedCorner::DISABLED, + IsBorderlineRequired() ? Borderline::ENABLED : Borderline::DISABLED + ); } else { diff --git a/dali-toolkit/internal/visuals/visual-base-data-impl.cpp b/dali-toolkit/internal/visuals/visual-base-data-impl.cpp index 2d42f93..53b5246 100644 --- a/dali-toolkit/internal/visuals/visual-base-data-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-data-impl.cpp @@ -119,16 +119,23 @@ Internal::Visual::Base::Impl::Impl(FittingMode fittingMode, Toolkit::Visual::Typ mTransform(), mMixColor(Color::WHITE), mControlSize(Vector2::ZERO), + mBorderlineWidth(0.0f), + mBorderlineColor(Color::BLACK), + mBorderlineOffset(0.0f), mCornerRadius(Vector4::ZERO), mCornerRadiusPolicy(1.0f), mDepthIndex(0.0f), mMixColorIndex(Property::INVALID_INDEX), + mBorderlineWidthIndex(Property::INVALID_INDEX), + mBorderlineColorIndex(Property::INVALID_INDEX), + mBorderlineOffsetIndex(Property::INVALID_INDEX), mCornerRadiusIndex(Property::INVALID_INDEX), mFittingMode(fittingMode), mFlags(0), mResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING), mType(type), - mNeedCornerRadius(false) + mNeedCornerRadius(false), + mNeedBorderline(false) { } diff --git a/dali-toolkit/internal/visuals/visual-base-data-impl.h b/dali-toolkit/internal/visuals/visual-base-data-impl.h index acb6805..52e0d98 100644 --- a/dali-toolkit/internal/visuals/visual-base-data-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-data-impl.h @@ -123,16 +123,23 @@ struct Base::Impl Transform mTransform; Vector4 mMixColor; Size mControlSize; + float mBorderlineWidth; + Vector4 mBorderlineColor; + float mBorderlineOffset; Vector4 mCornerRadius; float mCornerRadiusPolicy; int mDepthIndex; Property::Index mMixColorIndex; + Property::Index mBorderlineWidthIndex; + Property::Index mBorderlineColorIndex; + Property::Index mBorderlineOffsetIndex; Property::Index mCornerRadiusIndex; FittingMode mFittingMode; //< How the contents should fit the view int mFlags; Toolkit::Visual::ResourceStatus mResourceStatus; const Toolkit::Visual::Type mType; bool mNeedCornerRadius; + bool mNeedBorderline; }; } // namespace Visual diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index 528bc14..49b3120 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -89,6 +89,14 @@ void Visual::Base::Initialize() mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON); } + if(IsBorderlineRequired()) + { + mImpl->mBorderlineWidthIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH, mImpl->mBorderlineWidth); + mImpl->mBorderlineColorIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_COLOR, BORDERLINE_COLOR, mImpl->mBorderlineColor); + mImpl->mBorderlineOffsetIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET, mImpl->mBorderlineOffset); + + mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON); + } } } @@ -142,6 +150,18 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) { matchKey = Property::Key(Toolkit::DevelVisual::Property::VISUAL_FITTING_MODE); } + else if(matchKey == BORDERLINE_WIDTH) + { + matchKey = Property::Key(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH); + } + else if(matchKey == BORDERLINE_COLOR) + { + matchKey = Property::Key(Toolkit::DevelVisual::Property::BORDERLINE_COLOR); + } + else if(matchKey == BORDERLINE_OFFSET) + { + matchKey = Property::Key(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET); + } else if(matchKey == CORNER_RADIUS) { matchKey = Property::Key(Toolkit::DevelVisual::Property::CORNER_RADIUS); @@ -217,6 +237,33 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) value, VISUAL_FITTING_MODE_TABLE, VISUAL_FITTING_MODE_TABLE_COUNT, mImpl->mFittingMode); break; } + case Toolkit::DevelVisual::Property::BORDERLINE_WIDTH: + { + float width; + if(value.Get(width)) + { + mImpl->mBorderlineWidth = width; + } + break; + } + case Toolkit::DevelVisual::Property::BORDERLINE_COLOR: + { + Vector4 color; + if(value.Get(color)) + { + mImpl->mBorderlineColor = color; + } + break; + } + case Toolkit::DevelVisual::Property::BORDERLINE_OFFSET: + { + float offset; + if(value.Get(offset)) + { + mImpl->mBorderlineOffset = offset; + } + break; + } case Toolkit::DevelVisual::Property::CORNER_RADIUS: { if(value.GetType() == Property::VECTOR4) @@ -388,6 +435,18 @@ void Visual::Base::CreatePropertyMap(Property::Map& map) const { mImpl->mCornerRadius = mImpl->mRenderer.GetProperty(mImpl->mCornerRadiusIndex); } + if(mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX) + { + mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty(mImpl->mBorderlineWidthIndex); + } + if(mImpl->mBorderlineColorIndex != Property::INVALID_INDEX) + { + mImpl->mBorderlineColor = mImpl->mRenderer.GetProperty(mImpl->mBorderlineColorIndex); + } + if(mImpl->mBorderlineOffsetIndex != Property::INVALID_INDEX) + { + mImpl->mBorderlineOffset = mImpl->mRenderer.GetProperty(mImpl->mBorderlineOffsetIndex); + } } DoCreatePropertyMap(map); @@ -413,6 +472,10 @@ void Visual::Base::CreatePropertyMap(Property::Map& map) const mImpl->mFittingMode, VISUAL_FITTING_MODE_TABLE, VISUAL_FITTING_MODE_TABLE_COUNT); map.Insert(Toolkit::DevelVisual::Property::VISUAL_FITTING_MODE, fittingModeString); + map.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, mImpl->mBorderlineWidth); + map.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, mImpl->mBorderlineColor); + map.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, mImpl->mBorderlineOffset); + map.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, mImpl->mCornerRadius); map.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY, static_cast(mImpl->mCornerRadiusPolicy)); } @@ -470,6 +533,16 @@ bool Visual::Base::IsRoundedCornerRequired() const return !(mImpl->mCornerRadius == Vector4::ZERO) || mImpl->mNeedCornerRadius; } +bool Visual::Base::IsBorderlineRequired() const +{ + if(mImpl->mRenderer && mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX) + { + // Update values from Renderer + mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty(mImpl->mBorderlineWidthIndex); + } + return !EqualsZero(mImpl->mBorderlineWidth) || mImpl->mNeedBorderline; +} + void Visual::Base::OnDoAction(const Property::Index actionId, const Property::Value& attributes) { // May be overriden by derived class @@ -824,7 +897,24 @@ Dali::Property Visual::Base::GetPropertyObject(Dali::Property::Key key) 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)) + if((key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_WIDTH) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_WIDTH) || + (key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_COLOR) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_COLOR) || + (key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_OFFSET) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_OFFSET)) + { + mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON); + + // Register borderline properties + mImpl->mBorderlineWidthIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH, mImpl->mBorderlineWidth); + mImpl->mBorderlineColorIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_COLOR, BORDERLINE_COLOR, mImpl->mBorderlineColor); + mImpl->mBorderlineOffsetIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET, mImpl->mBorderlineOffset); + mImpl->mNeedBorderline = true; + + index = mImpl->mRenderer.GetPropertyIndex(key); + + // Change shader + UpdateShader(); + } + else 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); diff --git a/dali-toolkit/internal/visuals/visual-base-impl.h b/dali-toolkit/internal/visuals/visual-base-impl.h index c958992..8800ad8 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-impl.h @@ -389,6 +389,13 @@ protected: */ bool IsRoundedCornerRequired() const; + /** + * @brief Query whether the borderline of the visual requires to be rendered. + * + * @return Returns true if the outline is required, false otherwise. + */ + bool IsBorderlineRequired() const; + private: /** * Register the mix color uniform on the Renderer and store the property index. diff --git a/dali-toolkit/internal/visuals/visual-factory-cache.h b/dali-toolkit/internal/visuals/visual-factory-cache.h index 418b10e..6e8f37d 100644 --- a/dali-toolkit/internal/visuals/visual-factory-cache.h +++ b/dali-toolkit/internal/visuals/visual-factory-cache.h @@ -57,21 +57,34 @@ public: { COLOR_SHADER, COLOR_SHADER_ROUNDED_CORNER, + COLOR_SHADER_BORDERLINE, + COLOR_SHADER_ROUNDED_BORDERLINE, COLOR_SHADER_BLUR_EDGE, + COLOR_SHADER_ROUNDED_CORNER_BLUR_EDGE, BORDER_SHADER, BORDER_SHADER_ANTI_ALIASING, - GRADIENT_SHADER_LINEAR_USER_SPACE, GRADIENT_SHADER_LINEAR_BOUNDING_BOX, - GRADIENT_SHADER_RADIAL_USER_SPACE, - GRADIENT_SHADER_RADIAL_BOUNDING_BOX, - GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_CORNER, GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_CORNER, - GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_CORNER, + GRADIENT_SHADER_LINEAR_BOUNDING_BOX_BORDERLINE, + GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_BORDERLINE, + GRADIENT_SHADER_LINEAR_USER_SPACE, + GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_CORNER, + GRADIENT_SHADER_LINEAR_USER_SPACE_BORDERLINE, + GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_BORDERLINE, + GRADIENT_SHADER_RADIAL_BOUNDING_BOX, GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_CORNER, + GRADIENT_SHADER_RADIAL_BOUNDING_BOX_BORDERLINE, + GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_BORDERLINE, + GRADIENT_SHADER_RADIAL_USER_SPACE, + GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_CORNER, + GRADIENT_SHADER_RADIAL_USER_SPACE_BORDERLINE, + GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_BORDERLINE, IMAGE_SHADER, IMAGE_SHADER_ATLAS_DEFAULT_WRAP, IMAGE_SHADER_ATLAS_CUSTOM_WRAP, IMAGE_SHADER_ROUNDED_CORNER, + IMAGE_SHADER_BORDERLINE, + IMAGE_SHADER_ROUNDED_BORDERLINE, NINE_PATCH_SHADER, NINE_PATCH_MASK_SHADER, TEXT_SHADER_MULTI_COLOR_TEXT, diff --git a/dali-toolkit/internal/visuals/visual-string-constants.cpp b/dali-toolkit/internal/visuals/visual-string-constants.cpp index 9c9ca4b..53bcd1c 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.cpp +++ b/dali-toolkit/internal/visuals/visual-string-constants.cpp @@ -75,6 +75,11 @@ const char* const OPACITY("opacity"); // Fitting mode const char* const VISUAL_FITTING_MODE("visualFittingMode"); +// Border line +const char* const BORDERLINE_WIDTH("borderlineWidth"); +const char* const BORDERLINE_COLOR("borderlineColor"); +const char* const BORDERLINE_OFFSET("borderlineOffset"); + // Corner radius const char* const CORNER_RADIUS("cornerRadius"); const char* const CORNER_RADIUS_POLICY("cornerRadiusPolicy"); diff --git a/dali-toolkit/internal/visuals/visual-string-constants.h b/dali-toolkit/internal/visuals/visual-string-constants.h index 966e51f..470ded9 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.h +++ b/dali-toolkit/internal/visuals/visual-string-constants.h @@ -59,6 +59,11 @@ extern const char* const OPACITY; // Fitting mode extern const char* const VISUAL_FITTING_MODE; +// Border line +extern const char* const BORDERLINE_WIDTH; +extern const char* const BORDERLINE_COLOR; +extern const char* const BORDERLINE_OFFSET; + // Corner radius extern const char* const CORNER_RADIUS; extern const char* const CORNER_RADIUS_POLICY; diff --git a/dali-toolkit/public-api/controls/control-impl.h b/dali-toolkit/public-api/controls/control-impl.h index 6717f5b..9a68ca1 100644 --- a/dali-toolkit/public-api/controls/control-impl.h +++ b/dali-toolkit/public-api/controls/control-impl.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_CONTROL_IMPL_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -20,6 +20,8 @@ // EXTERNAL INCLUDES #include +#include +#include #include #include #include @@ -251,6 +253,7 @@ public: DALI_INTERNAL void KeyboardEnter(); /// @endcond + // Signals /** @@ -614,6 +617,21 @@ public: // API for derived classes to override return NULL; } + // Transition + + /** + * @brief Retrieve visual property animations. + * This Control is a destination. + * + * @param[in] animation generated animation + * @param[in] source source control of the animation. + * @param[in] alphaFunction AlphaFunction of the animation + * @param[in] timePeriod TimePeriod of the animation + */ + virtual void OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod) + { + } + private: /// @cond internal diff --git a/dali-toolkit/public-api/controls/flex-container/flex-container.h b/dali-toolkit/public-api/controls/flex-container/flex-container.h index 51e26f7..71589e0 100644 --- a/dali-toolkit/public-api/controls/flex-container/flex-container.h +++ b/dali-toolkit/public-api/controls/flex-container/flex-container.h @@ -138,7 +138,8 @@ public: JUSTIFY_CENTER, ///< Items are positioned at the center of the container @SINCE_1_1.35 JUSTIFY_FLEX_END, ///< Items are positioned at the end of the container @SINCE_1_1.35 JUSTIFY_SPACE_BETWEEN, ///< Items are positioned with equal space between the lines @SINCE_1_1.35 - JUSTIFY_SPACE_AROUND ///< Items are positioned with equal space before, between, and after the lines @SINCE_1_1.35 + JUSTIFY_SPACE_AROUND, ///< Items are positioned with equal space before, and after the lines @SINCE_1_1.35 + JUSTIFY_SPACE_EVENLY ///< Items are positioned with equal space before, between, and after the lines @SINCE_2_0.29 }; /** diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index f31d0a0..89f0ec4 100644 --- a/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -29,7 +29,7 @@ namespace Toolkit { const unsigned int TOOLKIT_MAJOR_VERSION = 2; const unsigned int TOOLKIT_MINOR_VERSION = 0; -const unsigned int TOOLKIT_MICRO_VERSION = 28; +const unsigned int TOOLKIT_MICRO_VERSION = 30; const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/dali-toolkit/public-api/file.list b/dali-toolkit/public-api/file.list index 76863a7..071b602 100644 --- a/dali-toolkit/public-api/file.list +++ b/dali-toolkit/public-api/file.list @@ -31,6 +31,9 @@ SET( public_api_src_files ${public_api_src_dir}/image-loader/async-image-loader.cpp ${public_api_src_dir}/image-loader/sync-image-loader.cpp ${public_api_src_dir}/styling/style-manager.cpp + ${public_api_src_dir}/transition/transition-base.cpp + ${public_api_src_dir}/transition/transition-set.cpp + ${public_api_src_dir}/transition/transition.cpp ${public_api_src_dir}/focus-manager/keyboard-focus-manager.cpp ${public_api_src_dir}/dali-toolkit-version.cpp ${public_api_src_dir}/enums.cpp @@ -143,6 +146,12 @@ SET( public_api_visuals_header_files ${public_api_src_dir}/visuals/text-visual-properties.h ) +SET( public_api_transition_header_files + ${public_api_src_dir}/transition/transition-base.h + ${public_api_src_dir}/transition/transition-set.h + ${public_api_src_dir}/transition/transition.h +) + SET( SOURCES ${SOURCES} ${public_api_src_files} ) @@ -162,6 +171,7 @@ SET( PUBLIC_API_HEADERS ${PUBLIC_API_HEADERS} ${public_api_slider_header_files} ${public_api_styling_header_files} ${public_api_text_controls_header_files} + ${public_api_transition_header_files} ${public_api_focus_manager_header_files} ${public_api_text_header_files} ${public_api_video_view_header_files} diff --git a/dali-toolkit/public-api/transition/transition-base.cpp b/dali-toolkit/public-api/transition/transition-base.cpp new file mode 100644 index 0000000..5e70e21 --- /dev/null +++ b/dali-toolkit/public-api/transition/transition-base.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +TransitionBase::TransitionBase() = default; + +TransitionBase::TransitionBase(Internal::TransitionBase* transitionBase) +: BaseHandle(transitionBase) +{ +} + +TransitionBase TransitionBase::New() +{ + Internal::TransitionBasePtr internal = Dali::Toolkit::Internal::TransitionBase::New(); + + return TransitionBase(internal.Get()); +} + +TransitionBase TransitionBase::DownCast(BaseHandle handle) +{ + return TransitionBase(dynamic_cast(handle.GetObjectPtr())); +} + +TransitionBase::~TransitionBase() = default; + +TransitionBase::TransitionBase(const TransitionBase& handle) = default; + +TransitionBase& TransitionBase::operator=(const TransitionBase& rhs) = default; + +TransitionBase::TransitionBase(TransitionBase&& rhs) = default; + +TransitionBase& TransitionBase::operator=(TransitionBase&& rhs) = default; + +void TransitionBase::SetTimePeriod(TimePeriod timePeriod) +{ + GetImplementation(*this).SetTimePeriod(timePeriod); +} + +TimePeriod TransitionBase::GetTimePeriod() const +{ + return GetImplementation(*this).GetTimePeriod(); +} + +void TransitionBase::SetAlphaFunction(AlphaFunction alphaFunction) +{ + GetImplementation(*this).SetAlphaFunction(alphaFunction); +} + +AlphaFunction TransitionBase::GetAlphaFunction() const +{ + return GetImplementation(*this).GetAlphaFunction(); +} + +void TransitionBase::TransitionWithChild(bool transitionWithChild) +{ + return GetImplementation(*this).TransitionWithChild(transitionWithChild); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/transition/transition-base.h b/dali-toolkit/public-api/transition/transition-base.h new file mode 100644 index 0000000..9a274ac --- /dev/null +++ b/dali-toolkit/public-api/transition/transition-base.h @@ -0,0 +1,152 @@ +#ifndef DALI_TOOLKIT_TRANSITION_BASE_H +#define DALI_TOOLKIT_TRANSITION_BASE_H + +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal DALI_INTERNAL +{ +class TransitionBase; +} + +/** + * @brief + * + * Transition provides continuous and seamless motions for the visually plausible scene change. + * And, TransitionBase is a base class for every Transition cases. + */ +class DALI_TOOLKIT_API TransitionBase : public BaseHandle +{ +public: + /** + * @brief Creates an uninitialized TransitionBase; this can be initialized with TransitionBase::New(). + * + * Calling member functions with an uninitialized TransitionBase handle is not allowed. + */ + TransitionBase(); + + /** + * @brief Creates an initialized TransitionBase. + */ + static TransitionBase New(); + + /** + * @brief Downcasts a handle to TransitionBase handle. + * + * If handle points to an TransitionBase object, the downcast produces valid handle. + * If not, the returned handle is left uninitialized. + * + * @param[in] handle Handle to an object + * @return Handle to an TransitionBase object or an uninitialized handle + */ + static TransitionBase DownCast(BaseHandle handle); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~TransitionBase(); + + /** + * @brief This copy constructor is required for (smart) pointer semantics. + * + * @param[in] handle A reference to the copied handle + */ + TransitionBase(const TransitionBase& handle); + + /** + * @brief This assignment operator is required for (smart) pointer semantics. + * + * @param[in] rhs A reference to the copied handle + * @return A reference to this + */ + TransitionBase& operator=(const TransitionBase& rhs); + + /** + * @brief Move constructor. + * + * @param[in] rhs A reference to the moved handle + */ + TransitionBase(TransitionBase&& rhs); + + /** + * @brief Move assignment operator. + * + * @param[in] rhs A reference to the moved handle + * @return A reference to this handle + */ + TransitionBase& operator=(TransitionBase&& rhs); + + /** + * Set time period that contains delay and duration + * @param[in] timePeriod The time period for an animator. + */ + void SetTimePeriod(TimePeriod timePeriod); + + /** + * Get time period that contains delay and duration + */ + TimePeriod GetTimePeriod() const; + + /** + * @brief Sets the alpha function for an transition. + * + * This is applied to individual property transitions, if no further alpha functions are supplied. + * @param[in] alpha The alpha function + */ + void SetAlphaFunction(AlphaFunction alpha); + + /** + * @brief Retrieves the alpha function for an transition. + * + * @return The alpha function + */ + AlphaFunction GetAlphaFunction() const; + + /** + * @brief A View could be transition with its child Views or without them. + */ + void TransitionWithChild(bool transitionWithChild); + +public: // Not intended for use by Application developers + /// @cond internal + /** + * @brief This constructor is used by TransitionBase::New() methods. + * @param[in] transitionBase A pointer to a newly allocated Dali resource + */ + explicit DALI_INTERNAL TransitionBase(Internal::TransitionBase* transitionBase); + /// @endcond +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TRANSITION_BASE_H diff --git a/dali-toolkit/public-api/transition/transition-set.cpp b/dali-toolkit/public-api/transition/transition-set.cpp new file mode 100644 index 0000000..fe8f33f --- /dev/null +++ b/dali-toolkit/public-api/transition/transition-set.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +TransitionSet::TransitionSet() = default; + +TransitionSet::TransitionSet(Internal::TransitionSet* transition) +: BaseHandle(transition) +{ +} + +TransitionSet TransitionSet::New() +{ + Internal::TransitionSetPtr internal = Dali::Toolkit::Internal::TransitionSet::New(); + + return TransitionSet(internal.Get()); +} + +TransitionSet TransitionSet::DownCast(BaseHandle handle) +{ + return TransitionSet(dynamic_cast(handle.GetObjectPtr())); +} + +TransitionSet::~TransitionSet() = default; + +TransitionSet::TransitionSet(const TransitionSet& handle) = default; + +TransitionSet& TransitionSet::operator=(const TransitionSet& rhs) = default; + +TransitionSet::TransitionSet(TransitionSet&& rhs) = default; + +TransitionSet& TransitionSet::operator=(TransitionSet&& rhs) = default; + +void TransitionSet::AddTransition(TransitionBase transition) +{ + if(transition) + { + Internal::TransitionBasePtr transitionBasePtr(&GetImplementation(transition)); + GetImplementation(*this).AddTransition(transitionBasePtr); + } +} + +TransitionBase TransitionSet::GetTransitionAt(uint32_t index) const +{ + Internal::TransitionBase* transitionBasePtr = GetImplementation(*this).GetTransitionAt(static_cast(index)); + return Dali::Toolkit::TransitionBase(transitionBasePtr); +} + +uint32_t TransitionSet::GetTransitionCount() const +{ + return GetImplementation(*this).GetTransitionCount(); +} + +void TransitionSet::Play() +{ + GetImplementation(*this).Play(); +} + +TransitionSet::TransitionSetSignalType& TransitionSet::FinishedSignal() +{ + return GetImplementation(*this).FinishedSignal(); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/transition/transition-set.h b/dali-toolkit/public-api/transition/transition-set.h new file mode 100644 index 0000000..8df1ea5 --- /dev/null +++ b/dali-toolkit/public-api/transition/transition-set.h @@ -0,0 +1,165 @@ +#ifndef DALI_TOOLKIT_TRANSITION_SET_H +#define DALI_TOOLKIT_TRANSITION_SET_H + +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +// EXTERNAL INCLUDES +#include +#include +#include // uint32_t, uint8_t + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal DALI_INTERNAL +{ +class TransitionSet; +} + +/** + * @brief + * + * TransitionSet is used to control lifetime of multiple Transitions. + * Transition could be played with multiple other transitions for a scene change. + * For the case, it is more useful to manage a group of transitions with same lifetime and a finished signal. + * TransitionSet provides a single Play call and Finished callback for the multiple traisitions those added on it. + */ +class DALI_TOOLKIT_API TransitionSet : public BaseHandle +{ +public: + using TransitionSetSignalType = Signal; ///< TransitionSet finished signal type + + /** + * @brief Creates an uninitialized TransitionSet; this can be initialized with TransitionSet::New(). + * + * Calling member functions with an uninitialized TransitionSet handle is not allowed. + */ + TransitionSet(); + + /** + * @brief Creates an initialized TransitionSet. + * + * @return A handle to a newly allocated Dali resource + * @note durationSeconds can not be negative. + */ + static TransitionSet New(); + + /** + * @brief Downcasts a handle to TransitionSet handle. + * + * If handle points to an TransitionSet object, the downcast produces valid handle. + * If not, the returned handle is left uninitialized. + * + * @param[in] handle Handle to an object + * @return Handle to an TransitionSet object or an uninitialized handle + */ + static TransitionSet DownCast(BaseHandle handle); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~TransitionSet(); + + /** + * @brief This copy constructor is required for (smart) pointer semantics. + * + * @param[in] handle A reference to the copied handle + */ + TransitionSet(const TransitionSet& handle); + + /** + * @brief This assignment operator is required for (smart) pointer semantics. + * + * @param[in] rhs A reference to the copied handle + * @return A reference to this + */ + TransitionSet& operator=(const TransitionSet& rhs); + + /** + * @brief Move constructor. + * + * @param[in] rhs A reference to the moved handle + */ + TransitionSet(TransitionSet&& rhs); + + /** + * @brief Move assignment operator. + * + * @param[in] rhs A reference to the moved handle + * @return A reference to this handle + */ + TransitionSet& operator=(TransitionSet&& rhs); + + /** + * @brief Add a TransitionBase on this TransitionSet. + * + * @param[in] transition TransitionBase to be added. + */ + void AddTransition(TransitionBase transition); + + /** + * @brief Retrieves a TransitionBase at the index. + * + * @return The TransitionBase of index + */ + TransitionBase GetTransitionAt(uint32_t index) const; + + /** + * @brief Retrieves the number of Transitions added in TransitionSet + * + * @return The number of Transitions + */ + uint32_t GetTransitionCount() const; + + /** + * @brief Play the transition. + * This method not make property animation instantly. + * Transition requires some world transform properties. + * The Transitions currently added on this TransitionSet are queued TransitionQueue + * and they are played at the end of this tick of event Thread + */ + void Play(); + + /** + * @brief Connects to this signal to be notified when all TransitionSet's transitions have finished. + * + * @return A signal object to connect with + */ + TransitionSetSignalType& FinishedSignal(); + +public: // Not intended for use by Application developers + /// @cond internal + /** + * @brief This constructor is used by TransitionSet::New() methods. + * @param[in] transition A pointer to a newly allocated Dali resource + */ + explicit DALI_INTERNAL TransitionSet(Internal::TransitionSet* transition); + /// @endcond +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TRANSITION_SET_H diff --git a/dali-toolkit/public-api/transition/transition.cpp b/dali-toolkit/public-api/transition/transition.cpp new file mode 100644 index 0000000..3e2f378 --- /dev/null +++ b/dali-toolkit/public-api/transition/transition.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +Transition::Transition() = default; + +Transition::Transition(Internal::Transition* transition) +: TransitionBase(transition) +{ +} + +Transition Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod) +{ + Internal::TransitionPtr internal = Dali::Toolkit::Internal::Transition::New(source, destination, timePeriod); + + return Transition(internal.Get()); +} + +Transition Transition::DownCast(BaseHandle handle) +{ + return Transition(dynamic_cast(handle.GetObjectPtr())); +} + +Transition::~Transition() = default; + +Transition::Transition(const Transition& handle) = default; + +Transition& Transition::operator=(const Transition& rhs) = default; + +Transition::Transition(Transition&& rhs) = default; + +Transition& Transition::operator=(Transition&& rhs) = default; + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/transition/transition.h b/dali-toolkit/public-api/transition/transition.h new file mode 100644 index 0000000..634face --- /dev/null +++ b/dali-toolkit/public-api/transition/transition.h @@ -0,0 +1,124 @@ +#ifndef DALI_TOOLKIT_TRANSITION_H +#define DALI_TOOLKIT_TRANSITION_H + +/* + * Copyright (c) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal DALI_INTERNAL +{ +class Transition; +} + +/** + * @brief + * + * Transition provides continuous and seamless motions between two Controls. + * This Transition generates property animation for transforms(position, scale, orientation), size, color, and opacity. + * And, if there are common renderer properties of source and destination Control, they also animated. + */ +class DALI_TOOLKIT_API Transition : public TransitionBase +{ +public: + /** + * @brief Creates an uninitialized Transition; this can be initialized with Transition::New(). + * + * Calling member functions with an uninitialized Transition handle is not allowed. + */ + Transition(); + + /** + * @brief Creates an initialized Transition. + * + * @param[in] source Source + * @param[in] destination Destination + * @param[in] timePeriod The duration in seconds + * @return A handle to a newly allocated Dali resource + * @note durationSeconds can not be negative. + */ + static Transition New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod); + + /** + * @brief Downcasts a handle to Transition handle. + * + * If handle points to an Transition object, the downcast produces valid handle. + * If not, the returned handle is left uninitialized. + * + * @param[in] handle Handle to an object + * @return Handle to an Transition object or an uninitialized handle + */ + static Transition DownCast(BaseHandle handle); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~Transition(); + + /** + * @brief This copy constructor is required for (smart) pointer semantics. + * + * @param[in] handle A reference to the copied handle + */ + Transition(const Transition& handle); + + /** + * @brief This assignment operator is required for (smart) pointer semantics. + * + * @param[in] rhs A reference to the copied handle + * @return A reference to this + */ + Transition& operator=(const Transition& rhs); + + /** + * @brief Move constructor. + * + * @param[in] rhs A reference to the moved handle + */ + Transition(Transition&& rhs); + + /** + * @brief Move assignment operator. + * + * @param[in] rhs A reference to the moved handle + * @return A reference to this handle + */ + Transition& operator=(Transition&& rhs); + +public: // Not intended for use by Application developers + /// @cond internal + /** + * @brief This constructor is used by Transition::New() methods. + * @param[in] transition A pointer to a newly allocated Dali resource + */ + explicit DALI_INTERNAL Transition(Internal::Transition* transition); + /// @endcond +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TRANSITION_H diff --git a/docs/content/programming-guide/flex-container.md b/docs/content/programming-guide/flex-container.md index 4552527..df6b9e4 100644 --- a/docs/content/programming-guide/flex-container.md +++ b/docs/content/programming-guide/flex-container.md @@ -115,7 +115,8 @@ The possible values for this property are: | JUSTIFY_CENTER | Items are positioned at the center of the container | | JUSTIFY_FLEX_END | Items are positioned at the end of the container | | JUSTIFY_SPACE_BETWEEN | Items are positioned with equal space between the lines | -| JUSTIFY_SPACE_AROUND | Items are positioned with equal space before, between, and after the lines | +| JUSTIFY_SPACE_AROUND | Items are positioned with equal space before, and after the lines | +| JUSTIFY_SPACE_EVENLY | Items are positioned with equal space before, between, and after the lines | ### Usage diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index 70ea699..7609a2c 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali2-toolkit Summary: Dali 3D engine Toolkit -Version: 2.0.28 +Version: 2.0.30 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT