From 1dbbbeced14e992bc0234e4eb3e47db0af4607cd Mon Sep 17 00:00:00 2001 From: stefnotch Date: Wed, 24 Feb 2021 21:05:10 +0100 Subject: [PATCH] Specialized Visject Connection Broadphase Intersection --- Source/Editor/Surface/Elements/OutputBox.cs | 100 +++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Surface/Elements/OutputBox.cs b/Source/Editor/Surface/Elements/OutputBox.cs index 0c3ba8da4..251d599b8 100644 --- a/Source/Editor/Surface/Elements/OutputBox.cs +++ b/Source/Editor/Surface/Elements/OutputBox.cs @@ -2,6 +2,7 @@ using FlaxEngine; using FlaxEngine.GUI; +using System; namespace FlaxEditor.Surface.Elements { @@ -43,10 +44,86 @@ namespace FlaxEditor.Surface.Elements */ } + private static bool IsRight(ref Vector2 a, ref Vector2 b, ref Vector2 point) + { + return ((b.X - a.X) * (point.Y - a.Y) - (b.Y - a.Y) * (point.X - a.X)) <= 0; + } + + /// + /// Checks if a point intersects a bezier curve + /// + /// The start location. + /// The end location. + /// The point + /// Distance at which its an intersection + public static bool IntersectsConnection(ref Vector2 start, ref Vector2 end, ref Vector2 point, float distance) + { + if ((point.X - start.X) * (end.X - point.X) < 0) return false; + + var dst = (end - start) * new Vector2(0.25f, 0.05f); // Purposefully tweaked to 0.25 + Vector2 control1 = new Vector2(start.X + dst.X, start.Y + dst.Y); + Vector2 control2 = new Vector2(end.X - dst.X, end.Y + dst.Y); + + // I'm ignoring the start.Y + dst.Y + + Vector2 direction = end - start; + float offset = Mathf.Sign(direction.Y) * distance; + + Vector2 pointAbove1 = new Vector2(control1.X, start.Y - offset); + Vector2 pointAbove2 = new Vector2(end.X, end.Y - offset); + Vector2 pointBelow1 = new Vector2(start.X, start.Y + offset); + Vector2 pointBelow2 = new Vector2(control2.X, end.Y + offset); + + /* Render2D.DrawLine(pointAbove1, pointAbove2, Color.Red); + Render2D.DrawRectangle(new Rectangle(pointAbove2 - new Vector2(5), new Vector2(10)), Color.Red); + Render2D.DrawLine(pointBelow1, pointBelow2, Color.Green); + Render2D.DrawRectangle(new Rectangle(pointBelow2 - new Vector2(5), new Vector2(10)), Color.Green); + */ + // TODO: are they parallel ^? + + return IsRight(ref pointAbove1, ref pointAbove2, ref point) == IsRight(ref pointBelow2, ref pointBelow1, ref point); + + + // Taken from the Render2D.DrawBezier code + float squaredDistance = distance; + + Vector2 d1 = control1 - start; + Vector2 d2 = control2 - control1; + Vector2 d3 = end - control2; + float len = d1.Length + d2.Length + d3.Length; + int segmentCount = Math.Min(Math.Max(Mathf.CeilToInt(len * 0.05f), 1), 100); + float segmentCountInv = 1.0f / segmentCount; + + Bezier(ref start, ref control1, ref control2, ref end, 0, out Vector2 p); + for (int i = 1; i <= segmentCount; i++) + { + Vector2 oldp = p; + float t = i * segmentCountInv; + Bezier(ref start, ref control1, ref control2, ref end, t, out p); + + CollisionsHelper.ClosestPointPointLine(ref point, ref oldp, ref p, out Vector2 result); + if (Vector2.DistanceSquared(point, result) <= squaredDistance) + { + return true; + } + } + return false; + } + + private static void Bezier(ref Vector2 p0, ref Vector2 p1, ref Vector2 p2, ref Vector2 p3, float alpha, out Vector2 result) + { + Vector2.Lerp(ref p0, ref p1, alpha, out var p01); + Vector2.Lerp(ref p1, ref p2, alpha, out var p12); + Vector2.Lerp(ref p2, ref p3, alpha, out var p23); + Vector2.Lerp(ref p01, ref p12, alpha, out var p012); + Vector2.Lerp(ref p12, ref p23, alpha, out var p123); + Vector2.Lerp(ref p012, ref p123, alpha, out result); + } + /// /// Draw all connections coming from this box. /// - public void DrawConnections() + public void DrawConnections(ref Vector2 mousePosition) { // Draw all the connections var center = Size * 0.5f; @@ -60,10 +137,31 @@ namespace FlaxEditor.Surface.Elements Vector2 endPos = targetBox.Parent.PointToParent(ref tmp); var highlight = 1 + Mathf.Max(startHighlight, targetBox.ConnectionsHighlightIntensity); var color = _currentTypeColor * highlight; + + // if (PointInRectangle(ref startPos, ref endPos, ref mousePosition)) + { + for (int ix = 0; ix < 10000; ix++) + { + OutputBox.IntersectsConnection(ref startPos, ref endPos, ref mousePosition, 30f); + } + if (OutputBox.IntersectsConnection(ref startPos, ref endPos, ref mousePosition, 30f)) + { + highlight += 2; + } + } + + DrawConnection(ref startPos, ref endPos, ref color, highlight); } } + private bool PointInRectangle(ref Vector2 a, ref Vector2 b, ref Vector2 point) + { + // This has the convenient property that it doesn't matter if a and b are switched + Vector2 signs = (point - a) * (b - point); + return signs.X >= 0 && signs.Y >= 0; + } + /// /// Draw a selected connections coming from this box. ///