Refactored Actor screen to local conversion
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-coords.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <dali/internal/event/actors/actor-coords.h>
18 #include <dali/internal/event/common/projection.h>
19
20 namespace Dali::Internal
21 {
22 bool ConvertScreenToLocal(
23   const Matrix&   viewMatrix,
24   const Matrix&   projectionMatrix,
25   const Matrix&   worldMatrix,
26   const Vector3&  currentSize,
27   const Viewport& viewport,
28   float&          localX,
29   float&          localY,
30   float           screenX,
31   float           screenY)
32 {
33   // Get the ModelView matrix
34   Matrix modelView;
35   Matrix::Multiply(modelView, worldMatrix, viewMatrix);
36
37   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
38   Matrix invertedMvp(false /*don't init*/);
39   Matrix::Multiply(invertedMvp, modelView, projectionMatrix);
40   bool success = invertedMvp.Invert();
41
42   // Convert to GL coordinates
43   Vector4 screenPos(screenX - static_cast<float>(viewport.x), static_cast<float>(viewport.height) - screenY - static_cast<float>(viewport.y), 0.f, 1.f);
44
45   Vector4 nearPos;
46   if(success)
47   {
48     success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
49   }
50
51   Vector4 farPos;
52   if(success)
53   {
54     screenPos.z = 1.0f;
55     success     = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
56   }
57
58   if(success)
59   {
60     Vector4 local;
61     if(XyPlaneIntersect(nearPos, farPos, local))
62     {
63       Vector3 size = currentSize;
64       localX       = local.x + size.x * 0.5f;
65       localY       = local.y + size.y * 0.5f;
66     }
67     else
68     {
69       success = false;
70     }
71   }
72
73   return success;
74 }
75
76 bool ConvertScreenToLocalRenderTask(
77   const RenderTask& renderTask,
78   const Matrix&     worldMatrix,
79   const Vector3&    currentSize,
80   float&            localX,
81   float&            localY,
82   float             screenX,
83   float             screenY)
84 {
85   bool         success = false;
86   CameraActor* camera  = renderTask.GetCameraActor();
87   if(camera)
88   {
89     Viewport viewport;
90     renderTask.GetViewport(viewport);
91
92     // need to translate coordinates to render tasks coordinate space
93     Vector2 converted(screenX, screenY);
94     if(renderTask.TranslateCoordinates(converted))
95     {
96       success = ConvertScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, currentSize, viewport, localX, localY, converted.x, converted.y);
97     }
98   }
99   return success;
100 }
101
102 bool ConvertScreenToLocalRenderTaskList(
103   const RenderTaskList& renderTaskList,
104   const Matrix&         worldMatrix,
105   const Vector3&        currentSize,
106   float&                localX,
107   float&                localY,
108   float                 screenX,
109   float                 screenY)
110 {
111   // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
112   uint32_t taskCount = renderTaskList.GetTaskCount();
113   for(uint32_t i = taskCount; i > 0; --i)
114   {
115     RenderTaskPtr task = renderTaskList.GetTask(i - 1);
116     if(ConvertScreenToLocalRenderTask(*task, worldMatrix, currentSize, localX, localY, screenX, screenY))
117     {
118       // found a task where this conversion was ok so return
119       return true;
120     }
121   }
122   return false;
123 };
124
125 } // namespace Dali::Internal