|
|
|
@ -4,16 +4,12 @@
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// BUGS:
|
|
|
|
// BUGS:
|
|
|
|
// * Camera order ambiguity
|
|
|
|
// * Camera order ambiguity
|
|
|
|
// * Load new GLTF -> Despawn all level entities
|
|
|
|
// * Multi-GLTF UX is bad.
|
|
|
|
|
|
|
|
// * Consider GLTF hierarchy (GLTF1 > Scene1a/Scene1b, GlTF2 > Scene2a/Scene2b, etc)
|
|
|
|
|
|
|
|
// * Easy despawn when de-selecting gltf
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// TODO:
|
|
|
|
// TODO:
|
|
|
|
// * Disable auto start/load
|
|
|
|
// * (easy) Play all animations
|
|
|
|
// * Better handle hide/close monologue
|
|
|
|
|
|
|
|
// * (hard) Harden Active Camera
|
|
|
|
|
|
|
|
// * (medium) Despawn entire scene when GLTF changed?
|
|
|
|
|
|
|
|
// * (medium) Select Font -> "Default Font" Resource
|
|
|
|
|
|
|
|
// * (medium) Pre-compute animation target entities
|
|
|
|
|
|
|
|
// * (medium) Animation buttons only visible when playable
|
|
|
|
|
|
|
|
// * (easy) Clear button to wipe spawned scene
|
|
|
|
// * (easy) Clear button to wipe spawned scene
|
|
|
|
// * (brutal) export level
|
|
|
|
// * (brutal) export level
|
|
|
|
// * (hard) import level
|
|
|
|
// * (hard) import level
|
|
|
|
@ -29,11 +25,12 @@
|
|
|
|
// * Monologues (done)
|
|
|
|
// * Monologues (done)
|
|
|
|
|
|
|
|
|
|
|
|
use bevy::{
|
|
|
|
use bevy::{
|
|
|
|
asset::{Asset, AssetLoader, Assets, ChangeWatcher, LoadContext, LoadedAsset},
|
|
|
|
asset::{Asset, Assets},
|
|
|
|
|
|
|
|
asset::{AssetLoader, LoadContext, LoadedAsset},
|
|
|
|
audio::PlaybackMode,
|
|
|
|
audio::PlaybackMode,
|
|
|
|
gltf::Gltf,
|
|
|
|
gltf::Gltf,
|
|
|
|
prelude::*,
|
|
|
|
prelude::*,
|
|
|
|
utils::{BoxedFuture, Duration},
|
|
|
|
utils::BoxedFuture,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
use monologue_trees::{debug::*, ui};
|
|
|
|
use monologue_trees::{debug::*, ui};
|
|
|
|
|
|
|
|
|
|
|
|
@ -53,18 +50,13 @@ const WELCOME_MESSAGES: &'static [&'static str] = &[
|
|
|
|
fn main() {
|
|
|
|
fn main() {
|
|
|
|
App::new()
|
|
|
|
App::new()
|
|
|
|
.add_plugins((
|
|
|
|
.add_plugins((
|
|
|
|
DefaultPlugins
|
|
|
|
DefaultPlugins.set(WindowPlugin {
|
|
|
|
.set(WindowPlugin {
|
|
|
|
|
|
|
|
primary_window: Some(Window {
|
|
|
|
primary_window: Some(Window {
|
|
|
|
title: "Monologue Trees Editor".into(),
|
|
|
|
title: "Monologue Trees Editor".into(),
|
|
|
|
resolution: (640., 480.).into(),
|
|
|
|
resolution: (640., 480.).into(),
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
})
|
|
|
|
|
|
|
|
.set(AssetPlugin {
|
|
|
|
|
|
|
|
watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(200)),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
DebugInfoPlugin,
|
|
|
|
DebugInfoPlugin,
|
|
|
|
ui::GameUiPlugin,
|
|
|
|
ui::GameUiPlugin,
|
|
|
|
@ -78,16 +70,16 @@ fn main() {
|
|
|
|
.add_systems(
|
|
|
|
.add_systems(
|
|
|
|
Update,
|
|
|
|
Update,
|
|
|
|
(
|
|
|
|
(
|
|
|
|
|
|
|
|
manage_gltf_animation_ui,
|
|
|
|
init_animations_ui,
|
|
|
|
init_animations_ui,
|
|
|
|
remove_animations_ui,
|
|
|
|
animations_ui,
|
|
|
|
add_animations_ui,
|
|
|
|
|
|
|
|
play_all_animations,
|
|
|
|
play_all_animations,
|
|
|
|
play_animation,
|
|
|
|
play_animation,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.add_systems(
|
|
|
|
.add_systems(
|
|
|
|
Update,
|
|
|
|
Update,
|
|
|
|
(remove_scenes_ui, add_scenes_ui, control_active_scenes),
|
|
|
|
(manage_gltf_scene_ui, scenes_ui, control_active_scenes),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.add_systems(
|
|
|
|
.add_systems(
|
|
|
|
Update,
|
|
|
|
Update,
|
|
|
|
@ -111,14 +103,6 @@ fn main() {
|
|
|
|
sync_monologue_font,
|
|
|
|
sync_monologue_font,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.add_systems(
|
|
|
|
|
|
|
|
Update,
|
|
|
|
|
|
|
|
(
|
|
|
|
|
|
|
|
point_light_force_shadows,
|
|
|
|
|
|
|
|
spot_light_force_shadows,
|
|
|
|
|
|
|
|
directional_light_force_shadows,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.run();
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -240,18 +224,18 @@ fn initialize_ui(mut commands: Commands) {
|
|
|
|
content_containers.push(spawn_tab_container::<SceneWidget>(
|
|
|
|
content_containers.push(spawn_tab_container::<SceneWidget>(
|
|
|
|
"Scene",
|
|
|
|
"Scene",
|
|
|
|
parent,
|
|
|
|
parent,
|
|
|
|
ui::Select::Single,
|
|
|
|
ui::Select::Multi,
|
|
|
|
));
|
|
|
|
|
|
|
|
content_containers.push(spawn_tab_container::<CameraWidget>(
|
|
|
|
|
|
|
|
"Camera",
|
|
|
|
|
|
|
|
parent,
|
|
|
|
|
|
|
|
ui::Select::Single,
|
|
|
|
|
|
|
|
));
|
|
|
|
));
|
|
|
|
content_containers.push(spawn_tab_container::<AnimationWidget>(
|
|
|
|
content_containers.push(spawn_tab_container::<AnimationWidget>(
|
|
|
|
"Animation",
|
|
|
|
"Animation",
|
|
|
|
parent,
|
|
|
|
parent,
|
|
|
|
ui::Select::Multi,
|
|
|
|
ui::Select::Multi,
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
content_containers.push(spawn_tab_container::<CameraWidget>(
|
|
|
|
|
|
|
|
"Camera",
|
|
|
|
|
|
|
|
parent,
|
|
|
|
|
|
|
|
ui::Select::Single,
|
|
|
|
|
|
|
|
));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Container for tabs that open/close containers
|
|
|
|
// Container for tabs that open/close containers
|
|
|
|
@ -569,6 +553,22 @@ mod assets {
|
|
|
|
commands.entity(entity).despawn_recursive();
|
|
|
|
commands.entity(entity).despawn_recursive();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn has_extensions<T: Asset>(
|
|
|
|
|
|
|
|
server: &AssetServer,
|
|
|
|
|
|
|
|
handle: Handle<T>,
|
|
|
|
|
|
|
|
extensions: &[&'static str],
|
|
|
|
|
|
|
|
) -> bool {
|
|
|
|
|
|
|
|
if let Some(asset_path) = server.get_handle_path(handle.clone()) {
|
|
|
|
|
|
|
|
if let Some(extension) = asset_path.path().extension() {
|
|
|
|
|
|
|
|
extensions.iter().any(|&check| check == extension)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
use gltf::*;
|
|
|
|
use gltf::*;
|
|
|
|
@ -650,6 +650,103 @@ mod gltf {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn manage_gltf_animation_ui(
|
|
|
|
|
|
|
|
added: Query<Entity, (With<Button>, Added<ui::Active>)>,
|
|
|
|
|
|
|
|
mut removed: RemovedComponents<ui::Active>,
|
|
|
|
|
|
|
|
targets_gltf: Query<&ui::TargetAsset<Gltf>>,
|
|
|
|
|
|
|
|
gltfs: Res<Assets<Gltf>>,
|
|
|
|
|
|
|
|
mut animation_clip_events: EventWriter<CustomAssetEvent<AnimationClip>>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
removed
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.filter_map(|entity| {
|
|
|
|
|
|
|
|
if let Ok(ui::TargetAsset { handle }) = targets_gltf.get(entity) {
|
|
|
|
|
|
|
|
gltfs.get(handle)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.for_each(|gltf| {
|
|
|
|
|
|
|
|
gltf.named_animations
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.for_each(|(animation_name, animation_handle)| {
|
|
|
|
|
|
|
|
info!("Named animation: {:?}", animation_name);
|
|
|
|
|
|
|
|
animation_clip_events.send(CustomAssetEvent::Remove {
|
|
|
|
|
|
|
|
handle: animation_handle.clone(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
added
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.filter_map(|entity| {
|
|
|
|
|
|
|
|
if let Ok(ui::TargetAsset { handle }) = targets_gltf.get(entity) {
|
|
|
|
|
|
|
|
gltfs.get(handle)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.for_each(|gltf| {
|
|
|
|
|
|
|
|
// Populate animations tab
|
|
|
|
|
|
|
|
gltf.named_animations
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.for_each(|(animation_name, animation_handle)| {
|
|
|
|
|
|
|
|
animation_clip_events.send(CustomAssetEvent::Add {
|
|
|
|
|
|
|
|
name: animation_name.clone(),
|
|
|
|
|
|
|
|
handle: animation_handle.clone(),
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn manage_gltf_scene_ui(
|
|
|
|
|
|
|
|
added: Query<Entity, (With<Button>, Added<ui::Active>)>,
|
|
|
|
|
|
|
|
mut removed: RemovedComponents<ui::Active>,
|
|
|
|
|
|
|
|
targets_gltf: Query<&ui::TargetAsset<Gltf>>,
|
|
|
|
|
|
|
|
gltfs: Res<Assets<Gltf>>,
|
|
|
|
|
|
|
|
mut scene_events: EventWriter<CustomAssetEvent<Scene>>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
removed
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.filter_map(|entity| {
|
|
|
|
|
|
|
|
if let Ok(ui::TargetAsset { handle }) = targets_gltf.get(entity) {
|
|
|
|
|
|
|
|
gltfs.get(handle)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.for_each(|gltf| {
|
|
|
|
|
|
|
|
gltf.named_scenes
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.for_each(|(scene_name, scene_handle)| {
|
|
|
|
|
|
|
|
info!("Named scene: {:?}", scene_name);
|
|
|
|
|
|
|
|
scene_events.send(CustomAssetEvent::Remove {
|
|
|
|
|
|
|
|
handle: scene_handle.clone(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
added
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.filter_map(|entity| {
|
|
|
|
|
|
|
|
if let Ok(ui::TargetAsset { handle }) = targets_gltf.get(entity) {
|
|
|
|
|
|
|
|
gltfs.get(handle)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.for_each(|gltf| {
|
|
|
|
|
|
|
|
// Populate scenes tab
|
|
|
|
|
|
|
|
gltf.named_scenes
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.for_each(|(scene_name, scene_handle)| {
|
|
|
|
|
|
|
|
info!("Named scene: {:?}", scene_name);
|
|
|
|
|
|
|
|
scene_events.send(CustomAssetEvent::Add {
|
|
|
|
|
|
|
|
name: scene_name.clone(),
|
|
|
|
|
|
|
|
handle: scene_handle.clone(),
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Mark loaded animation as active
|
|
|
|
// TODO: Mark loaded animation as active
|
|
|
|
@ -660,16 +757,20 @@ mod scenes {
|
|
|
|
#[derive(Debug, Component, Default)]
|
|
|
|
#[derive(Debug, Component, Default)]
|
|
|
|
pub struct SceneWidget;
|
|
|
|
pub struct SceneWidget;
|
|
|
|
|
|
|
|
|
|
|
|
pub fn add_scenes_ui(
|
|
|
|
pub fn scenes_ui(
|
|
|
|
gltf_selected: Query<&ui::TargetAsset<Gltf>, Added<ui::Active>>,
|
|
|
|
mut events: EventReader<CustomAssetEvent<Scene>>,
|
|
|
|
mut commands: Commands,
|
|
|
|
mut commands: Commands,
|
|
|
|
gltfs: Res<Assets<Gltf>>,
|
|
|
|
|
|
|
|
widget: Query<Entity, With<SceneWidget>>,
|
|
|
|
widget: Query<Entity, With<SceneWidget>>,
|
|
|
|
|
|
|
|
current: Query<(Entity, &ui::TargetAsset<Scene>)>,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
gltf_selected.iter().for_each(|ui::TargetAsset { handle }| {
|
|
|
|
events.iter().for_each(|event| {
|
|
|
|
if let Some(gltf) = gltfs.get(&handle.clone()) {
|
|
|
|
let empty = current.iter().len() == 0;
|
|
|
|
gltf.named_scenes.iter().for_each(|(name, handle)| {
|
|
|
|
|
|
|
|
create_asset_button(
|
|
|
|
match event {
|
|
|
|
|
|
|
|
CustomAssetEvent::Add { name, handle } => {
|
|
|
|
|
|
|
|
info!("Asset loading! {:?}({:?})", name, handle);
|
|
|
|
|
|
|
|
// Spawn new tree
|
|
|
|
|
|
|
|
let e = create_asset_button(
|
|
|
|
&widget,
|
|
|
|
&widget,
|
|
|
|
&mut commands,
|
|
|
|
&mut commands,
|
|
|
|
ui::TargetAsset {
|
|
|
|
ui::TargetAsset {
|
|
|
|
@ -678,24 +779,12 @@ mod scenes {
|
|
|
|
name.clone(),
|
|
|
|
name.clone(),
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
);
|
|
|
|
);
|
|
|
|
})
|
|
|
|
// If this is the first scene being added, set it as active
|
|
|
|
|
|
|
|
if empty {
|
|
|
|
|
|
|
|
commands.entity(e).insert(ui::Active);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomAssetEvent::Remove { handle } => {
|
|
|
|
pub fn remove_scenes_ui(
|
|
|
|
|
|
|
|
mut gltf_unselected: RemovedComponents<ui::Active>,
|
|
|
|
|
|
|
|
target_assets: Query<&ui::TargetAsset<Gltf>>,
|
|
|
|
|
|
|
|
current: Query<(Entity, &ui::TargetAsset<Scene>)>,
|
|
|
|
|
|
|
|
gltfs: Res<Assets<Gltf>>,
|
|
|
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
gltf_unselected
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.filter_map(|entity| target_assets.get(entity).ok())
|
|
|
|
|
|
|
|
.filter_map(|ui::TargetAsset { handle }| gltfs.get(handle))
|
|
|
|
|
|
|
|
.for_each(|gltf| {
|
|
|
|
|
|
|
|
gltf.scenes.iter().for_each(|handle| {
|
|
|
|
|
|
|
|
destroy_asset_button(
|
|
|
|
destroy_asset_button(
|
|
|
|
¤t,
|
|
|
|
¤t,
|
|
|
|
&mut commands,
|
|
|
|
&mut commands,
|
|
|
|
@ -703,7 +792,11 @@ mod scenes {
|
|
|
|
handle: handle.clone(),
|
|
|
|
handle: handle.clone(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
);
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomAssetEvent::Clear => {
|
|
|
|
|
|
|
|
commands.entity(widget.single()).despawn_descendants();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -785,64 +878,28 @@ mod animations {
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// When a new scene is loaded, add any newly compatible animations
|
|
|
|
pub fn animations_ui(
|
|
|
|
pub fn add_animations_ui(
|
|
|
|
mut events: EventReader<CustomAssetEvent<AnimationClip>>,
|
|
|
|
player_spawned: Query<&Name, Added<AnimationPlayer>>,
|
|
|
|
|
|
|
|
widget: Query<Entity, With<AnimationWidget>>,
|
|
|
|
|
|
|
|
mut commands: Commands,
|
|
|
|
mut commands: Commands,
|
|
|
|
gltfs: Res<Assets<Gltf>>,
|
|
|
|
widget: Query<Entity, With<AnimationWidget>>,
|
|
|
|
clips: Res<Assets<AnimationClip>>,
|
|
|
|
current: Query<(Entity, &ui::TargetAsset<AnimationClip>)>,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
player_spawned.iter().for_each(|player_name| {
|
|
|
|
events.iter().for_each(|event| {
|
|
|
|
gltfs
|
|
|
|
match event {
|
|
|
|
.iter()
|
|
|
|
CustomAssetEvent::Add { name, handle } => {
|
|
|
|
.flat_map(|(_, gltf)| gltf.named_animations.iter())
|
|
|
|
info!("Asset loading! {:?}({:?})", name, handle);
|
|
|
|
.filter_map(|(clip_name, handle)| {
|
|
|
|
// Spawn new tree
|
|
|
|
if let Some(clip) = clips.get(&handle) {
|
|
|
|
|
|
|
|
Some((clip_name, handle, clip))
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.filter(|(_, _, clip)| clip.compatible_with(player_name))
|
|
|
|
|
|
|
|
.for_each(|(clip_name, handle, _)| {
|
|
|
|
|
|
|
|
create_asset_button(
|
|
|
|
create_asset_button(
|
|
|
|
&widget,
|
|
|
|
&widget,
|
|
|
|
&mut commands,
|
|
|
|
&mut commands,
|
|
|
|
ui::TargetAsset {
|
|
|
|
ui::TargetAsset {
|
|
|
|
handle: handle.clone(),
|
|
|
|
handle: handle.clone(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
clip_name.clone(),
|
|
|
|
name.clone(),
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
);
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomAssetEvent::Remove { handle } => {
|
|
|
|
// When a scene is de-selected, remove any outdated animation options
|
|
|
|
|
|
|
|
pub fn remove_animations_ui(
|
|
|
|
|
|
|
|
mut removed_players: RemovedComponents<Handle<Scene>>,
|
|
|
|
|
|
|
|
names: Query<&Name>,
|
|
|
|
|
|
|
|
current: Query<(Entity, &ui::TargetAsset<AnimationClip>)>,
|
|
|
|
|
|
|
|
clips: Res<Assets<AnimationClip>>,
|
|
|
|
|
|
|
|
targets: Query<(&AnimationPlayer, &Name)>,
|
|
|
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
// For each removed scene
|
|
|
|
|
|
|
|
removed_players.iter().for_each(|_| {
|
|
|
|
|
|
|
|
// Iterate over the current animation buttons
|
|
|
|
|
|
|
|
current
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.filter(|(_, ui::TargetAsset { handle })| {
|
|
|
|
|
|
|
|
// Check if this clip is compatible with any remaining entities
|
|
|
|
|
|
|
|
// NOTE: We are checking this is *not* compatible with any entities
|
|
|
|
|
|
|
|
clips
|
|
|
|
|
|
|
|
.get(handle)
|
|
|
|
|
|
|
|
.map(|clip| !(targets.iter().any(|(_, name)| clip.compatible_with(name))))
|
|
|
|
|
|
|
|
.unwrap_or(true)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.for_each(|(_, ui::TargetAsset { handle })| {
|
|
|
|
|
|
|
|
// Destroy the buton if it is so
|
|
|
|
|
|
|
|
destroy_asset_button(
|
|
|
|
destroy_asset_button(
|
|
|
|
¤t,
|
|
|
|
¤t,
|
|
|
|
&mut commands,
|
|
|
|
&mut commands,
|
|
|
|
@ -850,7 +907,11 @@ mod animations {
|
|
|
|
handle: handle.clone(),
|
|
|
|
handle: handle.clone(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
);
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomAssetEvent::Clear => {
|
|
|
|
|
|
|
|
commands.entity(widget.single()).despawn_descendants();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1037,6 +1098,7 @@ mod monologues {
|
|
|
|
));
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Load .txt files for monologues
|
|
|
|
pub fn texts_ui(
|
|
|
|
pub fn texts_ui(
|
|
|
|
mut events: EventReader<AssetEvent<Monologue>>,
|
|
|
|
mut events: EventReader<AssetEvent<Monologue>>,
|
|
|
|
mut commands: Commands,
|
|
|
|
mut commands: Commands,
|
|
|
|
@ -1089,8 +1151,10 @@ mod monologues {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO(BUG): Better handle hide/close monologue
|
|
|
|
pub fn show_preview_text(
|
|
|
|
pub fn show_preview_text(
|
|
|
|
added: Query<Entity, (With<Button>, Added<ui::Active>)>,
|
|
|
|
added: Query<Entity, (With<Button>, Added<ui::Active>)>,
|
|
|
|
|
|
|
|
mut removed: RemovedComponents<ui::Active>,
|
|
|
|
monologue_handles: Query<&ui::TargetAsset<Monologue>>,
|
|
|
|
monologue_handles: Query<&ui::TargetAsset<Monologue>>,
|
|
|
|
monologues: Res<Assets<Monologue>>,
|
|
|
|
monologues: Res<Assets<Monologue>>,
|
|
|
|
container: Query<Entity, With<MonologueContainer>>,
|
|
|
|
container: Query<Entity, With<MonologueContainer>>,
|
|
|
|
@ -1169,6 +1233,7 @@ mod cameras {
|
|
|
|
#[derive(Debug, Component, Default)]
|
|
|
|
#[derive(Debug, Component, Default)]
|
|
|
|
pub struct CameraWidget;
|
|
|
|
pub struct CameraWidget;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Despawn camera button when camera removed
|
|
|
|
pub fn cameras_ui(
|
|
|
|
pub fn cameras_ui(
|
|
|
|
mut added: Query<(Entity, &mut Camera, &Name), (Added<Camera>, Without<EditorCamera>)>,
|
|
|
|
mut added: Query<(Entity, &mut Camera, &Name), (Added<Camera>, Without<EditorCamera>)>,
|
|
|
|
mut removed: RemovedComponents<Camera>,
|
|
|
|
mut removed: RemovedComponents<Camera>,
|
|
|
|
@ -1181,14 +1246,20 @@ mod cameras {
|
|
|
|
destroy_entity_button(¤t, &mut commands, &ui::TargetEntity { entity });
|
|
|
|
destroy_entity_button(¤t, &mut commands, &ui::TargetEntity { entity });
|
|
|
|
});
|
|
|
|
});
|
|
|
|
added.iter_mut().for_each(|(entity, mut camera, name)| {
|
|
|
|
added.iter_mut().for_each(|(entity, mut camera, name)| {
|
|
|
|
|
|
|
|
let empty = current.iter().len() == 0;
|
|
|
|
|
|
|
|
|
|
|
|
info!("Camera added {:?} {:?}", entity, name);
|
|
|
|
info!("Camera added {:?} {:?}", entity, name);
|
|
|
|
create_entity_button(
|
|
|
|
let e = create_entity_button(
|
|
|
|
&widget,
|
|
|
|
&widget,
|
|
|
|
&mut commands,
|
|
|
|
&mut commands,
|
|
|
|
ui::TargetEntity { entity },
|
|
|
|
ui::TargetEntity { entity },
|
|
|
|
name.as_str().into(),
|
|
|
|
name.as_str().into(),
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
if empty {
|
|
|
|
|
|
|
|
commands.entity(e).insert(ui::Active);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
camera.is_active = false;
|
|
|
|
camera.is_active = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1221,11 +1292,13 @@ mod cameras {
|
|
|
|
mut cameras: Query<&mut Camera>,
|
|
|
|
mut cameras: Query<&mut Camera>,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
removed.iter().for_each(|entity| {
|
|
|
|
removed.iter().for_each(|entity| {
|
|
|
|
|
|
|
|
info!("Setting {:?} to inactive camera", entity);
|
|
|
|
if let Ok(mut camera) = cameras.get_mut(entity) {
|
|
|
|
if let Ok(mut camera) = cameras.get_mut(entity) {
|
|
|
|
camera.is_active = false;
|
|
|
|
camera.is_active = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
added.iter().for_each(|entity| {
|
|
|
|
added.iter().for_each(|entity| {
|
|
|
|
|
|
|
|
info!("Setting {:?} to active camera", entity);
|
|
|
|
if let Ok(mut camera) = cameras.get_mut(entity) {
|
|
|
|
if let Ok(mut camera) = cameras.get_mut(entity) {
|
|
|
|
camera.is_active = true;
|
|
|
|
camera.is_active = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -1249,28 +1322,3 @@ mod cameras {
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
use lighting::*;
|
|
|
|
|
|
|
|
mod lighting {
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn spot_light_force_shadows(mut spot_lights: Query<&mut SpotLight, Added<SpotLight>>) {
|
|
|
|
|
|
|
|
spot_lights.iter_mut().for_each(|mut light| {
|
|
|
|
|
|
|
|
light.shadows_enabled = true;
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn directional_light_force_shadows(
|
|
|
|
|
|
|
|
mut directional_lights: Query<&mut DirectionalLight, Added<DirectionalLight>>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
directional_lights.iter_mut().for_each(|mut light| {
|
|
|
|
|
|
|
|
light.shadows_enabled = true;
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn point_light_force_shadows(mut point_lights: Query<&mut PointLight, Added<PointLight>>) {
|
|
|
|
|
|
|
|
point_lights.iter_mut().for_each(|mut light| {
|
|
|
|
|
|
|
|
light.shadows_enabled = true;
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|