@mflrevan/ucp 0.2.0 → 0.2.3

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.
Files changed (66) hide show
  1. package/README.md +3 -3
  2. package/bridge/com.ucp.bridge/CHANGELOG.md +56 -0
  3. package/bridge/com.ucp.bridge/CHANGELOG.md.meta +7 -0
  4. package/bridge/com.ucp.bridge/Editor/Bridge/BridgeServer.cs +573 -0
  5. package/bridge/com.ucp.bridge/Editor/Bridge/BridgeServer.cs.meta +2 -0
  6. package/bridge/com.ucp.bridge/Editor/Bridge.meta +8 -0
  7. package/bridge/com.ucp.bridge/Editor/Controllers/AssetController.cs +499 -0
  8. package/bridge/com.ucp.bridge/Editor/Controllers/AssetController.cs.meta +2 -0
  9. package/bridge/com.ucp.bridge/Editor/Controllers/BuildController.cs +230 -0
  10. package/bridge/com.ucp.bridge/Editor/Controllers/BuildController.cs.meta +2 -0
  11. package/bridge/com.ucp.bridge/Editor/Controllers/CompilationController.cs +26 -0
  12. package/bridge/com.ucp.bridge/Editor/Controllers/CompilationController.cs.meta +2 -0
  13. package/bridge/com.ucp.bridge/Editor/Controllers/EditorSettingsController.cs +435 -0
  14. package/bridge/com.ucp.bridge/Editor/Controllers/EditorSettingsController.cs.meta +2 -0
  15. package/bridge/com.ucp.bridge/Editor/Controllers/FileController.cs +130 -0
  16. package/bridge/com.ucp.bridge/Editor/Controllers/FileController.cs.meta +2 -0
  17. package/bridge/com.ucp.bridge/Editor/Controllers/HierarchyController.cs +319 -0
  18. package/bridge/com.ucp.bridge/Editor/Controllers/HierarchyController.cs.meta +2 -0
  19. package/bridge/com.ucp.bridge/Editor/Controllers/LogsController.cs +291 -0
  20. package/bridge/com.ucp.bridge/Editor/Controllers/LogsController.cs.meta +2 -0
  21. package/bridge/com.ucp.bridge/Editor/Controllers/MaterialController.cs +295 -0
  22. package/bridge/com.ucp.bridge/Editor/Controllers/MaterialController.cs.meta +2 -0
  23. package/bridge/com.ucp.bridge/Editor/Controllers/PlayModeController.cs +38 -0
  24. package/bridge/com.ucp.bridge/Editor/Controllers/PlayModeController.cs.meta +2 -0
  25. package/bridge/com.ucp.bridge/Editor/Controllers/PrefabController.cs +242 -0
  26. package/bridge/com.ucp.bridge/Editor/Controllers/PrefabController.cs.meta +2 -0
  27. package/bridge/com.ucp.bridge/Editor/Controllers/PropertyController.cs +551 -0
  28. package/bridge/com.ucp.bridge/Editor/Controllers/PropertyController.cs.meta +2 -0
  29. package/bridge/com.ucp.bridge/Editor/Controllers/SceneController.cs +70 -0
  30. package/bridge/com.ucp.bridge/Editor/Controllers/SceneController.cs.meta +2 -0
  31. package/bridge/com.ucp.bridge/Editor/Controllers/ScreenshotController.cs +125 -0
  32. package/bridge/com.ucp.bridge/Editor/Controllers/ScreenshotController.cs.meta +2 -0
  33. package/bridge/com.ucp.bridge/Editor/Controllers/ScriptController.cs +104 -0
  34. package/bridge/com.ucp.bridge/Editor/Controllers/ScriptController.cs.meta +2 -0
  35. package/bridge/com.ucp.bridge/Editor/Controllers/SnapshotController.cs +227 -0
  36. package/bridge/com.ucp.bridge/Editor/Controllers/SnapshotController.cs.meta +2 -0
  37. package/bridge/com.ucp.bridge/Editor/Controllers/TestRunnerController.cs +180 -0
  38. package/bridge/com.ucp.bridge/Editor/Controllers/TestRunnerController.cs.meta +2 -0
  39. package/bridge/com.ucp.bridge/Editor/Controllers/VcsController.cs +611 -0
  40. package/bridge/com.ucp.bridge/Editor/Controllers/VcsController.cs.meta +2 -0
  41. package/bridge/com.ucp.bridge/Editor/Controllers.meta +8 -0
  42. package/bridge/com.ucp.bridge/Editor/Protocol/CommandRouter.cs +45 -0
  43. package/bridge/com.ucp.bridge/Editor/Protocol/CommandRouter.cs.meta +2 -0
  44. package/bridge/com.ucp.bridge/Editor/Protocol/MessageTypes.cs +80 -0
  45. package/bridge/com.ucp.bridge/Editor/Protocol/MessageTypes.cs.meta +2 -0
  46. package/bridge/com.ucp.bridge/Editor/Protocol/MiniJson.cs +358 -0
  47. package/bridge/com.ucp.bridge/Editor/Protocol/MiniJson.cs.meta +2 -0
  48. package/bridge/com.ucp.bridge/Editor/Protocol.meta +8 -0
  49. package/bridge/com.ucp.bridge/Editor/Scripts/IUCPScript.cs +37 -0
  50. package/bridge/com.ucp.bridge/Editor/Scripts/IUCPScript.cs.meta +2 -0
  51. package/bridge/com.ucp.bridge/Editor/Scripts.meta +8 -0
  52. package/bridge/com.ucp.bridge/Editor/UCP.Bridge.Editor.asmdef +16 -0
  53. package/bridge/com.ucp.bridge/Editor/UCP.Bridge.Editor.asmdef.meta +7 -0
  54. package/bridge/com.ucp.bridge/Editor.meta +8 -0
  55. package/bridge/com.ucp.bridge/Runtime/UCP.Bridge.Runtime.asmdef +14 -0
  56. package/bridge/com.ucp.bridge/Runtime/UCP.Bridge.Runtime.asmdef.meta +7 -0
  57. package/bridge/com.ucp.bridge/Runtime.meta +8 -0
  58. package/bridge/com.ucp.bridge/Tests/Editor/ControllerSmokeTests.cs +194 -0
  59. package/bridge/com.ucp.bridge/Tests/Editor/ControllerSmokeTests.cs.meta +2 -0
  60. package/bridge/com.ucp.bridge/Tests/Editor/UCP.Bridge.Editor.Tests.asmdef +12 -0
  61. package/bridge/com.ucp.bridge/Tests/Editor/UCP.Bridge.Editor.Tests.asmdef.meta +7 -0
  62. package/bridge/com.ucp.bridge/Tests/Editor.meta +8 -0
  63. package/bridge/com.ucp.bridge/Tests.meta +8 -0
  64. package/bridge/com.ucp.bridge/package.json +27 -0
  65. package/bridge/com.ucp.bridge/package.json.meta +7 -0
  66. package/package.json +1 -1
@@ -0,0 +1,295 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using UnityEditor;
4
+ using UnityEngine;
5
+ using UnityEngine.Rendering;
6
+
7
+ namespace UCP.Bridge
8
+ {
9
+ public static class MaterialController
10
+ {
11
+ public static void Register(CommandRouter router)
12
+ {
13
+ router.Register("material/get-properties", HandleGetProperties);
14
+ router.Register("material/get-property", HandleGetProperty);
15
+ router.Register("material/set-property", HandleSetProperty);
16
+ router.Register("material/get-keywords", HandleGetKeywords);
17
+ router.Register("material/set-keyword", HandleSetKeyword);
18
+ router.Register("material/set-shader", HandleSetShader);
19
+ }
20
+
21
+ private static object HandleGetProperties(string paramsJson)
22
+ {
23
+ var mat = ResolveMaterial(paramsJson);
24
+ var shader = mat.shader;
25
+ int count = shader.GetPropertyCount();
26
+
27
+ var properties = new List<object>();
28
+ for (int i = 0; i < count; i++)
29
+ {
30
+ var propName = shader.GetPropertyName(i);
31
+ var propType = shader.GetPropertyType(i);
32
+ var propDesc = shader.GetPropertyDescription(i);
33
+
34
+ var propInfo = new Dictionary<string, object>
35
+ {
36
+ ["name"] = propName,
37
+ ["type"] = propType.ToString(),
38
+ ["description"] = propDesc,
39
+ ["value"] = ReadMaterialValue(mat, propName, propType)
40
+ };
41
+
42
+ properties.Add(propInfo);
43
+ }
44
+
45
+ return new Dictionary<string, object>
46
+ {
47
+ ["material"] = mat.name,
48
+ ["shader"] = shader.name,
49
+ ["properties"] = properties
50
+ };
51
+ }
52
+
53
+ private static object HandleGetProperty(string paramsJson)
54
+ {
55
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
56
+ if (p == null || !p.TryGetValue("property", out var propObj))
57
+ throw new ArgumentException("Missing 'property' parameter");
58
+
59
+ var mat = ResolveMaterial(paramsJson);
60
+ string propName = propObj.ToString();
61
+ var shader = mat.shader;
62
+
63
+ int propIdx = shader.FindPropertyIndex(propName);
64
+ if (propIdx < 0)
65
+ throw new ArgumentException($"Property '{propName}' not found on shader {shader.name}");
66
+
67
+ var propType = shader.GetPropertyType(propIdx);
68
+
69
+ return new Dictionary<string, object>
70
+ {
71
+ ["material"] = mat.name,
72
+ ["property"] = propName,
73
+ ["type"] = propType.ToString(),
74
+ ["value"] = ReadMaterialValue(mat, propName, propType)
75
+ };
76
+ }
77
+
78
+ private static object HandleSetProperty(string paramsJson)
79
+ {
80
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
81
+ if (p == null || !p.TryGetValue("property", out var propObj))
82
+ throw new ArgumentException("Missing 'property' parameter");
83
+ if (!p.ContainsKey("value"))
84
+ throw new ArgumentException("Missing 'value' parameter");
85
+
86
+ var mat = ResolveMaterial(paramsJson);
87
+ string propName = propObj.ToString();
88
+ var shader = mat.shader;
89
+
90
+ int propIdx = shader.FindPropertyIndex(propName);
91
+ if (propIdx < 0)
92
+ throw new ArgumentException($"Property '{propName}' not found on shader {shader.name}");
93
+
94
+ var propType = shader.GetPropertyType(propIdx);
95
+ Undo.RecordObject(mat, $"UCP Set Material {propName}");
96
+ WriteMaterialValue(mat, propName, propType, p["value"]);
97
+ EditorUtility.SetDirty(mat);
98
+
99
+ return new Dictionary<string, object>
100
+ {
101
+ ["status"] = "ok",
102
+ ["material"] = mat.name,
103
+ ["property"] = propName
104
+ };
105
+ }
106
+
107
+ private static object HandleGetKeywords(string paramsJson)
108
+ {
109
+ var mat = ResolveMaterial(paramsJson);
110
+ var keywords = new List<object>();
111
+ foreach (var kw in mat.enabledKeywords)
112
+ keywords.Add(kw.name);
113
+
114
+ return new Dictionary<string, object>
115
+ {
116
+ ["material"] = mat.name,
117
+ ["keywords"] = keywords
118
+ };
119
+ }
120
+
121
+ private static object HandleSetKeyword(string paramsJson)
122
+ {
123
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
124
+ if (p == null || !p.TryGetValue("keyword", out var kwObj))
125
+ throw new ArgumentException("Missing 'keyword' parameter");
126
+ if (!p.TryGetValue("enabled", out var enObj))
127
+ throw new ArgumentException("Missing 'enabled' parameter");
128
+
129
+ var mat = ResolveMaterial(paramsJson);
130
+ string keyword = kwObj.ToString();
131
+ bool enabled = Convert.ToBoolean(enObj);
132
+
133
+ Undo.RecordObject(mat, $"UCP Set Keyword {keyword}");
134
+ if (enabled)
135
+ mat.EnableKeyword(keyword);
136
+ else
137
+ mat.DisableKeyword(keyword);
138
+ EditorUtility.SetDirty(mat);
139
+
140
+ return new Dictionary<string, object>
141
+ {
142
+ ["status"] = "ok",
143
+ ["material"] = mat.name,
144
+ ["keyword"] = keyword,
145
+ ["enabled"] = enabled
146
+ };
147
+ }
148
+
149
+ private static object HandleSetShader(string paramsJson)
150
+ {
151
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
152
+ if (p == null || !p.TryGetValue("shader", out var shaderObj))
153
+ throw new ArgumentException("Missing 'shader' parameter");
154
+
155
+ var mat = ResolveMaterial(paramsJson);
156
+ string shaderName = shaderObj.ToString();
157
+ var shader = Shader.Find(shaderName);
158
+ if (shader == null)
159
+ throw new ArgumentException($"Shader not found: {shaderName}");
160
+
161
+ Undo.RecordObject(mat, "UCP Set Shader");
162
+ mat.shader = shader;
163
+ EditorUtility.SetDirty(mat);
164
+
165
+ return new Dictionary<string, object>
166
+ {
167
+ ["status"] = "ok",
168
+ ["material"] = mat.name,
169
+ ["shader"] = shaderName
170
+ };
171
+ }
172
+
173
+ // ---- Helper methods ----
174
+
175
+ private static Material ResolveMaterial(string paramsJson)
176
+ {
177
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
178
+ if (p == null)
179
+ throw new ArgumentException("Invalid parameters");
180
+
181
+ // Resolve by asset path
182
+ if (p.TryGetValue("path", out var pathObj) && pathObj != null)
183
+ {
184
+ string path = pathObj.ToString();
185
+ var mat = AssetDatabase.LoadAssetAtPath<Material>(path);
186
+ if (mat == null)
187
+ throw new ArgumentException($"Material not found at: {path}");
188
+ return mat;
189
+ }
190
+
191
+ // Resolve by instanceId (scene object's renderer material)
192
+ if (p.TryGetValue("instanceId", out var idObj))
193
+ {
194
+ int instanceId = Convert.ToInt32(idObj);
195
+ var obj = EditorUtility.InstanceIDToObject(instanceId);
196
+
197
+ if (obj is Material directMat)
198
+ return directMat;
199
+
200
+ if (obj is GameObject go)
201
+ {
202
+ var renderer = go.GetComponent<Renderer>();
203
+ if (renderer != null && renderer.sharedMaterial != null)
204
+ return renderer.sharedMaterial;
205
+ }
206
+
207
+ throw new ArgumentException($"No material found for instance {instanceId}");
208
+ }
209
+
210
+ throw new ArgumentException("Provide 'path' or 'instanceId' to identify the material");
211
+ }
212
+
213
+ private static object ReadMaterialValue(Material mat, string propName, UnityEngine.Rendering.ShaderPropertyType propType)
214
+ {
215
+ switch (propType)
216
+ {
217
+ case ShaderPropertyType.Color:
218
+ var c = mat.GetColor(propName);
219
+ return new List<object> { (double)c.r, (double)c.g, (double)c.b, (double)c.a };
220
+ case ShaderPropertyType.Vector:
221
+ var v = mat.GetVector(propName);
222
+ return new List<object> { (double)v.x, (double)v.y, (double)v.z, (double)v.w };
223
+ case ShaderPropertyType.Float:
224
+ case ShaderPropertyType.Range:
225
+ return (double)mat.GetFloat(propName);
226
+ case ShaderPropertyType.Texture:
227
+ var tex = mat.GetTexture(propName);
228
+ if (tex != null)
229
+ {
230
+ var texPath = AssetDatabase.GetAssetPath(tex);
231
+ return new Dictionary<string, object>
232
+ {
233
+ ["name"] = tex.name,
234
+ ["path"] = texPath,
235
+ ["instanceId"] = tex.GetInstanceID()
236
+ };
237
+ }
238
+ return null;
239
+ case ShaderPropertyType.Int:
240
+ return mat.GetInteger(propName);
241
+ default:
242
+ return null;
243
+ }
244
+ }
245
+
246
+ private static void WriteMaterialValue(Material mat, string propName, ShaderPropertyType propType, object value)
247
+ {
248
+ switch (propType)
249
+ {
250
+ case ShaderPropertyType.Color:
251
+ if (value is List<object> ca && ca.Count >= 3)
252
+ mat.SetColor(propName, new Color(
253
+ Convert.ToSingle(ca[0]),
254
+ Convert.ToSingle(ca[1]),
255
+ Convert.ToSingle(ca[2]),
256
+ ca.Count >= 4 ? Convert.ToSingle(ca[3]) : 1f));
257
+ break;
258
+ case ShaderPropertyType.Vector:
259
+ if (value is List<object> va && va.Count >= 4)
260
+ mat.SetVector(propName, new Vector4(
261
+ Convert.ToSingle(va[0]),
262
+ Convert.ToSingle(va[1]),
263
+ Convert.ToSingle(va[2]),
264
+ Convert.ToSingle(va[3])));
265
+ break;
266
+ case ShaderPropertyType.Float:
267
+ case ShaderPropertyType.Range:
268
+ mat.SetFloat(propName, Convert.ToSingle(value));
269
+ break;
270
+ case ShaderPropertyType.Int:
271
+ mat.SetInteger(propName, Convert.ToInt32(value));
272
+ break;
273
+ case ShaderPropertyType.Texture:
274
+ if (value == null)
275
+ {
276
+ mat.SetTexture(propName, null);
277
+ }
278
+ else if (value is Dictionary<string, object> texDict)
279
+ {
280
+ if (texDict.TryGetValue("path", out var tp))
281
+ {
282
+ var tex = AssetDatabase.LoadAssetAtPath<Texture>(tp.ToString());
283
+ mat.SetTexture(propName, tex);
284
+ }
285
+ else if (texDict.TryGetValue("instanceId", out var tid))
286
+ {
287
+ var tex = EditorUtility.InstanceIDToObject(Convert.ToInt32(tid)) as Texture;
288
+ mat.SetTexture(propName, tex);
289
+ }
290
+ }
291
+ break;
292
+ }
293
+ }
294
+ }
295
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: f768b9444f7579b4ebc18654e99f118a
@@ -0,0 +1,38 @@
1
+ using UnityEditor;
2
+
3
+ namespace UCP.Bridge
4
+ {
5
+ public static class PlayModeController
6
+ {
7
+ public static void Register(CommandRouter router)
8
+ {
9
+ router.Register("play", HandlePlay);
10
+ router.Register("stop", HandleStop);
11
+ router.Register("pause", HandlePause);
12
+ }
13
+
14
+ private static object HandlePlay(string paramsJson)
15
+ {
16
+ if (EditorApplication.isPlaying)
17
+ return new { status = "already_playing" };
18
+
19
+ EditorApplication.isPlaying = true;
20
+ return new { status = "ok" };
21
+ }
22
+
23
+ private static object HandleStop(string paramsJson)
24
+ {
25
+ if (!EditorApplication.isPlaying)
26
+ return new { status = "already_stopped" };
27
+
28
+ EditorApplication.isPlaying = false;
29
+ return new { status = "ok" };
30
+ }
31
+
32
+ private static object HandlePause(string paramsJson)
33
+ {
34
+ EditorApplication.isPaused = !EditorApplication.isPaused;
35
+ return new { status = "ok", paused = EditorApplication.isPaused };
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 647b22516c825e84da0f1815a6e0fa30
@@ -0,0 +1,242 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.Linq;
4
+ using UnityEditor;
5
+ using UnityEngine;
6
+
7
+ namespace UCP.Bridge
8
+ {
9
+ public static class PrefabController
10
+ {
11
+ public static void Register(CommandRouter router)
12
+ {
13
+ router.Register("prefab/status", HandleStatus);
14
+ router.Register("prefab/apply", HandleApply);
15
+ router.Register("prefab/revert", HandleRevert);
16
+ router.Register("prefab/unpack", HandleUnpack);
17
+ router.Register("prefab/create", HandleCreate);
18
+ router.Register("prefab/overrides", HandleOverrides);
19
+ }
20
+
21
+ private static object HandleStatus(string paramsJson)
22
+ {
23
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
24
+ if (p == null || !p.TryGetValue("instanceId", out var idObj))
25
+ throw new ArgumentException("Missing 'instanceId' parameter");
26
+
27
+ var go = EditorUtility.InstanceIDToObject(Convert.ToInt32(idObj)) as GameObject;
28
+ if (go == null)
29
+ throw new ArgumentException($"GameObject not found: {idObj}");
30
+
31
+ bool isPrefab = PrefabUtility.IsPartOfAnyPrefab(go);
32
+ bool isInstance = PrefabUtility.IsPartOfPrefabInstance(go);
33
+ bool isRoot = PrefabUtility.IsOutermostPrefabInstanceRoot(go);
34
+ bool hasOverrides = PrefabUtility.HasPrefabInstanceAnyOverrides(go, false);
35
+
36
+ var result = new Dictionary<string, object>
37
+ {
38
+ ["name"] = go.name,
39
+ ["isPrefab"] = isPrefab,
40
+ ["isInstance"] = isInstance,
41
+ ["isRoot"] = isRoot,
42
+ ["hasOverrides"] = hasOverrides
43
+ };
44
+
45
+ if (isInstance)
46
+ {
47
+ var source = PrefabUtility.GetCorrespondingObjectFromSource(go);
48
+ if (source != null)
49
+ {
50
+ result["sourcePath"] = AssetDatabase.GetAssetPath(source);
51
+ result["sourceName"] = source.name;
52
+ }
53
+ }
54
+
55
+ return result;
56
+ }
57
+
58
+ private static object HandleApply(string paramsJson)
59
+ {
60
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
61
+ if (p == null || !p.TryGetValue("instanceId", out var idObj))
62
+ throw new ArgumentException("Missing 'instanceId' parameter");
63
+
64
+ var go = EditorUtility.InstanceIDToObject(Convert.ToInt32(idObj)) as GameObject;
65
+ if (go == null)
66
+ throw new ArgumentException($"GameObject not found: {idObj}");
67
+
68
+ if (!PrefabUtility.IsPartOfPrefabInstance(go))
69
+ throw new ArgumentException("Object is not a prefab instance");
70
+
71
+ string assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(go);
72
+ PrefabUtility.ApplyPrefabInstance(go, InteractionMode.AutomatedAction);
73
+
74
+ return new Dictionary<string, object>
75
+ {
76
+ ["status"] = "ok",
77
+ ["assetPath"] = assetPath
78
+ };
79
+ }
80
+
81
+ private static object HandleRevert(string paramsJson)
82
+ {
83
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
84
+ if (p == null || !p.TryGetValue("instanceId", out var idObj))
85
+ throw new ArgumentException("Missing 'instanceId' parameter");
86
+
87
+ var go = EditorUtility.InstanceIDToObject(Convert.ToInt32(idObj)) as GameObject;
88
+ if (go == null)
89
+ throw new ArgumentException($"GameObject not found: {idObj}");
90
+
91
+ if (!PrefabUtility.IsPartOfPrefabInstance(go))
92
+ throw new ArgumentException("Object is not a prefab instance");
93
+
94
+ PrefabUtility.RevertPrefabInstance(go, InteractionMode.AutomatedAction);
95
+
96
+ return new Dictionary<string, object>
97
+ {
98
+ ["status"] = "ok",
99
+ ["name"] = go.name
100
+ };
101
+ }
102
+
103
+ private static object HandleUnpack(string paramsJson)
104
+ {
105
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
106
+ if (p == null || !p.TryGetValue("instanceId", out var idObj))
107
+ throw new ArgumentException("Missing 'instanceId' parameter");
108
+
109
+ bool completely = false;
110
+ if (p.TryGetValue("completely", out var compObj))
111
+ completely = Convert.ToBoolean(compObj);
112
+
113
+ var go = EditorUtility.InstanceIDToObject(Convert.ToInt32(idObj)) as GameObject;
114
+ if (go == null)
115
+ throw new ArgumentException($"GameObject not found: {idObj}");
116
+
117
+ if (!PrefabUtility.IsPartOfPrefabInstance(go))
118
+ throw new ArgumentException("Object is not a prefab instance");
119
+
120
+ var mode = completely
121
+ ? PrefabUnpackMode.Completely
122
+ : PrefabUnpackMode.OutermostRoot;
123
+
124
+ PrefabUtility.UnpackPrefabInstance(go, mode, InteractionMode.AutomatedAction);
125
+
126
+ return new Dictionary<string, object>
127
+ {
128
+ ["status"] = "ok",
129
+ ["name"] = go.name,
130
+ ["mode"] = mode.ToString()
131
+ };
132
+ }
133
+
134
+ private static object HandleCreate(string paramsJson)
135
+ {
136
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
137
+ if (p == null || !p.TryGetValue("instanceId", out var idObj))
138
+ throw new ArgumentException("Missing 'instanceId' parameter");
139
+ if (!p.TryGetValue("path", out var pathObj))
140
+ throw new ArgumentException("Missing 'path' parameter");
141
+
142
+ var go = EditorUtility.InstanceIDToObject(Convert.ToInt32(idObj)) as GameObject;
143
+ if (go == null)
144
+ throw new ArgumentException($"GameObject not found: {idObj}");
145
+
146
+ string savePath = pathObj.ToString();
147
+
148
+ // Ensure directory exists
149
+ string dir = System.IO.Path.GetDirectoryName(savePath);
150
+ if (!string.IsNullOrEmpty(dir) && !AssetDatabase.IsValidFolder(dir))
151
+ {
152
+ CreateFoldersRecursive(dir);
153
+ }
154
+
155
+ bool success;
156
+ var prefab = PrefabUtility.SaveAsPrefabAsset(go, savePath, out success);
157
+
158
+ if (!success || prefab == null)
159
+ throw new InvalidOperationException($"Failed to create prefab at {savePath}");
160
+
161
+ return new Dictionary<string, object>
162
+ {
163
+ ["status"] = "ok",
164
+ ["path"] = savePath,
165
+ ["name"] = prefab.name,
166
+ ["instanceId"] = prefab.GetInstanceID()
167
+ };
168
+ }
169
+
170
+ private static object HandleOverrides(string paramsJson)
171
+ {
172
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
173
+ if (p == null || !p.TryGetValue("instanceId", out var idObj))
174
+ throw new ArgumentException("Missing 'instanceId' parameter");
175
+
176
+ var go = EditorUtility.InstanceIDToObject(Convert.ToInt32(idObj)) as GameObject;
177
+ if (go == null)
178
+ throw new ArgumentException($"GameObject not found: {idObj}");
179
+
180
+ if (!PrefabUtility.IsPartOfPrefabInstance(go))
181
+ throw new ArgumentException("Object is not a prefab instance");
182
+
183
+ var modifications = PrefabUtility.GetPropertyModifications(go);
184
+ var overrides = new List<object>();
185
+
186
+ if (modifications != null)
187
+ {
188
+ foreach (var mod in modifications)
189
+ {
190
+ overrides.Add(new Dictionary<string, object>
191
+ {
192
+ ["target"] = mod.target?.GetType().Name ?? "null",
193
+ ["propertyPath"] = mod.propertyPath,
194
+ ["value"] = mod.value ?? ""
195
+ });
196
+ }
197
+ }
198
+
199
+ var addedComponents = PrefabUtility.GetAddedComponents(go);
200
+ var added = new List<object>();
201
+ foreach (var ac in addedComponents)
202
+ {
203
+ added.Add(new Dictionary<string, object>
204
+ {
205
+ ["component"] = ac.instanceComponent.GetType().Name,
206
+ ["instanceId"] = ac.instanceComponent.GetInstanceID()
207
+ });
208
+ }
209
+
210
+ var removedComponents = PrefabUtility.GetRemovedComponents(go);
211
+ var removed = new List<object>();
212
+ foreach (var rc in removedComponents)
213
+ {
214
+ removed.Add(new Dictionary<string, object>
215
+ {
216
+ ["component"] = rc.assetComponent.GetType().Name
217
+ });
218
+ }
219
+
220
+ return new Dictionary<string, object>
221
+ {
222
+ ["name"] = go.name,
223
+ ["propertyModifications"] = overrides,
224
+ ["addedComponents"] = added,
225
+ ["removedComponents"] = removed
226
+ };
227
+ }
228
+
229
+ private static void CreateFoldersRecursive(string path)
230
+ {
231
+ var parts = path.Replace("\\", "/").Split('/');
232
+ string current = parts[0];
233
+ for (int i = 1; i < parts.Length; i++)
234
+ {
235
+ string next = current + "/" + parts[i];
236
+ if (!AssetDatabase.IsValidFolder(next))
237
+ AssetDatabase.CreateFolder(current, parts[i]);
238
+ current = next;
239
+ }
240
+ }
241
+ }
242
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 14f389b8e0d407c4da00f07435f44e39