123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- using System;
- using System.Linq;
- using System.Text;
- using UnityEditor;
- using UnityEngine;
- namespace EnhancedHierarchy {
- /// <summary>
- /// Misc utilities for Enhanced Hierarchy.
- /// </summary>
- public static class Utility {
- private const string CTRL = "Ctrl";
- private const string CMD = "Cmd";
- private const string MENU_ITEM_PATH = "Edit/Enhanced Hierarchy %h";
- private static int errorCount;
- private static readonly GUIContent tempContent = new GUIContent();
- public static string CtrlKey { get { return Application.platform == RuntimePlatform.OSXEditor ? CMD : CTRL; } }
- [MenuItem(MENU_ITEM_PATH, false, int.MinValue)]
- private static void EnableDisableHierarchy() {
- Preferences.Enabled.Value = !Preferences.Enabled;
- EditorApplication.RepaintHierarchyWindow();
- }
- [MenuItem(MENU_ITEM_PATH, true)]
- private static bool CheckHierarchyEnabled() {
- Menu.SetChecked(MENU_ITEM_PATH, Preferences.Enabled);
- return true;
- }
- public static void EnableFPSCounter() {
- var frames = 0;
- var fps = 0d;
- var lastTime = 0d;
- var content = new GUIContent();
- var evt = EventType.Repaint;
- EditorApplication.hierarchyWindowItemOnGUI += (id, rect) => {
- using(ProfilerSample.Get("Enhanced Hierarchy"))
- using(ProfilerSample.Get("FPS Counter")) {
- if (evt == Event.current.type)
- return;
- evt = Event.current.type;
- if (evt == EventType.Repaint)
- frames++;
- if (EditorApplication.timeSinceStartup - lastTime < 0.5d)
- return;
- fps = frames / (EditorApplication.timeSinceStartup - lastTime);
- lastTime = EditorApplication.timeSinceStartup;
- frames = 0;
- content.text = string.Format("{0:00.0} FPS", fps);
- content.image = Styles.warningIcon;
- SetHierarchyTitle(content);
- }
- };
- }
- public static bool ShouldCalculateTooltipAt(Rect area) {
- return area.Contains(Event.current.mousePosition);
- }
- public static void ForceUpdateHierarchyEveryFrame() {
- // EditorApplication.update += () => {
- // if(EditorWindow.mouseOverWindow)
- // EditorApplication.RepaintHierarchyWindow();
- // };
- }
- public static void LogException(Exception e) {
- Debug.LogError("Unexpected exception in Enhanced Hierarchy");
- Debug.LogException(e);
- if (errorCount++ >= 10) {
- Debug.LogWarning("Automatically disabling Enhanced Hierarchy, if the error persists contact the developer");
- Preferences.Enabled.Value = false;
- errorCount = 0;
- if (!EditorPrefs.GetBool("EHEmailAskDisabled", false))
- switch (EditorUtility.DisplayDialogComplex("Mail Developer", "Enhanced Hierarchy has found an exeption, would you like to report a bug to the developer? (If you choose yes your mail app will open with a few techinical information)", "Yes", "Not now", "No and don't ask again")) {
- case 0:
- Preferences.OpenSupportEmail(e);
- EditorUtility.DisplayDialog("Mail Developer", "Your mail app will open now, if it doesn't please send an email reporting the bug to " + Preferences.DEVELOPER_EMAIL, "OK");
- break;
- case 1:
- break;
- case 2:
- EditorPrefs.SetBool("EHEmailAskDisabled", true);
- EditorUtility.DisplayDialog("Mail Developer", "You won't be bothered again, sorry", "OK");
- break;
- }
- }
- }
- public static void SetHierarchyTitle(string title) {
- try {
- Reflected.HierarchyWindowInstance.titleContent.text = title;
- } catch (Exception e) {
- Debug.LogWarning("Failed to set hierarchy title: " + e);
- }
- }
- public static void SetHierarchyTitle(GUIContent content) {
- try {
- Reflected.HierarchyWindowInstance.titleContent = content;
- } catch (Exception e) {
- Debug.LogWarning("Failed to set hierarchy title: " + e);
- }
- }
- public static GUIStyle CreateStyleFromTextures(Texture2D on, Texture2D off) {
- return CreateStyleFromTextures(null, on, off);
- }
- public static GUIStyle CreateStyleFromTextures(GUIStyle reference, Texture2D on, Texture2D off) {
- using(ProfilerSample.Get()) {
- var style = reference != null ? new GUIStyle(reference) : new GUIStyle();
- style.active.background = off;
- style.focused.background = off;
- style.hover.background = off;
- style.normal.background = off;
- style.onActive.background = on;
- style.onFocused.background = on;
- style.onHover.background = on;
- style.onNormal.background = on;
- style.imagePosition = ImagePosition.ImageOnly;
- EditorApplication.update += () => {
- style.fixedHeight = Preferences.IconsSize;
- style.fixedWidth = Preferences.IconsSize;
- };
- return style;
- }
- }
- public static Texture2D GetBackground(GUIStyle style, bool on) {
- return on ?
- style.onNormal.background :
- style.normal.background;
- }
- public static Texture2D FindOrLoad(string base64) {
- var name = string.Format("Enhanced_Hierarchy_{0}", (long)base64.GetHashCode() - int.MinValue);
- return FindTextureFromName(name) ?? LoadTexture(base64, name);
- }
- public static Texture2D LoadTexture(string base64, string name) {
- using(ProfilerSample.Get())
- try {
- var bytes = Convert.FromBase64String(base64);
- var texture = new Texture2D(0, 0, TextureFormat.ARGB32, false, false);
- texture.name = name;
- texture.hideFlags = HideFlags.HideAndDontSave;
- texture.LoadImage(bytes);
- return texture;
- } catch (Exception e) {
- Debug.LogErrorFormat("Failed to load texture \"{0}\": {1}", name, e);
- return null;
- }
- }
- public static Texture2D FindTextureFromName(string name) {
- using(ProfilerSample.Get())
- try {
- var textures = Resources.FindObjectsOfTypeAll<Texture2D>();
- for (var i = 0; i < textures.Length; i++)
- if (textures[i].name == name)
- return textures[i];
- return null;
- } catch (Exception e) {
- Debug.LogErrorFormat("Failed to find texture \"{0}\": {1}", name, e);
- return null;
- }
- }
- public static Color GetHierarchyColor(Transform t) {
- if (!t)
- return Color.clear;
- return GetHierarchyColor(t.gameObject);
- }
- public static Color GetHierarchyColor(GameObject go) {
- if (!go)
- return Color.black;
- return GetHierarchyLabelStyle(go).normal.textColor;
- }
- public static GUIStyle GetHierarchyLabelStyle(GameObject go) {
- using(ProfilerSample.Get()) {
- if (!go)
- return EditorStyles.label;
- var active = go.activeInHierarchy;
- #if UNITY_2018_3_OR_NEWER
- var prefabType = PrefabUtility.GetPrefabInstanceStatus(go);
- switch (prefabType) {
- case PrefabInstanceStatus.Connected:
- return active ? Styles.labelPrefab : Styles.labelPrefabDisabled;
- case PrefabInstanceStatus.MissingAsset:
- return active ? Styles.labelPrefabBroken : Styles.labelPrefabBrokenDisabled;
- default:
- return active ? Styles.labelNormal : Styles.labelDisabled;
- }
- #else
- var prefabType = PrefabUtility.GetPrefabType(PrefabUtility.FindPrefabRoot(go));
- switch (prefabType) {
- case PrefabType.PrefabInstance:
- case PrefabType.ModelPrefabInstance:
- return active ? Styles.labelPrefab : Styles.labelPrefabDisabled;
- case PrefabType.MissingPrefabInstance:
- return active ? Styles.labelPrefabBroken : Styles.labelPrefabBrokenDisabled;
- default:
- return active ? Styles.labelNormal : Styles.labelDisabled;
- }
- #endif
- }
- }
- public static Color OverlayColors(Color src, Color dst) {
- using(ProfilerSample.Get()) {
- var alpha = dst.a + src.a * (1f - dst.a);
- var result = (dst * dst.a + src * src.a * (1f - dst.a)) / alpha;
- result.a = alpha;
- return result;
- }
- }
- public static bool TransformIsLastChild(Transform t) {
- using(ProfilerSample.Get()) {
- if (!t)
- return true;
- return t.GetSiblingIndex() == t.parent.childCount - 1;
- }
- }
- public static void ApplyHideFlagsToPrefab(UnityEngine.Object obj) {
- var handle = PrefabUtility.GetPrefabInstanceHandle(obj);
- if (handle)
- handle.hideFlags = obj.hideFlags;
- }
- public static void LockObject(GameObject go) {
- using(ProfilerSample.Get()) {
- go.hideFlags |= HideFlags.NotEditable;
- ApplyHideFlagsToPrefab(go);
- #if UNITY_2019_3_OR_NEWER
- if (!Preferences.AllowPickingLockedObjects)
- SceneVisibilityManager.instance.DisablePicking(go, false);
- #endif
- EditorUtility.SetDirty(go);
- }
- }
- public static void UnlockObject(GameObject go) {
- using(ProfilerSample.Get()) {
- go.hideFlags &= ~HideFlags.NotEditable;
- ApplyHideFlagsToPrefab(go);
- #if UNITY_2019_3_OR_NEWER
- if (!Preferences.AllowPickingLockedObjects)
- SceneVisibilityManager.instance.EnablePicking(go, false);
- #endif
- EditorUtility.SetDirty(go);
- }
- }
- // public static void UnlockAllObjects() {
- // using(ProfilerSample.Get())
- // foreach (var objRaw in Resources.FindObjectsOfTypeAll<GameObject>()) {
- // var obj = ObjectOrPrefabInstanceHandle(objRaw);
- // if (obj && (obj.hideFlags & HideFlags.HideInHierarchy) == 0 && !EditorUtility.IsPersistent(obj))
- // UnlockObject(obj);
- // }
- // }
- public static void ApplyPrefabModifications(GameObject go, bool allowCreatingNew) {
- #if UNITY_2018_3_OR_NEWER
- var isPrefab = PrefabUtility.IsPartOfAnyPrefab(go);
- #else
- var isPrefab = PrefabUtility.GetPrefabType(go) == PrefabType.PrefabInstance;
- #endif
- if (isPrefab) {
- #if UNITY_2018_3_OR_NEWER
- var prefab = PrefabUtility.GetNearestPrefabInstanceRoot(go);
- #elif UNITY_2018_2_OR_NEWER
- var prefab = PrefabUtility.GetCorrespondingObjectFromSource(go);
- #else
- var prefab = PrefabUtility.GetPrefabParent(go);
- #endif
- if (!prefab) {
- Debug.LogError("Prefab asset not valid!");
- return;
- }
- #if UNITY_2018_3_OR_NEWER
- if (PrefabUtility.GetPrefabInstanceStatus(prefab) == PrefabInstanceStatus.Connected)
- PrefabUtility.ApplyPrefabInstance(prefab, InteractionMode.UserAction);
- else if (EditorUtility.DisplayDialog("Apply disconnected prefab", "This is a disconnected game object, do you want to try to reconnect to the last prefab asset?", "Try to Reconnect", "Cancel"))
- PrefabUtility.RevertPrefabInstance(prefab, InteractionMode.UserAction);
- EditorUtility.SetDirty(prefab);
- #else
- var selection = Selection.instanceIDs;
- Selection.activeGameObject = go;
- if (EditorApplication.ExecuteMenuItem("GameObject/Apply Changes To Prefab")) {
- EditorUtility.SetDirty(prefab);
- Selection.instanceIDs = selection;
- } else
- Debug.LogError("Failed to apply prefab modifications");
- #endif
- } else if (allowCreatingNew) {
- var path = EditorUtility.SaveFilePanelInProject("Save prefab", "New Prefab", "prefab", "Save the selected prefab");
- if (!string.IsNullOrEmpty(path))
- #if UNITY_2018_3_OR_NEWER
- PrefabUtility.SaveAsPrefabAssetAndConnect(go, path, InteractionMode.UserAction);
- #else
- PrefabUtility.CreatePrefab(path, go, ReplacePrefabOptions.ConnectToPrefab);
- #endif
- }
- }
- public static string EnumFlagsToString(Enum value) {
- using(ProfilerSample.Get())
- try {
- if ((int)(object)value == -1)
- return "Everything";
- var str = new StringBuilder();
- var separator = ", ";
- foreach (var enumValue in Enum.GetValues(value.GetType())) {
- var i = (int)enumValue;
- if (i != 0 && (i & (i - 1)) == 0 && Enum.IsDefined(value.GetType(), i) && (Convert.ToInt32(value) & i) != 0) {
- str.Append(ObjectNames.NicifyVariableName(enumValue.ToString()));
- str.Append(separator);
- }
- }
- if (str.Length > 0)
- str.Length -= separator.Length;
- return str.ToString();
- } catch (Exception e) {
- if (Preferences.DebugEnabled)
- Debug.LogException(e);
- return string.Empty;
- }
- }
- public static GUIContent GetTempGUIContent(string text, string tooltip = null, Texture2D image = null) {
- tempContent.text = text;
- tempContent.tooltip = tooltip;
- tempContent.image = image;
- return tempContent;
- }
- public static string SafeGetName(this IconBase icon) {
- try {
- return icon.Name;
- } catch (Exception e) {
- Debug.LogException(e);
- Preferences.ForceDisableButton(icon);
- return string.Empty;
- }
- }
- public static float SafeGetWidth(this IconBase icon) {
- try {
- return icon.Width + (Preferences.IconsSize - 15) / 2;
- } catch (Exception e) {
- Debug.LogException(e);
- Preferences.ForceDisableButton(icon);
- return 0f;
- }
- }
- public static void SafeInit(this IconBase icon) {
- try {
- icon.Init();
- } catch (Exception e) {
- Debug.LogException(e);
- Preferences.ForceDisableButton(icon);
- }
- }
- public static void SafeDoGUI(this IconBase icon, Rect rect) {
- try {
- rect.yMin -= (Preferences.IconsSize - 15) / 2;
- rect.xMin -= (Preferences.IconsSize - 15) / 2;
- icon.DoGUI(rect);
- } catch (Exception e) {
- Debug.LogException(e);
- Preferences.ForceDisableButton(icon);
- }
- }
- public static Rect FlipRectHorizontally(Rect rect) {
- return Rect.MinMaxRect(
- rect.xMax,
- rect.yMin,
- rect.xMin,
- rect.yMax
- );
- }
- }
- }
|