Refactored Actor screen to local conversion
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
index 776c3f3..decf85a 100644 (file)
 
 #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>
@@ -148,6 +148,8 @@ DALI_PROPERTY("updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::P
 DALI_PROPERTY("captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START)
 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
@@ -254,60 +256,6 @@ 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<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()
@@ -1118,6 +1066,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
@@ -1129,54 +1087,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()
@@ -1332,6 +1253,8 @@ Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
   mSensitive(true),
   mLeaveRequired(false),
   mKeyboardFocusable(false),
+  mKeyboardFocusableChildren(true),
+  mTouchFocusable(false),
   mOnSceneSignalled(false),
   mInsideOnSizeSet(false),
   mInheritPosition(true),
@@ -1341,12 +1264,13 @@ Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
   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)
 {
 }
 
@@ -1387,14 +1311,31 @@ Actor::~Actor()
   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
@@ -1427,7 +1368,7 @@ void Actor::UnparentChildren()
   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.
@@ -1444,7 +1385,7 @@ void Actor::ConnectToScene(uint32_t parentDepth)
   // Notify applications about the newly connected actors.
   for(const auto& actor : connectionList)
   {
-    actor->NotifyStageConnection();
+    actor->NotifyStageConnection(notify);
   }
 
   RelayoutRequest();
@@ -1496,19 +1437,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
@@ -1519,7 +1463,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.
@@ -1536,7 +1480,7 @@ void Actor::DisconnectFromStage()
   // Notify applications about the newly disconnected actors.
   for(const auto& actor : disconnectionList)
   {
-    actor->NotifyStageDisconnection();
+    actor->NotifyStageDisconnection(notify);
   }
 }
 
@@ -1573,20 +1517,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
@@ -1806,7 +1753,7 @@ void Actor::LowerBelow(Internal::Actor& target)
   }
 }
 
-void Actor::SetParent(ActorParent* parent)
+void Actor::SetParent(ActorParent* parent, bool notify)
 {
   if(parent)
   {
@@ -1820,7 +1767,7 @@ void Actor::SetParent(ActorParent* 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
@@ -1839,7 +1786,7 @@ void Actor::SetParent(ActorParent* parent)
       DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
 
       // Instruct each actor to discard pointers to the scene-graph
-      DisconnectFromStage();
+      DisconnectFromStage(notify);
     }
 
     mScene = nullptr;
@@ -1878,6 +1825,16 @@ Rect<> Actor::CalculateScreenExtents() const
   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);