diff --git a/bin/editor.rs b/bin/editor.rs index ec94e74..0f155a0 100644 --- a/bin/editor.rs +++ b/bin/editor.rs @@ -8,13 +8,13 @@ // // TODO: // * Disable auto start/load -// * Better handle hide/close monologue // * (hard) Harden Active Camera // * (medium) Despawn entire scene when GLTF changed? // * (medium) Select Font -> "Default Font" Resource // * (medium) Pre-compute animation target entities // * (medium) Animation buttons only visible when playable // * (easy) Clear button to wipe spawned scene +// * Better handle hide/close monologue // * (brutal) export level // * (hard) import level // @@ -119,6 +119,7 @@ fn main() { directional_light_force_shadows, ), ) + .add_systems(Update, (clear_level, clear_assets)) .run(); } @@ -197,6 +198,15 @@ fn initialize_ui(mut commands: Commands) { // HACK: This is super janky but I think we need it like this for UI layout rules let mut content_containers: Vec<(String, Entity)> = Vec::new(); + let simple_button = ButtonBundle { + style: Style { + ..base_style.clone() + }, + background_color: Color::WHITE.into(), + border_color: Color::BLACK.into(), + ..default() + }; + // Containers with asset content parent .spawn(( @@ -274,24 +284,38 @@ fn initialize_ui(mut commands: Commands) { ui::Select::Single, )) .with_children(|parent| { - let b = ButtonBundle { - style: Style { - ..base_style.clone() + content_containers.iter().enumerate().for_each( + |(i, (name, target))| { + parent.spawn(( + simple_button.clone(), + ui::Title { + text: name.clone(), + ..default() + }, + ui::Collapse { target: *target }, + ui::Sorting(i as u8), + )); }, - background_color: Color::WHITE.into(), - border_color: Color::BLACK.into(), - ..default() - }; - content_containers.iter().for_each(|(name, target)| { - parent.spawn(( - b.clone(), - ui::Title { - text: name.clone(), - ..default() - }, - ui::Collapse { target: *target }, - )); - }); + ); + + parent.spawn(( + simple_button.clone(), + ClearAssets, + ui::Sorting(90), + ui::Title { + text: "Clear Assets".into(), + ..default() + }, + )); + parent.spawn(( + simple_button.clone(), + ClearLevel, + ui::Sorting(95), + ui::Title { + text: "Reset Level".into(), + ..default() + }, + )); }); }) .id(); @@ -786,6 +810,7 @@ mod animations { } /// When a new scene is loaded, add any newly compatible animations + /// TODO: Add target entity(s) too pub fn add_animations_ui( player_spawned: Query<&Name, Added>, widget: Query>, @@ -822,7 +847,6 @@ mod animations { // When a scene is de-selected, remove any outdated animation options pub fn remove_animations_ui( mut removed_players: RemovedComponents>, - names: Query<&Name>, current: Query<(Entity, &ui::TargetAsset)>, clips: Res>, targets: Query<(&AnimationPlayer, &Name)>, @@ -1274,3 +1298,74 @@ mod lighting { }) } } + +use reset::*; +mod reset { + use super::*; + + #[derive(Debug, Component)] + pub struct ClearLevel; + + pub fn clear_level( + events: Query, Added)>, + actives: Query< + Entity, + ( + With, + Or<( + With, + With>, + With>, + With>, + With>, + With>, + With>, + )>, + ), + >, + root: Query>, + mut commands: Commands, + ) { + events.iter().for_each(|_| { + actives.iter().for_each(|entity| { + commands.entity(entity).remove::(); + }); + commands.entity(root.single()).despawn_descendants(); + }) + } + + #[derive(Debug, Component)] + pub struct ClearAssets; + + pub fn clear_assets( + events: Query, Added)>, + asset_holders: Query< + Entity, + Or<( + With>, + With>, + With>, + With>, + With>, + With>, + With>, + With>, + With>, + With>, + With>, + With>, + )>, + >, + mut registry: ResMut, + mut commands: Commands, + ) { + events.iter().for_each(|entity| { + asset_holders + .iter() + .for_each(|entity| commands.entity(entity).despawn_recursive()); + registry.0.clear(); + // TODO: .clear() assets? + commands.entity(entity).remove::(); + }) + } +}