|
|
|
@ -64,6 +64,7 @@ fn main() {
|
|
|
|
.init_resource::<FontInfo>()
|
|
|
|
.init_resource::<FontInfo>()
|
|
|
|
.add_asset::<Monologue>()
|
|
|
|
.add_asset::<Monologue>()
|
|
|
|
.init_asset_loader::<MonologueLoader>()
|
|
|
|
.init_asset_loader::<MonologueLoader>()
|
|
|
|
|
|
|
|
.add_event::<ControlAudio>()
|
|
|
|
.add_systems(Startup, (initialize_ui, init_texts_ui, welcome_message))
|
|
|
|
.add_systems(Startup, (initialize_ui, init_texts_ui, welcome_message))
|
|
|
|
.add_systems(Update, quit.run_if(ui::activated::<QuitAction>))
|
|
|
|
.add_systems(Update, quit.run_if(ui::activated::<QuitAction>))
|
|
|
|
.add_systems(
|
|
|
|
.add_systems(
|
|
|
|
@ -81,7 +82,7 @@ fn main() {
|
|
|
|
(remove_scenes_ui, add_scenes_ui, control_active_scenes),
|
|
|
|
(remove_scenes_ui, add_scenes_ui, control_active_scenes),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.add_systems(Update, (cameras_ui, manage_active_camera, fallback_camera))
|
|
|
|
.add_systems(Update, (cameras_ui, manage_active_camera, fallback_camera))
|
|
|
|
.add_systems(Update, (audio_ui, play_audio, pause_audio))
|
|
|
|
.add_systems(Update, (audio_ui, play_audio, pause_audio, control_audio))
|
|
|
|
.add_systems(
|
|
|
|
.add_systems(
|
|
|
|
Update,
|
|
|
|
Update,
|
|
|
|
(
|
|
|
|
(
|
|
|
|
@ -126,12 +127,41 @@ fn main() {
|
|
|
|
Update,
|
|
|
|
Update,
|
|
|
|
(
|
|
|
|
(
|
|
|
|
sync_asset_buttons::<Font>,
|
|
|
|
sync_asset_buttons::<Font>,
|
|
|
|
|
|
|
|
sync_remove_asset_buttons::<Font>,
|
|
|
|
sync_asset_buttons::<AudioSource>,
|
|
|
|
sync_asset_buttons::<AudioSource>,
|
|
|
|
|
|
|
|
sync_remove_asset_buttons::<AudioSource>,
|
|
|
|
sync_asset_buttons::<Monologue>,
|
|
|
|
sync_asset_buttons::<Monologue>,
|
|
|
|
|
|
|
|
sync_remove_asset_buttons::<Monologue>,
|
|
|
|
sync_asset_buttons::<Level>,
|
|
|
|
sync_asset_buttons::<Level>,
|
|
|
|
|
|
|
|
sync_remove_asset_buttons::<Level>,
|
|
|
|
sync_asset_buttons::<Gltf>,
|
|
|
|
sync_asset_buttons::<Gltf>,
|
|
|
|
|
|
|
|
sync_remove_asset_buttons::<Gltf>,
|
|
|
|
sync_asset_buttons::<Scene>,
|
|
|
|
sync_asset_buttons::<Scene>,
|
|
|
|
|
|
|
|
sync_remove_asset_buttons::<Scene>,
|
|
|
|
sync_asset_buttons::<AnimationClip>,
|
|
|
|
sync_asset_buttons::<AnimationClip>,
|
|
|
|
|
|
|
|
sync_remove_asset_buttons::<AnimationClip>,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.add_systems(
|
|
|
|
|
|
|
|
Update,
|
|
|
|
|
|
|
|
(
|
|
|
|
|
|
|
|
add_timeline_epoch.run_if(ui::activated::<AddEpoch>),
|
|
|
|
|
|
|
|
set_epoch_gltf,
|
|
|
|
|
|
|
|
load_epoch_gltf,
|
|
|
|
|
|
|
|
set_epoch_scene,
|
|
|
|
|
|
|
|
load_epoch_scene,
|
|
|
|
|
|
|
|
set_epoch_camera,
|
|
|
|
|
|
|
|
load_epoch_camera,
|
|
|
|
|
|
|
|
set_epoch_music,
|
|
|
|
|
|
|
|
load_epoch_music,
|
|
|
|
|
|
|
|
set_epoch_monologue,
|
|
|
|
|
|
|
|
load_epoch_monologue,
|
|
|
|
|
|
|
|
set_epoch_font,
|
|
|
|
|
|
|
|
load_epoch_font,
|
|
|
|
|
|
|
|
set_epoch_sfx,
|
|
|
|
|
|
|
|
load_epoch_sfx,
|
|
|
|
|
|
|
|
set_epoch_animations,
|
|
|
|
|
|
|
|
load_epoch_animations,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
.run();
|
|
|
|
@ -184,6 +214,7 @@ fn initialize_ui(mut commands: Commands) {
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Assets widget
|
|
|
|
commands
|
|
|
|
commands
|
|
|
|
.spawn(NodeBundle {
|
|
|
|
.spawn(NodeBundle {
|
|
|
|
style: Style {
|
|
|
|
style: Style {
|
|
|
|
@ -328,6 +359,8 @@ fn initialize_ui(mut commands: Commands) {
|
|
|
|
ui::Sorting(0),
|
|
|
|
ui::Sorting(0),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Actions widget
|
|
|
|
commands
|
|
|
|
commands
|
|
|
|
.spawn(NodeBundle {
|
|
|
|
.spawn(NodeBundle {
|
|
|
|
style: Style {
|
|
|
|
style: Style {
|
|
|
|
@ -422,6 +455,88 @@ fn initialize_ui(mut commands: Commands) {
|
|
|
|
ui::Sorting(0),
|
|
|
|
ui::Sorting(0),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Actions widget
|
|
|
|
|
|
|
|
commands
|
|
|
|
|
|
|
|
.spawn(NodeBundle {
|
|
|
|
|
|
|
|
style: Style {
|
|
|
|
|
|
|
|
bottom: Val::Px(0.0),
|
|
|
|
|
|
|
|
right: Val::Px(0.0),
|
|
|
|
|
|
|
|
position_type: PositionType::Absolute,
|
|
|
|
|
|
|
|
border: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
|
|
|
margin: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
|
|
|
padding: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
|
|
|
|
overflow: Overflow::clip(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
background_color: Color::WHITE.into(),
|
|
|
|
|
|
|
|
border_color: Color::BLACK.into(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.with_children(|parent| {
|
|
|
|
|
|
|
|
let container = parent
|
|
|
|
|
|
|
|
.spawn((
|
|
|
|
|
|
|
|
NodeBundle {
|
|
|
|
|
|
|
|
style: Style {
|
|
|
|
|
|
|
|
border: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
|
|
|
margin: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
|
|
|
padding: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
|
|
|
flex_direction: FlexDirection::Row,
|
|
|
|
|
|
|
|
overflow: Overflow::clip(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
background_color: Color::WHITE.into(),
|
|
|
|
|
|
|
|
border_color: Color::BLACK.into(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
ui::Sorting(99),
|
|
|
|
|
|
|
|
ui::Select::Single,
|
|
|
|
|
|
|
|
TimelineWidget,
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
.with_children(|parent| {
|
|
|
|
|
|
|
|
// "Add Epoch" button
|
|
|
|
|
|
|
|
parent
|
|
|
|
|
|
|
|
.spawn((
|
|
|
|
|
|
|
|
NodeBundle {
|
|
|
|
|
|
|
|
style: Style {
|
|
|
|
|
|
|
|
border: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
|
|
|
margin: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
|
|
|
padding: UiRect::all(Val::Px(1.0)),
|
|
|
|
|
|
|
|
flex_direction: FlexDirection::Row,
|
|
|
|
|
|
|
|
align_items: AlignItems::Center,
|
|
|
|
|
|
|
|
justify_items: JustifyItems::Center,
|
|
|
|
|
|
|
|
overflow: Overflow::clip(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
background_color: Color::WHITE.into(),
|
|
|
|
|
|
|
|
border_color: Color::BLACK.into(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
ui::Select::Action,
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
.with_children(|parent| {
|
|
|
|
|
|
|
|
parent.spawn((
|
|
|
|
|
|
|
|
simple_button.clone(),
|
|
|
|
|
|
|
|
AddEpoch,
|
|
|
|
|
|
|
|
ui::Title {
|
|
|
|
|
|
|
|
text: "+".into(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.id();
|
|
|
|
|
|
|
|
parent.spawn((
|
|
|
|
|
|
|
|
ui::TitleBarBase::new(Color::WHITE).bundle(),
|
|
|
|
|
|
|
|
ui::Title {
|
|
|
|
|
|
|
|
text: "Timeline".into(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
ui::Minimize { target: container },
|
|
|
|
|
|
|
|
ui::Sorting(0),
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn welcome_message(mut writer: EventWriter<ui::Alert>) {
|
|
|
|
fn welcome_message(mut writer: EventWriter<ui::Alert>) {
|
|
|
|
@ -522,49 +637,79 @@ mod audio {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn play_audio(
|
|
|
|
#[derive(Debug, Event)]
|
|
|
|
events: Query<&ui::TargetAsset<AudioSource>, (With<Button>, Added<ui::Active>)>,
|
|
|
|
pub enum ControlAudio {
|
|
|
|
|
|
|
|
Play(Handle<AudioSource>),
|
|
|
|
|
|
|
|
Loop(Handle<AudioSource>),
|
|
|
|
|
|
|
|
Stop(Handle<AudioSource>),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn control_audio(
|
|
|
|
|
|
|
|
mut events: EventReader<ControlAudio>,
|
|
|
|
root: Query<Entity, With<AudioRoot>>,
|
|
|
|
root: Query<Entity, With<AudioRoot>>,
|
|
|
|
mut commands: Commands,
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
sources: Query<(Entity, &Handle<AudioSource>), With<AudioSink>>,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
events.iter().for_each(|ui::TargetAsset { handle }| {
|
|
|
|
events.iter().for_each(|event| match event {
|
|
|
|
let root = if let Ok(entity) = root.get_single() {
|
|
|
|
ControlAudio::Play(handle) => (),
|
|
|
|
entity
|
|
|
|
ControlAudio::Loop(handle) => {
|
|
|
|
} else {
|
|
|
|
info!("Looping audio {:?}", handle);
|
|
|
|
commands.spawn(AudioRoot).id()
|
|
|
|
let root = if let Ok(entity) = root.get_single() {
|
|
|
|
};
|
|
|
|
entity
|
|
|
|
commands.entity(root).with_children(|parent| {
|
|
|
|
} else {
|
|
|
|
parent.spawn(AudioSourceBundle {
|
|
|
|
commands.spawn(AudioRoot).id()
|
|
|
|
source: handle.clone(),
|
|
|
|
};
|
|
|
|
settings: PlaybackSettings {
|
|
|
|
commands.entity(root).with_children(|parent| {
|
|
|
|
mode: PlaybackMode::Loop,
|
|
|
|
parent.spawn(AudioSourceBundle {
|
|
|
|
paused: false,
|
|
|
|
source: handle.clone(),
|
|
|
|
..default()
|
|
|
|
settings: PlaybackSettings {
|
|
|
|
},
|
|
|
|
mode: PlaybackMode::Loop,
|
|
|
|
|
|
|
|
paused: false,
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
info!("Done spawning");
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ControlAudio::Stop(handle) => {
|
|
|
|
|
|
|
|
info!("Stopping audio {:?}", handle);
|
|
|
|
|
|
|
|
sources
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.find_map(|(entity, source_handle)| {
|
|
|
|
|
|
|
|
if source_handle == handle {
|
|
|
|
|
|
|
|
Some(entity)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.for_each(|&entity| {
|
|
|
|
|
|
|
|
commands.entity(entity).despawn_recursive();
|
|
|
|
|
|
|
|
info!("Done despawning");
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn play_audio(
|
|
|
|
|
|
|
|
events: Query<&ui::TargetAsset<AudioSource>, (With<Button>, Added<ui::Active>)>,
|
|
|
|
|
|
|
|
mut writer: EventWriter<ControlAudio>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
events.iter().for_each(|ui::TargetAsset { handle }| {
|
|
|
|
|
|
|
|
writer.send(ControlAudio::Loop(handle.clone()));
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn pause_audio(
|
|
|
|
pub fn pause_audio(
|
|
|
|
mut events: RemovedComponents<ui::Active>,
|
|
|
|
mut events: RemovedComponents<ui::Active>,
|
|
|
|
targets: Query<&ui::TargetAsset<AudioSource>>,
|
|
|
|
targets: Query<&ui::TargetAsset<AudioSource>>,
|
|
|
|
sources: Query<(Entity, &Handle<AudioSource>), With<AudioSink>>,
|
|
|
|
mut writer: EventWriter<ControlAudio>,
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
// Iterate over the audio button events
|
|
|
|
// Iterate over the audio button events
|
|
|
|
events.iter().for_each(|entity| {
|
|
|
|
events.iter().for_each(|entity| {
|
|
|
|
// Get the handle for the audio source we want to despawn
|
|
|
|
// Get the handle for the audio source we want to despawn
|
|
|
|
if let Ok(ui::TargetAsset { handle }) = targets.get(entity) {
|
|
|
|
if let Ok(ui::TargetAsset { handle }) = targets.get(entity) {
|
|
|
|
if let Some(entity) = sources.iter().find_map(|(entity, source_handle)| {
|
|
|
|
writer.send(ControlAudio::Stop(handle.clone()));
|
|
|
|
if source_handle == handle {
|
|
|
|
|
|
|
|
Some(entity)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}) {
|
|
|
|
|
|
|
|
commands.entity(entity).despawn_recursive();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -1568,6 +1713,8 @@ mod level {
|
|
|
|
builder.allow::<LevelRoot>();
|
|
|
|
builder.allow::<LevelRoot>();
|
|
|
|
builder.allow::<AudioRoot>();
|
|
|
|
builder.allow::<AudioRoot>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Serialize Timeline
|
|
|
|
|
|
|
|
|
|
|
|
// Scene components
|
|
|
|
// Scene components
|
|
|
|
builder.allow::<Handle<Scene>>();
|
|
|
|
builder.allow::<Handle<Scene>>();
|
|
|
|
|
|
|
|
|
|
|
|
@ -1650,8 +1797,6 @@ mod asset_sync {
|
|
|
|
use super::*;
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
|
|
// This sets buttons to active when their associated handle is spawned
|
|
|
|
// This sets buttons to active when their associated handle is spawned
|
|
|
|
// TODO: Remove active when handle is despawned?
|
|
|
|
|
|
|
|
// ONLY IF there are no instances of that handle [!any(*)]
|
|
|
|
|
|
|
|
pub fn sync_asset_buttons<T: Asset>(
|
|
|
|
pub fn sync_asset_buttons<T: Asset>(
|
|
|
|
events: Query<&Handle<T>, Added<Handle<T>>>,
|
|
|
|
events: Query<&Handle<T>, Added<Handle<T>>>,
|
|
|
|
buttons: Query<(Entity, &ui::TargetAsset<T>)>,
|
|
|
|
buttons: Query<(Entity, &ui::TargetAsset<T>)>,
|
|
|
|
@ -1674,4 +1819,369 @@ mod asset_sync {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Remove active when handle is despawned?
|
|
|
|
|
|
|
|
// ONLY IF there are no instances of that handle [!any(*)]
|
|
|
|
|
|
|
|
pub fn sync_remove_asset_buttons<T: Asset>(
|
|
|
|
|
|
|
|
mut events: RemovedComponents<Handle<T>>,
|
|
|
|
|
|
|
|
asset_entities: Query<&Handle<T>>,
|
|
|
|
|
|
|
|
buttons: Query<(Entity, &ui::TargetAsset<T>)>,
|
|
|
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
events
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.find_map(|this_asset_entity| asset_entities.get(this_asset_entity).ok())
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.for_each(|this_handle| {
|
|
|
|
|
|
|
|
info!("Syncing removal of {:?}", this_handle);
|
|
|
|
|
|
|
|
buttons
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.find_map(|(entity, ui::TargetAsset { handle })| {
|
|
|
|
|
|
|
|
if handle == *this_handle {
|
|
|
|
|
|
|
|
Some(entity)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.for_each(|&entity| {
|
|
|
|
|
|
|
|
commands.entity(entity).remove::<ui::Active>();
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use timeline::*;
|
|
|
|
|
|
|
|
mod timeline {
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Timeline widget marker
|
|
|
|
|
|
|
|
#[derive(Debug, Component)]
|
|
|
|
|
|
|
|
pub struct TimelineWidget;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Add Epoch component, used on a button to trigger a new epoch addition
|
|
|
|
|
|
|
|
#[derive(Debug, Component)]
|
|
|
|
|
|
|
|
pub struct AddEpoch;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Epoch ID Component
|
|
|
|
|
|
|
|
#[derive(Debug, Reflect, Component, Clone)]
|
|
|
|
|
|
|
|
pub struct EpochId {
|
|
|
|
|
|
|
|
id: usize,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// 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
|
|
|
|
|
|
|
|
/// Triggered when a button with the AddEpoch marker is Active
|
|
|
|
|
|
|
|
pub fn add_timeline_epoch(
|
|
|
|
|
|
|
|
root: Query<(Entity, &Children), With<TimelineWidget>>,
|
|
|
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
info!("Adding timeline epoch");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
root.iter().for_each(|(entity, children)| {
|
|
|
|
|
|
|
|
let id = children.iter().len();
|
|
|
|
|
|
|
|
let name = format!("{}", id);
|
|
|
|
|
|
|
|
commands.entity(entity).with_children(|parent| {
|
|
|
|
|
|
|
|
parent.spawn((
|
|
|
|
|
|
|
|
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: name,
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
EpochId { id },
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Set the GLTF for the current epoch
|
|
|
|
|
|
|
|
pub 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
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn load_epoch_gltf(events: Query<Option<&EpochGltf>, (Added<ui::Active>, With<EpochId>)>) {
|
|
|
|
|
|
|
|
events.iter().for_each(|epoch_gltf| {
|
|
|
|
|
|
|
|
warn!("TODO: Load epoch GLTF!");
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub 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(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn load_epoch_scene(
|
|
|
|
|
|
|
|
events: Query<Option<&EpochScene>, (Added<ui::Active>, With<EpochId>)>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
events.iter().for_each(|epoch_scene| {
|
|
|
|
|
|
|
|
warn!("TODO: Load epoch Scene!");
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub 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 });
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn load_epoch_camera(
|
|
|
|
|
|
|
|
events: Query<Option<&EpochCamera>, (Added<ui::Active>, With<EpochId>)>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
events.iter().for_each(|epoch_camera| {
|
|
|
|
|
|
|
|
warn!("TODO: Load epoch Camera");
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub 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() });
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn load_epoch_music(
|
|
|
|
|
|
|
|
events: Query<Option<&EpochMusic>, (Added<ui::Active>, With<EpochId>)>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
events.iter().for_each(|epoch_music| {
|
|
|
|
|
|
|
|
warn!("TODO: Load epoch music!");
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub 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(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub 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");
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub 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(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub 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());
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub 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()],
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub 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()));
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub 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()],
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn load_epoch_animations(
|
|
|
|
|
|
|
|
events: Query<Option<&EpochAnimations>, (Added<ui::Active>, With<EpochId>)>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
events.iter().for_each(|epoch_animations| {
|
|
|
|
|
|
|
|
warn!("TODO: Load epoch Animations!");
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|