Blacksite/crates/settings/src/plugin.rs
Rbanh 0553a85220
Some checks are pending
CI / Format, lint, test, build (push) Waiting to run
Build production-ready editor authoring workflows
2026-07-11 12:41:04 -04:00

116 lines
3.8 KiB
Rust

use bevy::prelude::*;
use crate::{
load_project_settings_from_path, save_project_settings_to_string, PhysicsSettings,
ProjectSettings, DEFAULT_PROJECT_PATH,
};
/// Runtime copy of physics tuning consumed by `sim` systems.
#[derive(Resource, Debug, Clone, Copy)]
pub struct SimTuning {
pub player_radius: f32,
pub player_length: f32,
pub eye_offset_stand: f32,
pub eye_offset_crouch: f32,
pub gravity: f32,
pub walk_speed: f32,
pub run_speed: f32,
pub crouch_speed: f32,
pub jump_speed: f32,
pub ground_accel: f32,
pub air_accel: f32,
pub ground_check_dist: f32,
pub skin: f32,
pub max_slide_iter: u32,
pub ground_normal_y: f32,
pub coyote_time: f32,
pub jump_buffer: f32,
}
impl SimTuning {
pub fn from_physics(physics: &PhysicsSettings) -> Self {
Self {
player_radius: physics.player_radius,
player_length: physics.player_length,
eye_offset_stand: physics.eye_offset_stand,
eye_offset_crouch: physics.eye_offset_crouch,
gravity: physics.gravity,
walk_speed: physics.walk_speed,
run_speed: physics.run_speed,
crouch_speed: physics.crouch_speed,
jump_speed: physics.jump_speed,
ground_accel: physics.ground_accel,
air_accel: physics.air_accel,
ground_check_dist: physics.ground_check_dist,
skin: physics.skin,
max_slide_iter: physics.max_slide_iter,
ground_normal_y: physics.ground_normal_y,
coyote_time: physics.coyote_time,
jump_buffer: physics.jump_buffer,
}
}
}
/// Tracks project settings file path and dirty state (editor persists via UI).
#[derive(Resource, Debug)]
pub struct ProjectSettingsIo {
pub path: String,
pub dirty: bool,
}
impl Default for ProjectSettingsIo {
fn default() -> Self {
Self {
path: DEFAULT_PROJECT_PATH.into(),
dirty: false,
}
}
}
/// Fired after project settings are saved or reloaded from disk.
#[derive(Message, Debug, Clone, Copy, Default)]
pub struct ProjectSettingsChanged;
pub struct ProjectSettingsPlugin;
impl Plugin for ProjectSettingsPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<ProjectSettingsIo>()
.register_type::<ProjectSettings>()
.register_type::<crate::ProjectKind>()
.register_type::<crate::AudioSettings>()
.register_type::<crate::AudioBusSettings>()
.register_type::<crate::GiMode>()
.register_type::<crate::ExposureMode>()
.register_type::<crate::ActiveCameraRenderProfile>()
.register_type::<crate::EffectiveRenderStack>()
.register_type::<crate::RenderFallbackReason>()
.register_type::<crate::RenderingCapabilities>()
.add_message::<ProjectSettingsChanged>()
.add_systems(PreStartup, load_settings);
}
}
fn load_settings(mut commands: Commands, io: Res<ProjectSettingsIo>) {
let settings = load_project_settings_from_path(&io.path);
let tuning = SimTuning::from_physics(&settings.physics);
commands.insert_resource(settings);
commands.insert_resource(tuning);
}
/// Refreshes [`SimTuning`] from the current [`ProjectSettings`] resource.
pub fn sync_sim_tuning(settings: &ProjectSettings, mut tuning: ResMut<SimTuning>) {
*tuning = SimTuning::from_physics(&settings.physics);
}
/// Persists settings to the path in [`ProjectSettingsIo`].
pub fn save_project_settings(
settings: &ProjectSettings,
io: &mut ProjectSettingsIo,
) -> Result<(), String> {
let text = save_project_settings_to_string(settings).map_err(|error| error.to_string())?;
std::fs::write(&io.path, text).map_err(|error| error.to_string())?;
io.dirty = false;
Ok(())
}