Replace input layout JSON with typed projection

This commit is contained in:
Meta Vens 2026-06-13 22:45:06 +01:00
commit ccdfc1fbfc
8 changed files with 84 additions and 325 deletions

Binary file not shown.

View file

@ -49,15 +49,15 @@ Unity runtime code, with `RuntimeEntityBlueprintProjector` capturing and
instantiating those projections. They no longer carry save-file or serializer
vocabulary, and they do not declare MessagePack persistence attributes.
Keyboard layout rendering now reads the checked-in Unity text asset directly.
`InputDisplayLayout` parses that display geometry through Unity-side `SimpleJson`
as a projection parser, not as durable Aetheria state. The generated
`AetheriaInput` wrapper still calls Unity's `InputActionAsset.FromJson`; that is
an engine-owned lowering boundary under Aetheria's remapping layer, not a save
format or state owner. The old generated `GameData/KeyboardLayouts/*.msgpack`
cache was deleted. Remapping and action-bar edits are owned by typed
`AetheriaPlayerSettings` commits; keyboard display layout edits remain
runtime-only until Verse owns a typed layout document.
Keyboard layout rendering now builds the static ANSI-104 display as typed
`InputLayout` rows and columns. It no longer reads a checked-in JSON text asset
or uses `SimpleJson` for display geometry. The generated `AetheriaInput` wrapper
still calls Unity's `InputActionAsset.FromJson`; that is an engine-owned
lowering boundary under Aetheria's remapping layer, not a save format or state
owner. The old generated `GameData/KeyboardLayouts/*.msgpack` cache and the
checked-in `ansi104.json` display file are deleted. Remapping and action-bar
edits are owned by typed `AetheriaPlayerSettings` commits; keyboard display
layout edits remain runtime-only until Verse owns a typed layout document.
The old IMGUI CultCache database editor has been deleted, and `NameTools` no
longer exports `NameFile/*.msgpack`. `AetherDB.msgpack` and existing name files

View file

@ -171,7 +171,6 @@ MonoBehaviour:
MouseForward: {fileID: 3575543200853098931}
MouseBack: {fileID: 3575543200736016711}
RowContainer: {fileID: 3575543201062286835}
LayoutFile: {fileID: 4900000, guid: 44459239c373d2c449a479e84867648a, type: 3}
LabelPrototype: {fileID: 3575543201132091708}
LinePrototype: {fileID: 3575543201409287276}
RowPrototype: {fileID: 3575543199809032540}

View file

@ -1,214 +0,0 @@
[
[
"Esc",
{
"x": 1
},
"F1",
"F2",
"F3",
"F4",
{
"x": 0.5
},
"F5",
"F6",
"F7",
"F8",
{
"x": 0.5
},
"F9",
"F10",
"F11",
"F12",
{
"x": 0.25
},
"",
"",
""
],
[
{
"y": 0.5
},
"~\n`",
"!\n1",
"@\n2",
"#\n3",
"$\n4",
"%\n5",
"^\n6",
"&\n7",
"*\n8",
"(\n9",
")\n0",
"_\n-",
"+\n=",
{
"w": 2
},
"Backspace",
{
"x": 0.25
},
"Insert",
"Home",
"PgUp",
{
"x": 0.25
},
"",
"/",
"*",
"-"
],
[
{
"w": 1.5
},
"Tab",
"Q",
"W",
"E",
"R",
"T",
"Y",
"U",
"I",
"O",
"P",
"{\n[",
"}\n]",
{
"w": 1.5
},
"|\n\\",
{
"x": 0.25
},
"Delete",
"End",
"PgDn",
{
"x": 0.25
},
"Home\n7",
"↑\n8",
"PgUp\n9",
{
"h": 2
},
"+"
],
[
{
"w": 1.75
},
"Caps Lock",
"A",
"S",
"D",
"F",
"G",
"H",
"J",
"K",
"L",
":\n;",
"\"\n'",
{
"w": 2.25
},
"Enter",
{
"x": 3.5
},
"←\n4",
"5",
"→\n6"
],
[
{
"w": 2.25
},
"Shift",
"Z",
"X",
"C",
"V",
"B",
"N",
"M",
"<\n,",
">\n.",
"?\n/",
{
"w": 2.75
},
"Shift",
{
"x": 1.25
},
"↑",
{
"x": 1.25
},
"End\n1",
"↓\n2",
"PgDn\n3",
{
"h": 2
},
"Enter"
],
[
{
"w": 1.25
},
"Ctrl",
{
"w": 1.25
},
"",
{
"w": 1.25
},
"Alt",
{
"a": 7,
"w": 6.25
},
"Spacebar",
{
"a": 4,
"w": 1.25
},
"Alt",
{
"w": 1.25
},
"",
{
"w": 1.25
},
"",
{
"w": 1.25
},
"Ctrl",
{
"x": 0.25
},
"←",
"↓",
"→",
{
"x": 0.25,
"w": 2
},
"Ins\n0",
"Del\n."
]
]

View file

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 44459239c373d2c449a479e84867648a
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -2,7 +2,6 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Ink.Runtime;
using TMPro;
using UniRx;
using UnityEngine;
@ -23,7 +22,6 @@ public class InputDisplayLayout : MonoBehaviour
public InputDisplayButton MouseForward;
public InputDisplayButton MouseBack;
public VerticalLayoutGroup RowContainer;
public TextAsset LayoutFile;
public Prototype LabelPrototype;
public Prototype LinePrototype;
//public UILineRendererList LineRenderer;
@ -82,7 +80,7 @@ public class InputDisplayLayout : MonoBehaviour
void Start()
{
_canvas = transform.root.GetComponent<Canvas>();
_inputLayout = ParseKeyboardLayoutProjection(LayoutFile.text);
_inputLayout = InputLayout.CreateAnsi104();
DisplayLayout(_inputLayout);
_buttonMappings.Add(MapMouseButton(MouseLeft, "<Mouse>/leftButton"));
@ -376,93 +374,6 @@ public class InputDisplayLayout : MonoBehaviour
}
}
public InputLayout ParseKeyboardLayoutProjection(string layout)
{
var rows = new List<InputLayoutRow>();
var nextWidth = 1f;
var nextHeight = 1;
foreach (var rowValue in SimpleJson.TextToArray(layout))
{
if (!(rowValue is List<object> parsedRow))
throw new FormatException("Unexpected keyboard layout JSON format: expected a row array.");
var row = new InputLayoutKeyRow();
var columns = new List<InputLayoutColumn>();
foreach (var columnValue in parsedRow)
{
switch (columnValue)
{
case Dictionary<string, object> options:
ApplyLayoutOptions(options, rows, columns, ref nextWidth, ref nextHeight);
break;
case string label:
columns.Add(CreateLayoutKey(label, ref nextWidth, ref nextHeight));
break;
default:
throw new FormatException("Unexpected keyboard layout JSON format: expected a key label or options object.");
}
}
row.Columns = columns.ToArray();
rows.Add(row);
}
return new InputLayout {Rows = rows.ToArray()};
}
private static void ApplyLayoutOptions(
Dictionary<string, object> options,
ICollection<InputLayoutRow> rows,
ICollection<InputLayoutColumn> columns,
ref float nextWidth,
ref int nextHeight)
{
foreach (var option in options)
{
switch (option.Key)
{
case "a":
break;
case "w":
nextWidth = Convert.ToSingle(option.Value);
break;
case "h":
nextHeight = Convert.ToInt32(option.Value);
break;
case "y":
rows.Add(new InputLayoutRowSpacer {Height = Convert.ToSingle(option.Value)});
break;
case "x":
columns.Add(new InputLayoutColumnSpacer {Width = Convert.ToSingle(option.Value)});
break;
}
}
}
private static InputLayoutKey CreateLayoutKey(string label, ref float nextWidth, ref int nextHeight)
{
InputLayoutKey key;
var trimmedLabel = label.Trim();
if (!string.IsNullOrEmpty(trimmedLabel))
{
var labels = trimmedLabel.Split('\n');
key = nextHeight != 1 ? new InputLayoutMultiRowKey {Height = nextHeight} : new InputLayoutBindableKey();
nextHeight = 1;
((InputLayoutBindableKey) key).MainLabel = labels.Length == 2 ? labels[1] : trimmedLabel;
((InputLayoutBindableKey) key).AltLabel = labels.Length == 2 ? labels[0] : "";
}
else
{
key = new InputLayoutKey();
}
key.Width = nextWidth;
nextWidth = 1f;
return key;
}
private IEnumerator AssociateInputKeys()
{
var path = "";

View file

@ -4,6 +4,76 @@ public class InputLayout
{
public InputLayoutRow[] Rows;
public static InputLayout CreateAnsi104()
{
return new InputLayout
{
Rows = new InputLayoutRow[]
{
Row(
Key("Esc"), Spacer(1), Key("F1"), Key("F2"), Key("F3"), Key("F4"), Spacer(.5f),
Key("F5"), Key("F6"), Key("F7"), Key("F8"), Spacer(.5f),
Key("F9"), Key("F10"), Key("F11"), Key("F12"), Spacer(.25f),
Key(""), Key(""), Key("")),
RowSpacer(.5f),
Row(
Key("~\n`"), Key("!\n1"), Key("@\n2"), Key("#\n3"), Key("$\n4"), Key("%\n5"), Key("^\n6"),
Key("&\n7"), Key("*\n8"), Key("(\n9"), Key(")\n0"), Key("_\n-"), Key("+\n="), Key("Backspace", 2),
Spacer(.25f), Key("Insert"), Key("Home"), Key("PgUp"), Spacer(.25f), Key(""), Key("/"), Key("*"), Key("-")),
Row(
Key("Tab", 1.5f), Key("Q"), Key("W"), Key("E"), Key("R"), Key("T"), Key("Y"), Key("U"), Key("I"), Key("O"), Key("P"),
Key("{\n["), Key("}\n]"), Key("|\n\\", 1.5f), Spacer(.25f),
Key("Delete"), Key("End"), Key("PgDn"), Spacer(.25f), Key("Home\n7"), Key("Up\n8"), Key("PgUp\n9"), Key("+", 1, 2)),
Row(
Key("Caps Lock", 1.75f), Key("A"), Key("S"), Key("D"), Key("F"), Key("G"), Key("H"), Key("J"), Key("K"), Key("L"),
Key(":\n;"), Key("\"\n'"), Key("Enter", 2.25f), Spacer(3.5f), Key("Left\n4"), Key("5"), Key("Right\n6")),
Row(
Key("Shift", 2.25f), Key("Z"), Key("X"), Key("C"), Key("V"), Key("B"), Key("N"), Key("M"),
Key("<\n,"), Key(">\n."), Key("?\n/"), Key("Shift", 2.75f), Spacer(1.25f), Key("Up"), Spacer(1.25f),
Key("End\n1"), Key("Down\n2"), Key("PgDn\n3"), Key("Enter", 1, 2)),
Row(
Key("Ctrl", 1.25f), Key("", 1.25f), Key("Alt", 1.25f), Key("Spacebar", 6.25f), Key("Alt", 1.25f),
Key("", 1.25f), Key("", 1.25f), Key("Ctrl", 1.25f), Spacer(.25f),
Key("Left"), Key("Down"), Key("Right"), Spacer(.25f), Key("Ins\n0", 2), Key("Del\n."))
}
};
}
private static InputLayoutRowSpacer RowSpacer(float height)
{
return new InputLayoutRowSpacer {Height = height};
}
private static InputLayoutKeyRow Row(params InputLayoutColumn[] columns)
{
return new InputLayoutKeyRow {Columns = columns};
}
private static InputLayoutColumnSpacer Spacer(float width)
{
return new InputLayoutColumnSpacer {Width = width};
}
private static InputLayoutKey Key(string label, float width = 1f, int height = 1)
{
InputLayoutKey key;
var trimmedLabel = label.Trim();
if (!string.IsNullOrEmpty(trimmedLabel))
{
var labels = trimmedLabel.Split('\n');
key = height != 1 ? new InputLayoutMultiRowKey {Height = height} : new InputLayoutBindableKey();
((InputLayoutBindableKey) key).MainLabel = labels.Length == 2 ? labels[1] : trimmedLabel;
((InputLayoutBindableKey) key).AltLabel = labels.Length == 2 ? labels[0] : "";
}
else
{
key = new InputLayoutKey();
}
key.Width = width;
return key;
}
public IEnumerable<InputLayoutBindableKey> GetBindableKeys()
{
foreach (var row in Rows)

View file

@ -762,10 +762,10 @@ First Aetheria surfaces to publish:
`InputActionAsset.FromJson`, but that JSON belongs to Unity's generated input
action lowering under Aetheria's remapping system. It is not durable Aetheria
state and does not own remapping authority.
- Keyboard display layout parsing is named as a runtime projection parser:
`InputDisplayLayout` uses Unity-side `SimpleJson` only to read checked-in
keyboard display geometry. The dead commented Ink `ToJson` write path has
been removed from live source.
- Keyboard display layout parsing is no longer JSON-backed:
`InputDisplayLayout` builds its static ANSI-104 display projection from typed
`InputLayout` rows/columns. The dead commented Ink `ToJson` write path and
checked-in `ansi104.json` display file have been removed from live source.
- `Aetheria.State.Smoke` proves the provider-owned Eve command bridge drains
`gamecult.eve.command.v1` envelopes, accepts advertised refresh commands,
rejects unknown commands, persists `AetheriaEveCommandDrainStatus`, and exposes