From 4a8d49365b3ea5442600accd3701b69185373370 Mon Sep 17 00:00:00 2001 From: Zicklag Date: Wed, 30 Aug 2023 15:55:20 +0000 Subject: [PATCH] feat!: enable rendering bones images in Egui. (#189) This also creates the concept of "shared resources" in the `bones_lib::Game`. Previously the asset server was the only shared resource, and it was manually coded, but now it's generic and there can be any number of shared resources that will be available across all game sessions. --- Cargo.lock | 2 +- demos/assets_minimal/src/main.rs | 7 +- demos/features/assets/game.yaml | 1 + demos/features/assets/menu-image.png | Bin 0 -> 38787 bytes demos/features/src/main.rs | 13 +- .../bones_bevy_renderer/src/lib.rs | 216 +++++++++++------- framework_crates/bones_ecs/src/resources.rs | 43 +++- framework_crates/bones_framework/Cargo.toml | 1 + framework_crates/bones_framework/src/lib.rs | 9 +- .../bones_framework/src/localization.rs | 5 +- .../bones_framework/src/render/ui.rs | 8 + framework_crates/bones_lib/Cargo.toml | 1 - framework_crates/bones_lib/src/lib.rs | 74 ++++-- 13 files changed, 260 insertions(+), 120 deletions(-) create mode 100644 demos/features/assets/menu-image.png diff --git a/Cargo.lock b/Cargo.lock index b6ae571a20..dce0f7d744 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1093,6 +1093,7 @@ dependencies = [ name = "bones_framework" version = "0.3.0" dependencies = [ + "bones_asset", "bones_lib", "document-features", "egui", @@ -1116,7 +1117,6 @@ dependencies = [ name = "bones_lib" version = "0.3.0" dependencies = [ - "bones_asset", "bones_ecs", ] diff --git a/demos/assets_minimal/src/main.rs b/demos/assets_minimal/src/main.rs index 8a577c804d..095fc1986f 100644 --- a/demos/assets_minimal/src/main.rs +++ b/demos/assets_minimal/src/main.rs @@ -22,8 +22,11 @@ fn main() { // First create bones game. let mut game = Game::new(); - // We must register all of our asset types before they can be loaded. - game.asset_server().register_asset::(); + game + // We initialize the asset server. + .init_shared_resource::() + // We must register all of our asset types before they can be loaded. + .register_asset::(); // Create a new session for the game menu. Each session is it's own bones world with it's own // plugins, systems, and entities. diff --git a/demos/features/assets/game.yaml b/demos/features/assets/game.yaml index f212544e2e..91240b9199 100644 --- a/demos/features/assets/game.yaml +++ b/demos/features/assets/game.yaml @@ -1,3 +1,4 @@ +menu_image: ./menu-image.png sprite_demo: ./sprite/fractal.png atlas_demo: ./atlas/atlas-demo.yaml tilemap_demo: ./tilemap/tilemap.yaml diff --git a/demos/features/assets/menu-image.png b/demos/features/assets/menu-image.png new file mode 100644 index 0000000000000000000000000000000000000000..39b5937521b30770304ddb5cbe5b6bff045c976c GIT binary patch literal 38787 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 P00000NkvXXu0mjf%6L@{ literal 0 HcmV?d00001 diff --git a/demos/features/src/main.rs b/demos/features/src/main.rs index 8fc7240704..9667ea4c5a 100644 --- a/demos/features/src/main.rs +++ b/demos/features/src/main.rs @@ -14,6 +14,8 @@ use bones_framework::prelude::*; // Allow asset to be loaded from "game.yaml" assets. #[type_data(metadata_asset("game"))] struct GameMeta { + /// The image displayed on the menu. + menu_image: Handle, /// The image for the sprite demo sprite_demo: Handle, /// Character information that will be loaded from a separate asset file. @@ -80,7 +82,7 @@ pub fn create_game() -> Game { let mut game = Game::new(); // Configure the asset server - game.asset_server() + game.init_shared_resource::() // Register the default asset types .register_default_assets() // Register our custom asset types @@ -118,9 +120,11 @@ fn menu_startup( /// Our main menu system. fn menu_system( + meta: Root, egui_ctx: ResMut, mut sessions: ResMut, mut session_options: ResMut, + egui_textures: Res, // Get the localization field from our `GameMeta` localization: Localization, ) { @@ -172,6 +176,13 @@ fn menu_system( .create("path2d_demo") .install_plugin(path2d_demo_plugin); } + + ui.add_space(40.0); + + // When using a bones image in egui, we have to get it's corresponding egui texture + // from the egui textures resource. + ui.label("Bones Image Rendered in Egui"); + ui.image(egui_textures.get(meta.menu_image), [100., 100.]); }); }); } diff --git a/framework_crates/bones_bevy_renderer/src/lib.rs b/framework_crates/bones_bevy_renderer/src/lib.rs index 127f365831..04fd22bacd 100644 --- a/framework_crates/bones_bevy_renderer/src/lib.rs +++ b/framework_crates/bones_bevy_renderer/src/lib.rs @@ -74,22 +74,40 @@ impl BonesImageIds { pub fn load_bones_images( &mut self, bones_assets: &mut bones::AssetServer, + bones_egui_textures: &mut bones::EguiTextures, bevy_images: &mut Assets, + bevy_egui_textures: &mut bevy_egui::EguiUserTextures, ) { - for asset in bones_assets.store.assets.values_mut() { + for (handle, cid) in bones_assets.store.asset_ids.iter() { + let asset = bones_assets.store.assets.get_mut(cid).unwrap(); if let Ok(image) = asset.data.try_cast_mut::() { - self.load_bones_image(image, bevy_images) + self.load_bones_image( + handle.typed(), + image, + bones_egui_textures, + bevy_images, + bevy_egui_textures, + ) } } } /// Load a bones image into bevy. - pub fn load_bones_image(&mut self, image: &mut bones::Image, bevy_images: &mut Assets) { + pub fn load_bones_image( + &mut self, + bones_handle: bones::Handle, + image: &mut bones::Image, + bones_egui_textures: &mut bones::EguiTextures, + bevy_images: &mut Assets, + bevy_egui_textures: &mut bevy_egui::EguiUserTextures, + ) { let Self { map, next_id } = self; let mut taken_image = bones::Image::External(0); // Dummy value temporarily std::mem::swap(image, &mut taken_image); if let bones::Image::Data(data) = taken_image { let handle = bevy_images.add(Image::from_dynamic(data, true)); + let egui_texture = bevy_egui_textures.add_image(handle.clone()); + bones_egui_textures.insert(bones_handle, egui_texture); map.insert(*next_id, handle); *image = bones::Image::External(*next_id); *next_id += 1; @@ -103,7 +121,7 @@ pub struct BonesData { /// The bones game. pub game: bones::Game, /// The bones asset server cell. - pub asset_server: bones::AtomicResource, + pub asset_server: Option>, } impl BonesBevyRenderer { @@ -122,7 +140,7 @@ impl BonesBevyRenderer { } /// Return a bevy [`App`] configured to run the bones game. - pub fn app(self) -> App { + pub fn app(mut self) -> App { let mut app = App::new(); // Initialize Bevy plugins we use @@ -142,10 +160,15 @@ impl BonesBevyRenderer { }) .init_resource::(); - { - let mut bones_image_ids = BonesImageIds::default(); - let mut asset_server = self.game.asset_server(); - let mut bevy_images = app.world.resource_mut::>(); + let mut bones_image_ids = BonesImageIds::default(); + let mut bones_egui_textures = bones::EguiTextures::default(); + 'asset_load: { + let Some(mut asset_server) = self.game.shared_resource::() else { + break 'asset_load; + }; + let world = app.world.cell(); + let mut bevy_images = world.resource_mut::>(); + let mut bevy_egui_textures = world.resource_mut::(); if !asset_server.asset_types.is_empty() { #[cfg(not(target_arch = "wasm32"))] @@ -160,22 +183,33 @@ impl BonesBevyRenderer { .expect("Could not load game assets"); // Take all loaded image assets and conver them to external images that reference bevy handles - bones_image_ids.load_bones_images(&mut asset_server, &mut bevy_images); + bones_image_ids.load_bones_images( + &mut asset_server, + &mut bones_egui_textures, + &mut bevy_images, + &mut bevy_egui_textures, + ); } #[cfg(target_arch = "wasm32")] { - bones_image_ids.load_bones_images(&mut asset_server, &mut bevy_images); + bones_image_ids.load_bones_images( + &mut asset_server, + &mut bones_egui_textures, + &mut bevy_images, + &mut bevy_egui_textures, + ); // TODO: Implement WASM asset loader. unimplemented!("WASM asset loading is not implemented yet."); } } - - app.insert_resource(bones_image_ids); } + self.game.insert_shared_resource(bones_egui_textures); + app.insert_resource(bones_image_ids); + // Insert the bones data app.insert_resource(BonesData { - asset_server: self.game.asset_server.clone_cell(), + asset_server: self.game.shared_resource_cell::(), game: self.game, }) .init_resource::(); @@ -257,76 +291,82 @@ fn step_bones_game( In((mouse_inputs, keyboard_inputs)): In<(bones::MouseInputs, bones::KeyboardInputs)>, world: &mut World, ) { - world.resource_scope(|world: &mut World, mut data: Mut| { - world.resource_scope( - |world: &mut World, mut bones_image_ids: Mut| { - world.resource_scope(|world: &mut World, mut bevy_images: Mut>| { - let egui_ctx = { - let mut egui_query = - world.query_filtered::<&mut EguiContext, With>(); - let mut egui_ctx = egui_query.get_single_mut(world).unwrap(); - egui_ctx.get_mut().clone() - }; - let BonesData { game, asset_server } = &mut *data; - let bevy_time = world.resource::