|
|
|
@ -1,3 +1,5 @@
|
|
|
|
|
|
|
|
use bevy::reflect::{TypePath, TypeUuid};
|
|
|
|
|
|
|
|
|
|
|
|
use crate::editor::prelude::*;
|
|
|
|
use crate::editor::prelude::*;
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Default)]
|
|
|
|
#[derive(Debug, Default)]
|
|
|
|
@ -6,23 +8,17 @@ pub struct EditorTimelinePlugin;
|
|
|
|
impl Plugin for EditorTimelinePlugin {
|
|
|
|
impl Plugin for EditorTimelinePlugin {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
app.add_systems(Update, add_timeline_epoch.run_if(ui::activated::<AddEpoch>))
|
|
|
|
app.add_systems(Update, add_timeline_epoch.run_if(ui::activated::<AddEpoch>))
|
|
|
|
.add_systems(Update, set_epoch_gltf)
|
|
|
|
.add_systems(Update, control_active_epoch);
|
|
|
|
.add_systems(Update, load_epoch_gltf)
|
|
|
|
}
|
|
|
|
.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);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(
|
|
|
|
|
|
|
|
Debug, Component, Resource, Clone, Default, TypeUuid, Deserialize, TypePath, FromReflect,
|
|
|
|
|
|
|
|
)]
|
|
|
|
|
|
|
|
#[uuid = "959f5f02-7c80-4b3d-ad02-9dc2e5d1b963"]
|
|
|
|
|
|
|
|
pub struct Epoch {
|
|
|
|
|
|
|
|
id: usize,
|
|
|
|
|
|
|
|
scene: DynamicScene,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Timeline widget marker
|
|
|
|
/// Timeline widget marker
|
|
|
|
@ -33,58 +29,13 @@ pub struct TimelineWidget;
|
|
|
|
#[derive(Debug, Component)]
|
|
|
|
#[derive(Debug, Component)]
|
|
|
|
pub struct AddEpoch;
|
|
|
|
pub struct AddEpoch;
|
|
|
|
|
|
|
|
|
|
|
|
/// Epoch ID Component
|
|
|
|
fn control_active_epoch(
|
|
|
|
#[derive(Debug, Reflect, Component, Clone)]
|
|
|
|
events: Query<(Entity, &Epoch), Added<ui::Active>>,
|
|
|
|
pub struct EpochId {
|
|
|
|
mut commands: Commands,
|
|
|
|
id: usize,
|
|
|
|
) {
|
|
|
|
}
|
|
|
|
events.iter().for_each(|(entity, epoch)| {
|
|
|
|
|
|
|
|
commands.insert_resource(epoch.clone());
|
|
|
|
/// Epoch GLTF Component
|
|
|
|
});
|
|
|
|
#[derive(Debug, Reflect, Component, Clone)]
|
|
|
|
|
|
|
|
pub struct EpochGltf {
|
|
|
|
|
|
|
|
gltf: Handle<Gltf>,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// 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>>,
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// System for adding an epoch to the level's timeline
|
|
|
|
/// System for adding an epoch to the level's timeline
|
|
|
|
@ -114,237 +65,8 @@ fn add_timeline_epoch(
|
|
|
|
text: name,
|
|
|
|
text: name,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
EpochId { id },
|
|
|
|
Epoch { id, ..default() },
|
|
|
|
));
|
|
|
|
));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Set the GLTF for the current epoch
|
|
|
|
|
|
|
|
fn set_epoch_gltf(
|
|
|
|
|
|
|
|
events: Query<&ui::TargetAsset<Gltf>, Added<ui::Active>>,
|
|
|
|
|
|
|
|
active_epoch: Query<Entity, (With<ui::Active>, With<EpochId>)>,
|
|
|
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
// Each time a GLTF 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 GLTF (overwrite existing GLTF selections)
|
|
|
|
|
|
|
|
commands.entity(entity).insert(EpochGltf {
|
|
|
|
|
|
|
|
gltf: handle.clone(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Unset Scene, Camera, Animations
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn load_epoch_gltf(events: Query<Option<&EpochGltf>, (Added<ui::Active>, With<EpochId>)>) {
|
|
|
|
|
|
|
|
events.iter().for_each(|epoch_gltf| {
|
|
|
|
|
|
|
|
warn!("TODO: Load epoch GLTF!");
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn set_epoch_scene(
|
|
|
|
|
|
|
|
events: Query<&ui::TargetAsset<Scene>, 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(EpochScene {
|
|
|
|
|
|
|
|
scene: handle.clone(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn load_epoch_scene(events: Query<Option<&EpochScene>, (Added<ui::Active>, With<EpochId>)>) {
|
|
|
|
|
|
|
|
events.iter().for_each(|epoch_scene| {
|
|
|
|
|
|
|
|
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(events: Query<Option<&EpochCamera>, (Added<ui::Active>, With<EpochId>)>) {
|
|
|
|
|
|
|
|
events.iter().for_each(|epoch_camera| {
|
|
|
|
|
|
|
|
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(events: Query<Option<&EpochMusic>, (Added<ui::Active>, With<EpochId>)>) {
|
|
|
|
|
|
|
|
events.iter().for_each(|epoch_music| {
|
|
|
|
|
|
|
|
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(
|
|
|
|
|
|
|
|
events: Query<&ui::TargetAsset<AudioSource>, Added<ui::Active>>,
|
|
|
|
|
|
|
|
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(|ui::TargetAsset { handle }| {
|
|
|
|
|
|
|
|
// Iterate over all (0 or 1) active epochs
|
|
|
|
|
|
|
|
active_epoch.iter_mut().for_each(|(entity, maybe_sfx)| {
|
|
|
|
|
|
|
|
info!("Adding sfx {:?} to epoch {:?}", maybe_sfx, 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()],
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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!");
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|