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.
- package/Editor/HierarchyActivationTool.cs +134 -30
- package/package.json +1 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
using
|
|
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
|
-
|
|
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
|
-
|
|
19
|
+
AssemblyReloadEvents.beforeAssemblyReload += Uninstall;
|
|
20
|
+
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
// ВАЖНО: здесь EntityId, никаких int / InstanceID.
|
|
24
|
-
private static void HierarchyWindowOnGui(
|
|
25
|
-
EntityId entityId,
|
|
26
|
-
Rect selectionRect)
|
|
22
|
+
private static void Install()
|
|
27
23
|
{
|
|
28
|
-
|
|
29
|
-
EditorUtility.EntityIdToObject(entityId) as GameObject;
|
|
24
|
+
const BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
|
|
30
25
|
|
|
31
|
-
|
|
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
|
-
|
|
86
|
+
ParameterExpression idParameter = Expression.Parameter( idType, "id" );
|
|
35
87
|
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
52
|
-
//
|
|
53
|
-
Rect
|
|
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(
|
|
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,
|
|
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
|
}
|