Blacksite/crates/game/src/scene_bootstrap.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

86 lines
2.7 KiB
Rust

//! Standalone project-scene bootstrap.
use bevy::prelude::*;
use bevy::world_serialization::DynamicWorld;
use settings::ProjectSettings;
/// Runtime root for the standalone project's configured default level.
#[derive(Component, Debug)]
pub struct ProjectDefaultLevelRoot;
pub(crate) fn spawn_project_default_level(
mut commands: Commands,
asset_server: Res<AssetServer>,
settings: Res<ProjectSettings>,
existing: Query<(), With<ProjectDefaultLevelRoot>>,
) {
if !existing.is_empty() {
return;
}
let configured_path = settings.default_level.trim();
if configured_path.is_empty() {
error!("Project default_level is empty; standalone scene startup was skipped");
return;
}
let asset_path = shared::asset_server_path(configured_path);
let handle: Handle<DynamicWorld> = asset_server.load(asset_path.clone());
commands.spawn((
Name::new(format!("Project Default Level ({configured_path})")),
ProjectDefaultLevelRoot,
DynamicWorldRoot(handle),
));
info!("Loading project default level {configured_path} ({asset_path})");
}
#[cfg(test)]
mod tests {
use super::*;
use bevy::asset::AssetPlugin;
use bevy::world_serialization::WorldSerializationPlugin;
fn test_app(default_level: &str) -> App {
let mut app = App::new();
app.add_plugins((
MinimalPlugins,
AssetPlugin::default(),
WorldSerializationPlugin,
));
app.insert_resource(ProjectSettings {
default_level: default_level.to_string(),
..Default::default()
});
app
}
#[test]
fn standalone_bootstrap_uses_the_project_default_level() {
let mut app = test_app("assets/levels/editor_scene.scn.ron");
app.add_systems(Startup, spawn_project_default_level);
app.update();
let world = app.world_mut();
let mut roots = world.query_filtered::<&DynamicWorldRoot, With<ProjectDefaultLevelRoot>>();
let root = roots.single(world).expect("one standalone scene root");
let path = world
.resource::<AssetServer>()
.get_path(root.0.id())
.expect("default level handle retains its asset path");
assert_eq!(path.to_string(), "levels/editor_scene.scn.ron");
}
#[test]
fn empty_default_level_does_not_create_a_runtime_root() {
let mut app = test_app(" ");
app.add_systems(Startup, spawn_project_default_level);
app.update();
let world = app.world_mut();
let mut roots = world.query_filtered::<Entity, With<ProjectDefaultLevelRoot>>();
assert_eq!(roots.iter(world).count(), 0);
}
}