@mflrevan/ucp 0.2.0 → 0.3.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.
Files changed (66) hide show
  1. package/README.md +5 -3
  2. package/bridge/com.ucp.bridge/CHANGELOG.md +71 -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 +84 -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 +111 -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 +240 -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 +485 -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,499 @@
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 AssetController
10
+ {
11
+ public static void Register(CommandRouter router)
12
+ {
13
+ router.Register("asset/search", HandleSearch);
14
+ router.Register("asset/info", HandleInfo);
15
+ router.Register("asset/read", HandleReadScriptableObject);
16
+ router.Register("asset/write", HandleWriteScriptableObject);
17
+ router.Register("asset/create-so", HandleCreateScriptableObject);
18
+ }
19
+
20
+ private static object HandleSearch(string paramsJson)
21
+ {
22
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
23
+ string typeFilter = null;
24
+ string nameFilter = null;
25
+ string pathFilter = null;
26
+ int maxResults = 100;
27
+
28
+ if (p != null)
29
+ {
30
+ if (p.TryGetValue("type", out var tObj) && tObj != null)
31
+ typeFilter = tObj.ToString();
32
+ if (p.TryGetValue("name", out var nObj) && nObj != null)
33
+ nameFilter = nObj.ToString();
34
+ if (p.TryGetValue("path", out var pObj) && pObj != null)
35
+ pathFilter = pObj.ToString();
36
+ if (p.TryGetValue("maxResults", out var mObj))
37
+ maxResults = Convert.ToInt32(mObj);
38
+ }
39
+
40
+ // Build search filter
41
+ string filter = "";
42
+ if (!string.IsNullOrEmpty(nameFilter))
43
+ filter += nameFilter + " ";
44
+ if (!string.IsNullOrEmpty(typeFilter))
45
+ filter += $"t:{GetSearchTypeFilter(typeFilter)}";
46
+
47
+ string[] searchFolders = null;
48
+ if (!string.IsNullOrEmpty(pathFilter))
49
+ searchFolders = new[] { pathFilter };
50
+
51
+ string[] guids;
52
+ if (searchFolders != null)
53
+ guids = AssetDatabase.FindAssets(filter.Trim(), searchFolders);
54
+ else
55
+ guids = AssetDatabase.FindAssets(filter.Trim());
56
+
57
+ var results = new List<object>();
58
+ int totalMatches = 0;
59
+ for (int i = 0; i < guids.Length; i++)
60
+ {
61
+ string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]);
62
+ foreach (var asset in GetMatchingAssets(assetPath, typeFilter, nameFilter))
63
+ {
64
+ totalMatches++;
65
+ if (results.Count >= maxResults)
66
+ continue;
67
+
68
+ results.Add(new Dictionary<string, object>
69
+ {
70
+ ["guid"] = guids[i],
71
+ ["path"] = assetPath,
72
+ ["type"] = GetDisplayType(assetPath, asset),
73
+ ["name"] = asset.name,
74
+ ["isSubAsset"] = AssetDatabase.IsSubAsset(asset)
75
+ });
76
+ }
77
+ }
78
+
79
+ return new Dictionary<string, object>
80
+ {
81
+ ["results"] = results,
82
+ ["total"] = totalMatches,
83
+ ["returned"] = results.Count
84
+ };
85
+ }
86
+
87
+ private static object HandleInfo(string paramsJson)
88
+ {
89
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
90
+ if (p == null || !p.TryGetValue("path", out var pathObj))
91
+ throw new ArgumentException("Missing 'path' parameter");
92
+
93
+ string assetPath = pathObj.ToString();
94
+ var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath);
95
+ if (asset == null)
96
+ throw new ArgumentException($"Asset not found: {assetPath}");
97
+
98
+ var info = new Dictionary<string, object>
99
+ {
100
+ ["path"] = assetPath,
101
+ ["name"] = asset.name,
102
+ ["type"] = asset.GetType().Name,
103
+ ["fullType"] = asset.GetType().FullName,
104
+ ["instanceId"] = asset.GetInstanceID(),
105
+ ["guid"] = AssetDatabase.AssetPathToGUID(assetPath)
106
+ };
107
+
108
+ // Add additional info for specific types
109
+ if (asset is GameObject go)
110
+ {
111
+ info["isPrefab"] = true;
112
+ var components = new List<string>();
113
+ foreach (var c in go.GetComponents<Component>())
114
+ {
115
+ if (c != null)
116
+ components.Add(c.GetType().Name);
117
+ }
118
+ info["components"] = components;
119
+ }
120
+
121
+ if (asset is ScriptableObject)
122
+ {
123
+ info["isScriptableObject"] = true;
124
+ }
125
+
126
+ return info;
127
+ }
128
+
129
+ private static object HandleReadScriptableObject(string paramsJson)
130
+ {
131
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
132
+ if (p == null || !p.TryGetValue("path", out var pathObj))
133
+ throw new ArgumentException("Missing 'path' parameter");
134
+
135
+ string assetPath = pathObj.ToString();
136
+ var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath);
137
+ if (asset == null)
138
+ throw new ArgumentException($"Asset not found: {assetPath}");
139
+
140
+ // Optional: read specific field only
141
+ string fieldName = null;
142
+ if (p.TryGetValue("field", out var fObj) && fObj != null)
143
+ fieldName = fObj.ToString();
144
+
145
+ var so = new SerializedObject(asset);
146
+ var fields = new List<object>();
147
+
148
+ if (fieldName != null)
149
+ {
150
+ var prop = so.FindProperty(fieldName);
151
+ if (prop == null)
152
+ throw new ArgumentException($"Field '{fieldName}' not found on {asset.GetType().Name}");
153
+
154
+ fields.Add(new Dictionary<string, object>
155
+ {
156
+ ["name"] = prop.name,
157
+ ["displayName"] = prop.displayName,
158
+ ["type"] = prop.propertyType.ToString(),
159
+ ["value"] = ReadSerializedValue(prop)
160
+ });
161
+ }
162
+ else
163
+ {
164
+ var iter = so.GetIterator();
165
+ if (iter.NextVisible(true))
166
+ {
167
+ do
168
+ {
169
+ if (iter.name == "m_Script") continue;
170
+ fields.Add(new Dictionary<string, object>
171
+ {
172
+ ["name"] = iter.name,
173
+ ["displayName"] = iter.displayName,
174
+ ["type"] = iter.propertyType.ToString(),
175
+ ["value"] = ReadSerializedValue(iter)
176
+ });
177
+ }
178
+ while (iter.NextVisible(false));
179
+ }
180
+ }
181
+
182
+ so.Dispose();
183
+
184
+ return new Dictionary<string, object>
185
+ {
186
+ ["path"] = assetPath,
187
+ ["name"] = asset.name,
188
+ ["type"] = asset.GetType().Name,
189
+ ["fields"] = fields
190
+ };
191
+ }
192
+
193
+ private static object HandleWriteScriptableObject(string paramsJson)
194
+ {
195
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
196
+ if (p == null || !p.TryGetValue("path", out var pathObj))
197
+ throw new ArgumentException("Missing 'path' parameter");
198
+ if (!p.TryGetValue("field", out var fieldObj) || fieldObj == null)
199
+ throw new ArgumentException("Missing 'field' parameter");
200
+ if (!p.ContainsKey("value"))
201
+ throw new ArgumentException("Missing 'value' parameter");
202
+
203
+ string assetPath = pathObj.ToString();
204
+ var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath);
205
+ if (asset == null)
206
+ throw new ArgumentException($"Asset not found: {assetPath}");
207
+
208
+ string fieldName = fieldObj.ToString();
209
+ var so = new SerializedObject(asset);
210
+ var prop = so.FindProperty(fieldName);
211
+ if (prop == null)
212
+ {
213
+ so.Dispose();
214
+ throw new ArgumentException($"Field '{fieldName}' not found on {asset.GetType().Name}");
215
+ }
216
+
217
+ Undo.RecordObject(asset, $"UCP Write {fieldName}");
218
+ WriteSerializedValue(prop, p["value"]);
219
+ so.ApplyModifiedProperties();
220
+ EditorUtility.SetDirty(asset);
221
+ AssetDatabase.SaveAssetIfDirty(asset);
222
+ so.Dispose();
223
+
224
+ return new Dictionary<string, object>
225
+ {
226
+ ["status"] = "ok",
227
+ ["path"] = assetPath,
228
+ ["field"] = fieldName
229
+ };
230
+ }
231
+
232
+ private static object HandleCreateScriptableObject(string paramsJson)
233
+ {
234
+ var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
235
+ if (p == null || !p.TryGetValue("type", out var typeObj) || typeObj == null)
236
+ throw new ArgumentException("Missing 'type' parameter");
237
+ if (!p.TryGetValue("path", out var pathObj) || pathObj == null)
238
+ throw new ArgumentException("Missing 'path' parameter");
239
+
240
+ string typeName = typeObj.ToString();
241
+ string assetPath = pathObj.ToString();
242
+
243
+ // Resolve ScriptableObject type
244
+ Type soType = null;
245
+ foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
246
+ {
247
+ foreach (var t in assembly.GetTypes())
248
+ {
249
+ if (!typeof(ScriptableObject).IsAssignableFrom(t)) continue;
250
+ if (t.Name == typeName || t.FullName == typeName)
251
+ {
252
+ soType = t;
253
+ break;
254
+ }
255
+ }
256
+ if (soType != null) break;
257
+ }
258
+
259
+ if (soType == null)
260
+ throw new ArgumentException($"ScriptableObject type not found: {typeName}");
261
+
262
+ var instance = ScriptableObject.CreateInstance(soType);
263
+
264
+ // Ensure directory exists
265
+ string dir = System.IO.Path.GetDirectoryName(assetPath);
266
+ if (!string.IsNullOrEmpty(dir) && !AssetDatabase.IsValidFolder(dir))
267
+ {
268
+ CreateFoldersRecursive(dir);
269
+ }
270
+
271
+ AssetDatabase.CreateAsset(instance, assetPath);
272
+ AssetDatabase.SaveAssets();
273
+
274
+ return new Dictionary<string, object>
275
+ {
276
+ ["status"] = "ok",
277
+ ["path"] = assetPath,
278
+ ["type"] = soType.Name,
279
+ ["instanceId"] = instance.GetInstanceID()
280
+ };
281
+ }
282
+
283
+ private static void CreateFoldersRecursive(string path)
284
+ {
285
+ var parts = path.Replace("\\", "/").Split('/');
286
+ string current = parts[0];
287
+ for (int i = 1; i < parts.Length; i++)
288
+ {
289
+ string next = current + "/" + parts[i];
290
+ if (!AssetDatabase.IsValidFolder(next))
291
+ AssetDatabase.CreateFolder(current, parts[i]);
292
+ current = next;
293
+ }
294
+ }
295
+
296
+ private static IEnumerable<UnityEngine.Object> GetMatchingAssets(string assetPath, string typeFilter, string nameFilter)
297
+ {
298
+ UnityEngine.Object[] candidates;
299
+ if (string.IsNullOrEmpty(typeFilter) && string.IsNullOrEmpty(nameFilter))
300
+ {
301
+ var mainAsset = AssetDatabase.LoadMainAssetAtPath(assetPath);
302
+ candidates = mainAsset != null ? new[] { mainAsset } : Array.Empty<UnityEngine.Object>();
303
+ }
304
+ else
305
+ {
306
+ candidates = AssetDatabase.LoadAllAssetsAtPath(assetPath);
307
+ }
308
+
309
+ foreach (var candidate in candidates)
310
+ {
311
+ if (candidate == null) continue;
312
+ if (!MatchesName(candidate, assetPath, nameFilter)) continue;
313
+ if (!MatchesType(candidate, assetPath, typeFilter)) continue;
314
+ yield return candidate;
315
+ }
316
+ }
317
+
318
+ private static bool MatchesName(UnityEngine.Object asset, string assetPath, string nameFilter)
319
+ {
320
+ if (string.IsNullOrEmpty(nameFilter))
321
+ return true;
322
+
323
+ return asset.name.Contains(nameFilter, StringComparison.OrdinalIgnoreCase)
324
+ || System.IO.Path.GetFileNameWithoutExtension(assetPath).Contains(nameFilter, StringComparison.OrdinalIgnoreCase);
325
+ }
326
+
327
+ private static bool MatchesType(UnityEngine.Object asset, string assetPath, string typeFilter)
328
+ {
329
+ if (string.IsNullOrEmpty(typeFilter))
330
+ return true;
331
+
332
+ if (typeFilter.Equals("Prefab", StringComparison.OrdinalIgnoreCase))
333
+ {
334
+ return asset is GameObject
335
+ && !AssetDatabase.IsSubAsset(asset)
336
+ && assetPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase);
337
+ }
338
+
339
+ var normalizedType = NormalizeTypeFilter(typeFilter);
340
+ var assetType = asset.GetType();
341
+ return assetType.Name.Equals(normalizedType, StringComparison.OrdinalIgnoreCase)
342
+ || (assetType.FullName != null && assetType.FullName.Equals(normalizedType, StringComparison.OrdinalIgnoreCase));
343
+ }
344
+
345
+ private static string GetDisplayType(string assetPath, UnityEngine.Object asset)
346
+ {
347
+ if (asset is GameObject
348
+ && !AssetDatabase.IsSubAsset(asset)
349
+ && assetPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
350
+ {
351
+ return "Prefab";
352
+ }
353
+
354
+ return asset.GetType().Name;
355
+ }
356
+
357
+ private static string GetSearchTypeFilter(string typeFilter)
358
+ {
359
+ if (typeFilter.Equals("Prefab", StringComparison.OrdinalIgnoreCase))
360
+ return "GameObject";
361
+
362
+ return NormalizeTypeFilter(typeFilter);
363
+ }
364
+
365
+ private static string NormalizeTypeFilter(string typeFilter)
366
+ {
367
+ return typeFilter?.Trim() ?? string.Empty;
368
+ }
369
+
370
+ // ---- Serialized property value reading/writing ----
371
+
372
+ private static object ReadSerializedValue(SerializedProperty prop)
373
+ {
374
+ switch (prop.propertyType)
375
+ {
376
+ case SerializedPropertyType.Integer: return prop.intValue;
377
+ case SerializedPropertyType.Boolean: return prop.boolValue;
378
+ case SerializedPropertyType.Float: return (double)prop.floatValue;
379
+ case SerializedPropertyType.String: return prop.stringValue;
380
+ case SerializedPropertyType.Color:
381
+ var c = prop.colorValue;
382
+ return new List<object> { (double)c.r, (double)c.g, (double)c.b, (double)c.a };
383
+ case SerializedPropertyType.ObjectReference:
384
+ if (prop.objectReferenceValue != null)
385
+ return new Dictionary<string, object>
386
+ {
387
+ ["instanceId"] = prop.objectReferenceValue.GetInstanceID(),
388
+ ["name"] = prop.objectReferenceValue.name,
389
+ ["type"] = prop.objectReferenceValue.GetType().Name
390
+ };
391
+ return null;
392
+ case SerializedPropertyType.Enum:
393
+ return prop.enumValueIndex < prop.enumDisplayNames.Length
394
+ ? prop.enumDisplayNames[prop.enumValueIndex]
395
+ : prop.enumValueIndex.ToString();
396
+ case SerializedPropertyType.Vector2:
397
+ var v2 = prop.vector2Value;
398
+ return new List<object> { (double)v2.x, (double)v2.y };
399
+ case SerializedPropertyType.Vector3:
400
+ var v3 = prop.vector3Value;
401
+ return new List<object> { (double)v3.x, (double)v3.y, (double)v3.z };
402
+ case SerializedPropertyType.Vector4:
403
+ var v4 = prop.vector4Value;
404
+ return new List<object> { (double)v4.x, (double)v4.y, (double)v4.z, (double)v4.w };
405
+ case SerializedPropertyType.Quaternion:
406
+ var q = prop.quaternionValue;
407
+ return new List<object> { (double)q.x, (double)q.y, (double)q.z, (double)q.w };
408
+ case SerializedPropertyType.Rect:
409
+ var r = prop.rectValue;
410
+ return new Dictionary<string, object>
411
+ {
412
+ ["x"] = (double)r.x,
413
+ ["y"] = (double)r.y,
414
+ ["width"] = (double)r.width,
415
+ ["height"] = (double)r.height
416
+ };
417
+ case SerializedPropertyType.Bounds:
418
+ var b = prop.boundsValue;
419
+ return new Dictionary<string, object>
420
+ {
421
+ ["center"] = new List<object> { (double)b.center.x, (double)b.center.y, (double)b.center.z },
422
+ ["size"] = new List<object> { (double)b.size.x, (double)b.size.y, (double)b.size.z }
423
+ };
424
+ case SerializedPropertyType.ArraySize:
425
+ return prop.intValue;
426
+ case SerializedPropertyType.LayerMask:
427
+ return prop.intValue;
428
+ default:
429
+ return $"<{prop.propertyType}>";
430
+ }
431
+ }
432
+
433
+ private static void WriteSerializedValue(SerializedProperty prop, object value)
434
+ {
435
+ switch (prop.propertyType)
436
+ {
437
+ case SerializedPropertyType.Integer:
438
+ prop.intValue = Convert.ToInt32(value);
439
+ break;
440
+ case SerializedPropertyType.Boolean:
441
+ prop.boolValue = Convert.ToBoolean(value);
442
+ break;
443
+ case SerializedPropertyType.Float:
444
+ prop.floatValue = Convert.ToSingle(value);
445
+ break;
446
+ case SerializedPropertyType.String:
447
+ prop.stringValue = value?.ToString() ?? "";
448
+ break;
449
+ case SerializedPropertyType.Color:
450
+ if (value is List<object> cArr && cArr.Count >= 3)
451
+ prop.colorValue = new Color(
452
+ Convert.ToSingle(cArr[0]),
453
+ Convert.ToSingle(cArr[1]),
454
+ Convert.ToSingle(cArr[2]),
455
+ cArr.Count >= 4 ? Convert.ToSingle(cArr[3]) : 1f);
456
+ break;
457
+ case SerializedPropertyType.Enum:
458
+ if (value is string enumStr)
459
+ {
460
+ int idx = Array.IndexOf(prop.enumDisplayNames, enumStr);
461
+ if (idx >= 0) prop.enumValueIndex = idx;
462
+ else if (int.TryParse(enumStr, out int enumIdx)) prop.enumValueIndex = enumIdx;
463
+ }
464
+ else
465
+ {
466
+ prop.enumValueIndex = Convert.ToInt32(value);
467
+ }
468
+ break;
469
+ case SerializedPropertyType.Vector2:
470
+ if (value is List<object> v2 && v2.Count >= 2)
471
+ prop.vector2Value = new Vector2(Convert.ToSingle(v2[0]), Convert.ToSingle(v2[1]));
472
+ break;
473
+ case SerializedPropertyType.Vector3:
474
+ if (value is List<object> v3 && v3.Count >= 3)
475
+ prop.vector3Value = new Vector3(Convert.ToSingle(v3[0]), Convert.ToSingle(v3[1]), Convert.ToSingle(v3[2]));
476
+ break;
477
+ case SerializedPropertyType.Vector4:
478
+ if (value is List<object> v4 && v4.Count >= 4)
479
+ prop.vector4Value = new Vector4(Convert.ToSingle(v4[0]), Convert.ToSingle(v4[1]), Convert.ToSingle(v4[2]), Convert.ToSingle(v4[3]));
480
+ break;
481
+ case SerializedPropertyType.Quaternion:
482
+ if (value is List<object> qArr && qArr.Count >= 4)
483
+ prop.quaternionValue = new Quaternion(Convert.ToSingle(qArr[0]), Convert.ToSingle(qArr[1]), Convert.ToSingle(qArr[2]), Convert.ToSingle(qArr[3]));
484
+ break;
485
+ case SerializedPropertyType.ObjectReference:
486
+ if (value == null)
487
+ prop.objectReferenceValue = null;
488
+ else if (value is Dictionary<string, object> refDict && refDict.TryGetValue("instanceId", out var refId))
489
+ prop.objectReferenceValue = EditorUtility.InstanceIDToObject(Convert.ToInt32(refId));
490
+ break;
491
+ case SerializedPropertyType.LayerMask:
492
+ prop.intValue = Convert.ToInt32(value);
493
+ break;
494
+ default:
495
+ throw new ArgumentException($"Cannot write property of type {prop.propertyType}");
496
+ }
497
+ }
498
+ }
499
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: bc9394bede1a4b14a8c95bbbccf6e41d