From 50ee319921253c33a2cd9e8f792bf70621a9f2ca Mon Sep 17 00:00:00 2001 From: Elijah Voigt Date: Sat, 2 Sep 2023 14:27:32 -0700 Subject: [PATCH] action buttons work again I guess --- assets/models/FlightHelmet.bin | 3 - assets/models/FlightHelmet.gltf | 3 - assets/models/materials.blend | 4 +- assets/models/materials.blend1 | 4 +- assets/output.scn.ron | 16 +-- bin/editor.rs | 92 +++++++++++---- bin/serialize-wtf.rs | 196 ++++++++++++++++++++++++++------ src/ui.rs | 42 ++++--- 8 files changed, 268 insertions(+), 92 deletions(-) delete mode 100644 assets/models/FlightHelmet.bin delete mode 100644 assets/models/FlightHelmet.gltf diff --git a/assets/models/FlightHelmet.bin b/assets/models/FlightHelmet.bin deleted file mode 100644 index a586e84..0000000 --- a/assets/models/FlightHelmet.bin +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9e623a27f837e1cc995d1380da5fd3becf4d29586fefba882fc0ba76b49f94bf -size 3227148 diff --git a/assets/models/FlightHelmet.gltf b/assets/models/FlightHelmet.gltf deleted file mode 100644 index cfcb890..0000000 --- a/assets/models/FlightHelmet.gltf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c94a08a28305fb49a612cf273330a04e3dfc084306257d52dc00b4447eeb1091 -size 18511 diff --git a/assets/models/materials.blend b/assets/models/materials.blend index 9dfa649..6e3c307 100644 --- a/assets/models/materials.blend +++ b/assets/models/materials.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49b4c75ff7a022cb5893fb01d7a162c0bc11e83797315408d86a69775b759869 -size 1318832 +oid sha256:ef4108e09018bc403171bbf0bc866252c4c2aa53ec58ee05120639c52122d3da +size 1320872 diff --git a/assets/models/materials.blend1 b/assets/models/materials.blend1 index 8f19b7d..48f16f1 100644 --- a/assets/models/materials.blend1 +++ b/assets/models/materials.blend1 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a85ef985fb7450a815b3cd7397d10a6492153b03c950c998fa77f9a85805ef7c -size 1318832 +oid sha256:91c85fdfc9306f695dfa2df2c236131dafd3dc9262963c8d962d89f608ccf3cc +size 1320872 diff --git a/assets/output.scn.ron b/assets/output.scn.ron index 979d07f..2e87fc6 100644 --- a/assets/output.scn.ron +++ b/assets/output.scn.ron @@ -1,7 +1,7 @@ ( resources: {}, entities: { - 4: ( + 19: ( components: { "bevy_transform::components::transform::Transform": ( translation: ( @@ -42,20 +42,20 @@ )), "bevy_render::view::visibility::Visibility": Inherited, "bevy_hierarchy::components::children::Children": ([ - 5, - 6, + 20, + 21, ]), }, ), - 5: ( + 20: ( components: { - "bevy_hierarchy::components::parent::Parent": (4), + "bevy_hierarchy::components::parent::Parent": (19), "bevy_asset::handle::Handle": ( id: AssetPathId(((5718828327369153735), (8823233378563626002))), ), }, ), - 6: ( + 21: ( components: { "bevy_transform::components::transform::Transform": ( translation: ( @@ -95,9 +95,9 @@ ), )), "bevy_render::view::visibility::Visibility": Inherited, - "bevy_hierarchy::components::parent::Parent": (4), + "bevy_hierarchy::components::parent::Parent": (19), "bevy_hierarchy::components::children::Children": ([ - 16, + 22, ]), "bevy_asset::handle::Handle": ( id: AssetPathId(((8329447081204006281), (13531267934229906755))), diff --git a/bin/editor.rs b/bin/editor.rs index 6773f4e..fac4d35 100644 --- a/bin/editor.rs +++ b/bin/editor.rs @@ -56,6 +56,7 @@ fn main() { }, )) .init_resource::() + .add_event::() .add_asset::() .init_asset_loader::() .add_systems(Startup, (initialize_ui, init_texts_ui, welcome_message)) @@ -78,7 +79,6 @@ fn main() { .add_systems( Update, ( - import_files, gltf_ui, fonts_ui, texts_ui, @@ -87,6 +87,7 @@ fn main() { sync_monologue_font, ), ) + .add_systems(Update, (import_assets, import_file, import_folder)) .add_systems( Update, ( @@ -386,27 +387,6 @@ fn spawn_tab_container( ) } -fn import_files( - mut events: EventReader, - server: Res, - mut registry: ResMut, -) { - events.iter().for_each(|event| match event { - FileDragAndDrop::DroppedFile { path_buf, .. } => { - registry.0.push( - server.load_untyped( - path_buf - .clone() - .into_os_string() - .into_string() - .expect("Path converts to string"), - ), - ); - } - _ => (), - }) -} - use audio::*; mod audio { @@ -499,8 +479,72 @@ mod audio { use assets::*; mod assets { + use std::path::PathBuf; + use super::*; + #[derive(Debug, Event)] + pub enum ImportAsset { + File(PathBuf), + Dir(PathBuf), + } + + pub fn import_assets( + mut events: EventReader, + mut writer: EventWriter, + ) { + events.iter().for_each(|event| match event { + FileDragAndDrop::DroppedFile { path_buf, .. } => { + if path_buf.is_file() { + writer.send(ImportAsset::File(path_buf.clone())); + } else if path_buf.is_dir() { + writer.send(ImportAsset::Dir(path_buf.clone())); + } else { + warn!("Could not identify filetype for {:?}", path_buf) + } + } + _ => (), + }) + } + + pub fn import_file( + mut events: EventReader, + server: Res, + mut registry: ResMut, + ) { + events + .iter() + .filter_map(|event| match event { + ImportAsset::File(path) => Some(path), + _ => None, + }) + .for_each(|path| { + registry + .0 + .push(server.load_untyped(String::from(path.to_string_lossy()))); + }); + } + + pub fn import_folder( + mut events: EventReader, + server: Res, + mut registry: ResMut, + ) { + events + .iter() + .filter_map(|event| match event { + ImportAsset::Dir(path) => Some(path), + _ => None, + }) + .for_each(|path| { + registry.0.extend( + server + .load_folder(String::from(path.to_string_lossy())) + .expect("Loading assets from folder"), + ); + }); + } + pub fn get_asset_name(server: &AssetServer, handle: Handle) -> String { if let Some(asset_path) = server.get_handle_path(handle.clone()) { if let Some(stem) = asset_path.path().file_stem() { @@ -1336,7 +1380,9 @@ mod reset { mut registry: ResMut, mut commands: Commands, ) { - events.iter().for_each(|entity| { + events.iter().for_each(|_| { + info!("Clearing assets"); + // Clear buttons holding asset references asset_holders .iter() diff --git a/bin/serialize-wtf.rs b/bin/serialize-wtf.rs index 7b4db11..871f7fc 100644 --- a/bin/serialize-wtf.rs +++ b/bin/serialize-wtf.rs @@ -1,33 +1,67 @@ -use std::{fs::File, io::Write}; - -use bevy::{audio::PlaybackMode, prelude::*, tasks::IoTaskPool}; +// TODO: +// * Determine where local assets folder needs to be created +// * Create local assets folder +// * Recusrively laod that folder and watch for changes +// * Copy assets into local folder in leue of importing them +// * Check portability by moving binary + folder to new location + +use std::{ + fs::{DirBuilder, File}, + io::Write, + time::Duration, +}; + +use bevy::{ + asset::{Asset, ChangeWatcher}, + audio::PlaybackMode, + gltf::Gltf, + prelude::*, + tasks::IoTaskPool, +}; use monologue_trees::{debug::*, ui}; fn main() { App::new() .init_resource::() .add_plugins(( - DefaultPlugins.set(WindowPlugin { - primary_window: Some(Window { - title: "Serialization WTF".into(), - resolution: (640., 480.).into(), + DefaultPlugins + .set(WindowPlugin { + primary_window: Some(Window { + title: "Serialization WTF".into(), + resolution: (640., 480.).into(), + ..default() + }), + ..default() + }) + .set(AssetPlugin { + asset_folder: "assets".into(), + // Tell the asset server to watch for asset changes on disk: + watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(0)), ..default() }), - ..default() - }), DebugInfoPlugin, ui::GameUiPlugin { ..default() }, )) - .add_systems(Startup, init) + .add_systems(Startup, (init, init_assets_dir)) .add_systems( Update, ( export.run_if(interaction_condition::), clear.run_if(interaction_condition::), import.run_if(interaction_condition::), + inspect.run_if(interaction_condition::), + load.run_if(interaction_condition::), + unload.run_if(interaction_condition::), + spawn_level.run_if(interaction_condition::), + asset_inspector::, + asset_inspector::, + ), + ) + .add_systems( + PostUpdate, + ( rehydrate::, rehydrate::, PlaybackSettings>, - inspect.run_if(interaction_condition::), fallback_camera.run_if(fallback_camera_condition), ), ) @@ -50,38 +84,37 @@ struct ImportAction; #[derive(Debug, Component)] struct InspectAction; +#[derive(Debug, Component)] +struct LoadAssetsAction; + +#[derive(Debug, Component)] +struct UnloadAssetsAction; + +#[derive(Debug, Component)] +struct SpawnLevelAction; + #[derive(Debug, Resource, Default)] struct AssetRegistry { handles: Vec, } -fn init(server: Res, mut commands: Commands, mut registry: ResMut) { +fn init_assets_dir() { + IoTaskPool::get() + .spawn(async move { + match DirBuilder::new().create("assets") { + Ok(_) => info!("Created assets directory"), + Err(e) => warn!("Error creating assets directory", e), + } + }) + .detach(); +} + +fn init(mut commands: Commands) { commands.spawn(( Camera2dBundle { ..default() }, UiCameraConfig { show_ui: true }, )); - let audio_handle: Handle = server.load("audio/Ambient/Lake Sound 1.ogg"); - let scene_handle: Handle = server.load("models/materials.glb#Scene0"); - commands - .spawn((SpatialBundle { ..default() }, LevelRoot)) - .with_children(|parent| { - parent.spawn(AudioSourceBundle { - source: audio_handle.clone(), - settings: PlaybackSettings { - mode: PlaybackMode::Loop, - paused: false, - ..default() - }, - }); - parent.spawn((SceneBundle { - scene: scene_handle.clone(), - ..default() - },)); - }); - registry.handles.push(audio_handle.clone_untyped()); - registry.handles.push(scene_handle.clone_untyped()); - commands .spawn(( NodeBundle { @@ -101,6 +134,57 @@ fn init(server: Res, mut commands: Commands, mut registry: ResMut>, mut commands: Commands) { }); } +// TODO: Figure out how to import the same asset from a differnt source +// How do the plugins do it?? fn import(mut commands: Commands, server: Res) { info!("Importing level"); @@ -295,3 +381,47 @@ fn fallback_camera( ) { ui_camera.single_mut().is_active = cameras.iter().len() <= 0; } + +fn asset_inspector(mut events: EventReader>) { + events.iter().for_each(|event| match event { + AssetEvent::Created { handle } => info!("Asset Created {:?}", handle), + AssetEvent::Modified { handle } => info!("Asset Modified {:?}", handle), + AssetEvent::Removed { handle } => info!("Asset Removed {:?}", handle), + }); +} + +// OK seems like `load_folder` does not automatically pick up added files +fn load(mut registry: ResMut, server: Res) { + info!("Loading assets"); + + registry.handles = server.load_folder("./dynamic").unwrap(); + info!("Current files: {:?}", registry.handles); +} + +fn unload(mut registry: ResMut, mut gltfs: ResMut>) { + info!("Unloading asstes"); + + registry.handles.clear(); + + // This is required to clear scenes from asset cache + gltfs.clear(); +} + +fn spawn_level(mut commands: Commands, server: Res) { + commands + .spawn((SpatialBundle { ..default() }, LevelRoot)) + .with_children(|parent| { + parent.spawn(AudioSourceBundle { + source: server.load::("dynamic/Lake Sound 1.ogg"), + settings: PlaybackSettings { + mode: PlaybackMode::Loop, + paused: false, + ..default() + }, + }); + parent.spawn((SceneBundle { + scene: server.load("dynamic/materials.glb#Scene0"), + ..default() + },)); + }); +} diff --git a/src/ui.rs b/src/ui.rs index d50ca93..f9a307f 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -439,33 +439,39 @@ mod buttons { ) { events .iter() - .filter(|(_, _, _, &interaction)| interaction == Interaction::Pressed) - .for_each(|(entity, parent, active, _)| { + .for_each(|(entity, parent, active, interaction)| { selects .get(parent.get()) .iter() - .for_each(|(select, children)| { - match active { - Some(_) => { - commands.entity(entity).remove::(); + .for_each(|(select, children)| match interaction { + Interaction::Pressed => { + match active { + Some(_) => { + commands.entity(entity).remove::(); + } + None => { + commands.entity(entity).insert(Active); + } } - None => { - commands.entity(entity).insert(Active); + match select { + Select::Multi | Select::Action => (), + Select::Single => { + children.iter().filter(|&child| *child != entity).for_each( + |&child| { + commands.entity(child).remove::(); + }, + ); + } } } - match select { + // A silly hack to get actions to maintain the active tag for 1+ frames + Interaction::None => match select { Select::Action => { commands.entity(entity).remove::(); } - Select::Multi => (), - Select::Single => { - children.iter().filter(|&child| *child != entity).for_each( - |&child| { - commands.entity(child).remove::(); - }, - ); - } - } + _ => (), + }, + _ => (), }); }); }