using System; using System.Collections.Generic; using UnityEngine; namespace Leap.Unity.RuntimeGizmos { public class RuntimeGizmoDrawer { public Shader gizmoShader { get { if (this._gizmoMaterial == null) { return null; } return this._gizmoMaterial.shader; } set { if (this._gizmoMaterial == null) { this._gizmoMaterial = new Material(value); this._gizmoMaterial.name = "Runtime Gizmo Material"; this._gizmoMaterial.hideFlags = HideFlags.HideAndDontSave; } else { this._gizmoMaterial.shader = value; } } } public void BeginGuard() { this._operationCountOnGuard = this._operations.Count; } public void EndGuard() { bool flag = this._operations.Count > this._operationCountOnGuard; this._operationCountOnGuard = -1; if (flag) { Debug.LogError("New gizmos were drawn to the front buffer! Make sure to never keep a reference to a Drawer, always get a new one every time you want to start drawing."); } } public void RelativeTo(Transform transform) { this.matrix = transform.localToWorldMatrix; } public void PushMatrix() { this._matrixStack.Push(this._currMatrix); } public void PopMatrix() { this.matrix = this._matrixStack.Pop(); } public void ResetMatrixAndColorState() { this.matrix = Matrix4x4.identity; this.color = Color.white; } public Color color { get { return this._currColor; } set { if (this._currColor == value) { return; } this._currColor = value; this._operations.Add(RuntimeGizmoDrawer.OperationType.SetColor); this._colors.Add(this._currColor); } } public Matrix4x4 matrix { get { return this._currMatrix; } set { if (this._currMatrix == value) { return; } this._currMatrix = value; this._operations.Add(RuntimeGizmoDrawer.OperationType.SetMatrix); this._matrices.Add(this._currMatrix); } } public void DrawMesh(Mesh mesh, Matrix4x4 matrix) { this.setWireMode(false); this.drawMeshInternal(mesh, matrix); } public void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Vector3 scale) { this.DrawMesh(mesh, Matrix4x4.TRS(position, rotation, scale)); } public void DrawWireMesh(Mesh mesh, Matrix4x4 matrix) { this.setWireMode(true); this.drawMeshInternal(mesh, matrix); } public void DrawWireMesh(Mesh mesh, Vector3 position, Quaternion rotation, Vector3 scale) { this.DrawWireMesh(mesh, Matrix4x4.TRS(position, rotation, scale)); } public void DrawLine(Vector3 a, Vector3 b) { this._operations.Add(RuntimeGizmoDrawer.OperationType.DrawLine); this._lines.Add(new RuntimeGizmoDrawer.Line(a, b)); } public void DrawCube(Vector3 position, Vector3 size) { this.DrawMesh(this.cubeMesh, position, Quaternion.identity, size); } public void DrawWireCube(Vector3 position, Vector3 size) { this.DrawWireMesh(this.wireCubeMesh, position, Quaternion.identity, size); } public void DrawSphere(Vector3 center, float radius) { this.DrawMesh(this.sphereMesh, center, Quaternion.identity, Vector3.one * radius * 2f); } public void DrawWireSphere(Vector3 center, float radius) { this.DrawWireMesh(this.wireSphereMesh, center, Quaternion.identity, Vector3.one * radius * 2f); } public void DrawWireCirlce(Vector3 center, Vector3 direction, float radius) { this.PushMatrix(); this.matrix = Matrix4x4.TRS(center, Quaternion.LookRotation(direction), new Vector3(1f, 1f, 0f)) * this.matrix; this.DrawWireSphere(Vector3.zero, radius); this.PopMatrix(); } public void DrawColliders(GameObject gameObject, bool useWireframe = true, bool traverseHierarchy = true) { this.PushMatrix(); if (traverseHierarchy) { gameObject.GetComponentsInChildren(this._colliderList); } else { gameObject.GetComponents(this._colliderList); } for (int i = 0; i < this._colliderList.Count; i++) { Collider collider = this._colliderList[i]; this.RelativeTo(collider.transform); if (collider is BoxCollider) { BoxCollider boxCollider = collider as BoxCollider; if (useWireframe) { this.DrawWireCube(boxCollider.center, boxCollider.size); } else { this.DrawCube(boxCollider.center, boxCollider.size); } } else if (collider is SphereCollider) { SphereCollider sphereCollider = collider as SphereCollider; if (useWireframe) { this.DrawWireSphere(sphereCollider.center, sphereCollider.radius); } else { this.DrawSphere(sphereCollider.center, sphereCollider.radius); } } else if (collider is CapsuleCollider) { CapsuleCollider capsuleCollider = collider as CapsuleCollider; Vector3 vector = Vector3.zero; vector += Vector3.one * capsuleCollider.radius * 2f; vector += new Vector3((float)((capsuleCollider.direction != 0) ? 0 : 1), (float)((capsuleCollider.direction != 1) ? 0 : 1), (float)((capsuleCollider.direction != 2) ? 0 : 1)) * (capsuleCollider.height - capsuleCollider.radius * 2f); if (useWireframe) { this.DrawWireCube(capsuleCollider.center, vector); } else { this.DrawCube(capsuleCollider.center, vector); } } else if (collider is MeshCollider) { MeshCollider meshCollider = collider as MeshCollider; if (meshCollider.sharedMesh != null) { if (useWireframe) { this.DrawWireMesh(meshCollider.sharedMesh, Matrix4x4.identity); } else { this.DrawMesh(meshCollider.sharedMesh, Matrix4x4.identity); } } } } this.PopMatrix(); } public void ClearAllGizmos() { this._operations.Clear(); this._matrices.Clear(); this._colors.Clear(); this._lines.Clear(); this._meshes.Clear(); this._isInWireMode = false; this._currMatrix = Matrix4x4.identity; this._currColor = Color.white; } public void DrawAllGizmosToScreen() { try { int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = -1; this._currMatrix = Matrix4x4.identity; this._currColor = Color.white; GL.wireframe = false; for (int i = 0; i < this._operations.Count; i++) { RuntimeGizmoDrawer.OperationType operationType = this._operations[i]; switch (operationType) { case RuntimeGizmoDrawer.OperationType.SetMatrix: this._currMatrix = this._matrices[num++]; break; case RuntimeGizmoDrawer.OperationType.ToggleWireframe: GL.wireframe = !GL.wireframe; break; case RuntimeGizmoDrawer.OperationType.SetColor: this._currColor = this._colors[num2++]; num5 = -1; break; case RuntimeGizmoDrawer.OperationType.DrawLine: { this.setPass(ref num5, true); GL.Begin(1); RuntimeGizmoDrawer.Line line = this._lines[num3++]; GL.Vertex(this._currMatrix.MultiplyPoint(line.a)); GL.Vertex(this._currMatrix.MultiplyPoint(line.b)); GL.End(); break; } case RuntimeGizmoDrawer.OperationType.DrawMesh: if (GL.wireframe) { this.setPass(ref num5, true); } else { this.setPass(ref num5, false); } Graphics.DrawMeshNow(this._meshes[num4++], this._currMatrix * this._matrices[num++]); break; default: throw new InvalidOperationException("Unexpected operation type " + operationType); } } } finally { GL.wireframe = false; } } private void setPass(ref int currPass, bool isUnlit) { int num; if (isUnlit) { if (this._currColor.a < 1f) { num = 1; } else { num = 0; } } else if (this._currColor.a < 1f) { num = 3; } else { num = 2; } if (currPass != num) { currPass = num; this._gizmoMaterial.color = this._currColor; this._gizmoMaterial.SetPass(currPass); } } private void drawMeshInternal(Mesh mesh, Matrix4x4 matrix) { if (mesh == null) { throw new InvalidOperationException("Mesh cannot be null!"); } this._operations.Add(RuntimeGizmoDrawer.OperationType.DrawMesh); this._meshes.Add(mesh); this._matrices.Add(matrix); } private void setWireMode(bool wireMode) { if (this._isInWireMode != wireMode) { this._operations.Add(RuntimeGizmoDrawer.OperationType.ToggleWireframe); this._isInWireMode = wireMode; } } public const int UNLIT_SOLID_PASS = 0; public const int UNLIT_TRANSPARENT_PASS = 1; public const int SHADED_SOLID_PASS = 2; public const int SHADED_TRANSPARENT_PASS = 3; private List _operations = new List(); private List _matrices = new List(); private List _colors = new List(); private List _lines = new List(); private List _meshes = new List(); private Color _currColor = Color.white; private Matrix4x4 _currMatrix = Matrix4x4.identity; private Stack _matrixStack = new Stack(); private bool _isInWireMode; private Material _gizmoMaterial; private int _operationCountOnGuard = -1; public Mesh cubeMesh; public Mesh wireCubeMesh; public Mesh sphereMesh; public Mesh wireSphereMesh; private List _colliderList = new List(); private enum OperationType { SetMatrix, ToggleWireframe, SetColor, DrawLine, DrawMesh } private struct Line { public Line(Vector3 a, Vector3 b) { this.a = a; this.b = b; } public Vector3 a; public Vector3 b; } } }