This commit is contained in:
Mister_Nebula 2021-01-04 17:31:58 +00:00
parent a7284cf945
commit 1dd58e977c
10 changed files with 841 additions and 845 deletions

View File

@ -1,8 +1,8 @@
namespace Popcron
{
public class Constants
{
public const string UniqueIdentifier = "Popcron.Gizmos";
public const string EnabledKey = UniqueIdentifier + ".Enabled";
}
public class Constants
{
public const string UniqueIdentifier = "Popcron.Gizmos";
public const string EnabledKey = UniqueIdentifier + ".Enabled";
}
}

View File

@ -1,70 +1,70 @@
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace Popcron
{
public abstract class Drawer
{
private static Dictionary<Type, Drawer> typeToDrawer = null;
public abstract class Drawer
{
private static Dictionary<Type, Drawer> typeToDrawer = null;
public abstract int Draw(ref Vector3[] buffer, params object[] args);
public abstract int Draw(ref Vector3[] buffer, params object[] args);
public Drawer()
{
public Drawer()
{
}
}
public static Drawer Get<T>() where T : class
{
//find all drawers
if (typeToDrawer == null)
{
typeToDrawer = new Dictionary<Type, Drawer>();
public static Drawer Get<T>() where T : class
{
//find all drawers
if (typeToDrawer == null)
{
typeToDrawer = new Dictionary<Type, Drawer>();
//add defaults
//add defaults
typeToDrawer.Add(typeof(CubeDrawer), new CubeDrawer());
typeToDrawer.Add(typeof(LineDrawer), new LineDrawer());
typeToDrawer.Add(typeof(PolygonDrawer),new PolygonDrawer());
typeToDrawer.Add(typeof(PolygonDrawer), new PolygonDrawer());
typeToDrawer.Add(typeof(SquareDrawer), new SquareDrawer());
//find extras
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.IsAbstract)
{
continue;
}
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.IsAbstract)
{
continue;
}
if (type.IsSubclassOf(typeof(Drawer)) && !typeToDrawer.ContainsKey(type))
{
try
{
Drawer value = (Drawer)Activator.CreateInstance(type);
typeToDrawer[type] = value;
}
catch (Exception e)
{
Debug.LogError($"couldnt register drawer of type {type} because {e.Message}");
}
}
}
}
}
if (type.IsSubclassOf(typeof(Drawer)) && !typeToDrawer.ContainsKey(type))
{
try
{
Drawer value = (Drawer)Activator.CreateInstance(type);
typeToDrawer[type] = value;
}
catch (Exception e)
{
Debug.LogError($"couldnt register drawer of type {type} because {e.Message}");
}
}
}
}
}
if (typeToDrawer.TryGetValue(typeof(T), out Drawer drawer))
{
return drawer;
}
else
{
return null;
}
}
}
if (typeToDrawer.TryGetValue(typeof(T), out Drawer drawer))
{
return drawer;
}
else
{
return null;
}
}
}
}

View File

@ -2,95 +2,95 @@
namespace Popcron
{
public class CubeDrawer : Drawer
{
public class CubeDrawer : Drawer
{
public CubeDrawer()
{
}
public override int Draw(ref Vector3[] buffer, params object[] values)
{
Vector3 position = (Vector3)values[0];
Quaternion rotation = (Quaternion)values[1];
Vector3 size = (Vector3)values[2];
size *= 0.5f;
public override int Draw(ref Vector3[] buffer, params object[] values)
{
Vector3 position = (Vector3)values[0];
Quaternion rotation = (Quaternion)values[1];
Vector3 size = (Vector3)values[2];
Vector3 point1 = new Vector3(position.x - size.x, position.y - size.y, position.z - size.z);
Vector3 point2 = new Vector3(position.x + size.x, position.y - size.y, position.z - size.z);
Vector3 point3 = new Vector3(position.x + size.x, position.y + size.y, position.z - size.z);
Vector3 point4 = new Vector3(position.x - size.x, position.y + size.y, position.z - size.z);
size *= 0.5f;
Vector3 point5 = new Vector3(position.x - size.x, position.y - size.y, position.z + size.z);
Vector3 point6 = new Vector3(position.x + size.x, position.y - size.y, position.z + size.z);
Vector3 point7 = new Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
Vector3 point8 = new Vector3(position.x - size.x, position.y + size.y, position.z + size.z);
Vector3 point1 = new Vector3(position.x - size.x, position.y - size.y, position.z - size.z);
Vector3 point2 = new Vector3(position.x + size.x, position.y - size.y, position.z - size.z);
Vector3 point3 = new Vector3(position.x + size.x, position.y + size.y, position.z - size.z);
Vector3 point4 = new Vector3(position.x - size.x, position.y + size.y, position.z - size.z);
point1 = rotation * (point1 - position);
point1 += position;
Vector3 point5 = new Vector3(position.x - size.x, position.y - size.y, position.z + size.z);
Vector3 point6 = new Vector3(position.x + size.x, position.y - size.y, position.z + size.z);
Vector3 point7 = new Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
Vector3 point8 = new Vector3(position.x - size.x, position.y + size.y, position.z + size.z);
point2 = rotation * (point2 - position);
point2 += position;
point1 = rotation * (point1 - position);
point1 += position;
point3 = rotation * (point3 - position);
point3 += position;
point2 = rotation * (point2 - position);
point2 += position;
point4 = rotation * (point4 - position);
point4 += position;
point3 = rotation * (point3 - position);
point3 += position;
point5 = rotation * (point5 - position);
point5 += position;
point4 = rotation * (point4 - position);
point4 += position;
point6 = rotation * (point6 - position);
point6 += position;
point5 = rotation * (point5 - position);
point5 += position;
point7 = rotation * (point7 - position);
point7 += position;
point6 = rotation * (point6 - position);
point6 += position;
point8 = rotation * (point8 - position);
point8 += position;
point7 = rotation * (point7 - position);
point7 += position;
//square
buffer[0] = point1;
buffer[1] = point2;
point8 = rotation * (point8 - position);
point8 += position;
buffer[2] = point2;
buffer[3] = point3;
//square
buffer[0] = point1;
buffer[1] = point2;
buffer[4] = point3;
buffer[5] = point4;
buffer[2] = point2;
buffer[3] = point3;
buffer[6] = point4;
buffer[7] = point1;
buffer[4] = point3;
buffer[5] = point4;
//other square
buffer[8] = point5;
buffer[9] = point6;
buffer[6] = point4;
buffer[7] = point1;
buffer[10] = point6;
buffer[11] = point7;
//other square
buffer[8] = point5;
buffer[9] = point6;
buffer[12] = point7;
buffer[13] = point8;
buffer[10] = point6;
buffer[11] = point7;
buffer[14] = point8;
buffer[15] = point5;
buffer[12] = point7;
buffer[13] = point8;
//connectors
buffer[16] = point1;
buffer[17] = point5;
buffer[14] = point8;
buffer[15] = point5;
buffer[18] = point2;
buffer[19] = point6;
//connectors
buffer[16] = point1;
buffer[17] = point5;
buffer[20] = point3;
buffer[21] = point7;
buffer[18] = point2;
buffer[19] = point6;
buffer[22] = point4;
buffer[23] = point8;
buffer[20] = point3;
buffer[21] = point7;
return 24;
}
}
buffer[22] = point4;
buffer[23] = point8;
return 24;
}
}
}

View File

@ -2,18 +2,18 @@
namespace Popcron
{
public class LineDrawer : Drawer
{
public class LineDrawer : Drawer
{
public LineDrawer()
{
}
public override int Draw(ref Vector3[] buffer, params object[] args)
{
buffer[0] = (Vector3)args[0];
buffer[1] = (Vector3)args[1];
return 2;
}
}
public override int Draw(ref Vector3[] buffer, params object[] args)
{
buffer[0] = (Vector3)args[0];
buffer[1] = (Vector3)args[1];
return 2;
}
}
}

View File

@ -2,39 +2,39 @@
namespace Popcron
{
public class PolygonDrawer : Drawer
{
public class PolygonDrawer : Drawer
{
public PolygonDrawer()
{
}
public override int Draw(ref Vector3[] buffer, params object[] values)
{
Vector3 position = (Vector3)values[0];
int points = (int)values[1];
float radius = (float)values[2];
float offset = (float)values[3];
Quaternion rotation = (Quaternion)values[4];
float step = 360f / points;
offset *= Mathf.Deg2Rad;
public override int Draw(ref Vector3[] buffer, params object[] values)
{
Vector3 position = (Vector3)values[0];
int points = (int)values[1];
float radius = (float)values[2];
float offset = (float)values[3];
Quaternion rotation = (Quaternion)values[4];
for (int i = 0; i < points; i++)
{
float cx = Mathf.Cos(Mathf.Deg2Rad * step * i + offset) * radius;
float cy = Mathf.Sin(Mathf.Deg2Rad * step * i + offset) * radius;
Vector3 current = new Vector3(cx, cy);
float step = 360f / points;
offset *= Mathf.Deg2Rad;
float nx = Mathf.Cos(Mathf.Deg2Rad * step * (i + 1) + offset) * radius;
float ny = Mathf.Sin(Mathf.Deg2Rad * step * (i + 1) + offset) * radius;
Vector3 next = new Vector3(nx, ny);
for (int i = 0; i < points; i++)
{
float cx = Mathf.Cos(Mathf.Deg2Rad * step * i + offset) * radius;
float cy = Mathf.Sin(Mathf.Deg2Rad * step * i + offset) * radius;
Vector3 current = new Vector3(cx, cy);
buffer[i * 2] = position + (rotation * current);
buffer[(i * 2) + 1] = position + (rotation * next);
}
float nx = Mathf.Cos(Mathf.Deg2Rad * step * (i + 1) + offset) * radius;
float ny = Mathf.Sin(Mathf.Deg2Rad * step * (i + 1) + offset) * radius;
Vector3 next = new Vector3(nx, ny);
return points * 2;
}
}
buffer[i * 2] = position + (rotation * current);
buffer[(i * 2) + 1] = position + (rotation * next);
}
return points * 2;
}
}
}

View File

@ -2,71 +2,71 @@
namespace Popcron
{
public class SquareDrawer : Drawer
{
public class SquareDrawer : Drawer
{
public SquareDrawer()
{
}
public override int Draw(ref Vector3[] buffer, params object[] values)
{
Vector2 position = default;
if (values[0] is Vector2 p2)
{
position = p2;
}
else if (values[0] is Vector3 p3)
{
position = p3;
}
Quaternion rotation = (Quaternion)values[1];
public override int Draw(ref Vector3[] buffer, params object[] values)
{
Vector2 position = default;
if (values[0] is Vector2 p2)
{
position = p2;
}
else if (values[0] is Vector3 p3)
{
position = p3;
}
Vector2 size = default;
if (values[2] is Vector2 s2)
{
size = s2;
}
else if (values[2] is Vector3 s3)
{
size = s3;
}
Quaternion rotation = (Quaternion)values[1];
size *= 0.5f;
Vector2 size = default;
if (values[2] is Vector2 s2)
{
size = s2;
}
else if (values[2] is Vector3 s3)
{
size = s3;
}
Vector2 point1 = new Vector3(position.x - size.x, position.y - size.y);
Vector2 point2 = new Vector3(position.x + size.x, position.y - size.y);
Vector2 point3 = new Vector3(position.x + size.x, position.y + size.y);
Vector2 point4 = new Vector3(position.x - size.x, position.y + size.y);
size *= 0.5f;
point1 = rotation * (point1 - position);
point1 += position;
Vector2 point1 = new Vector3(position.x - size.x, position.y - size.y);
Vector2 point2 = new Vector3(position.x + size.x, position.y - size.y);
Vector2 point3 = new Vector3(position.x + size.x, position.y + size.y);
Vector2 point4 = new Vector3(position.x - size.x, position.y + size.y);
point2 = rotation * (point2 - position);
point2 += position;
point1 = rotation * (point1 - position);
point1 += position;
point3 = rotation * (point3 - position);
point3 += position;
point2 = rotation * (point2 - position);
point2 += position;
point4 = rotation * (point4 - position);
point4 += position;
point3 = rotation * (point3 - position);
point3 += position;
//square
buffer[0] = point1;
buffer[1] = point2;
point4 = rotation * (point4 - position);
point4 += position;
buffer[2] = point2;
buffer[3] = point3;
//square
buffer[0] = point1;
buffer[1] = point2;
buffer[4] = point3;
buffer[5] = point4;
buffer[2] = point2;
buffer[3] = point3;
//loop back to start
buffer[6] = point4;
buffer[7] = point1;
buffer[4] = point3;
buffer[5] = point4;
return 8;
}
}
//loop back to start
buffer[6] = point4;
buffer[7] = point1;
return 8;
}
}
}

View File

@ -1,12 +1,11 @@
using System;
using UnityEngine;
using UnityEngine;
namespace Popcron
{
internal class Element
{
public Vector3[] points = { };
public Color color = Color.white;
public bool dashed = false;
}
internal class Element
{
public Vector3[] points = { };
public Color color = Color.white;
public bool dashed = false;
}
}

View File

@ -3,374 +3,374 @@ using UnityEngine;
namespace Popcron
{
public class Gizmos
{
private static string _prefsKey = null;
private static int? _bufferSize = null;
private static bool? _enabled = null;
private static float? _dashGap = null;
private static bool? _cull = null;
private static int? _pass = null;
private static Vector3? _offset = null;
public class Gizmos
{
private static string _prefsKey = null;
private static int? _bufferSize = null;
private static bool? _enabled = null;
private static float? _dashGap = null;
private static bool? _cull = null;
private static int? _pass = null;
private static Vector3? _offset = null;
private static Vector3[] buffer = new Vector3[BufferSize];
private static Vector3[] buffer = new Vector3[BufferSize];
/// <summary>
/// By default, it will always render to scene view camera and the main camera.
/// Subscribing to this allows you to whitelist your custom cameras.
/// </summary>
public static Func<Camera, bool> CameraFilter = cam => false;
/// <summary>
/// By default, it will always render to scene view camera and the main camera.
/// Subscribing to this allows you to whitelist your custom cameras.
/// </summary>
public static Func<Camera, bool> CameraFilter = cam => false;
private static string PrefsKey
{
get
{
if (string.IsNullOrEmpty(_prefsKey))
{
_prefsKey = $"{SystemInfo.deviceUniqueIdentifier}.{Application.companyName}.{Application.productName}.{Constants.UniqueIdentifier}";
}
private static string PrefsKey
{
get
{
if (string.IsNullOrEmpty(_prefsKey))
{
_prefsKey = $"{SystemInfo.deviceUniqueIdentifier}.{Application.companyName}.{Application.productName}.{Constants.UniqueIdentifier}";
}
return _prefsKey;
}
}
return _prefsKey;
}
}
/// <summary>
/// The size of the total gizmos buffer.
/// Default is 4096.
/// </summary>
public static int BufferSize
{
get
{
if (_bufferSize == null)
{
_bufferSize = PlayerPrefs.GetInt($"{PrefsKey}.BufferSize", 4096);
}
/// <summary>
/// The size of the total gizmos buffer.
/// Default is 4096.
/// </summary>
public static int BufferSize
{
get
{
if (_bufferSize == null)
{
_bufferSize = PlayerPrefs.GetInt($"{PrefsKey}.BufferSize", 4096);
}
return _bufferSize.Value;
}
set
{
value = Mathf.Clamp(value, 0, int.MaxValue);
if (_bufferSize != value)
{
_bufferSize = value;
PlayerPrefs.SetInt($"{PrefsKey}.BufferSize", value);
return _bufferSize.Value;
}
set
{
value = Mathf.Clamp(value, 0, int.MaxValue);
if (_bufferSize != value)
{
_bufferSize = value;
PlayerPrefs.SetInt($"{PrefsKey}.BufferSize", value);
//buffer size changed, so recreate the buffer array too
buffer = new Vector3[value];
}
}
}
//buffer size changed, so recreate the buffer array too
buffer = new Vector3[value];
}
}
}
/// <summary>
/// Toggles wether the gizmos could be drawn or not.
/// </summary>
public static bool Enabled
{
get
{
if (_enabled == null)
{
_enabled = PlayerPrefs.GetInt($"{PrefsKey}.Enabled", 1) == 1;
}
/// <summary>
/// Toggles wether the gizmos could be drawn or not.
/// </summary>
public static bool Enabled
{
get
{
if (_enabled == null)
{
_enabled = PlayerPrefs.GetInt($"{PrefsKey}.Enabled", 1) == 1;
}
return _enabled.Value;
}
set
{
if (_enabled != value)
{
_enabled = value;
PlayerPrefs.SetInt($"{PrefsKey}.Enabled", value ? 1 : 0);
}
}
}
return _enabled.Value;
}
set
{
if (_enabled != value)
{
_enabled = value;
PlayerPrefs.SetInt($"{PrefsKey}.Enabled", value ? 1 : 0);
}
}
}
/// <summary>
/// The size of the gap when drawing dashed elements.
/// Default gap size is 0.1
/// </summary>
public static float DashGap
{
get
{
if (_dashGap == null)
{
_dashGap = PlayerPrefs.GetFloat($"{PrefsKey}.DashGap", 0.1f);
}
/// <summary>
/// The size of the gap when drawing dashed elements.
/// Default gap size is 0.1
/// </summary>
public static float DashGap
{
get
{
if (_dashGap == null)
{
_dashGap = PlayerPrefs.GetFloat($"{PrefsKey}.DashGap", 0.1f);
}
return _dashGap.Value;
}
set
{
if (_dashGap != value)
{
_dashGap = value;
PlayerPrefs.SetFloat($"{PrefsKey}.DashGap", value);
}
}
}
return _dashGap.Value;
}
set
{
if (_dashGap != value)
{
_dashGap = value;
PlayerPrefs.SetFloat($"{PrefsKey}.DashGap", value);
}
}
}
[Obsolete("This property is obsolete. Use FrustumCulling instead.", false)]
public static bool Cull
{
get
{
return FrustumCulling;
}
set
{
FrustumCulling = value;
}
}
[Obsolete("This property is obsolete. Use FrustumCulling instead.", false)]
public static bool Cull
{
get
{
return FrustumCulling;
}
set
{
FrustumCulling = value;
}
}
[Obsolete("This property is obsolete. Subscribe to CameraFilter predicate instead and return true for your custom camera.", false)]
public static Camera Camera
{
get => null;
set
{
[Obsolete("This property is obsolete. Subscribe to CameraFilter predicate instead and return true for your custom camera.", false)]
public static Camera Camera
{
get => null;
set
{
}
}
}
}
/// <summary>
/// Should the camera not draw elements that are not visible?
/// </summary>
public static bool FrustumCulling
{
get
{
if (_cull == null)
{
_cull = PlayerPrefs.GetInt($"{PrefsKey}.FrustumCulling", 1) == 1;
}
/// <summary>
/// Should the camera not draw elements that are not visible?
/// </summary>
public static bool FrustumCulling
{
get
{
if (_cull == null)
{
_cull = PlayerPrefs.GetInt($"{PrefsKey}.FrustumCulling", 1) == 1;
}
return _cull.Value;
}
set
{
if (_cull != value)
{
_cull = value;
PlayerPrefs.SetInt($"{PrefsKey}.FrustumCulling", value ? 1 : 0);
}
}
}
return _cull.Value;
}
set
{
if (_cull != value)
{
_cull = value;
PlayerPrefs.SetInt($"{PrefsKey}.FrustumCulling", value ? 1 : 0);
}
}
}
/// <summary>
/// The material being used to render.
/// </summary>
public static Material Material
{
get => GizmosInstance.Material;
set => GizmosInstance.Material = value;
}
/// <summary>
/// The material being used to render.
/// </summary>
public static Material Material
{
get => GizmosInstance.Material;
set => GizmosInstance.Material = value;
}
/// <summary>
/// Rendering pass to activate.
/// </summary>
public static int Pass
{
get
{
if (_pass == null)
{
_pass = PlayerPrefs.GetInt($"{PrefsKey}.Pass", 0);
}
/// <summary>
/// Rendering pass to activate.
/// </summary>
public static int Pass
{
get
{
if (_pass == null)
{
_pass = PlayerPrefs.GetInt($"{PrefsKey}.Pass", 0);
}
return _pass.Value;
}
set
{
if (_pass != value)
{
_pass = value;
PlayerPrefs.SetInt($"{PrefsKey}.Pass", value);
}
}
}
return _pass.Value;
}
set
{
if (_pass != value)
{
_pass = value;
PlayerPrefs.SetInt($"{PrefsKey}.Pass", value);
}
}
}
/// <summary>
/// Global offset for all points. Default is (0, 0, 0).
/// </summary>
public static Vector3 Offset
{
get
{
const string Delim = ",";
if (_offset == null)
{
string data = PlayerPrefs.GetString($"{PrefsKey}.Offset", 0 + Delim + 0 + Delim + 0);
int indexOf = data.IndexOf(Delim);
int lastIndexOf = data.LastIndexOf(Delim);
if (indexOf + lastIndexOf > 0)
{
string[] arr = data.Split(Delim[0]);
_offset = new Vector3(float.Parse(arr[0]), float.Parse(arr[1]), float.Parse(arr[2]));
}
else
{
return Vector3.zero;
}
}
/// <summary>
/// Global offset for all points. Default is (0, 0, 0).
/// </summary>
public static Vector3 Offset
{
get
{
const string Delim = ",";
if (_offset == null)
{
string data = PlayerPrefs.GetString($"{PrefsKey}.Offset", 0 + Delim + 0 + Delim + 0);
int indexOf = data.IndexOf(Delim);
int lastIndexOf = data.LastIndexOf(Delim);
if (indexOf + lastIndexOf > 0)
{
string[] arr = data.Split(Delim[0]);
_offset = new Vector3(float.Parse(arr[0]), float.Parse(arr[1]), float.Parse(arr[2]));
}
else
{
return Vector3.zero;
}
}
return _offset.Value;
}
set
{
const string Delim = ",";
if (_offset != value)
{
_offset = value;
PlayerPrefs.SetString($"{PrefsKey}.Offset", value.x + Delim + value.y + Delim + value.y);
}
}
}
return _offset.Value;
}
set
{
const string Delim = ",";
if (_offset != value)
{
_offset = value;
PlayerPrefs.SetString($"{PrefsKey}.Offset", value.x + Delim + value.y + Delim + value.y);
}
}
}
/// <summary>
/// Draws an element onto the screen.
/// </summary>
public static void Draw<T>(Color? color, bool dashed, params object[] args) where T : Drawer
{
if (!Enabled)
{
return;
}
/// <summary>
/// Draws an element onto the screen.
/// </summary>
public static void Draw<T>(Color? color, bool dashed, params object[] args) where T : Drawer
{
if (!Enabled)
{
return;
}
Drawer drawer = Drawer.Get<T>();
if (drawer != null)
{
int points = drawer.Draw(ref buffer, args);
Drawer drawer = Drawer.Get<T>();
if (drawer != null)
{
int points = drawer.Draw(ref buffer, args);
//copy from buffer and add to the queue
Vector3[] array = new Vector3[points];
Array.Copy(buffer, array, points);
GizmosInstance.Submit(array, color, dashed);
}
}
//copy from buffer and add to the queue
Vector3[] array = new Vector3[points];
Array.Copy(buffer, array, points);
GizmosInstance.Submit(array, color, dashed);
}
}
/// <summary>
/// Draws an array of lines. Useful for things like paths.
/// </summary>
public static void Lines(Vector3[] lines, Color? color = null, bool dashed = false)
{
if (!Enabled)
{
return;
}
/// <summary>
/// Draws an array of lines. Useful for things like paths.
/// </summary>
public static void Lines(Vector3[] lines, Color? color = null, bool dashed = false)
{
if (!Enabled)
{
return;
}
GizmosInstance.Submit(lines, color, dashed);
}
GizmosInstance.Submit(lines, color, dashed);
}
/// <summary>
/// Draw line in world space.
/// </summary>
public static void Line(Vector3 a, Vector3 b, Color? color = null, bool dashed = false)
{
Draw<LineDrawer>(color, dashed, a, b);
}
/// <summary>
/// Draw line in world space.
/// </summary>
public static void Line(Vector3 a, Vector3 b, Color? color = null, bool dashed = false)
{
Draw<LineDrawer>(color, dashed, a, b);
}
/// <summary>
/// Draw square in world space.
/// </summary>
public static void Square(Vector2 position, Vector2 size, Color? color = null, bool dashed = false)
{
Square(position, Quaternion.identity, size, color, dashed);
}
/// <summary>
/// Draw square in world space.
/// </summary>
public static void Square(Vector2 position, Vector2 size, Color? color = null, bool dashed = false)
{
Square(position, Quaternion.identity, size, color, dashed);
}
/// <summary>
/// Draw square in world space with float diameter parameter.
/// </summary>
public static void Square(Vector2 position, float diameter, Color? color = null, bool dashed = false)
{
Square(position, Quaternion.identity, Vector2.one * diameter, color, dashed);
}
/// <summary>
/// Draw square in world space with float diameter parameter.
/// </summary>
public static void Square(Vector2 position, float diameter, Color? color = null, bool dashed = false)
{
Square(position, Quaternion.identity, Vector2.one * diameter, color, dashed);
}
/// <summary>
/// Draw square in world space with a rotation parameter.
/// </summary>
public static void Square(Vector2 position, Quaternion rotation, Vector2 size, Color? color = null, bool dashed = false)
{
Draw<SquareDrawer>(color, dashed, position, rotation, size);
}
/// <summary>
/// Draw square in world space with a rotation parameter.
/// </summary>
public static void Square(Vector2 position, Quaternion rotation, Vector2 size, Color? color = null, bool dashed = false)
{
Draw<SquareDrawer>(color, dashed, position, rotation, size);
}
/// <summary>
/// Draws a cube in world space.
/// </summary>
public static void Cube(Vector3 position, Quaternion rotation, Vector3 size, Color? color = null, bool dashed = false)
{
Draw<CubeDrawer>(color, dashed, position, rotation, size);
}
/// <summary>
/// Draws a cube in world space.
/// </summary>
public static void Cube(Vector3 position, Quaternion rotation, Vector3 size, Color? color = null, bool dashed = false)
{
Draw<CubeDrawer>(color, dashed, position, rotation, size);
}
/// <summary>
/// Draws a rectangle in screen space.
/// </summary>
public static void Rect(Rect rect, Camera camera, Color? color = null, bool dashed = false)
{
rect.y = Screen.height - rect.y;
Vector2 corner = camera.ScreenToWorldPoint(new Vector2(rect.x, rect.y - rect.height));
Draw<SquareDrawer>(color, dashed, corner + rect.size * 0.5f, Quaternion.identity, rect.size);
}
/// <summary>
/// Draws a rectangle in screen space.
/// </summary>
public static void Rect(Rect rect, Camera camera, Color? color = null, bool dashed = false)
{
rect.y = Screen.height - rect.y;
Vector2 corner = camera.ScreenToWorldPoint(new Vector2(rect.x, rect.y - rect.height));
Draw<SquareDrawer>(color, dashed, corner + rect.size * 0.5f, Quaternion.identity, rect.size);
}
/// <summary>
/// Draws a representation of a bounding box.
/// </summary>
public static void Bounds(Bounds bounds, Color? color = null, bool dashed = false)
{
Draw<CubeDrawer>(color, dashed, bounds.center, Quaternion.identity, bounds.size);
}
/// <summary>
/// Draws a representation of a bounding box.
/// </summary>
public static void Bounds(Bounds bounds, Color? color = null, bool dashed = false)
{
Draw<CubeDrawer>(color, dashed, bounds.center, Quaternion.identity, bounds.size);
}
/// <summary>
/// Draws a cone similar to the one that spot lights draw.
/// </summary>
public static void Cone(Vector3 position, Quaternion rotation, float length, float angle, Color? color = null, bool dashed = false, int pointsCount = 16)
{
//draw the end of the cone
float endAngle = Mathf.Tan(angle * 0.5f * Mathf.Deg2Rad) * length;
Vector3 forward = rotation * Vector3.forward;
Vector3 endPosition = position + forward * length;
float offset = 0f;
Draw<PolygonDrawer>(color, dashed, endPosition, pointsCount, endAngle, offset, rotation);
/// <summary>
/// Draws a cone similar to the one that spot lights draw.
/// </summary>
public static void Cone(Vector3 position, Quaternion rotation, float length, float angle, Color? color = null, bool dashed = false, int pointsCount = 16)
{
//draw the end of the cone
float endAngle = Mathf.Tan(angle * 0.5f * Mathf.Deg2Rad) * length;
Vector3 forward = rotation * Vector3.forward;
Vector3 endPosition = position + forward * length;
float offset = 0f;
Draw<PolygonDrawer>(color, dashed, endPosition, pointsCount, endAngle, offset, rotation);
//draw the 4 lines
for (int i = 0; i < 4; i++)
{
float a = i * 90f * Mathf.Deg2Rad;
Vector3 point = rotation * new Vector3(Mathf.Cos(a), Mathf.Sin(a)) * endAngle;
Line(position, position + point + forward * length, color, dashed);
}
}
//draw the 4 lines
for (int i = 0; i < 4; i++)
{
float a = i * 90f * Mathf.Deg2Rad;
Vector3 point = rotation * new Vector3(Mathf.Cos(a), Mathf.Sin(a)) * endAngle;
Line(position, position + point + forward * length, color, dashed);
}
}
/// <summary>
/// Draws a sphere at position with specified radius.
/// </summary>
public static void Sphere(Vector3 position, float radius, Color? color = null, bool dashed = false, int pointsCount = 16)
{
float offset = 0f;
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(0f, 0f, 0f));
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(90f, 0f, 0f));
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(0f, 90f, 90f));
}
/// <summary>
/// Draws a sphere at position with specified radius.
/// </summary>
public static void Sphere(Vector3 position, float radius, Color? color = null, bool dashed = false, int pointsCount = 16)
{
float offset = 0f;
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(0f, 0f, 0f));
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(90f, 0f, 0f));
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, Quaternion.Euler(0f, 90f, 90f));
}
/// <summary>
/// Draws a circle in world space and billboards towards the camera.
/// </summary>
public static void Circle(Vector3 position, float radius, Camera camera, Color? color = null, bool dashed = false, int pointsCount = 16)
{
float offset = 0f;
Quaternion rotation = Quaternion.LookRotation(position - camera.transform.position);
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, rotation);
}
/// <summary>
/// Draws a circle in world space and billboards towards the camera.
/// </summary>
public static void Circle(Vector3 position, float radius, Camera camera, Color? color = null, bool dashed = false, int pointsCount = 16)
{
float offset = 0f;
Quaternion rotation = Quaternion.LookRotation(position - camera.transform.position);
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, rotation);
}
/// <summary>
/// Draws a circle in world space with a specified rotation.
/// </summary>
public static void Circle(Vector3 position, float radius, Quaternion rotation, Color? color = null, bool dashed = false, int pointsCount = 16)
{
float offset = 0f;
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, rotation);
}
}
/// <summary>
/// Draws a circle in world space with a specified rotation.
/// </summary>
public static void Circle(Vector3 position, float radius, Quaternion rotation, Color? color = null, bool dashed = false, int pointsCount = 16)
{
float offset = 0f;
Draw<PolygonDrawer>(color, dashed, position, pointsCount, radius, offset, rotation);
}
}
}

View File

@ -1,9 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
#if UNITY_EDITOR
using UnityEditor;
@ -11,118 +9,117 @@ using UnityEditor.SceneManagement;
#endif
#if !UNITY_2019_1_OR_NEWER
using System;
public struct ScriptableRenderContext {}
public struct ScriptableRenderContext { }
public static class RenderPipelineManager
{
public static event Action<ScriptableRenderContext, Camera> endCameraRendering;
public static event Action<ScriptableRenderContext, Camera> endCameraRendering;
}
#endif
namespace Popcron
{
[ExecuteInEditMode]
[AddComponentMenu("")]
public class GizmosInstance : MonoBehaviour
{
private const int DefaultQueueSize = 4096;
[ExecuteInEditMode]
[AddComponentMenu("")]
public class GizmosInstance : MonoBehaviour
{
private const int DefaultQueueSize = 4096;
private static GizmosInstance instance;
private static bool hotReloaded = true;
private static Material defaultMaterial;
private static Plane[] cameraPlanes = new Plane[6];
private static GizmosInstance instance;
private static bool hotReloaded = true;
private static Material defaultMaterial;
private static Plane[] cameraPlanes = new Plane[6];
private Material overrideMaterial;
private int queueIndex = 0;
private int lastFrame;
private Element[] queue = new Element[DefaultQueueSize];
private Material overrideMaterial;
private int queueIndex = 0;
private int lastFrame;
private Element[] queue = new Element[DefaultQueueSize];
/// <summary>
/// The material being used to render
/// </summary>
public static Material Material
{
get
{
GizmosInstance inst = GetOrCreate();
if (inst.overrideMaterial)
{
return inst.overrideMaterial;
}
/// <summary>
/// The material being used to render
/// </summary>
public static Material Material
{
get
{
GizmosInstance inst = GetOrCreate();
if (inst.overrideMaterial)
{
return inst.overrideMaterial;
}
return DefaultMaterial;
}
set
{
GizmosInstance inst = GetOrCreate();
inst.overrideMaterial = value;
}
}
return DefaultMaterial;
}
set
{
GizmosInstance inst = GetOrCreate();
inst.overrideMaterial = value;
}
}
/// <summary>
/// The default line renderer material
/// </summary>
public static Material DefaultMaterial
{
get
{
if (!defaultMaterial)
{
// Unity has a built-in shader that is useful for drawing
// simple colored things.
Shader shader = Shader.Find("Hidden/Internal-Colored");
defaultMaterial = new Material(shader)
{
hideFlags = HideFlags.HideAndDontSave
};
/// <summary>
/// The default line renderer material
/// </summary>
public static Material DefaultMaterial
{
get
{
if (!defaultMaterial)
{
// Unity has a built-in shader that is useful for drawing
// simple colored things.
Shader shader = Shader.Find("Hidden/Internal-Colored");
defaultMaterial = new Material(shader)
{
hideFlags = HideFlags.HideAndDontSave
};
// Turn on alpha blending
defaultMaterial.SetInt("_SrcBlend", (int)BlendMode.SrcAlpha);
defaultMaterial.SetInt("_DstBlend", (int)BlendMode.OneMinusSrcAlpha);
defaultMaterial.SetInt("_Cull", (int)CullMode.Off);
defaultMaterial.SetInt("_ZWrite", 0);
}
// Turn on alpha blending
defaultMaterial.SetInt("_SrcBlend", (int)BlendMode.SrcAlpha);
defaultMaterial.SetInt("_DstBlend", (int)BlendMode.OneMinusSrcAlpha);
defaultMaterial.SetInt("_Cull", (int)CullMode.Off);
defaultMaterial.SetInt("_ZWrite", 0);
}
return defaultMaterial;
}
}
return defaultMaterial;
}
}
internal static GizmosInstance GetOrCreate()
{
if (hotReloaded || !instance)
{
bool markDirty = false;
GizmosInstance[] gizmosInstances = FindObjectsOfType<GizmosInstance>();
for (int i = 0; i < gizmosInstances.Length; i++)
{
instance = gizmosInstances[i];
internal static GizmosInstance GetOrCreate()
{
if (hotReloaded || !instance)
{
bool markDirty = false;
GizmosInstance[] gizmosInstances = FindObjectsOfType<GizmosInstance>();
for (int i = 0; i < gizmosInstances.Length; i++)
{
instance = gizmosInstances[i];
//destroy any extra gizmo instances
if (i > 0)
{
if (Application.isPlaying)
{
Destroy(gizmosInstances[i]);
}
else
{
DestroyImmediate(gizmosInstances[i]);
markDirty = true;
}
}
}
//destroy any extra gizmo instances
if (i > 0)
{
if (Application.isPlaying)
{
Destroy(gizmosInstances[i]);
}
else
{
DestroyImmediate(gizmosInstances[i]);
markDirty = true;
}
}
}
//none were found, create a new one
if (!instance)
{
instance = new GameObject(typeof(GizmosInstance).FullName).AddComponent<GizmosInstance>();
instance.gameObject.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
//none were found, create a new one
if (!instance)
{
instance = new GameObject(typeof(GizmosInstance).FullName).AddComponent<GizmosInstance>();
instance.gameObject.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
markDirty = true;
}
markDirty = true;
}
#if UNITY_EDITOR
//mark scene as dirty
@ -133,108 +130,108 @@ namespace Popcron
}
#endif
hotReloaded = false;
}
hotReloaded = false;
}
return instance;
}
return instance;
}
private float CurrentTime
{
get
{
float time = 0f;
if (Application.isPlaying)
{
time = Time.time;
}
else
{
private float CurrentTime
{
get
{
float time = 0f;
if (Application.isPlaying)
{
time = Time.time;
}
else
{
#if UNITY_EDITOR
time = (float)EditorApplication.timeSinceStartup;
#endif
}
}
return time;
}
}
return time;
}
}
/// <summary>
/// Submits an array of points to draw into the queue.
/// </summary>
internal static void Submit(Vector3[] points, Color? color, bool dashed)
{
GizmosInstance inst = GetOrCreate();
/// <summary>
/// Submits an array of points to draw into the queue.
/// </summary>
internal static void Submit(Vector3[] points, Color? color, bool dashed)
{
GizmosInstance inst = GetOrCreate();
//if new frame, reset index
if (inst.lastFrame != Time.frameCount)
{
inst.lastFrame = Time.frameCount;
inst.queueIndex = 0;
}
//if new frame, reset index
if (inst.lastFrame != Time.frameCount)
{
inst.lastFrame = Time.frameCount;
inst.queueIndex = 0;
}
//excedeed the length, so make it even bigger
if (inst.queueIndex >= inst.queue.Length)
{
Element[] bigger = new Element[inst.queue.Length + DefaultQueueSize];
for (int i = inst.queue.Length; i < bigger.Length; i++)
{
bigger[i] = new Element();
}
//excedeed the length, so make it even bigger
if (inst.queueIndex >= inst.queue.Length)
{
Element[] bigger = new Element[inst.queue.Length + DefaultQueueSize];
for (int i = inst.queue.Length; i < bigger.Length; i++)
{
bigger[i] = new Element();
}
Array.Copy(inst.queue, 0, bigger, 0, inst.queue.Length);
inst.queue = bigger;
}
Array.Copy(inst.queue, 0, bigger, 0, inst.queue.Length);
inst.queue = bigger;
}
inst.queue[inst.queueIndex].color = color ?? Color.white;
inst.queue[inst.queueIndex].points = points;
inst.queue[inst.queueIndex].dashed = dashed;
inst.queue[inst.queueIndex].color = color ?? Color.white;
inst.queue[inst.queueIndex].points = points;
inst.queue[inst.queueIndex].dashed = dashed;
inst.queueIndex++;
}
inst.queueIndex++;
}
private void OnEnable()
{
//populate queue with empty elements
queue = new Element[DefaultQueueSize];
for (int i = 0; i < DefaultQueueSize; i++)
{
queue[i] = new Element();
}
private void OnEnable()
{
//populate queue with empty elements
queue = new Element[DefaultQueueSize];
for (int i = 0; i < DefaultQueueSize; i++)
{
queue[i] = new Element();
}
if (GraphicsSettings.renderPipelineAsset == null)
{
Camera.onPostRender += OnRendered;
}
else
{
RenderPipelineManager.endCameraRendering += OnRendered;
}
}
if (GraphicsSettings.renderPipelineAsset == null)
{
Camera.onPostRender += OnRendered;
}
else
{
RenderPipelineManager.endCameraRendering += OnRendered;
}
}
private void OnDisable()
{
if (GraphicsSettings.renderPipelineAsset == null)
{
Camera.onPostRender -= OnRendered;
}
else
{
RenderPipelineManager.endCameraRendering -= OnRendered;
}
}
private void OnDisable()
{
if (GraphicsSettings.renderPipelineAsset == null)
{
Camera.onPostRender -= OnRendered;
}
else
{
RenderPipelineManager.endCameraRendering -= OnRendered;
}
}
private void OnRendered(ScriptableRenderContext context, Camera camera) => OnRendered(camera);
private void OnRendered(ScriptableRenderContext context, Camera camera) => OnRendered(camera);
private bool ShouldRenderCamera(Camera camera)
{
if (!camera)
{
return false;
}
private bool ShouldRenderCamera(Camera camera)
{
if (!camera)
{
return false;
}
//allow the scene and main camera always
bool isSceneCamera = false;
//allow the scene and main camera always
bool isSceneCamera = false;
#if UNITY_EDITOR
SceneView sceneView = SceneView.currentDrawingSceneView;
if (sceneView == null)
@ -247,149 +244,149 @@ namespace Popcron
isSceneCamera = true;
}
#endif
if (isSceneCamera || camera.CompareTag("MainCamera"))
{
return true;
}
if (isSceneCamera || camera.CompareTag("MainCamera"))
{
return true;
}
//it passed through the filter
if (Gizmos.CameraFilter?.Invoke(camera) == true)
{
return true;
}
//it passed through the filter
if (Gizmos.CameraFilter?.Invoke(camera) == true)
{
return true;
}
return false;
}
return false;
}
private bool IsVisibleByCamera(Element points, Camera camera)
{
if (!camera)
{
return false;
}
private bool IsVisibleByCamera(Element points, Camera camera)
{
if (!camera)
{
return false;
}
//essentially check if at least 1 point is visible by the camera
for (int i = 0; i < points.points.Length; i++)
{
Vector3 vp = camera.WorldToViewportPoint(points.points[i]);
if (vp.x >= 0 && vp.x <= 1 && vp.y >= 0 && vp.y <= 1)
{
return true;
}
}
//essentially check if at least 1 point is visible by the camera
for (int i = 0; i < points.points.Length; i++)
{
Vector3 vp = camera.WorldToViewportPoint(points.points[i]);
if (vp.x >= 0 && vp.x <= 1 && vp.y >= 0 && vp.y <= 1)
{
return true;
}
}
return false;
}
return false;
}
private void Update()
{
//always render something
Gizmos.Line(default, default);
}
private void OnRendered(Camera camera)
{
Material.SetPass(Gizmos.Pass);
//shouldnt be rendering
if (!Gizmos.Enabled)
{
queueIndex = 0;
}
private void OnRendered(Camera camera)
{
Material.SetPass(Gizmos.Pass);
//check if this camera is ok to render with
if (!ShouldRenderCamera(camera))
{
//shouldnt be rendering
if (!Gizmos.Enabled)
{
queueIndex = 0;
}
//check if this camera is ok to render with
if (!ShouldRenderCamera(camera))
{
GL.PushMatrix();
GL.Begin(GL.LINES);
//bla bla bla
GL.End();
GL.PopMatrix();
return;
}
return;
}
Vector3 offset = Gizmos.Offset;
Vector3 offset = Gizmos.Offset;
GL.PushMatrix();
GL.MultMatrix(Matrix4x4.identity);
GL.Begin(GL.LINES);
GL.PushMatrix();
GL.MultMatrix(Matrix4x4.identity);
GL.Begin(GL.LINES);
bool alt = CurrentTime % 1 > 0.5f;
float dashGap = Mathf.Clamp(Gizmos.DashGap, 0.01f, 32f);
bool frustumCull = Gizmos.FrustumCulling;
List<Vector3> points = new List<Vector3>();
bool alt = CurrentTime % 1 > 0.5f;
float dashGap = Mathf.Clamp(Gizmos.DashGap, 0.01f, 32f);
bool frustumCull = Gizmos.FrustumCulling;
List<Vector3> points = new List<Vector3>();
//draw le elements
for (int e = 0; e < queueIndex; e++)
{
//just in case
if (queue.Length <= e)
{
break;
}
//draw le elements
for (int e = 0; e < queueIndex; e++)
{
//just in case
if (queue.Length <= e)
{
break;
}
Element element = queue[e];
Element element = queue[e];
//dont render this thingy if its not inside the frustum
if (frustumCull)
{
if (!IsVisibleByCamera(element, camera))
{
continue;
}
}
//dont render this thingy if its not inside the frustum
if (frustumCull)
{
if (!IsVisibleByCamera(element, camera))
{
continue;
}
}
points.Clear();
if (element.dashed)
{
//subdivide
for (int i = 0; i < element.points.Length - 1; i++)
{
Vector3 pointA = element.points[i];
Vector3 pointB = element.points[i + 1];
Vector3 direction = pointB - pointA;
if (direction.sqrMagnitude > dashGap * dashGap * 2f)
{
float magnitude = direction.magnitude;
int amount = Mathf.RoundToInt(magnitude / dashGap);
direction /= magnitude;
points.Clear();
if (element.dashed)
{
//subdivide
for (int i = 0; i < element.points.Length - 1; i++)
{
Vector3 pointA = element.points[i];
Vector3 pointB = element.points[i + 1];
Vector3 direction = pointB - pointA;
if (direction.sqrMagnitude > dashGap * dashGap * 2f)
{
float magnitude = direction.magnitude;
int amount = Mathf.RoundToInt(magnitude / dashGap);
direction /= magnitude;
for (int p = 0; p < amount - 1; p++)
{
if (p % 2 == (alt ? 1 : 0))
{
float startLerp = p / (amount - 1f);
float endLerp = (p + 1) / (amount - 1f);
Vector3 start = Vector3.Lerp(pointA, pointB, startLerp);
Vector3 end = Vector3.Lerp(pointA, pointB, endLerp);
points.Add(start);
points.Add(end);
}
}
}
else
{
points.Add(pointA);
points.Add(pointB);
}
}
}
else
{
points.AddRange(element.points);
}
for (int p = 0; p < amount - 1; p++)
{
if (p % 2 == (alt ? 1 : 0))
{
float startLerp = p / (amount - 1f);
float endLerp = (p + 1) / (amount - 1f);
Vector3 start = Vector3.Lerp(pointA, pointB, startLerp);
Vector3 end = Vector3.Lerp(pointA, pointB, endLerp);
points.Add(start);
points.Add(end);
}
}
}
else
{
points.Add(pointA);
points.Add(pointB);
}
}
}
else
{
points.AddRange(element.points);
}
GL.Color(element.color);
for (int i = 0; i < points.Count; i++)
{
GL.Vertex(points[i] + offset);
}
}
GL.Color(element.color);
for (int i = 0; i < points.Count; i++)
{
GL.Vertex(points[i] + offset);
}
}
GL.End();
GL.PopMatrix();
}
}
GL.End();
GL.PopMatrix();
}
}
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<GameDir>D:\EpicGames\OuterWilds</GameDir>
<GameDir>E:\Epic\Epic Games\OuterWilds</GameDir>
<OwmlDir>C:\Users\Henry\AppData\Roaming\OuterWildsModManager\OWML</OwmlDir>
<ProjectView>ShowAllFiles</ProjectView>
</PropertyGroup>