diff --git a/Source/Engine/UI/GUI/CanvasContainer.cs b/Source/Engine/UI/GUI/CanvasContainer.cs
index d85ed37a8..f032a99d3 100644
--- a/Source/Engine/UI/GUI/CanvasContainer.cs
+++ b/Source/Engine/UI/GUI/CanvasContainer.cs
@@ -29,34 +29,6 @@ namespace FlaxEngine.GUI
return ((CanvasRootControl)a).Canvas.Order - ((CanvasRootControl)b).Canvas.Order;
}
- private bool IntersectsChildContent(CanvasRootControl child, ref Ray ray, out Float2 childSpaceLocation)
- {
- // Inline bounds calculations (it will reuse world matrix)
- var bounds = new OrientedBoundingBox
- {
- Extents = new Vector3(child.Size * 0.5f, Mathf.Epsilon)
- };
-
- child.Canvas.GetWorldMatrix(out var world);
- Matrix.Translation((float)bounds.Extents.X, (float)bounds.Extents.Y, 0, out var offset);
- Matrix.Multiply(ref offset, ref world, out var boxWorld);
- boxWorld.Decompose(out bounds.Transformation);
-
- // Hit test
- if (bounds.Intersects(ref ray, out Vector3 hitPoint))
- {
- // Transform world-space hit point to canvas local-space
- world.Invert();
- Vector3.Transform(ref hitPoint, ref world, out Vector3 localHitPoint);
-
- childSpaceLocation = new Float2(localHitPoint);
- return child.ContainsPoint(ref childSpaceLocation);
- }
-
- childSpaceLocation = Float2.Zero;
- return false;
- }
-
///
public override void OnChildrenChanged()
{
@@ -102,7 +74,7 @@ namespace FlaxEngine.GUI
var child = (CanvasRootControl)_children[i];
if (child.Visible && child.Enabled && child.Is3D)
{
- if (IntersectsChildContent(child, ref ray, out var childLocation))
+ if (child.Intersects3D(ref ray, out var childLocation))
{
child.OnMouseEnter(childLocation);
return;
@@ -148,7 +120,7 @@ namespace FlaxEngine.GUI
}
else
{
- if (!isFirst3DHandled && IntersectsChildContent(child, ref ray, out var childLocation))
+ if (!isFirst3DHandled && child.Intersects3D(ref ray, out var childLocation))
{
isFirst3DHandled = true;
@@ -189,7 +161,7 @@ namespace FlaxEngine.GUI
var child = (CanvasRootControl)_children[i];
if (child.Visible && child.Enabled && child.Is3D)
{
- if (IntersectsChildContent(child, ref ray, out var childLocation))
+ if (child.Intersects3D(ref ray, out var childLocation))
{
child.OnMouseWheel(childLocation, delta);
return true;
@@ -216,7 +188,7 @@ namespace FlaxEngine.GUI
var child = (CanvasRootControl)_children[i];
if (child.Visible && child.Enabled && child.Is3D)
{
- if (IntersectsChildContent(child, ref ray, out var childLocation))
+ if (child.Intersects3D(ref ray, out var childLocation))
{
child.OnMouseDown(childLocation, button);
return true;
@@ -243,7 +215,7 @@ namespace FlaxEngine.GUI
var child = (CanvasRootControl)_children[i];
if (child.Visible && child.Enabled && child.Is3D)
{
- if (IntersectsChildContent(child, ref ray, out var childLocation))
+ if (child.Intersects3D(ref ray, out var childLocation))
{
child.OnMouseUp(childLocation, button);
return true;
@@ -270,7 +242,7 @@ namespace FlaxEngine.GUI
var child = (CanvasRootControl)_children[i];
if (child.Visible && child.Enabled && child.Is3D)
{
- if (IntersectsChildContent(child, ref ray, out var childLocation))
+ if (child.Intersects3D(ref ray, out var childLocation))
{
child.OnMouseDoubleClick(childLocation, button);
return true;
diff --git a/Source/Engine/UI/GUI/CanvasRootControl.cs b/Source/Engine/UI/GUI/CanvasRootControl.cs
index a3d099eee..408c46b0f 100644
--- a/Source/Engine/UI/GUI/CanvasRootControl.cs
+++ b/Source/Engine/UI/GUI/CanvasRootControl.cs
@@ -40,6 +40,40 @@ namespace FlaxEngine.GUI
_canvas = canvas;
}
+ ///
+ /// Checks if the 3D canvas intersects with a given 3D mouse ray.
+ ///
+ /// The input ray to test (in world-space).
+ /// Output canvas-space local position.
+ /// True if canvas intersects with that point, otherwise false.
+ public bool Intersects3D(ref Ray ray, out Float2 canvasLocation)
+ {
+ // Inline bounds calculations (it will reuse world matrix)
+ var bounds = new OrientedBoundingBox
+ {
+ Extents = new Vector3(Size * 0.5f, Mathf.Epsilon)
+ };
+
+ _canvas.GetWorldMatrix(out var world);
+ Matrix.Translation((float)bounds.Extents.X, (float)bounds.Extents.Y, 0, out var offset);
+ Matrix.Multiply(ref offset, ref world, out var boxWorld);
+ boxWorld.Decompose(out bounds.Transformation);
+
+ // Hit test
+ if (bounds.Intersects(ref ray, out Vector3 hitPoint))
+ {
+ // Transform world-space hit point to canvas local-space
+ world.Invert();
+ Vector3.Transform(ref hitPoint, ref world, out Vector3 localHitPoint);
+
+ canvasLocation = new Float2(localHitPoint);
+ return ContainsPoint(ref canvasLocation);
+ }
+
+ canvasLocation = Float2.Zero;
+ return false;
+ }
+
///
public override CursorType Cursor
{
@@ -136,6 +170,22 @@ namespace FlaxEngine.GUI
return location;
}
+ ///
+ public override Float2 PointFromParent(ref Float2 locationParent)
+ {
+ if (Is2D)
+ return base.PointFromParent(ref locationParent);
+
+ var camera = Camera.MainCamera;
+ if (!camera)
+ return locationParent;
+
+ // Use world-space ray to convert it to the local-space of the canvas
+ UICanvas.CalculateRay(ref locationParent, out Ray ray);
+ Intersects3D(ref ray, out var location);
+ return location;
+ }
+
///
public override bool ContainsPoint(ref Float2 location)
{