feat(render): implement Campaign AR and terrain fidelity
This commit is contained in:
parent
99cf26e00c
commit
7a5f96ede5
368 changed files with 50611 additions and 950 deletions
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Numerics;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
using AcDream.Plugin.Abstractions.Rendering;
|
||||
using AcDream.UI.Abstractions.Panels.Settings;
|
||||
|
||||
namespace AcDream.App.Tests.UI.Layout;
|
||||
|
|
@ -285,7 +286,8 @@ public sealed class ConfigOptionsPageControllerTests
|
|||
public List<CameraTurningSettings> CameraTurningSaves { get; } = new();
|
||||
public List<ChatSettings> ChatSaves { get; } = new();
|
||||
|
||||
public ConfigOptionsPageController.Bindings ToBindings() => new(
|
||||
public ConfigOptionsPageController.Bindings ToBindings(
|
||||
ConfigOptionsPageController.RenderPackBindings? renderPacks = null) => new(
|
||||
LoadDisplay: () => Display,
|
||||
SaveDisplay: value => { Display = value; DisplaySaves.Add(value); },
|
||||
LoadAudio: () => Audio,
|
||||
|
|
@ -293,7 +295,10 @@ public sealed class ConfigOptionsPageControllerTests
|
|||
LoadCameraTurning: () => CameraTurning,
|
||||
SaveCameraTurning: value => { CameraTurning = value; CameraTurningSaves.Add(value); },
|
||||
LoadChat: () => Chat,
|
||||
SaveChat: value => { Chat = value; ChatSaves.Add(value); });
|
||||
SaveChat: value => { Chat = value; ChatSaves.Add(value); })
|
||||
{
|
||||
RenderPacks = renderPacks,
|
||||
};
|
||||
}
|
||||
|
||||
private static (OptionsPanelController Panel, FakeBindings Bindings, bool Bound) BindReal(
|
||||
|
|
@ -430,6 +435,377 @@ public sealed class ConfigOptionsPageControllerTests
|
|||
Assert.Equal(39, viewport.Children.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OptInRenderPackBindings_append_two_menus_without_changing_retail_only_fixture()
|
||||
{
|
||||
ImportedLayout layout = FixtureLoader.LoadOptionsPanelHost();
|
||||
OptionsPanelController controller = OptionsPanelController.Bind(
|
||||
layout,
|
||||
new OptionsPanelController.Callbacks(
|
||||
Toggle: () => { },
|
||||
RequestExitToCharacterSelection: () => { },
|
||||
ExitGame: () => { },
|
||||
UseMouseTurningSettings: () => { },
|
||||
DisplaySystemMessage: _ => { }))!;
|
||||
var fake = new FakeBindings();
|
||||
string? activationFailure = "Last activation failed: shader interface mismatch.";
|
||||
var renderPacks = new ConfigOptionsPageController.RenderPackBindings(() =>
|
||||
[
|
||||
new ConfigOptionsPageController.RenderPackChoice(
|
||||
"acdream.atmospheric",
|
||||
"Atmospheric Rendering",
|
||||
"1.0.0",
|
||||
true,
|
||||
null,
|
||||
[
|
||||
new ConfigOptionsPageController.RenderPackPresetChoice(
|
||||
"low", "Low", true, null)
|
||||
{
|
||||
MaxResidentGpuBytes = 64L * 1024 * 1024,
|
||||
MaxIncrementalGpuMillisecondsP50 = 2.0,
|
||||
MaxIncrementalGpuMillisecondsP99 = 3.0,
|
||||
MaxIncrementalCpuMillisecondsP50 = 0.15,
|
||||
MaxIncrementalCpuMillisecondsP99 = 0.50,
|
||||
},
|
||||
new("medium", "Medium", true, null),
|
||||
new("high", "High", false, "High needs more GPU memory."),
|
||||
])
|
||||
{
|
||||
FeatureSummary = "Filmic atmosphere and moving-sun shadows.",
|
||||
},
|
||||
new ConfigOptionsPageController.RenderPackChoice(
|
||||
"test.unsupported",
|
||||
"Unsupported Test Pack",
|
||||
"2.0.0",
|
||||
false,
|
||||
"Directional depth sampling is unavailable.",
|
||||
[new("low", "Low", false, "Directional depth sampling is unavailable.")]),
|
||||
])
|
||||
{
|
||||
LoadFailureNotice = () => activationFailure,
|
||||
};
|
||||
|
||||
bool bound = ConfigOptionsPageController.Bind(
|
||||
layout,
|
||||
controller.ConfigPage,
|
||||
MakeTemplateResolver(),
|
||||
(_, _) => null,
|
||||
fake.ToBindings(renderPacks));
|
||||
|
||||
Assert.True(bound);
|
||||
var configSlot = UiElement.FindDescendant(controller.TabPanel, ConfigPageSlotId)!;
|
||||
var listBox = Assert.IsType<UiTemplateListBox>(
|
||||
UiElement.FindDescendant(configSlot, ConfigOptionsPageController.ListBoxElementId));
|
||||
Assert.Equal(43, Assert.Single(listBox.Children).Children.Count);
|
||||
Assert.Equal(32, controller.ConfigPage.Rows.Count);
|
||||
|
||||
List<UiMenu> menus = CollectMenus(configSlot);
|
||||
UiMenu packMenu = menus[^2];
|
||||
UiMenu presetMenu = menus[^1];
|
||||
Assert.Equal("acdream default (retail-faithful)", packMenu.Items[0].Label);
|
||||
Assert.Contains(packMenu.Items, value => Equals(value.Payload, "acdream.atmospheric"));
|
||||
Assert.False(packMenu.EnabledProvider!("test.unsupported"));
|
||||
Assert.Equal(
|
||||
"Last activation failed: shader interface mismatch.",
|
||||
packMenu.GetTooltipText()!.Split(Environment.NewLine)[0]);
|
||||
packMenu.OnSelect!("test.unsupported");
|
||||
Assert.True(fake.Display.RenderPack.IsRetail);
|
||||
|
||||
packMenu.OnSelect!("acdream.atmospheric");
|
||||
Assert.Equal("acdream.atmospheric", fake.Display.RenderPack.PackId);
|
||||
Assert.Equal("1.0.0", fake.Display.RenderPack.PackVersion);
|
||||
Assert.Equal("low", fake.Display.RenderPack.PresetId);
|
||||
activationFailure = null;
|
||||
Assert.Equal(
|
||||
"Filmic atmosphere and moving-sun shadows.",
|
||||
packMenu.GetTooltipText());
|
||||
presetMenu = CollectMenus(configSlot)[^1];
|
||||
Assert.Equal(3, presetMenu.Items.Count);
|
||||
Assert.False(presetMenu.EnabledProvider!("high"));
|
||||
Assert.Contains(
|
||||
"GPU p50/p99 ≤ 2/3 ms",
|
||||
presetMenu.GetTooltipText(),
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains("pack VRAM ≤ 64 MiB", presetMenu.GetTooltipText(), StringComparison.Ordinal);
|
||||
|
||||
presetMenu.OnSelect!("medium");
|
||||
Assert.Equal("medium", fake.Display.RenderPack.PresetId);
|
||||
Assert.True(fake.DisplaySaves.Count >= 2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderPackMenu_revision_refresh_removes_withdrawn_schema_and_discovers_reregistration()
|
||||
{
|
||||
ImportedLayout layout = FixtureLoader.LoadOptionsPanelHost();
|
||||
OptionsPanelController controller = OptionsPanelController.Bind(
|
||||
layout,
|
||||
new OptionsPanelController.Callbacks(
|
||||
Toggle: () => { },
|
||||
RequestExitToCharacterSelection: () => { },
|
||||
ExitGame: () => { },
|
||||
UseMouseTurningSettings: () => { },
|
||||
DisplaySystemMessage: _ => { }))!;
|
||||
var alpha = new ConfigOptionsPageController.RenderPackChoice(
|
||||
"pack.alpha", "Alpha", "1.0.0", true, null,
|
||||
[new("low", "Low", true, null)])
|
||||
{
|
||||
Settings =
|
||||
[
|
||||
new RenderSettingDeclaration(
|
||||
"alpha-toggle", "Alpha toggle", RenderSettingKind.Boolean,
|
||||
"true", null, null, null, []),
|
||||
],
|
||||
};
|
||||
var beta = new ConfigOptionsPageController.RenderPackChoice(
|
||||
"pack.beta", "Beta", "2.0.0", true, null,
|
||||
[new("medium", "Medium", true, null)]);
|
||||
IReadOnlyList<ConfigOptionsPageController.RenderPackChoice> discovered = [alpha];
|
||||
long revision = 1;
|
||||
var fake = new FakeBindings
|
||||
{
|
||||
Display = DisplaySettings.Default with
|
||||
{
|
||||
RenderPack = new RenderPackSelectionSettings(
|
||||
"pack.alpha", "1.0.0", "low"),
|
||||
},
|
||||
};
|
||||
var renderPacks = new ConfigOptionsPageController.RenderPackBindings(
|
||||
() => discovered)
|
||||
{
|
||||
LoadRevision = () => revision,
|
||||
};
|
||||
|
||||
Assert.True(ConfigOptionsPageController.Bind(
|
||||
layout,
|
||||
controller.ConfigPage,
|
||||
MakeTemplateResolver(),
|
||||
(_, _) => null,
|
||||
fake.ToBindings(renderPacks)));
|
||||
|
||||
var configSlot = UiElement.FindDescendant(controller.TabPanel, ConfigPageSlotId)!;
|
||||
var listBox = Assert.IsType<UiTemplateListBox>(
|
||||
UiElement.FindDescendant(configSlot, ConfigOptionsPageController.ListBoxElementId));
|
||||
UiMenu packMenu = CollectMenus(configSlot)[^2];
|
||||
Assert.Equal(44, listBox.ItemCount);
|
||||
Assert.Contains(packMenu.Items, item => Equals(item.Payload, "pack.alpha"));
|
||||
|
||||
discovered = [beta];
|
||||
revision++;
|
||||
packMenu.BeforeOpen!();
|
||||
|
||||
Assert.DoesNotContain(packMenu.Items, item => Equals(item.Payload, "pack.alpha"));
|
||||
Assert.Contains(packMenu.Items, item => Equals(item.Payload, "pack.beta"));
|
||||
Assert.Equal(RenderPackSelectionSettings.RetailPackId, packMenu.Selected);
|
||||
Assert.Equal(43, listBox.ItemCount);
|
||||
Assert.Equal(32, controller.ConfigPage.Rows.Count);
|
||||
controller.ConfigPage.Reset();
|
||||
Assert.Equal(RenderPackSelectionSettings.RetailPackId, packMenu.Selected);
|
||||
Assert.DoesNotContain(packMenu.Items, item => Equals(item.Payload, "pack.alpha"));
|
||||
|
||||
fake.Display = fake.Display with
|
||||
{
|
||||
RenderPack = new RenderPackSelectionSettings(
|
||||
"pack.beta", "2.0.0", "medium"),
|
||||
};
|
||||
revision++;
|
||||
packMenu.BeforeOpen!();
|
||||
|
||||
Assert.Equal("pack.beta", packMenu.Selected);
|
||||
Assert.Equal(43, listBox.ItemCount);
|
||||
Assert.Equal("Medium", CollectMenus(configSlot)[^1].Items.Single().Label);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderPackSettings_live_schema_swap_replaces_only_the_optional_tail()
|
||||
{
|
||||
ImportedLayout layout = FixtureLoader.LoadOptionsPanelHost();
|
||||
OptionsPanelController controller = OptionsPanelController.Bind(
|
||||
layout,
|
||||
new OptionsPanelController.Callbacks(
|
||||
Toggle: () => { },
|
||||
RequestExitToCharacterSelection: () => { },
|
||||
ExitGame: () => { },
|
||||
UseMouseTurningSettings: () => { },
|
||||
DisplaySystemMessage: _ => { }))!;
|
||||
var fake = new FakeBindings
|
||||
{
|
||||
Display = DisplaySettings.Default with
|
||||
{
|
||||
RenderPack = new RenderPackSelectionSettings("pack.alpha", "1.0.0", "low"),
|
||||
},
|
||||
};
|
||||
RenderSettingDeclaration[] alphaSettings =
|
||||
[
|
||||
new("enabled", "Enabled", RenderSettingKind.Boolean, "false", null, null, null, []),
|
||||
new("strength", "Strength", RenderSettingKind.Float, "0.5", 0, 1, 0.25, []),
|
||||
new("samples", "Samples", RenderSettingKind.Integer, "2", 0, 10, 2, []),
|
||||
new("mode", "Mode", RenderSettingKind.Choice, "low", null, null, null,
|
||||
["low", "high"]),
|
||||
];
|
||||
var alpha = new ConfigOptionsPageController.RenderPackChoice(
|
||||
"pack.alpha", "Alpha", "1.0.0", true, null,
|
||||
[
|
||||
new ConfigOptionsPageController.RenderPackPresetChoice(
|
||||
"low", "Low", true, null)
|
||||
{
|
||||
SettingOverrides =
|
||||
[
|
||||
new RenderQualitySettingOverride("strength", "0.75"),
|
||||
],
|
||||
},
|
||||
new ConfigOptionsPageController.RenderPackPresetChoice(
|
||||
"high", "High", true, null),
|
||||
])
|
||||
{
|
||||
Settings = alphaSettings,
|
||||
};
|
||||
var beta = new ConfigOptionsPageController.RenderPackChoice(
|
||||
"pack.beta", "Beta", "2.0.0", true, null,
|
||||
[new("default", "Default", true, null)])
|
||||
{
|
||||
Settings =
|
||||
[
|
||||
new RenderSettingDeclaration(
|
||||
"beta-enabled", "Beta enabled", RenderSettingKind.Boolean,
|
||||
"true", null, null, null, []),
|
||||
],
|
||||
};
|
||||
var renderPacks = new ConfigOptionsPageController.RenderPackBindings(() =>
|
||||
[alpha, beta]);
|
||||
|
||||
Assert.True(ConfigOptionsPageController.Bind(
|
||||
layout,
|
||||
controller.ConfigPage,
|
||||
MakeTemplateResolver(),
|
||||
(_, _) => null,
|
||||
fake.ToBindings(renderPacks)));
|
||||
|
||||
var configSlot = UiElement.FindDescendant(controller.TabPanel, ConfigPageSlotId)!;
|
||||
var listBox = Assert.IsType<UiTemplateListBox>(
|
||||
UiElement.FindDescendant(configSlot, ConfigOptionsPageController.ListBoxElementId));
|
||||
Assert.Equal(47, listBox.ItemCount); // exact retail 39 + 8-row optional tail
|
||||
Assert.Equal(36, controller.ConfigPage.Rows.Count); // retail 30 + pack/preset + 4 settings
|
||||
|
||||
IReadOnlyList<UiElement> items = listBox.ViewportForTest!.Children;
|
||||
var enabled = Assert.IsType<UiButton>(
|
||||
UiElement.FindDescendant(items[42], 0x10000219u));
|
||||
var strength = Assert.IsType<UiScrollbar>(
|
||||
UiElement.FindDescendant(items[43], 0x1000021Cu));
|
||||
var samples = Assert.IsType<UiScrollbar>(
|
||||
UiElement.FindDescendant(items[44], 0x1000021Cu));
|
||||
List<UiMenu> menus = CollectMenus(configSlot);
|
||||
UiMenu packMenu = menus[^3];
|
||||
UiMenu presetMenu = menus[^2];
|
||||
UiMenu oldModeMenu = menus[^1];
|
||||
Assert.Equal(0.75f, strength.ScalarPosition, 3); // preset wins declaration default
|
||||
Assert.Equal(["low", "high"], oldModeMenu.Items.Select(value => value.Label));
|
||||
|
||||
enabled.Selected = true;
|
||||
enabled.OnClick!();
|
||||
strength.ScalarChanged!(0.62f); // 0.62 snaps to 0.5 on the declared 0.25 step
|
||||
samples.ScalarChanged!(0.33f); // 3.3 snaps to integer step 4
|
||||
oldModeMenu.OnSelect!("high");
|
||||
|
||||
Assert.Equal("true", fake.Display.RenderPack.SettingOverrides["enabled"]);
|
||||
Assert.Equal("0.5", fake.Display.RenderPack.SettingOverrides["strength"]);
|
||||
Assert.Equal("4", fake.Display.RenderPack.SettingOverrides["samples"]);
|
||||
Assert.Equal("high", fake.Display.RenderPack.SettingOverrides["mode"]);
|
||||
|
||||
presetMenu.OnSelect!("high");
|
||||
Assert.Equal("high", fake.Display.RenderPack.PresetId);
|
||||
Assert.Equal(4, fake.Display.RenderPack.SettingOverrides.Count);
|
||||
Assert.Equal(47, listBox.ItemCount);
|
||||
Assert.Equal(36, controller.ConfigPage.Rows.Count);
|
||||
int savesBeforeStaleWidget = fake.DisplaySaves.Count;
|
||||
oldModeMenu.OnSelect!("low");
|
||||
Assert.Equal(savesBeforeStaleWidget, fake.DisplaySaves.Count);
|
||||
|
||||
packMenu.OnSelect!("pack.beta");
|
||||
Assert.Equal("pack.beta", fake.Display.RenderPack.PackId);
|
||||
Assert.Equal("2.0.0", fake.Display.RenderPack.PackVersion);
|
||||
Assert.Equal("default", fake.Display.RenderPack.PresetId);
|
||||
Assert.Empty(fake.Display.RenderPack.SettingOverrides);
|
||||
Assert.Equal(44, listBox.ItemCount); // header + pack + preset + one setting + separator
|
||||
Assert.Equal(33, controller.ConfigPage.Rows.Count);
|
||||
|
||||
oldModeMenu.OnSelect!("high");
|
||||
Assert.Empty(fake.Display.RenderPack.SettingOverrides);
|
||||
|
||||
controller.ConfigPage.Reset();
|
||||
Assert.Equal("pack.alpha", fake.Display.RenderPack.PackId);
|
||||
Assert.Equal(47, listBox.ItemCount);
|
||||
Assert.Equal(36, controller.ConfigPage.Rows.Count);
|
||||
|
||||
controller.ConfigPage.Defaults();
|
||||
Assert.True(fake.Display.RenderPack.IsRetail);
|
||||
Assert.Equal(43, listBox.ItemCount); // header + pack + retail preset + separator
|
||||
Assert.Equal(32, controller.ConfigPage.Rows.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderPackSettingEdit_sanitizes_unknown_and_invalid_persisted_values()
|
||||
{
|
||||
ImportedLayout layout = FixtureLoader.LoadOptionsPanelHost();
|
||||
OptionsPanelController controller = OptionsPanelController.Bind(
|
||||
layout,
|
||||
new OptionsPanelController.Callbacks(
|
||||
Toggle: () => { },
|
||||
RequestExitToCharacterSelection: () => { },
|
||||
ExitGame: () => { },
|
||||
UseMouseTurningSettings: () => { },
|
||||
DisplaySystemMessage: _ => { }))!;
|
||||
var fake = new FakeBindings
|
||||
{
|
||||
Display = DisplaySettings.Default with
|
||||
{
|
||||
RenderPack = new RenderPackSelectionSettings("pack.alpha", "1.0.0", "low")
|
||||
{
|
||||
SettingOverrides = new RenderPackSettingOverrides(
|
||||
new Dictionary<string, string>
|
||||
{
|
||||
["removed"] = "1",
|
||||
["strength"] = "0.6", // not aligned to 0.25
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
var pack = new ConfigOptionsPageController.RenderPackChoice(
|
||||
"pack.alpha", "Alpha", "1.0.0", true, null,
|
||||
[new("low", "Low", true, null)])
|
||||
{
|
||||
Settings =
|
||||
[
|
||||
new RenderSettingDeclaration(
|
||||
"enabled", "Enabled", RenderSettingKind.Boolean,
|
||||
"false", null, null, null, []),
|
||||
new RenderSettingDeclaration(
|
||||
"strength", "Strength", RenderSettingKind.Float,
|
||||
"0.5", 0, 1, 0.25, []),
|
||||
],
|
||||
};
|
||||
|
||||
Assert.True(ConfigOptionsPageController.Bind(
|
||||
layout,
|
||||
controller.ConfigPage,
|
||||
MakeTemplateResolver(),
|
||||
(_, _) => null,
|
||||
fake.ToBindings(new ConfigOptionsPageController.RenderPackBindings(() => [pack]))));
|
||||
|
||||
var configSlot = UiElement.FindDescendant(controller.TabPanel, ConfigPageSlotId)!;
|
||||
var listBox = Assert.IsType<UiTemplateListBox>(
|
||||
UiElement.FindDescendant(configSlot, ConfigOptionsPageController.ListBoxElementId));
|
||||
UiElement enabledRow = listBox.ViewportForTest!.Children[42];
|
||||
var enabled = Assert.IsType<UiButton>(
|
||||
UiElement.FindDescendant(enabledRow, 0x10000219u));
|
||||
enabled.Selected = true;
|
||||
enabled.OnClick!();
|
||||
|
||||
Assert.Single(fake.Display.RenderPack.SettingOverrides);
|
||||
Assert.Equal("true", fake.Display.RenderPack.SettingOverrides["enabled"]);
|
||||
Assert.False(fake.Display.RenderPack.SettingOverrides.ContainsKey("removed"));
|
||||
Assert.False(fake.Display.RenderPack.SettingOverrides.ContainsKey("strength"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToggleRow_SfxEnabled_WritesThroughAudioBindings()
|
||||
{
|
||||
|
|
@ -1043,7 +1419,7 @@ public sealed class ConfigOptionsPageControllerTests
|
|||
(24, RowKind.Menu, true, "Environment Texture Detail"), // AP-198
|
||||
(25, RowKind.Menu, true, "Texture Filtering"), // AP-198
|
||||
(26, RowKind.Menu, true, "Landscape Draw Distance"), // AP-198
|
||||
(27, RowKind.Toggle, true, "Building Detail Textures"), // AP-198
|
||||
(27, RowKind.Toggle, false, "Building Detail Textures"), // LIVE — #226
|
||||
(28, RowKind.Toggle, true, "Multi-Pass Alpha"), // AP-198
|
||||
(31, RowKind.Slider, true, "Mouse Look Sensitivity"), // TS-74
|
||||
(32, RowKind.Toggle, true, "Invert Mouselook Y Axis"), // TS-74
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue