feat: runtime-configurable VSync via config.toml

[display]
vsync = "mailbox"   # "vsync" | "mailbox" | "uncapped"

VsyncMode enum with custom Deserialize — accepts string values in toml.
apply_vsync_setting system reads GameConfig on every frame, updates
Window.present_mode immediately on change. No restart needed.
This commit is contained in:
2026-03-20 17:10:54 +00:00
parent 11d4b6a8a0
commit eac787be3f
3 changed files with 51 additions and 1 deletions
+3
View File
@@ -1,5 +1,8 @@
initial_chunk_radius = 15
[display]
vsync = "mailbox"
[spawn_counts]
dorfs = 5
pigs = 5
+31
View File
@@ -8,6 +8,37 @@ use std::sync::OnceLock;
pub struct GameConfig {
pub initial_chunk_radius: i32,
pub spawn_counts: SpawnCounts,
#[serde(default)]
pub display: DisplaySettings,
}
#[derive(Debug, Deserialize, Clone, Default)]
pub struct DisplaySettings {
#[serde(default)]
pub vsync: VsyncMode,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum VsyncMode {
#[default]
Vsync,
Mailbox,
Uncapped,
}
impl<'de> Deserialize<'de> for VsyncMode {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
match s.as_str() {
"vsync" => Ok(VsyncMode::Vsync),
"mailbox" => Ok(VsyncMode::Mailbox),
"uncapped" => Ok(VsyncMode::Uncapped),
_ => Ok(VsyncMode::Vsync),
}
}
}
#[derive(Debug, Deserialize, Clone)]
+17 -1
View File
@@ -1,6 +1,6 @@
use crate::{
camera,
config::GameConfig,
config::{GameConfig, VsyncMode},
world::generation::{
generate_chunk_fauna, generate_chunk_foliage, generate_chunk_forrestry,
generate_chunk_weathering_and_precipitation, apply_terrain_blobs, spawn_terrain_tasks,
@@ -18,6 +18,21 @@ pub use chunks::management::*;
pub use textures::management::*;
pub use tiles::{prefabs::*, rendering::*, visibility::*};
pub fn apply_vsync_setting(
config: Res<GameConfig>,
mut windows: Query<&mut Window>,
) {
if config.is_changed() {
if let Ok(mut window) = windows.single_mut() {
window.present_mode = match config.display.vsync {
VsyncMode::Vsync => bevy::window::PresentMode::AutoVsync,
VsyncMode::Mailbox => bevy::window::PresentMode::Mailbox,
VsyncMode::Uncapped => bevy::window::PresentMode::AutoNoVsync,
};
}
}
}
pub struct WorldPlugin;
impl Plugin for WorldPlugin {
@@ -58,6 +73,7 @@ impl Plugin for WorldPlugin {
.after(crate::entities::item::item_tile_management_system),
tiles::track_benchmark,
tiles::render_bench_report_system,
apply_vsync_setting,
handle_tile_occlusion_updates,
tiles::spawn_tilemap_chunks,
tiles::on_camera_z_changed,