/*
- * 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.
#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-coords.h>
#include <dali/internal/event/actors/actor-parent.h>
#include <dali/internal/event/actors/actor-property-handler.h>
#include <dali/internal/event/actors/actor-relayouter.h>
#include <dali/internal/event/actors/camera-actor-impl.h>
#include <dali/internal/event/common/event-thread-services.h>
-#include <dali/internal/event/common/projection.h>
#include <dali/internal/event/common/property-helper.h>
#include <dali/internal/event/common/scene-impl.h>
#include <dali/internal/event/common/stage-impl.h>
#include <dali/internal/event/events/actor-gesture-data.h>
#include <dali/internal/event/render-tasks/render-task-impl.h>
#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+#include <dali/internal/event/rendering/renderer-impl.h>
#include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
+#include <dali/internal/update/manager/update-manager.h>
#include <dali/internal/update/nodes/node-messages.h>
using Dali::Internal::SceneGraph::AnimatableProperty;
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_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties)
// Signals
}
}
-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<float>(viewport.x), static_cast<float>(viewport.height) - screenY - static_cast<float>(viewport.y), 0.f, 1.f);
-
- Vector4 nearPos;
- if(success)
- {
- success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
- }
-
- Vector4 farPos;
- if(success)
- {
- screenPos.z = 1.0f;
- success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
- }
-
- if(success)
- {
- 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;
- }
- }
-
- return success;
-}
-
} // unnamed namespace
ActorPtr Actor::New()
return node;
}
-
-void Actor::SetName( std::string_view name )
+void Actor::SetName(std::string_view name)
{
mName = ConstString(name);
// ATTENTION: string for debug purposes is not thread safe.
- DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), mName.GetCString() );
+ DALI_LOG_SET_OBJECT_STRING(const_cast<SceneGraph::Node*>(&GetNode()), mName.GetCString());
}
uint32_t Actor::GetId() const
// 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
Vector3 currentSize = GetCurrentSize();
- 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 )||
- ( fabsf( mTargetSize.width - currentSize.width ) > Math::MACHINE_EPSILON_1 )||
- ( fabsf( mTargetSize.height- currentSize.height ) > Math::MACHINE_EPSILON_1 )||
- ( fabsf( mTargetSize.depth - currentSize.depth ) > Math::MACHINE_EPSILON_1 ) )
+ 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) ||
+ (fabsf(mTargetSize.width - currentSize.width) > Math::MACHINE_EPSILON_1) ||
+ (fabsf(mTargetSize.height - currentSize.height) > Math::MACHINE_EPSILON_1) ||
+ (fabsf(mTargetSize.depth - currentSize.depth) > Math::MACHINE_EPSILON_1))
{
mTargetSize = size;
{
if(!mRenderers)
{
- mRenderers = new RendererContainer;
- }
-
- if(mIsBlendEquationSet)
- {
- renderer.SetBlendEquation(static_cast<DevelBlendEquation::Type>(mBlendEquation));
+ mRenderers = new RendererContainer(GetEventThreadServices());
}
-
- uint32_t index = static_cast<uint32_t>(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<uint32_t>(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);
}
}
{
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<DevelBlendEquation::Type>(blendEquation));
+ mRenderers->SetBlending(blendEquation);
}
}
mIsBlendEquationSet = true;
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
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()
mTargetPosition(Vector3::ZERO),
mTargetScale(Vector3::ONE),
mAnimatedSize(Vector3::ZERO),
- mTouchArea(Vector2::ZERO),
+ mTouchAreaOffset(0, 0, 0, 0),
mName(),
mSortedDepth(0u),
mDepth(0u),
mSensitive(true),
mLeaveRequired(false),
mKeyboardFocusable(false),
+ mKeyboardFocusableChildren(true),
+ mTouchFocusable(false),
mOnSceneSignalled(false),
mInsideOnSizeSet(false),
mInheritPosition(true),
mVisible(true),
mInheritLayoutDirection(true),
mCaptureAllTouchAfterStart(false),
+ mIsBlendEquationSet(false),
+ mNeedGesturePropagation(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)
{
}
delete mRelayoutData;
}
-void Actor::Add(Actor& child)
+void Actor::Add(Actor& child, bool notify)
{
- mParentImpl.Add(child);
+ mParentImpl.Add(child, notify);
}
-void Actor::Remove(Actor& child)
+void Actor::Remove(Actor& child, bool notify)
{
- mParentImpl.Remove(child);
+ mParentImpl.Remove(child, notify);
+}
+
+void Actor::SwitchParent(Actor& newParent)
+{
+ 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
mParentImpl.UnparentChildren();
}
-void Actor::ConnectToScene(uint32_t parentDepth)
+void Actor::ConnectToScene(uint32_t parentDepth, bool notify)
{
// This container is used instead of walking the Actor hierarchy.
// It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
// Notify applications about the newly connected actors.
for(const auto& actor : connectionList)
{
- actor->NotifyStageConnection();
+ actor->NotifyStageConnection(notify);
}
RelayoutRequest();
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
}
}
-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.
// Notify applications about the newly disconnected actors.
for(const auto& actor : disconnectionList)
{
- actor->NotifyStageDisconnection();
+ actor->NotifyStageDisconnection(notify);
}
}
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
return componentIndex;
}
+const SceneGraph::Node& Actor::GetNode() const
+{
+ return *static_cast<const SceneGraph::Node*>(mUpdateObject);
+}
+
void Actor::Raise()
{
if(mParent)
}
}
-void Actor::SetParent(ActorParent* parent)
+void Actor::SetParent(ActorParent* parent, bool notify)
{
if(parent)
{
parentActor->OnScene())
{
// Instruct each actor to create a corresponding node in the scene graph
- ConnectToScene(parentActor->GetHierarchyDepth());
+ ConnectToScene(parentActor->GetHierarchyDepth(), notify);
}
// Resolve the name and index for the child properties if any
DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
// Instruct each actor to discard pointers to the scene-graph
- DisconnectFromStage();
+ DisconnectFromStage(notify);
}
mScene = nullptr;
return {position.x, position.y, size.x, size.y};
}
+void Actor::SetNeedGesturePropagation(bool propagation)
+{
+ mNeedGesturePropagation = propagation;
+}
+
+bool Actor::NeedGesturePropagation()
+{
+ return mNeedGesturePropagation;
+}
+
bool Actor::GetCachedPropertyValue(Property::Index index, Property::Value& value) const
{
return PropertyHandler::GetCachedPropertyValue(*this, index, value);