From 2f03591b2cecae7efcb2f60bdd7b256373435ad0 Mon Sep 17 00:00:00 2001 From: {} Date: Tue, 15 Apr 2025 22:04:36 +0900 Subject: [PATCH 1/2] - Add color highlighting for Tags and Layers - Hide tag "Untagged" - Show full name as tooltip on mouse hover - Show checkmark to current on selection menu --- .../Scripts/Editor/Data/GlobalData.cs | 4 + .../Editor/Hierarchy/Info/TagLayerInfo.cs | 469 ++++++++++-------- .../Scripts/Editor/Tabs/GeneralTab.cs | 4 +- 3 files changed, 258 insertions(+), 219 deletions(-) diff --git a/HierarchyDecorator/Scripts/Editor/Data/GlobalData.cs b/HierarchyDecorator/Scripts/Editor/Data/GlobalData.cs index 8312c3d..5e021b5 100644 --- a/HierarchyDecorator/Scripts/Editor/Data/GlobalData.cs +++ b/HierarchyDecorator/Scripts/Editor/Data/GlobalData.cs @@ -49,6 +49,10 @@ public class GlobalData public bool showTags = true; public bool showLayers = true; public bool applyChildLayers = true; + public bool coloringTags = true; + public bool coloringLayers = true; + [Range(0, 1)] public float coloringTagLayerS = 0.6f; + [Range(0, 2)] public float coloringTagLayerV = 2f; // Components diff --git a/HierarchyDecorator/Scripts/Editor/Hierarchy/Info/TagLayerInfo.cs b/HierarchyDecorator/Scripts/Editor/Hierarchy/Info/TagLayerInfo.cs index 2f81111..56cbf53 100644 --- a/HierarchyDecorator/Scripts/Editor/Hierarchy/Info/TagLayerInfo.cs +++ b/HierarchyDecorator/Scripts/Editor/Hierarchy/Info/TagLayerInfo.cs @@ -5,242 +5,275 @@ namespace HierarchyDecorator { - public class TagLayerInfo : HierarchyInfo - { - private const int LABEL_GRID_SIZE = 3; - - // --- Settings - - private bool tagEnabled; - private bool layerEnabled; - - private bool setChildLayers; - - private bool isVertical; - private bool tagFirst; - - private bool bothShown => tagEnabled && layerEnabled; - - // --- Methods - - protected override void OnDrawInit(HierarchyItem item, Settings settings) - { - setChildLayers = settings.globalData.applyChildLayers; - - TagLayerLayout layout = settings.globalData.tagLayerLayout; - isVertical = layout == TagLayerLayout.TagAbove || layout == TagLayerLayout.LayerAbove; - tagFirst = layout == TagLayerLayout.TagInFront; - } - - protected override bool DrawerIsEnabled(HierarchyItem item, Settings settings) - { - tagEnabled = settings.globalData.showTags; - layerEnabled = settings.globalData.showLayers; - - if (settings.styleData.HasStyle(item.DisplayName)) - { - tagEnabled &= settings.styleData.displayTags; - layerEnabled &= settings.styleData.displayLayers; - } - - return tagEnabled || layerEnabled; - } - - protected override void DrawInfo(Rect rect, HierarchyItem item, Settings settings) - { - if (tagEnabled) - { - DrawTag(rect, item.GameObject, settings.globalData.tagLayerLayout); - } - - if (layerEnabled) - { - DrawLayer(rect, item.GameObject, settings.globalData.tagLayerLayout); - } - } - - protected override int CalculateGridCount() - { - if (isVertical || !bothShown) - { - return LABEL_GRID_SIZE; - } - - return LABEL_GRID_SIZE * 2; - } - - protected override bool ValidateGrid() - { - if (GridCount < LABEL_GRID_SIZE) // Not big enough for either element - { - return false; - } - - if (GridCount < LABEL_GRID_SIZE * 2 && !isVertical && bothShown) - { - tagEnabled = !tagFirst; - layerEnabled = tagFirst; - } - - return true; - } - - // - Drawing elements - - private void DrawTag(Rect rect, GameObject instance, TagLayerLayout layout) - { - rect = GetInfoAreaRect(rect, true, layout); - DrawInstanceInfo(rect, instance.tag, instance, true); - } - - private void DrawLayer(Rect rect, GameObject instance, TagLayerLayout layout) - { - rect = GetInfoAreaRect(rect, false, layout); - DrawInstanceInfo(rect, LayerMask.LayerToName(instance.layer), instance, false); - } - - private void DrawInstanceInfo(Rect rect, string label, GameObject instance, bool isTag) - { - EditorGUI.LabelField(rect, label, (isVertical && bothShown) ? Style.TinyText : Style.SmallDropdown); - - Event e = Event.current; - bool hasClicked = rect.Contains(e.mousePosition) && e.type == EventType.MouseDown; - - if (!hasClicked) - { - return; - } - - // Create menu here - - GenericMenu menu = isTag - ? CreateMenu(InternalEditorUtility.tags, AssignTag) - : CreateMenu(InternalEditorUtility.layers, AssignLayer); - - GameObject[] selection = Selection.gameObjects; - if (selection.Length < 2) - { - Selection.SetActiveObjectWithContext(instance, null); - } - - menu.ShowAsContext(); - e.Use(); - } - - // - Assignment - - private void AssignTag(string tag) - { - Undo.RecordObjects(Selection.gameObjects, "Tag Updated"); - - foreach (GameObject go in Selection.gameObjects) - { - go.tag = tag; + public class TagLayerInfo : HierarchyInfo + { + private const int LABEL_GRID_SIZE = 3; + + // --- Settings + + private bool tagEnabled; + private bool layerEnabled; + + private bool setChildLayers; + + private bool isVertical; + private bool tagFirst; + + private bool bothShown => tagEnabled && layerEnabled; + + // --- Methods + + protected override void OnDrawInit(HierarchyItem item, Settings settings) + { + setChildLayers = settings.globalData.applyChildLayers; + + TagLayerLayout layout = settings.globalData.tagLayerLayout; + isVertical = layout == TagLayerLayout.TagAbove || layout == TagLayerLayout.LayerAbove; + tagFirst = layout == TagLayerLayout.TagInFront; + } + + protected override bool DrawerIsEnabled(HierarchyItem item, Settings settings) + { + tagEnabled = settings.globalData.showTags; + layerEnabled = settings.globalData.showLayers; + + if (settings.styleData.HasStyle(item.DisplayName)) + { + tagEnabled &= settings.styleData.displayTags; + layerEnabled &= settings.styleData.displayLayers; + } + + return tagEnabled || layerEnabled; + } + + protected override void DrawInfo(Rect rect, HierarchyItem item, Settings settings) + { + if (tagEnabled) + { + DrawTag(rect, item.GameObject, settings); + } + + if (layerEnabled) + { + DrawLayer(rect, item.GameObject, settings); + } + } + + protected override int CalculateGridCount() + { + if (isVertical || !bothShown) + { + return LABEL_GRID_SIZE; + } + + return LABEL_GRID_SIZE * 2; + } + + protected override bool ValidateGrid() + { + if (GridCount < LABEL_GRID_SIZE) // Not big enough for either element + { + return false; + } + + if (GridCount < LABEL_GRID_SIZE * 2 && !isVertical && bothShown) + { + tagEnabled = !tagFirst; + layerEnabled = tagFirst; + } + + return true; + } + + // - Drawing elements + + private void DrawTag(Rect rect, GameObject instance, Settings settings) + { + rect = GetInfoAreaRect(rect, true, settings.globalData.tagLayerLayout); + if (settings.globalData.coloringTags) + { + var color = GUI.contentColor; + GUI.contentColor = GetHashColor(instance.tag, settings.globalData.coloringTagLayerS, settings.globalData.coloringTagLayerV); + DrawInstanceInfo(rect, instance.tag, instance, true); + GUI.contentColor = color; + } + else + DrawInstanceInfo(rect, instance.tag, instance, true); + } + + private void DrawLayer(Rect rect, GameObject instance, Settings settings) + { + rect = GetInfoAreaRect(rect, false, settings.globalData.tagLayerLayout); + var label = LayerMask.LayerToName(instance.layer); + if (settings.globalData.coloringLayers) + { + var color = GUI.contentColor; + GUI.contentColor = GetHashColor(label, settings.globalData.coloringTagLayerS, settings.globalData.coloringTagLayerV); + DrawInstanceInfo(rect, label, instance, false); + GUI.contentColor = color; + } + else + DrawInstanceInfo(rect, label, instance, false); + } + + private Color GetHashColor(string label, float s, float v) + { + unchecked + { + int hash = 23; + foreach (char c in label) + hash = hash * 31 + c; + uint uhash = (uint)hash; + float h = (uhash * 0.61803398875f) % 1.0f; + return Color.HSVToRGB(h, s, v); + } + } + + private void DrawInstanceInfo(Rect rect, string label, GameObject instance, bool isTag) + { + if (!isTag || label != "Untagged") + { + GUI.Label(rect, new GUIContent(label, label), (isVertical && bothShown) ? Style.TinyText : Style.SmallDropdown); + } + + Event e = Event.current; + bool hasClicked = rect.Contains(e.mousePosition) && e.type == EventType.MouseDown; + + if (!hasClicked) + { + return; + } + + // Create menu here + + GenericMenu menu = isTag + ? CreateMenu(InternalEditorUtility.tags, label, AssignTag) + : CreateMenu(InternalEditorUtility.layers, label, AssignLayer); + + GameObject[] selection = Selection.gameObjects; + if (selection.Length < 2) + { + Selection.SetActiveObjectWithContext(instance, null); + } + + menu.ShowAsContext(); + e.Use(); + } + + // - Assignment + + private void AssignTag(string tag) + { + Undo.RecordObjects(Selection.gameObjects, "Tag Updated"); + + foreach (GameObject go in Selection.gameObjects) + { + go.tag = tag; + + if (Selection.gameObjects.Length == 1) + { + Selection.SetActiveObjectWithContext(Selection.gameObjects[0], null); + } + } + } + + private void AssignLayer(string layer) + { + Undo.RecordObjects(Selection.gameObjects, "Layer Updated"); + + foreach (GameObject go in Selection.gameObjects) + { + int layerIndex = LayerMask.NameToLayer(layer); + go.layer = layerIndex; + + if (setChildLayers) + { + Undo.RecordObjects(Selection.gameObjects, "Layer Updated"); + + foreach (Transform child in go.transform) + { + child.gameObject.layer = layerIndex; + } + } + + if (Selection.gameObjects.Length == 1) + { + Selection.SetActiveObjectWithContext(Selection.gameObjects[0], null); + } + } + } + + // - Helpers + + private static GenericMenu CreateMenu(string[] items, string label, Action onSelect) + { + GenericMenu menu = new GenericMenu(); + for (int i = 0; i < items.Length; i++) + { + string item = items[i]; + menu.AddItem(new GUIContent(item), label == item, () => onSelect.Invoke(item)); + } - if (Selection.gameObjects.Length == 1) - { - Selection.SetActiveObjectWithContext(Selection.gameObjects[0], null); - } - } - } - - private void AssignLayer(string layer) - { - Undo.RecordObjects(Selection.gameObjects, "Layer Updated"); - - foreach (GameObject go in Selection.gameObjects) - { - int layerIndex = LayerMask.NameToLayer(layer); - go.layer = layerIndex; + return menu; + } + + private Rect GetInfoAreaRect(Rect rect, bool isTag, TagLayerLayout layout) + { + if (!bothShown) + { + return rect; + } - if (setChildLayers) - { - Undo.RecordObjects(Selection.gameObjects, "Layer Updated"); + switch (layout) + { + // Horizontal - foreach (Transform child in go.transform) - { - child.gameObject.layer = layerIndex; - } - } + // - Front Element - if (Selection.gameObjects.Length == 1) - { - Selection.SetActiveObjectWithContext(Selection.gameObjects[0], null); - } - } - } + case TagLayerLayout.TagInFront when isTag: + case TagLayerLayout.LayerInFront when !isTag: - // - Helpers + float halfWidth = rect.width * 0.5f; + rect.width = halfWidth; - private static GenericMenu CreateMenu(string[] items, Action onSelect) - { - GenericMenu menu = new GenericMenu(); - for (int i = 0; i < items.Length; i++) - { - string item = items[i]; - menu.AddItem(new GUIContent(item), false, () => onSelect.Invoke(item)); - } + break; - return menu; - } + // - Back Element - private Rect GetInfoAreaRect(Rect rect, bool isTag, TagLayerLayout layout) - { - if (!bothShown) - { - return rect; - } + case TagLayerLayout.TagInFront when !isTag: + case TagLayerLayout.LayerInFront when isTag: - switch (layout) - { - // Horizontal + halfWidth = rect.width * 0.5f; + rect.width = halfWidth; + rect.x += halfWidth; - // - Front Element + break; - case TagLayerLayout.TagInFront when isTag: - case TagLayerLayout.LayerInFront when !isTag: + // Vertical - float halfWidth = rect.width * 0.5f; - rect.width = halfWidth; + // - Top element - break; + case TagLayerLayout.TagAbove when isTag: + case TagLayerLayout.LayerAbove when !isTag: - // - Back Element + float halfHeight = rect.height * 0.5f; + rect.height = halfHeight; - case TagLayerLayout.TagInFront when !isTag: - case TagLayerLayout.LayerInFront when isTag: + break; - halfWidth = rect.width * 0.5f; - rect.width = halfWidth; - rect.x += halfWidth; + // - Lower element - break; + case TagLayerLayout.LayerAbove when isTag: + case TagLayerLayout.TagAbove when !isTag: - // Vertical + halfHeight = rect.height * 0.5f; + rect.height = halfHeight; + rect.y += halfHeight; - // - Top element + break; + } - case TagLayerLayout.TagAbove when isTag: - case TagLayerLayout.LayerAbove when !isTag: - - float halfHeight = rect.height * 0.5f; - rect.height = halfHeight; - - break; - - // - Lower element - - case TagLayerLayout.LayerAbove when isTag: - case TagLayerLayout.TagAbove when !isTag: - - halfHeight = rect.height * 0.5f; - rect.height = halfHeight; - rect.y += halfHeight; - - break; - } - - return rect; - } - } + return rect; + } + } } diff --git a/HierarchyDecorator/Scripts/Editor/Tabs/GeneralTab.cs b/HierarchyDecorator/Scripts/Editor/Tabs/GeneralTab.cs index a71f4fd..0a43e3a 100644 --- a/HierarchyDecorator/Scripts/Editor/Tabs/GeneralTab.cs +++ b/HierarchyDecorator/Scripts/Editor/Tabs/GeneralTab.cs @@ -8,6 +8,7 @@ public class GeneralTab : SettingsTab { private string[] TagFields = new[] { "showTags" }; private string[] LayerFields = new[] { "showLayers", "applyChildLayers" }; + private string[] coloringTagLayerFields = new[] { "coloringTags", "coloringLayers", "coloringTagLayerS", "coloringTagLayerV"}; public GeneralTab(Settings settings, SerializedObject serializedSettings) : base (settings, serializedSettings, "globalData", "General", "d_CustomTool") { @@ -21,7 +22,8 @@ public GeneralTab(Settings settings, SerializedObject serializedSettings) : base CreateDrawableGroup("Tags & Layers") .RegisterSerializedProperty(serializedTab, TagFields) .RegisterSerializedProperty(serializedTab, LayerFields).Space() - .RegisterSerializedProperty(serializedTab, "tagLayerLayout"); + .RegisterSerializedProperty(serializedTab, "tagLayerLayout") + .RegisterSerializedProperty(serializedTab, coloringTagLayerFields); // --- Breadcrumbs From 2fbb83097ec6d9b0e6de52cb54ed153cc612a025 Mon Sep 17 00:00:00 2001 From: {} Date: Tue, 6 May 2025 10:47:53 +0900 Subject: [PATCH 2/2] fix: code indentation. --- .../Scripts/Editor/Data/GlobalData.cs | 8 +- .../Editor/Hierarchy/Info/TagLayerInfo.cs | 502 +++++++++--------- 2 files changed, 255 insertions(+), 255 deletions(-) diff --git a/HierarchyDecorator/Scripts/Editor/Data/GlobalData.cs b/HierarchyDecorator/Scripts/Editor/Data/GlobalData.cs index 5e021b5..2ca73ba 100644 --- a/HierarchyDecorator/Scripts/Editor/Data/GlobalData.cs +++ b/HierarchyDecorator/Scripts/Editor/Data/GlobalData.cs @@ -49,10 +49,10 @@ public class GlobalData public bool showTags = true; public bool showLayers = true; public bool applyChildLayers = true; - public bool coloringTags = true; - public bool coloringLayers = true; - [Range(0, 1)] public float coloringTagLayerS = 0.6f; - [Range(0, 2)] public float coloringTagLayerV = 2f; + public bool coloringTags = true; + public bool coloringLayers = true; + [Range(0, 1)] public float coloringTagLayerS = 0.6f; + [Range(0, 2)] public float coloringTagLayerV = 2f; // Components diff --git a/HierarchyDecorator/Scripts/Editor/Hierarchy/Info/TagLayerInfo.cs b/HierarchyDecorator/Scripts/Editor/Hierarchy/Info/TagLayerInfo.cs index 56cbf53..e29ebc4 100644 --- a/HierarchyDecorator/Scripts/Editor/Hierarchy/Info/TagLayerInfo.cs +++ b/HierarchyDecorator/Scripts/Editor/Hierarchy/Info/TagLayerInfo.cs @@ -5,275 +5,275 @@ namespace HierarchyDecorator { - public class TagLayerInfo : HierarchyInfo - { - private const int LABEL_GRID_SIZE = 3; - - // --- Settings - - private bool tagEnabled; - private bool layerEnabled; - - private bool setChildLayers; - - private bool isVertical; - private bool tagFirst; - - private bool bothShown => tagEnabled && layerEnabled; - - // --- Methods - - protected override void OnDrawInit(HierarchyItem item, Settings settings) - { - setChildLayers = settings.globalData.applyChildLayers; - - TagLayerLayout layout = settings.globalData.tagLayerLayout; - isVertical = layout == TagLayerLayout.TagAbove || layout == TagLayerLayout.LayerAbove; - tagFirst = layout == TagLayerLayout.TagInFront; - } - - protected override bool DrawerIsEnabled(HierarchyItem item, Settings settings) - { - tagEnabled = settings.globalData.showTags; - layerEnabled = settings.globalData.showLayers; - - if (settings.styleData.HasStyle(item.DisplayName)) - { - tagEnabled &= settings.styleData.displayTags; - layerEnabled &= settings.styleData.displayLayers; - } - - return tagEnabled || layerEnabled; - } - - protected override void DrawInfo(Rect rect, HierarchyItem item, Settings settings) - { - if (tagEnabled) - { - DrawTag(rect, item.GameObject, settings); - } - - if (layerEnabled) - { - DrawLayer(rect, item.GameObject, settings); - } - } - - protected override int CalculateGridCount() - { - if (isVertical || !bothShown) - { - return LABEL_GRID_SIZE; - } - - return LABEL_GRID_SIZE * 2; - } - - protected override bool ValidateGrid() - { - if (GridCount < LABEL_GRID_SIZE) // Not big enough for either element - { - return false; - } - - if (GridCount < LABEL_GRID_SIZE * 2 && !isVertical && bothShown) - { - tagEnabled = !tagFirst; - layerEnabled = tagFirst; - } - - return true; - } - - // - Drawing elements - - private void DrawTag(Rect rect, GameObject instance, Settings settings) - { - rect = GetInfoAreaRect(rect, true, settings.globalData.tagLayerLayout); - if (settings.globalData.coloringTags) - { - var color = GUI.contentColor; - GUI.contentColor = GetHashColor(instance.tag, settings.globalData.coloringTagLayerS, settings.globalData.coloringTagLayerV); - DrawInstanceInfo(rect, instance.tag, instance, true); - GUI.contentColor = color; - } - else - DrawInstanceInfo(rect, instance.tag, instance, true); - } - - private void DrawLayer(Rect rect, GameObject instance, Settings settings) - { - rect = GetInfoAreaRect(rect, false, settings.globalData.tagLayerLayout); - var label = LayerMask.LayerToName(instance.layer); - if (settings.globalData.coloringLayers) - { - var color = GUI.contentColor; - GUI.contentColor = GetHashColor(label, settings.globalData.coloringTagLayerS, settings.globalData.coloringTagLayerV); - DrawInstanceInfo(rect, label, instance, false); - GUI.contentColor = color; - } - else - DrawInstanceInfo(rect, label, instance, false); - } - - private Color GetHashColor(string label, float s, float v) - { - unchecked - { - int hash = 23; - foreach (char c in label) - hash = hash * 31 + c; - uint uhash = (uint)hash; - float h = (uhash * 0.61803398875f) % 1.0f; - return Color.HSVToRGB(h, s, v); - } - } - - private void DrawInstanceInfo(Rect rect, string label, GameObject instance, bool isTag) - { - if (!isTag || label != "Untagged") - { - GUI.Label(rect, new GUIContent(label, label), (isVertical && bothShown) ? Style.TinyText : Style.SmallDropdown); - } - - Event e = Event.current; - bool hasClicked = rect.Contains(e.mousePosition) && e.type == EventType.MouseDown; - - if (!hasClicked) - { - return; - } - - // Create menu here - - GenericMenu menu = isTag - ? CreateMenu(InternalEditorUtility.tags, label, AssignTag) - : CreateMenu(InternalEditorUtility.layers, label, AssignLayer); - - GameObject[] selection = Selection.gameObjects; - if (selection.Length < 2) - { - Selection.SetActiveObjectWithContext(instance, null); - } - - menu.ShowAsContext(); - e.Use(); - } - - // - Assignment - - private void AssignTag(string tag) - { - Undo.RecordObjects(Selection.gameObjects, "Tag Updated"); - - foreach (GameObject go in Selection.gameObjects) - { - go.tag = tag; - - if (Selection.gameObjects.Length == 1) - { - Selection.SetActiveObjectWithContext(Selection.gameObjects[0], null); - } - } - } - - private void AssignLayer(string layer) - { - Undo.RecordObjects(Selection.gameObjects, "Layer Updated"); - - foreach (GameObject go in Selection.gameObjects) - { - int layerIndex = LayerMask.NameToLayer(layer); - go.layer = layerIndex; - - if (setChildLayers) - { - Undo.RecordObjects(Selection.gameObjects, "Layer Updated"); - - foreach (Transform child in go.transform) - { - child.gameObject.layer = layerIndex; - } - } - - if (Selection.gameObjects.Length == 1) - { - Selection.SetActiveObjectWithContext(Selection.gameObjects[0], null); - } - } - } - - // - Helpers - - private static GenericMenu CreateMenu(string[] items, string label, Action onSelect) - { - GenericMenu menu = new GenericMenu(); - for (int i = 0; i < items.Length; i++) - { - string item = items[i]; - menu.AddItem(new GUIContent(item), label == item, () => onSelect.Invoke(item)); - } + public class TagLayerInfo : HierarchyInfo + { + private const int LABEL_GRID_SIZE = 3; + + // --- Settings + + private bool tagEnabled; + private bool layerEnabled; + + private bool setChildLayers; + + private bool isVertical; + private bool tagFirst; + + private bool bothShown => tagEnabled && layerEnabled; + + // --- Methods + + protected override void OnDrawInit(HierarchyItem item, Settings settings) + { + setChildLayers = settings.globalData.applyChildLayers; + + TagLayerLayout layout = settings.globalData.tagLayerLayout; + isVertical = layout == TagLayerLayout.TagAbove || layout == TagLayerLayout.LayerAbove; + tagFirst = layout == TagLayerLayout.TagInFront; + } + + protected override bool DrawerIsEnabled(HierarchyItem item, Settings settings) + { + tagEnabled = settings.globalData.showTags; + layerEnabled = settings.globalData.showLayers; + + if (settings.styleData.HasStyle(item.DisplayName)) + { + tagEnabled &= settings.styleData.displayTags; + layerEnabled &= settings.styleData.displayLayers; + } + + return tagEnabled || layerEnabled; + } + + protected override void DrawInfo(Rect rect, HierarchyItem item, Settings settings) + { + if (tagEnabled) + { + DrawTag(rect, item.GameObject, settings); + } + + if (layerEnabled) + { + DrawLayer(rect, item.GameObject, settings); + } + } + + protected override int CalculateGridCount() + { + if (isVertical || !bothShown) + { + return LABEL_GRID_SIZE; + } + + return LABEL_GRID_SIZE * 2; + } + + protected override bool ValidateGrid() + { + if (GridCount < LABEL_GRID_SIZE) // Not big enough for either element + { + return false; + } + + if (GridCount < LABEL_GRID_SIZE * 2 && !isVertical && bothShown) + { + tagEnabled = !tagFirst; + layerEnabled = tagFirst; + } + + return true; + } + + // - Drawing elements + + private void DrawTag(Rect rect, GameObject instance, Settings settings) + { + rect = GetInfoAreaRect(rect, true, settings.globalData.tagLayerLayout); + if (settings.globalData.coloringTags) + { + var color = GUI.contentColor; + GUI.contentColor = GetHashColor(instance.tag, settings.globalData.coloringTagLayerS, settings.globalData.coloringTagLayerV); + DrawInstanceInfo(rect, instance.tag, instance, true); + GUI.contentColor = color; + } + else + DrawInstanceInfo(rect, instance.tag, instance, true); + } + + private void DrawLayer(Rect rect, GameObject instance, Settings settings) + { + rect = GetInfoAreaRect(rect, false, settings.globalData.tagLayerLayout); + var label = LayerMask.LayerToName(instance.layer); + if (settings.globalData.coloringLayers) + { + var color = GUI.contentColor; + GUI.contentColor = GetHashColor(label, settings.globalData.coloringTagLayerS, settings.globalData.coloringTagLayerV); + DrawInstanceInfo(rect, label, instance, false); + GUI.contentColor = color; + } + else + DrawInstanceInfo(rect, label, instance, false); + } + + private Color GetHashColor(string label, float s, float v) + { + unchecked + { + int hash = 23; + foreach (char c in label) + hash = hash * 31 + c; + uint uhash = (uint)hash; + float h = (uhash * 0.61803398875f) % 1.0f; + return Color.HSVToRGB(h, s, v); + } + } + + private void DrawInstanceInfo(Rect rect, string label, GameObject instance, bool isTag) + { + if (!isTag || label != "Untagged") + { + GUI.Label(rect, new GUIContent(label, label), (isVertical && bothShown) ? Style.TinyText : Style.SmallDropdown); + } + + Event e = Event.current; + bool hasClicked = rect.Contains(e.mousePosition) && e.type == EventType.MouseDown; + + if (!hasClicked) + { + return; + } + + // Create menu here + + GenericMenu menu = isTag + ? CreateMenu(InternalEditorUtility.tags, label, AssignTag) + : CreateMenu(InternalEditorUtility.layers, label, AssignLayer); + + GameObject[] selection = Selection.gameObjects; + if (selection.Length < 2) + { + Selection.SetActiveObjectWithContext(instance, null); + } + + menu.ShowAsContext(); + e.Use(); + } + + // - Assignment + + private void AssignTag(string tag) + { + Undo.RecordObjects(Selection.gameObjects, "Tag Updated"); + + foreach (GameObject go in Selection.gameObjects) + { + go.tag = tag; + + if (Selection.gameObjects.Length == 1) + { + Selection.SetActiveObjectWithContext(Selection.gameObjects[0], null); + } + } + } + + private void AssignLayer(string layer) + { + Undo.RecordObjects(Selection.gameObjects, "Layer Updated"); + + foreach (GameObject go in Selection.gameObjects) + { + int layerIndex = LayerMask.NameToLayer(layer); + go.layer = layerIndex; + + if (setChildLayers) + { + Undo.RecordObjects(Selection.gameObjects, "Layer Updated"); + + foreach (Transform child in go.transform) + { + child.gameObject.layer = layerIndex; + } + } + + if (Selection.gameObjects.Length == 1) + { + Selection.SetActiveObjectWithContext(Selection.gameObjects[0], null); + } + } + } + + // - Helpers + + private static GenericMenu CreateMenu(string[] items, string label, Action onSelect) + { + GenericMenu menu = new GenericMenu(); + for (int i = 0; i < items.Length; i++) + { + string item = items[i]; + menu.AddItem(new GUIContent(item), label == item, () => onSelect.Invoke(item)); + } - return menu; - } - - private Rect GetInfoAreaRect(Rect rect, bool isTag, TagLayerLayout layout) - { - if (!bothShown) - { - return rect; - } + return menu; + } + + private Rect GetInfoAreaRect(Rect rect, bool isTag, TagLayerLayout layout) + { + if (!bothShown) + { + return rect; + } - switch (layout) - { - // Horizontal + switch (layout) + { + // Horizontal - // - Front Element + // - Front Element - case TagLayerLayout.TagInFront when isTag: - case TagLayerLayout.LayerInFront when !isTag: + case TagLayerLayout.TagInFront when isTag: + case TagLayerLayout.LayerInFront when !isTag: - float halfWidth = rect.width * 0.5f; - rect.width = halfWidth; + float halfWidth = rect.width * 0.5f; + rect.width = halfWidth; - break; + break; - // - Back Element + // - Back Element - case TagLayerLayout.TagInFront when !isTag: - case TagLayerLayout.LayerInFront when isTag: + case TagLayerLayout.TagInFront when !isTag: + case TagLayerLayout.LayerInFront when isTag: - halfWidth = rect.width * 0.5f; - rect.width = halfWidth; - rect.x += halfWidth; + halfWidth = rect.width * 0.5f; + rect.width = halfWidth; + rect.x += halfWidth; - break; + break; - // Vertical + // Vertical - // - Top element + // - Top element - case TagLayerLayout.TagAbove when isTag: - case TagLayerLayout.LayerAbove when !isTag: + case TagLayerLayout.TagAbove when isTag: + case TagLayerLayout.LayerAbove when !isTag: - float halfHeight = rect.height * 0.5f; - rect.height = halfHeight; + float halfHeight = rect.height * 0.5f; + rect.height = halfHeight; - break; + break; - // - Lower element + // - Lower element - case TagLayerLayout.LayerAbove when isTag: - case TagLayerLayout.TagAbove when !isTag: + case TagLayerLayout.LayerAbove when isTag: + case TagLayerLayout.TagAbove when !isTag: - halfHeight = rect.height * 0.5f; - rect.height = halfHeight; - rect.y += halfHeight; + halfHeight = rect.height * 0.5f; + rect.height = halfHeight; + rect.y += halfHeight; - break; - } + break; + } - return rect; - } - } + return rect; + } + } }