com.soosvet_games.common_tools 1.1.7 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,7 @@
1
- using UnityEditor;
1
+ using System;
2
+ using System.Linq.Expressions;
3
+ using System.Reflection;
4
+ using UnityEditor;
2
5
  using UnityEngine;
3
6
 
4
7
  namespace SoosvetGames.CommonTools.Extensions.Editor
@@ -6,63 +9,164 @@ namespace SoosvetGames.CommonTools.Extensions.Editor
6
9
  [ InitializeOnLoad ]
7
10
  internal static class HierarchyActivationTool
8
11
  {
12
+ private static FieldInfo _callbackField;
13
+ private static Delegate _callback;
14
+
9
15
  static HierarchyActivationTool()
10
16
  {
11
- #if UNITY_6000_5_OR_NEWER
12
- EditorApplication.hierarchyWindowItemByEntityIdOnGUI -= HierarchyWindowOnGui;
13
- EditorApplication.hierarchyWindowItemByEntityIdOnGUI += HierarchyWindowOnGui;
14
- #else
15
- EditorApplication.hierarchyWindowItemOnGUI -= HierarchyWindowOnGui;
16
- EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowOnGui;
17
- #endif
18
- }
17
+ Install();
19
18
 
20
- #if UNITY_6000_5_OR_NEWER
19
+ AssemblyReloadEvents.beforeAssemblyReload += Uninstall;
20
+ }
21
21
 
22
- // Unity 6000.5+
23
- // ВАЖНО: здесь EntityId, никаких int / InstanceID.
24
- private static void HierarchyWindowOnGui(
25
- EntityId entityId,
26
- Rect selectionRect)
22
+ private static void Install()
27
23
  {
28
- GameObject obj =
29
- EditorUtility.EntityIdToObject(entityId) as GameObject;
24
+ const BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
30
25
 
31
- DrawToggle(obj, selectionRect);
32
- }
26
+ // Unity 6.5 / 6.6+
27
+ _callbackField = typeof(EditorApplication).GetField( "hierarchyWindowItemByEntityIdOnGUI", flags );
28
+
29
+ // Старые версии Unity
30
+ if ( _callbackField == null )
31
+ {
32
+ _callbackField = typeof(EditorApplication).GetField( "hierarchyWindowItemOnGUI", flags );
33
+ }
34
+
35
+ if ( _callbackField == null )
36
+ {
37
+ Debug.LogWarning( "[HierarchyActivationTool] " + "Hierarchy callback was not found." );
38
+
39
+ return;
40
+ }
41
+
42
+ Type delegateType = _callbackField.FieldType;
43
+
44
+ MethodInfo invokeMethod = delegateType.GetMethod( "Invoke" );
45
+
46
+ if ( invokeMethod == null )
47
+ return;
48
+
49
+ ParameterInfo[] parameters = invokeMethod.GetParameters();
50
+
51
+ if ( parameters.Length != 2 )
52
+ return;
53
+
54
+ Type idType = parameters[ 0 ].ParameterType;
55
+ Type rectType = parameters[ 1 ].ParameterType;
56
+
57
+ if ( rectType != typeof(Rect) )
58
+ return;
59
+
60
+ // В новой Unity это EntityIdToObject(EntityId).
61
+ // В старой — InstanceIDToObject(int).
62
+ string converterName = idType == typeof(int) ? "InstanceIDToObject" : "EntityIdToObject";
63
+
64
+ MethodInfo converterMethod = FindConverterMethod( converterName, idType );
65
+
66
+ if ( converterMethod == null )
67
+ {
68
+ Debug.LogWarning( $"[HierarchyActivationTool] " + $"{converterName} was not found." );
69
+
70
+ return;
71
+ }
72
+
73
+ /*
74
+ * Здесь динамически создаётся callback правильного типа:
75
+ *
76
+ * Старые Unity:
77
+ * (int instanceId, Rect rect)
78
+ *
79
+ * Новые Unity:
80
+ * (EntityId entityId, Rect rect)
81
+ *
82
+ * Поэтому EntityId вообще не фигурирует в исходном коде
83
+ * и старые Unity тоже могут его скомпилировать.
84
+ */
33
85
 
34
- #else
86
+ ParameterExpression idParameter = Expression.Parameter( idType, "id" );
35
87
 
36
- // Старые версии Unity
37
- private static void HierarchyWindowOnGui( int instanceId, Rect selectionRect )
88
+ ParameterExpression rectParameter = Expression.Parameter( typeof(Rect), "selectionRect" );
89
+
90
+ MethodCallExpression objectCall = Expression.Call( converterMethod, idParameter );
91
+
92
+ UnaryExpression gameObject = Expression.TypeAs( objectCall, typeof(GameObject) );
93
+
94
+ MethodInfo drawMethod = typeof(HierarchyActivationTool).GetMethod( nameof(DrawToggle), BindingFlags.NonPublic | BindingFlags.Static );
95
+
96
+ MethodCallExpression drawCall = Expression.Call( drawMethod, gameObject, rectParameter );
97
+
98
+ _callback = Expression.Lambda( delegateType, drawCall, idParameter, rectParameter ).Compile();
99
+
100
+ Delegate currentCallback = _callbackField.GetValue( null ) as Delegate;
101
+
102
+ Delegate newCallback = Delegate.Combine( currentCallback, _callback );
103
+
104
+ _callbackField.SetValue( null, newCallback );
105
+ }
106
+
107
+ private static MethodInfo FindConverterMethod( string methodName, Type idType )
38
108
  {
39
- GameObject obj = EditorUtility.InstanceIDToObject( instanceId ) as GameObject;
109
+ const BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
110
+
111
+ MethodInfo[] methods = typeof(EditorUtility).GetMethods( flags );
112
+
113
+ foreach ( MethodInfo method in methods )
114
+ {
115
+ if ( method.Name != methodName )
116
+ continue;
40
117
 
41
- DrawToggle( obj, selectionRect );
118
+ ParameterInfo[] parameters = method.GetParameters();
119
+
120
+ if ( parameters.Length != 1 )
121
+ continue;
122
+
123
+ if ( parameters[ 0 ].ParameterType != idType )
124
+ continue;
125
+
126
+ return method;
127
+ }
128
+
129
+ return null;
42
130
  }
43
131
 
44
- #endif
132
+ private static void Uninstall()
133
+ {
134
+ if ( _callbackField == null || _callback == null )
135
+ {
136
+ return;
137
+ }
138
+
139
+ Delegate currentCallback = _callbackField.GetValue( null ) as Delegate;
140
+
141
+ Delegate newCallback = Delegate.Remove( currentCallback, _callback );
142
+
143
+ _callbackField.SetValue( null, newCallback );
144
+
145
+ _callback = null;
146
+ }
45
147
 
46
148
  private static void DrawToggle( GameObject obj, Rect selectionRect )
47
149
  {
48
150
  if ( obj == null )
49
151
  return;
50
152
 
51
- // Располагаем toggle относительно объекта,
52
- // а не по абсолютному x = 35.
53
- Rect toggleRect = new Rect( selectionRect.x - 18f, selectionRect.y, 16f, selectionRect.height );
153
+ // Сохраняем расположение как в твоём
154
+ // оригинальном инструменте.
155
+ Rect rect = new Rect( selectionRect ) { x = 35, width = 18 };
54
156
 
55
157
  bool previousValue = obj.activeSelf;
56
158
 
57
- bool newValue = GUI.Toggle( toggleRect, previousValue, GUIContent.none );
159
+ bool newValue = GUI.Toggle( rect, previousValue, GUIContent.none );
58
160
 
59
161
  if ( newValue == previousValue )
60
162
  return;
61
163
 
62
- Undo.RecordObject( obj, newValue ? $"Activate {obj.name}" : $"Deactivate {obj.name}" );
164
+ Undo.RecordObject( obj, $"Set Active {obj.name}" );
63
165
 
64
166
  obj.SetActive( newValue );
65
167
 
168
+ EditorUtility.SetDirty( obj );
169
+
66
170
  EditorApplication.RepaintHierarchyWindow();
67
171
  }
68
172
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name" : "com.soosvet_games.common_tools",
3
3
  "displayName" : "Soosvet Games Common Tools",
4
- "version" : "1.1.7",
4
+ "version" : "1.1.8",
5
5
  "author" : "Soosvet Games",
6
6
  "description" : "Common tools for Unity.",
7
7
  "repository": {