@mflrevan/ucp 0.4.3 → 0.4.5
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/CHANGELOG.md +145 -0
- package/bridge/com.ucp.bridge/CHANGELOG.md.meta +7 -0
- package/bridge/com.ucp.bridge/Editor/Bridge/BridgeServer.cs +583 -0
- package/bridge/com.ucp.bridge/Editor/Bridge/BridgeServer.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Bridge.meta +8 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/AssetController.cs +425 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/AssetController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/AssetImportSupport.cs +355 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/AssetImportSupport.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/BuildController.cs +233 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/BuildController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/CompilationController.cs +26 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/CompilationController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/EditorController.cs +31 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/EditorController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/EditorSettingsController.cs +527 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/EditorSettingsController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/FileController.cs +141 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/FileController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/HierarchyController.cs +326 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/HierarchyController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ImporterController.cs +209 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ImporterController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/LogsController.cs +409 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/LogsController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/MaterialController.cs +354 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/MaterialController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ObjectReferenceResolver.cs +93 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ObjectReferenceResolver.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/PackagesController.cs +503 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/PackagesController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/PlayModeController.cs +188 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/PlayModeController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/PrefabController.cs +260 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/PrefabController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ProfilerController.cs +1679 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ProfilerController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/PropertyController.cs +563 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/PropertyController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/SceneChangeTracker.cs +166 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/SceneChangeTracker.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/SceneController.cs +318 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/SceneController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ScreenshotController.cs +125 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ScreenshotController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ScriptController.cs +104 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ScriptController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/SnapshotController.cs +227 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/SnapshotController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/TestRunnerController.cs +240 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/TestRunnerController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/VcsController.cs +611 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/VcsController.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Controllers.meta +8 -0
- package/bridge/com.ucp.bridge/Editor/Protocol/CommandRouter.cs +53 -0
- package/bridge/com.ucp.bridge/Editor/Protocol/CommandRouter.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Protocol/MessageTypes.cs +80 -0
- package/bridge/com.ucp.bridge/Editor/Protocol/MessageTypes.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Protocol/MiniJson.cs +358 -0
- package/bridge/com.ucp.bridge/Editor/Protocol/MiniJson.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Protocol.meta +8 -0
- package/bridge/com.ucp.bridge/Editor/Scripts/IUCPScript.cs +37 -0
- package/bridge/com.ucp.bridge/Editor/Scripts/IUCPScript.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Editor/Scripts.meta +8 -0
- package/bridge/com.ucp.bridge/Editor/UCP.Bridge.Editor.asmdef +16 -0
- package/bridge/com.ucp.bridge/Editor/UCP.Bridge.Editor.asmdef.meta +7 -0
- package/bridge/com.ucp.bridge/Editor.meta +8 -0
- package/bridge/com.ucp.bridge/Runtime/UCP.Bridge.Runtime.asmdef +14 -0
- package/bridge/com.ucp.bridge/Runtime/UCP.Bridge.Runtime.asmdef.meta +7 -0
- package/bridge/com.ucp.bridge/Runtime.meta +8 -0
- package/bridge/com.ucp.bridge/Tests/Editor/ControllerSmokeTests.cs +1085 -0
- package/bridge/com.ucp.bridge/Tests/Editor/ControllerSmokeTests.cs.meta +2 -0
- package/bridge/com.ucp.bridge/Tests/Editor/UCP.Bridge.Editor.Tests.asmdef +12 -0
- package/bridge/com.ucp.bridge/Tests/Editor/UCP.Bridge.Editor.Tests.asmdef.meta +7 -0
- package/bridge/com.ucp.bridge/Tests/Editor.meta +8 -0
- package/bridge/com.ucp.bridge/Tests.meta +8 -0
- package/bridge/com.ucp.bridge/package.json +27 -0
- package/bridge/com.ucp.bridge/package.json.meta +7 -0
- package/package.json +2 -2
- package/scripts/install.js +4 -6
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using UnityEditor;
|
|
4
|
+
using UnityEngine;
|
|
5
|
+
|
|
6
|
+
namespace UCP.Bridge
|
|
7
|
+
{
|
|
8
|
+
public static class AssetImportSupport
|
|
9
|
+
{
|
|
10
|
+
private static string s_lastReimportedPathForTests;
|
|
11
|
+
|
|
12
|
+
public static string LastReimportedPathForTests => s_lastReimportedPathForTests;
|
|
13
|
+
|
|
14
|
+
public static void ClearTestState()
|
|
15
|
+
{
|
|
16
|
+
s_lastReimportedPathForTests = null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public static bool SupportsAutomaticReimport(string requestedPath)
|
|
20
|
+
{
|
|
21
|
+
var assetPath = GetPrimaryAssetPath(requestedPath);
|
|
22
|
+
return !string.IsNullOrEmpty(assetPath) && IsProjectAssetPath(assetPath);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public static string GetPrimaryAssetPath(string requestedPath)
|
|
26
|
+
{
|
|
27
|
+
var normalized = NormalizePath(requestedPath);
|
|
28
|
+
if (string.IsNullOrEmpty(normalized))
|
|
29
|
+
return normalized;
|
|
30
|
+
|
|
31
|
+
if (normalized.EndsWith(".meta", StringComparison.OrdinalIgnoreCase))
|
|
32
|
+
normalized = normalized.Substring(0, normalized.Length - 5);
|
|
33
|
+
|
|
34
|
+
return normalized;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public static AssetImporter ResolveImporter(string requestedPath)
|
|
38
|
+
{
|
|
39
|
+
var assetPath = GetPrimaryAssetPath(requestedPath);
|
|
40
|
+
if (string.IsNullOrEmpty(assetPath))
|
|
41
|
+
throw new ArgumentException("Missing 'path' parameter");
|
|
42
|
+
|
|
43
|
+
var importer = AssetImporter.GetAtPath(assetPath);
|
|
44
|
+
if (importer == null)
|
|
45
|
+
throw new ArgumentException($"No asset importer found for: {requestedPath}");
|
|
46
|
+
|
|
47
|
+
return importer;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public static Dictionary<string, object> ReimportOrDescribe(string requestedPath, bool noReimport)
|
|
51
|
+
{
|
|
52
|
+
if (noReimport)
|
|
53
|
+
return CreateReimportResult(requestedPath, GetPrimaryAssetPath(requestedPath), false, true, "Skipped by request");
|
|
54
|
+
|
|
55
|
+
if (!SupportsAutomaticReimport(requestedPath))
|
|
56
|
+
return CreateReimportResult(
|
|
57
|
+
requestedPath,
|
|
58
|
+
GetPrimaryAssetPath(requestedPath),
|
|
59
|
+
false,
|
|
60
|
+
true,
|
|
61
|
+
"Path is outside Unity-managed Assets/ or Packages/");
|
|
62
|
+
|
|
63
|
+
return Reimport(requestedPath);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public static Dictionary<string, object> Reimport(string requestedPath, bool forceSynchronous = true)
|
|
67
|
+
{
|
|
68
|
+
var assetPath = GetPrimaryAssetPath(requestedPath);
|
|
69
|
+
if (string.IsNullOrEmpty(assetPath))
|
|
70
|
+
throw new ArgumentException("Missing 'path' parameter");
|
|
71
|
+
if (!IsProjectAssetPath(assetPath))
|
|
72
|
+
throw new ArgumentException($"Path is not under Assets/ or Packages/: {requestedPath}");
|
|
73
|
+
|
|
74
|
+
var options = ImportAssetOptions.ForceUpdate;
|
|
75
|
+
if (forceSynchronous)
|
|
76
|
+
options |= ImportAssetOptions.ForceSynchronousImport;
|
|
77
|
+
|
|
78
|
+
AssetDatabase.ImportAsset(assetPath, options);
|
|
79
|
+
RecordReimport(assetPath);
|
|
80
|
+
return CreateReimportResult(requestedPath, assetPath, true, false, null);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public static Dictionary<string, object> SaveImporterSettings(string requestedPath, AssetImporter importer, bool noReimport)
|
|
84
|
+
{
|
|
85
|
+
if (importer == null)
|
|
86
|
+
throw new ArgumentNullException(nameof(importer));
|
|
87
|
+
|
|
88
|
+
var assetPath = GetPrimaryAssetPath(requestedPath);
|
|
89
|
+
if (string.IsNullOrEmpty(assetPath))
|
|
90
|
+
throw new ArgumentException("Missing 'path' parameter");
|
|
91
|
+
|
|
92
|
+
EditorUtility.SetDirty(importer);
|
|
93
|
+
|
|
94
|
+
if (noReimport)
|
|
95
|
+
{
|
|
96
|
+
AssetDatabase.WriteImportSettingsIfDirty(assetPath);
|
|
97
|
+
return CreateReimportResult(requestedPath, assetPath, false, true, "Skipped by request");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
importer.SaveAndReimport();
|
|
101
|
+
RecordReimport(assetPath);
|
|
102
|
+
return CreateReimportResult(requestedPath, assetPath, true, false, null);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private static bool IsProjectAssetPath(string assetPath)
|
|
106
|
+
{
|
|
107
|
+
return assetPath.Equals("Assets", StringComparison.OrdinalIgnoreCase)
|
|
108
|
+
|| assetPath.StartsWith("Assets/", StringComparison.OrdinalIgnoreCase)
|
|
109
|
+
|| assetPath.Equals("Packages", StringComparison.OrdinalIgnoreCase)
|
|
110
|
+
|| assetPath.StartsWith("Packages/", StringComparison.OrdinalIgnoreCase);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private static string NormalizePath(string path)
|
|
114
|
+
{
|
|
115
|
+
return path?.Trim().Replace('\\', '/');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private static void RecordReimport(string assetPath)
|
|
119
|
+
{
|
|
120
|
+
s_lastReimportedPathForTests = assetPath;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private static Dictionary<string, object> CreateReimportResult(
|
|
124
|
+
string requestedPath,
|
|
125
|
+
string assetPath,
|
|
126
|
+
bool reimported,
|
|
127
|
+
bool skipped,
|
|
128
|
+
string reason)
|
|
129
|
+
{
|
|
130
|
+
var importer = !string.IsNullOrEmpty(assetPath)
|
|
131
|
+
? AssetImporter.GetAtPath(assetPath)
|
|
132
|
+
: null;
|
|
133
|
+
|
|
134
|
+
var result = new Dictionary<string, object>
|
|
135
|
+
{
|
|
136
|
+
["requestedPath"] = requestedPath,
|
|
137
|
+
["assetPath"] = assetPath,
|
|
138
|
+
["reimported"] = reimported,
|
|
139
|
+
["skipped"] = skipped
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
if (!string.IsNullOrEmpty(reason))
|
|
143
|
+
result["reason"] = reason;
|
|
144
|
+
|
|
145
|
+
if (importer != null)
|
|
146
|
+
result["importerType"] = importer.GetType().Name;
|
|
147
|
+
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
internal static class SerializedPropertyControllerSupport
|
|
153
|
+
{
|
|
154
|
+
public static Dictionary<string, object> Describe(SerializedProperty property)
|
|
155
|
+
{
|
|
156
|
+
return new Dictionary<string, object>
|
|
157
|
+
{
|
|
158
|
+
["name"] = property.name,
|
|
159
|
+
["propertyPath"] = property.propertyPath,
|
|
160
|
+
["displayName"] = property.displayName,
|
|
161
|
+
["type"] = property.propertyType.ToString(),
|
|
162
|
+
["value"] = ReadValue(property)
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
public static object ReadValue(SerializedProperty property)
|
|
167
|
+
{
|
|
168
|
+
switch (property.propertyType)
|
|
169
|
+
{
|
|
170
|
+
case SerializedPropertyType.Integer:
|
|
171
|
+
return property.intValue;
|
|
172
|
+
case SerializedPropertyType.Boolean:
|
|
173
|
+
return property.boolValue;
|
|
174
|
+
case SerializedPropertyType.Float:
|
|
175
|
+
return (double)property.floatValue;
|
|
176
|
+
case SerializedPropertyType.String:
|
|
177
|
+
return property.stringValue;
|
|
178
|
+
case SerializedPropertyType.Color:
|
|
179
|
+
var color = property.colorValue;
|
|
180
|
+
return new List<object> { (double)color.r, (double)color.g, (double)color.b, (double)color.a };
|
|
181
|
+
case SerializedPropertyType.ObjectReference:
|
|
182
|
+
return ObjectReferenceResolver.Serialize(property.objectReferenceValue);
|
|
183
|
+
case SerializedPropertyType.Enum:
|
|
184
|
+
return property.enumValueIndex < property.enumDisplayNames.Length
|
|
185
|
+
? property.enumDisplayNames[property.enumValueIndex]
|
|
186
|
+
: property.enumValueIndex.ToString();
|
|
187
|
+
case SerializedPropertyType.Vector2:
|
|
188
|
+
var vector2 = property.vector2Value;
|
|
189
|
+
return new List<object> { (double)vector2.x, (double)vector2.y };
|
|
190
|
+
case SerializedPropertyType.Vector3:
|
|
191
|
+
var vector3 = property.vector3Value;
|
|
192
|
+
return new List<object> { (double)vector3.x, (double)vector3.y, (double)vector3.z };
|
|
193
|
+
case SerializedPropertyType.Vector4:
|
|
194
|
+
var vector4 = property.vector4Value;
|
|
195
|
+
return new List<object> { (double)vector4.x, (double)vector4.y, (double)vector4.z, (double)vector4.w };
|
|
196
|
+
case SerializedPropertyType.Quaternion:
|
|
197
|
+
var quaternion = property.quaternionValue;
|
|
198
|
+
return new List<object> { (double)quaternion.x, (double)quaternion.y, (double)quaternion.z, (double)quaternion.w };
|
|
199
|
+
case SerializedPropertyType.Rect:
|
|
200
|
+
var rect = property.rectValue;
|
|
201
|
+
return new Dictionary<string, object>
|
|
202
|
+
{
|
|
203
|
+
["x"] = (double)rect.x,
|
|
204
|
+
["y"] = (double)rect.y,
|
|
205
|
+
["width"] = (double)rect.width,
|
|
206
|
+
["height"] = (double)rect.height
|
|
207
|
+
};
|
|
208
|
+
case SerializedPropertyType.Bounds:
|
|
209
|
+
var bounds = property.boundsValue;
|
|
210
|
+
return new Dictionary<string, object>
|
|
211
|
+
{
|
|
212
|
+
["center"] = new List<object> { (double)bounds.center.x, (double)bounds.center.y, (double)bounds.center.z },
|
|
213
|
+
["size"] = new List<object> { (double)bounds.size.x, (double)bounds.size.y, (double)bounds.size.z }
|
|
214
|
+
};
|
|
215
|
+
case SerializedPropertyType.ArraySize:
|
|
216
|
+
return property.intValue;
|
|
217
|
+
case SerializedPropertyType.LayerMask:
|
|
218
|
+
return property.intValue;
|
|
219
|
+
case SerializedPropertyType.Generic:
|
|
220
|
+
if (property.isArray)
|
|
221
|
+
{
|
|
222
|
+
var items = new List<object>();
|
|
223
|
+
for (var index = 0; index < property.arraySize; index++)
|
|
224
|
+
items.Add(ReadValue(property.GetArrayElementAtIndex(index)));
|
|
225
|
+
return items;
|
|
226
|
+
}
|
|
227
|
+
return $"<{property.propertyType}>";
|
|
228
|
+
default:
|
|
229
|
+
return $"<{property.propertyType}>";
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
public static void WriteFieldValue(SerializedObject serializedObject, string ownerName, string fieldName, object value)
|
|
234
|
+
{
|
|
235
|
+
var property = serializedObject.FindProperty(fieldName);
|
|
236
|
+
if (property == null)
|
|
237
|
+
throw new ArgumentException($"Field '{fieldName}' not found on {ownerName}");
|
|
238
|
+
|
|
239
|
+
WriteValue(property, value);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
public static void WriteValue(SerializedProperty property, object value)
|
|
243
|
+
{
|
|
244
|
+
switch (property.propertyType)
|
|
245
|
+
{
|
|
246
|
+
case SerializedPropertyType.Integer:
|
|
247
|
+
property.intValue = Convert.ToInt32(value);
|
|
248
|
+
break;
|
|
249
|
+
case SerializedPropertyType.Boolean:
|
|
250
|
+
property.boolValue = Convert.ToBoolean(value);
|
|
251
|
+
break;
|
|
252
|
+
case SerializedPropertyType.Float:
|
|
253
|
+
property.floatValue = Convert.ToSingle(value);
|
|
254
|
+
break;
|
|
255
|
+
case SerializedPropertyType.String:
|
|
256
|
+
property.stringValue = value?.ToString() ?? string.Empty;
|
|
257
|
+
break;
|
|
258
|
+
case SerializedPropertyType.Color:
|
|
259
|
+
if (value is List<object> colorArray && colorArray.Count >= 3)
|
|
260
|
+
{
|
|
261
|
+
property.colorValue = new Color(
|
|
262
|
+
Convert.ToSingle(colorArray[0]),
|
|
263
|
+
Convert.ToSingle(colorArray[1]),
|
|
264
|
+
Convert.ToSingle(colorArray[2]),
|
|
265
|
+
colorArray.Count >= 4 ? Convert.ToSingle(colorArray[3]) : 1f);
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
throw new ArgumentException($"Expected an array for '{property.displayName}'");
|
|
269
|
+
case SerializedPropertyType.Enum:
|
|
270
|
+
if (value is string enumString)
|
|
271
|
+
{
|
|
272
|
+
var enumIndex = Array.IndexOf(property.enumDisplayNames, enumString);
|
|
273
|
+
if (enumIndex >= 0)
|
|
274
|
+
{
|
|
275
|
+
property.enumValueIndex = enumIndex;
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (int.TryParse(enumString, out var parsedEnumIndex))
|
|
280
|
+
{
|
|
281
|
+
property.enumValueIndex = parsedEnumIndex;
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else
|
|
286
|
+
{
|
|
287
|
+
property.enumValueIndex = Convert.ToInt32(value);
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
throw new ArgumentException($"Enum value '{value}' is not valid for '{property.displayName}'");
|
|
292
|
+
case SerializedPropertyType.Vector2:
|
|
293
|
+
if (value is List<object> vector2 && vector2.Count >= 2)
|
|
294
|
+
{
|
|
295
|
+
property.vector2Value = new Vector2(
|
|
296
|
+
Convert.ToSingle(vector2[0]),
|
|
297
|
+
Convert.ToSingle(vector2[1]));
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
throw new ArgumentException($"Expected a 2-item array for '{property.displayName}'");
|
|
301
|
+
case SerializedPropertyType.Vector3:
|
|
302
|
+
if (value is List<object> vector3 && vector3.Count >= 3)
|
|
303
|
+
{
|
|
304
|
+
property.vector3Value = new Vector3(
|
|
305
|
+
Convert.ToSingle(vector3[0]),
|
|
306
|
+
Convert.ToSingle(vector3[1]),
|
|
307
|
+
Convert.ToSingle(vector3[2]));
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
throw new ArgumentException($"Expected a 3-item array for '{property.displayName}'");
|
|
311
|
+
case SerializedPropertyType.Vector4:
|
|
312
|
+
if (value is List<object> vector4 && vector4.Count >= 4)
|
|
313
|
+
{
|
|
314
|
+
property.vector4Value = new Vector4(
|
|
315
|
+
Convert.ToSingle(vector4[0]),
|
|
316
|
+
Convert.ToSingle(vector4[1]),
|
|
317
|
+
Convert.ToSingle(vector4[2]),
|
|
318
|
+
Convert.ToSingle(vector4[3]));
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
throw new ArgumentException($"Expected a 4-item array for '{property.displayName}'");
|
|
322
|
+
case SerializedPropertyType.Quaternion:
|
|
323
|
+
if (value is List<object> quaternion && quaternion.Count >= 4)
|
|
324
|
+
{
|
|
325
|
+
property.quaternionValue = new Quaternion(
|
|
326
|
+
Convert.ToSingle(quaternion[0]),
|
|
327
|
+
Convert.ToSingle(quaternion[1]),
|
|
328
|
+
Convert.ToSingle(quaternion[2]),
|
|
329
|
+
Convert.ToSingle(quaternion[3]));
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
throw new ArgumentException($"Expected a 4-item array for '{property.displayName}'");
|
|
333
|
+
case SerializedPropertyType.ObjectReference:
|
|
334
|
+
property.objectReferenceValue = ObjectReferenceResolver.Resolve(value, property.displayName);
|
|
335
|
+
if (value != null && property.objectReferenceValue == null)
|
|
336
|
+
throw new ArgumentException($"Unable to assign object reference to '{property.displayName}'");
|
|
337
|
+
break;
|
|
338
|
+
case SerializedPropertyType.LayerMask:
|
|
339
|
+
property.intValue = Convert.ToInt32(value);
|
|
340
|
+
break;
|
|
341
|
+
case SerializedPropertyType.Generic:
|
|
342
|
+
if (property.isArray && value is List<object> items)
|
|
343
|
+
{
|
|
344
|
+
property.arraySize = items.Count;
|
|
345
|
+
for (var index = 0; index < items.Count; index++)
|
|
346
|
+
WriteValue(property.GetArrayElementAtIndex(index), items[index]);
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
throw new ArgumentException($"Cannot write property of type {property.propertyType}");
|
|
350
|
+
default:
|
|
351
|
+
throw new ArgumentException($"Cannot write property of type {property.propertyType}");
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Linq;
|
|
4
|
+
using UnityEditor;
|
|
5
|
+
using UnityEditor.Build;
|
|
6
|
+
using UnityEditor.Build.Reporting;
|
|
7
|
+
using UnityEngine;
|
|
8
|
+
|
|
9
|
+
namespace UCP.Bridge
|
|
10
|
+
{
|
|
11
|
+
public static class BuildController
|
|
12
|
+
{
|
|
13
|
+
public static void Register(CommandRouter router)
|
|
14
|
+
{
|
|
15
|
+
router.Register("build/targets", HandleTargets);
|
|
16
|
+
router.Register("build/active-target", HandleActiveTarget);
|
|
17
|
+
router.Register("build/set-target", HandleSetTarget);
|
|
18
|
+
router.Register("build/scenes", HandleScenes);
|
|
19
|
+
router.Register("build/set-scenes", HandleSetScenes);
|
|
20
|
+
router.Register("build/start", HandleStart);
|
|
21
|
+
router.Register("build/defines", HandleDefines);
|
|
22
|
+
router.Register("build/set-defines", HandleSetDefines);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private static object HandleTargets(string paramsJson)
|
|
26
|
+
{
|
|
27
|
+
var targets = new List<object>();
|
|
28
|
+
foreach (BuildTarget bt in Enum.GetValues(typeof(BuildTarget)))
|
|
29
|
+
{
|
|
30
|
+
if ((int)bt < 0) continue;
|
|
31
|
+
var group = BuildPipeline.GetBuildTargetGroup(bt);
|
|
32
|
+
if (group == BuildTargetGroup.Unknown) continue;
|
|
33
|
+
|
|
34
|
+
bool isInstalled = BuildPipeline.IsBuildTargetSupported(group, bt);
|
|
35
|
+
targets.Add(new Dictionary<string, object>
|
|
36
|
+
{
|
|
37
|
+
["name"] = bt.ToString(),
|
|
38
|
+
["group"] = group.ToString(),
|
|
39
|
+
["installed"] = isInstalled,
|
|
40
|
+
["isActive"] = bt == EditorUserBuildSettings.activeBuildTarget
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return new Dictionary<string, object>
|
|
45
|
+
{
|
|
46
|
+
["targets"] = targets,
|
|
47
|
+
["active"] = EditorUserBuildSettings.activeBuildTarget.ToString(),
|
|
48
|
+
["activeGroup"] = EditorUserBuildSettings.selectedBuildTargetGroup.ToString()
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private static object HandleActiveTarget(string paramsJson)
|
|
53
|
+
{
|
|
54
|
+
return new Dictionary<string, object>
|
|
55
|
+
{
|
|
56
|
+
["target"] = EditorUserBuildSettings.activeBuildTarget.ToString(),
|
|
57
|
+
["group"] = EditorUserBuildSettings.selectedBuildTargetGroup.ToString()
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private static object HandleSetTarget(string paramsJson)
|
|
62
|
+
{
|
|
63
|
+
var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
|
|
64
|
+
if (p == null || !p.TryGetValue("target", out var targetObj))
|
|
65
|
+
throw new ArgumentException("Missing 'target' parameter");
|
|
66
|
+
|
|
67
|
+
string targetStr = targetObj.ToString();
|
|
68
|
+
if (!Enum.TryParse<BuildTarget>(targetStr, true, out var target))
|
|
69
|
+
throw new ArgumentException($"Unknown build target: {targetStr}");
|
|
70
|
+
|
|
71
|
+
var group = BuildPipeline.GetBuildTargetGroup(target);
|
|
72
|
+
bool success = EditorUserBuildSettings.SwitchActiveBuildTarget(group, target);
|
|
73
|
+
|
|
74
|
+
return new Dictionary<string, object>
|
|
75
|
+
{
|
|
76
|
+
["status"] = success ? "ok" : "failed",
|
|
77
|
+
["target"] = target.ToString(),
|
|
78
|
+
["group"] = group.ToString()
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private static object HandleScenes(string paramsJson)
|
|
83
|
+
{
|
|
84
|
+
var scenes = new List<object>();
|
|
85
|
+
foreach (var scene in EditorBuildSettings.scenes)
|
|
86
|
+
{
|
|
87
|
+
scenes.Add(new Dictionary<string, object>
|
|
88
|
+
{
|
|
89
|
+
["path"] = scene.path,
|
|
90
|
+
["enabled"] = scene.enabled,
|
|
91
|
+
["guid"] = scene.guid.ToString()
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return new Dictionary<string, object>
|
|
96
|
+
{
|
|
97
|
+
["scenes"] = scenes
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private static object HandleSetScenes(string paramsJson)
|
|
102
|
+
{
|
|
103
|
+
var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
|
|
104
|
+
if (p == null || !p.TryGetValue("scenes", out var scenesObj))
|
|
105
|
+
throw new ArgumentException("Missing 'scenes' parameter");
|
|
106
|
+
|
|
107
|
+
var sceneList = scenesObj as List<object>;
|
|
108
|
+
if (sceneList == null)
|
|
109
|
+
throw new ArgumentException("'scenes' must be an array");
|
|
110
|
+
|
|
111
|
+
var editorScenes = new List<EditorBuildSettingsScene>();
|
|
112
|
+
foreach (var s in sceneList)
|
|
113
|
+
{
|
|
114
|
+
if (s is Dictionary<string, object> sd)
|
|
115
|
+
{
|
|
116
|
+
string path = sd.TryGetValue("path", out var pv) ? pv.ToString() : "";
|
|
117
|
+
bool enabled = !sd.TryGetValue("enabled", out var ev) || Convert.ToBoolean(ev);
|
|
118
|
+
editorScenes.Add(new EditorBuildSettingsScene(path, enabled));
|
|
119
|
+
}
|
|
120
|
+
else if (s is string path)
|
|
121
|
+
{
|
|
122
|
+
editorScenes.Add(new EditorBuildSettingsScene(path, true));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
EditorBuildSettings.scenes = editorScenes.ToArray();
|
|
127
|
+
|
|
128
|
+
return new Dictionary<string, object>
|
|
129
|
+
{
|
|
130
|
+
["status"] = "ok",
|
|
131
|
+
["count"] = editorScenes.Count
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private static object HandleStart(string paramsJson)
|
|
136
|
+
{
|
|
137
|
+
var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
|
|
138
|
+
|
|
139
|
+
string outputPath = null;
|
|
140
|
+
if (p != null && p.TryGetValue("output", out var outObj) && outObj != null)
|
|
141
|
+
outputPath = outObj.ToString();
|
|
142
|
+
|
|
143
|
+
BuildOptions options = BuildOptions.None;
|
|
144
|
+
if (p != null && p.TryGetValue("development", out var devObj) && Convert.ToBoolean(devObj))
|
|
145
|
+
options |= BuildOptions.Development;
|
|
146
|
+
|
|
147
|
+
// Use build settings scenes
|
|
148
|
+
var scenes = EditorBuildSettings.scenes
|
|
149
|
+
.Where(s => s.enabled)
|
|
150
|
+
.Select(s => s.path)
|
|
151
|
+
.ToArray();
|
|
152
|
+
|
|
153
|
+
if (scenes.Length == 0)
|
|
154
|
+
throw new ArgumentException("No scenes enabled in build settings");
|
|
155
|
+
|
|
156
|
+
if (string.IsNullOrEmpty(outputPath))
|
|
157
|
+
outputPath = "Builds/" + EditorUserBuildSettings.activeBuildTarget.ToString() + "/Build";
|
|
158
|
+
|
|
159
|
+
var buildOptions = new BuildPlayerOptions
|
|
160
|
+
{
|
|
161
|
+
scenes = scenes,
|
|
162
|
+
locationPathName = outputPath,
|
|
163
|
+
target = EditorUserBuildSettings.activeBuildTarget,
|
|
164
|
+
options = options
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
var report = BuildPipeline.BuildPlayer(buildOptions);
|
|
168
|
+
|
|
169
|
+
var steps = new List<object>();
|
|
170
|
+
foreach (var step in report.steps)
|
|
171
|
+
{
|
|
172
|
+
steps.Add(new Dictionary<string, object>
|
|
173
|
+
{
|
|
174
|
+
["name"] = step.name,
|
|
175
|
+
["duration"] = step.duration.TotalSeconds
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return new Dictionary<string, object>
|
|
180
|
+
{
|
|
181
|
+
["result"] = report.summary.result.ToString(),
|
|
182
|
+
["totalTime"] = report.summary.totalTime.TotalSeconds,
|
|
183
|
+
["totalSize"] = report.summary.totalSize,
|
|
184
|
+
["totalErrors"] = report.summary.totalErrors,
|
|
185
|
+
["totalWarnings"] = report.summary.totalWarnings,
|
|
186
|
+
["outputPath"] = report.summary.outputPath,
|
|
187
|
+
["steps"] = steps
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private static object HandleDefines(string paramsJson)
|
|
192
|
+
{
|
|
193
|
+
var group = EditorUserBuildSettings.selectedBuildTargetGroup;
|
|
194
|
+
var namedTarget = NamedBuildTarget.FromBuildTargetGroup(group);
|
|
195
|
+
string defines = PlayerSettings.GetScriptingDefineSymbols(namedTarget);
|
|
196
|
+
|
|
197
|
+
return new Dictionary<string, object>
|
|
198
|
+
{
|
|
199
|
+
["group"] = group.ToString(),
|
|
200
|
+
["defines"] = defines,
|
|
201
|
+
["list"] = defines.Split(';')
|
|
202
|
+
.Where(s => !string.IsNullOrWhiteSpace(s))
|
|
203
|
+
.Select(s => (object)s.Trim())
|
|
204
|
+
.ToList()
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private static object HandleSetDefines(string paramsJson)
|
|
209
|
+
{
|
|
210
|
+
var p = MiniJson.Deserialize(paramsJson) as Dictionary<string, object>;
|
|
211
|
+
if (p == null || !p.TryGetValue("defines", out var defObj))
|
|
212
|
+
throw new ArgumentException("Missing 'defines' parameter");
|
|
213
|
+
|
|
214
|
+
var group = EditorUserBuildSettings.selectedBuildTargetGroup;
|
|
215
|
+
string defines;
|
|
216
|
+
|
|
217
|
+
if (defObj is List<object> defList)
|
|
218
|
+
defines = string.Join(";", defList.Select(d => d.ToString()));
|
|
219
|
+
else
|
|
220
|
+
defines = defObj.ToString();
|
|
221
|
+
|
|
222
|
+
var namedTarget = NamedBuildTarget.FromBuildTargetGroup(group);
|
|
223
|
+
PlayerSettings.SetScriptingDefineSymbols(namedTarget, defines);
|
|
224
|
+
|
|
225
|
+
return new Dictionary<string, object>
|
|
226
|
+
{
|
|
227
|
+
["status"] = "ok",
|
|
228
|
+
["group"] = group.ToString(),
|
|
229
|
+
["defines"] = defines
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
using UnityEditor;
|
|
2
|
+
using UnityEditor.Compilation;
|
|
3
|
+
|
|
4
|
+
namespace UCP.Bridge
|
|
5
|
+
{
|
|
6
|
+
public static class CompilationController
|
|
7
|
+
{
|
|
8
|
+
public static void Register(CommandRouter router)
|
|
9
|
+
{
|
|
10
|
+
router.Register("compile", HandleCompile);
|
|
11
|
+
router.Register("refresh-assets", HandleRefresh);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private static object HandleCompile(string paramsJson)
|
|
15
|
+
{
|
|
16
|
+
CompilationPipeline.RequestScriptCompilation();
|
|
17
|
+
return new { status = "ok", message = "Compilation requested" };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private static object HandleRefresh(string paramsJson)
|
|
21
|
+
{
|
|
22
|
+
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
|
|
23
|
+
return new { status = "ok", message = "Asset database refreshed" };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
using UnityEditor;
|
|
2
|
+
|
|
3
|
+
namespace UCP.Bridge
|
|
4
|
+
{
|
|
5
|
+
public static class EditorController
|
|
6
|
+
{
|
|
7
|
+
public static void Register(CommandRouter router)
|
|
8
|
+
{
|
|
9
|
+
router.Register("editor/status", HandleStatus);
|
|
10
|
+
router.Register("editor/quit", HandleQuit);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
private static object HandleStatus(string paramsJson)
|
|
14
|
+
{
|
|
15
|
+
return new
|
|
16
|
+
{
|
|
17
|
+
compiling = EditorApplication.isCompiling,
|
|
18
|
+
updating = EditorApplication.isUpdating,
|
|
19
|
+
playing = EditorApplication.isPlaying,
|
|
20
|
+
willChangePlaymode = EditorApplication.isPlayingOrWillChangePlaymode,
|
|
21
|
+
timeSinceStartup = EditorApplication.timeSinceStartup
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private static object HandleQuit(string paramsJson)
|
|
26
|
+
{
|
|
27
|
+
EditorApplication.delayCall += () => EditorApplication.Exit(0);
|
|
28
|
+
return new { status = "ok", message = "Unity editor shutdown requested" };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|