Skip to content
This repository was archived by the owner on Jan 18, 2022. It is now read-only.

Commit 9e6a3ef

Browse files
author
Jamie Brynes
authored
Add entity type rendering to Worker Inspector (#1401)
1 parent 352b85a commit 9e6a3ef

File tree

4 files changed

+79
-88
lines changed

4 files changed

+79
-88
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
- This window also displays the entities that a worker has checked out.
1515
- For each entity checked out, you can view the components on that entity and whether the worker is authoritative over that component.
1616
- Each component can have an icon associated with it, set through a schema annotation. [#1385](https://github.com/spatialos/gdk-for-unity/pull/1385)
17+
- Each component's data will also be rendered in the Worker Inspector, with the exception of `map<k, v>` fields. (This will come in a future release!) [#1387](https://github.com/spatialos/gdk-for-unity/pull/1387) [#1391](https://github.com/spatialos/gdk-for-unity/pull/1391) [#1392](https://github.com/spatialos/gdk-for-unity/pull/1392) [#1396](https://github.com/spatialos/gdk-for-unity/pull/1396) [#1401](https://github.com/spatialos/gdk-for-unity/pull/1401)
18+
- Added two ways to instantiate valid `EntitySnapshot` objects. [#1401](https://github.com/spatialos/gdk-for-unity/pull/1401)
19+
- `EntitySnapshot.Empty()` to create an empty `EntitySnapshot`
20+
- `new EntitySnapshot(params ISpatialComponentSnapshot[] components)` to create and seed the `EntitySnapshot` with some data.
1721

1822
### Fixed
1923

workers/unity/Packages/io.improbable.gdk.core/Utility/EntitySnapshot.cs

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Text;
24
using Improbable.Worker.CInterop;
35

46
namespace Improbable.Gdk.Core
@@ -8,7 +10,22 @@ namespace Improbable.Gdk.Core
810
/// </summary>
911
public struct EntitySnapshot
1012
{
11-
private readonly Dictionary<uint, ISpatialComponentSnapshot> components;
13+
private Dictionary<uint, ISpatialComponentSnapshot> components;
14+
15+
public static EntitySnapshot Empty()
16+
{
17+
return new EntitySnapshot { components = new Dictionary<uint, ISpatialComponentSnapshot>() };
18+
}
19+
20+
public EntitySnapshot(params ISpatialComponentSnapshot[] snapshots)
21+
{
22+
components = new Dictionary<uint, ISpatialComponentSnapshot>();
23+
24+
foreach (var snapshot in snapshots)
25+
{
26+
components[snapshot.ComponentId] = snapshot;
27+
}
28+
}
1229

1330
/// <summary>
1431
/// Gets the SpatialOS component snapshot if present.
@@ -90,6 +107,25 @@ internal void SerializeToSchemaObject(SchemaObject inObj)
90107
Dynamic.ForComponent(pair.Key, handler);
91108
}
92109
}
110+
111+
public override string ToString()
112+
{
113+
var sb = new StringBuilder("Entity Snapshot: ");
114+
115+
var componentNames = components.Keys.Select(id =>
116+
{
117+
if (!ComponentDatabase.Metaclasses.TryGetValue(id, out var metaclass))
118+
{
119+
return $"Unknown Component ({id})";
120+
}
121+
122+
return metaclass.Name;
123+
});
124+
125+
sb.Append(string.Join(", ", componentNames));
126+
127+
return sb.ToString();
128+
}
93129
}
94130

95131
internal struct QueryComponentDataHandler : Dynamic.IHandler

workers/unity/Packages/io.improbable.gdk.debug/.codegen/Source/Generators/DebugExtensions/FieldTypeHandler.cs

+34-87
Original file line numberDiff line numberDiff line change
@@ -23,35 +23,13 @@ public string ToFieldDeclaration(UnityFieldDetails fieldDetails)
2323
{
2424
case SingularFieldType singularFieldType:
2525
var uiType = GetUiFieldType(singularFieldType.ContainedType);
26-
27-
if (uiType == "")
28-
{
29-
// TODO: Eliminate this case by supporting 'Entity'.
30-
return "";
31-
}
32-
3326
return $"private readonly {uiType} {fieldDetails.CamelCaseName}Field;";
3427
case OptionFieldType optionFieldType:
3528
var innerUiType = GetUiFieldType(optionFieldType.ContainedType);
36-
37-
if (innerUiType == "")
38-
{
39-
// TODO: Eliminate this case by supporting 'Entity'.
40-
return "";
41-
}
42-
4329
var element = optionFieldType.IsNullable ? "NullableVisualElement" : "OptionVisualElement";
44-
4530
return $"private readonly {element}<{innerUiType}, {optionFieldType.ContainedType.FqnType}> {fieldDetails.CamelCaseName}Field;";
4631
case ListFieldType listFieldType:
4732
var innerListType = GetUiFieldType(listFieldType.ContainedType);
48-
49-
if (innerListType == "")
50-
{
51-
// TODO: Eliminate this case by supporting 'Entity'.
52-
return "";
53-
}
54-
5533
return $"private readonly PaginatedListView<{innerListType}, {listFieldType.ContainedType.FqnType}> {fieldDetails.CamelCaseName}Field;";
5634
default:
5735
// TODO: Maps.
@@ -64,49 +42,21 @@ public IEnumerable<string> ToFieldInitialisation(UnityFieldDetails fieldDetails,
6442
switch (fieldDetails.FieldType)
6543
{
6644
case SingularFieldType singularFieldType:
67-
68-
var uiType = GetUiFieldType(singularFieldType.ContainedType);
69-
70-
if (uiType == "")
71-
{
72-
// TODO: Eliminate this case by supporting 'Entity'.
73-
yield break;
74-
}
75-
7645
var humanReadableName = Formatting.SnakeCaseToHumanReadable(fieldDetails.Name);
77-
yield return $"{fieldDetails.CamelCaseName}Field = new {uiType}(\"{humanReadableName}\");";
7846

79-
if (singularFieldType.ContainedType.Category != ValueType.Type)
47+
foreach (var initializer in GetFieldInitializer(singularFieldType.ContainedType, $"{fieldDetails.CamelCaseName}Field", humanReadableName, false))
8048
{
81-
yield return $"{fieldDetails.CamelCaseName}Field.SetEnabled(false);";
82-
}
83-
84-
if (singularFieldType.ContainedType.Category == ValueType.Enum)
85-
{
86-
yield return $"{fieldDetails.CamelCaseName}Field.Init(default({fieldDetails.Type}));";
49+
yield return initializer;
8750
}
8851

8952
yield return $"{parentContainer}.Add({fieldDetails.CamelCaseName}Field);";
9053
break;
9154
case OptionFieldType optionFieldType:
9255
var innerUiType = GetUiFieldType(optionFieldType.ContainedType);
9356

94-
if (innerUiType == "")
57+
foreach (var initializer in GetFieldInitializer(optionFieldType.ContainedType, $"{fieldDetails.CamelCaseName}InnerField", "Value"))
9558
{
96-
// TODO: Eliminate this case by supporting 'Entity'.
97-
yield break;
98-
}
99-
100-
yield return $"var {fieldDetails.CamelCaseName}InnerField = new {innerUiType}(\"Value\");";
101-
102-
if (optionFieldType.ContainedType.Category != ValueType.Type)
103-
{
104-
yield return $"{fieldDetails.CamelCaseName}InnerField.SetEnabled(false);";
105-
}
106-
107-
if (optionFieldType.ContainedType.Category == ValueType.Enum)
108-
{
109-
yield return $"{fieldDetails.CamelCaseName}InnerField.Init(default({optionFieldType.ContainedType.FqnType}));";
59+
yield return initializer;
11060
}
11161

11262
var element = optionFieldType.IsNullable ? "NullableVisualElement" : "OptionVisualElement";
@@ -118,24 +68,12 @@ public IEnumerable<string> ToFieldInitialisation(UnityFieldDetails fieldDetails,
11868
case ListFieldType listFieldType:
11969
var innerListType = GetUiFieldType(listFieldType.ContainedType);
12070

121-
if (innerListType == "")
122-
{
123-
// TODO: Eliminate this case by supporting 'Entity'.
124-
yield break;
125-
}
126-
12771
yield return
128-
$"{fieldDetails.CamelCaseName}Field = new PaginatedListView<{innerListType}, {listFieldType.ContainedType.FqnType}>(\"{Formatting.SnakeCaseToHumanReadable(fieldDetails.Name)}\", () => {{ var inner = new {innerListType}(\"\");";
129-
130-
// These lines are part of the func to create an inner list item.
131-
if (listFieldType.ContainedType.Category != ValueType.Type)
132-
{
133-
yield return "inner.SetEnabled(false);";
134-
}
72+
$"{fieldDetails.CamelCaseName}Field = new PaginatedListView<{innerListType}, {listFieldType.ContainedType.FqnType}>(\"{Formatting.SnakeCaseToHumanReadable(fieldDetails.Name)}\", () => {{";
13573

136-
if (listFieldType.ContainedType.Category == ValueType.Enum)
74+
foreach (var initializer in GetFieldInitializer(listFieldType.ContainedType, "inner", ""))
13775
{
138-
yield return $"inner.Init(default({listFieldType.ContainedType.FqnType}));";
76+
yield return initializer;
13977
}
14078

14179
yield return "return inner; }, (index, data, element) => {";
@@ -161,27 +99,40 @@ public string ToUiFieldUpdate(UnityFieldDetails fieldDetails, string fieldParent
16199
case SingularFieldType singularFieldType:
162100
return ContainedTypeToUiFieldUpdate(singularFieldType.ContainedType, uiElementName, $"{fieldParent}.{fieldDetails.PascalCaseName}");
163101
case OptionFieldType optionFieldType:
164-
if (GetUiFieldType(optionFieldType.ContainedType) == "")
165-
{
166-
// TODO: Eliminate this case by supporting 'Entity'.
167-
return "";
168-
}
169-
170102
return $"{uiElementName}.Update({fieldParent}.{fieldDetails.PascalCaseName});";
171103
case ListFieldType listFieldType:
172-
if (GetUiFieldType(listFieldType.ContainedType) == "")
173-
{
174-
// TODO: Eliminate this case by supporting 'Entity'.
175-
return "";
176-
}
177-
178104
return $"{uiElementName}.Update({fieldParent}.{fieldDetails.PascalCaseName});";
179105
default:
180106
// TODO: Maps.
181107
return "";
182108
}
183109
}
184110

111+
private IEnumerable<string> GetFieldInitializer(ContainedType containedType, string uiElementName, string label, bool newVariable = true)
112+
{
113+
var inner = GetUiFieldType(containedType);
114+
115+
if (newVariable)
116+
{
117+
yield return $"var {uiElementName} = new {inner}(\"{label}\");";
118+
}
119+
else
120+
{
121+
yield return $"{uiElementName} = new {inner}(\"{label}\");";
122+
}
123+
124+
// These lines are part of the func to create an inner list item.
125+
if (containedType.Category != ValueType.Type)
126+
{
127+
yield return $"{uiElementName}.SetEnabled(false);";
128+
}
129+
130+
if (containedType.Category == ValueType.Enum)
131+
{
132+
yield return $"{uiElementName}.Init(default({containedType.FqnType}));";
133+
}
134+
}
135+
185136
private string ContainedTypeToUiFieldUpdate(ContainedType containedType, string uiElementName, string fieldAccessor)
186137
{
187138
switch (containedType.Category)
@@ -206,15 +157,12 @@ private string ContainedTypeToUiFieldUpdate(ContainedType containedType, string
206157
case PrimitiveType.Double:
207158
case PrimitiveType.String:
208159
case PrimitiveType.EntityId:
160+
case PrimitiveType.Entity:
209161
return $"{uiElementName}.value = {fieldAccessor}.ToString();";
210162
case PrimitiveType.Bytes:
211163
return $"{uiElementName}.value = global::System.Text.Encoding.Default.GetString({fieldAccessor});";
212164
case PrimitiveType.Bool:
213165
return $"{uiElementName}.value = {fieldAccessor};";
214-
break;
215-
case PrimitiveType.Entity:
216-
// TODO: Entity type.
217-
return "";
218166
case PrimitiveType.Invalid:
219167
throw new ArgumentException("Unknown primitive type encountered");
220168
default:
@@ -251,11 +199,10 @@ private string GetUiFieldType(ContainedType type)
251199
case PrimitiveType.String:
252200
case PrimitiveType.EntityId:
253201
case PrimitiveType.Bytes:
202+
case PrimitiveType.Entity:
254203
return "TextField";
255204
case PrimitiveType.Bool:
256205
return "Toggle";
257-
case PrimitiveType.Entity:
258-
return "";
259206
case PrimitiveType.Invalid:
260207
throw new ArgumentException("Unknown primitive type encountered.");
261208
default:

workers/unity/Packages/io.improbable.gdk.debug/WorkerInspector/Templates/WorkerInspectorWindow.uss

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
border-top-width: 1px;
3939
}
4040

41+
#entity-detail .unity-text-field__input {
42+
white-space: normal;
43+
}
4144
#entity-info {
4245
min-height: 50px;
4346
padding: 8px;
@@ -51,6 +54,7 @@
5154
-unity-font-style: bold;
5255
font-size: 14px;
5356
padding-bottom: 4px;
57+
white-space: normal;
5458
}
5559

5660
.component-foldout {

0 commit comments

Comments
 (0)