@mflrevan/ucp 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bridge/com.ucp.bridge/CHANGELOG.md +48 -0
- package/bridge/com.ucp.bridge/Editor/Bridge/BridgeServer.cs +55 -6
- package/bridge/com.ucp.bridge/Editor/Bridge/EditorStateSummary.cs +165 -0
- package/bridge/com.ucp.bridge/Editor/Bridge/EditorStateSummary.cs.meta +11 -0
- package/bridge/com.ucp.bridge/Editor/Compatibility/UnityObjectCompat.cs +22 -5
- package/bridge/com.ucp.bridge/Editor/Controllers/EditorController.cs +1 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/HierarchyController.cs +10 -10
- package/bridge/com.ucp.bridge/Editor/Controllers/LogsController.cs +71 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/MaterialController.cs +2 -2
- package/bridge/com.ucp.bridge/Editor/Controllers/ObjectLocator.cs +4 -4
- package/bridge/com.ucp.bridge/Editor/Controllers/ObjectReferenceResolver.cs +3 -3
- package/bridge/com.ucp.bridge/Editor/Controllers/PrefabController.cs +6 -6
- package/bridge/com.ucp.bridge/Editor/Controllers/PropertyController.cs +7 -7
- package/bridge/com.ucp.bridge/Editor/Controllers/RecordingController.cs +8 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/SceneChangeTracker.cs +3 -3
- package/bridge/com.ucp.bridge/Editor/Controllers/SceneController.cs +3 -3
- package/bridge/com.ucp.bridge/Editor/Controllers/SnapshotController.cs +5 -5
- package/bridge/com.ucp.bridge/Editor/Controllers/TestRunnerController.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/Controllers/TransformController.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/Controllers/UiController.cs +70 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/UiController.cs.meta +11 -0
- package/bridge/com.ucp.bridge/Editor/Controllers/ViewController.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/Protocol/MiniJson.cs +1 -1
- package/bridge/com.ucp.bridge/Editor/Ui/UiHost.cs +468 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiHost.cs.meta +11 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiLintService.cs +554 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiLintService.cs.meta +11 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiOperationManager.cs +870 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiOperationManager.cs.meta +11 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiScenarioApplier.cs +496 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiScenarioApplier.cs.meta +11 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiScenarioLoader.cs +854 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiScenarioLoader.cs.meta +11 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiScenarioModels.cs +374 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiScenarioModels.cs.meta +11 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiVisualTreeInspector.cs +690 -0
- package/bridge/com.ucp.bridge/Editor/Ui/UiVisualTreeInspector.cs.meta +11 -0
- package/bridge/com.ucp.bridge/{Runtime.meta → Editor/Ui.meta} +1 -1
- package/bridge/com.ucp.bridge/Tests/Editor/ControllerSmokeTests.cs +79 -4
- package/bridge/com.ucp.bridge/Tests/Editor/SpatialVisualControllerTests.cs +2 -2
- package/bridge/com.ucp.bridge/Tests/Editor/UiControllerTests.cs +547 -0
- package/bridge/com.ucp.bridge/Tests/Editor/UiControllerTests.cs.meta +11 -0
- package/bridge/com.ucp.bridge/Tests/Editor/UiLintServiceTests.cs +253 -0
- package/bridge/com.ucp.bridge/Tests/Editor/UiLintServiceTests.cs.meta +11 -0
- package/bridge/com.ucp.bridge/Tests/Editor/UiScenarioTests.cs +587 -0
- package/bridge/com.ucp.bridge/Tests/Editor/UiScenarioTests.cs.meta +11 -0
- package/bridge/com.ucp.bridge/package.json +1 -1
- package/package.json +1 -1
- package/bridge/com.ucp.bridge/Runtime/UCP.Bridge.Runtime.asmdef +0 -14
- package/bridge/com.ucp.bridge/Runtime/UCP.Bridge.Runtime.asmdef.meta +0 -7
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
#if UNITY_6000_0_OR_NEWER
|
|
2
|
+
using System;
|
|
3
|
+
using System.Collections.Generic;
|
|
4
|
+
using UnityEngine;
|
|
5
|
+
using UnityEngine.UIElements;
|
|
6
|
+
|
|
7
|
+
namespace UCP.Bridge
|
|
8
|
+
{
|
|
9
|
+
internal sealed class UiScenarioException : ArgumentException
|
|
10
|
+
{
|
|
11
|
+
public UiScenarioException(string code, string message, string location = null)
|
|
12
|
+
: base(location == null ? message : $"{message} ({location})")
|
|
13
|
+
{
|
|
14
|
+
Code = code;
|
|
15
|
+
Location = location;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public string Code { get; }
|
|
19
|
+
public string Location { get; }
|
|
20
|
+
|
|
21
|
+
public Dictionary<string, object> ToDictionary()
|
|
22
|
+
{
|
|
23
|
+
return new Dictionary<string, object>
|
|
24
|
+
{
|
|
25
|
+
["severity"] = "error",
|
|
26
|
+
["code"] = Code,
|
|
27
|
+
["message"] = Message,
|
|
28
|
+
["location"] = Location
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
internal sealed class UiViewport
|
|
34
|
+
{
|
|
35
|
+
public const int DefaultWidth = 960;
|
|
36
|
+
public const int DefaultHeight = 640;
|
|
37
|
+
|
|
38
|
+
public UiViewport(int width = DefaultWidth, int height = DefaultHeight)
|
|
39
|
+
{
|
|
40
|
+
Width = width;
|
|
41
|
+
Height = height;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public int Width { get; }
|
|
45
|
+
public int Height { get; }
|
|
46
|
+
|
|
47
|
+
public Dictionary<string, object> ToDictionary()
|
|
48
|
+
{
|
|
49
|
+
return new Dictionary<string, object>
|
|
50
|
+
{
|
|
51
|
+
["width"] = Width,
|
|
52
|
+
["height"] = Height
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
internal sealed class UiSettleOptions
|
|
58
|
+
{
|
|
59
|
+
public const int DefaultStableFrames = 3;
|
|
60
|
+
public const int DefaultPixelStableFrames = 2;
|
|
61
|
+
public const double DefaultTimeoutSeconds = 15.0;
|
|
62
|
+
|
|
63
|
+
public UiSettleOptions(
|
|
64
|
+
int stableFrames = DefaultStableFrames,
|
|
65
|
+
int pixelStableFrames = DefaultPixelStableFrames,
|
|
66
|
+
double timeoutSeconds = DefaultTimeoutSeconds)
|
|
67
|
+
{
|
|
68
|
+
StableFrames = stableFrames;
|
|
69
|
+
PixelStableFrames = pixelStableFrames;
|
|
70
|
+
TimeoutSeconds = timeoutSeconds;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public int StableFrames { get; }
|
|
74
|
+
public int PixelStableFrames { get; }
|
|
75
|
+
public double TimeoutSeconds { get; }
|
|
76
|
+
|
|
77
|
+
public Dictionary<string, object> ToDictionary()
|
|
78
|
+
{
|
|
79
|
+
return new Dictionary<string, object>
|
|
80
|
+
{
|
|
81
|
+
["stableFrames"] = StableFrames,
|
|
82
|
+
["pixelStableFrames"] = PixelStableFrames,
|
|
83
|
+
["timeoutSeconds"] = TimeoutSeconds
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
internal sealed class UiSetOperation
|
|
89
|
+
{
|
|
90
|
+
public UiSetOperation(string selector, string property, object value, string location)
|
|
91
|
+
{
|
|
92
|
+
Selector = selector;
|
|
93
|
+
Property = property;
|
|
94
|
+
Value = value;
|
|
95
|
+
Location = location;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public string Selector { get; }
|
|
99
|
+
public string Property { get; }
|
|
100
|
+
public object Value { get; }
|
|
101
|
+
public string Location { get; }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
internal enum UiCollectionMode
|
|
105
|
+
{
|
|
106
|
+
Repeat,
|
|
107
|
+
ListView
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
internal sealed class UiCollectionDefinition
|
|
111
|
+
{
|
|
112
|
+
public UiCollectionDefinition(
|
|
113
|
+
string selector,
|
|
114
|
+
UiCollectionMode mode,
|
|
115
|
+
string source,
|
|
116
|
+
string templatePath,
|
|
117
|
+
VisualTreeAsset template,
|
|
118
|
+
float? itemHeight,
|
|
119
|
+
string location)
|
|
120
|
+
{
|
|
121
|
+
Selector = selector;
|
|
122
|
+
Mode = mode;
|
|
123
|
+
Source = source;
|
|
124
|
+
TemplatePath = templatePath;
|
|
125
|
+
Template = template;
|
|
126
|
+
ItemHeight = itemHeight;
|
|
127
|
+
Location = location;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public string Selector { get; }
|
|
131
|
+
public UiCollectionMode Mode { get; }
|
|
132
|
+
public string Source { get; }
|
|
133
|
+
public string TemplatePath { get; }
|
|
134
|
+
public VisualTreeAsset Template { get; }
|
|
135
|
+
public float? ItemHeight { get; }
|
|
136
|
+
public string Location { get; }
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
internal sealed class UiResolvedScenario
|
|
140
|
+
{
|
|
141
|
+
public UiResolvedScenario(
|
|
142
|
+
string targetPath,
|
|
143
|
+
string fixturePath,
|
|
144
|
+
string stateName,
|
|
145
|
+
string documentPath,
|
|
146
|
+
VisualTreeAsset document,
|
|
147
|
+
Dictionary<string, object> data,
|
|
148
|
+
IReadOnlyList<UiSetOperation> setOperations,
|
|
149
|
+
IReadOnlyList<UiCollectionDefinition> collections,
|
|
150
|
+
UiViewport viewport,
|
|
151
|
+
UiSettleOptions settle)
|
|
152
|
+
{
|
|
153
|
+
TargetPath = targetPath;
|
|
154
|
+
FixturePath = fixturePath;
|
|
155
|
+
StateName = stateName;
|
|
156
|
+
DocumentPath = documentPath;
|
|
157
|
+
Document = document;
|
|
158
|
+
Data = data;
|
|
159
|
+
SetOperations = setOperations;
|
|
160
|
+
Collections = collections;
|
|
161
|
+
Viewport = viewport;
|
|
162
|
+
Settle = settle;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
public string TargetPath { get; }
|
|
166
|
+
public string FixturePath { get; }
|
|
167
|
+
public string StateName { get; }
|
|
168
|
+
public string DocumentPath { get; }
|
|
169
|
+
public VisualTreeAsset Document { get; }
|
|
170
|
+
public Dictionary<string, object> Data { get; }
|
|
171
|
+
public IReadOnlyList<UiSetOperation> SetOperations { get; }
|
|
172
|
+
public IReadOnlyList<UiCollectionDefinition> Collections { get; }
|
|
173
|
+
public UiViewport Viewport { get; }
|
|
174
|
+
public UiSettleOptions Settle { get; }
|
|
175
|
+
|
|
176
|
+
public Dictionary<string, object> ToDictionary()
|
|
177
|
+
{
|
|
178
|
+
return new Dictionary<string, object>
|
|
179
|
+
{
|
|
180
|
+
["target"] = TargetPath,
|
|
181
|
+
["fixture"] = FixturePath,
|
|
182
|
+
["state"] = StateName,
|
|
183
|
+
["document"] = DocumentPath,
|
|
184
|
+
["viewport"] = Viewport.ToDictionary(),
|
|
185
|
+
["settle"] = Settle.ToDictionary(),
|
|
186
|
+
["setCount"] = SetOperations.Count,
|
|
187
|
+
["collectionCount"] = Collections.Count
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
internal sealed class UiApplyReport
|
|
193
|
+
{
|
|
194
|
+
private readonly List<Dictionary<string, object>> _diagnostics = new List<Dictionary<string, object>>();
|
|
195
|
+
private readonly List<UiCollectionMetadata> _collections = new List<UiCollectionMetadata>();
|
|
196
|
+
|
|
197
|
+
public int BindingRewriteCount { get; internal set; }
|
|
198
|
+
public int SetCount { get; internal set; }
|
|
199
|
+
public int RepeatItemCount { get; internal set; }
|
|
200
|
+
public IReadOnlyList<Dictionary<string, object>> Diagnostics => _diagnostics;
|
|
201
|
+
public IReadOnlyList<UiCollectionMetadata> Collections => _collections;
|
|
202
|
+
|
|
203
|
+
internal void AddDiagnostic(string severity, string code, string message, string location = null)
|
|
204
|
+
{
|
|
205
|
+
_diagnostics.Add(new Dictionary<string, object>
|
|
206
|
+
{
|
|
207
|
+
["severity"] = severity,
|
|
208
|
+
["code"] = code,
|
|
209
|
+
["message"] = message,
|
|
210
|
+
["location"] = location
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
internal void AddCollection(UiCollectionMetadata metadata)
|
|
215
|
+
{
|
|
216
|
+
_collections.Add(metadata);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public Dictionary<string, object> ToDictionary()
|
|
220
|
+
{
|
|
221
|
+
var collections = new List<object>(_collections.Count);
|
|
222
|
+
foreach (var collection in _collections)
|
|
223
|
+
collections.Add(collection.ToDictionary());
|
|
224
|
+
|
|
225
|
+
return new Dictionary<string, object>
|
|
226
|
+
{
|
|
227
|
+
["bindingRewriteCount"] = BindingRewriteCount,
|
|
228
|
+
["setCount"] = SetCount,
|
|
229
|
+
["repeatItemCount"] = RepeatItemCount,
|
|
230
|
+
["collections"] = collections,
|
|
231
|
+
["diagnostics"] = new List<object>(_diagnostics)
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
internal sealed class UiCollectionMetadata
|
|
237
|
+
{
|
|
238
|
+
private readonly HashSet<VisualElement> _realizedRows = new HashSet<VisualElement>();
|
|
239
|
+
private readonly Dictionary<VisualElement, int> _boundRows = new Dictionary<VisualElement, int>();
|
|
240
|
+
private readonly VisualElement _target;
|
|
241
|
+
private readonly VisualElement _inspectionRoot;
|
|
242
|
+
|
|
243
|
+
public UiCollectionMetadata(
|
|
244
|
+
string selector,
|
|
245
|
+
UiCollectionMode mode,
|
|
246
|
+
string source,
|
|
247
|
+
int logicalItemCount,
|
|
248
|
+
VisualElement target,
|
|
249
|
+
VisualElement inspectionRoot)
|
|
250
|
+
{
|
|
251
|
+
Selector = selector;
|
|
252
|
+
Mode = mode;
|
|
253
|
+
Source = source;
|
|
254
|
+
LogicalItemCount = logicalItemCount;
|
|
255
|
+
_target = target;
|
|
256
|
+
_inspectionRoot = inspectionRoot;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
public string Selector { get; }
|
|
260
|
+
public UiCollectionMode Mode { get; }
|
|
261
|
+
public string Source { get; }
|
|
262
|
+
public int LogicalItemCount { get; }
|
|
263
|
+
public int RealizedRowCount => _realizedRows.Count;
|
|
264
|
+
public int BoundRowCount => _boundRows.Count;
|
|
265
|
+
|
|
266
|
+
internal void Realize(VisualElement row)
|
|
267
|
+
{
|
|
268
|
+
if (row != null)
|
|
269
|
+
_realizedRows.Add(row);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
internal void Bind(VisualElement row, int index)
|
|
273
|
+
{
|
|
274
|
+
Realize(row);
|
|
275
|
+
_boundRows[row] = index;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
internal void Unbind(VisualElement row)
|
|
279
|
+
{
|
|
280
|
+
if (row != null)
|
|
281
|
+
_boundRows.Remove(row);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
internal void Destroy(VisualElement row)
|
|
285
|
+
{
|
|
286
|
+
if (row == null)
|
|
287
|
+
return;
|
|
288
|
+
|
|
289
|
+
_boundRows.Remove(row);
|
|
290
|
+
_realizedRows.Remove(row);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
public Dictionary<string, object> ToDictionary()
|
|
294
|
+
{
|
|
295
|
+
var rows = new List<object>(_boundRows.Count);
|
|
296
|
+
var visibleRowCount = 0;
|
|
297
|
+
foreach (var pair in _boundRows)
|
|
298
|
+
{
|
|
299
|
+
var row = pair.Key;
|
|
300
|
+
var visible = row != null && row.panel != null && row.resolvedStyle.display != DisplayStyle.None;
|
|
301
|
+
var intersectsViewport = visible && IntersectsViewport(row);
|
|
302
|
+
if (intersectsViewport)
|
|
303
|
+
visibleRowCount++;
|
|
304
|
+
rows.Add(new Dictionary<string, object>
|
|
305
|
+
{
|
|
306
|
+
["index"] = pair.Value,
|
|
307
|
+
["name"] = row != null ? row.name : null,
|
|
308
|
+
["attached"] = row != null && row.panel != null,
|
|
309
|
+
["displayed"] = visible,
|
|
310
|
+
["visible"] = intersectsViewport
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
rows.Sort((left, right) =>
|
|
315
|
+
{
|
|
316
|
+
var leftIndex = Convert.ToInt32(((Dictionary<string, object>)left)["index"]);
|
|
317
|
+
var rightIndex = Convert.ToInt32(((Dictionary<string, object>)right)["index"]);
|
|
318
|
+
return leftIndex.CompareTo(rightIndex);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
return new Dictionary<string, object>
|
|
322
|
+
{
|
|
323
|
+
["target"] = Selector,
|
|
324
|
+
["mode"] = Mode == UiCollectionMode.Repeat ? "repeat" : "list-view",
|
|
325
|
+
["source"] = Source,
|
|
326
|
+
["logicalItemCount"] = LogicalItemCount,
|
|
327
|
+
["realizedRowCount"] = RealizedRowCount,
|
|
328
|
+
["boundRowCount"] = BoundRowCount,
|
|
329
|
+
["visibleRowCount"] = visibleRowCount,
|
|
330
|
+
["boundRows"] = rows
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
private bool IntersectsViewport(VisualElement row)
|
|
335
|
+
{
|
|
336
|
+
if (_target == null || _inspectionRoot == null)
|
|
337
|
+
return false;
|
|
338
|
+
|
|
339
|
+
for (var current = row; current != null; current = current.parent)
|
|
340
|
+
{
|
|
341
|
+
if (current.resolvedStyle.display == DisplayStyle.None ||
|
|
342
|
+
current.resolvedStyle.visibility == Visibility.Hidden)
|
|
343
|
+
return false;
|
|
344
|
+
if (current == _inspectionRoot)
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
var rowBounds = row.worldBound;
|
|
349
|
+
var viewport = Intersect(_target.worldBound, _inspectionRoot.worldBound);
|
|
350
|
+
return IsFinite(rowBounds) && IsFinite(viewport) && rowBounds.width > 0f && rowBounds.height > 0f &&
|
|
351
|
+
viewport.width > 0f && viewport.height > 0f && rowBounds.Overlaps(viewport);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
private static Rect Intersect(Rect left, Rect right)
|
|
355
|
+
{
|
|
356
|
+
var xMin = Math.Max(left.xMin, right.xMin);
|
|
357
|
+
var yMin = Math.Max(left.yMin, right.yMin);
|
|
358
|
+
var xMax = Math.Min(left.xMax, right.xMax);
|
|
359
|
+
var yMax = Math.Min(left.yMax, right.yMax);
|
|
360
|
+
return Rect.MinMaxRect(xMin, yMin, xMax, yMax);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
private static bool IsFinite(Rect value)
|
|
364
|
+
{
|
|
365
|
+
return IsFinite(value.x) && IsFinite(value.y) && IsFinite(value.width) && IsFinite(value.height);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
private static bool IsFinite(float value)
|
|
369
|
+
{
|
|
370
|
+
return !float.IsNaN(value) && !float.IsInfinity(value);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
#endif
|