//! Shared native launch configuration for the game and in-process editor. use std::path::{Path, PathBuf}; use bevy::app::PluginGroupBuilder; use bevy::asset::AssetPlugin; use bevy::log::{LogPlugin, DEFAULT_FILTER}; use bevy::prelude::*; use bevy::window::{CompositeAlphaMode, PresentMode, WindowMode, WindowPlugin}; /// Runtime switch for the HDR camera pass. /// /// Set to `0`, `false`, `off`, or `no` to force the game/editor cameras through /// the SDR path when debugging mixed HDR/SDR compositor issues. pub const HDR_ENV_VAR: &str = "BEVY_FPS_HDR"; /// Locates the workspace `assets/` folder when the binary lives under `target/`. pub fn resolve_assets_directory() -> String { if let Some(path) = find_assets_directory(std::env::current_dir().ok()) { return path; } if let Ok(exe) = std::env::current_exe() { let mut dir = exe.parent().map(Path::to_path_buf); while let Some(current) = dir { if let Some(path) = find_assets_directory(Some(current.clone())) { return path; } dir = current.parent().map(Path::to_path_buf); } } "assets".into() } fn find_assets_directory(start: Option) -> Option { let start = start?; let assets = start.join("assets"); assets .is_dir() .then(|| assets.to_string_lossy().replace('\\', "/")) } pub fn default_plugins(title: impl Into) -> PluginGroupBuilder { DefaultPlugins .set(LogPlugin { // Blacksite intentionally replaces Bevy's `.scn.ron` loader with a // schema-aware loader. Keep the expected registration warning out // of normal startup logs; RUST_LOG still overrides this filter. filter: format!("{DEFAULT_FILTER}bevy_asset::server::loaders=error"), ..default() }) .set(WindowPlugin { primary_window: Some(primary_window(title)), ..default() }) .set(AssetPlugin { file_path: resolve_assets_directory(), ..default() }) } pub fn primary_window(title: impl Into) -> Window { Window { title: title.into(), name: Some("bevy-fps-foundation".into()), present_mode: PresentMode::AutoVsync, mode: WindowMode::Windowed, transparent: false, // Force an opaque surface. On Wayland/Hyprland the default `Auto` mode // can select an alpha-respecting surface, which may composite the whole // window as transparent on SDR outputs in mixed HDR/SDR setups. composite_alpha_mode: CompositeAlphaMode::Opaque, ..default() } } pub fn hdr_enabled_from_env() -> bool { std::env::var(HDR_ENV_VAR) .map(|value| { !matches!( value.trim().to_ascii_lowercase().as_str(), "0" | "false" | "off" | "no" ) }) .unwrap_or(true) } #[cfg(test)] mod tests { use super::{primary_window, resolve_assets_directory}; use bevy::window::CompositeAlphaMode; #[test] fn primary_window_is_opaque() { let window = primary_window("test"); assert!(!window.transparent); assert_eq!(window.composite_alpha_mode, CompositeAlphaMode::Opaque); } #[test] fn resolve_assets_directory_finds_workspace_assets() { let cwd = std::env::current_dir().expect("cwd"); let expected = cwd.join("assets"); if !expected.is_dir() { return; } assert_eq!(resolve_assets_directory(), expected.to_string_lossy()); } }