|
|
|
|
@ -6,21 +6,7 @@ pub struct EditorTimelinePlugin;
|
|
|
|
|
impl Plugin for EditorTimelinePlugin {
|
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
|
app.add_systems(Update, add_timeline_epoch.run_if(ui::activated::<AddEpoch>))
|
|
|
|
|
.add_systems(Update, control_active_epoch)
|
|
|
|
|
.add_systems(Update, set_epoch_scene)
|
|
|
|
|
.add_systems(Update, load_epoch_scene)
|
|
|
|
|
.add_systems(Update, set_epoch_camera)
|
|
|
|
|
.add_systems(Update, load_epoch_camera)
|
|
|
|
|
.add_systems(Update, set_epoch_music)
|
|
|
|
|
.add_systems(Update, load_epoch_music)
|
|
|
|
|
.add_systems(Update, set_epoch_monologue)
|
|
|
|
|
.add_systems(Update, load_epoch_monologue)
|
|
|
|
|
.add_systems(Update, set_epoch_font)
|
|
|
|
|
.add_systems(Update, load_epoch_font)
|
|
|
|
|
.add_systems(Update, set_epoch_sfx)
|
|
|
|
|
.add_systems(Update, load_epoch_sfx)
|
|
|
|
|
.add_systems(Update, set_epoch_animations)
|
|
|
|
|
.add_systems(Update, load_epoch_animations);
|
|
|
|
|
.add_systems(Update, control_active_epoch);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -40,57 +26,24 @@ pub struct AddEpoch;
|
|
|
|
|
|
|
|
|
|
/// Epoch ID Component
|
|
|
|
|
#[derive(Debug, Reflect, Component, Clone)]
|
|
|
|
|
pub struct EpochId {
|
|
|
|
|
struct EpochId {
|
|
|
|
|
id: usize,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Epoch Scene Component
|
|
|
|
|
#[derive(Debug, Reflect, Component, Clone)]
|
|
|
|
|
pub struct EpochScene {
|
|
|
|
|
scene: Handle<Scene>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Epoch Camera Component, marking the current camera
|
|
|
|
|
#[derive(Debug, Reflect, Component, Clone)]
|
|
|
|
|
pub struct EpochCamera {
|
|
|
|
|
camera: Entity,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Epoch music component, marking the opening track for this epoch
|
|
|
|
|
#[derive(Debug, Reflect, Default, Component, Clone)]
|
|
|
|
|
pub struct EpochMusic {
|
|
|
|
|
music: Handle<AudioSource>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Epoch monologue, marking the dialog spoken this epoch
|
|
|
|
|
#[derive(Debug, Reflect, Component, Clone)]
|
|
|
|
|
pub struct EpochMonologue {
|
|
|
|
|
monologue: Handle<Monologue>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Epoch font, marking the font used for this epoch's monologue
|
|
|
|
|
#[derive(Debug, Reflect, Component, Clone)]
|
|
|
|
|
pub struct EpochFont {
|
|
|
|
|
font: Handle<Font>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A vector of audios looping this epoch as background tracks
|
|
|
|
|
#[derive(Debug, Reflect, Component, Clone)]
|
|
|
|
|
pub struct EpochSfx {
|
|
|
|
|
sfx: Vec<Handle<AudioSource>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Epoch animations, looping this epoch
|
|
|
|
|
#[derive(Debug, Reflect, Component, Clone)]
|
|
|
|
|
pub struct EpochAnimations {
|
|
|
|
|
animations: Vec<Handle<AnimationClip>>,
|
|
|
|
|
}
|
|
|
|
|
#[derive(Component)]
|
|
|
|
|
struct EpochScene(DynamicScene);
|
|
|
|
|
|
|
|
|
|
fn control_active_epoch(
|
|
|
|
|
events: Query<(Entity, &EpochId), Added<ui::Active>>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
level_root: Query<Entity, With<LevelRoot>>,
|
|
|
|
|
audio_root: Query<Entity, With<AudioRoot>>,
|
|
|
|
|
children: Query<&Children>,
|
|
|
|
|
world: &World,
|
|
|
|
|
) {
|
|
|
|
|
events.iter().for_each(|(entity, &ref id)| {
|
|
|
|
|
let scene = export_level_state(&level_root, &audio_root, &children, world);
|
|
|
|
|
commands.entity(entity).insert(EpochScene(scene));
|
|
|
|
|
commands.insert_resource(ActiveEpoch {
|
|
|
|
|
id: id.clone(),
|
|
|
|
|
entity,
|
|
|
|
|
@ -130,226 +83,3 @@ fn add_timeline_epoch(
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_epoch_scene(
|
|
|
|
|
mut events: EventReader<ControlScene>,
|
|
|
|
|
active_epoch: Option<Res<ActiveEpoch>>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
// Each time a Scene is selected in the editor
|
|
|
|
|
events.iter().for_each(|event| {
|
|
|
|
|
active_epoch.iter().for_each(|active| {
|
|
|
|
|
match event {
|
|
|
|
|
ControlScene::Spawn(handle) => {
|
|
|
|
|
// Set the Scene (overwrite existing Scene selections)
|
|
|
|
|
commands.entity(active.entity).insert(EpochScene {
|
|
|
|
|
scene: handle.clone(),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
ControlScene::Despawn(_) => (),
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn load_epoch_scene(active_epoch: Option<Res<ActiveEpoch>>) {
|
|
|
|
|
if let Some(active) = active_epoch {
|
|
|
|
|
if active.is_added() || active.is_changed() {
|
|
|
|
|
warn!("TODO: Load epoch Scene!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_epoch_camera(
|
|
|
|
|
events: Query<&ui::TargetEntity, Added<ui::Active>>,
|
|
|
|
|
active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
// Each time a Scene is selected in the editor
|
|
|
|
|
events.iter().for_each(|ui::TargetEntity { entity }| {
|
|
|
|
|
// Iterate over all (0 or 1) active epochs
|
|
|
|
|
active_epoch.iter().for_each(|this_entity| {
|
|
|
|
|
// Set the Scene (overwrite existing Scene selections)
|
|
|
|
|
commands
|
|
|
|
|
.entity(this_entity)
|
|
|
|
|
.insert(EpochCamera { camera: *entity });
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn load_epoch_camera(active_epoch: Option<Res<ActiveEpoch>>) {
|
|
|
|
|
if let Some(active) = active_epoch {
|
|
|
|
|
if active.is_added() || active.is_changed() {
|
|
|
|
|
warn!("TODO: Load epoch Camera");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_epoch_music(
|
|
|
|
|
events: Query<&ui::TargetAsset<AudioSource>, Added<ui::Active>>,
|
|
|
|
|
active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
// Each time a Scene is selected in the editor
|
|
|
|
|
events.iter().for_each(|ui::TargetAsset { handle }| {
|
|
|
|
|
info!("TODO: Select scene music");
|
|
|
|
|
|
|
|
|
|
// // Iterate over all (0 or 1) active epochs
|
|
|
|
|
// active_epoch.iter().for_each(|entity| {
|
|
|
|
|
// // Set the Scene (overwrite existing Scene selections)
|
|
|
|
|
// commands.entity(entity).insert(EpochMusic { music: handle.clone() });
|
|
|
|
|
// });
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn load_epoch_music(active_epoch: Option<Res<ActiveEpoch>>) {
|
|
|
|
|
if let Some(active) = active_epoch {
|
|
|
|
|
if active.is_added() || active.is_changed() {
|
|
|
|
|
warn!("TODO: Load epoch music!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_epoch_monologue(
|
|
|
|
|
events: Query<&ui::TargetAsset<Monologue>, Added<ui::Active>>,
|
|
|
|
|
active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
// Each time a Scene is selected in the editor
|
|
|
|
|
events.iter().for_each(|ui::TargetAsset { handle }| {
|
|
|
|
|
// Iterate over all (0 or 1) active epochs
|
|
|
|
|
active_epoch.iter().for_each(|entity| {
|
|
|
|
|
// Set the Scene (overwrite existing Scene selections)
|
|
|
|
|
commands.entity(entity).insert(EpochMonologue {
|
|
|
|
|
monologue: handle.clone(),
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn load_epoch_monologue(
|
|
|
|
|
events: Query<Option<&EpochMonologue>, (Added<ui::Active>, With<EpochId>)>,
|
|
|
|
|
) {
|
|
|
|
|
events.iter().for_each(|epoch_monologue| {
|
|
|
|
|
warn!("TODO: unset epoch Monologue!");
|
|
|
|
|
epoch_monologue
|
|
|
|
|
.iter()
|
|
|
|
|
.for_each(|EpochMonologue { monologue }| {
|
|
|
|
|
warn!("TODO: Set level epoch");
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_epoch_font(
|
|
|
|
|
events: Query<&ui::TargetAsset<Font>, Added<ui::Active>>,
|
|
|
|
|
active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
// Each time a Scene is selected in the editor
|
|
|
|
|
events.iter().for_each(|ui::TargetAsset { handle }| {
|
|
|
|
|
// Iterate over all (0 or 1) active epochs
|
|
|
|
|
active_epoch.iter().for_each(|entity| {
|
|
|
|
|
// Set the Scene (overwrite existing Scene selections)
|
|
|
|
|
commands.entity(entity).insert(EpochFont {
|
|
|
|
|
font: handle.clone(),
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn load_epoch_font(
|
|
|
|
|
events: Query<Option<&EpochFont>, (Added<ui::Active>, With<EpochId>)>,
|
|
|
|
|
mut font_info: ResMut<FontInfo>,
|
|
|
|
|
) {
|
|
|
|
|
events.iter().for_each(|epoch_font| {
|
|
|
|
|
font_info.default = epoch_font.map(|EpochFont { font }| font.clone());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_epoch_sfx(
|
|
|
|
|
mut events: EventReader<ControlAudio>,
|
|
|
|
|
mut active_epoch: Query<(Entity, Option<&mut EpochSfx>), (With<ui::Active>, With<EpochId>)>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
// Each time a Scene is selected in the editor
|
|
|
|
|
events.iter().for_each(|event| {
|
|
|
|
|
// Iterate over all (0 or 1) active epochs
|
|
|
|
|
active_epoch.iter_mut().for_each(|(entity, maybe_sfx)| {
|
|
|
|
|
match event {
|
|
|
|
|
ControlAudio::Loop(handle) => {
|
|
|
|
|
debug!("Adding sfx {:?} to epoch {:?}", handle, entity);
|
|
|
|
|
if let Some(mut epoch_sfx) = maybe_sfx {
|
|
|
|
|
epoch_sfx.sfx.push(handle.clone());
|
|
|
|
|
} else {
|
|
|
|
|
// Set the Scene (overwrite existing Scene selections)
|
|
|
|
|
commands.entity(entity).insert(EpochSfx {
|
|
|
|
|
sfx: vec![handle.clone()],
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ControlAudio::Stop(handle) => {
|
|
|
|
|
if let Some(mut epoch_sfx) = maybe_sfx {
|
|
|
|
|
debug!("Removing sfx {:?} from epoch {:?}", handle, entity);
|
|
|
|
|
epoch_sfx.sfx.retain(|element| element != handle);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn load_epoch_sfx(
|
|
|
|
|
added: Query<Entity, (Added<ui::Active>, With<EpochId>)>,
|
|
|
|
|
mut removed: RemovedComponents<ui::Active>,
|
|
|
|
|
epoch_sfx: Query<&EpochSfx>,
|
|
|
|
|
mut writer: EventWriter<ControlAudio>,
|
|
|
|
|
) {
|
|
|
|
|
removed.iter().for_each(|entity| {
|
|
|
|
|
epoch_sfx.get(entity).iter().for_each(|EpochSfx { sfx }| {
|
|
|
|
|
sfx.iter().for_each(|handle| {
|
|
|
|
|
writer.send(ControlAudio::Stop(handle.clone()));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
added.iter().for_each(|entity| {
|
|
|
|
|
epoch_sfx.get(entity).iter().for_each(|EpochSfx { sfx }| {
|
|
|
|
|
sfx.iter().for_each(|handle| {
|
|
|
|
|
writer.send(ControlAudio::Loop(handle.clone()));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_epoch_animations(
|
|
|
|
|
events: Query<&ui::TargetAsset<AnimationClip>, Added<ui::Active>>,
|
|
|
|
|
mut active_epoch: Query<
|
|
|
|
|
(Entity, Option<&mut EpochAnimations>),
|
|
|
|
|
(With<ui::Active>, With<EpochId>),
|
|
|
|
|
>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
// Each time a Scene is selected in the editor
|
|
|
|
|
events.iter().for_each(|ui::TargetAsset { handle }| {
|
|
|
|
|
// Iterate over all (0 or 1) active epochs
|
|
|
|
|
active_epoch
|
|
|
|
|
.iter_mut()
|
|
|
|
|
.for_each(|(entity, maybe_animations)| {
|
|
|
|
|
if let Some(mut epoch_animations) = maybe_animations {
|
|
|
|
|
epoch_animations.animations.push(handle.clone());
|
|
|
|
|
} else {
|
|
|
|
|
// Set the Scene (overwrite existing Scene selections)
|
|
|
|
|
commands.entity(entity).insert(EpochAnimations {
|
|
|
|
|
animations: vec![handle.clone()],
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn load_epoch_animations(
|
|
|
|
|
events: Query<Option<&EpochAnimations>, (Added<ui::Active>, With<EpochId>)>,
|
|
|
|
|
) {
|
|
|
|
|
events.iter().for_each(|epoch_animations| {
|
|
|
|
|
warn!("TODO: Load epoch Animations!");
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|