fix(ui): complete retail indicator detail panels

Port the authored effect row template, remaining-time and selection details, synchronize the full gmPanelUI child geometry, and route the burden indicator to Character Information panel 3.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-17 11:36:43 +02:00
parent a96767ba6d
commit d1d603105f
24 changed files with 3696 additions and 147 deletions

View file

@ -6,12 +6,37 @@ namespace AcDream.App.Tests.UI.Layout;
/// <summary>
/// Unit tests for <see cref="CharacterController"/> and <see cref="SampleData.SampleCharacter"/>.
/// The controller CREATES the m_pMainText report element (0x1000011d) at bind time — retail's
/// gm*UI builds it at runtime; it is not a static dat element — and attaches it to the layout root.
/// No dats, no GL — pure data-wiring + report-content tests.
/// Production Character Information data authors m_pMainText (0x1000011d);
/// reduced unit-test layouts exercise the controller's fallback element.
/// No GL — pure data-wiring + report-content tests.
/// </summary>
public class CharacterControllerTests
{
[Fact]
public void AuthoredCharacterInformationPanel_BindsTextScrollbarAndClose()
{
ImportedLayout layout = FixtureLoader.LoadCharacterInformation();
int closes = 0;
CharacterController.Bind(
layout, SampleData.SampleCharacter, close: () => closes++);
Assert.Equal(CharacterController.RootId, layout.Root.DatElementId);
Assert.Equal((300f, 362f), (layout.Root.Width, layout.Root.Height));
UiText text = Assert.IsType<UiText>(
layout.FindElement(CharacterController.MainTextId));
UiScrollbar scrollbar = Assert.IsType<UiScrollbar>(
layout.FindElement(CharacterController.ScrollbarId));
Assert.Same(text.Scroll, scrollbar.Model);
Assert.False(text.PreserveEndOnLayout);
Assert.Contains("Studio Player", text.LinesProvider().Select(line => line.Text));
UiButton close = Assert.IsType<UiButton>(
layout.FindElement(CharacterController.CloseId));
close.OnEvent(new UiEvent(0, close, UiEventType.Click));
Assert.Equal(1, closes);
}
/// <summary>Bind on an empty layout, then return the created m_pMainText element.</summary>
private static UiText BindAndGetText(System.Func<CharacterSheet> data)
{

View file

@ -7,6 +7,28 @@ namespace AcDream.App.Tests.UI.Layout;
public sealed class EffectsUiControllerTests
{
private static (uint, int, int) NoTex(uint _) => (0u, 0, 0);
private static EffectRowTemplateFactory Templates()
=> new(FixtureLoader.LoadEffectRowTemplateInfos(), NoTex, defaultFont: null);
[Fact]
public void AuthoredEffectRowTemplate_HasRetailIconNameDurationAndSelectionStates()
{
ElementInfo row = FixtureLoader.LoadEffectRowTemplateInfos();
Assert.Equal(EffectsUiController.RowTemplateId, row.Id);
Assert.Equal((300f, 32f), (row.Width, row.Height));
Assert.Contains(UiButtonStateMachine.Normal, row.States.Keys);
Assert.Contains(UiButtonStateMachine.Highlight, row.States.Keys);
Assert.Equal((0f, 32f),
(FindInfo(row, EffectsUiController.RowIconId)!.X,
FindInfo(row, EffectsUiController.RowIconId)!.Width));
Assert.Equal((37f, 188f),
(FindInfo(row, EffectsUiController.RowLabelId)!.X,
FindInfo(row, EffectsUiController.RowLabelId)!.Width));
Assert.Equal((225f, 50f),
(FindInfo(row, EffectsUiController.RowDurationId)!.X,
FindInfo(row, EffectsUiController.RowDurationId)!.Width));
}
[Fact]
public void Rebuild_DoesNotAutoSelectFirstEffect_AndClearsRemovedSelection()
@ -25,8 +47,10 @@ public sealed class EffectsUiControllerTests
[EffectsUiController.InfoTextId] = info,
});
using EffectsUiController controller = EffectsUiController.Bind(
layout, spellbook, positive: true, () => 0d, NoTex, id => id)!;
layout, spellbook, positive: true, () => 0d, NoTex, id => id,
Templates(), "SELECT A SPELL")!;
Assert.False(info.PreserveEndOnLayout);
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
42u, 1u, 60f, 1u, Bucket: 1u, SpellCategory: 42u));
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
@ -34,10 +58,15 @@ public sealed class EffectsUiControllerTests
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
42u, 3u, 60f, 1u, Bucket: 8u, SpellCategory: 42u));
Assert.Null(controller.SelectedSpellId);
Assert.Equal("SELECT A SPELL", Assert.Single(info.LinesProvider()).Text);
Assert.Equal(1, list.GetNumUIItems());
UiCatalogSlot row = Assert.IsType<UiCatalogSlot>(list.GetItem(0));
UiTemplateListSlot row = Assert.IsType<UiTemplateListSlot>(list.GetItem(0));
UiText duration = Assert.IsType<UiText>(
row.Content.FindElement(EffectsUiController.RowDurationId));
Assert.Equal("1:00", Assert.Single(duration.LinesProvider()).Text);
row.OnEvent(new UiEvent(0, row, UiEventType.Click));
Assert.Equal(42u, controller.SelectedSpellId);
Assert.Equal(["Boon", "", ""], info.LinesProvider().Select(line => line.Text));
spellbook.OnEnchantmentRemoved(1u, 42u);
Assert.Null(controller.SelectedSpellId);
@ -57,14 +86,15 @@ public sealed class EffectsUiControllerTests
[EffectsUiController.ListId] = list,
});
using EffectsUiController controller = EffectsUiController.Bind(
layout, spellbook, positive: true, () => 0d, NoTex, id => id)!;
layout, spellbook, positive: true, () => 0d, NoTex, id => id,
Templates(), "SELECT A SPELL")!;
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
42u, 1u, 60f, 1u, Bucket: 1u, SpellCategory: 100u));
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
42u, 2u, 60f, 2u, Bucket: 2u, SpellCategory: 101u));
UiCatalogSlot first = Assert.IsType<UiCatalogSlot>(list.GetItem(0));
UiCatalogSlot second = Assert.IsType<UiCatalogSlot>(list.GetItem(1));
UiTemplateListSlot first = Assert.IsType<UiTemplateListSlot>(list.GetItem(0));
UiTemplateListSlot second = Assert.IsType<UiTemplateListSlot>(list.GetItem(1));
first.OnEvent(new UiEvent(0, first, UiEventType.Click));
Assert.Equal(42u, controller.SelectedSpellId);
@ -77,6 +107,32 @@ public sealed class EffectsUiControllerTests
Assert.False(second.Selected);
}
[Fact]
public void PermanentEffect_LeavesRetailDurationColumnEmpty()
{
var table = SpellTable.LoadFromReader(new StringReader(
"Spell ID,Name,Flags [Hex]\n42,Boon,0x4\n"));
var spellbook = new Spellbook(table);
var root = new UiPanel { Width = 160f, Height = 100f };
var list = new UiItemList(NoTex) { Width = 160f, Height = 64f };
root.AddChild(list);
var layout = new ImportedLayout(root, new Dictionary<uint, UiElement>
{
[EffectsUiController.ListId] = list,
});
using EffectsUiController controller = EffectsUiController.Bind(
layout, spellbook, positive: true, () => 0d, NoTex, id => id,
Templates(), "SELECT A SPELL")!;
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
42u, 1u, -1f, 1u, Bucket: 1u, SpellCategory: 42u));
UiTemplateListSlot row = Assert.IsType<UiTemplateListSlot>(list.GetItem(0));
UiText duration = Assert.IsType<UiText>(
row.Content.FindElement(EffectsUiController.RowDurationId));
Assert.Equal(string.Empty, Assert.Single(duration.LinesProvider()).Text);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
@ -117,11 +173,13 @@ public sealed class EffectsUiControllerTests
int closes = 0;
using EffectsUiController? controller = EffectsUiController.Bind(
layout, spellbook, positive, () => 0d, NoTex, id => id, () => closes++);
layout, spellbook, positive, () => 0d, NoTex, id => id,
Templates(), "SELECT A SPELL", () => closes++);
Assert.NotNull(controller);
Assert.NotNull(layout.FindElement(EffectsUiController.ListId));
Assert.IsType<UiText>(layout.FindElement(EffectsUiController.InfoTextId));
Assert.IsType<UiScrollbar>(layout.FindElement(EffectsUiController.ScrollbarId));
Assert.Equal(expectedRoot, layout.Root.DatElementId);
UiButton close = Assert.IsType<UiButton>(layout.FindElement(EffectsUiController.CloseId));
close.OnEvent(new UiEvent(0, close, UiEventType.Click));

View file

@ -137,6 +137,16 @@ public static class FixtureLoader
public static ElementInfo LoadNegativeEffectsInfos()
=> LoadInfos("effects_negative_2100001B.json");
public static ElementInfo LoadEffectRowTemplateInfos()
=> LoadInfos("effects_row_2100001B_10000128.json");
public static ImportedLayout LoadCharacterInformation()
=> LayoutImporter.Build(
LoadCharacterInformationInfos(), _ => (0u, 0, 0), null);
public static ElementInfo LoadCharacterInformationInfos()
=> LoadInfos("character_info_2100006E_10000183.json");
public static ImportedLayout LoadIndicators()
=> LayoutImporter.Build(LoadIndicatorsInfos(), _ => (0u, 0, 0), null);

View file

@ -98,7 +98,7 @@ public sealed class IndicatorBarControllerTests
burden.OnEvent(new UiEvent(0, burden, UiEventType.Click));
Assert.Equal([RetailPanelCatalog.Character], h.ToggledPanels);
Assert.Equal([RetailPanelCatalog.CharacterInformation], h.ToggledPanels);
}
[Theory]

View file

@ -64,6 +64,11 @@ public sealed class RetailLayoutFixtureGenerator
Assert.Equal(expected, localStrings.Resolve(
0x23000001u, DatStringResolver.ComputeHash(key)));
}
Assert.Equal(
"SELECT A SPELL",
localStrings.Resolve(
0x23000001u,
DatStringResolver.ComputeHash("ID_Effects_Info_SelectASpell")));
uint masterDid = (uint)dats.Portal.Header.MasterMapId;
Assert.True(dats.Portal.TryGet<EnumIDMap>(masterDid, out var master));
@ -120,6 +125,25 @@ public sealed class RetailLayoutFixtureGenerator
File.WriteAllText(Path.Combine(FixtureDirectory(), fileName), effectsJson);
}
foreach ((uint layoutId, uint rootId, string fileName) in new[]
{
(EffectsUiController.LayoutId, EffectsUiController.RowTemplateId,
"effects_row_2100001B_10000128.json"),
(CharacterController.LayoutId, CharacterController.RootId,
"character_info_2100006E_10000183.json"),
})
{
ElementInfo? panelPart = LayoutImporter.ImportInfos(dats, layoutId, rootId);
Assert.NotNull(panelPart);
File.WriteAllText(
Path.Combine(FixtureDirectory(), fileName),
JsonSerializer.Serialize(panelPart, new JsonSerializerOptions
{
IncludeFields = true,
WriteIndented = true,
}));
}
ElementInfo? miniGame = LayoutImporter.ImportInfos(
dats, MiniGameUiController.LayoutId, MiniGameUiController.RootId);
Assert.NotNull(miniGame);

View file

@ -79,9 +79,9 @@ public sealed class RetailPanelUiControllerTests
public void MainPanels_ShareOneCanonicalPlacementAcrossMoveCloseAndSwitch()
{
var root = new UiRoot { Width = 1280f, Height = 720f };
RetailWindowHandle inventory = Mount(root, WindowNames.Inventory, 40f, 60f);
RetailWindowHandle character = Mount(root, WindowNames.Character, 540f, 18f);
RetailWindowHandle spellbook = Mount(root, WindowNames.Spellbook, 18f, 18f);
RetailWindowHandle inventory = Mount(root, WindowNames.Inventory, 40f, 60f, 360f);
RetailWindowHandle character = Mount(root, WindowNames.Character, 540f, 18f, 500f);
RetailWindowHandle spellbook = Mount(root, WindowNames.Spellbook, 18f, 18f, 420f);
using var controller = Create(root);
controller.RegisterMainPanel(7u, WindowNames.Inventory, inventory);
controller.RegisterMainPanel(11u, WindowNames.Character, character);
@ -94,9 +94,12 @@ public sealed class RetailPanelUiControllerTests
controller.SetPanelVisibility(7u, visible: true);
inventory.MoveTo(312f, 147f);
inventory.ResizeTo(310f, 540f);
Assert.Equal((312f, 147f), (character.Left, character.Top));
Assert.Equal((312f, 147f), (spellbook.Left, spellbook.Top));
Assert.Equal((310f, 540f), (character.Width, character.Height));
Assert.Equal((310f, 540f), (spellbook.Width, spellbook.Height));
Assert.True(characterMoves > 0);
Assert.True(spellbookMoves > 0);
@ -104,12 +107,14 @@ public sealed class RetailPanelUiControllerTests
Assert.False(inventory.IsVisible);
Assert.True(character.IsVisible);
Assert.Equal((312f, 147f), (character.Left, character.Top));
Assert.Equal((310f, 540f), (character.Width, character.Height));
controller.SetPanelVisibility(11u, visible: false);
controller.SetPanelVisibility(13u, visible: true);
Assert.False(character.IsVisible);
Assert.True(spellbook.IsVisible);
Assert.Equal((312f, 147f), (spellbook.Left, spellbook.Top));
Assert.Equal((310f, 540f), (spellbook.Width, spellbook.Height));
}
[Fact]
@ -130,15 +135,18 @@ public sealed class RetailPanelUiControllerTests
controller.SetPanelVisibility(7u, visible: true);
inventory.MoveTo(280f, 120f);
inventory.ResizeTo(310f, 600f);
controller.SetPanelVisibility(4u, visible: true);
Assert.Equal((280f, 120f), (effect.Left, effect.Top));
Assert.Equal((310f, 600f), (effect.Width, effect.Height));
Assert.False(inventory.IsVisible);
Assert.True(effect.IsVisible);
controller.SetPanelVisibility(4u, visible: false);
Assert.True(inventory.IsVisible);
Assert.Equal((280f, 120f), (inventory.Left, inventory.Top));
Assert.Equal((310f, 600f), (inventory.Width, inventory.Height));
controller.SetPanelVisibility(11u, visible: true);
Assert.Equal((280f, 120f), (character.Left, character.Top));
@ -165,9 +173,10 @@ public sealed class RetailPanelUiControllerTests
UiRoot root,
string name,
float left,
float top)
float top,
float contentHeight = 500f)
{
var content = new UiPanel { Width = 300f, Height = 500f };
var content = new UiPanel { Width = 300f, Height = contentHeight };
return RetailWindowFrame.Mount(
root,
content,

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,961 @@
{
"Id": 268435752,
"Type": 3,
"X": 0,
"Y": 0,
"Width": 300,
"Height": 32,
"OriginalParentWidth": 0,
"OriginalParentHeight": 0,
"HasOriginalParentSize": false,
"Left": 1,
"Top": 1,
"Right": 1,
"Bottom": 2,
"ReadOrder": 3,
"ZLevel": 0,
"States": {
"4294967295": {
"Id": 4294967295,
"Name": "",
"PassToChildren": false,
"IncorporationFlags": 30,
"Image": null,
"Cursor": null,
"Properties": {
"Values": {}
}
},
"1": {
"Id": 1,
"Name": "Normal",
"PassToChildren": false,
"IncorporationFlags": 0,
"Image": {
"File": 100668310,
"DrawMode": 1
},
"Cursor": null,
"Properties": {
"Values": {}
}
},
"6": {
"Id": 6,
"Name": "Highlight",
"PassToChildren": false,
"IncorporationFlags": 0,
"Image": {
"File": 100668311,
"DrawMode": 1
},
"Cursor": null,
"Properties": {
"Values": {}
}
}
},
"DefaultStateId": 1,
"FontDid": 0,
"HJustify": 1,
"VJustify": 1,
"FontColor": null,
"StateMedia": {
"Normal": {
"Item1": 100668310,
"Item2": 1
},
"Highlight": {
"Item1": 100668311,
"Item2": 1
}
},
"StateCursors": {},
"DefaultStateName": "Normal",
"Children": [
{
"Id": 268435753,
"Type": 3,
"X": 0,
"Y": 0,
"Width": 32,
"Height": 32,
"OriginalParentWidth": 300,
"OriginalParentHeight": 32,
"HasOriginalParentSize": true,
"Left": 1,
"Top": 1,
"Right": 2,
"Bottom": 2,
"ReadOrder": 1,
"ZLevel": 0,
"States": {
"4294967295": {
"Id": 4294967295,
"Name": "",
"PassToChildren": false,
"IncorporationFlags": 30,
"Image": null,
"Cursor": null,
"Properties": {
"Values": {}
}
}
},
"DefaultStateId": 0,
"FontDid": 0,
"HJustify": 1,
"VJustify": 1,
"FontColor": null,
"StateMedia": {},
"StateCursors": {},
"DefaultStateName": "",
"Children": []
},
{
"Id": 268435754,
"Type": 12,
"X": 37,
"Y": 0,
"Width": 188,
"Height": 32,
"OriginalParentWidth": 300,
"OriginalParentHeight": 32,
"HasOriginalParentSize": true,
"Left": 1,
"Top": 1,
"Right": 1,
"Bottom": 1,
"ReadOrder": 2,
"ZLevel": 0,
"States": {
"4294967295": {
"Id": 4294967295,
"Name": "",
"PassToChildren": false,
"IncorporationFlags": 30,
"Image": null,
"Cursor": null,
"Properties": {
"Values": {
"35": {
"Kind": 4,
"MasterPropertyId": 35,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
},
"26": {
"Kind": 7,
"MasterPropertyId": 26,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [
{
"Kind": 2,
"MasterPropertyId": 24,
"UnsignedValue": 1073741825,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
}
],
"StructValue": {}
},
"37": {
"Kind": 4,
"MasterPropertyId": 37,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
},
"27": {
"Kind": 7,
"MasterPropertyId": 27,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [
{
"Kind": 6,
"MasterPropertyId": 25,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 255,
"Green": 255,
"Red": 255,
"Alpha": 255
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
}
],
"StructValue": {}
},
"20": {
"Kind": 0,
"MasterPropertyId": 20,
"UnsignedValue": 2,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
},
"21": {
"Kind": 0,
"MasterPropertyId": 21,
"UnsignedValue": 1,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
},
"199": {
"Kind": 5,
"MasterPropertyId": 199,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 58579907,
"TableId": 587202561,
"Override": 0,
"English": 1,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
},
"71": {
"Kind": 0,
"MasterPropertyId": 71,
"UnsignedValue": 268436373,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
},
"72": {
"Kind": 2,
"MasterPropertyId": 72,
"UnsignedValue": 553648193,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
},
"32": {
"Kind": 1,
"MasterPropertyId": 32,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": true,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
},
"208": {
"Kind": 1,
"MasterPropertyId": 208,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": true,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
}
}
}
},
"13": {
"Id": 13,
"Name": "Ghosted",
"PassToChildren": false,
"IncorporationFlags": 0,
"Image": null,
"Cursor": null,
"Properties": {
"Values": {
"27": {
"Kind": 7,
"MasterPropertyId": 27,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [
{
"Kind": 6,
"MasterPropertyId": 25,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 76,
"Green": 76,
"Red": 76,
"Alpha": 255
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
}
],
"StructValue": {}
}
}
}
}
},
"DefaultStateId": 0,
"FontDid": 1073741825,
"HJustify": 0,
"VJustify": 1,
"FontColor": {
"X": 1,
"Y": 1,
"Z": 1,
"W": 1
},
"StateMedia": {},
"StateCursors": {},
"DefaultStateName": "",
"Children": []
},
{
"Id": 268435755,
"Type": 12,
"X": 225,
"Y": 0,
"Width": 50,
"Height": 32,
"OriginalParentWidth": 300,
"OriginalParentHeight": 32,
"HasOriginalParentSize": true,
"Left": 1,
"Top": 1,
"Right": 1,
"Bottom": 1,
"ReadOrder": 3,
"ZLevel": 0,
"States": {
"4294967295": {
"Id": 4294967295,
"Name": "",
"PassToChildren": false,
"IncorporationFlags": 30,
"Image": null,
"Cursor": null,
"Properties": {
"Values": {
"35": {
"Kind": 4,
"MasterPropertyId": 35,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
},
"26": {
"Kind": 7,
"MasterPropertyId": 26,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [
{
"Kind": 2,
"MasterPropertyId": 24,
"UnsignedValue": 1073741825,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
}
],
"StructValue": {}
},
"37": {
"Kind": 4,
"MasterPropertyId": 37,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
},
"27": {
"Kind": 7,
"MasterPropertyId": 27,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [
{
"Kind": 6,
"MasterPropertyId": 25,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 255,
"Green": 255,
"Red": 255,
"Alpha": 255
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
}
],
"StructValue": {}
},
"20": {
"Kind": 0,
"MasterPropertyId": 20,
"UnsignedValue": 3,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
},
"21": {
"Kind": 0,
"MasterPropertyId": 21,
"UnsignedValue": 1,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
}
}
}
},
"13": {
"Id": 13,
"Name": "Ghosted",
"PassToChildren": false,
"IncorporationFlags": 0,
"Image": null,
"Cursor": null,
"Properties": {
"Values": {
"27": {
"Kind": 7,
"MasterPropertyId": 27,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 0,
"Green": 0,
"Red": 0,
"Alpha": 0
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [
{
"Kind": 6,
"MasterPropertyId": 25,
"UnsignedValue": 0,
"IntegerValue": 0,
"FloatValue": 0,
"BoolValue": false,
"StringInfoValue": {
"Token": 0,
"StringId": 0,
"TableId": 0,
"Override": 0,
"English": 0,
"Comment": 0
},
"ColorValue": {
"Blue": 76,
"Green": 76,
"Red": 76,
"Alpha": 255
},
"VectorValue": {
"X": 0,
"Y": 0,
"Z": 0
},
"ArrayValue": [],
"StructValue": {}
}
],
"StructValue": {}
}
}
}
}
},
"DefaultStateId": 0,
"FontDid": 1073741825,
"HJustify": 2,
"VJustify": 1,
"FontColor": {
"X": 1,
"Y": 1,
"Z": 1,
"W": 1
},
"StateMedia": {},
"StateCursors": {},
"DefaultStateName": "",
"Children": []
}
]
}