From 7e83d1dc2a864653968ad8a6e68c3afdf9f9918d Mon Sep 17 00:00:00 2001 From: Seungho Baek Date: Wed, 13 Jan 2021 14:58:54 +0900 Subject: [PATCH] Adds transition effect Change-Id: Ie32632d0d8d0b91fe840de56f7bab4a4fed1557f Signed-off-by: Seungho Baek --- automated-tests/src/dali-toolkit/CMakeLists.txt | 1 + .../src/dali-toolkit/utc-Dali-Transition.cpp | 929 +++++++++++++++++++++ dali-toolkit/devel-api/controls/control-devel.cpp | 13 + dali-toolkit/devel-api/controls/control-devel.h | 16 + .../controls/control/control-data-impl.cpp | 63 ++ .../internal/controls/control/control-data-impl.h | 12 + .../controls/image-view/image-view-impl.cpp | 69 ++ .../internal/controls/image-view/image-view-impl.h | 5 + dali-toolkit/internal/file.list | 4 + .../internal/transition/transition-base-impl.cpp | 390 +++++++++ .../internal/transition/transition-base-impl.h | 265 ++++++ .../internal/transition/transition-impl.cpp | 174 ++++ dali-toolkit/internal/transition/transition-impl.h | 108 +++ .../transition/transition-lifecycle-controller.cpp | 48 ++ .../transition/transition-lifecycle-controller.h | 83 ++ .../internal/transition/transition-set-impl.cpp | 184 ++++ .../internal/transition/transition-set-impl.h | 163 ++++ dali-toolkit/public-api/controls/control-impl.h | 20 +- dali-toolkit/public-api/file.list | 10 + .../public-api/transition/transition-base.cpp | 84 ++ .../public-api/transition/transition-base.h | 152 ++++ .../public-api/transition/transition-set.cpp | 89 ++ .../public-api/transition/transition-set.h | 165 ++++ dali-toolkit/public-api/transition/transition.cpp | 59 ++ dali-toolkit/public-api/transition/transition.h | 124 +++ 25 files changed, 3229 insertions(+), 1 deletion(-) create mode 100755 automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp create mode 100644 dali-toolkit/internal/transition/transition-base-impl.cpp create mode 100644 dali-toolkit/internal/transition/transition-base-impl.h create mode 100644 dali-toolkit/internal/transition/transition-impl.cpp create mode 100644 dali-toolkit/internal/transition/transition-impl.h create mode 100644 dali-toolkit/internal/transition/transition-lifecycle-controller.cpp create mode 100644 dali-toolkit/internal/transition/transition-lifecycle-controller.h create mode 100644 dali-toolkit/internal/transition/transition-set-impl.cpp create mode 100644 dali-toolkit/internal/transition/transition-set-impl.h create mode 100644 dali-toolkit/public-api/transition/transition-base.cpp create mode 100644 dali-toolkit/public-api/transition/transition-base.h create mode 100644 dali-toolkit/public-api/transition/transition-set.cpp create mode 100644 dali-toolkit/public-api/transition/transition-set.h create mode 100644 dali-toolkit/public-api/transition/transition.cpp create mode 100644 dali-toolkit/public-api/transition/transition.h 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-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/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/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/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/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/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/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/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 -- 2.7.4