using System; using UnityEditor; using UnityEngine; namespace PathBerserker2d { internal static class GizmosDrawingExtensions { public static void DrawArrowHead(Vector2 basePos, Vector2 dir, float size) { dir.Normalize(); Vector2 normal = new Vector2(-dir.y, dir.x) * size; Gizmos.DrawLine(basePos - normal, basePos + normal); Gizmos.DrawLine(basePos - normal, basePos + dir * size); Gizmos.DrawLine(basePos + normal, basePos + dir * size); } public static void DrawArrowHeadFromSpike(Vector2 pointyPos, Vector2 dir, float size) { dir.Normalize(); pointyPos -= dir * size; Vector2 normal = new Vector2(-dir.y, dir.x) * size; Gizmos.DrawLine(pointyPos - normal, pointyPos + normal); Gizmos.DrawLine(pointyPos - normal, pointyPos + dir * size); Gizmos.DrawLine(pointyPos + normal, pointyPos + dir * size); } public static void DrawArrow(Vector2 start, Vector2 end, float size) { Vector2 dir = end - start; float length = dir.magnitude; dir /= length; Vector3 end3 = new Vector3(end.x, end.y); Gizmos.DrawLine(start, end3); Vector2 normal = new Vector2(-dir.y, dir.x) * size; Vector2 baseA = start + dir * (length - size); Gizmos.DrawLine(baseA - normal, end3); Gizmos.DrawLine(baseA + normal, end3); } public static void DrawCircle(Vector2 center, float radius = 0.05f) { int segmentCount = 10; Vector2 prevPoint = center + Vector2.up * radius; for (float t = 1; t <= segmentCount; t++) { float x = (t / segmentCount) * Mathf.PI * 2.0f; float cx = Mathf.Sin(x); float cy = Mathf.Cos(x); Vector2 point = center + new Vector2(cx, cy) * radius; Gizmos.DrawLine(prevPoint, point); prevPoint = point; } Gizmos.DrawLine(prevPoint, center + Vector2.up * radius); } public static void DrawBezierConnection(Vector2 start, Vector2 end, bool biDirectional) { Vector2 cp; var tangent = (end - start); var length = tangent.magnitude; var normal = new Vector2(-tangent.y, tangent.x) / length; cp = start + tangent * 0.5f + normal * (length / 5f); DrawBezierConnection(start, end, cp, biDirectional); } public static void DrawBezierConnection(Vector2 start, Vector2 end, Vector2 cp, bool biDirectional) { float arcLength = (Vector2.Distance(end, start) * 2 + Vector2.Distance(end, cp) + Vector2.Distance(start, cp)) / 3f; int numberOfSegments = Mathf.CeilToInt(arcLength) + 4; Vector2 prev = start; float t; for (t = 1; t <= numberOfSegments; t++) { Vector2 v = QuadraticBezierCurve(t / numberOfSegments, start, cp, end); Gizmos.DrawLine(prev, v); prev = v; } //draw arrows t = (numberOfSegments - 1) / (float)numberOfSegments; Vector2 dir = end - QuadraticBezierCurve(t, start, cp, end); DrawArrowHeadFromSpike(end, dir, 0.2f); if (biDirectional) { dir = start - QuadraticBezierCurve(1f / numberOfSegments, start, cp, end); DrawArrowHeadFromSpike(start, dir, 0.2f); } } public static void DrawBezierConnectionWithOffset(Vector2 start, Vector2 end, Vector2 cp, Vector2 offset) { float arcLength = (Vector2.Distance(end, start) * 2 + Vector2.Distance(end, cp) + Vector2.Distance(start, cp)) / 3f; int numberOfSegments = Mathf.CeilToInt(arcLength); Vector2 prev = start + offset; Gizmos.DrawLine(start, prev); float t; for (t = 1; t <= numberOfSegments; t++) { Vector2 v = QuadraticBezierCurve(t / numberOfSegments, start, cp, end) + offset; Gizmos.DrawLine(v, v - offset); Gizmos.DrawLine(prev, v); prev = v; } } public static void DrawProjectileArc(Vector2 start, Vector2 end, float hSpeed, bool isBidiretional) { float hDelta = end.x - start.x; float t = hDelta / hSpeed; int numberOfSegments = Mathf.CeilToInt(t) + 4; float p0 = start.y - end.y; float v0 = 9.81f * t * 0.5f - p0 / t; Func func = x => 0.5f * -9.81f * x * x + v0 * x + p0; Vector2 prev = start; float z; float timePerSegment = t / numberOfSegments; for (z = 1; z <= numberOfSegments; z++) { Vector2 v = new Vector2(start.x + z * timePerSegment * hSpeed, end.y + func(z * timePerSegment)); Gizmos.DrawLine(prev, v); prev = v; } Vector2 dir = end - new Vector2(start.x + (numberOfSegments - 1) * timePerSegment * hSpeed, end.y + func((numberOfSegments - 1) * timePerSegment)); DrawArrowHeadFromSpike(end, dir, 0.2f); if (isBidiretional) { dir = start - new Vector2(start.x + timePerSegment * hSpeed, end.y + func(timePerSegment)); DrawArrowHeadFromSpike(start, dir, 0.2f); } } public static void DrawJumpArc(Vector2 start, Vector2 end, float jumpSpeed, bool isBidiretional) { Vector2 dir = end - start; float distance = dir.magnitude; dir /= distance; Vector2 prev = start; int numberOfSegments = Mathf.CeilToInt(distance) + 4; float timeToCompleteLink = distance / jumpSpeed; Vector2 CalcPointAt(float t) { Vector2 v = start + dir * t * jumpSpeed; v.y += distance * 0.3f * Mathf.Sin(Mathf.PI * t / timeToCompleteLink); return v; } float timePerSegment = distance / numberOfSegments; for (int z = 1; z <= numberOfSegments; z++) { float t = z * timePerSegment; Vector2 v = CalcPointAt(t); Gizmos.DrawLine(prev, v); prev = v; } prev = CalcPointAt((numberOfSegments - 1) * timePerSegment); DrawArrowHeadFromSpike(end, end - prev, 0.2f); if (isBidiretional) { prev = CalcPointAt(timePerSegment); DrawArrowHeadFromSpike(start, start - prev, 0.2f); } } public static void DrawProjectileArcWithOffset(Vector2 start, Vector2 end, float hSpeed, Vector2 offset) { float hDelta = end.x - start.x; float t = hDelta / hSpeed; int numberOfSegments = Mathf.CeilToInt(t) + 4; float p0 = start.y - end.y; float v0 = 9.81f * t * 0.5f - p0 / t; Func func = x => 0.5f * -9.81f * x * x + v0 * x + p0; Vector2 prev = start + offset; Gizmos.DrawLine(start, prev); float z; float timePerSegment = t / numberOfSegments; for (z = 1; z <= numberOfSegments; z++) { Vector2 v = new Vector2(start.x + z * timePerSegment * hSpeed, end.y + func(z * timePerSegment)) + offset; Gizmos.DrawLine(prev, v); Gizmos.DrawLine(v, v - offset); prev = v; } } private static Vector2 QuadraticBezierCurve(float t, Vector2 a, Vector2 b, Vector2 c) { return (1 - t) * (1 - t) * a + 2 * (1 - t) * t * b + t * t * c; } public static Color LinearBlendBetweenColors(float value, params Color[] colors) { value = Mathf.Clamp01(value); int index = (int)(value * (colors.Length - 1)); float t = (value * (colors.Length - 1)) - index; Color b = index >= colors.Length - 1 ? colors[index] : colors[index + 1]; return Color.Lerp(colors[index], b, t); } public static void DrawRect(Vector2 position, Vector2 size) { Gizmos.DrawLine(position + size, new Vector3(position.x, position.y + size.y)); Gizmos.DrawLine(position, new Vector3(position.x, position.y + size.y)); Gizmos.DrawLine(position + size, new Vector3(position.x + size.x, position.y)); Gizmos.DrawLine(position, new Vector3(position.x + size.x, position.y)); } public static void DrawRect(Rect rect) { Gizmos.DrawLine(rect.position + rect.size, new Vector3(rect.position.x, rect.position.y + rect.size.y)); Gizmos.DrawLine(rect.position, new Vector3(rect.position.x, rect.position.y + rect.size.y)); Gizmos.DrawLine(rect.position + rect.size, new Vector3(rect.position.x + rect.size.x, rect.position.y)); Gizmos.DrawLine(rect.position, new Vector3(rect.position.x + rect.size.x, rect.position.y)); } public static void SetColor(Color color) { Handles.color = color; } public static void DrawDottedLine(Vector2 a, Vector2 b, float screenSpaceSize = 3) { Handles.DrawDottedLine(a, b, screenSpaceSize); } } }