X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Factors%2Factor-impl.cpp;h=ab20929f0ab56d9f715e5f80c25c670985af9b6d;hb=d67b366a74050ddec47340ff10a0188c0d381561;hp=f2ae10b06a0bdca22cf8c190a04cfd7bfd813ff6;hpb=66df8a861f62fcb1ec441544e9ac6a10adf27002;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index f2ae10b..ab20929 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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,7 +20,6 @@ // EXTERNAL INCLUDES #include -#include #include // INTERNAL INCLUDES @@ -32,17 +31,16 @@ #include #include -#include #include #include +#include +#include #include #include -#include #include #include -#include #include #include #include @@ -51,8 +49,10 @@ #include #include #include -#include +#include +#include #include +#include using Dali::Internal::SceneGraph::AnimatableProperty; using Dali::Internal::SceneGraph::Node; @@ -141,11 +141,15 @@ DALI_PROPERTY("isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ DALI_PROPERTY("isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER) DALI_PROPERTY("connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE) DALI_PROPERTY("keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE) +DALI_PROPERTY("updateAreaHint", VECTOR4, true, false, false, Dali::Actor::Property::UPDATE_AREA_HINT) DALI_PROPERTY("siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER) -DALI_PROPERTY("updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT) DALI_PROPERTY("captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START) -DALI_PROPERTY("touchArea", VECTOR2, true, false, false, Dali::DevelActor::Property::TOUCH_AREA) +DALI_PROPERTY("touchAreaOffset", RECTANGLE, true, false, false, Dali::DevelActor::Property::TOUCH_AREA_OFFSET) DALI_PROPERTY("blendEquation", INTEGER, true, false, false, Dali::DevelActor::Property::BLEND_EQUATION) +DALI_PROPERTY("touchFocusable", BOOLEAN, true, false, false, Dali::DevelActor::Property::TOUCH_FOCUSABLE) +DALI_PROPERTY("keyboardFocusableChildren", BOOLEAN, true, false, false, Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN) +DALI_PROPERTY("userInteractionEnabled", BOOLEAN, true, false, false, Dali::DevelActor::Property::USER_INTERACTION_ENABLED) +DALI_PROPERTY("allowOnlyOwnTouch", BOOLEAN, true, false, false, Dali::DevelActor::Property::ALLOW_ONLY_OWN_TOUCH) DALI_PROPERTY_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties) // Signals @@ -171,61 +175,122 @@ BaseHandle CreateActor() return Dali::Actor::New(); } -TypeRegistration mType(typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties); +/** + * 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) +{ + bool connected(true); + Actor* actor = static_cast(object); // TypeRegistry guarantees that this is the correct type. + + std::string_view name(signalName); -SignalConnectorType signalConnector2(mType, std::string(SIGNAL_HOVERED), &Actor::DoConnectSignal); -SignalConnectorType signalConnector3(mType, std::string(SIGNAL_WHEEL_EVENT), &Actor::DoConnectSignal); -SignalConnectorType signalConnector4(mType, std::string(SIGNAL_ON_SCENE), &Actor::DoConnectSignal); -SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &Actor::DoConnectSignal); -SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &Actor::DoConnectSignal); -SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &Actor::DoConnectSignal); -SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &Actor::DoConnectSignal); -SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &Actor::DoConnectSignal); -SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &Actor::DoConnectSignal); -SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &Actor::DoConnectSignal); + if(name == SIGNAL_HOVERED) + { + actor->HoveredSignal().Connect(tracker, functor); + } + else if(signalName == SIGNAL_WHEEL_EVENT) + { + actor->WheelEventSignal().Connect(tracker, functor); + } + else if(name == SIGNAL_ON_SCENE) + { + actor->OnSceneSignal().Connect(tracker, functor); + } + else if(name == SIGNAL_OFF_SCENE) + { + actor->OffSceneSignal().Connect(tracker, functor); + } + else if(name == SIGNAL_ON_RELAYOUT) + { + actor->OnRelayoutSignal().Connect(tracker, functor); + } + else if(name == SIGNAL_TOUCHED) + { + actor->TouchedSignal().Connect(tracker, functor); + } + else if(name == SIGNAL_VISIBILITY_CHANGED) + { + actor->VisibilityChangedSignal().Connect(tracker, functor); + } + else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED) + { + actor->LayoutDirectionChangedSignal().Connect(tracker, functor); + } + else if(name == SIGNAL_CHILD_ADDED) + { + actor->ChildAddedSignal().Connect(tracker, functor); + } + else if(name == SIGNAL_CHILD_REMOVED) + { + actor->ChildRemovedSignal().Connect(tracker, functor); + } + else + { + // signalName does not match any signal + connected = false; + } -TypeAction a1(mType, std::string(ACTION_SHOW), &Actor::DoAction); -TypeAction a2(mType, std::string(ACTION_HIDE), &Actor::DoAction); + return connected; +} /** - * @brief Extract a given dimension from a Vector2 - * - * @param[in] values The values to extract from - * @param[in] dimension The dimension to extract - * @return Return the value for the dimension + * Performs actions as requested using the action name. + * @param[in] object The object on which to perform the action. + * @param[in] actionName The action to perform. + * @param[in] attributes The attributes with which to perfrom this action. + * @return true if the action was done. */ -constexpr float GetDimensionValue(const Vector2& values, Dimension::Type dimension) +bool DoAction(BaseObject* object, + const std::string& actionName, + const Property::Map& attributes) { - switch(dimension) + bool done = false; + Actor* actor = dynamic_cast(object); + + if(actor) { - case Dimension::WIDTH: - { - return values.width; - } - case Dimension::HEIGHT: + std::string_view name(actionName); + if(name == ACTION_SHOW) { - return values.height; + actor->SetVisible(true); + done = true; } - default: + else if(name == ACTION_HIDE) { - break; + actor->SetVisible(false); + done = true; } } - return 0.0f; -} -/** - * @brief Extract a given dimension from a Vector3 - * - * @param[in] values The values to extract from - * @param[in] dimension The dimension to extract - * @return Return the value for the dimension - */ -float GetDimensionValue(const Vector3& values, Dimension::Type dimension) -{ - return GetDimensionValue(values.GetVectorXY(), dimension); + return done; } +TypeRegistration mType(typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties); + +SignalConnectorType signalConnector2(mType, std::string(SIGNAL_HOVERED), &DoConnectSignal); +SignalConnectorType signalConnector3(mType, std::string(SIGNAL_WHEEL_EVENT), &DoConnectSignal); +SignalConnectorType signalConnector4(mType, std::string(SIGNAL_ON_SCENE), &DoConnectSignal); +SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &DoConnectSignal); +SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &DoConnectSignal); +SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &DoConnectSignal); +SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &DoConnectSignal); +SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &DoConnectSignal); +SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &DoConnectSignal); +SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &DoConnectSignal); + +TypeAction a1(mType, std::string(ACTION_SHOW), &DoAction); +TypeAction a2(mType, std::string(ACTION_HIDE), &DoAction); + /// Helper for emitting a signal template bool EmitConsumingSignal(Actor& actor, Signal& signal, const Event& event) @@ -252,58 +317,33 @@ void EmitSignal(Actor& actor, Signal& signal, Param... params) } } -bool ScreenToLocalInternal( - const Matrix& viewMatrix, - const Matrix& projectionMatrix, - const Matrix& worldMatrix, - const Viewport& viewport, - const Vector3& currentSize, - float& localX, - float& localY, - float screenX, - float screenY) -{ - // Get the ModelView matrix - Matrix modelView; - Matrix::Multiply(modelView, worldMatrix, viewMatrix); - - // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects - Matrix invertedMvp(false /*don't init*/); - Matrix::Multiply(invertedMvp, modelView, projectionMatrix); - bool success = invertedMvp.Invert(); - - // Convert to GL coordinates - Vector4 screenPos(screenX - static_cast(viewport.x), static_cast(viewport.height) - screenY - static_cast(viewport.y), 0.f, 1.f); +using ActorParentSiblingOrderMethod = void (ActorParent::*)(Actor&); +using ActorParentSiblingOrderMethodWithTarget = void (ActorParent::*)(Actor&, Actor&); - Vector4 nearPos; - if(success) +/// Helper to check and call actor sibling methods in ActorParent +void CheckParentAndCall(ActorParent* parent, Actor& actor, ActorParentSiblingOrderMethod memberFunction) +{ + if(parent) { - success = Unproject(screenPos, invertedMvp, static_cast(viewport.width), static_cast(viewport.height), nearPos); + (parent->*memberFunction)(actor); } - - Vector4 farPos; - if(success) + else { - screenPos.z = 1.0f; - success = Unproject(screenPos, invertedMvp, static_cast(viewport.width), static_cast(viewport.height), farPos); + DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n"); } +} - if(success) +/// Helper to check and call actor sibling methods with a target parameter in ActorParent +void CheckParentAndCall(ActorParent* parent, Actor& actor, Actor& target, ActorParentSiblingOrderMethodWithTarget memberFunction) +{ + if(parent) { - Vector4 local; - if(XyPlaneIntersect(nearPos, farPos, local)) - { - Vector3 size = currentSize; - localX = local.x + size.x * 0.5f; - localY = local.y + size.y * 0.5f; - } - else - { - success = false; - } + (parent->*memberFunction)(actor, target); + } + else + { + DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n"); } - - return success; } } // unnamed namespace @@ -333,12 +373,12 @@ const SceneGraph::Node* Actor::CreateNode() return node; } -void Actor::SetName(const std::string& name) +void Actor::SetName(std::string_view name) { - mName = name; + mName = ConstString(name); // ATTENTION: string for debug purposes is not thread safe. - DALI_LOG_SET_OBJECT_STRING(const_cast(&GetNode()), name); + DALI_LOG_SET_OBJECT_STRING(const_cast(&GetNode()), mName.GetCString()); } uint32_t Actor::GetId() const @@ -497,21 +537,19 @@ const Vector3& Actor::GetCurrentWorldPosition() const const Vector2 Actor::GetCurrentScreenPosition() const { - if(mScene && OnScene()) + if(mScene) { - Vector3 worldPosition = GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex()); - Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex()); - worldPosition -= cameraPosition; - - Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale(); - Vector2 halfSceneSize(mScene->GetSize() * 0.5f); // World position origin is center of scene - Vector3 halfActorSize(actorSize * 0.5f); - Vector3 anchorPointOffSet = halfActorSize - actorSize * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT); - - return Vector2(halfSceneSize.width + worldPosition.x - anchorPointOffSet.x, - halfSceneSize.height + worldPosition.y - anchorPointOffSet.y); + BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex(); + if(mLayer3DParentsCount == 0) + { + // We can assume that this actor is under 2d layer. Use faster, but imprecise algorithm + return CalculateActorScreenPosition(*this, bufferIndex); + } + else + { + return CalculateActorScreenPositionRenderTaskList(*this, bufferIndex); + } } - return Vector2::ZERO; } @@ -737,19 +775,12 @@ void Actor::SetInheritOrientation(bool inherit) void Actor::SetSizeModeFactor(const Vector3& factor) { - EnsureRelayouter(); - - mRelayoutData->sizeModeFactor = factor; + mSizer.SetSizeModeFactor(factor); } const Vector3& Actor::GetSizeModeFactor() const { - if(mRelayoutData) - { - return mRelayoutData->sizeModeFactor; - } - - return Relayouter::DEFAULT_SIZE_MODE_FACTOR; + return mSizer.GetSizeModeFactor(); } void Actor::SetColorMode(ColorMode colorMode) @@ -775,137 +806,31 @@ void Actor::SetSize(const Vector2& size) SetSize(Vector3(size.width, size.height, 0.f)); } -void Actor::SetSizeInternal(const Vector2& size) -{ - SetSizeInternal(Vector3(size.width, size.height, 0.f)); -} - void Actor::SetSize(const Vector3& size) { - if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout) - { - // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!! - SetPreferredSize(size.GetVectorXY()); - } - else - { - SetSizeInternal(size); - } -} - -void Actor::SetSizeInternal(const Vector3& size) -{ - // dont allow recursive loop - DALI_ASSERT_ALWAYS(!mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet"); - // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one - if((fabsf(mTargetSize.width - size.width) > Math::MACHINE_EPSILON_1) || - (fabsf(mTargetSize.height - size.height) > Math::MACHINE_EPSILON_1) || - (fabsf(mTargetSize.depth - size.depth) > Math::MACHINE_EPSILON_1)) - { - mTargetSize = size; - - // node is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformPropertyMessage::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler::Bake, mTargetSize); - - // Notification for derived classes - mInsideOnSizeSet = true; - OnSizeSet(mTargetSize); - mInsideOnSizeSet = false; - - // Raise a relayout request if the flag is not locked - if(mRelayoutData && !mRelayoutData->insideRelayout) - { - RelayoutRequest(); - } - } + mSizer.SetSize(size); } void Actor::SetWidth(float width) { - if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout) - { - SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH); - mRelayoutData->preferredSize.width = width; - } - else - { - mTargetSize.width = width; - - // node is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformComponentMessage::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler::BakeX, width); - } - - mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH; - - RelayoutRequest(); + mSizer.SetWidth(width); } void Actor::SetHeight(float height) { - if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout) - { - SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT); - mRelayoutData->preferredSize.height = height; - } - else - { - mTargetSize.height = height; - - // node is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodeTransformComponentMessage::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler::BakeY, height); - } - - mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT; - - RelayoutRequest(); + mSizer.SetHeight(height); } void Actor::SetDepth(float depth) { - mTargetSize.depth = depth; - - mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH; - + mSizer.SetDepth(depth); // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodeTransformComponentMessage::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler::BakeZ, depth); } Vector3 Actor::GetTargetSize() const { - Vector3 size = mTargetSize; - - if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH) - { - // Should return animated size if size is animated - size.width = mAnimatedSize.width; - } - else - { - // Should return preferred size if size is fixed as set by SetSize - if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::FIXED) - { - size.width = GetPreferredSize().width; - } - } - - if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT) - { - size.height = mAnimatedSize.height; - } - else - { - if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::FIXED) - { - size.height = GetPreferredSize().height; - } - } - - if(mUseAnimatedSize & AnimatedSizeFlag::DEPTH) - { - size.depth = mAnimatedSize.depth; - } - - return size; + return mSizer.GetTargetSize(); } const Vector3& Actor::GetCurrentSize() const @@ -922,165 +847,76 @@ Vector3 Actor::GetNaturalSize() const void Actor::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension) { - EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize); - - OnSetResizePolicy(policy, dimension); - - // Trigger relayout on this control - RelayoutRequest(); + mSizer.SetResizePolicy(policy, dimension); } ResizePolicy::Type Actor::GetResizePolicy(Dimension::Type dimension) const { - if(mRelayoutData) - { - return mRelayoutData->GetResizePolicy(dimension); - } - - return ResizePolicy::DEFAULT; -} - -void Actor::SetSizeScalePolicy(SizeScalePolicy::Type policy) -{ - EnsureRelayouter(); - - mRelayoutData->sizeSetPolicy = policy; - - // Trigger relayout on this control - RelayoutRequest(); -} - -SizeScalePolicy::Type Actor::GetSizeScalePolicy() const -{ - if(mRelayoutData) - { - return mRelayoutData->sizeSetPolicy; - } - - return Relayouter::DEFAULT_SIZE_SCALE_POLICY; -} - -void Actor::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency) -{ - EnsureRelayouter().SetDimensionDependency(dimension, dependency); -} - -Dimension::Type Actor::GetDimensionDependency(Dimension::Type dimension) const -{ - if(mRelayoutData) - { - return mRelayoutData->GetDimensionDependency(dimension); - } - - return Dimension::ALL_DIMENSIONS; // Default + return mSizer.GetResizePolicy(dimension); } void Actor::SetRelayoutEnabled(bool relayoutEnabled) { - // If relayout data has not been allocated yet and the client is requesting - // to disable it, do nothing - if(mRelayoutData || relayoutEnabled) - { - EnsureRelayouter(); - - DALI_ASSERT_DEBUG(mRelayoutData && "mRelayoutData not created"); - - mRelayoutData->relayoutEnabled = relayoutEnabled; - } + mSizer.SetRelayoutEnabled(relayoutEnabled); } bool Actor::IsRelayoutEnabled() const { - // Assume that if relayout data has not been allocated yet then - // relayout is disabled - return mRelayoutData && mRelayoutData->relayoutEnabled; + return mSizer.IsRelayoutEnabled(); } void Actor::SetLayoutDirty(bool dirty, Dimension::Type dimension) { - EnsureRelayouter().SetLayoutDirty(dirty, dimension); + mSizer.SetLayoutDirty(dirty, dimension); } bool Actor::IsLayoutDirty(Dimension::Type dimension) const { - return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension); + return mSizer.IsLayoutDirty(dimension); } bool Actor::RelayoutPossible(Dimension::Type dimension) const { - return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty(dimension); + return mSizer.RelayoutPossible(dimension); } bool Actor::RelayoutRequired(Dimension::Type dimension) const { - return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty(dimension); + return mSizer.RelayoutRequired(dimension); } uint32_t Actor::AddRenderer(Renderer& renderer) { if(!mRenderers) { - mRenderers = new RendererContainer; - } - - if(mIsBlendEquationSet) - { - renderer.SetBlendEquation(static_cast(mBlendEquation)); + mRenderers = new RendererContainer(GetEventThreadServices()); } - - uint32_t index = static_cast(mRenderers->size()); // 4,294,967,295 renderers per actor - RendererPtr rendererPtr = RendererPtr(&renderer); - mRenderers->push_back(rendererPtr); - AttachRendererMessage(GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject()); - return index; + return mRenderers->Add(GetNode(), renderer, mIsBlendEquationSet, mBlendEquation); } uint32_t Actor::GetRendererCount() const { - uint32_t rendererCount(0); - if(mRenderers) - { - rendererCount = static_cast(mRenderers->size()); // 4,294,967,295 renderers per actor - } - - return rendererCount; + return mRenderers ? mRenderers->GetCount() : 0u; } RendererPtr Actor::GetRendererAt(uint32_t index) { - RendererPtr renderer; - if(index < GetRendererCount()) - { - renderer = (*mRenderers)[index]; - } - - return renderer; + return mRenderers ? mRenderers->GetRendererAt(index) : nullptr; } void Actor::RemoveRenderer(Renderer& renderer) { if(mRenderers) { - RendererIter end = mRenderers->end(); - for(RendererIter iter = mRenderers->begin(); iter != end; ++iter) - { - if((*iter).Get() == &renderer) - { - mRenderers->erase(iter); - DetachRendererMessage(GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject()); - break; - } - } + mRenderers->Remove(GetNode(), renderer); } } void Actor::RemoveRenderer(uint32_t index) { - if(index < GetRendererCount()) + if(mRenderers) { - RendererPtr renderer = (*mRenderers)[index]; - DetachRendererMessage(GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject()); - mRenderers->erase(mRenderers->begin() + index); + mRenderers->Remove(GetNode(), index); } } @@ -1090,12 +926,10 @@ void Actor::SetBlendEquation(DevelBlendEquation::Type blendEquation) { if(mBlendEquation != blendEquation) { - mBlendEquation = blendEquation; - uint32_t rendererCount = GetRendererCount(); - for(uint32_t i = 0; i < rendererCount; ++i) + mBlendEquation = blendEquation; + if(mRenderers) { - RendererPtr renderer = GetRendererAt(i); - renderer->SetBlendEquation(static_cast(blendEquation)); + mRenderers->SetBlending(blendEquation); } } mIsBlendEquationSet = true; @@ -1111,6 +945,16 @@ DevelBlendEquation::Type Actor::GetBlendEquation() const return mBlendEquation; } +void Actor::SetTransparent(bool transparent) +{ + SetTransparentMessage(GetEventThreadServices(), GetNode(), transparent); +} + +bool Actor::IsTransparent() const +{ + return GetNode().IsTransparent(); +} + void Actor::SetDrawMode(DrawMode::Type drawMode) { // this flag is not animatable so keep the value @@ -1122,54 +966,17 @@ void Actor::SetDrawMode(DrawMode::Type drawMode) bool Actor::ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const { - // only valid when on-stage - if(mScene && OnScene()) - { - const RenderTaskList& taskList = mScene->GetRenderTaskList(); - - Vector2 converted(screenX, screenY); - - // do a reverse traversal of all lists (as the default onscreen one is typically the last one) - uint32_t taskCount = taskList.GetTaskCount(); - for(uint32_t i = taskCount; i > 0; --i) - { - RenderTaskPtr task = taskList.GetTask(i - 1); - if(ScreenToLocal(*task, localX, localY, screenX, screenY)) - { - // found a task where this conversion was ok so return - return true; - } - } - } - return false; + return mScene && OnScene() && ConvertScreenToLocalRenderTaskList(mScene->GetRenderTaskList(), GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY); } bool Actor::ScreenToLocal(const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY) const { - bool retval = false; - // only valid when on-stage - if(OnScene()) - { - CameraActor* camera = renderTask.GetCameraActor(); - if(camera) - { - Viewport viewport; - renderTask.GetViewport(viewport); - - // need to translate coordinates to render tasks coordinate space - Vector2 converted(screenX, screenY); - if(renderTask.TranslateCoordinates(converted)) - { - retval = ScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y); - } - } - } - return retval; + return OnScene() && ConvertScreenToLocalRenderTask(renderTask, GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY); } bool Actor::ScreenToLocal(const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY) const { - return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY); + return OnScene() && ConvertScreenToLocal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), GetCurrentSize(), viewport, localX, localY, screenX, screenY); } ActorGestureData& Actor::GetGestureData() @@ -1218,6 +1025,22 @@ void Actor::EmitLayoutDirectionChangedSignal(LayoutDirection::Type type) EmitSignal(*this, mLayoutDirectionChangedSignal, type); } +bool Actor::EmitHitTestResultSignal(Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) +{ + bool hit = true; + + if(IsHitTestResultRequired()) + { + Dali::Actor handle(this); + Integration::Point newPoint(point); + newPoint.SetHitActor(handle); + newPoint.SetLocalPosition(hitPointLocal); + Dali::TouchEvent touchEvent = Dali::Integration::NewTouchEvent(timeStamp, newPoint); + hit = mHitTestResultSignal.Emit(handle, touchEvent); + } + return hit; +} + DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal() { return mParentImpl.ChildAddedSignal(); @@ -1233,71 +1056,15 @@ DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal() return mParentImpl.ChildOrderChangedSignal(); } -bool Actor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor) -{ - bool connected(true); - Actor* actor = static_cast(object); // TypeRegistry guarantees that this is the correct type. - - std::string_view name(signalName); - - if(name == SIGNAL_HOVERED) - { - actor->HoveredSignal().Connect(tracker, functor); - } - else if(signalName == SIGNAL_WHEEL_EVENT) - { - actor->WheelEventSignal().Connect(tracker, functor); - } - else if(name == SIGNAL_ON_SCENE) - { - actor->OnSceneSignal().Connect(tracker, functor); - } - else if(name == SIGNAL_OFF_SCENE) - { - actor->OffSceneSignal().Connect(tracker, functor); - } - else if(name == SIGNAL_ON_RELAYOUT) - { - actor->OnRelayoutSignal().Connect(tracker, functor); - } - else if(name == SIGNAL_TOUCHED) - { - actor->TouchedSignal().Connect(tracker, functor); - } - else if(name == SIGNAL_VISIBILITY_CHANGED) - { - actor->VisibilityChangedSignal().Connect(tracker, functor); - } - else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED) - { - actor->LayoutDirectionChangedSignal().Connect(tracker, functor); - } - else if(name == SIGNAL_CHILD_ADDED) - { - actor->ChildAddedSignal().Connect(tracker, functor); - } - else if(name == SIGNAL_CHILD_REMOVED) - { - actor->ChildRemovedSignal().Connect(tracker, functor); - } - else - { - // signalName does not match any signal - connected = false; - } - - return connected; -} - Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node) : Object(&node), mParentImpl(*this), + mSizer(*this), mParent(nullptr), mScene(nullptr), mRenderers(nullptr), mParentOrigin(nullptr), mAnchorPoint(nullptr), - mRelayoutData(nullptr), mGestureData(nullptr), mInterceptTouchedSignal(), mTouchedSignal(), @@ -1308,25 +1075,25 @@ Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node) mOnRelayoutSignal(), mVisibilityChangedSignal(), mLayoutDirectionChangedSignal(), + mHitTestResultSignal(), mTargetOrientation(Quaternion::IDENTITY), mTargetColor(Color::WHITE), - mTargetSize(Vector3::ZERO), mTargetPosition(Vector3::ZERO), mTargetScale(Vector3::ONE), - mAnimatedSize(Vector3::ZERO), - mTouchArea(Vector2::ZERO), + mTouchAreaOffset(0, 0, 0, 0), mName(), mSortedDepth(0u), mDepth(0u), - mUseAnimatedSize(AnimatedSizeFlag::CLEAR), + mLayer3DParentsCount(0), mIsRoot(ROOT_LAYER == derivedType), mIsLayer(LAYER == derivedType || ROOT_LAYER == derivedType), mIsOnScene(false), mSensitive(true), mLeaveRequired(false), mKeyboardFocusable(false), + mKeyboardFocusableChildren(true), + mTouchFocusable(false), mOnSceneSignalled(false), - mInsideOnSizeSet(false), mInheritPosition(true), mInheritOrientation(true), mInheritScale(true), @@ -1334,12 +1101,15 @@ Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node) mVisible(true), mInheritLayoutDirection(true), mCaptureAllTouchAfterStart(false), + mIsBlendEquationSet(false), + mNeedGesturePropagation(false), + mUserInteractionEnabled(true), + mAllowOnlyOwnTouch(false), mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT), mDrawMode(DrawMode::NORMAL), mColorMode(Node::DEFAULT_COLOR_MODE), mClippingMode(ClippingMode::DISABLED), - mBlendEquation(DevelBlendEquation::ADD), - mIsBlendEquationSet(false) + mBlendEquation(DevelBlendEquation::ADD) { } @@ -1375,19 +1145,33 @@ Actor::~Actor() // Cleanup optional parent origin and anchor delete mParentOrigin; delete mAnchorPoint; +} - // Delete optional relayout data - delete mRelayoutData; +void Actor::Add(Actor& child, bool notify) +{ + mParentImpl.Add(child, notify); } -void Actor::Add(Actor& child) +void Actor::Remove(Actor& child, bool notify) { - mParentImpl.Add(child); + mParentImpl.Remove(child, notify); } -void Actor::Remove(Actor& child) +void Actor::SwitchParent(Actor& newParent) { - mParentImpl.Remove(child); + if(this == &newParent) + { + DALI_LOG_ERROR("Cannot add actor to itself"); + return; + } + + if(!this->OnScene() || !newParent.OnScene()) + { + DALI_LOG_ERROR("Both of current parent and new parent must be on Scene"); + return; + } + + newParent.Add(*this, false); } uint32_t Actor::GetChildCount() const @@ -1405,7 +1189,7 @@ ActorContainer& Actor::GetChildrenInternal() return mParentImpl.GetChildrenInternal(); } -ActorPtr Actor::FindChildByName(const std::string& actorName) +ActorPtr Actor::FindChildByName(ConstString actorName) { return mParentImpl.FindChildByName(actorName); } @@ -1420,7 +1204,7 @@ void Actor::UnparentChildren() mParentImpl.UnparentChildren(); } -void Actor::ConnectToScene(uint32_t parentDepth) +void Actor::ConnectToScene(uint32_t parentDepth, uint32_t layer3DParentsCount, bool notify) { // This container is used instead of walking the Actor hierarchy. // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks. @@ -1431,44 +1215,18 @@ void Actor::ConnectToScene(uint32_t parentDepth) mScene->RequestRebuildDepthTree(); } - // This stage is atomic i.e. not interrupted by user callbacks. - RecursiveConnectToScene(connectionList, parentDepth + 1); + // This stage is not interrupted by user callbacks. + mParentImpl.RecursiveConnectToScene(connectionList, layer3DParentsCount, parentDepth + 1); // Notify applications about the newly connected actors. for(const auto& actor : connectionList) { - actor->NotifyStageConnection(); + actor->NotifyStageConnection(notify); } RelayoutRequest(); } -void Actor::RecursiveConnectToScene(ActorContainer& connectionList, uint32_t depth) -{ - DALI_ASSERT_ALWAYS(!OnScene()); - - mIsOnScene = true; - mDepth = static_cast(depth); // overflow ignored, not expected in practice - - ConnectToSceneGraph(); - - // Notification for internal derived classes - OnSceneConnectionInternal(); - - // This stage is atomic; avoid emitting callbacks until all Actors are connected - connectionList.push_back(ActorPtr(this)); - - // Recursively connect children - if(GetChildCount() > 0) - { - for(const auto& child : mParentImpl.GetChildrenInternal()) - { - child->SetScene(*mScene); - child->RecursiveConnectToScene(connectionList, depth + 1); - } - } -} - /** * This method is called when the Actor is connected to the Stage. * The parent must have added its Node to the scene-graph. @@ -1489,19 +1247,22 @@ void Actor::ConnectToSceneGraph() OnSceneObjectAdd(); } -void Actor::NotifyStageConnection() +void Actor::NotifyStageConnection(bool notify) { // Actors can be removed (in a callback), before the on-stage stage is reported. // The actor may also have been reparented, in which case mOnSceneSignalled will be true. if(OnScene() && !mOnSceneSignalled) { - // Notification for external (CustomActor) derived classes - OnSceneConnectionExternal(mDepth); - - if(!mOnSceneSignal.Empty()) + if(notify) { - Dali::Actor handle(this); - mOnSceneSignal.Emit(handle); + // Notification for external (CustomActor) derived classes + OnSceneConnectionExternal(mDepth); + + if(!mOnSceneSignal.Empty()) + { + Dali::Actor handle(this); + mOnSceneSignal.Emit(handle); + } } // Guard against Remove during callbacks @@ -1512,7 +1273,7 @@ void Actor::NotifyStageConnection() } } -void Actor::DisconnectFromStage() +void Actor::DisconnectFromStage(bool notify) { // This container is used instead of walking the Actor hierachy. // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks. @@ -1523,37 +1284,14 @@ void Actor::DisconnectFromStage() mScene->RequestRebuildDepthTree(); } - // This stage is atomic i.e. not interrupted by user callbacks - RecursiveDisconnectFromStage(disconnectionList); + // This stage is not interrupted by user callbacks + mParentImpl.RecursiveDisconnectFromScene(disconnectionList); // Notify applications about the newly disconnected actors. for(const auto& actor : disconnectionList) { - actor->NotifyStageDisconnection(); - } -} - -void Actor::RecursiveDisconnectFromStage(ActorContainer& disconnectionList) -{ - // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value - mIsOnScene = false; - - // Recursively disconnect children - if(GetChildCount() > 0) - { - for(const auto& child : mParentImpl.GetChildrenInternal()) - { - child->RecursiveDisconnectFromStage(disconnectionList); - } + actor->NotifyStageDisconnection(notify); } - - // This stage is atomic; avoid emitting callbacks until all Actors are disconnected - disconnectionList.push_back(ActorPtr(this)); - - // Notification for internal derived classes - OnSceneDisconnectionInternal(); - - DisconnectFromSceneGraph(); } /** @@ -1566,20 +1304,23 @@ void Actor::DisconnectFromSceneGraph() OnSceneObjectRemove(); } -void Actor::NotifyStageDisconnection() +void Actor::NotifyStageDisconnection(bool notify) { // Actors can be added (in a callback), before the off-stage state is reported. // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here. // only do this step if there is a stage, i.e. Core is not being shut down if(EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled) { - // Notification for external (CustomeActor) derived classes - OnSceneDisconnectionExternal(); - - if(!mOffSceneSignal.Empty()) + if(notify) { - Dali::Actor handle(this); - mOffSceneSignal.Emit(handle); + // Notification for external (CustomeActor) derived classes + OnSceneDisconnectionExternal(); + + if(!mOffSceneSignal.Empty()) + { + Dali::Actor handle(this); + mOffSceneSignal.Emit(handle); + } } // Guard against Add during callbacks @@ -1592,17 +1333,7 @@ void Actor::NotifyStageDisconnection() bool Actor::IsNodeConnected() const { - bool connected(false); - - if(OnScene()) - { - if(IsRoot() || GetNode().GetParent()) - { - connected = true; - } - } - - return connected; + return OnScene() && (IsRoot() || GetNode().GetParent()); } // This method initiates traversal of the actor tree using depth-first @@ -1620,29 +1351,12 @@ void Actor::RebuildDepthTree() OwnerPointer sceneGraphNodeDepths(new SceneGraph::NodeDepths()); int32_t depthIndex = 1; - DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex); + mParentImpl.DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex); SetDepthIndicesMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths); DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: "); } -void Actor::DepthTraverseActorTree(OwnerPointer& sceneGraphNodeDepths, int32_t& depthIndex) -{ - mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER; - sceneGraphNodeDepths->Add(const_cast(&GetNode()), mSortedDepth); - - // Create/add to children of this node - if(GetChildCount() > 0) - { - for(const auto& child : mParentImpl.GetChildrenInternal()) - { - Actor* childActor = child.Get(); - ++depthIndex; - childActor->DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex); - } - } -} - void Actor::SetDefaultProperty(Property::Index index, const Property::Value& property) { PropertyHandler::SetDefaultProperty(*this, index, property); @@ -1722,79 +1436,42 @@ int32_t Actor::GetPropertyComponentIndex(Property::Index index) const return componentIndex; } +const SceneGraph::Node& Actor::GetNode() const +{ + return *static_cast(mUpdateObject); +} + void Actor::Raise() { - if(mParent) - { - mParent->RaiseChild(*this); - } - else - { - DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n"); - } + CheckParentAndCall(mParent, *this, &ActorParent::RaiseChild); } void Actor::Lower() { - if(mParent) - { - mParent->LowerChild(*this); - } - else - { - DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n"); - } + CheckParentAndCall(mParent, *this, &ActorParent::LowerChild); } void Actor::RaiseToTop() { - if(mParent) - { - mParent->RaiseChildToTop(*this); - } - else - { - DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n"); - } + CheckParentAndCall(mParent, *this, &ActorParent::RaiseChildToTop); } void Actor::LowerToBottom() { - if(mParent) - { - mParent->LowerChildToBottom(*this); - } - else - { - DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n"); - } + CheckParentAndCall(mParent, *this, &ActorParent::LowerChildToBottom); } void Actor::RaiseAbove(Internal::Actor& target) { - if(mParent) - { - mParent->RaiseChildAbove(*this, target); - } - else - { - DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n"); - } + CheckParentAndCall(mParent, *this, target, &ActorParent::RaiseChildAbove); } void Actor::LowerBelow(Internal::Actor& target) { - if(mParent) - { - mParent->LowerChildBelow(*this, target); - } - else - { - DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n"); - } + CheckParentAndCall(mParent, *this, target, &ActorParent::LowerChildBelow); } -void Actor::SetParent(ActorParent* parent) +void Actor::SetParent(ActorParent* parent, bool notify) { if(parent) { @@ -1804,11 +1481,11 @@ void Actor::SetParent(ActorParent* parent) Actor* parentActor = static_cast(parent); mScene = parentActor->mScene; - if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction + if(!EventThreadServices::IsShuttingDown() && // Don't emit signals or send messages during Core destruction parentActor->OnScene()) { // Instruct each actor to create a corresponding node in the scene graph - ConnectToScene(parentActor->GetHierarchyDepth()); + ConnectToScene(parentActor->GetHierarchyDepth(), parentActor->GetLayer3DParentCount(), notify); } // Resolve the name and index for the child properties if any @@ -1820,50 +1497,39 @@ void Actor::SetParent(ActorParent* parent) mParent = nullptr; - if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction + if(!EventThreadServices::IsShuttingDown() && // Don't emit signals or send messages during Core destruction OnScene()) { // Disconnect the Node & its children from the scene-graph. DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode()); // Instruct each actor to discard pointers to the scene-graph - DisconnectFromStage(); + DisconnectFromStage(notify); } mScene = nullptr; } } -bool Actor::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */) +Rect<> Actor::CalculateScreenExtents() const { - bool done = false; - Actor* actor = dynamic_cast(object); - - if(actor) + if(mLayer3DParentsCount == 0) { - std::string_view name(actionName); - if(name == ACTION_SHOW) - { - actor->SetVisible(true); - done = true; - } - else if(name == ACTION_HIDE) - { - actor->SetVisible(false); - done = true; - } + // We can assume that this actor is under 2d layer. Use faster, but imprecise algorithm + auto screenPosition = GetCurrentScreenPosition(); + BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex(); + return CalculateActorScreenExtents(*this, screenPosition, bufferIndex); + } + else + { + BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex(); + return CalculateActorScreenExtentsRenderTaskList(*this, bufferIndex); } - - return done; } -Rect<> Actor::CalculateScreenExtents() const +Vector3 Actor::GetAnchorPointForPosition() const { - auto screenPosition = GetCurrentScreenPosition(); - Vector3 size = GetCurrentSize() * GetCurrentWorldScale(); - Vector3 anchorPointOffSet = size * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT); - Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y); - return {position.x, position.y, size.x, size.y}; + return (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT); } bool Actor::GetCachedPropertyValue(Property::Index index, Property::Value& value) const @@ -1876,434 +1542,115 @@ bool Actor::GetCurrentPropertyValue(Property::Index index, Property::Value& valu return PropertyHandler::GetCurrentPropertyValue(*this, index, value); } -Actor::Relayouter& Actor::EnsureRelayouter() -{ - // Assign relayouter - if(!mRelayoutData) - { - mRelayoutData = new Relayouter(); - } - - return *mRelayoutData; -} - bool Actor::RelayoutDependentOnParent(Dimension::Type dimension) { - // Check if actor is dependent on parent - for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i) - { - if((dimension & (1 << i))) - { - const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast(1 << i)); - if(resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT) - { - return true; - } - } - } - - return false; + return mSizer.RelayoutDependentOnParent(dimension); } bool Actor::RelayoutDependentOnChildren(Dimension::Type dimension) { - // Check if actor is dependent on children - for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i) - { - if((dimension & (1 << i))) - { - const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast(1 << i)); - switch(resizePolicy) - { - case ResizePolicy::FIT_TO_CHILDREN: - case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children - { - return true; - } - - default: - { - break; - } - } - } - } - - return false; -} - -bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension) -{ - return Actor::RelayoutDependentOnChildren(dimension); + return mSizer.RelayoutDependentOnChildrenBase(dimension); } bool Actor::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension) { - // Check each possible dimension and see if it is dependent on the input one - for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i) - { - if(dimension & (1 << i)) - { - return mRelayoutData->resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[i] == dependentDimension; - } - } - - return false; -} - -void Actor::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension) -{ - for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i) - { - if(dimension & (1 << i)) - { - mRelayoutData->negotiatedDimensions[i] = negotiatedDimension; - } - } -} - -float Actor::GetNegotiatedDimension(Dimension::Type dimension) const -{ - // If more than one dimension is requested, just return the first one found - for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i) - { - if((dimension & (1 << i))) - { - return mRelayoutData->negotiatedDimensions[i]; - } - } - - return 0.0f; // Default + return mSizer.RelayoutDependentOnDimension(dimension, dependentDimension); } void Actor::SetPadding(const Vector2& padding, Dimension::Type dimension) { - EnsureRelayouter().SetPadding(padding, dimension); + mSizer.SetPadding(padding, dimension); } Vector2 Actor::GetPadding(Dimension::Type dimension) const { - if(mRelayoutData) - { - // If more than one dimension is requested, just return the first one found - for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i) - { - if((dimension & (1 << i))) - { - return mRelayoutData->dimensionPadding[i]; - } - } - } - - return Relayouter::DEFAULT_DIMENSION_PADDING; + return mSizer.GetPadding(dimension); } void Actor::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension) { - EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension); + mSizer.SetLayoutNegotiated(negotiated, dimension); } bool Actor::IsLayoutNegotiated(Dimension::Type dimension) const { - return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension); + return mSizer.IsLayoutNegotiated(dimension); } float Actor::GetHeightForWidthBase(float width) { - float height = 0.0f; - - const Vector3 naturalSize = GetNaturalSize(); - if(naturalSize.width > 0.0f) - { - height = naturalSize.height * width / naturalSize.width; - } - else // we treat 0 as 1:1 aspect ratio - { - height = width; - } - - return height; + // Can be overridden in derived class + return mSizer.GetHeightForWidthBase(width); } float Actor::GetWidthForHeightBase(float height) { - float width = 0.0f; - - const Vector3 naturalSize = GetNaturalSize(); - if(naturalSize.height > 0.0f) - { - width = naturalSize.width * height / naturalSize.height; - } - else // we treat 0 as 1:1 aspect ratio - { - width = height; - } - - return width; + // Can be overridden in derived class + return mSizer.GetWidthForHeightBase(height); } float Actor::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension) { - // Fill to parent, taking size mode factor into account - switch(child.GetResizePolicy(dimension)) - { - case ResizePolicy::FILL_TO_PARENT: - { - return GetLatestSize(dimension); - } - - case ResizePolicy::SIZE_RELATIVE_TO_PARENT: - { - return GetLatestSize(dimension) * GetDimensionValue(child.GetProperty(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension); - } - - case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT: - { - return GetLatestSize(dimension) + GetDimensionValue(child.GetProperty(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension); - } + // Can be overridden in derived class + return mSizer.CalculateChildSizeBase(child, dimension); +} - default: - { - return GetLatestSize(dimension); - } - } +bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension) +{ + return mSizer.RelayoutDependentOnChildrenBase(dimension); } float Actor::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension) { // Can be overridden in derived class - return CalculateChildSizeBase(child, dimension); + return mSizer.CalculateChildSizeBase(child, dimension); } float Actor::GetHeightForWidth(float width) { // Can be overridden in derived class - return GetHeightForWidthBase(width); + return mSizer.GetHeightForWidthBase(width); } float Actor::GetWidthForHeight(float height) { // Can be overridden in derived class - return GetWidthForHeightBase(height); -} - -float Actor::GetLatestSize(Dimension::Type dimension) const -{ - return IsLayoutNegotiated(dimension) ? GetNegotiatedDimension(dimension) : GetSize(dimension); + return mSizer.GetWidthForHeightBase(height); } float Actor::GetRelayoutSize(Dimension::Type dimension) const { - Vector2 padding = GetPadding(dimension); - - return GetLatestSize(dimension) + padding.x + padding.y; -} - -float Actor::NegotiateFromParent(Dimension::Type dimension) -{ - Actor* parent = GetParent(); - if(parent) - { - Vector2 padding(GetPadding(dimension)); - Vector2 parentPadding(parent->GetPadding(dimension)); - return parent->CalculateChildSize(Dali::Actor(this), dimension) - parentPadding.x - parentPadding.y - padding.x - padding.y; - } - - return 0.0f; -} - -float Actor::NegotiateFromChildren(Dimension::Type dimension) -{ - float maxDimensionPoint = 0.0f; - - for(uint32_t i = 0, count = GetChildCount(); i < count; ++i) - { - ActorPtr child = GetChildAt(i); - - if(!child->RelayoutDependentOnParent(dimension)) - { - // Calculate the min and max points that the children range across - float childPosition = GetDimensionValue(child->GetTargetPosition(), dimension); - float dimensionSize = child->GetRelayoutSize(dimension); - maxDimensionPoint = std::max(maxDimensionPoint, childPosition + dimensionSize); - } - } - - return maxDimensionPoint; -} - -float Actor::GetSize(Dimension::Type dimension) const -{ - return GetDimensionValue(mTargetSize, dimension); -} - -float Actor::GetNaturalSize(Dimension::Type dimension) const -{ - return GetDimensionValue(GetNaturalSize(), dimension); -} - -float Actor::CalculateSize(Dimension::Type dimension, const Vector2& maximumSize) -{ - switch(GetResizePolicy(dimension)) - { - case ResizePolicy::USE_NATURAL_SIZE: - { - return GetNaturalSize(dimension); - } - - case ResizePolicy::FIXED: - { - return GetDimensionValue(GetPreferredSize(), dimension); - } - - case ResizePolicy::USE_ASSIGNED_SIZE: - { - return GetDimensionValue(maximumSize, dimension); - } - - case ResizePolicy::FILL_TO_PARENT: - case ResizePolicy::SIZE_RELATIVE_TO_PARENT: - case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT: - { - return NegotiateFromParent(dimension); - } - - case ResizePolicy::FIT_TO_CHILDREN: - { - return NegotiateFromChildren(dimension); - } - - case ResizePolicy::DIMENSION_DEPENDENCY: - { - const Dimension::Type dimensionDependency = GetDimensionDependency(dimension); - - // Custom rules - if(dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT) - { - return GetWidthForHeight(GetNegotiatedDimension(Dimension::HEIGHT)); - } - - if(dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH) - { - return GetHeightForWidth(GetNegotiatedDimension(Dimension::WIDTH)); - } - - break; - } - - default: - { - break; - } - } - - return 0.0f; // Default -} - -Vector2 Actor::ApplySizeSetPolicy(const Vector2& size) -{ - return mRelayoutData->ApplySizeSetPolicy(*this, size); -} - -void Actor::SetNegotiatedSize(RelayoutContainer& container) -{ - // Do the set actor size - Vector2 negotiatedSize(GetLatestSize(Dimension::WIDTH), GetLatestSize(Dimension::HEIGHT)); - - // Adjust for size set policy - negotiatedSize = ApplySizeSetPolicy(negotiatedSize); - - // Lock the flag to stop recursive relayouts on set size - mRelayoutData->insideRelayout = true; - SetSize(negotiatedSize); - mRelayoutData->insideRelayout = false; - - // Clear flags for all dimensions - SetLayoutDirty(false); - - // Give deriving classes a chance to respond - OnRelayout(negotiatedSize, container); - - if(!mOnRelayoutSignal.Empty()) - { - Dali::Actor handle(this); - mOnRelayoutSignal.Emit(handle); - } + return mSizer.GetRelayoutSize(dimension); } void Actor::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container) { - Relayouter::NegotiateSize(*this, allocatedSize, container); -} - -void Actor::SetUseAssignedSize(bool use, Dimension::Type dimension) -{ - if(mRelayoutData) - { - mRelayoutData->SetUseAssignedSize(use, dimension); - } -} - -bool Actor::GetUseAssignedSize(Dimension::Type dimension) const -{ - return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension); + mSizer.NegotiateSize(allocatedSize, container); } void Actor::RelayoutRequest(Dimension::Type dimension) { - Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get(); - if(relayoutController) - { - Dali::Actor self(this); - relayoutController->RequestRelayout(self, dimension); - } -} - -void Actor::SetPreferredSize(const Vector2& size) -{ - EnsureRelayouter().SetPreferredSize(*this, size); -} - -Vector2 Actor::GetPreferredSize() const -{ - if(mRelayoutData) - { - return Vector2(mRelayoutData->preferredSize); - } - - return Relayouter::DEFAULT_PREFERRED_SIZE; + mSizer.RelayoutRequest(dimension); } void Actor::SetMinimumSize(float size, Dimension::Type dimension) { - EnsureRelayouter().SetMinimumSize(size, dimension); - RelayoutRequest(); + mSizer.SetMinimumSize(size, dimension); } float Actor::GetMinimumSize(Dimension::Type dimension) const { - if(mRelayoutData) - { - return mRelayoutData->GetMinimumSize(dimension); - } - - return 0.0f; // Default + return mSizer.GetMinimumSize(dimension); } void Actor::SetMaximumSize(float size, Dimension::Type dimension) { - EnsureRelayouter().SetMaximumSize(size, dimension); - RelayoutRequest(); + mSizer.SetMaximumSize(size, dimension); } float Actor::GetMaximumSize(Dimension::Type dimension) const { - if(mRelayoutData) - { - return mRelayoutData->GetMaximumSize(dimension); - } - - return FLT_MAX; // Default + return mSizer.GetMaximumSize(dimension); } void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage) @@ -2321,7 +1668,7 @@ void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage) mVisible = visible; // Emit the signal on this actor and all its children - EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF); + mParentImpl.EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF); } } @@ -2373,50 +1720,15 @@ void Actor::SetInheritLayoutDirection(bool inherit) if(inherit && mParent) { - InheritLayoutDirectionRecursively(GetParent()->mLayoutDirection); - } - } -} - -void Actor::InheritLayoutDirectionRecursively(Dali::LayoutDirection::Type direction, bool set) -{ - if(mInheritLayoutDirection || set) - { - if(mLayoutDirection != direction) - { - mLayoutDirection = direction; - EmitLayoutDirectionChangedSignal(direction); - RelayoutRequest(); - } - - if(GetChildCount() > 0) - { - for(const auto& child : mParentImpl.GetChildrenInternal()) - { - child->InheritLayoutDirectionRecursively(direction); - } + mParentImpl.InheritLayoutDirectionRecursively(GetParent()->mLayoutDirection); } } } -void Actor::SetUpdateSizeHint(const Vector2& updateSizeHint) +void Actor::SetUpdateAreaHint(const Vector4& updateAreaHint) { // node is being used in a separate thread; queue a message to set the value & base value - SceneGraph::NodePropertyMessage::Send(GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f)); -} - -void Actor::EmitVisibilityChangedSignalRecursively(bool visible, - DevelActor::VisibilityChange::Type type) -{ - EmitVisibilityChangedSignal(visible, type); - - if(GetChildCount() > 0) - { - for(auto& child : mParentImpl.GetChildrenInternal()) - { - child->EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::PARENT); - } - } + SceneGraph::NodePropertyMessage::Send(GetEventThreadServices(), &GetNode(), &GetNode().mUpdateAreaHint, &AnimatableProperty::Bake, updateAreaHint); } } // namespace Internal