using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; namespace Popcron { public class GizmosInstance : MonoBehaviour { private const int DefaultQueueSize = 4096; private static GizmosInstance instance; private static Material defaultMaterial; private Material overrideMaterial; private int queueIndex = 0; private int lastFrame; private Element[] queue = new Element[DefaultQueueSize]; /// /// The material being used to render /// public static Material Material { get { var inst = GetOrCreate(); if (inst.overrideMaterial) { return inst.overrideMaterial; } return DefaultMaterial; } set { var inst = GetOrCreate(); inst.overrideMaterial = value; } } /// /// The default line renderer material /// public static Material DefaultMaterial { get { if (!defaultMaterial) { // Unity has a built-in shader that is useful for drawing // simple colored things. var shader = Shader.Find("UI/Default"); defaultMaterial = new Material(shader) { hideFlags = HideFlags.HideAndDontSave }; // Turn on alpha blending defaultMaterial.SetInt("unity_GUIZTestMode", (int)CompareFunction.Always); } return defaultMaterial; } } internal static GizmosInstance GetOrCreate() { if (!instance) { var gizmosInstances = FindObjectsOfType(); for (var i = 0; i < gizmosInstances.Length; i++) { instance = gizmosInstances[i]; //destroy any extra gizmo instances if (i > 0) { Destroy(gizmosInstances[i]); } } //none were found, create a new one if (!instance) { //instance = new GameObject(typeof(GizmosInstance).FullName).AddComponent(); //instance.gameObject.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector; instance = Locator.GetPlayerCamera().gameObject.AddComponent(); } } return instance; } private float CurrentTime => Time.time; /// /// Submits an array of points to draw into the queue. /// internal static void Submit(Vector3[] points, Color? color) { var inst = GetOrCreate(); //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) { var bigger = new Element[inst.queue.Length + DefaultQueueSize]; for (var 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; } inst.queue[inst.queueIndex].color = color ?? Color.white; inst.queue[inst.queueIndex].points = points; inst.queueIndex++; } private void OnEnable() { //populate queue with empty elements queue = new Element[DefaultQueueSize]; for (var i = 0; i < DefaultQueueSize; i++) { queue[i] = new Element(); } } private void Update() => //always render something Gizmos.Line(default, default); private void OnPostRender() { Material.SetPass(0); var offset = Gizmos.Offset; GL.PushMatrix(); GL.MultMatrix(Matrix4x4.identity); GL.Begin(GL.LINES); var points = new List(); //draw le elements for (var e = 0; e < queueIndex; e++) { //just in case if (queue.Length <= e) { break; } var element = queue[e]; points.Clear(); points.AddRange(element.points); GL.Color(element.color); for (var i = 0; i < points.Count; i++) { GL.Vertex(points[i] + offset); } } GL.End(); GL.PopMatrix(); } } }