@mflrevan/ucp 0.5.1 → 0.6.0
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/README.md +1 -1
- package/bridge/com.ucp.bridge/Editor/AssemblyInfo.cs +3 -0
- package/bridge/com.ucp.bridge/Editor/AssemblyInfo.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Bridge/BridgeServer.cs +16 -3
- package/bridge/com.ucp.bridge/Editor/Compatibility/UnityObjectCompat.cs +26 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/AssetController.cs +172 -2
- package/bridge/com.ucp.bridge/Editor/Controllers/CompilationController.cs +88 -1
- package/bridge/com.ucp.bridge/Editor/Controllers/EditorModalGuard.cs +60 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/EditorModalGuard.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/HierarchyController.cs +56 -5
- package/bridge/com.ucp.bridge/Editor/Controllers/LogsController.cs +325 -13
- package/bridge/com.ucp.bridge/Editor/Controllers/MaterialController.cs +2 -2
- package/bridge/com.ucp.bridge/Editor/Controllers/ObjectLocator.cs +207 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ObjectLocator.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ObjectReferenceResolver.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/Controllers/PlayModeController.cs +14 -35
- package/bridge/com.ucp.bridge/Editor/Controllers/PrefabController.cs +3 -3
- package/bridge/com.ucp.bridge/Editor/Controllers/PropertyController.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/Controllers/ReferenceController.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/Controllers/SceneChangeTracker.cs +6 -6
- package/bridge/com.ucp.bridge/Editor/Controllers/SceneController.cs +2 -34
- package/bridge/com.ucp.bridge/Editor/Controllers/ShaderController.cs +151 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ShaderController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/SnapshotController.cs +304 -9
- package/bridge/com.ucp.bridge/Editor/Controllers/SpatialController.cs +322 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/SpatialController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/TransformController.cs +249 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/TransformController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ViewController.cs +415 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ViewController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Tests/Editor/ControllerSmokeTests.cs +135 -7
- package/bridge/com.ucp.bridge/Tests/Editor/SpatialVisualControllerTests.cs +252 -0
- package/bridge/com.ucp.bridge/Tests/Editor/SpatialVisualControllerTests.cs.meta +2 -0
- package/bridge/com.ucp.bridge/package.json +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
using UnityEditor;
|
|
2
|
-
using UnityEditor.SceneManagement;
|
|
3
|
-
using UnityEngine.SceneManagement;
|
|
4
2
|
using System.Collections.Generic;
|
|
5
3
|
using System;
|
|
6
4
|
|
|
@@ -64,7 +62,10 @@ namespace UCP.Bridge
|
|
|
64
62
|
|
|
65
63
|
var saveDirtyScenes = GetBoolParam(paramsJson, "saveDirtyScenes", true);
|
|
66
64
|
var discardUntitled = GetBoolParam(paramsJson, "discardUntitled", true);
|
|
67
|
-
|
|
65
|
+
var logFile = GetStringParam(paramsJson, "logFile");
|
|
66
|
+
EditorModalGuard.SaveOpenDirtyScenes(saveDirtyScenes, discardUntitled);
|
|
67
|
+
if (!string.IsNullOrEmpty(logFile))
|
|
68
|
+
LogsController.StartFileCapture(logFile);
|
|
68
69
|
|
|
69
70
|
lock (s_sessionLock)
|
|
70
71
|
{
|
|
@@ -88,38 +89,6 @@ namespace UCP.Bridge
|
|
|
88
89
|
return defaultValue;
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
private static void SaveDirtyScenesIfRequested(bool saveDirtyScenes, bool discardUntitled)
|
|
92
|
-
{
|
|
93
|
-
if (!saveDirtyScenes)
|
|
94
|
-
return;
|
|
95
|
-
|
|
96
|
-
var requiresUntitledDiscard = false;
|
|
97
|
-
|
|
98
|
-
for (var index = 0; index < SceneManager.sceneCount; index++)
|
|
99
|
-
{
|
|
100
|
-
var scene = SceneManager.GetSceneAt(index);
|
|
101
|
-
if (!scene.isLoaded || !scene.isDirty)
|
|
102
|
-
continue;
|
|
103
|
-
|
|
104
|
-
if (string.IsNullOrEmpty(scene.path))
|
|
105
|
-
{
|
|
106
|
-
if (!discardUntitled)
|
|
107
|
-
throw new System.InvalidOperationException("Dirty untitled scene cannot be auto-saved. Retry with discardUntitled=true.");
|
|
108
|
-
|
|
109
|
-
requiresUntitledDiscard = true;
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (!EditorSceneManager.SaveScene(scene))
|
|
114
|
-
throw new System.InvalidOperationException($"Failed to auto-save dirty scene: {scene.path}");
|
|
115
|
-
|
|
116
|
-
SceneChangeTracker.ClearScene(scene);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (requiresUntitledDiscard)
|
|
120
|
-
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
92
|
private static object HandleStop(string paramsJson)
|
|
124
93
|
{
|
|
125
94
|
if (!EditorApplication.isPlaying)
|
|
@@ -151,11 +120,21 @@ namespace UCP.Bridge
|
|
|
151
120
|
break;
|
|
152
121
|
case PlayModeStateChange.EnteredEditMode:
|
|
153
122
|
s_lastExitedPlayAtUtc = DateTime.UtcNow;
|
|
123
|
+
LogsController.StopFileCapture();
|
|
154
124
|
break;
|
|
155
125
|
}
|
|
156
126
|
}
|
|
157
127
|
}
|
|
158
128
|
|
|
129
|
+
private static string GetStringParam(string paramsJson, string key)
|
|
130
|
+
{
|
|
131
|
+
var parameters = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
|
|
132
|
+
if (parameters != null && parameters.TryGetValue(key, out var valueObj) && valueObj != null)
|
|
133
|
+
return valueObj.ToString();
|
|
134
|
+
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
159
138
|
private static object SerializeSessionSnapshot(SessionSnapshot snapshot)
|
|
160
139
|
{
|
|
161
140
|
var now = DateTime.UtcNow;
|
|
@@ -179,8 +179,8 @@ namespace UCP.Bridge
|
|
|
179
179
|
["status"] = "ok",
|
|
180
180
|
["path"] = savePath,
|
|
181
181
|
["name"] = prefab.name,
|
|
182
|
-
["instanceId"] = prefab.
|
|
183
|
-
["sceneInstanceId"] = go.
|
|
182
|
+
["instanceId"] = prefab.GetId(),
|
|
183
|
+
["sceneInstanceId"] = go.GetId(),
|
|
184
184
|
["isPrefabInstance"] = PrefabUtility.IsPartOfPrefabInstance(go)
|
|
185
185
|
};
|
|
186
186
|
}
|
|
@@ -221,7 +221,7 @@ namespace UCP.Bridge
|
|
|
221
221
|
added.Add(new Dictionary<string, object>
|
|
222
222
|
{
|
|
223
223
|
["component"] = ac.instanceComponent.GetType().Name,
|
|
224
|
-
["instanceId"] = ac.instanceComponent.
|
|
224
|
+
["instanceId"] = ac.instanceComponent.GetId()
|
|
225
225
|
});
|
|
226
226
|
}
|
|
227
227
|
|
|
@@ -538,7 +538,7 @@ namespace UCP.Bridge
|
|
|
538
538
|
|
|
539
539
|
private static GameObject FindInHierarchy(GameObject go, int instanceId)
|
|
540
540
|
{
|
|
541
|
-
if (go.
|
|
541
|
+
if (go.GetId() == instanceId) return go;
|
|
542
542
|
for (int i = 0; i < go.transform.childCount; i++)
|
|
543
543
|
{
|
|
544
544
|
var found = FindInHierarchy(go.transform.GetChild(i).gameObject, instanceId);
|
|
@@ -31,7 +31,7 @@ namespace UCP.Bridge
|
|
|
31
31
|
{
|
|
32
32
|
{ "serializationMode", mode },
|
|
33
33
|
{ "forceText", mode == 2 },
|
|
34
|
-
{ "visibleMetaFiles",
|
|
34
|
+
{ "visibleMetaFiles", VersionControlSettings.mode == "Visible Meta Files" }
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
finally
|
|
@@ -17,7 +17,7 @@ namespace UCP.Bridge
|
|
|
17
17
|
public HashSet<string> Components = new();
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
private static readonly Dictionary<
|
|
20
|
+
private static readonly Dictionary<long, Dictionary<string, TrackedSceneChange>> s_changesByScene = new();
|
|
21
21
|
|
|
22
22
|
static SceneChangeTracker()
|
|
23
23
|
{
|
|
@@ -33,7 +33,7 @@ namespace UCP.Bridge
|
|
|
33
33
|
if (gameObject == null)
|
|
34
34
|
return;
|
|
35
35
|
|
|
36
|
-
RecordSceneChange(gameObject.scene, gameObject.
|
|
36
|
+
RecordSceneChange(gameObject.scene, gameObject.GetId(), gameObject.name, componentName);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
public static void RecordDeletedObject(Scene scene, int instanceId, string name, string componentName)
|
|
@@ -56,7 +56,7 @@ namespace UCP.Bridge
|
|
|
56
56
|
var modifications = new List<object>();
|
|
57
57
|
var omittedCount = 0;
|
|
58
58
|
|
|
59
|
-
if (scene.IsValid() && s_changesByScene.TryGetValue(scene
|
|
59
|
+
if (scene.IsValid() && s_changesByScene.TryGetValue(UnityObjectCompat.GetSceneHandle(scene), out var trackedChanges))
|
|
60
60
|
{
|
|
61
61
|
var ordered = trackedChanges.Values
|
|
62
62
|
.OrderBy(change => change.InstanceId.HasValue ? 0 : 1)
|
|
@@ -101,7 +101,7 @@ namespace UCP.Bridge
|
|
|
101
101
|
if (!scene.IsValid())
|
|
102
102
|
return;
|
|
103
103
|
|
|
104
|
-
s_changesByScene.Remove(scene
|
|
104
|
+
s_changesByScene.Remove(UnityObjectCompat.GetSceneHandle(scene));
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
private static UndoPropertyModification[] OnPostprocessModifications(UndoPropertyModification[] modifications)
|
|
@@ -140,10 +140,10 @@ namespace UCP.Bridge
|
|
|
140
140
|
if (!scene.IsValid() || !scene.isLoaded)
|
|
141
141
|
return;
|
|
142
142
|
|
|
143
|
-
if (!s_changesByScene.TryGetValue(scene
|
|
143
|
+
if (!s_changesByScene.TryGetValue(UnityObjectCompat.GetSceneHandle(scene), out var sceneChanges))
|
|
144
144
|
{
|
|
145
145
|
sceneChanges = new Dictionary<string, TrackedSceneChange>();
|
|
146
|
-
s_changesByScene[scene
|
|
146
|
+
s_changesByScene[UnityObjectCompat.GetSceneHandle(scene)] = sceneChanges;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
var key = instanceId.HasValue ? instanceId.Value.ToString() : $"scene::{name}";
|
|
@@ -54,7 +54,7 @@ namespace UCP.Bridge
|
|
|
54
54
|
}
|
|
55
55
|
else
|
|
56
56
|
{
|
|
57
|
-
|
|
57
|
+
EditorModalGuard.SaveOpenDirtyScenes(saveDirtyScenes, discardUntitled);
|
|
58
58
|
EditorSceneManager.OpenScene(path, additive ? OpenSceneMode.Additive : OpenSceneMode.Single);
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -74,38 +74,6 @@ namespace UCP.Bridge
|
|
|
74
74
|
return defaultValue;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
private static void SaveDirtyScenesIfRequested(bool saveDirtyScenes, bool discardUntitled)
|
|
78
|
-
{
|
|
79
|
-
if (!saveDirtyScenes)
|
|
80
|
-
return;
|
|
81
|
-
|
|
82
|
-
var requiresUntitledDiscard = false;
|
|
83
|
-
|
|
84
|
-
for (var index = 0; index < SceneManager.sceneCount; index++)
|
|
85
|
-
{
|
|
86
|
-
var scene = SceneManager.GetSceneAt(index);
|
|
87
|
-
if (!scene.isLoaded || !scene.isDirty)
|
|
88
|
-
continue;
|
|
89
|
-
|
|
90
|
-
if (string.IsNullOrEmpty(scene.path))
|
|
91
|
-
{
|
|
92
|
-
if (!discardUntitled)
|
|
93
|
-
throw new System.InvalidOperationException("Dirty untitled scene cannot be auto-saved. Retry with discardUntitled=true.");
|
|
94
|
-
|
|
95
|
-
requiresUntitledDiscard = true;
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (!EditorSceneManager.SaveScene(scene))
|
|
100
|
-
throw new System.InvalidOperationException($"Failed to auto-save dirty scene: {scene.path}");
|
|
101
|
-
|
|
102
|
-
SceneChangeTracker.ClearScene(scene);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (requiresUntitledDiscard)
|
|
106
|
-
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
77
|
private static object HandleSaveActive(string paramsJson)
|
|
110
78
|
{
|
|
111
79
|
var scene = SceneManager.GetActiveScene();
|
|
@@ -302,7 +270,7 @@ namespace UCP.Bridge
|
|
|
302
270
|
|
|
303
271
|
private static GameObject FindInHierarchy(GameObject gameObject, int instanceId)
|
|
304
272
|
{
|
|
305
|
-
if (gameObject.
|
|
273
|
+
if (gameObject.GetId() == instanceId)
|
|
306
274
|
return gameObject;
|
|
307
275
|
|
|
308
276
|
foreach (Transform child in gameObject.transform)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Reflection;
|
|
4
|
+
using UnityEditor;
|
|
5
|
+
using UnityEngine;
|
|
6
|
+
|
|
7
|
+
namespace UCP.Bridge
|
|
8
|
+
{
|
|
9
|
+
public static class ShaderController
|
|
10
|
+
{
|
|
11
|
+
public static void Register(CommandRouter router)
|
|
12
|
+
{
|
|
13
|
+
router.Register("shader/errors", HandleErrors);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
private static object HandleErrors(string paramsJson)
|
|
17
|
+
{
|
|
18
|
+
var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
|
|
19
|
+
var errorsOnly = p != null && p.TryGetValue("errorsOnly", out var errorsOnlyObj) && errorsOnlyObj != null && Convert.ToBoolean(errorsOnlyObj);
|
|
20
|
+
var filter = p != null && p.TryGetValue("filter", out var filterObj) && filterObj != null ? filterObj.ToString() : null;
|
|
21
|
+
|
|
22
|
+
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
|
|
23
|
+
|
|
24
|
+
var diagnostics = new List<object>();
|
|
25
|
+
var scanned = 0;
|
|
26
|
+
foreach (var guid in AssetDatabase.FindAssets("t:Shader"))
|
|
27
|
+
{
|
|
28
|
+
var path = AssetDatabase.GUIDToAssetPath(guid);
|
|
29
|
+
var shader = AssetDatabase.LoadAssetAtPath<Shader>(path);
|
|
30
|
+
if (shader == null)
|
|
31
|
+
continue;
|
|
32
|
+
if (!MatchesFilter(shader.name, path, filter))
|
|
33
|
+
continue;
|
|
34
|
+
|
|
35
|
+
scanned++;
|
|
36
|
+
foreach (var diagnostic in ReadShaderDiagnostics(shader, path, errorsOnly))
|
|
37
|
+
diagnostics.Add(diagnostic);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return new Dictionary<string, object>
|
|
41
|
+
{
|
|
42
|
+
["status"] = "ok",
|
|
43
|
+
["capability"] = FindShaderMessageMethod() != null ? "shader-messages" : "fallback",
|
|
44
|
+
["scanned"] = scanned,
|
|
45
|
+
["count"] = diagnostics.Count,
|
|
46
|
+
["diagnostics"] = diagnostics
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private static IEnumerable<object> ReadShaderDiagnostics(Shader shader, string path, bool errorsOnly)
|
|
51
|
+
{
|
|
52
|
+
var method = FindShaderMessageMethod();
|
|
53
|
+
if (method == null)
|
|
54
|
+
yield break;
|
|
55
|
+
|
|
56
|
+
var messages = method.Invoke(null, new object[] { shader }) as Array;
|
|
57
|
+
if (messages == null)
|
|
58
|
+
yield break;
|
|
59
|
+
|
|
60
|
+
foreach (var message in messages)
|
|
61
|
+
{
|
|
62
|
+
var isWarning = ReadBoolMember(message, "warning", "isWarning");
|
|
63
|
+
if (errorsOnly && isWarning)
|
|
64
|
+
continue;
|
|
65
|
+
|
|
66
|
+
yield return new Dictionary<string, object>
|
|
67
|
+
{
|
|
68
|
+
["shader"] = shader.name,
|
|
69
|
+
["path"] = path,
|
|
70
|
+
["severity"] = isWarning ? "warning" : "error",
|
|
71
|
+
["message"] = ReadStringMember(message, "message", "messageDetails"),
|
|
72
|
+
["line"] = ReadIntMember(message, "line"),
|
|
73
|
+
["platform"] = ReadStringMember(message, "platform"),
|
|
74
|
+
["file"] = ReadStringMember(message, "file")
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private static MethodInfo FindShaderMessageMethod()
|
|
80
|
+
{
|
|
81
|
+
var shaderUtil = typeof(Editor).Assembly.GetType("UnityEditor.ShaderUtil");
|
|
82
|
+
return FindShaderMethod(shaderUtil, "GetShaderMessages")
|
|
83
|
+
?? FindShaderMethod(shaderUtil, "GetShaderErrors");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private static MethodInfo FindShaderMethod(Type shaderUtil, string name)
|
|
87
|
+
{
|
|
88
|
+
if (shaderUtil == null)
|
|
89
|
+
return null;
|
|
90
|
+
|
|
91
|
+
foreach (var method in shaderUtil.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
|
|
92
|
+
{
|
|
93
|
+
if (method.Name != name)
|
|
94
|
+
continue;
|
|
95
|
+
var parameters = method.GetParameters();
|
|
96
|
+
if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Shader))
|
|
97
|
+
return method;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private static bool MatchesFilter(string shaderName, string path, string filter)
|
|
104
|
+
{
|
|
105
|
+
if (string.IsNullOrEmpty(filter))
|
|
106
|
+
return true;
|
|
107
|
+
return shaderName.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0
|
|
108
|
+
|| path.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private static string ReadStringMember(object target, params string[] names)
|
|
112
|
+
{
|
|
113
|
+
foreach (var name in names)
|
|
114
|
+
{
|
|
115
|
+
var value = ReadMember(target, name);
|
|
116
|
+
if (value != null)
|
|
117
|
+
return value.ToString();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return string.Empty;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private static int ReadIntMember(object target, string name)
|
|
124
|
+
{
|
|
125
|
+
var value = ReadMember(target, name);
|
|
126
|
+
return value != null ? Convert.ToInt32(value) : 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private static bool ReadBoolMember(object target, params string[] names)
|
|
130
|
+
{
|
|
131
|
+
foreach (var name in names)
|
|
132
|
+
{
|
|
133
|
+
var value = ReadMember(target, name);
|
|
134
|
+
if (value != null)
|
|
135
|
+
return Convert.ToBoolean(value);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private static object ReadMember(object target, string name)
|
|
142
|
+
{
|
|
143
|
+
var type = target.GetType();
|
|
144
|
+
var field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
145
|
+
if (field != null)
|
|
146
|
+
return field.GetValue(target);
|
|
147
|
+
var property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
148
|
+
return property?.GetValue(target);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|