From b53700710fb09daf8e051a9ccff08383d20e706f Mon Sep 17 00:00:00 2001 From: David Steele Date: Tue, 1 Dec 2020 18:41:53 +0000 Subject: [PATCH] Moved sibling order algorithms out of actor-impl Reducing the line count of Internal::Actor to increase SAM score Change-Id: Icceb9d6a4d899a988a9d203f1879f1c84df3fe07 --- automated-tests/src/dali/utc-Dali-Actor.cpp | 337 ++++++++++++++++++++++++ dali/internal/event/actors/actor-declarations.h | 4 + dali/internal/event/actors/actor-impl.cpp | 207 +++------------ dali/internal/event/actors/actor-impl.h | 10 +- dali/internal/event/actors/actor-siblings.cpp | 200 ++++++++++++++ dali/internal/event/actors/actor-siblings.h | 108 ++++++++ dali/internal/file.list | 2 +- 7 files changed, 687 insertions(+), 181 deletions(-) create mode 100644 dali/internal/event/actors/actor-siblings.cpp create mode 100644 dali/internal/event/actors/actor-siblings.h diff --git a/automated-tests/src/dali/utc-Dali-Actor.cpp b/automated-tests/src/dali/utc-Dali-Actor.cpp index 5ac38fa..d23681c 100755 --- a/automated-tests/src/dali/utc-Dali-Actor.cpp +++ b/automated-tests/src/dali/utc-Dali-Actor.cpp @@ -5289,6 +5289,117 @@ int UtcDaliActorRaiseAbove(void) END_TEST; } +int UtcDaliActorRaiseAbove2(void) +{ + tet_infoline("UtcDaliActor RaiseToAbove test using SIBLING_ORDER property\n"); + + TestApplication application; + + Integration::Scene stage(application.GetScene()); + + Actor actorA = Actor::New(); + Actor actorB = Actor::New(); + Actor actorC = Actor::New(); + + actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + + actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + + actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + + actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT"); + actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT"); + + actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT"); + actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT"); + + actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT"); + actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT"); + + stage.Add(actorA); + stage.Add(actorB); + stage.Add(actorC); + + ResetTouchCallbacks(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION); + + // connect to actor touch signals, will use touch callbacks to determine which actor is on top. + // Only top actor will get touched. + actorA.TouchedSignal().Connect(TestTouchCallback); + actorB.TouchedSignal().Connect(TestTouchCallback2); + actorC.TouchedSignal().Connect(TestTouchCallback3); + + bool orderChangedSignal(false); + Actor orderChangedActor; + ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor); + DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f); + + Dali::Integration::Point point; + point.SetDeviceId(1); + point.SetState(PointState::DOWN); + point.SetScreenPosition(Vector2(10.f, 10.f)); + Dali::Integration::TouchEvent touchEvent; + touchEvent.AddPoint(point); + + application.ProcessEvent(touchEvent); + + DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION); + + ResetTouchCallbacks(); + + tet_printf("Raise actor B Above Actor C\n"); + + DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION); + int newOrder = actorC[DevelActor::Property::SIBLING_ORDER]; + actorB[DevelActor::Property::SIBLING_ORDER] = newOrder; + DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION); + DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION); + + // Ensure sorting happens at end of Core::ProcessEvents() before next touch + application.SendNotification(); + application.ProcessEvent(touchEvent); + + DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION); + + ResetTouchCallbacks(); + + tet_printf("Raise actor A Above Actor B\n"); + + orderChangedSignal = false; + + DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION); + newOrder = actorB[DevelActor::Property::SIBLING_ORDER]; + actorA[DevelActor::Property::SIBLING_ORDER] = newOrder; + DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION); + DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION); + + // Ensure sorting happens at end of Core::ProcessEvents() before next touch + application.SendNotification(); + + application.ProcessEvent(touchEvent); // process a touch event on ordered actors. + + DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION); + + ResetTouchCallbacks(); + + END_TEST; +} + int UtcDaliActorLowerBelow(void) { tet_infoline("UtcDaliActor LowerBelow test \n"); @@ -5514,6 +5625,232 @@ int UtcDaliActorLowerBelow(void) END_TEST; } + +int UtcDaliActorLowerBelow2(void) +{ + tet_infoline("UtcDaliActor LowerBelow test using SIBLING_ORDER property\n"); + + TestApplication application; + + Integration::Scene stage(application.GetScene()); + + // Set up renderers to add to Actors, float value 1, 2, 3 assigned to each + // enables checking of which actor the uniform is assigned too + Shader shaderA = CreateShader(); + shaderA.RegisterProperty("uRendererColor", 1.f); + + Shader shaderB = CreateShader(); + shaderB.RegisterProperty("uRendererColor", 2.f); + + Shader shaderC = CreateShader(); + shaderC.RegisterProperty("uRendererColor", 3.f); + + Actor actorA = Actor::New(); + Actor actorB = Actor::New(); + Actor actorC = Actor::New(); + + // Add renderers to Actors so ( uRendererColor, 1 ) is A, ( uRendererColor, 2 ) is B, and ( uRendererColor, 3 ) is C, + Geometry geometry = CreateQuadGeometry(); + + Renderer rendererA = Renderer::New(geometry, shaderA); + actorA.AddRenderer(rendererA); + + Renderer rendererB = Renderer::New(geometry, shaderB); + actorB.AddRenderer(rendererB); + + Renderer rendererC = Renderer::New(geometry, shaderC); + actorC.AddRenderer(rendererC); + + actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + + actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + + actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + + actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT"); + actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT"); + + actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT"); + actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT"); + + actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT"); + actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT"); + + Actor container = Actor::New(); + container.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + container.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS); + stage.Add(container); + + container.Add(actorA); + container.Add(actorB); + container.Add(actorC); + + ResetTouchCallbacks(); + + // Connect ChildOrderChangedSignal + bool orderChangedSignal(false); + Actor orderChangedActor; + ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor); + DevelActor::ChildOrderChangedSignal(container).Connect(&application, f); + + // Set up gl abstraction trace so can query the set uniform order + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableSetUniformCallTrace(true); + glAbstraction.ResetSetUniformCallStack(); + TraceCallStack& glSetUniformStack = glAbstraction.GetSetUniformTrace(); + + glAbstraction.ResetSetUniformCallStack(); + + application.SendNotification(); + application.Render(); + + glSetUniformStack = glAbstraction.GetSetUniformTrace(); + + tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str()); + + // Test order of uniforms in stack + int indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3"); + int indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2"); + int indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1"); + + tet_infoline("Testing C above B and A at bottom\n"); + bool CBA = (indexC > indexB) && (indexB > indexA); + + DALI_TEST_EQUALS(CBA, true, TEST_LOCATION); + + DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION); + + // connect to actor touch signals, will use touch callbacks to determine which actor is on top. + // Only top actor will get touched. + actorA.TouchedSignal().Connect(TestTouchCallback); + actorB.TouchedSignal().Connect(TestTouchCallback2); + actorC.TouchedSignal().Connect(TestTouchCallback3); + + Dali::Integration::Point point; + point.SetDeviceId(1); + point.SetState(PointState::DOWN); + point.SetScreenPosition(Vector2(10.f, 10.f)); + Dali::Integration::TouchEvent touchEvent; + touchEvent.AddPoint(point); + + tet_infoline("UtcDaliActor Test Set up completed \n"); + + application.ProcessEvent(touchEvent); + + DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION); + + ResetTouchCallbacks(); + + tet_printf("Lower actor C below Actor B ( actor B and A on same level due to insertion order) so C is below both \n"); + + DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION); + actorC[DevelActor::Property::SIBLING_ORDER] = 1; + DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION); + DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION); + + // Ensure sorting happens at end of Core::ProcessEvents() before next touch + application.SendNotification(); + application.Render(); + + application.ProcessEvent(touchEvent); // touch event + + glAbstraction.ResetSetUniformCallStack(); + glSetUniformStack = glAbstraction.GetSetUniformTrace(); + + application.SendNotification(); + application.Render(); + + tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str()); + + // Test order of uniforms in stack + indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3"); + indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2"); + indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1"); + + tet_infoline("Testing render order is A, C, B"); + DALI_TEST_EQUALS(indexC > indexA, true, TEST_LOCATION); + DALI_TEST_EQUALS(indexB > indexC, true, TEST_LOCATION); + + DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION); + + ResetTouchCallbacks(); + + tet_printf("Lower actor C below Actor A leaving B on top\n"); + + orderChangedSignal = false; + + DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION); + actorC[DevelActor::Property::SIBLING_ORDER] = 0; + DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION); + DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION); + + // Ensure sorting happens at end of Core::ProcessEvents() before next touch + application.SendNotification(); + application.Render(); + + application.ProcessEvent(touchEvent); + + glAbstraction.ResetSetUniformCallStack(); + glSetUniformStack = glAbstraction.GetSetUniformTrace(); + + application.Render(); + tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str()); + + // Test order of uniforms in stack + indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3"); + indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2"); + indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1"); + + DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION); + DALI_TEST_EQUALS(indexB > indexA, true, TEST_LOCATION); + + DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION); + DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION); + + ResetTouchCallbacks(); + + tet_printf("Lower actor B below Actor C leaving A on top\n"); + + orderChangedSignal = false; + + DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION); + actorB[DevelActor::Property::SIBLING_ORDER] = 0; + DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION); + DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION); + + // Ensure sorting happens at end of Core::ProcessEvents() before next touch + application.SendNotification(); + application.Render(); + + application.ProcessEvent(touchEvent); + + glAbstraction.ResetSetUniformCallStack(); + glSetUniformStack = glAbstraction.GetSetUniformTrace(); + + application.Render(); + tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str()); + + // Test order of uniforms in stack + indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3"); + indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2"); + indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1"); + + DALI_TEST_EQUALS(indexC > indexB, true, TEST_LOCATION); + DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION); + + END_TEST; +} + int UtcDaliActorRaiseAboveDifferentParentsN(void) { tet_infoline("UtcDaliActor RaiseToAbove test with actor and target actor having different parents \n"); diff --git a/dali/internal/event/actors/actor-declarations.h b/dali/internal/event/actors/actor-declarations.h index 72dfdac..f49bd1d 100644 --- a/dali/internal/event/actors/actor-declarations.h +++ b/dali/internal/event/actors/actor-declarations.h @@ -37,6 +37,10 @@ using CameraActorPtr = IntrusivePtr; using CustomActorPtr = IntrusivePtr; using LayerPtr = IntrusivePtr; +using ActorContainer = std::vector; +using ActorIter = ActorContainer::iterator; +using ActorConstIter = ActorContainer::const_iterator; + } // namespace Internal } // namespace Dali diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index cc6d998..bd47582 100755 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -33,21 +33,22 @@ #include #include #include +#include #include #include -#include -#include +#include #include -#include +#include +#include #include -#include -#include #include +#include #include -#include +#include +#include +#include #include #include -#include #include using Dali::Internal::SceneGraph::Node; @@ -2553,93 +2554,39 @@ void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage ) } } -void Actor::SetSiblingOrder( uint32_t order ) +void Actor::EmitOrderChangedAndRebuild() { - if ( mParent ) + Dali::Actor handle( this ); + mParent->mChildOrderChangedSignal.Emit( handle ); + if( mIsOnScene && mScene ) { - ActorContainer& siblings = *(mParent->mChildren); - uint32_t currentOrder = GetSiblingOrder(); - - if( order != currentOrder ) - { - if( order == 0 ) - { - LowerToBottom(); - } - else if( order < siblings.size() -1 ) - { - if( order > currentOrder ) - { - RaiseAbove( *siblings[order] ); - } - else - { - LowerBelow( *siblings[order] ); - } - } - else - { - RaiseToTop(); - } - } + mScene->RequestRebuildDepthTree(); } } -uint32_t Actor::GetSiblingOrder() const +void Actor::SetSiblingOrder( uint32_t order ) { - uint32_t order = 0; - - if ( mParent ) + if( mParent && SiblingHandler::SetSiblingOrder(*(mParent->mChildren), *this, order)) { - ActorContainer& siblings = *(mParent->mChildren); - for( std::size_t i = 0; i < siblings.size(); ++i ) - { - if( siblings[i] == this ) - { - order = static_cast( i ); - break; - } - } + EmitOrderChangedAndRebuild(); } - - return order; } -void Actor::RequestRebuildDepthTree() +uint32_t Actor::GetSiblingOrder() const { - if( mIsOnScene ) + uint32_t order = 0; + if( mParent ) { - if( mScene ) - { - mScene->RequestRebuildDepthTree(); - } + order = SiblingHandler::GetSiblingOrder(*(mParent->mChildren), *this); } + return order; } void Actor::Raise() { - if ( mParent ) + if( mParent && SiblingHandler::Raise(*(mParent->mChildren), *this) ) { - ActorContainer& siblings = *(mParent->mChildren); - if( siblings.back() != this ) // If not already at end - { - for( std::size_t i=0; imChildOrderChangedSignal.Emit( handle ); - - RequestRebuildDepthTree(); + EmitOrderChangedAndRebuild(); } else { @@ -2649,28 +2596,9 @@ void Actor::Raise() void Actor::Lower() { - if ( mParent ) + if( mParent && SiblingHandler::Lower(*(mParent->mChildren), *this) ) { - ActorContainer& siblings = *(mParent->mChildren); - if( siblings.front() != this ) // If not already at beginning - { - for( std::size_t i=1; imChildOrderChangedSignal.Emit( handle ); - - RequestRebuildDepthTree(); + EmitOrderChangedAndRebuild(); } else { @@ -2680,23 +2608,9 @@ void Actor::Lower() void Actor::RaiseToTop() { - if ( mParent ) + if( mParent && SiblingHandler::RaiseToTop(*(mParent->mChildren), *this) ) { - ActorContainer& siblings = *(mParent->mChildren); - if( siblings.back() != this ) // If not already at end - { - auto iter = std::find( siblings.begin(), siblings.end(), this ); - if( iter != siblings.end() ) - { - siblings.erase(iter); - siblings.push_back(ActorPtr(this)); - } - } - - Dali::Actor handle( this ); - mParent->mChildOrderChangedSignal.Emit( handle ); - - RequestRebuildDepthTree(); + EmitOrderChangedAndRebuild(); } else { @@ -2706,25 +2620,9 @@ void Actor::RaiseToTop() void Actor::LowerToBottom() { - if ( mParent ) + if( mParent && SiblingHandler::LowerToBottom(*(mParent->mChildren), *this) ) { - ActorContainer& siblings = *(mParent->mChildren); - if( siblings.front() != this ) // If not already at bottom, - { - ActorPtr thisPtr(this); // ensure this actor remains referenced. - - auto iter = std::find( siblings.begin(), siblings.end(), this ); - if( iter != siblings.end() ) - { - siblings.erase(iter); - siblings.insert(siblings.begin(), thisPtr); - } - } - - Dali::Actor handle( this ); - mParent->mChildOrderChangedSignal.Emit( handle ); - - RequestRebuildDepthTree(); + EmitOrderChangedAndRebuild(); } else { @@ -2734,30 +2632,9 @@ void Actor::LowerToBottom() void Actor::RaiseAbove( Internal::Actor& target ) { - if ( mParent ) + if( mParent && SiblingHandler::RaiseAbove( *(mParent->mChildren), *this, target )) { - ActorContainer& siblings = *(mParent->mChildren); - if( siblings.back() != this && target.mParent == mParent ) // If not already at top - { - ActorPtr thisPtr(this); // ensure this actor remains referenced. - - auto targetIter = std::find( siblings.begin(), siblings.end(), &target ); - auto thisIter = std::find( siblings.begin(), siblings.end(), this ); - if( thisIter < targetIter ) - { - siblings.erase(thisIter); - // Erasing early invalidates the targetIter. (Conversely, inserting first may also - // invalidate thisIter) - targetIter = std::find( siblings.begin(), siblings.end(), &target ); - ++targetIter; - siblings.insert(targetIter, thisPtr); - } - - Dali::Actor handle( this ); - mParent->mChildOrderChangedSignal.Emit( handle ); - - RequestRebuildDepthTree(); - } + EmitOrderChangedAndRebuild(); } else { @@ -2767,27 +2644,9 @@ void Actor::RaiseAbove( Internal::Actor& target ) void Actor::LowerBelow( Internal::Actor& target ) { - if ( mParent ) + if( mParent && SiblingHandler::LowerBelow(*(mParent->mChildren), *this, target ) ) { - ActorContainer& siblings = *(mParent->mChildren); - if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom - { - ActorPtr thisPtr(this); // ensure this actor remains referenced. - - auto targetIter = std::find( siblings.begin(), siblings.end(), &target ); - auto thisIter = std::find( siblings.begin(), siblings.end(), this ); - - if( thisIter > targetIter ) - { - siblings.erase(thisIter); // this only invalidates iterators at or after this point. - siblings.insert(targetIter, thisPtr); - } - - Dali::Actor handle( this ); - mParent->mChildOrderChangedSignal.Emit( handle ); - - RequestRebuildDepthTree(); - } + EmitOrderChangedAndRebuild(); } else { diff --git a/dali/internal/event/actors/actor-impl.h b/dali/internal/event/actors/actor-impl.h index 367beeb..249de1f 100755 --- a/dali/internal/event/actors/actor-impl.h +++ b/dali/internal/event/actors/actor-impl.h @@ -57,10 +57,6 @@ class RenderTask; class Renderer; class Scene; -using ActorContainer = std::vector; -using ActorIter = ActorContainer::iterator; -using ActorConstIter = ActorContainer::const_iterator; - using RendererContainer = std::vector; using RendererIter = RendererContainer::iterator; @@ -1974,9 +1970,10 @@ private: uint32_t GetSiblingOrder() const; /** - * Request that the stage rebuilds the actor depth indices. + * Emit ChildOrderChanged signal, and request that the scene + * rebuilds the actor depth indices. */ - void RequestRebuildDepthTree(); + void EmitOrderChangedAndRebuild(); /** * @brief Get the current position of the actor in screen coordinates. @@ -2089,6 +2086,7 @@ private: static ActorContainer mNullChildren; ///< Empty container (shared by all actors, returned by GetChildren() const) struct PropertyHandler; + struct SiblingHandler; }; } // namespace Internal diff --git a/dali/internal/event/actors/actor-siblings.cpp b/dali/internal/event/actors/actor-siblings.cpp new file mode 100644 index 0000000..c8cbf2e --- /dev/null +++ b/dali/internal/event/actors/actor-siblings.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2020 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 + +namespace Dali +{ +namespace Internal +{ + +bool Actor::SiblingHandler::SetSiblingOrder( + ActorContainer& siblings, + Actor& actor, + uint32_t order ) +{ + bool changed = false; + + uint32_t currentOrder = GetSiblingOrder(siblings, actor); + if( order != currentOrder ) + { + if( order == 0 ) + { + changed = LowerToBottom(siblings, actor); + } + else if( order < siblings.size() -1 ) + { + if( order > currentOrder ) + { + changed = RaiseAbove( siblings, actor, *siblings[order] ); + } + else + { + changed = LowerBelow( siblings, actor, *siblings[order] ); + } + } + else + { + changed = RaiseToTop(siblings, actor); + } + } + return changed; +} + +uint32_t Actor::SiblingHandler::GetSiblingOrder(const ActorContainer& siblings, const Actor& actor) +{ + uint32_t order=0; + for( std::size_t i = 0; i < siblings.size(); ++i ) + { + if( siblings[i] == &actor ) + { + order = static_cast( i ); + break; + } + } + return order; +} + +bool Actor::SiblingHandler::Raise(ActorContainer& siblings, Actor& actor) +{ + bool changed = false; + if( siblings.back() != &actor ) // If not already at end + { + for( std::size_t i=0; i targetIter ) + { + siblings.erase(actorIter); // actor only invalidates iterators at or after actor point. + siblings.insert(targetIter, actorPtr); + } + lowered = true; + } + return lowered; +} + + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actors/actor-siblings.h b/dali/internal/event/actors/actor-siblings.h new file mode 100644 index 0000000..9af67ba --- /dev/null +++ b/dali/internal/event/actors/actor-siblings.h @@ -0,0 +1,108 @@ +#ifndef DALI_INTERNAL_ACTOR_SIBLINGS_H +#define DALI_INTERNAL_ACTOR_SIBLINGS_H +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use actor 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 + +namespace Dali +{ +namespace Internal +{ + +struct Actor::SiblingHandler +{ + /** + * @brief Change the sibling order of the given actor. + * + * @param[in,out] siblings The container of siblings + * @param[in] actor The actor to change + * @param[in] order The new order for the actor + * @return true if order has been modified + */ + static bool SetSiblingOrder( ActorContainer& siblings, Actor& actor, uint32_t order ); + + /** + * @brief Get the sibling order of the given actor. + * + * @param[in] siblings The container of siblings + * @param[in] actor The actor to query + * @return the order in the sibling array of the actor + */ + static uint32_t GetSiblingOrder(const ActorContainer& siblings, const Actor& actor); + + /** + * @brief Raise the actor within the siblings list by one + * @param[in,out] siblings The container of siblings + * @param[in] actor The actor to move + * @return true if order has been modified + */ + static bool Raise(ActorContainer& siblings, Actor& actor); + + /** + * @brief Lower the actor within the siblings list by one + * @param[in,out] siblings The container of siblings + * @param[in] actor The actor to move + * @return true if order has been modified + */ + static bool Lower(ActorContainer& siblings, Actor& actor); + + /** + * @brief Raise the actor to the top of the siblings list. + * + * @param[in,out] siblings The container of siblings + * @param[in] actor The actor to move + * @return true if order has been modified + */ + static bool RaiseToTop(ActorContainer& siblings, Actor& actor); + + /** + * @brief Lower the actor to the bottom of the siblings list. + * + * @param[in,out] siblings The container of siblings + * @param[in] actor The actor to move + * @return true if order has been modified + */ + static bool LowerToBottom(ActorContainer& siblings, Actor& actor); + + /** + * @brief Raise the actor above the target actor within the siblings list. + * + * @param[in,out] siblings The container of siblings + * @param[in] actor The actor to move + * @param[in] target The target actor + * @return true if order has been modified + */ + static bool RaiseAbove(ActorContainer& siblings, Actor& actor, Actor& target); + + /** + * @brief Lower the actor below the target actor within the siblings list. + * + * @param[in,out] siblings The container of siblings + * @param[in] actor The actor to move + * @param[in] target The target actor + * @return true if order has been modified + */ + static bool LowerBelow(ActorContainer& siblings, Actor& actor, Actor& target); +}; + +} // namespace Internal + +} // namespace Dali + + +#endif diff --git a/dali/internal/file.list b/dali/internal/file.list index 07cf4ff..e18a954 100644 --- a/dali/internal/file.list +++ b/dali/internal/file.list @@ -13,10 +13,10 @@ SET( internal_src_files ${internal_src_dir}/common/fixed-size-memory-pool.cpp ${internal_src_dir}/common/const-string.cpp - ${internal_src_dir}/event/actors/actor-impl.cpp ${internal_src_dir}/event/actors/actor-property-handler.cpp ${internal_src_dir}/event/actors/actor-relayouter.cpp + ${internal_src_dir}/event/actors/actor-siblings.cpp ${internal_src_dir}/event/actors/custom-actor-internal.cpp ${internal_src_dir}/event/actors/layer-impl.cpp ${internal_src_dir}/event/actors/layer-list.cpp -- 2.7.4