using UnityEngine; using System.Collections.Generic; public static partial class D2D_Helper { public static int MeshVertexLimit = 65000; public static void GetPixelsBilinear(Texture2D t, int x, int y) { } public static void Swap(ref T a, ref T b) { var c = b; b = a; a = c; } public static float Atan2(Vector2 xy) { return Mathf.Atan2(xy.x, xy.y); } public static void ResizeArrayTo(List array, int size, System.Func newT, System.Action removeT) { if (array != null) { while (array.Count < size) { array.Add(newT != null ? newT(array.Count) : default(T)); } while (array.Count > size) { if (removeT != null) { removeT(array[array.Count - 1]); } array.RemoveAt(array.Count - 1); } } } private static HideFlags oldHideFlags; public static void BeginStealthSet(Object o) { if (o != null) { oldHideFlags = o.hideFlags; o.hideFlags = HideFlags.DontSave; } } public static void EndStealthSet(Object o) { if (o != null) { o.hideFlags = oldHideFlags; } } public static void StealthSet(MeshFilter mf, Mesh m) { if (mf != null && mf.sharedMesh != m) { #if UNITY_EDITOR var hf = mf.hideFlags; mf.hideFlags = HideFlags.DontSave; mf.sharedMesh = m; mf.hideFlags = hf; #else mf.sharedMesh = m; #endif } } public static void StealthSet(MeshRenderer mr, Material m) { if (mr != null && mr.sharedMaterial != m) { #if UNITY_EDITOR var hf = mr.hideFlags; mr.hideFlags = HideFlags.DontSave; mr.sharedMaterial = m; mr.hideFlags = hf; #else mr.sharedMaterial = m; #endif } } public static void SetPosition(Transform t, Vector3 v) { if (t != null) { #if UNITY_EDITOR if (Application.isPlaying == false && t.position == v) return; #endif t.position = v; } } public static void Destroy(Object o) { #if UNITY_EDITOR if (Application.isPlaying == false) { Object.DestroyImmediate(o, true); return; } #endif Object.Destroy(o); } public static void DestroyManaged(System.Action DestroyAction) { if (DestroyAction != null) { #if UNITY_EDITOR var isPlaying = Application.isPlaying; UnityEditor.EditorApplication.delayCall += () => { if (Application.isPlaying == isPlaying) { DestroyAction(); } }; #else DestroyAction(); #endif } } public static void SetParent(Transform t, Transform newParent, bool keepLocalTransform = true) { if (t != null && t.parent != newParent) { if (keepLocalTransform == true) { var oldLocalPosition = t.localPosition; var oldLocalRotation = t.localRotation; var oldLocalScale = t.localScale; t.parent = newParent; t.localPosition = oldLocalPosition; t.localRotation = oldLocalRotation; t.localScale = oldLocalScale; } else { t.parent = newParent; } } } public static void SetLocalPosition(Transform t, float x, float y, float z) { SetLocalPosition(t, new Vector3(x, y, z)); } public static void SetLocalPosition(Transform t, Vector3 v) { if (t != null) { #if UNITY_EDITOR if (Application.isPlaying == false && t.localPosition == v) return; #endif t.localPosition = v; } } public static void SetLocalScale(Transform t, float v) { SetLocalScale(t, new Vector3(v, v, v)); } public static void SetLocalScale(Transform t, Vector3 v) { if (t != null) { #if UNITY_EDITOR if (Application.isPlaying == false && t.localScale == v) return; #endif if (t.localScale == v) return; t.localScale = v; } } public static T GetComponentUpwards(Transform transform, bool skipFirst = false) where T : Component { if (transform != null) { if (skipFirst == true) { transform = transform.parent; } while (transform != null) { var component = transform.GetComponent(); if (component != null) return component; transform = transform.parent; } } return null; } public static T GetOrAddComponent(GameObject gameObject) where T : Component { if (gameObject != null) { var component = gameObject.GetComponent(); if (component == null) component = gameObject.AddComponent(); return component; } return null; } public static GameObject CloneGameObject(GameObject source, Transform parent, bool keepName = false) { if (source != null) { var clone = (GameObject)GameObject.Instantiate(source); if (clone == null) throw new System.NullReferenceException(); if (parent != null) SetParent(clone.transform, parent, true); if (keepName == true) clone.name = source.name; return clone; } return source; } public static GameObject CloneGameObject(GameObject source, Transform parent, Vector3 xyz, Quaternion rot, bool keepName = false) { if (source != null) { var clone = (GameObject)GameObject.Instantiate(source, xyz, rot); if (clone == null) throw new System.NullReferenceException(); if (parent != null) SetParent(clone.transform, parent, true); if (keepName == true) clone.name = source.name; return clone; } return source; } public static GameObject CreateGameObject(string name = "", Transform parent = null) { return CreateGameObject(name, parent, Vector3.zero, Quaternion.identity, Vector3.one); } public static GameObject CreateGameObject(string name, Transform parent, Vector3 position, Quaternion identity, Vector3 scale) { var gameObject = new GameObject(name); gameObject.transform.parent = parent; gameObject.transform.localPosition = Vector3.zero; gameObject.transform.localRotation = Quaternion.identity; gameObject.transform.localScale = Vector3.one; return gameObject; } public static T Clone(T o, bool keepName = true) where T : Object { if (o != null) { var c = (T)Object.Instantiate(o); if (c != null && keepName == true) c.name = o.name; return c; } return null; } public static bool Enabled(Behaviour b) { return b != null && b.enabled == true && b.gameObject.activeInHierarchy == true; } public static float Divide(float a, float b) { return Zero(b) == false ? a / b : 0.0f; } public static Vector2 Divide(float xA, float yA, float xB, float yB) { return new Vector2(Divide(xA, xB), Divide(yA, yB)); } public static float Reciprocal(float v) { return Zero(v) == false ? 1.0f / v : 0.0f; } public static Vector2 Reciprocal(Vector2 v) { return new Vector2(Reciprocal(v.x), Reciprocal(v.y)); } public static Vector2 Reciprocal(float x, float y) { return new Vector2(Reciprocal(x), Reciprocal(y)); } public static Vector3 Reciprocal(Vector3 v) { return new Vector3(Reciprocal(v.x), Reciprocal(v.y), Reciprocal(v.z)); } public static Vector3 Reciprocal(float x, float y, float z) { return new Vector3(Reciprocal(x), Reciprocal(y), Reciprocal(z)); } public static bool Zero(float v) { return Mathf.Approximately(v, 0.0f); } public static Matrix4x4 RotationMatrix(Quaternion q) { var matrix = Matrix4x4.TRS(Vector3.zero, q, Vector3.one); return matrix; } public static Matrix4x4 TranslationMatrix(Vector3 xyz) { return TranslationMatrix(xyz.x, xyz.y, xyz.z); } public static Matrix4x4 TranslationMatrix(float x, float y, float z) { var matrix = Matrix4x4.identity; matrix.m03 = x; matrix.m13 = y; matrix.m23 = z; return matrix; } public static Matrix4x4 ScalingMatrix(float xyz) { return ScalingMatrix(xyz, xyz, xyz); } public static Matrix4x4 ScalingMatrix(Vector3 xyz) { return ScalingMatrix(xyz.x, xyz.y, xyz.z); } public static Matrix4x4 ScalingMatrix(float x, float y, float z) { var matrix = Matrix4x4.identity; matrix.m00 = x; matrix.m11 = y; matrix.m22 = z; return matrix; } public static float DampenFactor(float dampening, float elapsed) { return 1.0f - Mathf.Pow((float)System.Math.E, - dampening * elapsed); } public static Quaternion Dampen(Quaternion current, Quaternion target, float dampening, float elapsed, float minStep = 0.0f) { var factor = DampenFactor(dampening, elapsed); var maxDelta = Quaternion.Angle(current, target) * factor + minStep * elapsed; return MoveTowards(current, target, maxDelta); } public static float Dampen(float current, float target, float dampening, float elapsed, float minStep = 0.0f) { var factor = DampenFactor(dampening, elapsed); var maxDelta = Mathf.Abs(target - current) * factor + minStep * elapsed; return MoveTowards(current, target, maxDelta); } public static Vector3 Dampen3(Vector3 current, Vector3 target, float dampening, float elapsed, float minStep = 0.0f) { var factor = DampenFactor(dampening, elapsed); var maxDelta = Mathf.Abs((target - current).magnitude) * factor + minStep * elapsed; return Vector3.MoveTowards(current, target, maxDelta); } public static Quaternion MoveTowards(Quaternion current, Quaternion target, float maxDelta) { var delta = Quaternion.Angle(current, target); return Quaternion.Slerp(current, target, Divide(maxDelta, delta)); } public static float MoveTowards(float current, float target, float maxDelta) { if (target > current) { current = System.Math.Min(target, current + maxDelta); } else { current = System.Math.Max(target, current - maxDelta); } return current; } public static Vector3 ClosestPointToLineSegment(Vector3 a, Vector3 b, Vector3 point) { var l = (b - a).magnitude; var d = (b - a).normalized; return a + Mathf.Clamp(Vector3.Dot(point - a, d), 0.0f, l) * d; } public static Vector3 ClosestPointToTriangle(Vector3 a, Vector3 b, Vector3 c, Vector3 p) { var r = Quaternion.Inverse(Quaternion.LookRotation(-Vector3.Cross(a - b, a - c))); var ra = r * a; var rb = r * b; var rc = r * c; var rp = r * p; var a2 = D2D_Helper.VectorXY(ra); var b2 = D2D_Helper.VectorXY(rb); var c2 = D2D_Helper.VectorXY(rc); var p2 = D2D_Helper.VectorXY(rp); if (PointLeftOfLine(a2, b2, p2) == true) { return ClosestPointToLineSegment(a, b, p); } if (PointLeftOfLine(b2, c2, p2) == true) { return ClosestPointToLineSegment(b, c, p); } if (PointLeftOfLine(c2, a2, p2) == true) { return ClosestPointToLineSegment(c, a, p); } var barycentric = GetBarycentric(a2, b2, c2, p2); return barycentric.x * a + barycentric.y * b + barycentric.z * c; } public static Vector3 GetBarycentric(Vector2 a, Vector2 b, Vector2 c, Vector2 p) { var barycentric = Vector3.zero; var v0 = b - a; var v1 = c - a; var v2 = p - a; var d00 = Vector2.Dot(v0, v0); var d01 = Vector2.Dot(v0, v1); var d11 = Vector2.Dot(v1, v1); var d20 = Vector2.Dot(v2, v0); var d21 = Vector2.Dot(v2, v1); var denom = D2D_Helper.Reciprocal(d00 * d11 - d01 * d01); barycentric.y = (d11 * d20 - d01 * d21) * denom; barycentric.z = (d00 * d21 - d01 * d20) * denom; barycentric.x = 1.0f - barycentric.y - barycentric.z; return barycentric; } public static bool PointLeftOfLine(Vector2 a, Vector2 b, Vector2 p) // NOTE: CCW { return ((b.x - a.x) * (p.y - a.y) - (p.x - a.x) * (b.y - a.y)) >= 0.0f; } public static bool PointRightOfLine(Vector2 a, Vector2 b, Vector2 p) // NOTE: CCW { return ((b.x - a.x) * (p.y - a.y) - (p.x - a.x) * (b.y - a.y)) <= 0.0f; } public static Vector2 VectorXY(Vector3 xyz) { return new Vector2(xyz.x, xyz.y); } }