2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <dali/internal/event/actors/actor-coords.h>
18 #include <dali/internal/event/common/event-thread-services.h>
19 #include <dali/internal/event/common/projection.h>
20 #include <dali/internal/event/common/scene-impl.h>
21 #include <dali/internal/update/nodes/node.h>
23 namespace Dali::Internal
25 bool ConvertScreenToLocal(
26 const Matrix& viewMatrix,
27 const Matrix& projectionMatrix,
28 const Matrix& worldMatrix,
29 const Vector3& currentSize,
30 const Viewport& viewport,
36 // Get the ModelView matrix
38 Matrix::Multiply(modelView, worldMatrix, viewMatrix);
40 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
41 Matrix invertedMvp(false /*don't init*/);
42 Matrix::Multiply(invertedMvp, modelView, projectionMatrix);
43 bool success = invertedMvp.Invert();
45 // Convert to GL coordinates
46 Vector4 screenPos(screenX - static_cast<float>(viewport.x), static_cast<float>(viewport.height) - screenY - static_cast<float>(viewport.y), 0.f, 1.f);
51 success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
58 success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
64 if(XyPlaneIntersect(nearPos, farPos, local))
66 Vector3 size = currentSize;
67 localX = local.x + size.x * 0.5f;
68 localY = local.y + size.y * 0.5f;
79 bool ConvertScreenToLocalRenderTask(
80 const RenderTask& renderTask,
81 const Matrix& worldMatrix,
82 const Vector3& currentSize,
89 CameraActor* camera = renderTask.GetCameraActor();
93 renderTask.GetViewport(viewport);
95 // need to translate coordinates to render tasks coordinate space
96 Vector2 converted(screenX, screenY);
97 if(renderTask.TranslateCoordinates(converted))
99 success = ConvertScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, currentSize, viewport, localX, localY, converted.x, converted.y);
105 bool ConvertScreenToLocalRenderTaskList(
106 const RenderTaskList& renderTaskList,
107 const Matrix& worldMatrix,
108 const Vector3& currentSize,
114 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
115 uint32_t taskCount = renderTaskList.GetTaskCount();
116 for(uint32_t i = taskCount; i > 0; --i)
118 RenderTaskPtr task = renderTaskList.GetTask(i - 1);
119 if(ConvertScreenToLocalRenderTask(*task, worldMatrix, currentSize, localX, localY, screenX, screenY))
121 // found a task where this conversion was ok so return
128 const Vector2 CalculateActorScreenPosition(const Actor& actor, BufferIndex bufferIndex)
130 Scene& scene = actor.GetScene();
133 const auto& node = actor.GetNode();
134 Vector3 worldPosition = node.GetWorldPosition(bufferIndex);
135 Vector3 cameraPosition = scene.GetDefaultCameraActor().GetNode().GetWorldPosition(bufferIndex);
136 worldPosition -= cameraPosition;
138 Vector3 actorSize = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
139 Vector2 halfSceneSize(scene.GetSize() * 0.5f); // World position origin is center of scene
140 Vector3 halfActorSize(actorSize * 0.5f);
141 Vector3 anchorPointOffSet = halfActorSize - actorSize * actor.GetAnchorPointForPosition();
142 return Vector2(halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
143 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y);
145 return Vector2::ZERO;
148 Rect<> CalculateActorScreenExtents(const Actor& actor, const Vector2& screenPosition, BufferIndex bufferIndex)
150 const auto& node = actor.GetNode();
151 Vector3 size = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
152 Vector3 anchorPointOffSet = size * actor.GetAnchorPointForPosition();
153 Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
154 return {position.x, position.y, size.x, size.y};
157 } // namespace Dali::Internal