#if UNITY_EDITOR using UnityEditor; #endif using UnityEngine; using System; using System.Collections.Generic; /// /// FM: Class which contains many helpful methods for generating files in project mainly for editor use /// public static class FGeneratingUtilities { #region Instantiating Related public static GameObject InstantiateObject(GameObject obj) { #if UNITY_EDITOR GameObject newObj = null; if (Application.isPlaying == false && (PrefabUtility.GetPrefabAssetType(obj) == PrefabAssetType.Regular || PrefabUtility.GetPrefabAssetType(obj) == PrefabAssetType.Variant)) newObj = (GameObject)PrefabUtility.InstantiatePrefab(obj); if (newObj == null) newObj = GameObject.Instantiate(obj); return newObj; #else return GameObject.Instantiate(obj); #endif } public static void DestroyObject(GameObject obj) { if (obj == null) return; #if UNITY_EDITOR if (Application.isPlaying == false) GameObject.DestroyImmediate(obj); else GameObject.Destroy(obj); #else GameObject.Destroy(obj); #endif } #endregion #region Defined Seed Random Handling static Dictionary randoms = new Dictionary(); static System.Random GetR(int randomId) { System.Random r; if (randoms.ContainsKey(randomId) == false) { r = new System.Random(randomId); randoms.Add(randomId, r); } else { r = randoms[randomId]; } return r; } static System.Random random = new System.Random(); public static void SetSeed(int seed) { random = new System.Random(seed); } public static void SetSeed(int seed, int randomId) { if (randoms.ContainsKey(randomId) == false) randoms.Add(randomId, new System.Random(randomId)); else randoms[randomId] = new System.Random(randomId); } public static float GetRandom() { return (float)random.NextDouble(); } public static float GetRandom(int randomId) { return (float)GetR(randomId).NextDouble(); } public static float GetRandom(float from, float to) { return from + (float)random.NextDouble() * (to - from); } public static float GetRandom(float from, float to, int randomId) { return from + (float)GetR(randomId).NextDouble() * (to - from); } public static int GetRandom(int from, int to) { return random.Next(from, to); } public static int GetRandom(int from, int to, int randomId) { return GetR(randomId).Next(from, to); } public static int GetRandom(MinMax minMax) { return (int)(minMax.Min + (float)random.NextDouble() * ((minMax.Max + 1) - minMax.Min)); } public static int GetRandom(MinMax minMax, int randomId) { return (int)(minMax.Min + (float)GetR(randomId).NextDouble() * ((minMax.Max + 1) - minMax.Min)); } #endregion #region GUI or Editor GUI Related #if UNITY_EDITOR public static void DrawGenerateScriptableField(ref T selected, string exampleFilename = "") where T : ScriptableObject { EditorGUILayout.BeginHorizontal(); EditorGUIUtility.labelWidth = 60; selected = (T)EditorGUILayout.ObjectField("Preset:", selected, typeof(T), false); DrawGenerateScriptableButton(ref selected, exampleFilename); EditorGUILayout.EndHorizontal(); } public static void DrawGenerateScriptableButton(ref T selected, string exampleFilename = "") where T : ScriptableObject { if (GUILayout.Button("Create New", GUILayout.Width(94))) selected = (T)GenerateScriptable(GameObject.Instantiate(selected), exampleFilename); } public static void DrawObjectList(List toDraw, GUIStyle style, string title, ref bool foldout, bool moveButtons = false, UnityEngine.Object toDirty = null) where T : UnityEngine.Object { if (toDraw == null) return; EditorGUILayout.BeginVertical(style); EditorGUILayout.BeginHorizontal(); string fold = foldout ? " ▼" : " ►"; if (GUILayout.Button(fold + " " + title + " (" + toDraw.Count + ")", EditorStyles.label, GUILayout.Width(200))) foldout = !foldout; if (foldout) { GUILayout.FlexibleSpace(); if (GUILayout.Button("+")) toDraw.Add(null); } EditorGUILayout.EndHorizontal(); if (foldout) { GUILayout.Space(4); if (toDraw.Count > 0) for (int i = 0; i < toDraw.Count; i++) { EditorGUI.BeginChangeCheck(); EditorGUILayout.BeginHorizontal(); GUIContent lbl = new GUIContent("[" + i + "]"); float wdth = EditorStyles.label.CalcSize(lbl).x; EditorGUILayout.LabelField(lbl, GUILayout.Width(wdth + 2)); toDraw[i] = (T)EditorGUILayout.ObjectField(toDraw[i], typeof(T), false); if (moveButtons) { if (i > 0) if (GUILayout.Button("˄", GUILayout.Width(24))) { T temp = toDraw[i - 1]; toDraw[i - 1] = toDraw[i]; toDraw[i] = temp; } if (i < toDraw.Count - 1) if (GUILayout.Button("˅", GUILayout.Width(24))) { T temp = toDraw[i + 1]; toDraw[i + 1] = toDraw[i]; toDraw[i] = temp; } } if (GUILayout.Button("X", GUILayout.Width(24))) { toDraw.RemoveAt(i); break; } EditorGUILayout.EndHorizontal(); if (toDirty != null) if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(toDirty); } } else { EditorGUILayout.LabelField("No object in list", EditorStyles.centeredGreyMiniLabel); } } EditorGUILayout.EndVertical(); } #endif #endregion #region Helper Class for Minimum and Maximum [System.Serializable] public struct MinMax { public int Min; public int Max; public MinMax(int min, int max) { Min = min; Max = max; } public int GetRandom() { return (int)(Min + (float)GetRandom() * ((Max + 1) - Min)); } #if UNITY_EDITOR public static MinMax DrawGUI(MinMax target, GUIContent label) { EditorGUILayout.BeginHorizontal(); float width = EditorStyles.label.CalcSize(label).x; EditorGUIUtility.labelWidth = width + 4; EditorGUILayout.LabelField(label, GUILayout.Width(width)); GUILayout.Space(28); EditorGUIUtility.labelWidth = 28; target.Min = EditorGUILayout.IntField("Min", target.Min, GUILayout.Width(70)); //GUILayout.FlexibleSpace(); GUILayout.Space(24); EditorGUIUtility.labelWidth = 32; target.Max = EditorGUILayout.IntField("Max", target.Max, GUILayout.Width(74)); EditorGUILayout.EndHorizontal(); EditorGUIUtility.labelWidth = 0; if (target.Min < 0) target.Min = 0; if (target.Max < 0) target.Max = 0; if (target.Min > target.Max) target.Max = target.Min; if (target.Max < target.Min) target.Min = target.Max; return target; } #endif } #if UNITY_EDITOR [CustomPropertyDrawer(typeof(MinMax))] public class MinMaxDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(position, label, property); Rect srcPos = position; position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); EditorGUIUtility.labelWidth = 30; float labelW = EditorStyles.label.CalcSize(label).x; var vRect = new Rect(srcPos.width - 60 * 2f - 10, position.y, 60, position.height); int preInd = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; SerializedProperty sp_min = property.FindPropertyRelative("Min"); EditorGUI.PropertyField(vRect, sp_min, new GUIContent(sp_min.displayName)); vRect = new Rect(srcPos.width - 60, position.y, 60, position.height); SerializedProperty sp_max = property.FindPropertyRelative("Max"); EditorGUI.PropertyField(vRect, sp_max, new GUIContent(sp_max.displayName)); if (sp_min.intValue < 0) sp_min.intValue = 0; if (sp_max.intValue < 0) sp_max.intValue = 0; if (sp_min.intValue > sp_max.intValue) sp_max.intValue = sp_min.intValue; if (sp_max.intValue < sp_min.intValue) sp_min.intValue = sp_max.intValue; EditorGUI.indentLevel = preInd; EditorGUIUtility.labelWidth = 0; EditorGUI.EndProperty(); } } #endif [System.Serializable] public struct MinMaxF { public float Min; public float Max; public MinMaxF(float min, float max) { Min = min; Max = max; } } #if UNITY_EDITOR [CustomPropertyDrawer(typeof(MinMaxF))] public class MinMaxFDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(position, label, property); Rect srcPos = position; position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); EditorGUIUtility.labelWidth = 30; float labelW = EditorStyles.label.CalcSize(label).x; var vRect = new Rect(srcPos.width - 60 * 2f - 10, position.y, 60, position.height); SerializedProperty sp_min = property.FindPropertyRelative("Min"); EditorGUI.PropertyField(vRect, sp_min, new GUIContent(sp_min.displayName)); vRect = new Rect(srcPos.width - 60, position.y, 60, position.height); SerializedProperty sp_max = property.FindPropertyRelative("Max"); EditorGUI.PropertyField(vRect, sp_max, new GUIContent(sp_max.displayName)); if (sp_min.floatValue < 0) sp_min.floatValue = 0; if (sp_max.floatValue < 0) sp_max.floatValue = 0; if (sp_min.floatValue > sp_max.floatValue) sp_max.floatValue = sp_min.floatValue; if (sp_max.floatValue < sp_min.floatValue) sp_min.floatValue = sp_max.floatValue; EditorGUIUtility.labelWidth = 0; EditorGUI.EndProperty(); } } #endif #endregion #region Scriptable Related public static string lastPath = ""; public static ScriptableObject GenerateScriptable(ScriptableObject reference, string exampleFilename = "", string playerPrefId = "") { #if UNITY_EDITOR if (lastPath == "") { if (EditorPrefs.HasKey(playerPrefId) && string.IsNullOrEmpty(playerPrefId) == false) { lastPath = EditorPrefs.GetString(playerPrefId); if (!System.IO.File.Exists(lastPath)) lastPath = Application.dataPath; } else lastPath = Application.dataPath; } string path = UnityEditor.EditorUtility.SaveFilePanelInProject("Generate Preset File", exampleFilename, "asset", "Enter name of file", lastPath); try { if (path != "") { lastPath = System.IO.Path.GetDirectoryName(path); EditorPrefs.SetString(playerPrefId, lastPath); UnityEditor.AssetDatabase.CreateAsset(reference, path); } } catch (System.Exception) { Debug.LogError("Something went wrong when creating scriptable file in your project."); } #endif return reference; } #endregion #region Final Utilities public static void CheckForNulls(List elements) { for (int i = elements.Count - 1; i >= 0; i--) { if (elements[i] == null) elements.RemoveAt(i); } } public static T GetRandomElement(this List list, bool unityRandom = false) { if (list == null) return default(T); if (list.Count == 1) return list[0]; if (unityRandom) return list[UnityEngine.Random.Range(0, list.Count)]; return list[GetRandom(0, list.Count)]; } public static T GetRandomElement(this List list, System.Random rand) { if (list == null) return default(T); if (list.Count == 1) return list[0]; return list[rand.Next(0, list.Count)]; } #endregion }