using UnityEngine; using System.Linq; using System.Collections.Generic; using System.Text.RegularExpressions; namespace UnityEngine.Polybrush { /// /// General static helper functions. /// internal static class Util { /// /// Returns a new array initialized with the @count and @value. /// internal static T[] Fill(T value, int count) { //return an empty list if the count is negative if(count < 0) { return null; } T[] arr = new T[count]; for(int i = 0; i < count; i++) arr[i] = value; return arr; } /// /// Returns a new array initialized with the @count and @value. /// internal static T[] Fill(System.Func constructor, int count) { //return an empty list if the count is negative if (count < 0) { return null; } T[] arr = new T[count]; for(int i = 0; i < count; i++) arr[i] = constructor(i); return arr; } /// /// Make a copy of an array /// /// type of the array /// array to be copied /// the new array of type T internal static T[] Duplicate(T[] array) { //null checks if(array == null) { return null; } T[] dup = new T[array.Length]; System.Array.Copy(array, 0, dup, 0, array.Length); return dup; } internal static string ToString(this IEnumerable enumerable, string delim) { if(enumerable == null) return ""; return string.Join(delim ?? "", enumerable.Select(x => x != null ? x.ToString() : "").ToArray()); } /// /// Clamp an animation curve's first and last keys. /// /// /// /// /// /// /// public static AnimationCurve ClampAnimationKeys(AnimationCurve curve, float firstKeyTime, float firstKeyValue, float secondKeyTime, float secondKeyValue) { Keyframe[] keys = curve.keys; int len = curve.length - 1; keys[0].time = firstKeyTime; keys[0].value = firstKeyValue; keys[len].time = secondKeyTime; keys[len].value = secondKeyValue; curve.keys = keys; return new AnimationCurve(keys); } /// /// Create a dictionnary with keys created from T values (from sublists items) and the value equal to the index of the top list /// Note that the function must receive unique values on sublists /// /// /// /// internal static Dictionary GetCommonLookup(this List> lists) { Dictionary lookup = new Dictionary(); int index = 0; foreach(var kvp in lists) { if (kvp == null) continue; foreach(var val in kvp) { if(lookup.ContainsKey(val)) { Debug.LogWarning("Error, duplicated values as keys"); return null; } lookup.Add(val, index); } index++; } return lookup; } /// /// Create a dictionnary with keys created from T values (from sublists items) and the value equal to the index of the top list /// Note that the function must receive unique values on sublists /// /// /// /// internal static Dictionary GetCommonLookup(this T[][] lists) { Dictionary lookup = new Dictionary(); int index = 0; foreach (var kvp in lists) { if (kvp == null) continue; foreach (var val in kvp) { if (lookup.ContainsKey(val)) { Debug.LogWarning("Error, duplicated values as keys"); return null; } lookup.Add(val, index); } index++; } return lookup; } /// /// Lerp between 2 colors using RGB. /// /// /// /// /// /// internal static Color32 Lerp(Color32 lhs, Color32 rhs, ColorMask mask, float alpha) { return new Color32( mask.r ? (byte)(lhs.r * (1f-alpha) + rhs.r * alpha) : lhs.r, mask.g ? (byte)(lhs.g * (1f-alpha) + rhs.g * alpha) : lhs.g, mask.b ? (byte)(lhs.b * (1f-alpha) + rhs.b * alpha) : lhs.b, mask.a ? (byte)(lhs.a * (1f-alpha) + rhs.a * alpha) : lhs.a ); } /// /// Lerp between 2 colors using RGB. /// /// /// /// /// internal static Color32 Lerp(Color32 lhs, Color32 rhs, float alpha) { return new Color32( (byte)(lhs.r * (1f-alpha) + rhs.r * alpha), (byte)(lhs.g * (1f-alpha) + rhs.g * alpha), (byte)(lhs.b * (1f-alpha) + rhs.b * alpha), (byte)(lhs.a * (1f-alpha) + rhs.a * alpha) ); } /// /// True if object is non-null and valid. /// /// /// /// internal static bool IsValid(this T target) where T : IValid { return target != null && target.IsValid; } /// /// Returns a new name with incremented prefix. /// /// /// /// internal static string IncrementPrefix(string prefix, string name) { string str = name; Regex regex = new Regex("^(" + prefix + "[0-9]*_)"); Match match = regex.Match(name); if( match.Success ) { string iteration = match.Value.Replace(prefix, "").Replace("_", ""); int val = 0; if (int.TryParse(iteration, out val)) { str = name.Replace(match.Value, prefix + (val + 1) + "_"); } else { str = prefix + "0_" + name; } } else { str = prefix + "0_" + name; } return str; } /// /// Checks a GameObject for SkinnedMeshRenderer & MeshRenderer components /// and returns all materials associated with either. /// /// /// internal static List GetMaterials(this GameObject gameObject) { //null checks if(gameObject == null) { return null; } List mats = new List(); foreach(Renderer ren in gameObject.GetComponents()) mats.AddRange(ren.sharedMaterials); return mats; } /// /// Will return the mesh if found /// /// the gameobject that contains the mesh /// the mesh found if any internal static Mesh GetMesh(this GameObject go) { //null checks if (go == null) { return null; } var mf = go.GetComponent(); var smr = go.GetComponent(); var polyMesh = go.GetComponent(); var mr = go.GetComponent(); //priority order: advs component > vertexstream mesh renderer > mesh filter > skin mesh renderer //even if normally having an additionalVertexStreams means that the component advs is on the object, double check it if (polyMesh != null && polyMesh.storedMesh!= null) { return polyMesh.storedMesh; } else if(mr != null && mr.additionalVertexStreams != null) { return mr.additionalVertexStreams; } else if (mf != null && mf.sharedMesh != null) { return mf.sharedMesh; } else if (smr != null && smr.sharedMesh != null) { return smr.sharedMesh; } else { return null; } } } }