use crate::authoring::registry::build_only::{MainMenu, SettingsProfile};
const SETTINGS_TABS: [(&str, &str); 3] = [
("video", "Video"),
("audio", "Audio"),
("controls", "Controls"),
];
pub(super) fn settings_tabs(profile: SettingsProfile) -> &'static [(&'static str, &'static str)] {
match profile {
SettingsProfile::Full => &SETTINGS_TABS,
SettingsProfile::Minimal => &SETTINGS_TABS[..2],
}
}
const VIDEO_ROWS: [(&str, &str); 7] = [
("vsync", "Vsync"),
("fps_cap", "Frame Rate"),
("window_mode", "Window Mode"),
("resolution", "Resolution"),
("perf_stats", "Display Performance Stats"),
("show_fps", "Show Framerate"),
("show_vram", "Show VRAM Usage"),
];
const VIDEO_MINIMAL_ROWS: [(&str, &str); 4] = [
("window_mode", "Window Mode"),
("resolution", "Resolution"),
("vsync", "Vsync"),
("fps_cap", "Frame Rate"),
];
const VIDEO_ADVANCED_ROWS: [(&str, &str); 8] = [
("render_scale", "Render Scale"),
("upscale_backend", "Upscaler"),
("temporal_upscaling", "Temporal Upscaling"),
("hdr_display", "HDR Display"),
("hdr_pq", "HDR10 (PQ)"),
("frames_in_flight", "Frame Buffering"),
("occlusion_two_pass", "Occlusion Culling"),
("texture_quality", "Texture Quality"),
];
const VIDEO_ADVANCED_SLIDERS: [(&str, &str); 8] = [
("exposure", "Exposure"),
("bloom_intensity", "Bloom"),
("bloom_threshold", "Bloom Threshold"),
("bloom_knee", "Bloom Knee"),
("vignette", "Vignette"),
("lut_strength", "Color Grade"),
("ambient_intensity", "Ambient"),
("fov", "Field of View"),
];
const VIDEO_QUALITY_ROWS: [(&str, &str); 15] = [
("aa_mode", "Anti-Aliasing"),
("ssao", "Ambient Occlusion"),
("ssr", "Screen-Space Reflections"),
("ray_traced_reflections", "Ray-Traced Reflections"),
("reflection_blur_resolution", "Reflection Blur"),
("ssgi", "Global Illumination"),
("ssgi_resolution", "GI Resolution"),
("ssgi_rays", "GI Rays"),
("ssgi_steps", "GI Steps"),
("shadow_map_size", "Shadow Resolution"),
("shadow_update", "Shadow Update"),
("shadow_distance", "Shadow Distance"),
("shadow_cascades", "Shadow Cascades"),
("auto_exposure", "Auto Exposure"),
("anisotropy", "Anisotropic Filtering"),
];
const VIDEO_QUALITY_SLIDERS: [(&str, &str); 9] = [
("ssao_radius", "AO Radius"),
("ssao_intensity", "AO Intensity"),
("ssr_intensity", "Reflection Intensity"),
("ssr_max_distance", "Reflection Distance"),
("ssgi_intensity", "GI Intensity"),
("ssgi_max_distance", "GI Distance"),
("auto_exposure_min_ev", "Auto Exposure Min"),
("auto_exposure_max_ev", "Auto Exposure Max"),
("auto_exposure_speed", "Auto Exposure Speed"),
];
const AUDIO_ROWS: [(&str, &str); 4] = [
("master_volume", "Master Volume"),
("music_volume", "Music Volume"),
("sfx_volume", "SFX Volume"),
("voice_volume", "Voice Volume"),
];
const CONTROLS_SLIDERS: [(&str, &str); 1] = [("mouse_sensitivity", "Sensitivity")];
const CONTROLS_REBINDS: [(&str, &str); 7] = [
("Move Forward", "key_forward"),
("Move Back", "key_backward"),
("Move Left", "key_left"),
("Move Right", "key_right"),
("Sprint", "key_sprint"),
("Jump", "key_jump"),
("Interact", "key_interact"),
];
const CONTROLS_KEYS: [(&str, &str); 1] = [("Pause", "Esc")];
const CONTROLS_PAD_SLIDERS: [(&str, &str); 2] = [
("gamepad_look_sensitivity", "Stick Sensitivity"),
("gamepad_deadzone", "Stick Deadzone"),
];
const CONTROLS_PAD_REBINDS: [(&str, &str); 3] = [
("Sprint", "pad_sprint"),
("Jump", "pad_jump"),
("Interact", "pad_interact"),
];
#[derive(Clone, Copy)]
pub(super) enum BodyRow {
Option(&'static str, &'static str, i32),
Slider(&'static str, &'static str, i32),
Key(&'static str, &'static str, usize, i32),
Rebind(&'static str, &'static str, usize, i32),
GroupHeader(usize, &'static str),
}
pub(super) struct GroupSpec {
pub(super) gid: usize,
pub(super) title: &'static str,
pub(super) collapsed: bool,
}
pub(super) fn settings_body_rows(
active: &str,
profile: SettingsProfile,
) -> (Vec<BodyRow>, Vec<GroupSpec>) {
if profile == SettingsProfile::Minimal && active != "audio" {
let rows = VIDEO_MINIMAL_ROWS
.iter()
.map(|&(s, l)| BodyRow::Option(s, l, -1))
.collect();
return (rows, Vec::new());
}
match active {
"audio" => (
AUDIO_ROWS
.iter()
.map(|&(s, l)| BodyRow::Option(s, l, -1))
.collect(),
Vec::new(),
),
"controls" => {
let mut rows: Vec<BodyRow> = CONTROLS_SLIDERS
.iter()
.map(|&(s, l)| BodyRow::Slider(s, l, -1))
.collect();
for (i, &(label, setting)) in CONTROLS_REBINDS.iter().enumerate() {
rows.push(BodyRow::Rebind(label, setting, i, -1));
}
for (i, &(action, key)) in CONTROLS_KEYS.iter().enumerate() {
rows.push(BodyRow::Key(action, key, i, -1));
}
rows.push(BodyRow::GroupHeader(0, "Gamepad"));
for &(s, l) in &CONTROLS_PAD_SLIDERS {
rows.push(BodyRow::Slider(s, l, 0));
}
for (i, &(label, setting)) in CONTROLS_PAD_REBINDS.iter().enumerate() {
rows.push(BodyRow::Rebind(
label,
setting,
CONTROLS_REBINDS.len() + i,
0,
));
}
(
rows,
vec![GroupSpec {
gid: 0,
title: "Gamepad",
collapsed: true,
}],
)
}
_ => {
let mut rows: Vec<BodyRow> =
vec![BodyRow::Option("graphics_quality", "Graphics Quality", -1)];
rows.extend(VIDEO_ROWS.iter().map(|&(s, l)| BodyRow::Option(s, l, -1)));
rows.push(BodyRow::GroupHeader(0, "Quality"));
for &(s, l) in &VIDEO_QUALITY_ROWS {
rows.push(BodyRow::Option(s, l, 0));
}
for &(s, l) in &VIDEO_QUALITY_SLIDERS {
rows.push(BodyRow::Slider(s, l, 0));
}
rows.push(BodyRow::GroupHeader(1, "Advanced"));
for &(s, l) in &VIDEO_ADVANCED_ROWS {
rows.push(BodyRow::Option(s, l, 1));
}
for &(s, l) in &VIDEO_ADVANCED_SLIDERS {
rows.push(BodyRow::Slider(s, l, 1));
}
(
rows,
vec![
GroupSpec {
gid: 0,
title: "Quality",
collapsed: true,
},
GroupSpec {
gid: 1,
title: "Advanced",
collapsed: true,
},
],
)
}
}
}
pub(super) struct SettingsRow<'a> {
pub(super) name: &'a str,
pub(super) setting: &'a str,
pub(super) label: &'a str,
pub(super) font: &'a str,
pub(super) x: f32,
pub(super) y: f32,
pub(super) width: f32,
pub(super) scale: f32,
pub(super) style: &'a MainMenu,
}
pub(super) fn option_select_row(row: &SettingsRow) -> serde_json::Value {
let &SettingsRow {
name,
setting,
label,
font,
x,
y,
width,
scale,
style,
} = row;
serde_json::json!({
"name": name,
"type": "OptionSelect",
"args": {
"setting": setting,
"label": label,
"x": x,
"y": y,
"width": width,
"height": style.button_height,
"font": font,
"text_color": style.text_color,
"value_color": style.text_color,
"text_scale": scale,
"hover_color": style.hover_color,
"hover_scale": scale * style.hover_scale,
}
})
}
pub(super) fn slider_row(row: &SettingsRow) -> serde_json::Value {
let &SettingsRow {
name,
setting,
label,
font,
x,
y,
width,
scale,
style,
} = row;
serde_json::json!({
"name": name,
"type": "Slider",
"args": {
"setting": setting,
"label": label,
"x": x,
"y": y,
"width": width,
"height": style.button_height,
"font": font,
"text_color": style.text_color,
"value_color": style.text_color,
"text_scale": scale,
"handle_color": [
style.hover_color[0], style.hover_color[1], style.hover_color[2], 1.0
],
}
})
}