Route main menu through portable CultUI surfaces

This commit is contained in:
Meta Vens 2026-07-01 12:04:24 +01:00
commit b6d0d5fb4c
3 changed files with 225 additions and 176 deletions

View file

@ -4,6 +4,10 @@ using System.Linq;
using Aetheria.State.Documents;
using GameCult.Aetheria.State.Verse;
using GameCult.Mesh;
using EveDocumentCommandTemplate = Aetheria.State.Documents.EveCommandTemplate;
using EveDocumentStyleToken = Aetheria.State.Documents.EveStyleToken;
using EveDocumentSurface = Aetheria.State.Documents.EveSurface;
using EveDocumentSurfaceComponent = Aetheria.State.Documents.EveSurfaceComponent;
namespace Aetheria.State;
@ -63,7 +67,7 @@ public static class AetheriaEveSurfaceDocuments
Title = "Aetheria Catalog",
Version = version,
UpdatedAtUtc = updatedAtUtc,
Surface = new EveSurface
Surface = new EveDocumentSurface
{
Id = CatalogSurfaceId,
Root = Node(
@ -93,7 +97,7 @@ public static class AetheriaEveSurfaceDocuments
},
Commands =
[
new EveCommandTemplate
new EveDocumentCommandTemplate
{
Command = refreshCommand.OperationId,
Label = refreshCommand.Label,
@ -131,7 +135,7 @@ public static class AetheriaEveSurfaceDocuments
Title = "Aetheria Operations",
Version = version,
UpdatedAtUtc = updatedAtUtc,
Surface = new EveSurface
Surface = new EveDocumentSurface
{
Id = OperationsSurfaceId,
Root = Node(
@ -188,7 +192,7 @@ public static class AetheriaEveSurfaceDocuments
},
Commands =
[
new EveCommandTemplate
new EveDocumentCommandTemplate
{
Command = refreshCommand.OperationId,
Label = refreshCommand.Label,
@ -231,12 +235,12 @@ public static class AetheriaEveSurfaceDocuments
Title = surface.Title,
Version = surface.Version,
UpdatedAtUtc = surface.UpdatedAtUtc,
Surface = new EveSurface
Surface = new EveDocumentSurface
{
Id = surface.Surface.Id,
Root = ConvertComponent(surface.Surface.Root),
Styles = surface.Surface.Styles
.Select(style => new EveStyleToken
.Select(style => new EveDocumentStyleToken
{
Name = style.Name,
Value = style.Value
@ -247,7 +251,7 @@ public static class AetheriaEveSurfaceDocuments
.Select(command =>
{
var record = CultMesh.OperationBindingRecord(command.Operation);
return new EveCommandTemplate
return new EveDocumentCommandTemplate
{
Command = record.OperationId,
Label = record.Label,
@ -479,23 +483,23 @@ public static class AetheriaEveSurfaceDocuments
return latest;
}
private static EveSurfaceComponent Metric(string id, string label, string value)
private static EveDocumentSurfaceComponent Metric(string id, string label, string value)
{
return Node(id, "metric", [("label", label), ("value", value)]);
}
private static EveSurfaceComponent Row(string id, params (string Key, string Value)[] props)
private static EveDocumentSurfaceComponent Row(string id, params (string Key, string Value)[] props)
{
return Node(id, "row", props);
}
private static EveSurfaceComponent Node(
private static EveDocumentSurfaceComponent Node(
string id,
string kind,
(string Key, string Value)[] props,
params EveSurfaceComponent[] children)
params EveDocumentSurfaceComponent[] children)
{
return new EveSurfaceComponent
return new EveDocumentSurfaceComponent
{
Id = id,
Kind = kind,
@ -504,9 +508,9 @@ public static class AetheriaEveSurfaceDocuments
};
}
private static EveSurfaceComponent ConvertComponent(AetheriaRuntimeSurfaceComponent component)
private static EveDocumentSurfaceComponent ConvertComponent(AetheriaRuntimeSurfaceComponent component)
{
return new EveSurfaceComponent
return new EveDocumentSurfaceComponent
{
Id = component.Id,
Kind = component.Kind,

View file

@ -1,7 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GameCult.Eve.Surface;
using GameCult.Mesh;
using EveUiCommandRequest = GameCult.Eve.Surface.EveSurfaceCommandRequest;
namespace GameCult.Aetheria.State.Verse
{
@ -150,60 +151,52 @@ namespace GameCult.Aetheria.State.Verse
string updatedAtUtc,
long version)
{
var commands = new List<AetheriaRuntimeSurfaceCommandTemplate>();
var actionButtons = new List<AetheriaRuntimeSurfaceComponent>();
var builder = MainMenuSurface(
AetheriaRuntimeMainMenuCommands.RootSurfaceId,
"Aetheria Terminus",
updatedAtUtc,
version)
.TitleSubtitle("AETHERIA", "TERMINUS")
.ButtonColumn(
$"{AetheriaRuntimeMainMenuCommands.RootSurfaceId}.actions",
actions =>
{
if (!inGame)
{
actions.Button(
"Continue",
Operation(AetheriaRuntimeMainMenuCommands.ContinueRun, "Continue"));
}
if (!inGame)
{
commands.Add(Command(AetheriaRuntimeMainMenuCommands.ContinueRun, "Continue"));
actionButtons.Add(Button(
$"{AetheriaRuntimeMainMenuCommands.RootSurfaceId}.continue",
"Continue",
AetheriaRuntimeMainMenuCommands.ContinueRun));
}
actions.Button("New Game", Operation(AetheriaRuntimeMainMenuCommands.NewGame, "New Game"));
actions.Button("Settings", Operation(AetheriaRuntimeMainMenuCommands.ShowSettings, "Settings"));
actions.Button("Quit", Operation(AetheriaRuntimeMainMenuCommands.Quit, "Quit"));
});
commands.Add(Command(AetheriaRuntimeMainMenuCommands.NewGame, "New Game"));
commands.Add(Command(AetheriaRuntimeMainMenuCommands.ShowSettings, "Settings"));
commands.Add(Command(AetheriaRuntimeMainMenuCommands.Quit, "Quit"));
actionButtons.Add(Button($"{AetheriaRuntimeMainMenuCommands.RootSurfaceId}.newGame", "New Game", AetheriaRuntimeMainMenuCommands.NewGame));
actionButtons.Add(Button($"{AetheriaRuntimeMainMenuCommands.RootSurfaceId}.settings", "Settings", AetheriaRuntimeMainMenuCommands.ShowSettings));
actionButtons.Add(Button($"{AetheriaRuntimeMainMenuCommands.RootSurfaceId}.quit", "Quit", AetheriaRuntimeMainMenuCommands.Quit));
return BuildSurfaceDocument(
AetheriaRuntimeMainMenuCommands.RootSurfaceId,
"Aetheria Terminus",
updatedAtUtc,
version,
commands,
Text($"{AetheriaRuntimeMainMenuCommands.RootSurfaceId}.title", "AETHERIA", "text.title"),
Text($"{AetheriaRuntimeMainMenuCommands.RootSurfaceId}.subtitle", "TERMINUS", "text.subtitle"),
ButtonColumn($"{AetheriaRuntimeMainMenuCommands.RootSurfaceId}.actions", actionButtons.ToArray()));
return AetheriaRuntimeSurfaceDocuments.FromPortableSurface(builder.Build());
}
public static AetheriaRuntimeSurfaceDocument BuildSettings(
string updatedAtUtc,
long version = 1)
{
return BuildSurfaceDocument(
AetheriaRuntimeMainMenuCommands.SettingsSurfaceId,
"Aetheria Settings",
updatedAtUtc,
version,
new[]
{
Command(AetheriaRuntimeMainMenuCommands.ShowPlayerSettings, "Player Settings"),
Command(AetheriaRuntimeMainMenuCommands.ShowVerseSettings, "Verse"),
Command(AetheriaRuntimeMainMenuCommands.ShowInputSettings, "Input"),
Command(AetheriaRuntimeMainMenuCommands.BackToMain, "Back")
},
Text("aetheria.mainMenu.settings.title", "SETTINGS", "text.title"),
ButtonColumn(
var builder = MainMenuSurface(
AetheriaRuntimeMainMenuCommands.SettingsSurfaceId,
"Aetheria Settings",
updatedAtUtc,
version)
.Title("SETTINGS")
.ButtonColumn(
"aetheria.mainMenu.settings.actions",
Button("aetheria.mainMenu.settings.playerSettings", "Player Settings", AetheriaRuntimeMainMenuCommands.ShowPlayerSettings),
Button("aetheria.mainMenu.settings.verse", "Verse", AetheriaRuntimeMainMenuCommands.ShowVerseSettings),
Button("aetheria.mainMenu.settings.input", "Input", AetheriaRuntimeMainMenuCommands.ShowInputSettings),
Button("aetheria.mainMenu.settings.back", "Back", AetheriaRuntimeMainMenuCommands.BackToMain)));
actions =>
{
actions.Button("Player Settings", Operation(AetheriaRuntimeMainMenuCommands.ShowPlayerSettings, "Player Settings"));
actions.Button("Verse", Operation(AetheriaRuntimeMainMenuCommands.ShowVerseSettings, "Verse"));
actions.Button("Input", Operation(AetheriaRuntimeMainMenuCommands.ShowInputSettings, "Input"));
actions.Button("Back", Operation(AetheriaRuntimeMainMenuCommands.BackToMain, "Back"));
});
return AetheriaRuntimeSurfaceDocuments.FromPortableSurface(builder.Build());
}
private static AetheriaRuntimeSurfaceDocument BuildInputSettings(
@ -214,63 +207,52 @@ namespace GameCult.Aetheria.State.Verse
string updatedAtUtc,
long version)
{
var commands = new List<AetheriaRuntimeSurfaceCommandTemplate>
{
Command(AetheriaRuntimeMainMenuCommands.BackToSettings, "Back")
};
var children = new List<AetheriaRuntimeSurfaceComponent>
{
Text("aetheria.mainMenu.input.title", "INPUT", "text.title"),
Metric(
"aetheria.mainMenu.input.bindingOverrides",
"Binding Overrides",
bindingOverrideCount.ToString()),
Metric(
"aetheria.mainMenu.input.actionBarInputs",
"Action-Bar Inputs",
actionBarInputCount.ToString())
};
var builder = MainMenuSurface(
AetheriaRuntimeMainMenuCommands.InputSettingsSurfaceId,
"Aetheria Input Settings",
updatedAtUtc,
version)
.Title("INPUT")
.Form(
"aetheria.mainMenu.input.metrics",
form => form
.Metric("Binding Overrides", bindingOverrideCount.ToString())
.Metric("Action-Bar Inputs", actionBarInputCount.ToString()));
if (canOpenRuntimeInputScreen)
{
commands.Insert(0, Command(AetheriaRuntimeMainMenuCommands.OpenRuntimeInputScreen, "Open Remap Screen"));
children.Add(Text(
"aetheria.mainMenu.input.note",
"The runtime Eve input screen owns low-level InputSystem rebinding and action-bar input edits. This title shell reports typed player-settings state and hands off to that owner."));
builder.Text(
"The runtime Eve input screen owns low-level InputSystem rebinding and action-bar input edits. This title shell reports typed player-settings state and hands off to that owner.",
"aetheria.mainMenu.input.note");
}
else if (inGame)
{
children.Add(Text(
"aetheria.mainMenu.input.note",
"The runtime Eve input screen should own rebinding here, but this scene has no active input surface to hand off to."));
builder.Text(
"The runtime Eve input screen should own rebinding here, but this scene has no active input surface to hand off to.",
"aetheria.mainMenu.input.note");
}
else
{
children.Add(Text(
"aetheria.mainMenu.input.note",
"This title shell reports the typed player-settings state. Launch a run to open the runtime Eve input screen that owns low-level InputSystem rebinding."));
builder.Text(
"This title shell reports the typed player-settings state. Launch a run to open the runtime Eve input screen that owns low-level InputSystem rebinding.",
"aetheria.mainMenu.input.note");
}
var buttons = new List<AetheriaRuntimeSurfaceComponent>();
if (canOpenRuntimeInputScreen)
{
buttons.Add(Button(
"aetheria.mainMenu.input.openRuntimeScreen",
"Open Remap Screen",
AetheriaRuntimeMainMenuCommands.OpenRuntimeInputScreen));
}
builder.ButtonColumn(
"aetheria.mainMenu.input.actions",
actions =>
{
if (canOpenRuntimeInputScreen)
{
actions.Button(
"Open Remap Screen",
Operation(AetheriaRuntimeMainMenuCommands.OpenRuntimeInputScreen, "Open Remap Screen"));
}
buttons.Add(Button("aetheria.mainMenu.input.back", "Back", AetheriaRuntimeMainMenuCommands.BackToSettings));
children.Add(ButtonColumn("aetheria.mainMenu.input.actions", buttons.ToArray()));
actions.Button("Back", Operation(AetheriaRuntimeMainMenuCommands.BackToSettings, "Back"));
});
return BuildSurfaceDocument(
AetheriaRuntimeMainMenuCommands.InputSettingsSurfaceId,
"Aetheria Input Settings",
updatedAtUtc,
version,
commands,
children.ToArray());
return AetheriaRuntimeSurfaceDocuments.FromPortableSurface(builder.Build());
}
public static AetheriaRuntimeSurfaceDocument BuildVerseSettingsShell(
@ -314,32 +296,21 @@ namespace GameCult.Aetheria.State.Verse
.ToArray());
}
private static string VerseLabel(string verseTitle, string verseId)
{
var title = string.IsNullOrWhiteSpace(verseTitle) ? "Unknown Verse" : verseTitle;
var id = string.IsNullOrWhiteSpace(verseId) ? "unknown" : verseId;
return string.Equals(title, id, StringComparison.Ordinal) ? title : $"{title} ({id})";
}
private static AetheriaRuntimeSurfaceDocument BuildSurfaceDocument(
private static GameCult.Mesh.EveSurfaceBuilder MainMenuSurface(
string surfaceId,
string title,
string updatedAtUtc,
long version,
IReadOnlyList<AetheriaRuntimeSurfaceCommandTemplate> commands,
params AetheriaRuntimeSurfaceComponent[] children)
long version)
{
return new AetheriaRuntimeSurfaceDocument(
providerId: ProviderId,
providerKind: ProviderKind,
title: title,
version: version,
updatedAtUtc: updatedAtUtc,
surface: new AetheriaRuntimeSurfaceTree(
surfaceId,
Node($"{surfaceId}.root", "surface", Array.Empty<(string Key, string Value)>(), children),
MainMenuStyleTokens()),
commands: commands);
var builder = GameCult.Mesh.EveSurface.Create(surfaceId)
.Provider(ProviderId, ProviderKind)
.Version(version)
.UpdatedAtUtc(updatedAtUtc);
foreach (var token in MainMenuStyleTokens())
builder.Style(token.Name, token.Value);
return builder;
}
private static IReadOnlyList<AetheriaRuntimeSurfaceStyleToken> MainMenuStyleTokens()
@ -363,17 +334,14 @@ namespace GameCult.Aetheria.State.Verse
return new AetheriaRuntimeSurfaceCommandTemplate(command, label, AetheriaRuntimeSurfaceCommandTemplate.CultMeshTransport);
}
private static AetheriaRuntimeSurfaceComponent Card(
string id,
string title,
params AetheriaRuntimeSurfaceComponent[] children)
private static CultMeshOperationBindingDescriptor Operation(string command, string label)
{
return Node(id, "card", new[] { ("title", title) }, children);
}
private static AetheriaRuntimeSurfaceComponent Metric(string id, string label, string value)
{
return Node(id, "metric", new[] { ("label", label), ("value", value ?? "") });
return CultMesh.OperationBindingRecord(
command,
label,
"",
nameof(CultMeshLocalityKind.Automatic),
AetheriaRuntimeSurfaceCommandTemplate.CultMeshTransport).ToBinding();
}
private static AetheriaRuntimeSurfaceComponent Text(string id, string value)
@ -454,7 +422,7 @@ namespace GameCult.Aetheria.State.Verse
public static class AetheriaRuntimeMainMenuSurfaceCommands
{
public static bool TryRead(
EveSurfaceCommandRequest request,
EveUiCommandRequest request,
out AetheriaRuntimeMainMenuCommand command)
{
command = default;

View file

@ -2,10 +2,15 @@ using System;
using System.Collections.Generic;
using System.Linq;
using GameCult.Caching;
using GameCult.Eve.Surface;
using GameCult.Mesh;
using MessagePack;
using EveSurfaceState = global::Aetheria.State.Documents.EveSurfaceState;
using EveUiCommandTemplate = GameCult.Eve.Surface.EveCommandTemplate;
using EveUiEmbeddedDocumentSlot = GameCult.Eve.Surface.EveEmbeddedDocumentSlot;
using EveUiStyleToken = GameCult.Eve.Surface.EveStyleToken;
using EveUiSurfaceComponent = GameCult.Eve.Surface.EveSurfaceComponent;
using EveUiSurfaceDocument = GameCult.Eve.Surface.EveSurfaceDocument;
using EveUiSurfaceTree = GameCult.Eve.Surface.EveSurfaceTree;
#nullable enable
@ -264,23 +269,45 @@ namespace GameCult.Aetheria.State.Verse
};
}
public static EveSurfaceDocument ToEveSurfaceDocument(AetheriaRuntimeSurfaceDocument document)
public static AetheriaRuntimeSurfaceDocument FromPortableSurface(GameCult.Mesh.EveSurfaceDocument document)
{
if (document == null) throw new ArgumentNullException(nameof(document));
return new AetheriaRuntimeSurfaceDocument(
document.ProviderId,
document.ProviderKind,
document.Title,
document.Version,
document.UpdatedAtUtc,
new AetheriaRuntimeSurfaceTree(
document.Surface.Id,
FromPortableComponent(document.Surface.Root),
document.Surface.Styles
.Select(style => new AetheriaRuntimeSurfaceStyleToken(style.Name, style.Value))
.ToArray()),
document.Commands
.Select(command => new AetheriaRuntimeSurfaceCommandTemplate(
FromPortableOperation(command.Operation)))
.ToArray());
}
public static EveUiSurfaceDocument ToEveSurfaceDocument(AetheriaRuntimeSurfaceDocument document)
{
return ToEveSurfaceDocument(document, null);
}
public static EveSurfaceDocument ToEveSurfaceDocument(EveSurfaceState state)
public static EveUiSurfaceDocument ToEveSurfaceDocument(EveSurfaceState state)
{
return ToEveSurfaceDocument(state, null);
}
public static EveSurfaceDocument ToEveSurfaceDocument(
public static EveUiSurfaceDocument ToEveSurfaceDocument(
EveSurfaceState state,
CultMeshStateRefResolver? stateRefResolver)
{
if (state == null) throw new ArgumentNullException(nameof(state));
var surface = new EveSurfaceDocument(
var surface = new EveUiSurfaceDocument(
state.Type,
state.Schema,
state.ProviderId,
@ -288,27 +315,27 @@ namespace GameCult.Aetheria.State.Verse
state.Title,
state.Version,
state.UpdatedAtUtc,
new EveSurfaceTree(
new EveUiSurfaceTree(
state.Surface.Id,
ToEveSurfaceComponent(state.Surface.Root),
state.Surface.Styles
.Select(style => new EveStyleToken(style.Name, style.Value))
.Select(style => new EveUiStyleToken(style.Name, style.Value))
.ToArray()),
state.Commands
.Select(command => new EveCommandTemplate(
.Select(command => new EveUiCommandTemplate(
ToCultMeshOperationBinding(command)))
.ToArray());
return ResolveStateRefs(surface, stateRefResolver);
}
public static EveSurfaceDocument ToEveSurfaceDocument(
public static EveUiSurfaceDocument ToEveSurfaceDocument(
AetheriaRuntimeSurfaceDocument document,
CultMeshStateRefResolver? stateRefResolver)
{
if (document == null) throw new ArgumentNullException(nameof(document));
var surface = new EveSurfaceDocument(
var surface = new EveUiSurfaceDocument(
"surface-state",
"gamecult.eve.surface.v1",
document.ProviderId,
@ -316,21 +343,21 @@ namespace GameCult.Aetheria.State.Verse
document.Title,
document.Version,
document.UpdatedAtUtc,
new EveSurfaceTree(
new EveUiSurfaceTree(
document.Surface.Id,
ToEveSurfaceComponent(document.Surface.Root),
document.Surface.Styles
.Select(style => new EveStyleToken(style.Name, style.Value))
.Select(style => new EveUiStyleToken(style.Name, style.Value))
.ToArray()),
document.Commands
.Select(command => new EveCommandTemplate(command.Operation))
.Select(command => new EveUiCommandTemplate(command.Operation))
.ToArray());
return ResolveStateRefs(surface, stateRefResolver);
}
public static EveSurfaceDocument ResolveStateRefs(
EveSurfaceDocument surface,
public static EveUiSurfaceDocument ResolveStateRefs(
EveUiSurfaceDocument surface,
CultMeshStateRefResolver? stateRefResolver)
{
if (surface == null) throw new ArgumentNullException(nameof(surface));
@ -338,7 +365,7 @@ namespace GameCult.Aetheria.State.Verse
return surface;
var resolveStateRef = stateRefResolver.AsFunc();
return new EveSurfaceDocument(
return new EveUiSurfaceDocument(
surface.Type,
surface.Schema,
surface.ProviderId,
@ -346,17 +373,17 @@ namespace GameCult.Aetheria.State.Verse
surface.Title,
surface.Version,
surface.UpdatedAtUtc,
new EveSurfaceTree(
new EveUiSurfaceTree(
surface.Surface.Id,
ResolveStateRefs(surface.Surface.Root, resolveStateRef),
surface.Surface.Styles),
surface.Commands);
}
public static EveSurfaceDocument EmptySurface(string surfaceId)
public static EveUiSurfaceDocument EmptySurface(string surfaceId)
{
var id = string.IsNullOrWhiteSpace(surfaceId) ? "aetheria.surface.missing" : surfaceId;
return new EveSurfaceDocument(
return new EveUiSurfaceDocument(
"surface-state",
"gamecult.eve.surface.v1",
"aetheria.daemon",
@ -364,22 +391,22 @@ namespace GameCult.Aetheria.State.Verse
"",
0,
"",
new EveSurfaceTree(
new EveUiSurfaceTree(
id,
new EveSurfaceComponent(
new EveUiSurfaceComponent(
id + ".missing",
"surface",
new Dictionary<string, string>(StringComparer.Ordinal),
Array.Empty<EveSurfaceComponent>()),
Array.Empty<EveStyleToken>()),
Array.Empty<EveCommandTemplate>());
Array.Empty<EveUiSurfaceComponent>()),
Array.Empty<EveUiStyleToken>()),
Array.Empty<EveUiCommandTemplate>());
}
private static EveSurfaceComponent ToEveSurfaceComponent(AetheriaRuntimeSurfaceComponent component)
private static EveUiSurfaceComponent ToEveSurfaceComponent(AetheriaRuntimeSurfaceComponent component)
{
var props = new Dictionary<string, string>(component.Props, StringComparer.Ordinal);
AetheriaRuntimeSurfaceStateBindings.AddPointerProps(props, component.StateBindings);
return new EveSurfaceComponent(
return new EveUiSurfaceComponent(
component.Id,
component.Kind,
props,
@ -435,7 +462,7 @@ namespace GameCult.Aetheria.State.Verse
};
}
private static EveSurfaceComponent ToEveSurfaceComponent(global::Aetheria.State.Documents.EveSurfaceComponent component)
private static EveUiSurfaceComponent ToEveSurfaceComponent(global::Aetheria.State.Documents.EveSurfaceComponent component)
{
var props = new Dictionary<string, string>(component.Props, StringComparer.Ordinal);
var stateBindings = (component.StateBindings ?? Array.Empty<global::Aetheria.State.Documents.EveSurfaceStateBinding>())
@ -444,7 +471,7 @@ namespace GameCult.Aetheria.State.Verse
AetheriaRuntimeSurfaceStateBindings.AddPointerProps(
props,
stateBindings);
return new EveSurfaceComponent(
return new EveUiSurfaceComponent(
component.Id,
component.Kind,
props,
@ -452,9 +479,9 @@ namespace GameCult.Aetheria.State.Verse
stateBindings.Select(ToCultMeshStateBinding).ToArray());
}
private static EveEmbeddedDocumentSlot ToEveEmbeddedDocumentSlot(AetheriaRuntimeEmbeddedDocumentSlot slot)
private static EveUiEmbeddedDocumentSlot ToEveEmbeddedDocumentSlot(AetheriaRuntimeEmbeddedDocumentSlot slot)
{
return new EveEmbeddedDocumentSlot(
return new EveUiEmbeddedDocumentSlot(
slot.SlotId,
slot.DocumentId,
slot.SchemaId,
@ -497,14 +524,14 @@ namespace GameCult.Aetheria.State.Verse
routeDescription).ToBinding();
}
private static EveSurfaceComponent ResolveStateRefs(
EveSurfaceComponent component,
private static EveUiSurfaceComponent ResolveStateRefs(
EveUiSurfaceComponent component,
Func<string, string> resolveStateRef)
{
var props = new Dictionary<string, string>(component.Props, StringComparer.Ordinal);
ResolvePropRefs(props, resolveStateRef);
return new EveSurfaceComponent(
return new EveUiSurfaceComponent(
component.Id,
component.Kind,
props,
@ -513,19 +540,69 @@ namespace GameCult.Aetheria.State.Verse
component.EmbeddedDocuments);
}
private static IReadOnlyList<EveSurfaceComponent> ResolveStateRefs(
IReadOnlyList<EveSurfaceComponent> children,
private static IReadOnlyList<EveUiSurfaceComponent> ResolveStateRefs(
IReadOnlyList<EveUiSurfaceComponent> children,
Func<string, string> resolveStateRef)
{
if (children == null || children.Count == 0)
return Array.Empty<EveSurfaceComponent>();
return Array.Empty<EveUiSurfaceComponent>();
var resolved = new EveSurfaceComponent[children.Count];
var resolved = new EveUiSurfaceComponent[children.Count];
for (var index = 0; index < children.Count; index++)
resolved[index] = ResolveStateRefs(children[index], resolveStateRef);
return resolved;
}
private static AetheriaRuntimeSurfaceComponent FromPortableComponent(GameCult.Mesh.EveSurfaceComponent component)
{
return new AetheriaRuntimeSurfaceComponent(
component.Id,
component.Kind,
new Dictionary<string, string>(component.Props, StringComparer.Ordinal),
component.Children.Select(FromPortableComponent).ToArray(),
component.StateBindings.Select(FromPortableStateBinding).ToArray(),
component.EmbeddedDocuments.Select(FromPortableEmbeddedDocumentSlot).ToArray());
}
private static AetheriaRuntimeEmbeddedDocumentSlot FromPortableEmbeddedDocumentSlot(
GameCult.Mesh.EveEmbeddedDocumentSlot slot)
{
return new AetheriaRuntimeEmbeddedDocumentSlot(
slot.SlotId,
slot.DocumentId,
slot.SchemaId,
slot.PresentationKind,
FromPortableRoute(slot.RouteHint));
}
private static CultMeshStateBindingDescriptor FromPortableStateBinding(
GameCult.Mesh.EveSurfaceStateBinding binding)
{
return CultMesh.StateBindingRecord(
binding.TargetProp,
binding.PointerId,
binding.SourceId,
binding.SchemaId,
binding.RouteHint.Kind,
binding.RouteHint.Description).ToBinding();
}
private static CultMeshOperationBindingDescriptor FromPortableOperation(
GameCult.Mesh.EveSurfaceOperationBinding operation)
{
return CultMesh.OperationBindingRecord(
operation.OperationId,
operation.Label,
operation.SchemaId,
operation.RouteHint.Kind,
operation.RouteHint.Description).ToBinding();
}
private static CultMeshRouteHint FromPortableRoute(GameCult.Mesh.EveSurfaceRouteHint route)
{
return new CultMeshRouteRecord(route.Kind, route.Description).ToRoute(CultMeshRouteHint.Automatic);
}
private static void ResolvePropRefs(
Dictionary<string, string> props,
Func<string, string> resolveStateRef)