Thing/packages/GameCult.Thing.Contract/Node.cs
Meta Vens b8e8abd981 GameCult.Thing.Contract: ParamDecl.Kind keeps its name (a rename sed hit its assignment)
The two previous GameCult.Thing.Contract commits do not build: ParamDecl's constructor assigned
InputKind. This restores Kind = Present(kind, "Kind").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:21:08 +02:00

663 lines
18 KiB
C#

using System.Collections.Generic;
using GameCult.Caching;
using MessagePack;
namespace GameCult.Thing.Contract;
[Union(0, typeof(BoxNode))]
[Union(1, typeof(TextNode))]
[Union(2, typeof(ImageNode))]
[Union(3, typeof(ButtonNode))]
[Union(4, typeof(ToggleNode))]
[Union(5, typeof(SliderNode))]
[Union(6, typeof(TextInputNode))]
[Union(7, typeof(SelectNode))]
[Union(8, typeof(RepeatNode))]
[Union(9, typeof(OverlayNode))]
[Union(10, typeof(PlotNode))]
[Union(11, typeof(EmbedNode))]
[Union(12, typeof(UseNode))]
public abstract class Node
{
internal Node() { }
}
[MessagePackObject]
public sealed class BoxNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public BoxStyle Style { get; }
[Key(2)] public Paint Paint { get; }
[Key(3)] public Role Role { get; }
[Key(4)] public IReadOnlyList<Node> Children { get; }
public BoxNode(NodeCommon common, BoxStyle style, Paint paint, Role role, IReadOnlyList<Node> children)
{
Common = ThingDomain.Present(common, "Common");
Style = ThingDomain.Present(style, "Style");
Paint = ThingDomain.Present(paint, "Paint");
Role = ThingDomain.Present(role, "Role");
Children = ThingDomain.Items(children, "Children");
}
}
[MessagePackObject]
public sealed class TextNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public TextSource Content { get; }
[Key(2)] public string StyleToken { get; }
[Key(3)] public bool Wrap { get; }
[Key(4)] public int? MaxLines { get; }
[Key(5)] public bool Selectable { get; }
public TextNode(NodeCommon common, TextSource content, string styleToken, bool wrap, int? maxLines, bool selectable)
{
Common = ThingDomain.Present(common, "Common");
Content = ThingDomain.Present(content, "Content");
StyleToken = ThingDomain.Present(styleToken, "StyleToken");
Wrap = wrap;
MaxLines = ThingDomain.Count(maxLines);
Selectable = selectable;
}
}
[MessagePackObject]
public sealed class ImageNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public string Catalog { get; }
[Key(2)] public string Asset { get; }
[Key(3)] public ImageFit Fit { get; }
[Key(4)] public TextSource Alt { get; }
public ImageNode(NodeCommon common, string catalog, string asset, ImageFit fit, TextSource alt)
{
Common = ThingDomain.Present(common, "Common");
Catalog = ThingDomain.Present(catalog, "Catalog");
Asset = ThingDomain.Present(asset, "Asset");
Fit = ThingDomain.Present(fit, "Fit");
Alt = ThingDomain.Present(alt, "Alt");
}
}
[MessagePackObject]
public sealed class ButtonNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public IReadOnlyList<Node> Content { get; }
[Key(2)] public CommandRef OnActivate { get; }
[Key(3)] public BoolSource Enabled { get; }
public ButtonNode(NodeCommon common, IReadOnlyList<Node> content, CommandRef onActivate, BoolSource enabled)
{
Common = ThingDomain.Present(common, "Common");
Content = ThingDomain.Items(content, "Content");
OnActivate = ThingDomain.Present(onActivate, "OnActivate");
Enabled = ThingDomain.Present(enabled, "Enabled");
}
}
[MessagePackObject]
public sealed class ToggleNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public BoolSource Checked { get; }
[Key(2)] public CommandRef OnChange { get; }
public ToggleNode(NodeCommon common, BoolSource @checked, CommandRef onChange)
{
Common = ThingDomain.Present(common, "Common");
Checked = ThingDomain.Present(@checked, "Checked");
OnChange = ThingDomain.Present(onChange, "OnChange");
}
}
[MessagePackObject]
public sealed class SliderNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public double Min { get; }
[Key(2)] public double Max { get; }
[Key(3)] public double Step { get; }
[Key(4)] public NumberSource Value { get; }
[Key(5)] public CommandRef Commit { get; }
public SliderNode(NodeCommon common, double min, double max, double step, NumberSource value, CommandRef commit)
{
Common = ThingDomain.Present(common, "Common");
Min = min;
Max = max;
Step = step;
Value = ThingDomain.Present(value, "Value");
Commit = ThingDomain.Present(commit, "Commit");
}
}
[MessagePackObject]
public sealed class TextInputNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public bool Multiline { get; }
[Key(2)] public InputKind InputKind { get; }
[Key(3)] public TextSource Placeholder { get; }
[Key(4)] public TextSource Initial { get; }
[Key(5)] public CommandRef Submit { get; }
public TextInputNode(NodeCommon common, bool multiline, InputKind inputKind, TextSource placeholder, TextSource initial, CommandRef submit)
{
Common = ThingDomain.Present(common, "Common");
Multiline = multiline;
InputKind = ThingDomain.Present(inputKind, "InputKind");
Placeholder = ThingDomain.Present(placeholder, "Placeholder");
Initial = ThingDomain.Present(initial, "Initial");
Submit = ThingDomain.Present(submit, "Submit");
}
}
[MessagePackObject]
public sealed class SelectNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public OptionList Options { get; }
[Key(2)] public Bind Value { get; }
[Key(3)] public CommandRef OnChange { get; }
public SelectNode(NodeCommon common, OptionList options, Bind value, CommandRef onChange)
{
Common = ThingDomain.Present(common, "Common");
Options = ThingDomain.Present(options, "Options");
Value = ThingDomain.Present(value, "Value");
OnChange = ThingDomain.Present(onChange, "OnChange");
}
}
[MessagePackObject]
public sealed class RepeatNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public CollectionSource Collection { get; }
[Key(2)] public MemberPath KeyMember { get; }
[Key(3)] public Node Template { get; }
public RepeatNode(NodeCommon common, CollectionSource collection, MemberPath keyMember, Node template)
{
Common = ThingDomain.Present(common, "Common");
Collection = ThingDomain.Present(collection, "Collection");
KeyMember = ThingDomain.Present(keyMember, "KeyMember");
Template = ThingDomain.Present(template, "Template");
}
}
[MessagePackObject]
public sealed class OverlayNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public Anchor Anchor { get; }
[Key(2)] public bool Modal { get; }
[Key(3)] public CommandRef Dismiss { get; }
[Key(4)] public IReadOnlyList<Node> Children { get; }
public OverlayNode(NodeCommon common, Anchor anchor, bool modal, CommandRef dismiss, IReadOnlyList<Node> children)
{
Common = ThingDomain.Present(common, "Common");
Anchor = ThingDomain.Present(anchor, "Anchor");
Modal = modal;
Dismiss = ThingDomain.Present(dismiss, "Dismiss");
Children = ThingDomain.Items(children, "Children");
}
}
[MessagePackObject]
public sealed class PlotNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public Bind Series { get; }
[Key(2)] public PlotMark Mark { get; }
[Key(3)] public double? XMin { get; }
[Key(4)] public double? XMax { get; }
[Key(5)] public double? YMin { get; }
[Key(6)] public double? YMax { get; }
public PlotNode(NodeCommon common, Bind series, PlotMark mark, double? xMin, double? xMax, double? yMin, double? yMax)
{
Common = ThingDomain.Present(common, "Common");
Series = ThingDomain.Present(series, "Series");
Mark = ThingDomain.Present(mark, "Mark");
XMin = xMin;
XMax = xMax;
YMin = yMin;
YMax = yMax;
}
}
[MessagePackObject]
public sealed class EmbedNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public string SlotKind { get; }
[Key(2)] public string SlotId { get; }
[Key(3)] public double Width { get; }
[Key(4)] public double Height { get; }
public EmbedNode(NodeCommon common, string slotKind, string slotId, double width, double height)
{
Common = ThingDomain.Present(common, "Common");
SlotKind = ThingDomain.Present(slotKind, "SlotKind");
SlotId = ThingDomain.Present(slotId, "SlotId");
Width = width;
Height = height;
}
}
[MessagePackObject]
public sealed class UseNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public CompositionRef Composition { get; }
[Key(2)] public IReadOnlyList<Arg> Args { get; }
public UseNode(NodeCommon common, CompositionRef composition, IReadOnlyList<Arg> args)
{
Common = ThingDomain.Present(common, "Common");
Composition = ThingDomain.Present(composition, "Composition");
Args = ThingDomain.Items(args, "Args");
}
}
[Union(0, typeof(ImageFitContain))]
[Union(1, typeof(ImageFitCover))]
[Union(2, typeof(ImageFitFill))]
[Union(3, typeof(ImageFitUnscaled))]
public abstract class ImageFit
{
internal ImageFit() { }
}
[MessagePackObject]
public sealed class ImageFitContain : ImageFit
{
public ImageFitContain() { }
}
[MessagePackObject]
public sealed class ImageFitCover : ImageFit
{
public ImageFitCover() { }
}
[MessagePackObject]
public sealed class ImageFitFill : ImageFit
{
public ImageFitFill() { }
}
[MessagePackObject]
public sealed class ImageFitUnscaled : ImageFit
{
public ImageFitUnscaled() { }
}
[Union(0, typeof(InputKindText))]
[Union(1, typeof(InputKindNumber))]
public abstract class InputKind
{
internal InputKind() { }
}
[MessagePackObject]
public sealed class InputKindText : InputKind
{
public InputKindText() { }
}
[MessagePackObject]
public sealed class InputKindNumber : InputKind
{
public InputKindNumber() { }
}
[Union(0, typeof(LiteralOptions))]
[Union(1, typeof(BoundOptions))]
public abstract class OptionList
{
internal OptionList() { }
}
[MessagePackObject]
public sealed class LiteralOptions : OptionList
{
[Key(0)] public IReadOnlyList<SelectOption> Options { get; }
public LiteralOptions(IReadOnlyList<SelectOption> options)
{
Options = ThingDomain.Items(options, "Options");
}
}
[MessagePackObject]
public sealed class BoundOptions : OptionList
{
[Key(0)] public CollectionSource Collection { get; }
[Key(1)] public MemberPath ValueMember { get; }
[Key(2)] public MemberPath LabelMember { get; }
public BoundOptions(CollectionSource collection, MemberPath valueMember, MemberPath labelMember)
{
Collection = ThingDomain.Present(collection, "Collection");
ValueMember = ThingDomain.Present(valueMember, "ValueMember");
LabelMember = ThingDomain.Present(labelMember, "LabelMember");
}
}
[Union(0, typeof(AnchorViewport))]
[Union(1, typeof(AnchorNode))]
public abstract class Anchor
{
internal Anchor() { }
}
[MessagePackObject]
public sealed class AnchorViewport : Anchor
{
public AnchorViewport() { }
}
[MessagePackObject]
public sealed class AnchorNode : Anchor
{
[Key(0)] public string Node { get; }
public AnchorNode(string node)
{
Node = ThingDomain.Present(node, "Node");
}
}
[Union(0, typeof(PlotMarkLine))]
[Union(1, typeof(PlotMarkBar))]
[Union(2, typeof(PlotMarkArea))]
public abstract class PlotMark
{
internal PlotMark() { }
}
[MessagePackObject]
public sealed class PlotMarkLine : PlotMark
{
public PlotMarkLine() { }
}
[MessagePackObject]
public sealed class PlotMarkBar : PlotMark
{
public PlotMarkBar() { }
}
[MessagePackObject]
public sealed class PlotMarkArea : PlotMark
{
public PlotMarkArea() { }
}
[Union(0, typeof(TextArg))]
[Union(1, typeof(NumberArg))]
[Union(2, typeof(BoolArg))]
[Union(3, typeof(ArgValueBind))]
[Union(4, typeof(CollectionArg))]
[Union(5, typeof(CommandArg))]
[Union(6, typeof(SlotArg))]
public abstract class ArgValue
{
internal ArgValue() { }
}
[MessagePackObject]
public sealed class TextArg : ArgValue
{
[Key(0)] public string Value { get; }
public TextArg(string value)
{
Value = ThingDomain.Present(value, "Value");
}
}
[MessagePackObject]
public sealed class NumberArg : ArgValue
{
[Key(0)] public double Value { get; }
public NumberArg(double value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class BoolArg : ArgValue
{
[Key(0)] public bool Value { get; }
public BoolArg(bool value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class ArgValueBind : ArgValue
{
[Key(0)] public StateSource Source { get; }
[Key(1)] public MemberPath Member { get; }
[Key(2)] public Format? Format { get; }
public ArgValueBind(StateSource source, MemberPath member, Format? format)
{
Source = ThingDomain.Present(source, "Source");
Member = ThingDomain.Present(member, "Member");
Format = format;
}
}
[MessagePackObject]
public sealed class CollectionArg : ArgValue
{
[Key(0)] public CollectionSource Source { get; }
public CollectionArg(CollectionSource source)
{
Source = ThingDomain.Present(source, "Source");
}
}
[MessagePackObject]
public sealed class CommandArg : ArgValue
{
[Key(0)] public CommandRef Command { get; }
public CommandArg(CommandRef command)
{
Command = ThingDomain.Present(command, "Command");
}
}
[MessagePackObject]
public sealed class SlotArg : ArgValue
{
[Key(0)] public IReadOnlyList<Node> Nodes { get; }
public SlotArg(IReadOnlyList<Node> nodes)
{
Nodes = ThingDomain.Items(nodes, "Nodes");
}
}
[Union(0, typeof(ParamKindText))]
[Union(1, typeof(ParamKindNumber))]
[Union(2, typeof(ParamKindBool))]
[Union(3, typeof(ParamKindBind))]
[Union(4, typeof(ParamKindCollection))]
[Union(5, typeof(ParamKindCommand))]
[Union(6, typeof(ParamKindSlot))]
public abstract class ParamKind
{
internal ParamKind() { }
}
[MessagePackObject]
public sealed class ParamKindText : ParamKind
{
public ParamKindText() { }
}
[MessagePackObject]
public sealed class ParamKindNumber : ParamKind
{
public ParamKindNumber() { }
}
[MessagePackObject]
public sealed class ParamKindBool : ParamKind
{
public ParamKindBool() { }
}
[MessagePackObject]
public sealed class ParamKindBind : ParamKind
{
public ParamKindBind() { }
}
[MessagePackObject]
public sealed class ParamKindCollection : ParamKind
{
public ParamKindCollection() { }
}
[MessagePackObject]
public sealed class ParamKindCommand : ParamKind
{
public ParamKindCommand() { }
}
[MessagePackObject]
public sealed class ParamKindSlot : ParamKind
{
public ParamKindSlot() { }
}
[MessagePackObject]
public sealed class NodeCommon
{
[Key(0)] public string Id { get; }
[Key(1)] public BoolSource Visible { get; }
[Key(2)] public TextSource? A11yLabel { get; }
public NodeCommon(string id, BoolSource visible, TextSource? a11yLabel)
{
Id = ThingDomain.Present(id, "Id");
Visible = ThingDomain.Present(visible, "Visible");
A11yLabel = a11yLabel;
}
}
[MessagePackObject]
public sealed class SelectOption
{
[Key(0)] public string Value { get; }
[Key(1)] public string Label { get; }
public SelectOption(string value, string label)
{
Value = ThingDomain.Present(value, "Value");
Label = ThingDomain.Present(label, "Label");
}
}
[MessagePackObject]
public sealed class CompositionRef
{
[Key(0)] public string Publisher { get; }
[Key(1)] public string Name { get; }
[Key(2)] public long Version { get; }
public CompositionRef(string publisher, string name, long version)
{
Publisher = ThingDomain.Present(publisher, "Publisher");
Name = ThingDomain.Segment(name);
Version = ThingDomain.Version(version);
}
}
[MessagePackObject]
public sealed class Arg
{
[Key(0)] public string Name { get; }
[Key(1)] public ArgValue Value { get; }
public Arg(string name, ArgValue value)
{
Name = ThingDomain.Present(name, "Name");
Value = ThingDomain.Present(value, "Value");
}
}
[MessagePackObject]
public sealed class ParamDecl
{
[Key(0)] public string Name { get; }
[Key(1)] public ParamKind Kind { get; }
public ParamDecl(string name, ParamKind kind)
{
Name = ThingDomain.Present(name, "Name");
Kind = ThingDomain.Present(kind, "Kind");
}
}
[CultDocument("gamecult.thing.surface", "gamecult.thing.surface.v1")]
[MessagePackObject]
public sealed class SurfaceDocument
{
[Key(0)] public string ProviderId { get; }
[Key(1)] public string Label { get; }
[Key(2)] public long Version { get; }
[Key(3)] public string Title { get; }
[Key(4)] public Node Root { get; }
[Key(5)] public IReadOnlyList<CommandDecl> Commands { get; }
public SurfaceDocument(string providerId, string label, long version, string title, Node root, IReadOnlyList<CommandDecl> commands)
{
ProviderId = ThingDomain.Present(providerId, "ProviderId");
Label = ThingDomain.Segment(label);
Version = ThingDomain.Version(version);
Title = ThingDomain.Present(title, "Title");
Root = ThingDomain.Present(root, "Root");
Commands = ThingDomain.Items(commands, "Commands");
}
[IgnoreMember] public string RecordKey => ThingKeys.SurfaceKey(ProviderId, Label);
}
[CultDocument("gamecult.thing.composition", "gamecult.thing.composition.v1")]
[MessagePackObject]
public sealed class CompositionDocument
{
[Key(0)] public string Publisher { get; }
[Key(1)] public string Name { get; }
[Key(2)] public long Version { get; }
[Key(3)] public IReadOnlyList<ParamDecl> Params { get; }
[Key(4)] public Node Body { get; }
public CompositionDocument(string publisher, string name, long version, IReadOnlyList<ParamDecl> @params, Node body)
{
Publisher = ThingDomain.Present(publisher, "Publisher");
Name = ThingDomain.Segment(name);
Version = ThingDomain.Version(version);
Params = ThingDomain.Items(@params, "Params");
Body = ThingDomain.Present(body, "Body");
}
[IgnoreMember] public string RecordKey => ThingKeys.CompositionKey(Publisher, Name, Version);
}