@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,1085 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections;
|
|
3
|
+
using System.Collections.Generic;
|
|
4
|
+
using System.IO;
|
|
5
|
+
using System.Text.RegularExpressions;
|
|
6
|
+
using NUnit.Framework;
|
|
7
|
+
using UnityEditor;
|
|
8
|
+
using UnityEditor.SceneManagement;
|
|
9
|
+
using UnityEngine;
|
|
10
|
+
using UnityEngine.Profiling;
|
|
11
|
+
using UnityEngine.TestTools;
|
|
12
|
+
|
|
13
|
+
namespace UCP.Bridge.Tests
|
|
14
|
+
{
|
|
15
|
+
public class ControllerSmokeTests
|
|
16
|
+
{
|
|
17
|
+
private const string TempAssetPath = "Assets/UcpControllerSmoke.asset";
|
|
18
|
+
private const string TempReferenceAssetPath = "Assets/UcpControllerReference.asset";
|
|
19
|
+
private const string TempPrefabPath = "Assets/UcpControllerSmoke.prefab";
|
|
20
|
+
private const string TempMaterialPath = "Assets/UcpControllerSmoke.mat";
|
|
21
|
+
private const string TempTextPath = "Assets/UcpControllerSmoke.txt";
|
|
22
|
+
private const string TempScriptPath = "Assets/UcpControllerSmokeComponent.cs";
|
|
23
|
+
private const string TempTexturePath = "Assets/UcpImporterSmoke.png";
|
|
24
|
+
private const string TempProfilerExportPath = "ProfilerCaptures\\smoke-export.json";
|
|
25
|
+
private const string TempLocalPackageFolder = "TempUcpLocalPackage";
|
|
26
|
+
private const string TempLocalPackageName = "com.ucp.temp.local";
|
|
27
|
+
|
|
28
|
+
private CommandRouter _router;
|
|
29
|
+
|
|
30
|
+
[SetUp]
|
|
31
|
+
public void SetUp()
|
|
32
|
+
{
|
|
33
|
+
_router = new CommandRouter();
|
|
34
|
+
SnapshotController.Register(_router);
|
|
35
|
+
AssetController.Register(_router);
|
|
36
|
+
ImporterController.Register(_router);
|
|
37
|
+
LogsController.Register(_router);
|
|
38
|
+
HierarchyController.Register(_router);
|
|
39
|
+
ProfilerController.Register(_router);
|
|
40
|
+
PropertyController.Register(_router);
|
|
41
|
+
FileController.Register(_router);
|
|
42
|
+
MaterialController.Register(_router);
|
|
43
|
+
PrefabController.Register(_router);
|
|
44
|
+
BuildController.Register(_router);
|
|
45
|
+
EditorSettingsController.Register(_router);
|
|
46
|
+
SceneController.Register(_router);
|
|
47
|
+
PackagesController.Register(_router);
|
|
48
|
+
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
|
49
|
+
DeleteTempAsset();
|
|
50
|
+
DeleteTempReferenceAsset();
|
|
51
|
+
DeleteTempPrefab();
|
|
52
|
+
DeleteTempMaterial();
|
|
53
|
+
DeleteTempTextFile();
|
|
54
|
+
DeleteTempScriptFile();
|
|
55
|
+
DeleteTempTextureAsset();
|
|
56
|
+
DeleteTempProfilerExport();
|
|
57
|
+
DeleteTempLocalPackage();
|
|
58
|
+
RemoveTempLocalPackageDependencyIfPresent();
|
|
59
|
+
LogsController.ClearHistoryForTests();
|
|
60
|
+
AssetImportSupport.ClearTestState();
|
|
61
|
+
Profiler.enabled = false;
|
|
62
|
+
Profiler.enableBinaryLog = false;
|
|
63
|
+
Profiler.enableAllocationCallstacks = false;
|
|
64
|
+
Profiler.logFile = string.Empty;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
[TearDown]
|
|
68
|
+
public void TearDown()
|
|
69
|
+
{
|
|
70
|
+
DeleteTempAsset();
|
|
71
|
+
DeleteTempReferenceAsset();
|
|
72
|
+
DeleteTempPrefab();
|
|
73
|
+
DeleteTempMaterial();
|
|
74
|
+
DeleteTempTextFile();
|
|
75
|
+
DeleteTempScriptFile();
|
|
76
|
+
DeleteTempTextureAsset();
|
|
77
|
+
DeleteTempProfilerExport();
|
|
78
|
+
DeleteTempLocalPackage();
|
|
79
|
+
RemoveTempLocalPackageDependencyIfPresent();
|
|
80
|
+
LogsController.ClearHistoryForTests();
|
|
81
|
+
AssetImportSupport.ClearTestState();
|
|
82
|
+
Profiler.enabled = false;
|
|
83
|
+
Profiler.enableBinaryLog = false;
|
|
84
|
+
Profiler.enableAllocationCallstacks = false;
|
|
85
|
+
Profiler.logFile = string.Empty;
|
|
86
|
+
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
[Test]
|
|
90
|
+
public void ProfilerStatus_ReturnsCapabilitiesAndConfig()
|
|
91
|
+
{
|
|
92
|
+
var response = _router.Dispatch("profiler/status", 1, "{}");
|
|
93
|
+
|
|
94
|
+
Assert.That(response.error, Is.Null);
|
|
95
|
+
|
|
96
|
+
var result = (Dictionary<string, object>)response.result;
|
|
97
|
+
Assert.That(result.ContainsKey("session"), Is.True);
|
|
98
|
+
Assert.That(result.ContainsKey("config"), Is.True);
|
|
99
|
+
Assert.That(result.ContainsKey("capabilities"), Is.True);
|
|
100
|
+
Assert.That(result.ContainsKey("editorState"), Is.True);
|
|
101
|
+
|
|
102
|
+
var capabilities = (Dictionary<string, object>)result["capabilities"];
|
|
103
|
+
Assert.That(Convert.ToBoolean(capabilities["status"]), Is.True);
|
|
104
|
+
Assert.That(Convert.ToBoolean(capabilities["sessionControl"]), Is.True);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
[Test]
|
|
108
|
+
public void ProfilerSessionStartStop_TogglesProfilerState()
|
|
109
|
+
{
|
|
110
|
+
Profiler.maxUsedMemory = 512 * 1024 * 1024;
|
|
111
|
+
|
|
112
|
+
var start = _router.Dispatch(
|
|
113
|
+
"profiler/session/start",
|
|
114
|
+
1,
|
|
115
|
+
"{\"mode\":\"edit\",\"binaryLog\":false,\"allocationCallstacks\":true}");
|
|
116
|
+
|
|
117
|
+
Assert.That(start.error, Is.Null);
|
|
118
|
+
Assert.That(Profiler.enabled, Is.True);
|
|
119
|
+
Assert.That(Profiler.maxUsedMemory, Is.EqualTo(64 * 1024 * 1024));
|
|
120
|
+
|
|
121
|
+
var startResult = (Dictionary<string, object>)start.result;
|
|
122
|
+
Assert.That(startResult["status"], Is.EqualTo("started"));
|
|
123
|
+
var session = (Dictionary<string, object>)startResult["session"];
|
|
124
|
+
Assert.That(Convert.ToBoolean(session["active"]), Is.True);
|
|
125
|
+
Assert.That(session["effectiveMode"], Is.EqualTo("edit"));
|
|
126
|
+
|
|
127
|
+
var stop = _router.Dispatch("profiler/session/stop", 1, "{}");
|
|
128
|
+
|
|
129
|
+
Assert.That(stop.error, Is.Null);
|
|
130
|
+
Assert.That(Profiler.enabled, Is.False);
|
|
131
|
+
Assert.That(Profiler.enableAllocationCallstacks, Is.False);
|
|
132
|
+
Assert.That(Profiler.maxUsedMemory, Is.EqualTo(512 * 1024 * 1024));
|
|
133
|
+
|
|
134
|
+
var stopResult = (Dictionary<string, object>)stop.result;
|
|
135
|
+
Assert.That(stopResult["status"], Is.EqualTo("stopped"));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
[Test]
|
|
139
|
+
public void ProfilerConfigSet_UpdatesAllocationCallstacksFlag()
|
|
140
|
+
{
|
|
141
|
+
var response = _router.Dispatch(
|
|
142
|
+
"profiler/config/set",
|
|
143
|
+
1,
|
|
144
|
+
"{\"mode\":\"edit\",\"binaryLog\":false,\"allocationCallstacks\":true}");
|
|
145
|
+
|
|
146
|
+
Assert.That(response.error, Is.Null);
|
|
147
|
+
Assert.That(Profiler.enableAllocationCallstacks, Is.True);
|
|
148
|
+
|
|
149
|
+
var result = (Dictionary<string, object>)response.result;
|
|
150
|
+
var config = (Dictionary<string, object>)result["config"];
|
|
151
|
+
Assert.That(Convert.ToBoolean(config["allocationCallstacks"]), Is.True);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
[Test]
|
|
155
|
+
public void ProfilerCaptureSave_ExportsStructuredJsonSnapshot()
|
|
156
|
+
{
|
|
157
|
+
var start = _router.Dispatch(
|
|
158
|
+
"profiler/session/start",
|
|
159
|
+
1,
|
|
160
|
+
"{\"mode\":\"edit\",\"binaryLog\":false,\"allocationCallstacks\":false,\"clearFirst\":true}");
|
|
161
|
+
|
|
162
|
+
Assert.That(start.error, Is.Null);
|
|
163
|
+
|
|
164
|
+
var response = _router.Dispatch(
|
|
165
|
+
"profiler/capture/save",
|
|
166
|
+
1,
|
|
167
|
+
"{\"output\":\"ProfilerCaptures/smoke-export.json\"}");
|
|
168
|
+
|
|
169
|
+
Assert.That(response.error, Is.Null);
|
|
170
|
+
|
|
171
|
+
var result = (Dictionary<string, object>)response.result;
|
|
172
|
+
var capture = (Dictionary<string, object>)result["capture"];
|
|
173
|
+
Assert.That(capture["kind"], Is.EqualTo("json"));
|
|
174
|
+
Assert.That(Convert.ToBoolean(capture["exists"]), Is.True);
|
|
175
|
+
Assert.That(File.Exists(ResolveProjectRelativePath(TempProfilerExportPath)), Is.True);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
[Test]
|
|
179
|
+
public void Snapshot_DefaultDepth_ReturnsLeanRootMetadata()
|
|
180
|
+
{
|
|
181
|
+
var root = new GameObject("Root");
|
|
182
|
+
var child = new GameObject("Child");
|
|
183
|
+
child.transform.SetParent(root.transform, false);
|
|
184
|
+
|
|
185
|
+
var response = _router.Dispatch("snapshot", 1, "{\"depth\":0}");
|
|
186
|
+
|
|
187
|
+
Assert.That(response.error, Is.Null);
|
|
188
|
+
|
|
189
|
+
var result = (Dictionary<string, object>)response.result;
|
|
190
|
+
var objects = (List<object>)result["objects"];
|
|
191
|
+
Assert.That(objects.Count, Is.EqualTo(1));
|
|
192
|
+
|
|
193
|
+
var entry = (Dictionary<string, object>)objects[0];
|
|
194
|
+
Assert.That(entry["name"], Is.EqualTo("Root"));
|
|
195
|
+
Assert.That(Convert.ToInt32(entry["depth"]), Is.EqualTo(0));
|
|
196
|
+
Assert.That(Convert.ToInt32(entry["childCount"]), Is.EqualTo(1));
|
|
197
|
+
Assert.That(entry.ContainsKey("components"), Is.True);
|
|
198
|
+
Assert.That(entry.ContainsKey("layerName"), Is.True);
|
|
199
|
+
Assert.That(entry.ContainsKey("children"), Is.False);
|
|
200
|
+
Assert.That(entry.ContainsKey("position"), Is.False);
|
|
201
|
+
Assert.That(entry.ContainsKey("rotation"), Is.False);
|
|
202
|
+
Assert.That(result.ContainsKey("logs"), Is.False);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
[Test]
|
|
206
|
+
public void AssetSearch_FiltersActualSubassetTypeMatches()
|
|
207
|
+
{
|
|
208
|
+
var root = ScriptableObject.CreateInstance<SearchRootAsset>();
|
|
209
|
+
root.name = "SmokeRoot";
|
|
210
|
+
AssetDatabase.CreateAsset(root, TempAssetPath);
|
|
211
|
+
|
|
212
|
+
var nested = ScriptableObject.CreateInstance<SearchNestedAsset>();
|
|
213
|
+
nested.name = "SmokeNested";
|
|
214
|
+
AssetDatabase.AddObjectToAsset(nested, root);
|
|
215
|
+
AssetDatabase.ImportAsset(TempAssetPath, ImportAssetOptions.ForceSynchronousImport);
|
|
216
|
+
AssetDatabase.SaveAssets();
|
|
217
|
+
|
|
218
|
+
var response = _router.Dispatch(
|
|
219
|
+
"asset/search",
|
|
220
|
+
1,
|
|
221
|
+
"{\"name\":\"SmokeNested\",\"path\":\"Assets\",\"maxResults\":10}"
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
Assert.That(response.error, Is.Null);
|
|
225
|
+
|
|
226
|
+
var result = (Dictionary<string, object>)response.result;
|
|
227
|
+
Assert.That(Convert.ToInt32(result["total"]), Is.GreaterThanOrEqualTo(1));
|
|
228
|
+
Assert.That(Convert.ToInt32(result["returned"]), Is.GreaterThanOrEqualTo(1));
|
|
229
|
+
|
|
230
|
+
var matches = (List<object>)result["results"];
|
|
231
|
+
var match = FindAssetMatch(matches, TempAssetPath, "SmokeNested");
|
|
232
|
+
Assert.That(match, Is.Not.Null);
|
|
233
|
+
Assert.That(match["path"], Is.EqualTo(TempAssetPath));
|
|
234
|
+
Assert.That(match["type"], Is.EqualTo("SearchNestedAsset"));
|
|
235
|
+
Assert.That(match["name"], Is.EqualTo("SmokeNested"));
|
|
236
|
+
Assert.That(Convert.ToBoolean(match["isSubAsset"]), Is.True);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
[Test]
|
|
240
|
+
public void LogsTail_ReturnsRequestedBufferedCount()
|
|
241
|
+
{
|
|
242
|
+
for (var index = 0; index < 12; index++)
|
|
243
|
+
LogsController.RecordTestLog("info", $"log {index}");
|
|
244
|
+
|
|
245
|
+
var response = _router.Dispatch("logs/tail", 1, "{\"count\":50}");
|
|
246
|
+
|
|
247
|
+
Assert.That(response.error, Is.Null);
|
|
248
|
+
|
|
249
|
+
var result = (Dictionary<string, object>)response.result;
|
|
250
|
+
Assert.That(Convert.ToInt32(result["total"]), Is.EqualTo(12));
|
|
251
|
+
Assert.That(Convert.ToInt32(result["returned"]), Is.EqualTo(12));
|
|
252
|
+
Assert.That(Convert.ToBoolean(result["truncated"]), Is.False);
|
|
253
|
+
|
|
254
|
+
var logs = (List<object>)result["logs"];
|
|
255
|
+
var first = (Dictionary<string, object>)logs[0];
|
|
256
|
+
Assert.That(Convert.ToInt64(first["id"]), Is.EqualTo(12));
|
|
257
|
+
Assert.That(first.ContainsKey("messagePreview"), Is.True);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
[Test]
|
|
261
|
+
public void LogsSearch_FiltersBeforeApplyingCount()
|
|
262
|
+
{
|
|
263
|
+
LogsController.RecordTestLog("warning", "Target failed once");
|
|
264
|
+
for (var index = 0; index < 8; index++)
|
|
265
|
+
LogsController.RecordTestLog("info", $"Noise {index}");
|
|
266
|
+
|
|
267
|
+
var response = _router.Dispatch("logs/search", 1, "{\"pattern\":\"Target\",\"count\":1}");
|
|
268
|
+
|
|
269
|
+
Assert.That(response.error, Is.Null);
|
|
270
|
+
|
|
271
|
+
var result = (Dictionary<string, object>)response.result;
|
|
272
|
+
Assert.That(Convert.ToInt32(result["total"]), Is.EqualTo(1));
|
|
273
|
+
Assert.That(Convert.ToInt32(result["returned"]), Is.EqualTo(1));
|
|
274
|
+
Assert.That(Convert.ToBoolean(result["truncated"]), Is.False);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
[Test]
|
|
278
|
+
public void LogsSearch_UsesRegexAgainstBufferedHistory()
|
|
279
|
+
{
|
|
280
|
+
LogsController.RecordTestLog("info", "Alpha ready");
|
|
281
|
+
LogsController.RecordTestLog("warning", "Beta failed");
|
|
282
|
+
LogsController.RecordTestLog("error", "Gamma failed hard");
|
|
283
|
+
|
|
284
|
+
var response = _router.Dispatch("logs/search", 1, "{\"pattern\":\"failed\",\"count\":20}");
|
|
285
|
+
|
|
286
|
+
Assert.That(response.error, Is.Null);
|
|
287
|
+
|
|
288
|
+
var result = (Dictionary<string, object>)response.result;
|
|
289
|
+
Assert.That(Convert.ToInt32(result["total"]), Is.EqualTo(2));
|
|
290
|
+
|
|
291
|
+
var logs = (List<object>)result["logs"];
|
|
292
|
+
Assert.That(logs.Count, Is.EqualTo(2));
|
|
293
|
+
var first = (Dictionary<string, object>)logs[0];
|
|
294
|
+
Assert.That(first["level"], Is.EqualTo("error"));
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
[Test]
|
|
298
|
+
public void LogsTail_RespectsLevelThresholdAndIdWindow()
|
|
299
|
+
{
|
|
300
|
+
var first = LogsController.RecordTestLog("info", "Alpha");
|
|
301
|
+
var second = LogsController.RecordTestLog("warning", "Beta warning");
|
|
302
|
+
var third = LogsController.RecordTestLog("error", "Gamma error");
|
|
303
|
+
|
|
304
|
+
var response = _router.Dispatch(
|
|
305
|
+
"logs/tail",
|
|
306
|
+
1,
|
|
307
|
+
"{\"level\":\"warn\",\"afterId\":" + Convert.ToInt64(first["id"]) + ",\"beforeId\":" + Convert.ToInt64(third["id"]) + ",\"count\":20}"
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
Assert.That(response.error, Is.Null);
|
|
311
|
+
|
|
312
|
+
var result = (Dictionary<string, object>)response.result;
|
|
313
|
+
Assert.That(Convert.ToInt32(result["total"]), Is.EqualTo(1));
|
|
314
|
+
|
|
315
|
+
var logs = (List<object>)result["logs"];
|
|
316
|
+
Assert.That(logs.Count, Is.EqualTo(1));
|
|
317
|
+
var only = (Dictionary<string, object>)logs[0];
|
|
318
|
+
Assert.That(only["level"], Is.EqualTo("warning"));
|
|
319
|
+
Assert.That(Convert.ToInt64(only["id"]), Is.EqualTo(Convert.ToInt64(second["id"])));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
[Test]
|
|
323
|
+
public void LogsGet_ReturnsFullMessageAndStackTrace()
|
|
324
|
+
{
|
|
325
|
+
var created = LogsController.RecordTestLog("error", "Exploded", "stack line 1\nstack line 2");
|
|
326
|
+
var id = Convert.ToInt64(created["id"]);
|
|
327
|
+
|
|
328
|
+
var response = _router.Dispatch("logs/get", 1, "{\"id\":" + id + "}");
|
|
329
|
+
|
|
330
|
+
Assert.That(response.error, Is.Null);
|
|
331
|
+
|
|
332
|
+
var result = (Dictionary<string, object>)response.result;
|
|
333
|
+
Assert.That(result["message"], Is.EqualTo("Exploded"));
|
|
334
|
+
Assert.That(result["stackTrace"], Is.EqualTo("stack line 1\nstack line 2"));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
[Test]
|
|
338
|
+
public void ObjectLifecycle_CreateMutateAndDelete_WorksEndToEnd()
|
|
339
|
+
{
|
|
340
|
+
var create = _router.Dispatch("object/create", 1, "{\"name\":\"SmokeObject\"}");
|
|
341
|
+
Assert.That(create.error, Is.Null);
|
|
342
|
+
|
|
343
|
+
var createResult = (Dictionary<string, object>)create.result;
|
|
344
|
+
var instanceId = Convert.ToInt32(createResult["instanceId"]);
|
|
345
|
+
|
|
346
|
+
var rename = _router.Dispatch("object/set-name", 1, "{\"instanceId\":" + instanceId + ",\"name\":\"RenamedSmoke\"}");
|
|
347
|
+
Assert.That(rename.error, Is.Null);
|
|
348
|
+
|
|
349
|
+
var deactivate = _router.Dispatch("object/set-active", 1, "{\"instanceId\":" + instanceId + ",\"active\":false}");
|
|
350
|
+
Assert.That(deactivate.error, Is.Null);
|
|
351
|
+
var deactivateResult = (Dictionary<string, object>)deactivate.result;
|
|
352
|
+
Assert.That(Convert.ToBoolean(deactivateResult["active"]), Is.False);
|
|
353
|
+
|
|
354
|
+
var activate = _router.Dispatch("object/set-active", 1, "{\"instanceId\":" + instanceId + ",\"active\":true}");
|
|
355
|
+
Assert.That(activate.error, Is.Null);
|
|
356
|
+
|
|
357
|
+
var addComponent = _router.Dispatch("object/add-component", 1, "{\"instanceId\":" + instanceId + ",\"type\":\"BoxCollider\"}");
|
|
358
|
+
Assert.That(addComponent.error, Is.Null);
|
|
359
|
+
|
|
360
|
+
var setPosition = _router.Dispatch(
|
|
361
|
+
"object/set-property",
|
|
362
|
+
1,
|
|
363
|
+
"{\"instanceId\":" + instanceId + ",\"component\":\"Transform\",\"property\":\"m_LocalPosition\",\"value\":[1,2,3]}"
|
|
364
|
+
);
|
|
365
|
+
Assert.That(setPosition.error, Is.Null);
|
|
366
|
+
|
|
367
|
+
var getPosition = _router.Dispatch(
|
|
368
|
+
"object/get-property",
|
|
369
|
+
1,
|
|
370
|
+
"{\"instanceId\":" + instanceId + ",\"component\":\"Transform\",\"property\":\"m_LocalPosition\"}"
|
|
371
|
+
);
|
|
372
|
+
Assert.That(getPosition.error, Is.Null);
|
|
373
|
+
|
|
374
|
+
var updated = EditorUtility.EntityIdToObject(instanceId) as GameObject;
|
|
375
|
+
Assert.That(updated, Is.Not.Null);
|
|
376
|
+
var localPosition = updated.transform.localPosition;
|
|
377
|
+
Assert.That(localPosition.x, Is.EqualTo(1f).Within(0.001f));
|
|
378
|
+
Assert.That(localPosition.y, Is.EqualTo(2f).Within(0.001f));
|
|
379
|
+
Assert.That(localPosition.z, Is.EqualTo(3f).Within(0.001f));
|
|
380
|
+
|
|
381
|
+
var removeComponent = _router.Dispatch("object/remove-component", 1, "{\"instanceId\":" + instanceId + ",\"type\":\"BoxCollider\"}");
|
|
382
|
+
Assert.That(removeComponent.error, Is.Null);
|
|
383
|
+
|
|
384
|
+
var delete = _router.Dispatch("object/delete", 1, "{\"instanceId\":" + instanceId + "}");
|
|
385
|
+
Assert.That(delete.error, Is.Null);
|
|
386
|
+
Assert.That(EditorUtility.EntityIdToObject(instanceId), Is.Null);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
[Test]
|
|
390
|
+
public void ObjectSetProperty_AssignsObjectReferenceByAssetPath()
|
|
391
|
+
{
|
|
392
|
+
var referencedAsset = ScriptableObject.CreateInstance<SearchRootAsset>();
|
|
393
|
+
referencedAsset.name = "ReferenceAsset";
|
|
394
|
+
AssetDatabase.CreateAsset(referencedAsset, TempReferenceAssetPath);
|
|
395
|
+
AssetDatabase.SaveAssets();
|
|
396
|
+
|
|
397
|
+
var go = new GameObject("ReferenceCarrier");
|
|
398
|
+
var component = go.AddComponent<ReferenceComponent>();
|
|
399
|
+
|
|
400
|
+
var response = _router.Dispatch(
|
|
401
|
+
"object/set-property",
|
|
402
|
+
1,
|
|
403
|
+
"{\"instanceId\":" + go.GetInstanceID() + ",\"component\":\"ReferenceComponent\",\"property\":\"referenceAsset\",\"value\":{\"path\":\"" + TempReferenceAssetPath + "\"}}"
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
Assert.That(response.error, Is.Null);
|
|
407
|
+
Assert.That(component.referenceAsset, Is.Not.Null);
|
|
408
|
+
Assert.That(AssetDatabase.GetAssetPath(component.referenceAsset), Is.EqualTo(TempReferenceAssetPath));
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
[Test]
|
|
412
|
+
public void ObjectSetProperty_AssignsRendererMaterialArrayByAssetPath()
|
|
413
|
+
{
|
|
414
|
+
var shader = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard");
|
|
415
|
+
Assert.That(shader, Is.Not.Null, "Expected a lit shader to exist for the material smoke test");
|
|
416
|
+
|
|
417
|
+
var material = new Material(shader) { name = "UcpControllerSmokeMat" };
|
|
418
|
+
AssetDatabase.CreateAsset(material, TempMaterialPath);
|
|
419
|
+
AssetDatabase.SaveAssets();
|
|
420
|
+
|
|
421
|
+
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
422
|
+
var renderer = cube.GetComponent<MeshRenderer>();
|
|
423
|
+
Assert.That(renderer, Is.Not.Null);
|
|
424
|
+
|
|
425
|
+
var response = _router.Dispatch(
|
|
426
|
+
"object/set-property",
|
|
427
|
+
1,
|
|
428
|
+
"{\"instanceId\":" + cube.GetInstanceID() + ",\"component\":\"MeshRenderer\",\"property\":\"m_Materials\",\"value\":[{\"path\":\"" + TempMaterialPath + "\"}]}"
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
Assert.That(response.error, Is.Null);
|
|
432
|
+
Assert.That(renderer.sharedMaterials, Has.Length.EqualTo(1));
|
|
433
|
+
Assert.That(renderer.sharedMaterials[0], Is.Not.Null);
|
|
434
|
+
Assert.That(AssetDatabase.GetAssetPath(renderer.sharedMaterials[0]), Is.EqualTo(TempMaterialPath));
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
[Test]
|
|
438
|
+
public void ObjectSetProperty_RejectsUnknownObjectReference()
|
|
439
|
+
{
|
|
440
|
+
var go = new GameObject("ReferenceCarrier");
|
|
441
|
+
go.AddComponent<ReferenceComponent>();
|
|
442
|
+
|
|
443
|
+
var response = _router.Dispatch(
|
|
444
|
+
"object/set-property",
|
|
445
|
+
1,
|
|
446
|
+
"{\"instanceId\":" + go.GetInstanceID() + ",\"component\":\"ReferenceComponent\",\"property\":\"referenceAsset\",\"value\":{\"path\":\"Assets/Missing.asset\"}}"
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
Assert.That(response.error, Is.Not.Null);
|
|
450
|
+
Assert.That(response.error.code, Is.EqualTo(ErrorCodes.InvalidParams));
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
[Test]
|
|
454
|
+
public void AssetWriteBatch_UpdatesMultipleFieldsIncludingObjectReference()
|
|
455
|
+
{
|
|
456
|
+
var reference = ScriptableObject.CreateInstance<SearchRootAsset>();
|
|
457
|
+
reference.name = "ReferenceAsset";
|
|
458
|
+
AssetDatabase.CreateAsset(reference, TempReferenceAssetPath);
|
|
459
|
+
|
|
460
|
+
var asset = ScriptableObject.CreateInstance<BatchWritableAsset>();
|
|
461
|
+
asset.maxPlayers = 2;
|
|
462
|
+
asset.spawnDelay = 5f;
|
|
463
|
+
AssetDatabase.CreateAsset(asset, TempAssetPath);
|
|
464
|
+
AssetDatabase.SaveAssets();
|
|
465
|
+
|
|
466
|
+
var response = _router.Dispatch(
|
|
467
|
+
"asset/write-batch",
|
|
468
|
+
1,
|
|
469
|
+
"{\"path\":\"" + TempAssetPath + "\",\"values\":{\"maxPlayers\":8,\"spawnDelay\":1.5,\"referenceAsset\":{\"path\":\"" + TempReferenceAssetPath + "\"}}}"
|
|
470
|
+
);
|
|
471
|
+
|
|
472
|
+
Assert.That(response.error, Is.Null);
|
|
473
|
+
|
|
474
|
+
var reloaded = AssetDatabase.LoadAssetAtPath<BatchWritableAsset>(TempAssetPath);
|
|
475
|
+
Assert.That(reloaded.maxPlayers, Is.EqualTo(8));
|
|
476
|
+
Assert.That(reloaded.spawnDelay, Is.EqualTo(1.5f).Within(0.001f));
|
|
477
|
+
Assert.That(AssetDatabase.GetAssetPath(reloaded.referenceAsset), Is.EqualTo(TempReferenceAssetPath));
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
[Test]
|
|
481
|
+
public void FileController_WritePatchRead_AndRejectsPathTraversal()
|
|
482
|
+
{
|
|
483
|
+
var write = _router.Dispatch("file/write", 1, "{\"path\":\"Assets/UcpControllerSmoke.txt\",\"content\":\"hello smoke\"}");
|
|
484
|
+
Assert.That(write.error, Is.Null);
|
|
485
|
+
|
|
486
|
+
var patch = _router.Dispatch(
|
|
487
|
+
"file/patch",
|
|
488
|
+
1,
|
|
489
|
+
"{\"path\":\"Assets/UcpControllerSmoke.txt\",\"patch\":{\"find\":\"smoke\",\"replace\":\"patched\"}}"
|
|
490
|
+
);
|
|
491
|
+
Assert.That(patch.error, Is.Null);
|
|
492
|
+
|
|
493
|
+
var read = _router.Dispatch("file/read", 1, "{\"path\":\"Assets/UcpControllerSmoke.txt\"}");
|
|
494
|
+
Assert.That(read.error, Is.Null);
|
|
495
|
+
var readResult = (Dictionary<string, object>)read.result;
|
|
496
|
+
Assert.That(readResult["content"].ToString(), Is.EqualTo("hello patched"));
|
|
497
|
+
|
|
498
|
+
var traversal = _router.Dispatch("file/read", 1, "{\"path\":\"../outside.txt\"}");
|
|
499
|
+
Assert.That(traversal.error, Is.Not.Null);
|
|
500
|
+
Assert.That(traversal.error.code, Is.EqualTo(ErrorCodes.FileAccessDenied));
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
[Test]
|
|
504
|
+
public void FileController_Write_RefreshesAssetDatabaseForNewAssets()
|
|
505
|
+
{
|
|
506
|
+
var write = _router.Dispatch(
|
|
507
|
+
"file/write",
|
|
508
|
+
1,
|
|
509
|
+
"{\"path\":\"Assets/UcpControllerSmokeComponent.cs\",\"content\":\"using UnityEngine; public class UcpControllerSmokeComponent : MonoBehaviour {}\"}"
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
Assert.That(write.error, Is.Null);
|
|
513
|
+
|
|
514
|
+
var script = AssetDatabase.LoadAssetAtPath<MonoScript>(TempScriptPath);
|
|
515
|
+
Assert.That(script, Is.Not.Null);
|
|
516
|
+
Assert.That(script.name, Is.EqualTo("UcpControllerSmokeComponent"));
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
[Test]
|
|
520
|
+
public void FileController_Write_ReimportsOwningAssetForMetaFiles()
|
|
521
|
+
{
|
|
522
|
+
CreateTempTextureAsset(Color.cyan);
|
|
523
|
+
var metaPath = TempTexturePath + ".meta";
|
|
524
|
+
var metaContent = File.ReadAllText(ResolveProjectRelativePath(metaPath));
|
|
525
|
+
AssetImportSupport.ClearTestState();
|
|
526
|
+
|
|
527
|
+
var write = _router.Dispatch(
|
|
528
|
+
"file/write",
|
|
529
|
+
1,
|
|
530
|
+
MiniJson.Serialize(new Dictionary<string, object>
|
|
531
|
+
{
|
|
532
|
+
["path"] = metaPath,
|
|
533
|
+
["content"] = metaContent
|
|
534
|
+
}));
|
|
535
|
+
|
|
536
|
+
Assert.That(write.error, Is.Null);
|
|
537
|
+
|
|
538
|
+
var result = (Dictionary<string, object>)write.result;
|
|
539
|
+
var reimport = (Dictionary<string, object>)result["reimport"];
|
|
540
|
+
Assert.That(Convert.ToBoolean(reimport["reimported"]), Is.True);
|
|
541
|
+
Assert.That(reimport["assetPath"], Is.EqualTo(TempTexturePath));
|
|
542
|
+
Assert.That(AssetImportSupport.LastReimportedPathForTests, Is.EqualTo(TempTexturePath));
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
[Test]
|
|
546
|
+
public void ImporterController_ReadWriteAndReimport_TextureSettings()
|
|
547
|
+
{
|
|
548
|
+
CreateTempTextureAsset(Color.red);
|
|
549
|
+
|
|
550
|
+
var read = _router.Dispatch(
|
|
551
|
+
"asset/import-settings/read",
|
|
552
|
+
1,
|
|
553
|
+
"{\"path\":\"" + TempTexturePath + "\",\"field\":\"m_IsReadable\"}");
|
|
554
|
+
|
|
555
|
+
Assert.That(read.error, Is.Null);
|
|
556
|
+
var readResult = (Dictionary<string, object>)read.result;
|
|
557
|
+
Assert.That(readResult["assetPath"], Is.EqualTo(TempTexturePath));
|
|
558
|
+
Assert.That(readResult["importerType"], Is.EqualTo("TextureImporter"));
|
|
559
|
+
var fields = (List<object>)readResult["fields"];
|
|
560
|
+
Assert.That(fields.Count, Is.EqualTo(1));
|
|
561
|
+
|
|
562
|
+
AssetImportSupport.ClearTestState();
|
|
563
|
+
var write = _router.Dispatch(
|
|
564
|
+
"asset/import-settings/write",
|
|
565
|
+
1,
|
|
566
|
+
"{\"path\":\"" + TempTexturePath + "\",\"field\":\"m_IsReadable\",\"value\":true}");
|
|
567
|
+
|
|
568
|
+
Assert.That(write.error, Is.Null);
|
|
569
|
+
var writeResult = (Dictionary<string, object>)write.result;
|
|
570
|
+
var reimport = (Dictionary<string, object>)writeResult["reimport"];
|
|
571
|
+
Assert.That(Convert.ToBoolean(reimport["reimported"]), Is.True);
|
|
572
|
+
Assert.That(reimport["assetPath"], Is.EqualTo(TempTexturePath));
|
|
573
|
+
Assert.That(AssetImportSupport.LastReimportedPathForTests, Is.EqualTo(TempTexturePath));
|
|
574
|
+
|
|
575
|
+
var importer = AssetImporter.GetAtPath(TempTexturePath) as TextureImporter;
|
|
576
|
+
Assert.That(importer, Is.Not.Null);
|
|
577
|
+
Assert.That(importer.isReadable, Is.True);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
[Test]
|
|
581
|
+
public void ImporterController_WriteBatch_CanSkipReimportUntilExplicitReimport()
|
|
582
|
+
{
|
|
583
|
+
CreateTempTextureAsset(Color.green);
|
|
584
|
+
AssetImportSupport.ClearTestState();
|
|
585
|
+
|
|
586
|
+
var write = _router.Dispatch(
|
|
587
|
+
"asset/import-settings/write-batch",
|
|
588
|
+
1,
|
|
589
|
+
"{\"path\":\"" + TempTexturePath + "\",\"values\":{\"m_IsReadable\":true},\"noReimport\":true}");
|
|
590
|
+
|
|
591
|
+
Assert.That(write.error, Is.Null);
|
|
592
|
+
var writeResult = (Dictionary<string, object>)write.result;
|
|
593
|
+
var reimport = (Dictionary<string, object>)writeResult["reimport"];
|
|
594
|
+
Assert.That(Convert.ToBoolean(reimport["reimported"]), Is.False);
|
|
595
|
+
Assert.That(Convert.ToBoolean(reimport["skipped"]), Is.True);
|
|
596
|
+
Assert.That(AssetImportSupport.LastReimportedPathForTests, Is.Null);
|
|
597
|
+
|
|
598
|
+
var explicitReimport = _router.Dispatch(
|
|
599
|
+
"asset/reimport",
|
|
600
|
+
1,
|
|
601
|
+
"{\"path\":\"" + TempTexturePath + ".meta\"}");
|
|
602
|
+
|
|
603
|
+
Assert.That(explicitReimport.error, Is.Null);
|
|
604
|
+
var explicitResult = (Dictionary<string, object>)explicitReimport.result;
|
|
605
|
+
Assert.That(explicitResult["assetPath"], Is.EqualTo(TempTexturePath));
|
|
606
|
+
Assert.That(AssetImportSupport.LastReimportedPathForTests, Is.EqualTo(TempTexturePath));
|
|
607
|
+
|
|
608
|
+
var importer = AssetImporter.GetAtPath(TempTexturePath) as TextureImporter;
|
|
609
|
+
Assert.That(importer, Is.Not.Null);
|
|
610
|
+
Assert.That(importer.isReadable, Is.True);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
[Test]
|
|
614
|
+
public void PackagesController_DependencySetInfoAndRemove_LocalFilePackage()
|
|
615
|
+
{
|
|
616
|
+
CreateTempLocalPackage();
|
|
617
|
+
|
|
618
|
+
var set = _router.Dispatch(
|
|
619
|
+
"packages/dependency/set",
|
|
620
|
+
1,
|
|
621
|
+
MiniJson.Serialize(new Dictionary<string, object>
|
|
622
|
+
{
|
|
623
|
+
["name"] = TempLocalPackageName,
|
|
624
|
+
["reference"] = "file:../" + TempLocalPackageFolder
|
|
625
|
+
}));
|
|
626
|
+
|
|
627
|
+
Assert.That(set.error, Is.Null);
|
|
628
|
+
var setResult = (Dictionary<string, object>)set.result;
|
|
629
|
+
Assert.That(setResult["name"], Is.EqualTo(TempLocalPackageName));
|
|
630
|
+
Assert.That(setResult["reference"], Is.EqualTo("file:../" + TempLocalPackageFolder));
|
|
631
|
+
Assert.That(Convert.ToBoolean(setResult["changed"]), Is.True);
|
|
632
|
+
|
|
633
|
+
var info = _router.Dispatch(
|
|
634
|
+
"packages/info",
|
|
635
|
+
1,
|
|
636
|
+
MiniJson.Serialize(new Dictionary<string, object>
|
|
637
|
+
{
|
|
638
|
+
["name"] = TempLocalPackageName
|
|
639
|
+
}));
|
|
640
|
+
|
|
641
|
+
Assert.That(info.error, Is.Null);
|
|
642
|
+
var infoResult = (Dictionary<string, object>)info.result;
|
|
643
|
+
Assert.That(infoResult["name"], Is.EqualTo(TempLocalPackageName));
|
|
644
|
+
Assert.That(Convert.ToBoolean(infoResult["installed"]), Is.True);
|
|
645
|
+
Assert.That(Convert.ToBoolean(infoResult["directDependency"]), Is.True);
|
|
646
|
+
Assert.That(infoResult["source"], Is.EqualTo("Local"));
|
|
647
|
+
|
|
648
|
+
var dependencies = _router.Dispatch("packages/dependencies", 1, "{}");
|
|
649
|
+
Assert.That(dependencies.error, Is.Null);
|
|
650
|
+
var dependencyResult = (Dictionary<string, object>)dependencies.result;
|
|
651
|
+
var entries = (List<object>)dependencyResult["dependencies"];
|
|
652
|
+
Assert.That(entries.Exists(item =>
|
|
653
|
+
{
|
|
654
|
+
var entry = (Dictionary<string, object>)item;
|
|
655
|
+
return entry["name"].ToString() == TempLocalPackageName
|
|
656
|
+
&& entry["reference"].ToString() == "file:../" + TempLocalPackageFolder;
|
|
657
|
+
}), Is.True);
|
|
658
|
+
|
|
659
|
+
var remove = _router.Dispatch(
|
|
660
|
+
"packages/dependency/remove",
|
|
661
|
+
1,
|
|
662
|
+
MiniJson.Serialize(new Dictionary<string, object>
|
|
663
|
+
{
|
|
664
|
+
["name"] = TempLocalPackageName
|
|
665
|
+
}));
|
|
666
|
+
|
|
667
|
+
Assert.That(remove.error, Is.Null);
|
|
668
|
+
var removeResult = (Dictionary<string, object>)remove.result;
|
|
669
|
+
Assert.That(removeResult["name"], Is.EqualTo(TempLocalPackageName));
|
|
670
|
+
Assert.That(removeResult["previousReference"], Is.EqualTo("file:../" + TempLocalPackageFolder));
|
|
671
|
+
|
|
672
|
+
var after = _router.Dispatch("packages/dependencies", 1, "{}");
|
|
673
|
+
Assert.That(after.error, Is.Null);
|
|
674
|
+
var afterEntries = (List<object>)((Dictionary<string, object>)after.result)["dependencies"];
|
|
675
|
+
Assert.That(afterEntries.Exists(item =>
|
|
676
|
+
{
|
|
677
|
+
var entry = (Dictionary<string, object>)item;
|
|
678
|
+
return entry["name"].ToString() == TempLocalPackageName;
|
|
679
|
+
}), Is.False);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
[Test]
|
|
683
|
+
public void SceneFocus_WithAxis_AlignsSceneCameraTowardTarget()
|
|
684
|
+
{
|
|
685
|
+
var sceneView = EditorWindow.GetWindow<SceneView>();
|
|
686
|
+
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
687
|
+
cube.name = "FocusTarget";
|
|
688
|
+
cube.transform.position = new Vector3(2f, 1f, 3f);
|
|
689
|
+
cube.transform.localScale = new Vector3(2f, 2f, 2f);
|
|
690
|
+
|
|
691
|
+
var response = _router.Dispatch(
|
|
692
|
+
"scene/focus",
|
|
693
|
+
1,
|
|
694
|
+
"{\"instanceId\":" + cube.GetInstanceID() + ",\"axis\":[1,0,1]}"
|
|
695
|
+
);
|
|
696
|
+
|
|
697
|
+
Assert.That(response.error, Is.Null);
|
|
698
|
+
|
|
699
|
+
var result = (Dictionary<string, object>)response.result;
|
|
700
|
+
Assert.That(result["name"].ToString(), Is.EqualTo("FocusTarget"));
|
|
701
|
+
Assert.That(Selection.activeGameObject, Is.EqualTo(cube));
|
|
702
|
+
|
|
703
|
+
var expectedDirection = new Vector3(1f, 0f, 1f).normalized;
|
|
704
|
+
var axisData = (List<object>)result["axis"];
|
|
705
|
+
var returnedAxis = new Vector3(
|
|
706
|
+
System.Convert.ToSingle(axisData[0]),
|
|
707
|
+
System.Convert.ToSingle(axisData[1]),
|
|
708
|
+
System.Convert.ToSingle(axisData[2]));
|
|
709
|
+
var actualForward = sceneView.camera.transform.forward;
|
|
710
|
+
Assert.That(Vector3.Dot(returnedAxis.normalized, expectedDirection), Is.GreaterThan(0.98f));
|
|
711
|
+
Assert.That(Mathf.Abs(Vector3.Dot(actualForward.normalized, expectedDirection)), Is.GreaterThan(0.98f));
|
|
712
|
+
Assert.That(Vector3.Distance(sceneView.pivot, cube.transform.position), Is.LessThan(2f));
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
[Test]
|
|
716
|
+
public void SceneFocus_RejectsZeroAxisVector()
|
|
717
|
+
{
|
|
718
|
+
EditorWindow.GetWindow<SceneView>();
|
|
719
|
+
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
720
|
+
cube.name = "ZeroAxisTarget";
|
|
721
|
+
|
|
722
|
+
var response = _router.Dispatch(
|
|
723
|
+
"scene/focus",
|
|
724
|
+
1,
|
|
725
|
+
"{\"instanceId\":" + cube.GetInstanceID() + ",\"axis\":[0,0,0]}"
|
|
726
|
+
);
|
|
727
|
+
|
|
728
|
+
Assert.That(response.error, Is.Not.Null);
|
|
729
|
+
Assert.That(response.error.code, Is.EqualTo(ErrorCodes.InvalidParams));
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
[Test]
|
|
733
|
+
public void MaterialController_SetAndGetFloatProperty_RoundTrips()
|
|
734
|
+
{
|
|
735
|
+
var shader = Shader.Find("Standard") ?? Shader.Find("Universal Render Pipeline/Lit");
|
|
736
|
+
Assert.That(shader, Is.Not.Null);
|
|
737
|
+
|
|
738
|
+
var propertyName = FindFirstFloatOrRangeProperty(shader);
|
|
739
|
+
Assert.That(propertyName, Is.Not.Null.And.Not.Empty);
|
|
740
|
+
|
|
741
|
+
var material = new Material(shader) { name = "UcpControllerSmokeMat" };
|
|
742
|
+
AssetDatabase.CreateAsset(material, TempMaterialPath);
|
|
743
|
+
AssetDatabase.SaveAssets();
|
|
744
|
+
|
|
745
|
+
var set = _router.Dispatch(
|
|
746
|
+
"material/set-property",
|
|
747
|
+
1,
|
|
748
|
+
"{\"path\":\"Assets/UcpControllerSmoke.mat\",\"property\":\"" + propertyName + "\",\"value\":0.42}"
|
|
749
|
+
);
|
|
750
|
+
Assert.That(set.error, Is.Null);
|
|
751
|
+
|
|
752
|
+
var get = _router.Dispatch(
|
|
753
|
+
"material/get-property",
|
|
754
|
+
1,
|
|
755
|
+
"{\"path\":\"Assets/UcpControllerSmoke.mat\",\"property\":\"" + propertyName + "\"}"
|
|
756
|
+
);
|
|
757
|
+
Assert.That(get.error, Is.Null);
|
|
758
|
+
|
|
759
|
+
var getResult = (Dictionary<string, object>)get.result;
|
|
760
|
+
var value = Convert.ToSingle(getResult["value"]);
|
|
761
|
+
Assert.That(value, Is.EqualTo(0.42f).Within(0.001f));
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
[Test]
|
|
765
|
+
public void PrefabController_CreateStatusOverridesAndUnpack_Works()
|
|
766
|
+
{
|
|
767
|
+
var create = _router.Dispatch("object/create", 1, "{\"name\":\"PrefabSource\"}");
|
|
768
|
+
Assert.That(create.error, Is.Null);
|
|
769
|
+
var sourceId = Convert.ToInt32(((Dictionary<string, object>)create.result)["instanceId"]);
|
|
770
|
+
|
|
771
|
+
var createPrefab = _router.Dispatch(
|
|
772
|
+
"prefab/create",
|
|
773
|
+
1,
|
|
774
|
+
"{\"instanceId\":" + sourceId + ",\"path\":\"Assets/UcpControllerSmoke.prefab\"}"
|
|
775
|
+
);
|
|
776
|
+
Assert.That(createPrefab.error, Is.Null);
|
|
777
|
+
|
|
778
|
+
var instantiate = _router.Dispatch(
|
|
779
|
+
"object/instantiate",
|
|
780
|
+
1,
|
|
781
|
+
"{\"prefab\":\"Assets/UcpControllerSmoke.prefab\",\"name\":\"PrefabInstance\"}"
|
|
782
|
+
);
|
|
783
|
+
Assert.That(instantiate.error, Is.Null);
|
|
784
|
+
var instanceId = Convert.ToInt32(((Dictionary<string, object>)instantiate.result)["instanceId"]);
|
|
785
|
+
|
|
786
|
+
var status = _router.Dispatch("prefab/status", 1, "{\"instanceId\":" + instanceId + "}");
|
|
787
|
+
Assert.That(status.error, Is.Null);
|
|
788
|
+
var statusResult = (Dictionary<string, object>)status.result;
|
|
789
|
+
Assert.That(Convert.ToBoolean(statusResult["isInstance"]), Is.True);
|
|
790
|
+
|
|
791
|
+
var mutate = _router.Dispatch(
|
|
792
|
+
"object/set-property",
|
|
793
|
+
1,
|
|
794
|
+
"{\"instanceId\":" + instanceId + ",\"component\":\"Transform\",\"property\":\"m_LocalPosition\",\"value\":[2,0,0]}"
|
|
795
|
+
);
|
|
796
|
+
Assert.That(mutate.error, Is.Null);
|
|
797
|
+
|
|
798
|
+
var overrides = _router.Dispatch("prefab/overrides", 1, "{\"instanceId\":" + instanceId + "}");
|
|
799
|
+
Assert.That(overrides.error, Is.Null);
|
|
800
|
+
var overridesResult = (Dictionary<string, object>)overrides.result;
|
|
801
|
+
var modifications = (List<object>)overridesResult["propertyModifications"];
|
|
802
|
+
Assert.That(modifications.Count, Is.GreaterThanOrEqualTo(1));
|
|
803
|
+
|
|
804
|
+
var unpack = _router.Dispatch("prefab/unpack", 1, "{\"instanceId\":" + instanceId + "}");
|
|
805
|
+
Assert.That(unpack.error, Is.Null);
|
|
806
|
+
|
|
807
|
+
var unpackedStatus = _router.Dispatch("prefab/status", 1, "{\"instanceId\":" + instanceId + "}");
|
|
808
|
+
Assert.That(unpackedStatus.error, Is.Null);
|
|
809
|
+
var unpackedStatusResult = (Dictionary<string, object>)unpackedStatus.result;
|
|
810
|
+
Assert.That(Convert.ToBoolean(unpackedStatusResult["isInstance"]), Is.False);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
[Test]
|
|
814
|
+
public void SettingsAndBuildControllers_RoundTripWithoutSideEffects()
|
|
815
|
+
{
|
|
816
|
+
var playerSettings = _router.Dispatch("settings/player", 1, "{}");
|
|
817
|
+
Assert.That(playerSettings.error, Is.Null);
|
|
818
|
+
var settingsResult = (Dictionary<string, object>)playerSettings.result;
|
|
819
|
+
var originalProductName = settingsResult["productName"].ToString();
|
|
820
|
+
|
|
821
|
+
var setPlayer = _router.Dispatch(
|
|
822
|
+
"settings/player-set",
|
|
823
|
+
1,
|
|
824
|
+
"{\"key\":\"productName\",\"value\":\"UcpQaProduct\"}"
|
|
825
|
+
);
|
|
826
|
+
Assert.That(setPlayer.error, Is.Null);
|
|
827
|
+
|
|
828
|
+
var verifyPlayer = _router.Dispatch("settings/player", 1, "{}");
|
|
829
|
+
Assert.That(verifyPlayer.error, Is.Null);
|
|
830
|
+
var verifyResult = (Dictionary<string, object>)verifyPlayer.result;
|
|
831
|
+
Assert.That(verifyResult["productName"].ToString(), Is.EqualTo("UcpQaProduct"));
|
|
832
|
+
|
|
833
|
+
var restorePlayer = _router.Dispatch(
|
|
834
|
+
"settings/player-set",
|
|
835
|
+
1,
|
|
836
|
+
"{\"key\":\"productName\",\"value\":\"" + originalProductName + "\"}"
|
|
837
|
+
);
|
|
838
|
+
Assert.That(restorePlayer.error, Is.Null);
|
|
839
|
+
|
|
840
|
+
var scenes = _router.Dispatch("build/scenes", 1, "{}");
|
|
841
|
+
Assert.That(scenes.error, Is.Null);
|
|
842
|
+
var scenesResult = (Dictionary<string, object>)scenes.result;
|
|
843
|
+
var currentScenes = (List<object>)scenesResult["scenes"];
|
|
844
|
+
Assert.That(currentScenes.Count, Is.GreaterThanOrEqualTo(1));
|
|
845
|
+
|
|
846
|
+
var firstScene = (Dictionary<string, object>)currentScenes[0];
|
|
847
|
+
var firstScenePath = firstScene["path"].ToString();
|
|
848
|
+
|
|
849
|
+
var setScenes = _router.Dispatch(
|
|
850
|
+
"build/set-scenes",
|
|
851
|
+
1,
|
|
852
|
+
"{\"scenes\":[\"" + EscapeForJson(firstScenePath) + "\"]}"
|
|
853
|
+
);
|
|
854
|
+
Assert.That(setScenes.error, Is.Null);
|
|
855
|
+
|
|
856
|
+
var defines = _router.Dispatch("build/defines", 1, "{}");
|
|
857
|
+
Assert.That(defines.error, Is.Null);
|
|
858
|
+
var definesResult = (Dictionary<string, object>)defines.result;
|
|
859
|
+
var originalDefines = definesResult["defines"].ToString();
|
|
860
|
+
|
|
861
|
+
var setDefines = _router.Dispatch("build/set-defines", 1, "{\"defines\":\"" + EscapeForJson(originalDefines) + "\"}");
|
|
862
|
+
Assert.That(setDefines.error, Is.Null);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
private static void DeleteTempAsset()
|
|
866
|
+
{
|
|
867
|
+
if (AssetDatabase.LoadMainAssetAtPath(TempAssetPath) != null)
|
|
868
|
+
{
|
|
869
|
+
AssetDatabase.DeleteAsset(TempAssetPath);
|
|
870
|
+
AssetDatabase.SaveAssets();
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
private static void DeleteTempReferenceAsset()
|
|
875
|
+
{
|
|
876
|
+
if (AssetDatabase.LoadMainAssetAtPath(TempReferenceAssetPath) != null)
|
|
877
|
+
{
|
|
878
|
+
AssetDatabase.DeleteAsset(TempReferenceAssetPath);
|
|
879
|
+
AssetDatabase.SaveAssets();
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
private static void DeleteTempPrefab()
|
|
884
|
+
{
|
|
885
|
+
if (AssetDatabase.LoadMainAssetAtPath(TempPrefabPath) != null)
|
|
886
|
+
{
|
|
887
|
+
AssetDatabase.DeleteAsset(TempPrefabPath);
|
|
888
|
+
AssetDatabase.SaveAssets();
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
private static void DeleteTempMaterial()
|
|
893
|
+
{
|
|
894
|
+
if (AssetDatabase.LoadMainAssetAtPath(TempMaterialPath) != null)
|
|
895
|
+
{
|
|
896
|
+
AssetDatabase.DeleteAsset(TempMaterialPath);
|
|
897
|
+
AssetDatabase.SaveAssets();
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
private static void DeleteTempTextFile()
|
|
902
|
+
{
|
|
903
|
+
if (AssetDatabase.LoadMainAssetAtPath(TempTextPath) != null)
|
|
904
|
+
{
|
|
905
|
+
AssetDatabase.DeleteAsset(TempTextPath);
|
|
906
|
+
AssetDatabase.SaveAssets();
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
private static void DeleteTempScriptFile()
|
|
911
|
+
{
|
|
912
|
+
if (AssetDatabase.LoadMainAssetAtPath(TempScriptPath) != null)
|
|
913
|
+
{
|
|
914
|
+
AssetDatabase.DeleteAsset(TempScriptPath);
|
|
915
|
+
AssetDatabase.SaveAssets();
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
private static void DeleteTempTextureAsset()
|
|
920
|
+
{
|
|
921
|
+
if (AssetDatabase.LoadMainAssetAtPath(TempTexturePath) != null)
|
|
922
|
+
{
|
|
923
|
+
AssetDatabase.DeleteAsset(TempTexturePath);
|
|
924
|
+
AssetDatabase.SaveAssets();
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
var fullPath = ResolveProjectRelativePath(TempTexturePath);
|
|
928
|
+
if (File.Exists(fullPath))
|
|
929
|
+
File.Delete(fullPath);
|
|
930
|
+
|
|
931
|
+
var metaPath = fullPath + ".meta";
|
|
932
|
+
if (File.Exists(metaPath))
|
|
933
|
+
File.Delete(metaPath);
|
|
934
|
+
|
|
935
|
+
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
private static void DeleteTempProfilerExport()
|
|
939
|
+
{
|
|
940
|
+
var fullPath = ResolveProjectRelativePath(TempProfilerExportPath);
|
|
941
|
+
if (File.Exists(fullPath))
|
|
942
|
+
File.Delete(fullPath);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
private void RemoveTempLocalPackageDependencyIfPresent()
|
|
946
|
+
{
|
|
947
|
+
var manifestPath = ResolveProjectRootRelativePath("Packages/manifest.json");
|
|
948
|
+
if (!File.Exists(manifestPath))
|
|
949
|
+
return;
|
|
950
|
+
|
|
951
|
+
var manifest = MiniJson.Deserialize(File.ReadAllText(manifestPath)) as Dictionary<string, object>;
|
|
952
|
+
if (manifest == null
|
|
953
|
+
|| !manifest.TryGetValue("dependencies", out var dependenciesObj)
|
|
954
|
+
|| !(dependenciesObj is Dictionary<string, object> dependencies)
|
|
955
|
+
|| !dependencies.ContainsKey(TempLocalPackageName))
|
|
956
|
+
{
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
var remove = _router.Dispatch(
|
|
961
|
+
"packages/dependency/remove",
|
|
962
|
+
1,
|
|
963
|
+
MiniJson.Serialize(new Dictionary<string, object>
|
|
964
|
+
{
|
|
965
|
+
["name"] = TempLocalPackageName
|
|
966
|
+
}));
|
|
967
|
+
|
|
968
|
+
Assert.That(remove.error, Is.Null, "Temp local package dependency cleanup should succeed");
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
private static void CreateTempLocalPackage()
|
|
972
|
+
{
|
|
973
|
+
DeleteTempLocalPackage();
|
|
974
|
+
var packageRoot = ResolveProjectRootRelativePath(TempLocalPackageFolder);
|
|
975
|
+
Directory.CreateDirectory(packageRoot);
|
|
976
|
+
File.WriteAllText(
|
|
977
|
+
Path.Combine(packageRoot, "package.json"),
|
|
978
|
+
"{\n"
|
|
979
|
+
+ " \"name\": \"" + TempLocalPackageName + "\",\n"
|
|
980
|
+
+ " \"version\": \"1.0.0\",\n"
|
|
981
|
+
+ " \"displayName\": \"UCP Temp Local Package\",\n"
|
|
982
|
+
+ " \"unity\": \"2021.3\",\n"
|
|
983
|
+
+ " \"description\": \"Temporary local package for controller smoke tests.\"\n"
|
|
984
|
+
+ "}");
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
private static void DeleteTempLocalPackage()
|
|
988
|
+
{
|
|
989
|
+
var packageRoot = ResolveProjectRootRelativePath(TempLocalPackageFolder);
|
|
990
|
+
if (Directory.Exists(packageRoot))
|
|
991
|
+
Directory.Delete(packageRoot, true);
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
private static void CreateTempTextureAsset(Color color)
|
|
995
|
+
{
|
|
996
|
+
DeleteTempTextureAsset();
|
|
997
|
+
|
|
998
|
+
var texture = new Texture2D(2, 2, TextureFormat.RGBA32, false);
|
|
999
|
+
texture.SetPixels(new[]
|
|
1000
|
+
{
|
|
1001
|
+
color,
|
|
1002
|
+
color,
|
|
1003
|
+
color,
|
|
1004
|
+
color
|
|
1005
|
+
});
|
|
1006
|
+
texture.Apply();
|
|
1007
|
+
|
|
1008
|
+
var bytes = texture.EncodeToPNG();
|
|
1009
|
+
UnityEngine.Object.DestroyImmediate(texture);
|
|
1010
|
+
|
|
1011
|
+
File.WriteAllBytes(ResolveProjectRelativePath(TempTexturePath), bytes);
|
|
1012
|
+
AssetDatabase.ImportAsset(
|
|
1013
|
+
TempTexturePath,
|
|
1014
|
+
ImportAssetOptions.ForceUpdate | ImportAssetOptions.ForceSynchronousImport);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
private static string ResolveProjectRelativePath(string assetPath)
|
|
1018
|
+
{
|
|
1019
|
+
var projectRoot = Path.GetDirectoryName(Application.dataPath);
|
|
1020
|
+
return Path.Combine(projectRoot, assetPath.Replace('/', Path.DirectorySeparatorChar));
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
private static string ResolveProjectRootRelativePath(string relativePath)
|
|
1024
|
+
{
|
|
1025
|
+
var projectRoot = Path.GetDirectoryName(Application.dataPath);
|
|
1026
|
+
return Path.Combine(projectRoot, relativePath.Replace('/', Path.DirectorySeparatorChar));
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
private static string FindFirstFloatOrRangeProperty(Shader shader)
|
|
1030
|
+
{
|
|
1031
|
+
for (var index = 0; index < shader.GetPropertyCount(); index++)
|
|
1032
|
+
{
|
|
1033
|
+
var propertyType = shader.GetPropertyType(index);
|
|
1034
|
+
if (propertyType == UnityEngine.Rendering.ShaderPropertyType.Float
|
|
1035
|
+
|| propertyType == UnityEngine.Rendering.ShaderPropertyType.Range)
|
|
1036
|
+
{
|
|
1037
|
+
return shader.GetPropertyName(index);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
return null;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
private static string EscapeForJson(string value)
|
|
1045
|
+
{
|
|
1046
|
+
return value
|
|
1047
|
+
.Replace("\\", "\\\\")
|
|
1048
|
+
.Replace("\"", "\\\"");
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
private static Dictionary<string, object> FindAssetMatch(List<object> matches, string expectedPath, string expectedName)
|
|
1052
|
+
{
|
|
1053
|
+
foreach (var entry in matches)
|
|
1054
|
+
{
|
|
1055
|
+
var match = (Dictionary<string, object>)entry;
|
|
1056
|
+
var path = match.ContainsKey("path") ? match["path"].ToString() : string.Empty;
|
|
1057
|
+
var name = match.ContainsKey("name") ? match["name"].ToString() : string.Empty;
|
|
1058
|
+
if (path == expectedPath && name == expectedName)
|
|
1059
|
+
return match;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
return null;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
private sealed class SearchRootAsset : ScriptableObject
|
|
1066
|
+
{
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
private sealed class SearchNestedAsset : ScriptableObject
|
|
1070
|
+
{
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
private sealed class BatchWritableAsset : ScriptableObject
|
|
1074
|
+
{
|
|
1075
|
+
public int maxPlayers;
|
|
1076
|
+
public float spawnDelay;
|
|
1077
|
+
public SearchRootAsset referenceAsset;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
private sealed class ReferenceComponent : MonoBehaviour
|
|
1081
|
+
{
|
|
1082
|
+
public SearchRootAsset referenceAsset;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|