Compare commits

...

5 Commits

@ -23,7 +23,7 @@
// * make min/max/close buttons into actions not selects // * make min/max/close buttons into actions not selects
// * (???) Better handle hide/close monologue // * (???) Better handle hide/close monologue
use bevy::{asset::ChangeWatcher, gltf::Gltf, prelude::*, utils::Duration}; use bevy::{asset::ChangeWatcher, prelude::*, utils::Duration};
use monologue_trees::{debug::*, editor::plugin::EditorPlugin, ui}; use monologue_trees::{debug::*, editor::plugin::EditorPlugin, ui};
fn main() { fn main() {

@ -5,15 +5,16 @@ pub struct EditorAnimationPlugin;
impl Plugin for EditorAnimationPlugin { impl Plugin for EditorAnimationPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Update, sync_asset_buttons::<AnimationClip>) app.add_event::<ControlAnimation>()
.add_systems(Update, sync_asset_buttons::<AnimationClip>)
.add_systems(Update, sync_remove_asset_buttons::<AnimationClip>) .add_systems(Update, sync_remove_asset_buttons::<AnimationClip>)
.add_systems(Update, set_epoch_animations)
.add_systems(Update, load_epoch_animations)
.add_systems(Update, init_animations_ui) .add_systems(Update, init_animations_ui)
.add_systems(Update, remove_animations_ui) .add_systems(Update, remove_animations_ui)
.add_systems(Update, add_animations_ui) .add_systems(Update, add_animations_ui)
.add_systems(Update, play_all_animations) .add_systems(Update, play_all_animations)
.add_systems(Update, play_animation); .add_systems(Update, play_animation)
.add_systems(Update, ui_control_animations)
.add_systems(Update, ui_active_animation);
} }
} }
@ -23,7 +24,7 @@ pub struct AnimationWidget;
#[derive(Debug, Component)] #[derive(Debug, Component)]
pub struct AnimationPlayAll; pub struct AnimationPlayAll;
pub fn init_animations_ui(events: Query<Entity, Added<AnimationWidget>>, mut commands: Commands) { fn init_animations_ui(events: Query<Entity, Added<AnimationWidget>>, mut commands: Commands) {
events.iter().for_each(|entity| { events.iter().for_each(|entity| {
commands.entity(entity).with_children(|parent| { commands.entity(entity).with_children(|parent| {
parent.spawn(( parent.spawn((
@ -49,7 +50,7 @@ pub fn init_animations_ui(events: Query<Entity, Added<AnimationWidget>>, mut com
/// When a new scene is loaded, add any newly compatible animations /// When a new scene is loaded, add any newly compatible animations
/// TODO: Add target entity(s) too /// TODO: Add target entity(s) too
pub fn add_animations_ui( fn add_animations_ui(
player_spawned: Query<&Name, Added<AnimationPlayer>>, player_spawned: Query<&Name, Added<AnimationPlayer>>,
widget: Query<Entity, With<AnimationWidget>>, widget: Query<Entity, With<AnimationWidget>>,
mut commands: Commands, mut commands: Commands,
@ -79,7 +80,7 @@ pub fn add_animations_ui(
} }
// When a scene is de-selected, remove any outdated animation options // When a scene is de-selected, remove any outdated animation options
pub fn remove_animations_ui( fn remove_animations_ui(
mut removed_players: RemovedComponents<Handle<Scene>>, mut removed_players: RemovedComponents<Handle<Scene>>,
current: Query<(Entity, &ui::TargetAsset<AnimationClip>)>, current: Query<(Entity, &ui::TargetAsset<AnimationClip>)>,
clips: Res<Assets<AnimationClip>>, clips: Res<Assets<AnimationClip>>,
@ -112,50 +113,19 @@ pub fn remove_animations_ui(
}); });
} }
pub fn play_all_animations( #[derive(Debug, Event)]
start: Query<Entity, (With<Button>, Added<ui::Active>)>, pub enum ControlAnimation {
mut stop: RemovedComponents<ui::Active>, Play(Handle<AnimationClip>),
play_all_btn: Query<Entity, With<AnimationPlayAll>>, Pause(Handle<AnimationClip>),
clip_btns: Query<Entity, With<ui::TargetAsset<AnimationClip>>>,
mut commands: Commands,
) {
stop.iter()
.filter(|&entity| play_all_btn.contains(entity))
.for_each(|_| {
clip_btns.iter().for_each(|entity| {
commands.entity(entity).remove::<ui::Active>();
})
});
start
.iter()
.filter(|&entity| play_all_btn.contains(entity))
.for_each(|_| {
clip_btns.iter().for_each(|entity| {
commands.entity(entity).insert(ui::Active);
})
});
} }
pub fn play_animation( fn play_animation(
start: Query<Entity, (With<Button>, Added<ui::Active>)>, mut events: EventReader<ControlAnimation>,
mut stop: RemovedComponents<ui::Active>,
clip_refs: Query<&ui::TargetAsset<AnimationClip>>,
mut targets: Query<(&mut AnimationPlayer, &Name), With<Transform>>, mut targets: Query<(&mut AnimationPlayer, &Name), With<Transform>>,
clips: Res<Assets<AnimationClip>>, clips: Res<Assets<AnimationClip>>,
) { ) {
stop.iter().for_each(|entity| { events.iter().for_each(|event| match event {
if let Ok(ui::TargetAsset { handle }) = clip_refs.get(entity) { ControlAnimation::Play(handle) => {
let clip = clips.get(&handle).expect("Load animation clip");
targets
.iter_mut()
.filter(|(_, name)| clip.compatible_with(name))
.for_each(|(mut player, _)| {
player.pause();
})
}
});
start.iter().for_each(|entity| {
if let Ok(ui::TargetAsset { handle }) = clip_refs.get(entity) {
let clip = clips.get(&handle).expect("Load animation clip"); let clip = clips.get(&handle).expect("Load animation clip");
targets targets
.iter_mut() .iter_mut()
@ -166,7 +136,102 @@ pub fn play_animation(
} else { } else {
player.play(handle.clone()).repeat(); player.play(handle.clone()).repeat();
} }
});
}
ControlAnimation::Pause(handle) => {
let clip = clips.get(handle).expect("Load animation clip");
targets
.iter_mut()
.filter(|(_, name)| clip.compatible_with(name))
.for_each(|(mut player, _)| {
player.pause();
});
}
});
}
fn play_all_animations(
events: Query<
(Entity, &Interaction, Option<&ui::Active>),
(With<AnimationPlayAll>, Changed<Interaction>),
>,
clip_btns: Query<&ui::TargetAsset<AnimationClip>>,
mut writer: EventWriter<ControlAnimation>,
mut commands: Commands,
) {
events
.iter()
.filter_map(|(entity, &interaction, active)| {
(interaction == Interaction::Pressed).then_some((entity, active))
})
.for_each(|(entity, active)| match active {
Some(_) => {
commands.entity(entity).remove::<ui::Active>();
clip_btns.iter().for_each(|ui::TargetAsset { handle }| {
writer.send(ControlAnimation::Pause(handle.clone()));
});
}
None => {
commands.entity(entity).insert(ui::Active);
clip_btns.iter().for_each(|ui::TargetAsset { handle }| {
writer.send(ControlAnimation::Play(handle.clone()));
});
}
})
}
fn ui_control_animations(
events: Query<
(
&Interaction,
&ui::TargetAsset<AnimationClip>,
Option<&ui::Active>,
),
(With<Button>, Changed<Interaction>),
>,
mut writer: EventWriter<ControlAnimation>,
) {
events
.iter()
.filter_map(
|(interaction, ui::TargetAsset { handle }, active)| match interaction {
Interaction::Pressed => Some((handle, active)),
_ => None,
},
)
.for_each(|(handle, active)| match active {
Some(_) => writer.send(ControlAnimation::Pause(handle.clone())),
None => writer.send(ControlAnimation::Play(handle.clone())),
});
}
fn ui_active_animation(
mut events: EventReader<ControlAnimation>,
targets: Query<(Entity, &ui::TargetAsset<AnimationClip>)>,
mut commands: Commands,
) {
events.iter().for_each(|event| match event {
ControlAnimation::Play(this_handle) => {
targets
.iter()
.find_map(|(entity, ui::TargetAsset { handle })| {
(handle == this_handle).then_some(entity)
})
.into_iter()
.for_each(|entity| {
commands.entity(entity).insert(ui::Active);
});
}
ControlAnimation::Pause(this_handle) => {
targets
.iter()
.find_map(|(entity, ui::TargetAsset { handle })| {
(handle == this_handle).then_some(entity)
}) })
.into_iter()
.for_each(|entity| {
commands.entity(entity).remove::<ui::Active>();
});
} }
}); });
} }

@ -5,9 +5,9 @@ pub struct EditorAssetsPlugin;
impl Plugin for EditorAssetsPlugin { impl Plugin for EditorAssetsPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Startup, reload_assets) app.init_resource::<AssetRegistry>()
.add_systems(Startup, reload_assets)
.add_systems(Update, reload_assets.run_if(ui::activated::<ReloadAssets>)) .add_systems(Update, reload_assets.run_if(ui::activated::<ReloadAssets>))
.init_resource::<AssetRegistry>()
.add_systems(Update, clear_assets.run_if(ui::activated::<ClearAssets>)); .add_systems(Update, clear_assets.run_if(ui::activated::<ClearAssets>));
} }
} }
@ -18,7 +18,7 @@ pub struct AssetRegistry(pub Vec<HandleUntyped>);
#[derive(Debug, Component)] #[derive(Debug, Component)]
pub struct ReloadAssets; pub struct ReloadAssets;
pub fn reload_assets( fn reload_assets(
server: Res<AssetServer>, server: Res<AssetServer>,
mut registry: ResMut<AssetRegistry>, mut registry: ResMut<AssetRegistry>,
mut writer: EventWriter<ui::Alert>, mut writer: EventWriter<ui::Alert>,
@ -142,14 +142,10 @@ pub fn sync_asset_buttons<T: Asset>(
buttons buttons
.iter() .iter()
.find_map(|(entity, ui::TargetAsset { handle })| { .find_map(|(entity, ui::TargetAsset { handle })| {
if handle == this_handle { (handle == this_handle).then_some(entity)
Some(entity)
} else {
None
}
}) })
.iter() .into_iter()
.for_each(|&entity| { .for_each(|entity| {
commands.entity(entity).insert(ui::Active); commands.entity(entity).insert(ui::Active);
}); });
}); });
@ -166,20 +162,16 @@ pub fn sync_remove_asset_buttons<T: Asset>(
events events
.iter() .iter()
.find_map(|this_asset_entity| asset_entities.get(this_asset_entity).ok()) .find_map(|this_asset_entity| asset_entities.get(this_asset_entity).ok())
.iter() .into_iter()
.for_each(|this_handle| { .for_each(|this_handle| {
info!("Syncing removal of {:?}", this_handle); debug!("Syncing removal of {:?}", this_handle);
buttons buttons
.iter() .iter()
.find_map(|(entity, ui::TargetAsset { handle })| { .find_map(|(entity, ui::TargetAsset { handle })| {
if handle == *this_handle { (handle == this_handle).then_some(entity)
Some(entity)
} else {
None
}
}) })
.iter() .into_iter()
.for_each(|&entity| { .for_each(|entity| {
commands.entity(entity).remove::<ui::Active>(); commands.entity(entity).remove::<ui::Active>();
}); });
}); });
@ -188,7 +180,7 @@ pub fn sync_remove_asset_buttons<T: Asset>(
#[derive(Debug, Component)] #[derive(Debug, Component)]
pub struct ClearAssets; pub struct ClearAssets;
pub fn clear_assets( fn clear_assets(
asset_holders: Query< asset_holders: Query<
Entity, Entity,
Or<( Or<(

@ -1,3 +1,5 @@
// TODO: Stop all button
use crate::editor::prelude::*; use crate::editor::prelude::*;
use bevy::audio::PlaybackMode; use bevy::audio::PlaybackMode;
@ -6,15 +8,17 @@ pub struct EditorAudioPlugin;
impl Plugin for EditorAudioPlugin { impl Plugin for EditorAudioPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Update, audio_ui) app.register_type::<AudioRoot>()
.add_systems(Update, ui_control_audio) .add_event::<ControlAudio>()
.add_systems(Update, init_audio_ui)
.add_systems(Update, ui_active::<AudioSource>) .add_systems(Update, ui_active::<AudioSource>)
.add_systems(Update, ui_inactive::<AudioSource>) .add_systems(Update, ui_inactive::<AudioSource>)
.add_systems(Update, control_audio)
.add_systems(Update, sync_asset_buttons::<AudioSource>) .add_systems(Update, sync_asset_buttons::<AudioSource>)
.register_type::<AudioRoot>() .add_systems(Update, sync_remove_asset_buttons::<AudioSource>)
.add_event::<ControlAudio>() .add_systems(Update, audio_ui)
.add_systems(Update, sync_remove_asset_buttons::<AudioSource>); .add_systems(Update, ui_control_audio)
.add_systems(Update, stop_all_audio)
.add_systems(Update, control_audio);
} }
} }
@ -25,7 +29,34 @@ pub struct AudioRoot;
#[derive(Debug, Component, Default)] #[derive(Debug, Component, Default)]
pub struct AudioWidget; pub struct AudioWidget;
pub fn audio_ui( #[derive(Debug, Component)]
struct AudioStopAll;
fn init_audio_ui(events: Query<Entity, Added<AudioWidget>>, mut commands: Commands) {
events.iter().for_each(|entity| {
commands.entity(entity).with_children(|parent| {
parent.spawn((
AudioStopAll,
ButtonBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
margin: UiRect::all(Val::Px(1.0)),
padding: UiRect::all(Val::Px(1.0)),
..default()
},
border_color: Color::BLACK.into(),
..default()
},
ui::Title {
text: "Stop All".into(),
..default()
},
));
});
})
}
fn audio_ui(
mut events: EventReader<AssetEvent<AudioSource>>, mut events: EventReader<AssetEvent<AudioSource>>,
mut commands: Commands, mut commands: Commands,
widget: Query<Entity, With<AudioWidget>>, widget: Query<Entity, With<AudioWidget>>,
@ -34,7 +65,7 @@ pub fn audio_ui(
) { ) {
events.iter().for_each(|event| match event { events.iter().for_each(|event| match event {
AssetEvent::Created { handle } => { AssetEvent::Created { handle } => {
info!("Asset created! {:?}", event); debug!("Audio asset created! {:?}", event);
create_asset_button( create_asset_button(
&widget, &widget,
&mut commands, &mut commands,
@ -46,7 +77,7 @@ pub fn audio_ui(
); );
} }
AssetEvent::Removed { handle } => { AssetEvent::Removed { handle } => {
info!("Asset removed! {:?}", event); debug!("Asset removed! {:?}", event);
destroy_asset_button( destroy_asset_button(
&current, &current,
&mut commands, &mut commands,
@ -56,7 +87,7 @@ pub fn audio_ui(
); );
} }
AssetEvent::Modified { handle } => { AssetEvent::Modified { handle } => {
info!("Asset modified! {:?}", event); debug!("Asset modified! {:?}", event);
destroy_asset_button( destroy_asset_button(
&current, &current,
&mut commands, &mut commands,
@ -83,7 +114,7 @@ pub enum ControlAudio {
Stop(Handle<AudioSource>), Stop(Handle<AudioSource>),
} }
pub fn control_audio( fn control_audio(
mut events: EventReader<ControlAudio>, mut events: EventReader<ControlAudio>,
root: Query<Entity, With<AudioRoot>>, root: Query<Entity, With<AudioRoot>>,
mut commands: Commands, mut commands: Commands,
@ -91,7 +122,7 @@ pub fn control_audio(
) { ) {
events.iter().for_each(|event| match event { events.iter().for_each(|event| match event {
ControlAudio::Loop(handle) => { ControlAudio::Loop(handle) => {
info!("Looping audio {:?}", handle); debug!("Looping audio {:?}", handle);
let root = if let Ok(entity) = root.get_single() { let root = if let Ok(entity) = root.get_single() {
entity entity
} else { } else {
@ -106,30 +137,24 @@ pub fn control_audio(
..default() ..default()
}, },
}); });
info!("Done spawning"); debug!("Done spawning {:?}", handle);
}); });
} }
ControlAudio::Stop(handle) => { ControlAudio::Stop(handle) => {
info!("Stopping audio {:?}", handle);
sources sources
.iter() .iter()
.find_map(|(entity, source_handle)| { .find_map(|(entity, source_handle)| (source_handle == handle).then_some(entity))
if source_handle == handle { .into_iter()
Some(entity) .for_each(|entity| {
} else { debug!("Stopping audio {:?}", handle);
None
}
})
.iter()
.for_each(|&entity| {
commands.entity(entity).despawn_recursive(); commands.entity(entity).despawn_recursive();
info!("Done despawning"); debug!("Done despawning {:?}", handle);
}); });
} }
}); });
} }
pub fn ui_control_audio( fn ui_control_audio(
events: Query< events: Query<
( (
&Interaction, &Interaction,
@ -153,3 +178,19 @@ pub fn ui_control_audio(
None => writer.send(ControlAudio::Loop(handle.clone())), None => writer.send(ControlAudio::Loop(handle.clone())),
}); });
} }
fn stop_all_audio(
events: Query<&Interaction, With<AudioStopAll>>,
targets: Query<&ui::TargetAsset<AudioSource>>,
mut writer: EventWriter<ControlAudio>,
) {
events
.into_iter()
.filter(|&interaction| *interaction == Interaction::Pressed)
.into_iter()
.for_each(|_| {
targets.iter().for_each(|ui::TargetAsset { handle }| {
writer.send(ControlAudio::Stop(handle.clone()));
});
});
}

@ -5,8 +5,10 @@ pub struct EditorCameraPlugin;
impl Plugin for EditorCameraPlugin { impl Plugin for EditorCameraPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Update, cameras_ui) app.insert_resource(Msaa::Sample4)
.add_systems(Update, manage_active_camera) .add_systems(Update, cameras_ui)
.add_systems(Update, control_active_camera)
.add_systems(Update, ui_control_active_camera)
.add_systems(Update, fallback_camera); .add_systems(Update, fallback_camera);
} }
} }
@ -17,7 +19,7 @@ pub struct EditorCamera;
#[derive(Debug, Component, Default)] #[derive(Debug, Component, Default)]
pub struct CameraWidget; pub struct CameraWidget;
pub fn cameras_ui( fn cameras_ui(
mut added: Query<(Entity, &mut Camera, &Name), Added<Camera>>, mut added: Query<(Entity, &mut Camera, &Name), Added<Camera>>,
mut removed: RemovedComponents<Camera>, mut removed: RemovedComponents<Camera>,
editor_camera: Query<Entity, With<EditorCamera>>, editor_camera: Query<Entity, With<EditorCamera>>,
@ -26,11 +28,11 @@ pub fn cameras_ui(
mut commands: Commands, mut commands: Commands,
) { ) {
removed.iter().for_each(|entity| { removed.iter().for_each(|entity| {
info!("Destroy button for {:?}", entity); debug!("Destroy button for {:?}", entity);
destroy_entity_button(&current, &mut commands, &ui::TargetEntity { entity }); destroy_entity_button(&current, &mut commands, &ui::TargetEntity { entity });
}); });
added.iter_mut().for_each(|(entity, mut camera, name)| { added.iter_mut().for_each(|(entity, mut camera, name)| {
info!("Camera added {:?} {:?}", entity, name); debug!("Camera added {:?} {:?}", entity, name);
create_entity_button( create_entity_button(
&widget, &widget,
&mut commands, &mut commands,
@ -42,25 +44,60 @@ pub fn cameras_ui(
} }
/// Set the camera active component based on button clicks /// Set the camera active component based on button clicks
pub fn manage_active_camera( fn control_active_camera(
events: Query<&ui::TargetEntity, Added<ui::Active>>, events: Query<(Entity, &Camera), Changed<Camera>>,
mut cameras: Query<(Entity, &mut Camera)>, buttons: Query<(Entity, &ui::TargetEntity)>,
mut commands: Commands,
) { ) {
events.iter().for_each(|ui::TargetEntity { entity }| { events
cameras.iter_mut().for_each(|(this_entity, mut camera)| { .iter()
if this_entity == *entity { .filter_map(|(e, c)| {
info!("Marking {:?} as active camera", entity); buttons
camera.is_active = true; .iter()
.find_map(|(button, ui::TargetEntity { entity })| {
(e == *entity).then_some((button, c))
})
})
.for_each(|(button, camera)| {
if camera.is_active {
commands.entity(button).insert(ui::Active);
} else { } else {
info!("Marking {:?} as inactive camera", entity); commands.entity(button).remove::<ui::Active>();
camera.is_active = false;
} }
}); });
}); }
fn ui_control_active_camera(
events: Query<
(&Interaction, &ui::TargetEntity, Option<&ui::Active>),
(With<Button>, Changed<Interaction>),
>,
mut cameras: Query<(Entity, &mut Camera, Option<&EditorCamera>)>,
) {
events
.iter()
.filter_map(|(&interaction, ui::TargetEntity { entity }, active)| {
(interaction == Interaction::Pressed).then_some((entity, active))
})
.for_each(|(&entity, active)| {
cameras
.iter_mut()
.for_each(|(this, mut camera, editor_cam)| {
if this == entity {
if editor_cam.is_some() {
camera.is_active = true;
} else {
camera.is_active = !active.is_some();
}
} else {
camera.is_active = false;
}
});
});
} }
// In the event that an active camera is despawned, fall back to the editor camera // In the event that an active camera is despawned, fall back to the editor camera
pub fn fallback_camera( fn fallback_camera(
modified: Query<Entity, (Changed<Camera>, Without<EditorCamera>)>, modified: Query<Entity, (Changed<Camera>, Without<EditorCamera>)>,
mut removed: RemovedComponents<Camera>, mut removed: RemovedComponents<Camera>,
other_cameras: Query<&Camera, Without<EditorCamera>>, other_cameras: Query<&Camera, Without<EditorCamera>>,

@ -5,11 +5,11 @@ pub struct EditorFontPlugin;
impl Plugin for EditorFontPlugin { impl Plugin for EditorFontPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Update, sync_asset_buttons::<Font>) app.init_resource::<FontInfo>()
.add_systems(Update, sync_asset_buttons::<Font>)
.add_systems(Update, sync_remove_asset_buttons::<Font>) .add_systems(Update, sync_remove_asset_buttons::<Font>)
.add_systems(Update, fonts_ui) .add_systems(Update, fonts_ui)
.add_systems(Update, ui_control_font) .add_systems(Update, ui_control_font)
.init_resource::<FontInfo>()
.add_systems(Update, sync_font); .add_systems(Update, sync_font);
} }
} }
@ -22,7 +22,7 @@ pub struct FontInfo {
pub default: Option<Handle<Font>>, pub default: Option<Handle<Font>>,
} }
pub fn fonts_ui( fn fonts_ui(
mut events: EventReader<AssetEvent<Font>>, mut events: EventReader<AssetEvent<Font>>,
mut commands: Commands, mut commands: Commands,
widget: Query<Entity, With<FontWidget>>, widget: Query<Entity, With<FontWidget>>,
@ -31,7 +31,7 @@ pub fn fonts_ui(
) { ) {
events.iter().for_each(|event| match event { events.iter().for_each(|event| match event {
AssetEvent::Created { handle } => { AssetEvent::Created { handle } => {
info!("Asset created! {:?}", event); debug!("Font asset created! {:?}", event);
create_asset_button( create_asset_button(
&widget, &widget,
&mut commands, &mut commands,
@ -43,7 +43,7 @@ pub fn fonts_ui(
); );
} }
AssetEvent::Removed { handle } => { AssetEvent::Removed { handle } => {
info!("Asset removed! {:?}", event); debug!("Font asset removed! {:?}", event);
destroy_asset_button( destroy_asset_button(
&current, &current,
&mut commands, &mut commands,
@ -53,7 +53,7 @@ pub fn fonts_ui(
); );
} }
AssetEvent::Modified { handle } => { AssetEvent::Modified { handle } => {
info!("Asset modified! {:?}", event); debug!("Font asset modified! {:?}", event);
destroy_asset_button( destroy_asset_button(
&current, &current,
&mut commands, &mut commands,
@ -74,7 +74,7 @@ pub fn fonts_ui(
}); });
} }
pub fn ui_control_font( fn ui_control_font(
events: Query< events: Query<
(&Interaction, &ui::TargetAsset<Font>, Option<&ui::Active>), (&Interaction, &ui::TargetAsset<Font>, Option<&ui::Active>),
(With<Button>, Changed<Interaction>), (With<Button>, Changed<Interaction>),
@ -95,7 +95,7 @@ pub fn ui_control_font(
}); });
} }
pub fn sync_font( fn sync_font(
query: Query<(Entity, &ui::TargetAsset<Font>)>, query: Query<(Entity, &ui::TargetAsset<Font>)>,
font: Res<FontInfo>, font: Res<FontInfo>,
mut commands: Commands, mut commands: Commands,

@ -1,79 +0,0 @@
use crate::editor::prelude::*;
#[derive(Debug, Default)]
pub struct EditorGltfPlugin;
impl Plugin for EditorGltfPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, sync_asset_buttons::<Gltf>)
.add_systems(Update, sync_remove_asset_buttons::<Gltf>)
.add_systems(Update, gltf_ui);
}
}
#[derive(Debug, Component, Default)]
pub struct GltfWidget;
pub fn gltf_ui(
mut events: EventReader<AssetEvent<Gltf>>,
mut commands: Commands,
widget: Query<Entity, With<GltfWidget>>,
current: Query<(Entity, &ui::TargetAsset<Gltf>)>,
server: Res<AssetServer>,
) {
events.iter().for_each(|event| match event {
AssetEvent::Created { handle } => {
info!("Asset created! {:?}", event);
create_asset_button(
&widget,
&mut commands,
ui::TargetAsset {
handle: handle.clone(),
},
get_asset_name(&server, handle.clone()),
None,
);
}
AssetEvent::Removed { handle } => {
info!("Asset removed! {:?}", event);
destroy_asset_button(
&current,
&mut commands,
&ui::TargetAsset {
handle: handle.clone(),
},
);
}
AssetEvent::Modified { handle } => {
info!("Asset modified! {:?}", event);
destroy_asset_button(
&current,
&mut commands,
&ui::TargetAsset {
handle: handle.clone(),
},
);
create_asset_button(
&widget,
&mut commands,
ui::TargetAsset {
handle: handle.clone(),
},
get_asset_name(&server, handle.clone()),
None,
);
}
});
}
pub fn control_active_gltf(
events: Query<Entity, (With<ui::TargetAsset<Gltf>>, Added<ui::Active>)>,
root: Query<Entity, With<LevelRoot>>,
mut commands: Commands,
) {
events.iter().for_each(|_| {
root.iter().for_each(|entity| {
commands.entity(entity).despawn_descendants();
});
});
}

@ -32,7 +32,7 @@ pub struct LevelWidget;
#[derive(Debug, Component)] #[derive(Debug, Component)]
pub struct ExportLevel; pub struct ExportLevel;
pub fn level_ui( fn level_ui(
mut events: EventReader<AssetEvent<Level>>, mut events: EventReader<AssetEvent<Level>>,
mut commands: Commands, mut commands: Commands,
widget: Query<Entity, With<LevelWidget>>, widget: Query<Entity, With<LevelWidget>>,
@ -41,7 +41,7 @@ pub fn level_ui(
) { ) {
events.iter().for_each(|event| match event { events.iter().for_each(|event| match event {
AssetEvent::Created { handle } => { AssetEvent::Created { handle } => {
info!("Asset created! {:?}", event); debug!("Level asset created! {:?}", event);
create_asset_button( create_asset_button(
&widget, &widget,
&mut commands, &mut commands,
@ -53,7 +53,7 @@ pub fn level_ui(
); );
} }
AssetEvent::Removed { handle } => { AssetEvent::Removed { handle } => {
info!("Asset removed! {:?}", event); debug!("Level asset removed! {:?}", event);
destroy_asset_button( destroy_asset_button(
&current, &current,
&mut commands, &mut commands,
@ -63,7 +63,7 @@ pub fn level_ui(
); );
} }
AssetEvent::Modified { handle } => { AssetEvent::Modified { handle } => {
info!("Asset modified! {:?}", event); debug!("Level asset modified! {:?}", event);
destroy_asset_button( destroy_asset_button(
&current, &current,
&mut commands, &mut commands,
@ -84,7 +84,7 @@ pub fn level_ui(
}); });
} }
pub fn load_level( fn load_level(
events: Query< events: Query<
&ui::TargetAsset<DynamicScene>, &ui::TargetAsset<DynamicScene>,
(Added<ui::Active>, With<ui::TargetAsset<DynamicScene>>), (Added<ui::Active>, With<ui::TargetAsset<DynamicScene>>),
@ -103,7 +103,7 @@ pub fn load_level(
}); });
} }
pub fn export_level( fn export_level(
level_root: Query<Entity, With<LevelRoot>>, level_root: Query<Entity, With<LevelRoot>>,
audio_root: Query<Entity, With<AudioRoot>>, audio_root: Query<Entity, With<AudioRoot>>,
children: Query<&Children>, children: Query<&Children>,
@ -176,7 +176,7 @@ pub fn export_level(
.detach(); .detach();
} }
pub fn rehydrate_level<W: Component, WO: Component + Default>( fn rehydrate_level<W: Component, WO: Component + Default>(
events: Query<Entity, (Added<W>, Without<WO>)>, events: Query<Entity, (Added<W>, Without<WO>)>,
mut commands: Commands, mut commands: Commands,
) { ) {
@ -188,7 +188,7 @@ pub fn rehydrate_level<W: Component, WO: Component + Default>(
#[derive(Debug, Component)] #[derive(Debug, Component)]
pub struct ClearLevel; pub struct ClearLevel;
pub fn clear_level( fn clear_level(
events: Query<Entity, (With<ClearLevel>, Added<ui::Active>)>, events: Query<Entity, (With<ClearLevel>, Added<ui::Active>)>,
actives: Query< actives: Query<
Entity, Entity,

@ -11,13 +11,13 @@ impl Plugin for EditorLightingPlugin {
} }
} }
pub fn spot_light_force_shadows(mut spot_lights: Query<&mut SpotLight, Added<SpotLight>>) { fn spot_light_force_shadows(mut spot_lights: Query<&mut SpotLight, Added<SpotLight>>) {
spot_lights.iter_mut().for_each(|mut light| { spot_lights.iter_mut().for_each(|mut light| {
light.shadows_enabled = true; light.shadows_enabled = true;
}) })
} }
pub fn directional_light_force_shadows( fn directional_light_force_shadows(
mut directional_lights: Query<&mut DirectionalLight, Added<DirectionalLight>>, mut directional_lights: Query<&mut DirectionalLight, Added<DirectionalLight>>,
) { ) {
directional_lights.iter_mut().for_each(|mut light| { directional_lights.iter_mut().for_each(|mut light| {
@ -25,7 +25,7 @@ pub fn directional_light_force_shadows(
}) })
} }
pub fn point_light_force_shadows(mut point_lights: Query<&mut PointLight, Added<PointLight>>) { fn point_light_force_shadows(mut point_lights: Query<&mut PointLight, Added<PointLight>>) {
point_lights.iter_mut().for_each(|mut light| { point_lights.iter_mut().for_each(|mut light| {
light.shadows_enabled = true; light.shadows_enabled = true;
}) })

@ -3,7 +3,6 @@ pub mod assets;
pub mod audio; pub mod audio;
pub mod camera; pub mod camera;
pub mod font; pub mod font;
pub mod gltf;
pub mod level; pub mod level;
pub mod lighting; pub mod lighting;
pub mod monologue; pub mod monologue;
@ -26,15 +25,11 @@ pub fn ui_active<T: Asset>(
buttons buttons
.iter() .iter()
.find_map(|(entity, ui::TargetAsset { handle })| { .find_map(|(entity, ui::TargetAsset { handle })| {
if handle == this_handle { (handle == this_handle).then_some(entity)
Some(entity)
} else {
None
}
}) })
.and_then(|entity| { .into_iter()
.for_each(|entity| {
commands.entity(entity).insert(ui::Active); commands.entity(entity).insert(ui::Active);
Some(())
}); });
}); });
} }
@ -48,12 +43,12 @@ pub fn ui_inactive<T: Asset>(
events.iter().for_each(|_| { events.iter().for_each(|_| {
targets targets
.iter() .iter()
.find_map(|(entity, ui::TargetAsset { handle })| { .filter_map(|(entity, ui::TargetAsset { handle })| {
(!sources.iter().any(|this_handle| this_handle == handle)).then_some(entity) (!sources.iter().any(|this_handle| this_handle == handle)).then_some(entity)
}) })
.and_then(|entity| { .for_each(|entity| {
debug!("handle entity remove Active {:?}", entity);
commands.entity(entity).remove::<ui::Active>(); commands.entity(entity).remove::<ui::Active>();
Some(())
}); });
}); });
} }
@ -156,8 +151,6 @@ fn initialize_ui(mut commands: Commands) {
.push(spawn_tab_container::<AudioWidget>("Audio", parent)); .push(spawn_tab_container::<AudioWidget>("Audio", parent));
content_containers content_containers
.push(spawn_tab_container::<LevelWidget>("Level", parent)); .push(spawn_tab_container::<LevelWidget>("Level", parent));
content_containers
.push(spawn_tab_container::<GltfWidget>("Gltf", parent));
content_containers content_containers
.push(spawn_tab_container::<SceneWidget>("Scene", parent)); .push(spawn_tab_container::<SceneWidget>("Scene", parent));
content_containers content_containers

@ -14,15 +14,16 @@ impl Plugin for EditorMonologuePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_asset::<Monologue>() app.add_asset::<Monologue>()
.init_asset_loader::<MonologueLoader>() .init_asset_loader::<MonologueLoader>()
.add_event::<ControlMonologue>()
.add_systems(Update, sync_asset_buttons::<Monologue>) .add_systems(Update, sync_asset_buttons::<Monologue>)
.add_systems(Update, sync_remove_asset_buttons::<Monologue>) .add_systems(Update, sync_remove_asset_buttons::<Monologue>)
.add_systems(Update, control_active_gltf)
.add_systems(Update, control_monologue) .add_systems(Update, control_monologue)
.add_systems(Update, ui_control_monologue) .add_systems(Update, ui_control_monologue)
.add_systems(Update, ui_active::<Monologue>) .add_systems(Update, ui_active::<Monologue>)
.add_systems(Update, ui_inactive::<Monologue>) .add_systems(Update, ui_inactive::<Monologue>)
.add_systems(Update, sync_monologue_font) .add_systems(Update, sync_monologue_font)
.add_event::<ControlMonologue>(); .add_systems(Startup, init_texts_ui)
.add_systems(Update, texts_ui);
} }
} }
@ -70,7 +71,7 @@ impl AssetLoader for MonologueLoader {
} }
} }
pub fn init_texts_ui(mut commands: Commands) { fn init_texts_ui(mut commands: Commands) {
commands.spawn(( commands.spawn((
NodeBundle { NodeBundle {
style: Style { style: Style {
@ -86,7 +87,7 @@ pub fn init_texts_ui(mut commands: Commands) {
)); ));
} }
pub fn texts_ui( fn texts_ui(
mut events: EventReader<AssetEvent<Monologue>>, mut events: EventReader<AssetEvent<Monologue>>,
mut commands: Commands, mut commands: Commands,
widget: Query<Entity, With<MonologueWidget>>, widget: Query<Entity, With<MonologueWidget>>,
@ -95,7 +96,7 @@ pub fn texts_ui(
) { ) {
events.iter().for_each(|event| match event { events.iter().for_each(|event| match event {
AssetEvent::Created { handle } => { AssetEvent::Created { handle } => {
info!("Monologue created! {:?}", event); debug!("Monologue created! {:?}", event);
create_asset_button( create_asset_button(
&widget, &widget,
&mut commands, &mut commands,
@ -107,7 +108,7 @@ pub fn texts_ui(
); );
} }
AssetEvent::Removed { handle } => { AssetEvent::Removed { handle } => {
info!("Monologue removed! {:?}", event); debug!("Monologue removed! {:?}", event);
destroy_asset_button( destroy_asset_button(
&current, &current,
&mut commands, &mut commands,
@ -117,7 +118,7 @@ pub fn texts_ui(
); );
} }
AssetEvent::Modified { handle } => { AssetEvent::Modified { handle } => {
info!("Monologue modified! {:?}", event); debug!("Monologue modified! {:?}", event);
destroy_asset_button( destroy_asset_button(
&current, &current,
&mut commands, &mut commands,
@ -138,7 +139,7 @@ pub fn texts_ui(
}); });
} }
pub fn control_monologue( fn control_monologue(
mut events: EventReader<ControlMonologue>, mut events: EventReader<ControlMonologue>,
monologues: Res<Assets<Monologue>>, monologues: Res<Assets<Monologue>>,
container: Query<Entity, With<MonologueContainer>>, container: Query<Entity, With<MonologueContainer>>,
@ -205,7 +206,7 @@ pub fn control_monologue(
}); });
} }
pub fn ui_control_monologue( fn ui_control_monologue(
events: Query< events: Query<
( (
&Interaction, &Interaction,
@ -231,10 +232,7 @@ pub fn ui_control_monologue(
} }
// TODO: Sync Handle<Monologue> and TextStyle components to automagically generate and sync text // TODO: Sync Handle<Monologue> and TextStyle components to automagically generate and sync text
pub fn sync_monologue_font( fn sync_monologue_font(mut texts: Query<&mut Text, With<Handle<Monologue>>>, font: Res<FontInfo>) {
mut texts: Query<&mut Text, With<Handle<Monologue>>>,
font: Res<FontInfo>,
) {
if font.is_changed() || font.is_added() { if font.is_changed() || font.is_added() {
texts.iter_mut().for_each(|mut text| { texts.iter_mut().for_each(|mut text| {
text.sections text.sections

@ -10,7 +10,6 @@ impl Plugin for EditorPlugin {
.add_plugins(EditorAudioPlugin::default()) .add_plugins(EditorAudioPlugin::default())
.add_plugins(EditorCameraPlugin::default()) .add_plugins(EditorCameraPlugin::default())
.add_plugins(EditorFontPlugin::default()) .add_plugins(EditorFontPlugin::default())
.add_plugins(EditorGltfPlugin::default())
.add_plugins(EditorLevelPlugin::default()) .add_plugins(EditorLevelPlugin::default())
.add_plugins(EditorLightingPlugin::default()) .add_plugins(EditorLightingPlugin::default())
.add_plugins(EditorMonologuePlugin::default()) .add_plugins(EditorMonologuePlugin::default())
@ -18,7 +17,6 @@ impl Plugin for EditorPlugin {
.add_plugins(EditorScenePlugin::default()) .add_plugins(EditorScenePlugin::default())
.add_plugins(EditorTimelinePlugin::default()) .add_plugins(EditorTimelinePlugin::default())
.add_systems(Startup, initialize_ui) .add_systems(Startup, initialize_ui)
.add_systems(Startup, init_texts_ui)
.add_systems(Startup, welcome_message); .add_systems(Startup, welcome_message);
} }
} }

@ -1,7 +1,7 @@
pub use crate::{ pub use crate::{
editor::{ editor::{
animation::*, assets::*, audio::*, camera::*, font::*, gltf::*, level::*, lighting::*, animation::*, assets::*, audio::*, camera::*, font::*, level::*, lighting::*, monologue::*,
monologue::*, quit::*, scene::*, timeline::*, *, quit::*, scene::*, timeline::*, *,
}, },
ui, ui,
}; };

@ -14,6 +14,6 @@ impl Plugin for EditorQuitPlugin {
#[derive(Debug, Component, Default)] #[derive(Debug, Component, Default)]
pub struct QuitAction; pub struct QuitAction;
pub fn quit(mut exit: EventWriter<AppExit>) { fn quit(mut exit: EventWriter<AppExit>) {
exit.send(AppExit); exit.send(AppExit);
} }

@ -5,41 +5,59 @@ pub struct EditorScenePlugin;
impl Plugin for EditorScenePlugin { impl Plugin for EditorScenePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Update, remove_scenes_ui) app.add_event::<ControlScene>()
.add_systems(Update, add_scenes_ui)
.add_systems(Update, control_active_scenes)
.add_systems(Update, sync_asset_buttons::<Scene>) .add_systems(Update, sync_asset_buttons::<Scene>)
.add_systems(Update, sync_remove_asset_buttons::<Scene>); .add_systems(Update, sync_remove_asset_buttons::<Scene>)
.add_systems(Update, ui_active::<Scene>)
.add_systems(Update, ui_inactive::<Scene>)
.add_systems(Update, add_scenes_ui)
.add_systems(Update, remove_scenes_ui)
.add_systems(Update, control_scene)
.add_systems(Update, ui_control_scene);
} }
} }
#[derive(Debug, Event)]
pub enum ControlScene {
Spawn(Handle<Scene>),
Despawn(Handle<Scene>),
}
#[derive(Debug, Component, Default)] #[derive(Debug, Component, Default)]
pub struct SceneWidget; pub struct SceneWidget;
pub fn add_scenes_ui( fn add_scenes_ui(
gltf_selected: Query<&ui::TargetAsset<Gltf>, Added<ui::Active>>, mut events: EventReader<AssetEvent<Gltf>>,
mut commands: Commands, mut commands: Commands,
gltfs: Res<Assets<Gltf>>, gltfs: Res<Assets<Gltf>>,
widget: Query<Entity, With<SceneWidget>>, widget: Query<Entity, With<SceneWidget>>,
server: Res<AssetServer>,
) { ) {
gltf_selected.iter().for_each(|ui::TargetAsset { handle }| { events
if let Some(gltf) = gltfs.get(&handle.clone()) { .iter()
gltf.named_scenes.iter().for_each(|(name, handle)| { .filter_map(|event| match event {
create_asset_button( AssetEvent::Created { handle } => Some(handle),
&widget, _ => None,
&mut commands, })
ui::TargetAsset { .for_each(|handle| {
handle: handle.clone(), let gltf_name = get_asset_name(&server, handle.clone());
}, if let Some(gltf) = gltfs.get(&handle.clone()) {
name.clone(), gltf.named_scenes.iter().for_each(|(name, handle)| {
None, create_asset_button(
); &widget,
}) &mut commands,
} ui::TargetAsset {
}); handle: handle.clone(),
},
format!("({}) {}", gltf_name, name),
None,
);
})
}
});
} }
pub fn remove_scenes_ui( fn remove_scenes_ui(
mut gltf_unselected: RemovedComponents<ui::Active>, mut gltf_unselected: RemovedComponents<ui::Active>,
target_assets: Query<&ui::TargetAsset<Gltf>>, target_assets: Query<&ui::TargetAsset<Gltf>>,
current: Query<(Entity, &ui::TargetAsset<Scene>)>, current: Query<(Entity, &ui::TargetAsset<Scene>)>,
@ -63,44 +81,48 @@ pub fn remove_scenes_ui(
}); });
} }
pub fn control_active_scenes( fn control_scene(
added: Query<Entity, (With<Button>, Added<ui::Active>)>, mut events: EventReader<ControlScene>,
mut removed: RemovedComponents<ui::Active>, root: Query<Entity, With<LevelRoot>>,
scene_refs: Query<&ui::TargetAsset<Scene>>,
scenes: Query<(Entity, &Handle<Scene>)>, scenes: Query<(Entity, &Handle<Scene>)>,
level_root: Query<Entity, With<LevelRoot>>,
mut commands: Commands, mut commands: Commands,
) { ) {
// A scene button was marked inactive events.iter().for_each(|event| match event {
removed.iter().for_each(|entity| { ControlScene::Spawn(handle) => {
// Get the handle associated with that button commands.entity(root.single()).with_children(|parent| {
scene_refs parent.spawn(SceneBundle {
.get(entity) scene: handle.clone(),
.iter() ..default()
.for_each(|ui::TargetAsset { handle }| { });
scenes
.iter()
.find_map(|(entity, this_handle)| (this_handle == handle).then_some(entity))
.iter()
.for_each(|&entity| {
commands.entity(entity).despawn_recursive();
});
});
});
added.iter().for_each(|entity| {
scene_refs
.get(entity)
.iter()
.for_each(|ui::TargetAsset { handle }| {
info!("Spawning Scene {:?}", handle);
commands
.entity(level_root.single())
.with_children(|parent| {
parent.spawn(SceneBundle {
scene: handle.clone(),
..default()
});
});
}); });
}
ControlScene::Despawn(handle) => {
scenes
.iter()
.find_map(|(entity, this_handle)| (handle == this_handle).then_some(entity))
.into_iter()
.for_each(|entity| commands.entity(entity).despawn_recursive());
}
}); });
} }
fn ui_control_scene(
events: Query<
(&Interaction, &ui::TargetAsset<Scene>, Option<&ui::Active>),
(With<Button>, Changed<Interaction>),
>,
mut writer: EventWriter<ControlScene>,
) {
events
.iter()
.filter_map(
|(interaction, ui::TargetAsset { handle }, active)| match interaction {
Interaction::Pressed => Some((handle, active)),
_ => None,
},
)
.for_each(|(handle, active)| match active {
Some(_) => writer.send(ControlScene::Despawn(handle.clone())),
None => writer.send(ControlScene::Spawn(handle.clone())),
});
}

@ -19,7 +19,9 @@ impl Plugin for EditorTimelinePlugin {
.add_systems(Update, set_epoch_font) .add_systems(Update, set_epoch_font)
.add_systems(Update, load_epoch_font) .add_systems(Update, load_epoch_font)
.add_systems(Update, set_epoch_sfx) .add_systems(Update, set_epoch_sfx)
.add_systems(Update, load_epoch_sfx); .add_systems(Update, load_epoch_sfx)
.add_systems(Update, set_epoch_animations)
.add_systems(Update, load_epoch_animations);
} }
} }
@ -87,7 +89,7 @@ pub struct EpochAnimations {
/// System for adding an epoch to the level's timeline /// System for adding an epoch to the level's timeline
/// Triggered when a button with the AddEpoch marker is Active /// Triggered when a button with the AddEpoch marker is Active
pub fn add_timeline_epoch( fn add_timeline_epoch(
root: Query<(Entity, &Children), With<TimelineWidget>>, root: Query<(Entity, &Children), With<TimelineWidget>>,
mut commands: Commands, mut commands: Commands,
) { ) {
@ -119,7 +121,7 @@ pub fn add_timeline_epoch(
} }
/// Set the GLTF for the current epoch /// Set the GLTF for the current epoch
pub fn set_epoch_gltf( fn set_epoch_gltf(
events: Query<&ui::TargetAsset<Gltf>, Added<ui::Active>>, events: Query<&ui::TargetAsset<Gltf>, Added<ui::Active>>,
active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>, active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>,
mut commands: Commands, mut commands: Commands,
@ -138,13 +140,13 @@ pub fn set_epoch_gltf(
}); });
} }
pub fn load_epoch_gltf(events: Query<Option<&EpochGltf>, (Added<ui::Active>, With<EpochId>)>) { fn load_epoch_gltf(events: Query<Option<&EpochGltf>, (Added<ui::Active>, With<EpochId>)>) {
events.iter().for_each(|epoch_gltf| { events.iter().for_each(|epoch_gltf| {
warn!("TODO: Load epoch GLTF!"); warn!("TODO: Load epoch GLTF!");
}) })
} }
pub fn set_epoch_scene( fn set_epoch_scene(
events: Query<&ui::TargetAsset<Scene>, Added<ui::Active>>, events: Query<&ui::TargetAsset<Scene>, Added<ui::Active>>,
active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>, active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>,
mut commands: Commands, mut commands: Commands,
@ -161,13 +163,13 @@ pub fn set_epoch_scene(
}); });
} }
pub fn load_epoch_scene(events: Query<Option<&EpochScene>, (Added<ui::Active>, With<EpochId>)>) { fn load_epoch_scene(events: Query<Option<&EpochScene>, (Added<ui::Active>, With<EpochId>)>) {
events.iter().for_each(|epoch_scene| { events.iter().for_each(|epoch_scene| {
warn!("TODO: Load epoch Scene!"); warn!("TODO: Load epoch Scene!");
}) })
} }
pub fn set_epoch_camera( fn set_epoch_camera(
events: Query<&ui::TargetEntity, Added<ui::Active>>, events: Query<&ui::TargetEntity, Added<ui::Active>>,
active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>, active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>,
mut commands: Commands, mut commands: Commands,
@ -184,13 +186,13 @@ pub fn set_epoch_camera(
}); });
} }
pub fn load_epoch_camera(events: Query<Option<&EpochCamera>, (Added<ui::Active>, With<EpochId>)>) { fn load_epoch_camera(events: Query<Option<&EpochCamera>, (Added<ui::Active>, With<EpochId>)>) {
events.iter().for_each(|epoch_camera| { events.iter().for_each(|epoch_camera| {
warn!("TODO: Load epoch Camera"); warn!("TODO: Load epoch Camera");
}) })
} }
pub fn set_epoch_music( fn set_epoch_music(
events: Query<&ui::TargetAsset<AudioSource>, Added<ui::Active>>, events: Query<&ui::TargetAsset<AudioSource>, Added<ui::Active>>,
active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>, active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>,
mut commands: Commands, mut commands: Commands,
@ -207,13 +209,13 @@ pub fn set_epoch_music(
}); });
} }
pub fn load_epoch_music(events: Query<Option<&EpochMusic>, (Added<ui::Active>, With<EpochId>)>) { fn load_epoch_music(events: Query<Option<&EpochMusic>, (Added<ui::Active>, With<EpochId>)>) {
events.iter().for_each(|epoch_music| { events.iter().for_each(|epoch_music| {
warn!("TODO: Load epoch music!"); warn!("TODO: Load epoch music!");
}) })
} }
pub fn set_epoch_monologue( fn set_epoch_monologue(
events: Query<&ui::TargetAsset<Monologue>, Added<ui::Active>>, events: Query<&ui::TargetAsset<Monologue>, Added<ui::Active>>,
active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>, active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>,
mut commands: Commands, mut commands: Commands,
@ -230,7 +232,7 @@ pub fn set_epoch_monologue(
}); });
} }
pub fn load_epoch_monologue( fn load_epoch_monologue(
events: Query<Option<&EpochMonologue>, (Added<ui::Active>, With<EpochId>)>, events: Query<Option<&EpochMonologue>, (Added<ui::Active>, With<EpochId>)>,
) { ) {
events.iter().for_each(|epoch_monologue| { events.iter().for_each(|epoch_monologue| {
@ -243,7 +245,7 @@ pub fn load_epoch_monologue(
}); });
} }
pub fn set_epoch_font( fn set_epoch_font(
events: Query<&ui::TargetAsset<Font>, Added<ui::Active>>, events: Query<&ui::TargetAsset<Font>, Added<ui::Active>>,
active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>, active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>,
mut commands: Commands, mut commands: Commands,
@ -260,7 +262,7 @@ pub fn set_epoch_font(
}); });
} }
pub fn load_epoch_font( fn load_epoch_font(
events: Query<Option<&EpochFont>, (Added<ui::Active>, With<EpochId>)>, events: Query<Option<&EpochFont>, (Added<ui::Active>, With<EpochId>)>,
mut font_info: ResMut<FontInfo>, mut font_info: ResMut<FontInfo>,
) { ) {
@ -269,7 +271,7 @@ pub fn load_epoch_font(
}); });
} }
pub fn set_epoch_sfx( fn set_epoch_sfx(
events: Query<&ui::TargetAsset<AudioSource>, Added<ui::Active>>, events: Query<&ui::TargetAsset<AudioSource>, Added<ui::Active>>,
mut active_epoch: Query<(Entity, Option<&mut EpochSfx>), (With<ui::Active>, With<EpochId>)>, mut active_epoch: Query<(Entity, Option<&mut EpochSfx>), (With<ui::Active>, With<EpochId>)>,
mut commands: Commands, mut commands: Commands,
@ -291,7 +293,7 @@ pub fn set_epoch_sfx(
}); });
} }
pub fn load_epoch_sfx( fn load_epoch_sfx(
added: Query<Entity, (Added<ui::Active>, With<EpochId>)>, added: Query<Entity, (Added<ui::Active>, With<EpochId>)>,
mut removed: RemovedComponents<ui::Active>, mut removed: RemovedComponents<ui::Active>,
epoch_sfx: Query<&EpochSfx>, epoch_sfx: Query<&EpochSfx>,
@ -313,7 +315,7 @@ pub fn load_epoch_sfx(
}); });
} }
pub fn set_epoch_animations( fn set_epoch_animations(
events: Query<&ui::TargetAsset<AnimationClip>, Added<ui::Active>>, events: Query<&ui::TargetAsset<AnimationClip>, Added<ui::Active>>,
mut active_epoch: Query< mut active_epoch: Query<
(Entity, Option<&mut EpochAnimations>), (Entity, Option<&mut EpochAnimations>),
@ -339,7 +341,7 @@ pub fn set_epoch_animations(
}); });
} }
pub fn load_epoch_animations( fn load_epoch_animations(
events: Query<Option<&EpochAnimations>, (Added<ui::Active>, With<EpochId>)>, events: Query<Option<&EpochAnimations>, (Added<ui::Active>, With<EpochId>)>,
) { ) {
events.iter().for_each(|epoch_animations| { events.iter().for_each(|epoch_animations| {

@ -367,17 +367,11 @@ mod collapse {
events.iter().for_each(|(entity, children)| { events.iter().for_each(|(entity, children)| {
// Find any tabs which have this as a target // Find any tabs which have this as a target
tabs.iter_mut() tabs.iter_mut()
.find_map(|(button, collapse)| { .find_map(|(button, collapse)| (entity == collapse.target).then_some(button))
if entity == collapse.target { .into_iter()
Some(button)
} else {
None
}
})
.iter()
.for_each(|button| { .for_each(|button| {
let num_children = children.len(); let num_children = children.len();
commands.entity(*button).insert(Note { commands.entity(button).insert(Note {
text: format!("({})", num_children), text: format!("({})", num_children),
}); });
}); });

Loading…
Cancel
Save