From 6fcea0a14eac278981fd254f02e4b518af68919f Mon Sep 17 00:00:00 2001 From: HugoKostic Date: Wed, 15 Oct 2025 15:23:23 +0200 Subject: [PATCH 1/2] Unity 6.3 support + rewrite Color picker + various fix feat(editor): Unity 6.3 compatibility, safe reflection, 1D palette, reliable repaint Replace ambiguous reflection with exact lookups Methods: GetMethod("...", types: Type.EmptyTypes) Properties: GetPropertyExact(type, name, returnType) to avoid AmbiguousMatchException Resolve members from instances (sceneHierarchy, treeView, data) in RefreshFolderIcons() Stop eager binding of fragile PropertyInfo/MethodInfo; use name + arity at runtime Add hard guards in IMGUI path to prevent NRE and GUI clip errors try/catch around reflection, early returns run RefreshFolderIcons once per frame via _hasProcessedFrame Switch to 1D color palette HierarchyFolderIcon.IconColors : Color[] pre-tinted variants _openVariants/_closedVariants GetIcons(storedIndex, out openTex, out closedTex) maps 0=default, 1..N=colors[i-1] Update InitIfNeeded() cache only GetAllSceneHierarchyWindows() and sceneHierarchy property support moved types (UnityEditor.SceneHierarchy or UnityEditor.IMGUI.Controls.SceneHierarchy) Add ForceRepaint() and ResetFolderIcons() load default folder icons rebuild tinted variants on demand force hierarchy repaint after changes Fix FolderEditor use actual serialized field "_colorIndex" UI is 0-based, storage is 1-based (_colorIndex = popup + 1) clamp index and show color preview Align Folder.TryGetIconIndex() return false if _colorIndex == 0, else index = 1..N expected by GetIcons() clamp against HierarchyFolderIcon.IconColors.Length Cleanup remove old 2D palette logic, tuples, and obsolete caches remove eager binds for treeView/data/selectedIcon/objectPPTR add helpers GetPropertyByName and GetPropertyExact Result: no lag or AmbiguousMatchException on Unity 6.3, colored folder icons apply correctly, inspector changes update the hierarchy immediately. --- Editor/FolderEditor.cs | 80 ++--- Editor/Icon Handling/HierarchyFolderIcon.cs | 342 ++++++++++++++------ 2 files changed, 274 insertions(+), 148 deletions(-) diff --git a/Editor/FolderEditor.cs b/Editor/FolderEditor.cs index fa4e3f2..e389c0e 100644 --- a/Editor/FolderEditor.cs +++ b/Editor/FolderEditor.cs @@ -1,4 +1,5 @@ #if UNITY_2019_1_OR_NEWER +using System.Linq; using UnityEditor; using UnityEngine; using UnityHierarchyFolders.Runtime; @@ -10,68 +11,55 @@ public class FolderEditor : UnityEditor.Editor { private bool _expanded = false; + + static readonly string[] s_DefaultIconColorNames = + new[] { "Default", "Yellow", "Blue", "Green", "Red" }; + public override bool RequiresConstantRepaint() => true; public override void OnInspectorGUI() { this._expanded = EditorGUILayout.Foldout(this._expanded, "Icon Color", true); if (this._expanded) { this.RenderColorPicker(); } } - - private void RenderColorPicker() + void RenderColorPicker() { - var colorIndexProperty = this.serializedObject.FindProperty("_colorIndex"); - - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); + serializedObject.Update(); - float buttonSize = 25f; + var colors = HierarchyFolderIcon.IconColors; + var names = s_DefaultIconColorNames; + if (names == null || names.Length != colors.Length) + names = Enumerable.Range(0, colors.Length).Select(i => $"Color {i}").ToArray(); - var gridRect = EditorGUILayout.GetControlRect(false, buttonSize * HierarchyFolderIcon.IconRowCount, - GUILayout.Width(buttonSize * HierarchyFolderIcon.IconColumnCount)); - - int currentIndex = colorIndexProperty.intValue; - for (int row = 0; row < HierarchyFolderIcon.IconRowCount; row++) + // Use the actual backing field name + var pIndex = serializedObject.FindProperty("_colorIndex"); + if (pIndex == null) { - for (int column = 0; column < HierarchyFolderIcon.IconColumnCount; column++) - { - int index = 1 + column + row * HierarchyFolderIcon.IconColumnCount; - float width = gridRect.width / HierarchyFolderIcon.IconColumnCount; - float height = gridRect.height / HierarchyFolderIcon.IconRowCount; - var rect = new Rect(gridRect.x + width * column, gridRect.y + height * row, width, height); - (var openIcon, var closeIcon) = HierarchyFolderIcon.ColoredFolderIcons(index); + EditorGUILayout.HelpBox("Missing '_colorIndex' property.", MessageType.Warning); + serializedObject.ApplyModifiedProperties(); + return; + } - if (Event.current.type == EventType.Repaint) - { - if (index == currentIndex) - { - GUIStyle hover = "TV Selection"; - hover.Draw(rect, false, false, false, false); - } - else if (rect.Contains(Event.current.mousePosition)) - { - GUI.backgroundColor = new Color(.7f, .7f, .7f, 1f); - GUIStyle white = "WhiteBackground"; - white.Draw(rect, false, false, true, false); - GUI.backgroundColor = Color.white; - } - } + pIndex.intValue = Mathf.Clamp(pIndex.intValue, 0, colors.Length - 1); - if (GUI.Button(rect, currentIndex == index ? openIcon : closeIcon, EditorStyles.label)) - { - Undo.RecordObject(this.target, "Set Folder Color"); - colorIndexProperty.intValue = currentIndex == index ? 0 : index; - this.serializedObject.ApplyModifiedProperties(); - EditorApplication.RepaintHierarchyWindow(); - GUIUtility.ExitGUI(); - } - } + EditorGUI.BeginChangeCheck(); + int newIndex = EditorGUILayout.Popup("Folder Color", pIndex.intValue , names); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(target, "Change Folder Color"); + pIndex.intValue = newIndex; + serializedObject.ApplyModifiedProperties(); + EditorUtility.SetDirty(target); + // Force repaint so the icon updates immediately + HierarchyFolderIcon.ForceRepaint(); + return; // avoid drawing preview with stale value this frame } - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); + var previewRect = GUILayoutUtility.GetRect(18, 18, GUILayout.ExpandWidth(false)); + EditorGUI.DrawRect(previewRect, colors[pIndex.intValue]); - GUILayout.Space(10f); + serializedObject.ApplyModifiedProperties(); } + } } #endif \ No newline at end of file diff --git a/Editor/Icon Handling/HierarchyFolderIcon.cs b/Editor/Icon Handling/HierarchyFolderIcon.cs index 6286677..e6ef72c 100644 --- a/Editor/Icon Handling/HierarchyFolderIcon.cs +++ b/Editor/Icon Handling/HierarchyFolderIcon.cs @@ -1,13 +1,11 @@ -#if UNITY_2019_1_OR_NEWER +#if UNITY_2019_1_OR_NEWER using System; using System.Collections; -using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEditor; -using UnityEditor.IMGUI.Controls; using UnityEngine; -using UnityHierarchyFolders.Runtime; +using UnityHierarchyFolders.Runtime; // Folder.TryGetIconIndex using Object = UnityEngine.Object; namespace UnityHierarchyFolders.Editor @@ -21,152 +19,292 @@ public static class HierarchyFolderIcon #endif private const string _closedFolderPrefix = "Folder"; + // ===== Palette 1D ===== + // Indexing convention used here: + // - storedIndex == 0 => default (no color) + // - storedIndex 1..N => colors[storedIndex - 1] + public static readonly Color[] IconColors = + { + new Color(0.91f, 0.91f, 0.91f), // Gray + new Color(0.98f, 0.80f, 0.27f), // Yellow + new Color(0.50f, 0.79f, 0.98f), // Blue + new Color(0.63f, 0.90f, 0.68f), // Green + new Color(0.96f, 0.62f, 0.62f), // Red + }; + public static int IconCount => IconColors.Length; + + // ===== State ===== private static Texture2D _openFolderTexture; private static Texture2D _closedFolderTexture; private static Texture2D _openFolderSelectedTexture; private static Texture2D _closedFolderSelectedTexture; + // Pre-tinted variants (length == IconCount) + static Texture2D[] _openVariants; + static Texture2D[] _closedVariants; + private static bool _isInitialized; private static bool _hasProcessedFrame = true; - // Reflected members - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Special naming scheme")] - private static PropertyInfo prop_sceneHierarchy; - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Special naming scheme")] - private static PropertyInfo prop_treeView; - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Special naming scheme")] - private static PropertyInfo prop_data; - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Special naming scheme")] - private static PropertyInfo prop_selectedIcon; - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Special naming scheme")] - private static PropertyInfo prop_objectPPTR; - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Special naming scheme")] - private static MethodInfo meth_getRows; - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Special naming scheme")] - private static MethodInfo meth_isExpanded; - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Special naming scheme")] + // Reflected members we actually need private static MethodInfo meth_getAllSceneHierarchyWindows; + private static PropertyInfo prop_sceneHierarchy; - private static (Texture2D open, Texture2D closed)[] _coloredFolderIcons; - public static (Texture2D open, Texture2D closed) ColoredFolderIcons(int i) => _coloredFolderIcons[i]; - - public static int IconColumnCount => IconColors.GetLength(0); - public static int IconRowCount => IconColors.GetLength(1); - - private static readonly Color[,] IconColors = { - {new Color(0.09f, 0.57f, 0.82f), new Color(0.05f, 0.34f, 0.48f),}, - {new Color(0.09f, 0.67f, 0.67f), new Color(0.05f, 0.42f, 0.42f),}, - {new Color(0.23f, 0.73f, 0.36f), new Color(0.15f, 0.41f, 0.22f),}, - {new Color(0.55f, 0.35f, 0.71f), new Color(0.35f, 0.24f, 0.44f),}, - {new Color(0.78f, 0.27f, 0.55f), new Color(0.52f, 0.15f, 0.35f),}, - {new Color(0.80f, 0.66f, 0.10f), new Color(0.56f, 0.46f, 0.02f),}, - {new Color(0.91f, 0.49f, 0.13f), new Color(0.62f, 0.33f, 0.07f),}, - {new Color(0.91f, 0.30f, 0.24f), new Color(0.77f, 0.15f, 0.09f),}, - {new Color(0.35f, 0.49f, 0.63f), new Color(0.24f, 0.33f, 0.42f),}, - }; + // Common flags + const BindingFlags F = + BindingFlags.Instance | BindingFlags.Static | + BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.FlattenHierarchy; - [InitializeOnLoadMethod] - private static void Startup() + // ===== Helpers ===== + static PropertyInfo GetPropertyExact(Type type, string name, BindingFlags flags, Type returnType) { - EditorApplication.update += ResetFolderIcons; - EditorApplication.hierarchyWindowItemOnGUI += RefreshFolderIcons; + var pi = type.GetProperty(name, flags, null, returnType, Type.EmptyTypes, null); + if (pi != null) return pi; + + return type.GetProperties(flags) + .FirstOrDefault(p => p.Name == name && + p.PropertyType == returnType && + p.GetIndexParameters().Length == 0); } - private static void InitIfNeeded() + static PropertyInfo GetPropertyByName(Type t, string name, BindingFlags flags) { - if (_isInitialized) { return; } + return t.GetProperties(flags) + .FirstOrDefault(p => p.Name == name && p.GetIndexParameters().Length == 0); + } - _openFolderTexture = (Texture2D)EditorGUIUtility.IconContent($"{_openedFolderPrefix} Icon").image; - _closedFolderTexture = (Texture2D)EditorGUIUtility.IconContent($"{_closedFolderPrefix} Icon").image; + // Cheap CPU tint; builds readable textures once + static Texture2D Tint(Texture2D src, Color tint) + { + if (src == null) return null; + var w = src.width; var h = src.height; + var tex = new Texture2D(w, h, TextureFormat.RGBA32, false) + { + filterMode = src.filterMode, + wrapMode = src.wrapMode + }; + // Copy pixels + var tmp = RenderTexture.GetTemporary(w, h, 0, RenderTextureFormat.ARGB32); + Graphics.Blit(src, tmp); + var prev = RenderTexture.active; + RenderTexture.active = tmp; + tex.ReadPixels(new Rect(0, 0, w, h), 0, 0); + tex.Apply(false); + RenderTexture.active = prev; + RenderTexture.ReleaseTemporary(tmp); + + var px = tex.GetPixels32(); + // multiply RGB by tint, keep original alpha + byte tr = (byte)Mathf.RoundToInt(Mathf.Clamp01(tint.r) * 255f); + byte tg = (byte)Mathf.RoundToInt(Mathf.Clamp01(tint.g) * 255f); + byte tb = (byte)Mathf.RoundToInt(Mathf.Clamp01(tint.b) * 255f); + for (int i = 0; i < px.Length; i++) + { + var p = px[i]; + px[i] = new Color32( + (byte)(p.r * tr / 255), + (byte)(p.g * tg / 255), + (byte)(p.b * tb / 255), + p.a); + } + tex.SetPixels32(px); + tex.Apply(false); + tex.name = src.name + "_tinted"; + return tex; + } - // We could use the actual white folder icons but I prefer the look of the tinted white folder icon - // To use the actual white version: - // texture = (Texture2D) EditorGUIUtility.IconContent($"{OpenedFolderPrefix | ClosedFolderPrefix} On Icon").image; - _openFolderSelectedTexture = TextureHelper.GetWhiteTexture(_openFolderTexture, $"{_openedFolderPrefix} Icon White"); - _closedFolderSelectedTexture = TextureHelper.GetWhiteTexture(_closedFolderTexture, $"{_closedFolderPrefix} Icon White"); + static void EnsureVariantsBuilt() + { + if (_openVariants != null && _closedVariants != null) return; + if (_openFolderTexture == null || _closedFolderTexture == null) return; - _coloredFolderIcons = new (Texture2D, Texture2D)[] { (_openFolderTexture, _closedFolderTexture) }; + int n = IconCount; + _openVariants = new Texture2D[n]; + _closedVariants = new Texture2D[n]; - for (int row = 0; row < IconRowCount; row++) + for (int i = 0; i < n; i++) { - for (int column = 0; column < IconColumnCount; column++) - { - int index = 1 + column + row * IconColumnCount; - var color = IconColors[column, row]; + var c = IconColors[i]; + _openVariants[i] = Tint(_openFolderTexture, c); + _closedVariants[i] = Tint(_closedFolderTexture, c); + } + } - var openFolderIcon = TextureHelper.GetTintedTexture(_openFolderSelectedTexture, - color, $"{_openFolderSelectedTexture.name} {index}"); - var closedFolderIcon = TextureHelper.GetTintedTexture(_closedFolderSelectedTexture, - color, $"{_closedFolderSelectedTexture.name} {index}"); + // Map stored index to textures (0 = default, 1..N = colored) + static void GetIcons(int storedIndex, out Texture2D openTex, out Texture2D closedTex) + { + openTex = _openFolderTexture; + closedTex = _closedFolderTexture; - ArrayUtility.Add(ref _coloredFolderIcons, (openFolderIcon, closedFolderIcon)); - } - } + EnsureVariantsBuilt(); + if (_openVariants == null || _closedVariants == null) return; + + if (storedIndex <= 0) return; // default + int i = Mathf.Clamp(storedIndex - 1, 0, IconCount - 1); + if (_openVariants[i] != null) openTex = _openVariants[i]; + if (_closedVariants[i] != null) closedTex = _closedVariants[i]; + } - // reflection + // ===== Entry points ===== + [InitializeOnLoadMethod] + private static void Startup() + { + EditorApplication.update += ResetFolderIcons; + EditorApplication.hierarchyWindowItemOnGUI += RefreshFolderIcons; + } - const BindingFlags BindingAll = BindingFlags.Public - | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance; + public static void ForceRepaint() + { + InitIfNeeded(); + _hasProcessedFrame = false; + EditorApplication.RepaintHierarchyWindow(); + } - var assembly = typeof(SceneView).Assembly; + static void InitIfNeeded() + { + if (_isInitialized) return; - var type_sceneHierarchyWindow = assembly.GetType("UnityEditor.SceneHierarchyWindow"); - meth_getAllSceneHierarchyWindows = type_sceneHierarchyWindow.GetMethod("GetAllSceneHierarchyWindows", BindingAll); - prop_sceneHierarchy = type_sceneHierarchyWindow.GetProperty("sceneHierarchy"); + try + { + var unityEditorAsm = typeof(UnityEditor.Editor).Assembly; + var type_sceneHierarchyWindow = unityEditorAsm.GetType("UnityEditor.SceneHierarchyWindow"); + if (type_sceneHierarchyWindow == null) + { + _isInitialized = true; + return; + } - var type_sceneHierarchy = assembly.GetType("UnityEditor.SceneHierarchy"); - prop_treeView = type_sceneHierarchy.GetProperty("treeView", BindingAll); + // Exact 0-arg overload + meth_getAllSceneHierarchyWindows = + type_sceneHierarchyWindow.GetMethod("GetAllSceneHierarchyWindows", F, null, Type.EmptyTypes, null) + ?? type_sceneHierarchyWindow.GetMethods(F).FirstOrDefault(m => m.Name == "GetAllSceneHierarchyWindows" && m.GetParameters().Length == 0); - var type_treeViewController = assembly.GetType("UnityEditor.IMGUI.Controls.TreeViewController"); - prop_data = type_treeViewController.GetProperty("data", BindingAll); + var type_sceneHierarchy = + unityEditorAsm.GetType("UnityEditor.SceneHierarchy") + ?? unityEditorAsm.GetType("UnityEditor.IMGUI.Controls.SceneHierarchy"); - var type_iTreeViewDataSource = assembly.GetType("UnityEditor.IMGUI.Controls.ITreeViewDataSource"); - meth_getRows = type_iTreeViewDataSource.GetMethod("GetRows"); - meth_isExpanded = type_iTreeViewDataSource.GetMethod("IsExpanded", new Type[] { typeof(TreeViewItem) }); + prop_sceneHierarchy = (type_sceneHierarchy != null) + ? GetPropertyExact(type_sceneHierarchyWindow, "sceneHierarchy", F, type_sceneHierarchy) + : GetPropertyByName(type_sceneHierarchyWindow, "sceneHierarchy", F); - var type_gameObjectTreeViewItem = assembly.GetType("UnityEditor.GameObjectTreeViewItem"); - prop_selectedIcon = type_gameObjectTreeViewItem.GetProperty("selectedIcon", BindingAll); - prop_objectPPTR = type_gameObjectTreeViewItem.GetProperty("objectPPTR", BindingAll); + if (meth_getAllSceneHierarchyWindows == null || prop_sceneHierarchy == null) + { + _isInitialized = true; + return; + } - _isInitialized = true; + _isInitialized = true; + } + catch + { + _isInitialized = true; + } } private static void ResetFolderIcons() { InitIfNeeded(); + + if (_openFolderTexture == null || _closedFolderTexture == null) + { +#if UNITY_2020_1_OR_NEWER + _openFolderTexture = EditorGUIUtility.IconContent("FolderOpened Icon").image as Texture2D; +#else + _openFolderTexture = EditorGUIUtility.IconContent("OpenedFolder Icon").image as Texture2D; +#endif + _closedFolderTexture = EditorGUIUtility.IconContent("Folder Icon").image as Texture2D; + + _openFolderSelectedTexture = _openFolderTexture; + _closedFolderSelectedTexture = _closedFolderTexture; + + // Rebuild variants next time GetIcons is called + _openVariants = _closedVariants = null; + } + _hasProcessedFrame = false; } private static void RefreshFolderIcons(int instanceid, Rect selectionrect) { - if (_hasProcessedFrame) { return; } - + if (_hasProcessedFrame) return; _hasProcessedFrame = true; - var windows = ((IEnumerable)meth_getAllSceneHierarchyWindows.Invoke(null, Array.Empty())).Cast().ToList(); - foreach (var window in windows) + if (meth_getAllSceneHierarchyWindows == null || prop_sceneHierarchy == null) + return; + + try { - object sceneHierarchy = prop_sceneHierarchy.GetValue(window); - object treeView = prop_treeView.GetValue(sceneHierarchy); - object data = prop_data.GetValue(treeView); + var windowsObj = meth_getAllSceneHierarchyWindows.Invoke(null, Array.Empty()); + if (windowsObj is not IEnumerable windows) return; - var rows = (IList)meth_getRows.Invoke(data, Array.Empty()); - foreach (var item in rows) + foreach (var w in windows) { - var itemObject = (Object)prop_objectPPTR.GetValue(item); - if (!Folder.TryGetIconIndex(itemObject, out int colorIndex)) { continue; } - - bool isExpanded = (bool)meth_isExpanded.Invoke(data, new object[] { item }); - - var icons = ColoredFolderIcons(Mathf.Clamp(colorIndex, 0, _coloredFolderIcons.Length - 1)); - - item.icon = isExpanded ? icons.open : icons.closed; - - prop_selectedIcon.SetValue(item, isExpanded ? _openFolderSelectedTexture : _closedFolderSelectedTexture); + if (w is not EditorWindow window) continue; + + var sceneHierarchy = prop_sceneHierarchy.GetValue(window); + if (sceneHierarchy == null) continue; + + // Resolve from instances (generic-safe) + var shType = sceneHierarchy.GetType(); + var piTree = GetPropertyByName(shType, "treeView", F); + var treeView = piTree?.GetValue(sceneHierarchy); + if (treeView == null) continue; + + var tvType = treeView.GetType(); + var piData = GetPropertyByName(tvType, "data", F); + var data = piData?.GetValue(treeView); + if (data == null) continue; + + var dataType = data.GetType(); + var miGetRows = dataType.GetMethod("GetRows", F, null, Type.EmptyTypes, null) + ?? dataType.GetMethods(F).FirstOrDefault(m => m.Name == "GetRows" && m.GetParameters().Length == 0); + if (miGetRows == null) continue; + + var miIsExpanded = dataType.GetMethods(F).FirstOrDefault(m => m.Name == "IsExpanded" && m.GetParameters().Length == 1); + + var rowsObj = miGetRows.Invoke(data, Array.Empty()) as IEnumerable; + if (rowsObj == null) continue; + + foreach (var item in rowsObj) + { + if (item == null) continue; + var itemType = item.GetType(); + + var piObject = GetPropertyExact(itemType, "objectPPTR", F, typeof(Object)) + ?? GetPropertyByName(itemType, "objectPPTR", F); + var itemObject = (Object)piObject?.GetValue(item); + if (itemObject == null) continue; + + if (!Folder.TryGetIconIndex(itemObject, out int colorIndex)) + continue; // no colored icon requested + + bool isExpanded = false; + if (miIsExpanded != null) + { + try { isExpanded = (bool)miIsExpanded.Invoke(data, new object[] { item }); } + catch { isExpanded = false; } + } + + GetIcons(colorIndex+1, out var openTex, out var closedTex); + + var piIcon = GetPropertyExact(itemType, "icon", F, typeof(Texture2D)) + ?? GetPropertyByName(itemType, "icon", F); + if (piIcon != null) + piIcon.SetValue(item, isExpanded ? openTex : closedTex); + + var piSelIcon = GetPropertyExact(itemType, "selectedIcon", F, typeof(Texture2D)) + ?? GetPropertyByName(itemType, "selectedIcon", F); + if (piSelIcon != null) + piSelIcon.SetValue(item, isExpanded ? _openFolderSelectedTexture : _closedFolderSelectedTexture); + } } } + catch + { + // swallow to avoid IMGUI clip imbalance + } } } } -#endif \ No newline at end of file +#endif From 5b2298123b45781708902cf94f3677181e9906de Mon Sep 17 00:00:00 2001 From: HugoKostic Date: Wed, 15 Oct 2025 15:46:18 +0200 Subject: [PATCH 2/2] Remove constant update using _hasProcessedFrame --- Editor/Icon Handling/HierarchyFolderIcon.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Editor/Icon Handling/HierarchyFolderIcon.cs b/Editor/Icon Handling/HierarchyFolderIcon.cs index e6ef72c..eb3093e 100644 --- a/Editor/Icon Handling/HierarchyFolderIcon.cs +++ b/Editor/Icon Handling/HierarchyFolderIcon.cs @@ -157,7 +157,6 @@ private static void Startup() public static void ForceRepaint() { InitIfNeeded(); - _hasProcessedFrame = false; EditorApplication.RepaintHierarchyWindow(); } @@ -222,13 +221,10 @@ private static void ResetFolderIcons() _openVariants = _closedVariants = null; } - _hasProcessedFrame = false; } private static void RefreshFolderIcons(int instanceid, Rect selectionrect) { - if (_hasProcessedFrame) return; - _hasProcessedFrame = true; if (meth_getAllSceneHierarchyWindows == null || prop_sceneHierarchy == null) return;