Fix 3D UI Canvas point conversion from parent control space to local space
#1129
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
|
||||
@@ -40,6 +40,40 @@ namespace FlaxEngine.GUI
|
||||
_canvas = canvas;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the 3D canvas intersects with a given 3D mouse ray.
|
||||
/// </summary>
|
||||
/// <param name="ray">The input ray to test (in world-space).</param>
|
||||
/// <param name="canvasLocation">Output canvas-space local position.</param>
|
||||
/// <returns>True if canvas intersects with that point, otherwise false.</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CursorType Cursor
|
||||
{
|
||||
@@ -136,6 +170,22 @@ namespace FlaxEngine.GUI
|
||||
return location;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool ContainsPoint(ref Float2 location)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user