Moved event side actor world calculation
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-coords.cpp
1 /*
2  * Copyright (c) 2022 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/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>
22
23 namespace Dali::Internal
24 {
25 bool ConvertScreenToLocal(
26   const Matrix&   viewMatrix,
27   const Matrix&   projectionMatrix,
28   const Matrix&   worldMatrix,
29   const Vector3&  currentSize,
30   const Viewport& viewport,
31   float&          localX,
32   float&          localY,
33   float           screenX,
34   float           screenY)
35 {
36   // Get the ModelView matrix
37   Matrix modelView;
38   Matrix::Multiply(modelView, worldMatrix, viewMatrix);
39
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();
44
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);
47
48   Vector4 nearPos;
49   if(success)
50   {
51     success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
52   }
53
54   Vector4 farPos;
55   if(success)
56   {
57     screenPos.z = 1.0f;
58     success     = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
59   }
60
61   if(success)
62   {
63     Vector4 local;
64     if(XyPlaneIntersect(nearPos, farPos, local))
65     {
66       Vector3 size = currentSize;
67       localX       = local.x + size.x * 0.5f;
68       localY       = local.y + size.y * 0.5f;
69     }
70     else
71     {
72       success = false;
73     }
74   }
75
76   return success;
77 }
78
79 bool ConvertScreenToLocalRenderTask(
80   const RenderTask& renderTask,
81   const Matrix&     worldMatrix,
82   const Vector3&    currentSize,
83   float&            localX,
84   float&            localY,
85   float             screenX,
86   float             screenY)
87 {
88   bool         success = false;
89   CameraActor* camera  = renderTask.GetCameraActor();
90   if(camera)
91   {
92     Viewport viewport;
93     renderTask.GetViewport(viewport);
94
95     // need to translate coordinates to render tasks coordinate space
96     Vector2 converted(screenX, screenY);
97     if(renderTask.TranslateCoordinates(converted))
98     {
99       success = ConvertScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), worldMatrix, currentSize, viewport, localX, localY, converted.x, converted.y);
100     }
101   }
102   return success;
103 }
104
105 bool ConvertScreenToLocalRenderTaskList(
106   const RenderTaskList& renderTaskList,
107   const Matrix&         worldMatrix,
108   const Vector3&        currentSize,
109   float&                localX,
110   float&                localY,
111   float                 screenX,
112   float                 screenY)
113 {
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)
117   {
118     RenderTaskPtr task = renderTaskList.GetTask(i - 1);
119     if(ConvertScreenToLocalRenderTask(*task, worldMatrix, currentSize, localX, localY, screenX, screenY))
120     {
121       // found a task where this conversion was ok so return
122       return true;
123     }
124   }
125   return false;
126 };
127
128 const Vector2 CalculateActorScreenPosition(const Actor& actor, BufferIndex bufferIndex)
129 {
130   Scene& scene = actor.GetScene();
131   if(actor.OnScene())
132   {
133     const auto& node           = actor.GetNode();
134     Vector3     worldPosition  = node.GetWorldPosition(bufferIndex);
135     Vector3     cameraPosition = scene.GetDefaultCameraActor().GetNode().GetWorldPosition(bufferIndex);
136     worldPosition -= cameraPosition;
137
138     Vector3 actorSize = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
139     auto    sceneSize = scene.GetCurrentSurfaceRect();                      // Use the update object's size
140     Vector2 halfSceneSize(sceneSize.width * 0.5f, sceneSize.height * 0.5f); // World position origin is center of scene
141     Vector3 halfActorSize(actorSize * 0.5f);
142     Vector3 anchorPointOffSet = halfActorSize - actorSize * actor.GetAnchorPointForPosition();
143     return Vector2(halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
144                    halfSceneSize.height + worldPosition.y - anchorPointOffSet.y);
145   }
146   return Vector2::ZERO;
147 }
148
149 Rect<> CalculateActorScreenExtents(const Actor& actor, const Vector2& screenPosition, BufferIndex bufferIndex)
150 {
151   const auto& node              = actor.GetNode();
152   Vector3     size              = node.GetSize(bufferIndex) * node.GetWorldScale(bufferIndex);
153   Vector3     anchorPointOffSet = size * actor.GetAnchorPointForPosition();
154   Vector2     position          = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
155   return {position.x, position.y, size.x, size.y};
156 }
157
158 /**
159  * @brief Computes and center position by using transform properties.
160  * @param[in] anchorPoint anchorPoint of an actor.
161  * @param[in] positionUsesAnchorPoint positionUsesAnchorPoint of an actor.
162  * @param[in] size size of an actor.
163  * @param[in] scale scale of an actor.
164  * @param[in] orientation orientation of an actor.
165  */
166 Vector3 CalculateCenterPosition(
167   const Vector3&    anchorPoint,
168   const bool        positionUsesAnchorPoint,
169   const Vector3&    size,
170   const Vector3&    scale,
171   const Quaternion& orientation)
172 {
173   Vector3       centerPosition;
174   const Vector3 half(0.5f, 0.5f, 0.5f);
175   const Vector3 topLeft(0.0f, 0.0f, 0.5f);
176   // Calculate the center-point by applying the scale and rotation on the anchor point.
177   centerPosition = (half - anchorPoint) * size * scale;
178   centerPosition *= orientation;
179
180   // If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
181   if(!positionUsesAnchorPoint)
182   {
183     centerPosition -= (topLeft - anchorPoint) * size;
184   }
185   return centerPosition;
186 }
187
188 Matrix CalculateActorWorldTransform(const Actor& actor)
189 {
190   enum InheritanceMode
191   {
192     DONT_INHERIT_TRANSFORM = 0,
193     INHERIT_POSITION       = 1,
194     INHERIT_SCALE          = 2,
195     INHERIT_ORIENTATION    = 4,
196     INHERIT_ALL            = INHERIT_POSITION | INHERIT_SCALE | INHERIT_ORIENTATION,
197   };
198
199   std::vector<Dali::Actor>     descentList;
200   std::vector<InheritanceMode> inheritanceModeList;
201   Dali::Actor                  currentActor(const_cast<Actor*>(&actor));
202   int                          inheritance = 0;
203   do
204   {
205     inheritance = (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_ORIENTATION)) << 2) +
206                   (static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_SCALE)) << 1) +
207                   static_cast<int>(currentActor.GetProperty<bool>(Dali::Actor::Property::INHERIT_POSITION));
208     inheritanceModeList.push_back(static_cast<InheritanceMode>(inheritance));
209     descentList.push_back(currentActor);
210     currentActor = currentActor.GetParent();
211   } while(inheritance != DONT_INHERIT_TRANSFORM && currentActor);
212
213   Matrix  worldMatrix;
214   Vector3 localPosition;
215   // descentList is leaf first, so traverse from root (end) to leaf (beginning)
216   for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i)
217   {
218     Vector3    anchorPoint             = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::ANCHOR_POINT);
219     Vector3    parentOrigin            = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::PARENT_ORIGIN);
220     bool       positionUsesAnchorPoint = descentList[i].GetProperty<bool>(Dali::Actor::Property::POSITION_USES_ANCHOR_POINT);
221     Vector3    size                    = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
222     Vector3    actorPosition           = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::POSITION);
223     Quaternion localOrientation        = descentList[i].GetProperty<Quaternion>(Dali::Actor::Property::ORIENTATION);
224     Vector3    localScale              = descentList[i].GetProperty<Vector3>(Dali::Actor::Property::SCALE);
225
226     Vector3 centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
227     if(inheritanceModeList[i] != DONT_INHERIT_TRANSFORM && descentList[i].GetParent())
228     {
229       Matrix  localMatrix;
230       Vector3 parentSize = descentList[i + 1].GetProperty<Vector3>(Dali::Actor::Property::SIZE);
231       if(inheritanceModeList[i] == INHERIT_ALL)
232       {
233         localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
234         localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
235
236         //Update the world matrix
237         Matrix tempMatrix;
238         Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
239         worldMatrix = tempMatrix;
240       }
241       else
242       {
243         Vector3    parentPosition, parentScale;
244         Quaternion parentOrientation;
245         worldMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
246
247         if((inheritanceModeList[i] & INHERIT_SCALE) == 0)
248         {
249           //Don't inherit scale
250           localScale /= parentScale;
251         }
252
253         if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0)
254         {
255           //Don't inherit orientation
256           parentOrientation.Invert();
257           localOrientation = parentOrientation * localOrientation;
258         }
259
260         if((inheritanceModeList[i] & INHERIT_POSITION) == 0)
261         {
262           localMatrix.SetTransformComponents(localScale, localOrientation, Vector3::ZERO);
263           Matrix tempMatrix;
264           Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
265           worldMatrix = tempMatrix;
266           worldMatrix.SetTranslation(actorPosition + centerPosition);
267         }
268         else
269         {
270           localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
271           localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
272           Matrix tempMatrix;
273           Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
274           worldMatrix = tempMatrix;
275         }
276       }
277     }
278     else
279     {
280       localPosition = actorPosition + centerPosition;
281       worldMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
282     }
283   }
284
285   return worldMatrix;
286 }
287
288 Vector4 CalculateActorWorldColor(const Actor& actor)
289 {
290   std::vector<Dali::Actor>     descentList;
291   std::vector<Dali::ColorMode> inheritanceModeList;
292   Dali::Actor                  currentActor(const_cast<Actor*>(&actor));
293   Dali::ColorMode              inheritance = Dali::ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA;
294   do
295   {
296     inheritance = currentActor.GetProperty<Dali::ColorMode>(Dali::Actor::Property::COLOR_MODE);
297     inheritanceModeList.push_back(inheritance);
298     descentList.push_back(currentActor);
299     currentActor = currentActor.GetParent();
300   } while(inheritance != Dali::ColorMode::USE_OWN_COLOR && currentActor);
301
302   Vector4 worldColor;
303   for(unsigned int i(descentList.size() - 1); i < descentList.size(); --i)
304   {
305     if(inheritanceModeList[i] == USE_OWN_COLOR || i == descentList.size() - 1)
306     {
307       worldColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
308     }
309     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_ALPHA)
310     {
311       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
312       worldColor       = Vector4(ownColor.r, ownColor.g, ownColor.b, ownColor.a * worldColor.a);
313     }
314     else if(inheritanceModeList[i] == USE_OWN_MULTIPLY_PARENT_COLOR)
315     {
316       Vector4 ownColor = descentList[i].GetProperty<Vector4>(Dali::Actor::Property::COLOR);
317       worldColor *= ownColor;
318     }
319   }
320
321   return worldColor;
322 }
323
324 } // namespace Dali::Internal