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

Commit

Permalink
Render primitive schema data & enums in the worker inspector (#1387)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jamie Brynes authored Jun 10, 2020
1 parent 2cd7b9b commit 8330867
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Improbable.Gdk.CodeGeneration.CodeWriter;
using Improbable.Gdk.CodeGeneration.CodeWriter.Scopes;
using Improbable.Gdk.CodeGeneration.Model;
using Improbable.Gdk.CodeGeneration.Model.Details;
using Improbable.Gdk.CodeGeneration.Utils;
using ValueType = Improbable.Gdk.CodeGeneration.Model.ValueType;

namespace Improbable.Gdk.CodeGenerator
{
Expand All @@ -13,6 +19,7 @@ public static CodeWriter Generate(UnityComponentDetails details)
cgw.UsingDirectives(
"Unity.Entities",
"UnityEngine.UIElements",
"UnityEditor.UIElements",
"Improbable.Gdk.Debug.WorkerInspector.Codegen"
);

Expand All @@ -22,28 +29,184 @@ public static CodeWriter Generate(UnityComponentDetails details)
{
type.Line($"public override ComponentType ComponentType {{ get; }} = ComponentType.ReadOnly<{details.Name}.Component>();");

type.TextList(details.FieldDetails.Select(ToFieldDeclaration));

GenerateConstructor(type, details);
GenerateUpdateMethod(type, details);
});
});
});
}

private static string ToFieldDeclaration(UnityFieldDetails fieldDetails)
{
switch (fieldDetails.FieldType)
{
case SingularFieldType singularFieldType:
var uiType = GetUiFieldType(singularFieldType.ContainedType);

if (uiType == "")
{
// TODO: Eliminate this case.
return "";
}

return $"private readonly {uiType} {fieldDetails.CamelCaseName}Field;";
default:
// TODO: Lists, maps, and options
return "";
}
}

private static void GenerateConstructor(TypeBlock typeBlock, UnityComponentDetails details)
{
typeBlock.Method($"public {details.Name}Renderer() : base()", mb =>
{
mb.Line($"ComponentFoldout.text = \"{details.Name}\";");
mb.Line($"AuthoritativeToggle.SetEnabled(false);");

foreach (var field in details.FieldDetails)
{
mb.TextList(ToFieldInitialisation(field));
}
});
}

private static IEnumerable<string> ToFieldInitialisation(UnityFieldDetails fieldDetails)
{
switch (fieldDetails.FieldType)
{
case SingularFieldType singularFieldType:

var uiType = GetUiFieldType(singularFieldType.ContainedType);

if (uiType == "")
{
// TODO: Eliminate this case.
yield break;
}

var humanReadableName = Formatting.SnakeCaseToHumanReadable(fieldDetails.Name);
yield return $"{fieldDetails.CamelCaseName}Field = new {uiType}(\"{humanReadableName}\");";
yield return $"{fieldDetails.CamelCaseName}Field.SetEnabled(false);";

if (singularFieldType.ContainedType.Category == ValueType.Enum)
{
yield return $"{fieldDetails.CamelCaseName}Field.Init(default({fieldDetails.Type}));";
}

yield return $"ComponentFoldout.Add({fieldDetails.CamelCaseName}Field);";
break;
default:
// TODO: Lists, maps, and options
yield break;
}
}

private static void GenerateUpdateMethod(TypeBlock typeBlock, UnityComponentDetails details)
{
typeBlock.Method("public override void Update(EntityManager manager, Entity entity)", mb =>
{
mb.Line($"AuthoritativeToggle.value = manager.HasComponent<{details.Name}.HasAuthority>(entity);");
mb.Line($"var component = manager.GetComponentData<{details.Name}.Component>(entity);");

mb.TextList(TextList.New(details.FieldDetails.Select(ToUiFieldUpdate)));
});
}

private static string ToUiFieldUpdate(UnityFieldDetails fieldDetails)
{
switch (fieldDetails.FieldType)
{
case SingularFieldType singularFieldType:
switch (singularFieldType.ContainedType.Category)
{
case ValueType.Enum:
return $"{fieldDetails.CamelCaseName}Field.value = component.{fieldDetails.PascalCaseName};";
case ValueType.Primitive:
var primitiveType = singularFieldType.ContainedType.PrimitiveType.Value;

switch (primitiveType)
{
case PrimitiveType.Int32:
case PrimitiveType.Int64:
case PrimitiveType.Uint32:
case PrimitiveType.Uint64:
case PrimitiveType.Sint32:
case PrimitiveType.Sint64:
case PrimitiveType.Fixed32:
case PrimitiveType.Fixed64:
case PrimitiveType.Sfixed32:
case PrimitiveType.Sfixed64:
case PrimitiveType.Float:
case PrimitiveType.Double:
case PrimitiveType.String:
case PrimitiveType.EntityId:
return $"{fieldDetails.CamelCaseName}Field.value = component.{fieldDetails.PascalCaseName}.ToString();";
case PrimitiveType.Bytes:
return $"{fieldDetails.CamelCaseName}Field.value = global::System.Text.Encoding.Default.GetString(component.{fieldDetails.PascalCaseName});";
case PrimitiveType.Bool:
return $"{fieldDetails.CamelCaseName}Field.value = component.{fieldDetails.PascalCaseName};";
break;
case PrimitiveType.Entity:
// TODO: Entity type.
return "";
case PrimitiveType.Invalid:
throw new ArgumentException("Unknown primitive type encountered");
default:
throw new ArgumentOutOfRangeException();
}
case ValueType.Type:
// TODO: User defined types.
return "";
default:
throw new ArgumentOutOfRangeException();
}
default:
// TODO: Lists, maps, and options
return "";
}
}

private static string GetUiFieldType(ContainedType type)
{
switch (type.Category)
{
case ValueType.Enum:
return "EnumField";
case ValueType.Primitive:
switch (type.PrimitiveType.Value)
{
case PrimitiveType.Int32:
case PrimitiveType.Int64:
case PrimitiveType.Uint32:
case PrimitiveType.Uint64:
case PrimitiveType.Sint32:
case PrimitiveType.Sint64:
case PrimitiveType.Fixed32:
case PrimitiveType.Fixed64:
case PrimitiveType.Sfixed32:
case PrimitiveType.Sfixed64:
case PrimitiveType.Float:
case PrimitiveType.Double:
case PrimitiveType.String:
case PrimitiveType.EntityId:
case PrimitiveType.Bytes:
return "TextField";
case PrimitiveType.Bool:
return "Toggle";
case PrimitiveType.Entity:
return "";
case PrimitiveType.Invalid:
throw new ArgumentException("Unknown primitive type encountered.");
default:
throw new ArgumentOutOfRangeException();
}
case ValueType.Type:
return "";
default:
throw new ArgumentOutOfRangeException();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public static string Generate()
return @"{
""name"": ""Improbable.Gdk.Generated.Debug"",
""references"": [
""Improbable.Gdk.Core"",
""Improbable.Gdk.Generated"",
""Improbable.Gdk.Debug.WorkerInspector.Codegen"",
""Unity.Entities""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public void TextList(TextList textList)
Add(textList);
}

public void TextList(IEnumerable<string> text)
{
Add(CodeGeneration.CodeWriter.TextList.New(text));
}

public void Line(string snippet)
{
Add(new Text(snippet));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public void TextList(TextList textList)
Add(textList);
}

public void TextList(IEnumerable<string> text)
{
Add(CodeGeneration.CodeWriter.TextList.New(text));
}

public void Line(string snippet)
{
Add(new Text(snippet));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,27 @@ namespace Improbable.Gdk.CodeGeneration.Model.Details
public class ContainedType
{
public readonly string FqnType;
private readonly ValueType category;
private PrimitiveType? primitiveType;
public readonly ValueType Category;
public readonly PrimitiveType? PrimitiveType;

public ContainedType(TypeReference innerType)
{
switch (innerType.ValueTypeSelector)
{
case ValueType.Enum:
category = ValueType.Enum;
Category = ValueType.Enum;
FqnType = DetailsUtils.GetCapitalisedFqnTypename(innerType.Enum);
primitiveType = null;
PrimitiveType = null;
break;
case ValueType.Primitive:
category = ValueType.Primitive;
Category = ValueType.Primitive;
FqnType = UnityTypeMappings.SchemaTypeToUnityType[innerType.Primitive];
primitiveType = innerType.Primitive;
PrimitiveType = innerType.Primitive;
break;
case ValueType.Type:
category = ValueType.Type;
Category = ValueType.Type;
FqnType = DetailsUtils.GetCapitalisedFqnTypename(innerType.Type);
primitiveType = null;
PrimitiveType = null;
break;
default:
throw new ArgumentOutOfRangeException("Malformed inner type.");
Expand All @@ -35,64 +35,64 @@ public ContainedType(TypeReference innerType)

public string GetSerializationStatement(string instance, string schemaObject, uint fieldNumber)
{
switch (category)
switch (Category)
{
case ValueType.Primitive:
return $"{schemaObject}.{SchemaFunctionMappings.AddSchemaFunctionFromType(primitiveType.Value)}({fieldNumber}, {instance});";
return $"{schemaObject}.{SchemaFunctionMappings.AddSchemaFunctionFromType(PrimitiveType.Value)}({fieldNumber}, {instance});";
case ValueType.Enum:
return $"{schemaObject}.AddEnum({fieldNumber}, (uint) {instance});";
case ValueType.Type:
return $"{FqnType}.Serialization.Serialize({instance}, {schemaObject}.AddObject({fieldNumber}));";
default:
throw new ArgumentOutOfRangeException(nameof(category), "Unknown type category encountered.");
throw new ArgumentOutOfRangeException(nameof(Category), "Unknown type category encountered.");
}
}

public string GetDeserializationExpression(string schemaObject, uint fieldNumber)
{
switch (category)
switch (Category)
{
case ValueType.Primitive:
return
$"{schemaObject}.{SchemaFunctionMappings.GetSchemaFunctionFromType(primitiveType.Value)}({fieldNumber})";
$"{schemaObject}.{SchemaFunctionMappings.GetSchemaFunctionFromType(PrimitiveType.Value)}({fieldNumber})";
case ValueType.Enum:
return $"({FqnType}) {schemaObject}.GetEnum({fieldNumber})";
case ValueType.Type:
return $"{FqnType}.Serialization.Deserialize({schemaObject}.GetObject({fieldNumber}))";
default:
throw new ArgumentOutOfRangeException(nameof(category), "Unknown type category encountered.");
throw new ArgumentOutOfRangeException(nameof(Category), "Unknown type category encountered.");
}
}

public string GetCountExpression(string schemaObject, uint fieldNumber)
{
switch (category)
switch (Category)
{
case ValueType.Primitive:
return
$"{schemaObject}.{SchemaFunctionMappings.GetCountSchemaFunctionFromType(primitiveType.Value)}({fieldNumber})";
$"{schemaObject}.{SchemaFunctionMappings.GetCountSchemaFunctionFromType(PrimitiveType.Value)}({fieldNumber})";
case ValueType.Enum:
return $"{schemaObject}.GetEnumCount({fieldNumber})";
case ValueType.Type:
return $"{schemaObject}.GetObjectCount({fieldNumber})";
default:
throw new ArgumentOutOfRangeException(nameof(category), "Unknown type category encountered.");
throw new ArgumentOutOfRangeException(nameof(Category), "Unknown type category encountered.");
}
}

public string GetFieldIndexExpression(string schemaObject, uint fieldNumber, string index)
{
switch (category)
switch (Category)
{
case ValueType.Primitive:
return
$"{schemaObject}.{SchemaFunctionMappings.IndexSchemaFunctionFromType(primitiveType.Value)}({fieldNumber}, (uint) {index})";
$"{schemaObject}.{SchemaFunctionMappings.IndexSchemaFunctionFromType(PrimitiveType.Value)}({fieldNumber}, (uint) {index})";
case ValueType.Enum:
return $"({FqnType}) {schemaObject}.IndexEnum({fieldNumber}, (uint) {index})";
case ValueType.Type:
return $"{FqnType}.Serialization.Deserialize({schemaObject}.IndexObject({fieldNumber}, (uint) {index}))";
default:
throw new ArgumentOutOfRangeException(nameof(category), "Unknown type category encountered.");
throw new ArgumentOutOfRangeException(nameof(Category), "Unknown type category encountered.");
}
}
}
Expand Down
Loading

0 comments on commit 8330867

Please sign in to comment.