@mflrevan/ucp 0.4.5 → 0.4.6
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/Bridge/BridgeServer.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/Compatibility/UnityObjectCompat.cs +18 -0
- package/bridge/com.ucp.bridge/Editor/Compatibility/UnityObjectCompat.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Compatibility.meta +8 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/HierarchyController.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/Controllers/MaterialController.cs +2 -2
- package/bridge/com.ucp.bridge/Editor/Controllers/ObjectReferenceResolver.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/Controllers/PrefabController.cs +6 -6
- package/bridge/com.ucp.bridge/Editor/Controllers/PropertyController.cs +49 -33
- package/bridge/com.ucp.bridge/Editor/Controllers/SceneController.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/Controllers/SnapshotController.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/UCP.Bridge.Editor.asmdef +3 -1
- package/bridge/com.ucp.bridge/Tests/Editor/ControllerSmokeTests.cs +2 -2
- package/bridge/com.ucp.bridge/package.json +4 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @mflrevan/ucp
|
|
2
2
|
|
|
3
|
-
Version `0.4.
|
|
3
|
+
Version `0.4.6` of the Unity Control Protocol CLI.
|
|
4
4
|
|
|
5
5
|
This package installs the `ucp` command, downloads the matching published binary for your platform during `postinstall`, and ships the matching Unity bridge payload inside the npm package.
|
|
6
6
|
|
|
@@ -26,7 +26,7 @@ namespace UCP.Bridge
|
|
|
26
26
|
private const int DefaultPort = 21342;
|
|
27
27
|
private const int MaxPort = 21352;
|
|
28
28
|
private const int MaxConnections = 4;
|
|
29
|
-
private const string ProtocolVersion = "0.4.
|
|
29
|
+
private const string ProtocolVersion = "0.4.6";
|
|
30
30
|
|
|
31
31
|
private static TcpListener s_listener;
|
|
32
32
|
private static CancellationTokenSource s_cts;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
using UnityEditor;
|
|
2
|
+
using UnityEngine;
|
|
3
|
+
|
|
4
|
+
namespace UCP.Bridge
|
|
5
|
+
{
|
|
6
|
+
internal static class UnityObjectCompat
|
|
7
|
+
{
|
|
8
|
+
public static Object ResolveByInstanceId(int instanceId)
|
|
9
|
+
{
|
|
10
|
+
return EditorUtility.InstanceIDToObject(instanceId);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public static T ResolveByInstanceId<T>(int instanceId) where T : Object
|
|
14
|
+
{
|
|
15
|
+
return ResolveByInstanceId(instanceId) as T;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -295,7 +295,7 @@ namespace UCP.Bridge
|
|
|
295
295
|
|
|
296
296
|
private static GameObject FindGameObject(int instanceId)
|
|
297
297
|
{
|
|
298
|
-
var obj =
|
|
298
|
+
var obj = UnityObjectCompat.ResolveByInstanceId<GameObject>(instanceId);
|
|
299
299
|
if (obj != null) return obj;
|
|
300
300
|
|
|
301
301
|
for (int i = 0; i < SceneManager.sceneCount; i++)
|
|
@@ -228,7 +228,7 @@ namespace UCP.Bridge
|
|
|
228
228
|
if (p.TryGetValue("instanceId", out var idObj))
|
|
229
229
|
{
|
|
230
230
|
int instanceId = Convert.ToInt32(idObj);
|
|
231
|
-
var obj =
|
|
231
|
+
var obj = UnityObjectCompat.ResolveByInstanceId(instanceId);
|
|
232
232
|
|
|
233
233
|
if (obj is Material directMat)
|
|
234
234
|
return directMat;
|
|
@@ -330,7 +330,7 @@ namespace UCP.Bridge
|
|
|
330
330
|
}
|
|
331
331
|
else if (texDict.TryGetValue("instanceId", out var tid))
|
|
332
332
|
{
|
|
333
|
-
var tex =
|
|
333
|
+
var tex = UnityObjectCompat.ResolveByInstanceId<Texture>(Convert.ToInt32(tid));
|
|
334
334
|
mat.SetTexture(propName, tex);
|
|
335
335
|
}
|
|
336
336
|
}
|
|
@@ -65,7 +65,7 @@ namespace UCP.Bridge
|
|
|
65
65
|
|
|
66
66
|
private static UnityEngine.Object ResolveByInstanceId(int instanceId, string propertyName)
|
|
67
67
|
{
|
|
68
|
-
var resolved =
|
|
68
|
+
var resolved = UnityObjectCompat.ResolveByInstanceId(instanceId);
|
|
69
69
|
if (resolved == null)
|
|
70
70
|
throw new ArgumentException($"Object reference for '{propertyName}' could not resolve instance id {instanceId}");
|
|
71
71
|
|
|
@@ -26,7 +26,7 @@ namespace UCP.Bridge
|
|
|
26
26
|
if (p == null || !p.TryGetValue("instanceId", out var idObj))
|
|
27
27
|
throw new ArgumentException("Missing 'instanceId' parameter");
|
|
28
28
|
|
|
29
|
-
var go =
|
|
29
|
+
var go = UnityObjectCompat.ResolveByInstanceId<GameObject>(Convert.ToInt32(idObj));
|
|
30
30
|
if (go == null)
|
|
31
31
|
throw new ArgumentException($"GameObject not found: {idObj}");
|
|
32
32
|
|
|
@@ -63,7 +63,7 @@ namespace UCP.Bridge
|
|
|
63
63
|
if (p == null || !p.TryGetValue("instanceId", out var idObj))
|
|
64
64
|
throw new ArgumentException("Missing 'instanceId' parameter");
|
|
65
65
|
|
|
66
|
-
var go =
|
|
66
|
+
var go = UnityObjectCompat.ResolveByInstanceId<GameObject>(Convert.ToInt32(idObj));
|
|
67
67
|
if (go == null)
|
|
68
68
|
throw new ArgumentException($"GameObject not found: {idObj}");
|
|
69
69
|
|
|
@@ -88,7 +88,7 @@ namespace UCP.Bridge
|
|
|
88
88
|
if (p == null || !p.TryGetValue("instanceId", out var idObj))
|
|
89
89
|
throw new ArgumentException("Missing 'instanceId' parameter");
|
|
90
90
|
|
|
91
|
-
var go =
|
|
91
|
+
var go = UnityObjectCompat.ResolveByInstanceId<GameObject>(Convert.ToInt32(idObj));
|
|
92
92
|
if (go == null)
|
|
93
93
|
throw new ArgumentException($"GameObject not found: {idObj}");
|
|
94
94
|
|
|
@@ -116,7 +116,7 @@ namespace UCP.Bridge
|
|
|
116
116
|
if (p.TryGetValue("completely", out var compObj))
|
|
117
117
|
completely = Convert.ToBoolean(compObj);
|
|
118
118
|
|
|
119
|
-
var go =
|
|
119
|
+
var go = UnityObjectCompat.ResolveByInstanceId<GameObject>(Convert.ToInt32(idObj));
|
|
120
120
|
if (go == null)
|
|
121
121
|
throw new ArgumentException($"GameObject not found: {idObj}");
|
|
122
122
|
|
|
@@ -147,7 +147,7 @@ namespace UCP.Bridge
|
|
|
147
147
|
if (!p.TryGetValue("path", out var pathObj))
|
|
148
148
|
throw new ArgumentException("Missing 'path' parameter");
|
|
149
149
|
|
|
150
|
-
var go =
|
|
150
|
+
var go = UnityObjectCompat.ResolveByInstanceId<GameObject>(Convert.ToInt32(idObj));
|
|
151
151
|
if (go == null)
|
|
152
152
|
throw new ArgumentException($"GameObject not found: {idObj}");
|
|
153
153
|
|
|
@@ -191,7 +191,7 @@ namespace UCP.Bridge
|
|
|
191
191
|
if (p == null || !p.TryGetValue("instanceId", out var idObj))
|
|
192
192
|
throw new ArgumentException("Missing 'instanceId' parameter");
|
|
193
193
|
|
|
194
|
-
var go =
|
|
194
|
+
var go = UnityObjectCompat.ResolveByInstanceId<GameObject>(Convert.ToInt32(idObj));
|
|
195
195
|
if (go == null)
|
|
196
196
|
throw new ArgumentException($"GameObject not found: {idObj}");
|
|
197
197
|
|
|
@@ -179,33 +179,40 @@ namespace UCP.Bridge
|
|
|
179
179
|
|
|
180
180
|
// Use SerializedObject for reliable Unity property enumeration
|
|
181
181
|
var so = new SerializedObject(comp);
|
|
182
|
-
|
|
183
|
-
if (prop.NextVisible(true))
|
|
182
|
+
try
|
|
184
183
|
{
|
|
185
|
-
|
|
184
|
+
so.Update();
|
|
185
|
+
var prop = so.GetIterator();
|
|
186
|
+
if (prop.NextVisible(true))
|
|
186
187
|
{
|
|
187
|
-
|
|
188
|
+
do
|
|
188
189
|
{
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
190
|
+
var fieldDict = new Dictionary<string, object>
|
|
191
|
+
{
|
|
192
|
+
["name"] = prop.name,
|
|
193
|
+
["displayName"] = prop.displayName,
|
|
194
|
+
["type"] = prop.propertyType.ToString(),
|
|
195
|
+
["editable"] = !prop.isReadOnly(true)
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
try
|
|
199
|
+
{
|
|
200
|
+
fieldDict["value"] = SerializedPropertyToValue(prop);
|
|
201
|
+
}
|
|
202
|
+
catch
|
|
203
|
+
{
|
|
204
|
+
fieldDict["value"] = "<unreadable>";
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
fields.Add(fieldDict);
|
|
202
208
|
}
|
|
203
|
-
|
|
204
|
-
fields.Add(fieldDict);
|
|
209
|
+
while (prop.NextVisible(false));
|
|
205
210
|
}
|
|
206
|
-
while (prop.NextVisible(false));
|
|
207
211
|
}
|
|
208
|
-
|
|
212
|
+
finally
|
|
213
|
+
{
|
|
214
|
+
so.Dispose();
|
|
215
|
+
}
|
|
209
216
|
|
|
210
217
|
return fields;
|
|
211
218
|
}
|
|
@@ -273,14 +280,17 @@ namespace UCP.Bridge
|
|
|
273
280
|
private static object GetPropertyValue(Component comp, string propertyName)
|
|
274
281
|
{
|
|
275
282
|
var so = new SerializedObject(comp);
|
|
276
|
-
|
|
277
|
-
|
|
283
|
+
try
|
|
284
|
+
{
|
|
285
|
+
so.Update();
|
|
286
|
+
var prop = so.FindProperty(propertyName);
|
|
287
|
+
if (prop != null)
|
|
288
|
+
return SerializedPropertyToValue(prop);
|
|
289
|
+
}
|
|
290
|
+
finally
|
|
278
291
|
{
|
|
279
|
-
var val = SerializedPropertyToValue(prop);
|
|
280
292
|
so.Dispose();
|
|
281
|
-
return val;
|
|
282
293
|
}
|
|
283
|
-
so.Dispose();
|
|
284
294
|
|
|
285
295
|
// Fallback to reflection
|
|
286
296
|
var type = comp.GetType();
|
|
@@ -298,15 +308,21 @@ namespace UCP.Bridge
|
|
|
298
308
|
private static void SetPropertyValue(Component comp, string propertyName, object jsonValue)
|
|
299
309
|
{
|
|
300
310
|
var so = new SerializedObject(comp);
|
|
301
|
-
|
|
302
|
-
|
|
311
|
+
try
|
|
312
|
+
{
|
|
313
|
+
so.Update();
|
|
314
|
+
var prop = so.FindProperty(propertyName);
|
|
315
|
+
if (prop != null)
|
|
316
|
+
{
|
|
317
|
+
SetSerializedPropertyValue(prop, jsonValue);
|
|
318
|
+
so.ApplyModifiedProperties();
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
finally
|
|
303
323
|
{
|
|
304
|
-
SetSerializedPropertyValue(prop, jsonValue);
|
|
305
|
-
so.ApplyModifiedProperties();
|
|
306
324
|
so.Dispose();
|
|
307
|
-
return;
|
|
308
325
|
}
|
|
309
|
-
so.Dispose();
|
|
310
326
|
|
|
311
327
|
// Fallback to reflection
|
|
312
328
|
var type = comp.GetType();
|
|
@@ -502,7 +518,7 @@ namespace UCP.Bridge
|
|
|
502
518
|
|
|
503
519
|
private static GameObject FindGameObject(int instanceId)
|
|
504
520
|
{
|
|
505
|
-
var obj =
|
|
521
|
+
var obj = UnityObjectCompat.ResolveByInstanceId<GameObject>(instanceId);
|
|
506
522
|
if (obj != null) return obj;
|
|
507
523
|
|
|
508
524
|
// Search in loaded scenes
|
|
@@ -273,7 +273,7 @@ namespace UCP.Bridge
|
|
|
273
273
|
|
|
274
274
|
private static GameObject FindGameObject(int instanceId)
|
|
275
275
|
{
|
|
276
|
-
var direct =
|
|
276
|
+
var direct = UnityObjectCompat.ResolveByInstanceId<GameObject>(instanceId);
|
|
277
277
|
if (direct != null)
|
|
278
278
|
return direct;
|
|
279
279
|
|
|
@@ -371,7 +371,7 @@ namespace UCP.Bridge.Tests
|
|
|
371
371
|
);
|
|
372
372
|
Assert.That(getPosition.error, Is.Null);
|
|
373
373
|
|
|
374
|
-
var updated = EditorUtility.
|
|
374
|
+
var updated = EditorUtility.InstanceIDToObject(instanceId) as GameObject;
|
|
375
375
|
Assert.That(updated, Is.Not.Null);
|
|
376
376
|
var localPosition = updated.transform.localPosition;
|
|
377
377
|
Assert.That(localPosition.x, Is.EqualTo(1f).Within(0.001f));
|
|
@@ -383,7 +383,7 @@ namespace UCP.Bridge.Tests
|
|
|
383
383
|
|
|
384
384
|
var delete = _router.Dispatch("object/delete", 1, "{\"instanceId\":" + instanceId + "}");
|
|
385
385
|
Assert.That(delete.error, Is.Null);
|
|
386
|
-
Assert.That(EditorUtility.
|
|
386
|
+
Assert.That(EditorUtility.InstanceIDToObject(instanceId), Is.Null);
|
|
387
387
|
}
|
|
388
388
|
|
|
389
389
|
[Test]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "com.ucp.bridge",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"displayName": "Unity Control Protocol Bridge",
|
|
5
5
|
"description": "WebSocket bridge for programmatic Unity Editor control via CLI and AI agents.",
|
|
6
6
|
"unity": "2021.3",
|
|
@@ -23,5 +23,7 @@
|
|
|
23
23
|
"type": "tool",
|
|
24
24
|
"documentationUrl": "https://github.com/mflRevan/unity-control-protocol/blob/main/README.md",
|
|
25
25
|
"changelogUrl": "https://github.com/mflRevan/unity-control-protocol/blob/main/unity-package/com.ucp.bridge/CHANGELOG.md",
|
|
26
|
-
"dependencies": {
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"com.unity.test-framework": "1.1.31"
|
|
28
|
+
}
|
|
27
29
|
}
|