240 lines
9.4 KiB
C#
240 lines
9.4 KiB
C#
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<float, float> 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<float, float> 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);
|
|
}
|
|
}
|
|
}
|