From 5513558f3d68956dbbdeca744bcbb944663e35c2 Mon Sep 17 00:00:00 2001 From: hodasemi Date: Thu, 27 Feb 2025 14:14:29 +0100 Subject: [PATCH] Fix engine for new concept --- .zed/settings.json | 0 context/src/core/context.rs | 86 ++++--- ecs/src/entity.rs | 2 - ecs/src/resources.rs | 10 + ecs/src/world.rs | 8 +- .../assets/{assetcache.rs => asset_cache.rs} | 16 +- .../{assetmanager.rs => asset_manager.rs} | 49 ++-- engine/src/assets/mod.rs | 4 +- engine/src/engine/asset_handler.rs | 77 +++--- engine/src/engine/engine.rs | 231 ++++++------------ engine/src/engine/engine_create_info.rs | 97 ++++++++ .../{engineobject.rs => engine_object.rs} | 0 .../{enginesettings.rs => engine_settings.rs} | 65 +++-- engine/src/engine/mod.rs | 5 +- engine/src/prelude.rs | 17 +- engine/src/scene/content/components/audio.rs | 49 ++-- engine/src/scene/scene/scene_base.rs | 126 +++++----- entity_manager/src/entity_manager.rs | 11 +- entity_manager/src/hitbox.rs | 11 +- examples/simple_window/src/main.rs | 25 +- presentation/src/input/eventsystem.rs | 224 ++++++++--------- presentation/src/presentationcore.rs | 6 +- presentation/src/renderbackend.rs | 3 +- presentation/src/traits.rs | 1 + 24 files changed, 546 insertions(+), 577 deletions(-) create mode 100644 .zed/settings.json rename engine/src/assets/{assetcache.rs => asset_cache.rs} (89%) rename engine/src/assets/{assetmanager.rs => asset_manager.rs} (86%) create mode 100644 engine/src/engine/engine_create_info.rs rename engine/src/engine/{engineobject.rs => engine_object.rs} (100%) rename engine/src/engine/{enginesettings.rs => engine_settings.rs} (88%) diff --git a/.zed/settings.json b/.zed/settings.json new file mode 100644 index 0000000..e69de29 diff --git a/context/src/core/context.rs b/context/src/core/context.rs index 3ac99c5..ee1357f 100644 --- a/context/src/core/context.rs +++ b/context/src/core/context.rs @@ -36,7 +36,7 @@ pub struct Context { render_core: Arc>>, #[cfg(feature = "sound")] - sound_handler: Mutex, + sound_handler: SoundHandler, os_specific: OsSpecific, @@ -61,45 +61,41 @@ impl Context { } #[cfg(feature = "sound")] - pub fn sound(&self) -> MutexGuard<'_, SoundHandler> { - self.sound_handler.lock().unwrap() + pub fn sound(&mut self) -> &mut SoundHandler { + &mut self.sound_handler } - pub fn run(&self, world: &mut World) -> Result<()> { - 'running: loop { - let render_core = self.render_core.clone(); + pub fn next_frame(&mut self, world: &mut World) -> Result { + let render_core = self.render_core.clone(); - match self.presentation.poll_events( - |event| { - // TODO - // if let Some(ctx_obj) = world.resources.get_mut_opt::() { - // ctx_obj.event(event)?; - // } + match self.presentation.poll_events( + |event| { + // TODO + // if let Some(ctx_obj) = world.resources.get_mut_opt::() { + // ctx_obj.event(event)?; + // } - Ok(()) - }, - |w, h| render_core.write().unwrap().resize(world, w, h), - ) { - Ok(res) => { - if !res { - break 'running; - } - } - Err(err) => { - if let Some(fallback) = &self.fallback { - (fallback)(err)?; - } + Ok(()) + }, + |w, h| render_core.write().unwrap().resize(world, w, h), + ) { + Ok(res) => { + if !res { + return Ok(false); } } - - if !self.render_core_mut().next_frame(world)? { - break 'running; + Err(err) => { + if let Some(fallback) = &self.fallback { + (fallback)(err)?; + } } } - self.render_core_mut().clear_post_processing_routines(); + if !self.render_core_mut().next_frame(world)? { + return Ok(false); + } - Ok(()) + Ok(true) } pub fn render_core(&self) -> impl Deref> + '_ { @@ -129,17 +125,17 @@ impl Context { self.core.queue() } - pub fn controllers(&self) -> RwLockReadGuard<'_, Vec>>> { + pub fn controllers(&self) -> &[Arc>] { self.presentation.event_system().controllers() } - pub fn active_controller(&self) -> Result>>> { - Ok(self.presentation.event_system().active_controller()?) + pub fn active_controller(&self) -> &Option>> { + self.presentation.event_system().active_controller() } - pub fn set_active_controller(&self, controller: &Arc>) { + pub fn set_active_controller(&mut self, controller: &Arc>) { self.presentation - .event_system() + .event_system_mut() .set_active_controller(controller) } } @@ -184,7 +180,7 @@ impl ContextInterface for Context { } #[cfg(feature = "sound")] - fn sound_handler(&self) -> MutexGuard<'_, SoundHandler> { + fn sound_handler(&mut self) -> &mut SoundHandler { self.sound() } } @@ -402,22 +398,22 @@ impl ContextBuilder { let vr_mode = self.get_vr_mode(); - let presentation = + let mut presentation = PresentationCore::new(vr_mode, &self.window_create_info, self.app_info.clone())?; presentation - .event_system() + .event_system_mut() .set_controller_axis_enable_deadzone(self.controller_deadzones.axis_enable_deadzone); presentation - .event_system() + .event_system_mut() .set_controller_axis_disable_deadzone(self.controller_deadzones.axis_disable_deadzone); presentation - .event_system() + .event_system_mut() .set_controller_trigger_enable_deadzone( self.controller_deadzones.trigger_enable_deadzone, ); presentation - .event_system() + .event_system_mut() .set_controller_trigger_disable_deadzone( self.controller_deadzones.trigger_disable_deadzone, ); @@ -440,15 +436,15 @@ impl ContextBuilder { )?; if self.enable_mouse { - presentation.event_system().enable_mouse(); + presentation.event_system_mut().enable_mouse(); } if self.enable_keyboard { - presentation.event_system().enable_keyboard(); + presentation.event_system_mut().enable_keyboard(); } if self.enable_controller { - presentation.event_system().enable_controller(); + presentation.event_system_mut().enable_controller(); } Ok(Context { @@ -457,7 +453,7 @@ impl ContextBuilder { render_core: Arc::new(RwLock::new(render_core)), #[cfg(feature = "sound")] - sound_handler: Mutex::new(self.create_sound_handler()?), + sound_handler: self.create_sound_handler()?, os_specific, diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs index 7151192..fdfdc35 100644 --- a/ecs/src/entity.rs +++ b/ecs/src/entity.rs @@ -9,8 +9,6 @@ use serde::{Deserialize, Serialize}; use crate::{ComponentDebug, ComponentNotFoundError, EntityComponent, MultiMut, TypeMap}; -pub const COMPONENT_SEPARATOR: char = 'ยง'; - #[derive(Debug)] pub struct EntityNotFoundError { entity: Entity, diff --git a/ecs/src/resources.rs b/ecs/src/resources.rs index 32b2101..f844fa6 100644 --- a/ecs/src/resources.rs +++ b/ecs/src/resources.rs @@ -4,6 +4,8 @@ use std::{ mem::transmute, }; +use utilities::prelude::{remove_life_time, remove_life_time_mut}; + #[derive(Default)] pub struct Resources { map: HashMap>, @@ -32,6 +34,10 @@ impl Resources { self.get_opt::().unwrap() } + pub fn get_unchecked<'a, T: Any + Send + Sync>(&self) -> &'a T { + unsafe { remove_life_time(self.get::()) } + } + pub fn get_opt(&self) -> Option<&T> { self.map .get(&TypeId::of::()) @@ -42,6 +48,10 @@ impl Resources { self.get_mut_opt::().unwrap() } + pub fn get_mut_unchecked<'a, T: Any + Send + Sync>(&mut self) -> &'a mut T { + unsafe { remove_life_time_mut(self.get_mut::()) } + } + pub fn get_mut_opt(&mut self) -> Option<&mut T> { self.map .get_mut(&TypeId::of::()) diff --git a/ecs/src/world.rs b/ecs/src/world.rs index c21109c..8a8d59d 100644 --- a/ecs/src/world.rs +++ b/ecs/src/world.rs @@ -79,12 +79,16 @@ impl World { } } + pub fn now(&self) -> Duration { + self.start_time.elapsed() + } + pub fn new_entity(&mut self) -> EntityObject { self.entity_object_manager.create_entity() } - pub fn now(&self) -> Duration { - self.start_time.elapsed() + pub fn entities(&self) -> impl Iterator { + self.entities.values() } pub fn entity( diff --git a/engine/src/assets/assetcache.rs b/engine/src/assets/asset_cache.rs similarity index 89% rename from engine/src/assets/assetcache.rs rename to engine/src/assets/asset_cache.rs index e687ec3..34dd09e 100644 --- a/engine/src/assets/assetcache.rs +++ b/engine/src/assets/asset_cache.rs @@ -6,8 +6,8 @@ use crate::prelude::*; use std::collections::HashMap; use std::sync::{ - atomic::{AtomicU32, Ordering}, Arc, RwLock, RwLockReadGuard, + atomic::{AtomicU32, Ordering}, }; use std::thread; @@ -25,8 +25,8 @@ pub struct AssetCache { impl AssetCache { pub(crate) fn new( - context: &Arc, - engine_settings: &Arc, + context: &Context, + engine_settings: &EngineSettings, loaded_assets: impl IntoIterator, names: impl IntoIterator, ) -> Result { @@ -52,7 +52,7 @@ impl AssetCache { let device = context.device().clone(); let queue = context.queue().clone(); - let engine_settings = engine_settings.clone(); + let render_type = engine_settings.graphics_info()?.render_type; let rw_lock_assets = rw_lock_assets.clone(); let ready_count = ready_count.clone(); @@ -63,13 +63,7 @@ impl AssetCache { } let gltf_asset = GltfAsset::new(&path)?; - let asset = Asset::new( - &device, - &queue, - engine_settings.graphics_info()?.render_type, - gltf_asset, - &name, - )?; + let asset = Asset::new(&device, &queue, render_type, gltf_asset, &name)?; { let mut locked_assets = rw_lock_assets.write().unwrap(); diff --git a/engine/src/assets/assetmanager.rs b/engine/src/assets/asset_manager.rs similarity index 86% rename from engine/src/assets/assetmanager.rs rename to engine/src/assets/asset_manager.rs index 5d1241b..789cb5f 100644 --- a/engine/src/assets/assetmanager.rs +++ b/engine/src/assets/asset_manager.rs @@ -9,7 +9,7 @@ use std::sync::{Arc, RwLock}; use std::thread; pub struct AssetManager { - engine_settings: Arc, + gltf_directory: AssetPath, gltf_file_list: Vec, @@ -22,9 +22,9 @@ pub struct AssetManager { impl AssetManager { /// Constructor for `AssetManager`, creates lists of '.gltf' and '.ent' files - pub(crate) fn new(engine_settings: Arc) -> Result { + pub(crate) fn new(engine_settings: &EngineSettings) -> Result { let mut asset_manager = AssetManager { - engine_settings, + gltf_directory: engine_settings.gltf_directory().clone(), gltf_file_list: Vec::new(), gltf_file_map: HashMap::new(), @@ -65,7 +65,7 @@ impl AssetManager { pub fn create_cache_with<'a, 'b>( &mut self, - context: &Arc, + world: &World, asset_names: impl IntoIterator + Clone, ) -> Result { let mut assets = Vec::new(); @@ -91,7 +91,12 @@ impl AssetManager { } } - AssetCache::new(context, &self.engine_settings, assets, names) + AssetCache::new( + world.resources.get::(), + world.resources.get::(), + assets, + names, + ) } /// Clears all loaded files @@ -111,9 +116,9 @@ impl AssetManager { /// Updates the lists of all '.gltf' and '.ent' files pub fn update_files(&mut self) -> Result<()> { let (mut gltf_file_list, gltf_file_map) = - super::search_file_names(self.engine_settings.gltf_directory(), ".gltf")?; + super::search_file_names(&self.gltf_directory, ".gltf")?; let (mut glb_file_list, glb_file_map) = - super::search_file_names(self.engine_settings.gltf_directory(), ".glb")?; + super::search_file_names(&self.gltf_directory, ".glb")?; gltf_file_list.append(&mut glb_file_list); @@ -127,7 +132,7 @@ impl AssetManager { /// Creates an empty `EditableEntity` pub fn load_asset_file(&mut self, world: &mut World, asset_file: &str) -> Result { // load asset - let asset = self.load_gltf_asset(world.resources.get::(), asset_file, true)?; + let asset = self.load_gltf_asset(world, asset_file, true)?; let mut entity_object = world.new_entity(); @@ -166,7 +171,11 @@ impl AssetManager { let asset = Asset::new( context.device(), context.queue(), - self.engine_settings.graphics_info()?.render_type, + world + .resources + .get::() + .graphics_info()? + .render_type, gltf_asset, asset_path, )?; @@ -196,7 +205,7 @@ impl AssetManager { pub fn async_load_gltf_file<'a, 'b>( &self, - context: &Arc, + world: &World, files: impl IntoIterator, ) -> Result<()> { let mut asset_files: Vec<(AssetPath, String)> = Vec::new(); @@ -214,12 +223,15 @@ impl AssetManager { } } + let context = world.resources.get::(); + let engine_settings = world.resources.get::(); + // naively spawn for every file a thread // TODO: spawn thread dependent on the cpu core count for (path, file_name) in asset_files { let device = context.device().clone(); let queue = context.queue().clone(); - let engine_settings = self.engine_settings.clone(); + let render_type = engine_settings.graphics_info()?.render_type; let loaded_gltf_files = self.loaded_gltf_files.clone(); let queued_for_async_load = self.queued_for_async_load.clone(); @@ -231,13 +243,7 @@ impl AssetManager { let gltf_asset = GltfAsset::new(&path)?; - let asset = Asset::new( - &device, - &queue, - engine_settings.graphics_info()?.render_type, - gltf_asset, - &file_name, - )?; + let asset = Asset::new(&device, &queue, render_type, gltf_asset, &file_name)?; { let mut gltf_files_lock = loaded_gltf_files.write().unwrap(); @@ -264,7 +270,10 @@ impl AssetManager { /// checks if the '.gltf' file with given name is already loaded, if not, loads it /// add - if true, adds the asset to the internal map - fn load_gltf_asset(&mut self, context: &Context, gltf_file: &str, add: bool) -> Result { + fn load_gltf_asset(&mut self, world: &World, gltf_file: &str, add: bool) -> Result { + let context = world.resources.get::(); + let engine_settings = world.resources.get::(); + loop { let queued_lock = self.queued_for_async_load.read().unwrap(); @@ -283,7 +292,7 @@ impl AssetManager { let asset = Asset::new( context.device(), context.queue(), - self.engine_settings.graphics_info()?.render_type, + engine_settings.graphics_info()?.render_type, gltf_asset, gltf_file, )?; diff --git a/engine/src/assets/mod.rs b/engine/src/assets/mod.rs index cd2e396..880658f 100644 --- a/engine/src/assets/mod.rs +++ b/engine/src/assets/mod.rs @@ -1,5 +1,5 @@ -pub mod assetcache; -pub mod assetmanager; +pub mod asset_cache; +pub mod asset_manager; use std::{collections::HashMap, path::Path}; diff --git a/engine/src/engine/asset_handler.rs b/engine/src/engine/asset_handler.rs index 568e5c7..e7319e1 100644 --- a/engine/src/engine/asset_handler.rs +++ b/engine/src/engine/asset_handler.rs @@ -1,8 +1,4 @@ -use std::marker::PhantomData; - -use std::sync::{Arc, RwLock}; - -use crate::assets::assetmanager::AssetManager; +use crate::assets::asset_manager::AssetManager; use crate::prelude::*; @@ -12,80 +8,69 @@ pub trait AssetLoader { fn load_entity(&mut self, assets: AssetHandler<'_>, entity_file: &str) -> Result; } -#[derive(Clone, Copy)] pub struct AssetHandler<'a> { - pub(crate) asset_manager: &'a RwLock, - - pub(crate) resource_base_path: &'a String, - - pub(crate) phantom_data: PhantomData<&'a ()>, + world: &'a mut World, + asset_manager: &'a mut AssetManager, + resource_base_path: String, } impl<'a> AssetHandler<'a> { - pub fn context(&self) -> &Arc { - self.context + pub fn create(world: &'a mut World) -> Self { + let asset_manager = world.resources.get_mut_unchecked::(); + let engine = world.resources.get::(); + + Self { + asset_manager, + resource_base_path: engine.resource_base_path.clone(), + world, + } } - pub fn update_file_cache(&self) -> Result<()> { - self.asset_manager.write().unwrap().update_files() + pub fn update_file_cache(&mut self) -> Result<()> { + self.asset_manager.update_files() } pub fn preload_assets<'b>(&self, files: impl IntoIterator) -> Result<()> { - self.asset_manager - .read() - .unwrap() - .async_load_gltf_file(self.context, files) + self.asset_manager.async_load_gltf_file(self.world, files) } pub fn create_cache<'b>( - &self, + &mut self, names: impl IntoIterator + Clone, ) -> Result { - self.asset_manager - .write() - .unwrap() - .create_cache_with(self.context, names) + self.asset_manager.create_cache_with(self.world, names) } pub fn insert_cache(&self, cache: &AssetCache) -> Result<()> { - self.asset_manager - .read() - .unwrap() - .insert_cached_assets(cache) + self.asset_manager.insert_cached_assets(cache) } - pub fn clear(&self) -> Result<()> { - self.asset_manager.write().unwrap().clear() + pub fn clear(&mut self) -> Result<()> { + self.asset_manager.clear() } pub fn gltf_files(&self) -> Result> { - Ok(self.asset_manager.read().unwrap().gltf_files().clone()) + Ok(self.asset_manager.gltf_files().clone()) } - pub fn create_entity(&self, asset_file: &str) -> Result { - self.asset_manager.write().unwrap().load_asset_file( - self.context, - self.entity_object_manager, - asset_file, - ) + pub fn create_entity(&mut self, asset_file: &str) -> Result { + self.asset_manager.load_asset_file(self.world, asset_file) } - pub fn create_entity_absolute(&self, asset_path: &str) -> Result { + pub fn create_entity_absolute(&mut self, asset_path: &str) -> Result { self.asset_manager - .write() - .unwrap() - .load_asset_file_absolute(self.context, self.entity_object_manager, asset_path) + .load_asset_file_absolute(self.world, asset_path) } - pub fn empty_entity(&self) -> EntityObject { - self.entity_object_manager.create_entity() + pub fn empty_entity(&mut self) -> EntityObject { + self.world.new_entity() } pub fn resource_base_path(&self) -> &str { - self.resource_base_path + &self.resource_base_path } - pub(crate) fn get_entity_id(&self) -> u32 { - self.entity_object_manager.fetch_add_entity_id() + pub fn world(&mut self) -> &mut World { + &mut self.world } } diff --git a/engine/src/engine/engine.rs b/engine/src/engine/engine.rs index ad33187..96143ec 100644 --- a/engine/src/engine/engine.rs +++ b/engine/src/engine/engine.rs @@ -1,56 +1,17 @@ #![allow(clippy::type_complexity)] -use super::asset_handler::AssetHandler; - -use super::engineobject::*; -use super::enginesettings::EngineSettings; +use super::engine_object::*; +use super::engine_settings::EngineSettings; use anyhow::Result; use assetpath::AssetPath; use context::prelude::cgmath::vec3; -use loading_screen::LoadingScreen; -use crate::assets::assetmanager::AssetManager; +use crate::assets::asset_manager::AssetManager; use crate::prelude::*; -use std::sync::{Arc, RwLock, RwLockReadGuard}; -use std::{collections::HashMap, marker::PhantomData}; -use std::{ - ptr::NonNull, - sync::{Mutex, MutexGuard}, -}; - -#[derive(Default, Debug, Clone)] -pub struct EngineCreateInfo<'a> { - pub app_info: ApplicationInfo, - - pub window_info: WindowCreateInfo, - - pub os_specific_config: OsSpecificConfig, - - pub vulkan_debug_info: VulkanDebugInfo, - pub volume_info: HashMap, - - pub gui_info: GuiHandlerCreateInfo<'a>, - - pub enable_backtrace: bool, - pub enable_mouse: bool, - pub enable_keyboard: bool, - pub enable_controller: bool, - - pub controller_deadzones: ControllerDeadzones, - - pub resource_base_path: String, - - // engine settings - pub controller_directories: ControllerPictureDirectories, - pub asset_directories: AssetDirectories, - - pub graphics_info: GraphicsInfo, - pub raytracing_info: RaytracingInfo, - pub rasterizer_info: RasterizerInfo, - pub key_backgrounds: ButtonBackgrounds, -} +use std::collections::HashMap; +use std::sync::{Arc, RwLock}; struct GuiPostProcess(Arc); @@ -73,37 +34,34 @@ impl context::prelude::PostProcess for GuiPostProcess { } pub struct Engine { - engine_settings: Arc, - - gui_handler: Arc, - gui_post_process: Arc, input: Arc>, // loads and keeps track of raw data asset_manager: AssetManager, - resource_base_path: String, + pub(crate) resource_base_path: String, } impl Engine { - pub fn new(#[allow(unused)] mut create_info: EngineCreateInfo<'_>) -> Result { - if let Font::Path(path) = &mut create_info.gui_info.font { - path.set_prefix(&create_info.resource_base_path); - } - create_info.gui_info.resource_directory.assume_prefix_free(); - + pub fn new( + #[allow(unused)] mut create_info: EngineCreateInfo<'_>, + world: &mut WorldBuilder, + ) -> Result<()> { create_info .controller_directories .xbox_path - .set_prefix(&create_info.resource_base_path); + .as_mut() + .map(|p| p.set_prefix(&create_info.resource_base_path)); create_info .controller_directories .steam_path - .set_prefix(&create_info.resource_base_path); + .as_mut() + .map(|p| p.set_prefix(&create_info.resource_base_path)); create_info .controller_directories .ps4_path - .set_prefix(&create_info.resource_base_path); + .as_mut() + .map(|p| p.set_prefix(&create_info.resource_base_path)); create_info .asset_directories @@ -129,7 +87,7 @@ impl Engine { // --------------- context -------------------- - let context = { + let mut context = { create_info.app_info.engine_name = "EngineNameNeeded".to_string(); create_info.app_info.engine_version = 1; @@ -182,10 +140,9 @@ impl Engine { }; // update sound handler center - { - let sound_handler = context.sound(); - sound_handler.set_direction(vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0))?; - } + context + .sound() + .set_direction(vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0))?; // --------------- settings ------------------- @@ -198,7 +155,7 @@ impl Engine { .ok_or_else(|| anyhow::Error::msg("No proper render type could be found"))?; } - let engine_settings = Arc::new(EngineSettings::new( + let engine_settings = EngineSettings::new( &context, create_info.graphics_info, create_info.raytracing_info, @@ -207,15 +164,26 @@ impl Engine { create_info.asset_directories, create_info.key_backgrounds, create_info.resource_base_path.clone(), - )?); - - let asset_manager = AssetManager::new(engine_settings.clone())?; - - let gui_handler = GuiHandler::new( - create_info.gui_info, - &(context.clone() as Arc), )?; + let asset_manager = AssetManager::new(&engine_settings)?; + + if let Some(mut gui_info) = create_info.gui_info { + if let Font::Path(path) = &mut gui_info.font { + path.set_prefix(&create_info.resource_base_path); + } + gui_info.resource_directory.assume_prefix_free(); + + let gui_handler = GuiHandler::new(gui_info, &context)?; + + let gui_post_process = Arc::new(GuiPostProcess(gui_handler.clone())); + context + .render_core() + .add_post_processing_routine(gui_post_process.clone()); + + world.resources.insert(gui_handler); + } + // default keyboard navigation let mut direction_mapping = HashMap::new(); // direction_mapping.insert(Keycode::A, GuiDirection::Left); @@ -227,105 +195,62 @@ impl Engine { direction_mapping.insert(Keycode::Up, GuiDirection::Up); direction_mapping.insert(Keycode::Down, GuiDirection::Down); - let input = Input { direction_mapping }; - - let gui_post_process = Arc::new(GuiPostProcess(gui_handler.clone())); - context - .render_core() - .add_post_processing_routine(gui_post_process.clone()); - - Ok(Engine { - gui_post_process, - gui_handler, - input: Arc::new(RwLock::new(input)), + let engine = Engine { + input: Arc::new(RwLock::new(Input { direction_mapping })), asset_manager, resource_base_path: create_info.resource_base_path, + }; - engine_settings, - }) - } + world.resources.insert(context); + world.resources.insert(engine); + world.resources.insert(engine_settings); - pub fn set_game_object(&self, engine_object: Option) -> Result<()> - where - E: EngineObject + Send + Sync, - { - self.context().set_context_object(match engine_object { - Some(engine_object) => Some(ContextObjectImpl::new( - self.graphical.context.clone(), - engine_object, - self.graphical.input.clone(), - self.gui_handler().clone(), - )?), - None => None, - }); + world.add_system(Self::main_system); Ok(()) } - pub fn loading_screen( - &self, - gui: Option>, - loader: L, - on_ready: R, - ) -> Result<()> - where - R: Fn(T) -> anyhow::Result<()> + 'static + Send + Sync, - T: Send + Sync + 'static, - L: FnOnce() -> T + Send + Sync + 'static, - G: TopLevelGui + TopGui + Send + Sync + 'static, - { - LoadingScreen::load(self.context(), gui, loader, on_ready) - } + // pub fn set_game_object(&self, engine_object: Option) -> Result<()> + // where + // E: EngineObject + Send + Sync, + // { + // self.context().set_context_object(match engine_object { + // Some(engine_object) => Some(ContextObjectImpl::new( + // self.graphical.context.clone(), + // engine_object, + // self.graphical.input.clone(), + // self.gui_handler().clone(), + // )?), + // None => None, + // }); - pub fn new_point_light(&self) -> Result { - Light::point_light(self.context().device()) - } + // Ok(()) + // } - pub fn new_directional_light(&self) -> Result { - Light::directional_light(self.context().device()) - } - - pub fn new_spot_light(&self) -> Result { - Light::spot_light(self.context().device()) - } - - pub fn controller_icon(&self, button: ControllerButton) -> Result> { - Ok(self.settings().controller_icon(self, button)?.unwrap_or( - self.settings() - .controller_button_for(self, button, ControllerType::XBox)?, - )) - } + // pub fn loading_screen( + // &self, + // gui: Option>, + // loader: L, + // on_ready: R, + // ) -> Result<()> + // where + // R: Fn(T) -> anyhow::Result<()> + 'static + Send + Sync, + // T: Send + Sync + 'static, + // L: FnOnce() -> T + Send + Sync + 'static, + // G: TopLevelGui + TopGui + Send + Sync + 'static, + // { + // LoadingScreen::load(self.context(), gui, loader, on_ready) + // } pub fn build_path(&self, path: &str) -> AssetPath { (self.resource_base_path.as_str(), path).into() } - pub fn assets(&self) -> AssetHandler<'_> { - AssetHandler { - asset_manager: &self.asset_manager, + pub fn main_system(world: &mut World) -> Result<()> { + // - context: &self.graphical.context, - - resource_base_path: &self.resource_base_path, - - phantom_data: PhantomData, - } - } -} - -// getter -impl Engine { - pub fn settings(&self) -> &Arc { - &self.engine_settings - } -} - -impl Drop for Engine { - fn drop(&mut self) { - self.context - .render_core() - .remove_post_processing_routine(self.gui_post_process.clone()); + Ok(()) } } diff --git a/engine/src/engine/engine_create_info.rs b/engine/src/engine/engine_create_info.rs new file mode 100644 index 0000000..c26c99d --- /dev/null +++ b/engine/src/engine/engine_create_info.rs @@ -0,0 +1,97 @@ +use std::collections::HashMap; + +use crate::prelude::*; + +#[derive(Debug, Clone)] +pub struct EngineCreateInfo<'a> { + pub app_info: ApplicationInfo, + + pub window_info: WindowCreateInfo, + + pub os_specific_config: OsSpecificConfig, + + pub vulkan_debug_info: VulkanDebugInfo, + pub volume_info: HashMap, + + pub gui_info: Option>, + + pub enable_backtrace: bool, + pub enable_mouse: bool, + pub enable_keyboard: bool, + pub enable_controller: bool, + + pub controller_deadzones: ControllerDeadzones, + + pub resource_base_path: String, + + // engine settings + pub controller_directories: ControllerPictureDirectories, + pub asset_directories: AssetDirectories, + + pub graphics_info: GraphicsInfo, + pub raytracing_info: RaytracingInfo, + pub rasterizer_info: RasterizerInfo, + pub key_backgrounds: ButtonBackgrounds, +} + +impl<'a> Default for EngineCreateInfo<'a> { + fn default() -> Self { + Self { + app_info: ApplicationInfo { + application_name: "Default Application Name".to_string(), + application_version: 1, + engine_name: "Default Engine Name".to_string(), + engine_version: 1, + }, + window_info: WindowCreateInfo { + title: "Default Window Title".to_string(), + width: 1600, + height: 900, + fullscreen: false, + requested_display: None, + }, + os_specific_config: OsSpecificConfig { + enable_game_mode: true, + }, + vulkan_debug_info: VulkanDebugInfo { + debugging: false, + steam_layer: false, + verbose: false, + renderdoc: false, + }, + volume_info: HashMap::new(), + gui_info: None, + enable_backtrace: true, + enable_mouse: true, + enable_keyboard: true, + enable_controller: true, + controller_deadzones: ControllerDeadzones::default(), + resource_base_path: String::new(), + controller_directories: ControllerPictureDirectories::default(), + asset_directories: AssetDirectories::default(), + graphics_info: GraphicsInfo { + sample_count: VK_SAMPLE_COUNT_4_BIT, + render_type: SceneType::Raytracer, + render_scale: 1.0, + vsync: true, + }, + raytracing_info: RaytracingInfo { + triangles_per_as: 8, + accelerate_buffer_size: 1024, + stack_size: 32, + + max_lights: 32, + recursion_depth: 3, + use_default_pipeline: true, + max_samplers: 1024, + }, + rasterizer_info: RasterizerInfo { + shadow_image_size: 1024, + enable_lighting: true, + use_deferred: false, + use_shadow_maps: false, + }, + key_backgrounds: ButtonBackgrounds::default(), + } + } +} diff --git a/engine/src/engine/engineobject.rs b/engine/src/engine/engine_object.rs similarity index 100% rename from engine/src/engine/engineobject.rs rename to engine/src/engine/engine_object.rs diff --git a/engine/src/engine/enginesettings.rs b/engine/src/engine/engine_settings.rs similarity index 88% rename from engine/src/engine/enginesettings.rs rename to engine/src/engine/engine_settings.rs index ac25395..34f632e 100644 --- a/engine/src/engine/enginesettings.rs +++ b/engine/src/engine/engine_settings.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{Result, bail}; use assetpath::AssetPath; use crate::prelude::*; @@ -54,9 +54,9 @@ pub struct RasterizerInfo { #[derive(Debug, Clone, Default)] pub struct ControllerPictureDirectories { - pub xbox_path: AssetPath, - pub steam_path: AssetPath, - pub ps4_path: AssetPath, + pub xbox_path: Option, + pub steam_path: Option, + pub ps4_path: Option, } #[derive(Debug, Clone, Default)] @@ -97,7 +97,7 @@ pub struct EngineSettings { impl EngineSettings { #[allow(clippy::too_many_arguments)] pub fn new( - context: &Arc, + context: &Context, mut graphics_info: GraphicsInfo, raytracing_info: RaytracingInfo, rasterizer_info: RasterizerInfo, @@ -191,15 +191,25 @@ impl EngineSettings { pub fn controller_icon( &self, - engine: &Engine, + context: &Context, + button: ControllerButton, + ) -> Result> { + Ok(self + ._controller_icon(context, button)? + .unwrap_or(self.controller_button_for(context, button, ControllerType::XBox)?)) + } + + fn _controller_icon( + &self, + context: &Context, button: ControllerButton, ) -> Result>> { // TODO: don't check it every time we request a button - self.check_controller(engine.context())?; + self.check_controller(context)?; match self.current_controller_type.read().unwrap().as_ref() { Some(controller_type) => Ok(Some(self.controller_button_for( - engine, + context, button, *controller_type, )?)), @@ -209,7 +219,7 @@ impl EngineSettings { pub fn controller_button_for( &self, - engine: &Engine, + context: &Context, button: ControllerButton, controller: ControllerType, ) -> Result> { @@ -219,26 +229,27 @@ impl EngineSettings { return Ok(image.clone()); } - let image_path = match controller { - ControllerType::PS4 => AssetPath::from(( - self.controller_directories.ps4_path.full_path(), - Self::ps4_input_map_to_texture(&button), - )), - ControllerType::Steam => AssetPath::from(( - self.controller_directories.steam_path.full_path(), - Self::steam_input_map_to_texture(&button), - )), - ControllerType::XBox => AssetPath::from(( - self.controller_directories.xbox_path.full_path(), - Self::xbox_input_map_to_texture(&button), - )), + let image_path_opt = match controller { + ControllerType::PS4 => self.controller_directories.ps4_path.as_ref().map(|path| { + AssetPath::from((path.full_path(), Self::ps4_input_map_to_texture(&button))) + }), + ControllerType::Steam => self.controller_directories.steam_path.as_ref().map(|path| { + AssetPath::from((path.full_path(), Self::steam_input_map_to_texture(&button))) + }), + + ControllerType::XBox => self.controller_directories.xbox_path.as_ref().map(|path| { + AssetPath::from((path.full_path(), Self::xbox_input_map_to_texture(&button))) + }), }; - let ctx = engine.context(); + let image_path = match image_path_opt { + Some(p) => p, + None => bail!("path not set"), + }; let image = Image::from_file(image_path)? - .attach_sampler(Sampler::nearest_sampler().build(ctx.device())?) - .build(ctx.device(), ctx.queue())?; + .attach_sampler(Sampler::nearest_sampler().build(context.device())?) + .build(context.device(), context.queue())?; map.insert(button, image.clone()); @@ -336,8 +347,8 @@ impl EngineSettings { } } - fn check_controller(&self, context: &Arc) -> Result<()> { - let active_controller = context.active_controller()?; + fn check_controller(&self, context: &Context) -> Result<()> { + let active_controller = context.active_controller(); match &active_controller { // there is an controller connected diff --git a/engine/src/engine/mod.rs b/engine/src/engine/mod.rs index 7658fb9..38d99be 100644 --- a/engine/src/engine/mod.rs +++ b/engine/src/engine/mod.rs @@ -1,7 +1,8 @@ pub mod engine; -pub mod enginesettings; +pub mod engine_settings; -pub mod engineobject; +pub mod engine_object; pub mod asset_handler; +pub mod engine_create_info; // pub mod engine_object_data; diff --git a/engine/src/prelude.rs b/engine/src/prelude.rs index 860bd66..c763426 100644 --- a/engine/src/prelude.rs +++ b/engine/src/prelude.rs @@ -7,18 +7,13 @@ pub use loading_screen::*; pub use crate::scene::prelude::*; pub use crate::engine::{ - // engine_object_data::*, - engineobject::{ - EngineObject, - // EngineObjectHelper - }, + asset_handler::{AssetHandler, AssetLoader}, + engine::*, + engine_create_info::EngineCreateInfo, + engine_object::{EngineEvent, EngineObject}, + engine_settings::*, }; -pub use crate::engine::asset_handler::{AssetHandler, AssetLoader}; -pub use crate::engine::{engine::*, enginesettings::*}; - -pub use crate::engine::engineobject::EngineEvent; - pub use serde::{ Deserialize, Deserializer, Serialize, Serializer, ser::{SerializeMap, SerializeSeq, SerializeStruct}, @@ -27,7 +22,7 @@ pub use serde::{ pub use ecs::*; pub use ron; -pub use crate::assets::assetcache::AssetCache; +pub use crate::assets::asset_cache::AssetCache; pub use asset::*; diff --git a/engine/src/scene/content/components/audio.rs b/engine/src/scene/content/components/audio.rs index 81ff832..b21983c 100644 --- a/engine/src/scene/content/components/audio.rs +++ b/engine/src/scene/content/components/audio.rs @@ -16,12 +16,11 @@ pub struct Audio { current_state: Option>, position: Vector3, - context: Arc, } impl Audio { pub fn new( - context: &Arc, + context: &mut Context, sounds: impl Into>>, ) -> Result { let mut sound_map = HashMap::new(); @@ -43,12 +42,11 @@ impl Audio { current_state: None, position: Vector3::zero(), - context: context.clone(), }) } pub fn from_info( - context: &Arc, + context: &mut Context, data_prefix: &str, sounds: Vec<(String, AssetPath)>, ) -> Result { @@ -75,10 +73,14 @@ impl Audio { Ok(()) } - pub fn set_sound(&mut self, path: AssetPath, sound_type: &str) -> Result<()> { + pub fn set_sound( + &mut self, + context: &mut Context, + path: AssetPath, + sound_type: &str, + ) -> Result<()> { if let Some(audio) = self.custom_sounds.get_mut(sound_type) { - *audio = self - .context + *audio = context .sound() .load_sound(path, "sfx", SoundInterpretation::Spatial)?; } @@ -101,9 +103,9 @@ impl Audio { Ok(()) } - fn clear(&mut self) -> Result<()> { + fn clear(&mut self, context: &mut Context) -> Result<()> { for sound in self.custom_sounds.values() { - self.context.sound().remove_sound(sound)?; + context.sound().remove_sound(sound)?; } Ok(()) @@ -147,10 +149,15 @@ impl Audio { Ok(()) } - pub fn add_custom_sound(&mut self, path: AssetPath, sound_type: &str) -> Result<()> { + pub fn add_custom_sound( + &mut self, + context: &mut Context, + path: AssetPath, + sound_type: &str, + ) -> Result<()> { self.custom_sounds.insert( sound_type.to_string(), - self.context + context .sound() .load_sound(path, "sfx", SoundInterpretation::Spatial)?, ); @@ -168,8 +175,14 @@ impl EntityComponent for Audio { self.play(ON_ENABLE_SOUND, false) } - fn disable(&mut self, _world: &mut World) -> Result<()> { - self.play(ON_DISABLE_SOUND, false) + fn disable(&mut self, world: &mut World) -> Result<()> { + self.play(ON_DISABLE_SOUND, false)?; + + if let Some(sound) = &self.current_state { + sound.stop_looping().unwrap(); + } + + self.clear(world.resources.get_mut::()) } } @@ -178,13 +191,3 @@ impl ComponentDebug for Audio { "Audio" } } - -impl Drop for Audio { - fn drop(&mut self) { - if let Some(sound) = &self.current_state { - sound.stop_looping().unwrap(); - } - - self.clear().unwrap(); - } -} diff --git a/engine/src/scene/scene/scene_base.rs b/engine/src/scene/scene/scene_base.rs index 95988d9..f8e96a3 100644 --- a/engine/src/scene/scene/scene_base.rs +++ b/engine/src/scene/scene/scene_base.rs @@ -18,7 +18,6 @@ use rayon::prelude::*; use utilities::prelude::cgmath::{Matrix4, Vector3, vec3}; use std::sync::Mutex; -use std::time::Instant; #[cfg(feature = "timings")] use std::time::Instant; @@ -32,18 +31,15 @@ pub struct Scene { device: Arc, queue: Arc>, - pub(crate) render_type: SceneType, + render_type: SceneType, - pub(crate) map: Option>, - - pub(crate) start_time: Instant, - pub(crate) last_frame: Duration, - pub(crate) frame_time: Duration, + last_frame: Duration, + frame_time: Duration, // renderer of this scene - pub(crate) renderer: Box, + renderer: Box, - pub(crate) frustum_check: Option< + frustum_check: Option< Box< dyn Fn(&EntityObject, &Matrix4, &ViewFrustum, &FrustumPlanes) -> Result + Send @@ -51,10 +47,10 @@ pub struct Scene { >, >, - pub(crate) particle_system_vulkan_objects: ParticleSystemVulkanObjects, + particle_system_vulkan_objects: ParticleSystemVulkanObjects, #[cfg(feature = "timings")] - pub(crate) timings: Timings, + timings: Timings, } impl Scene { @@ -87,7 +83,7 @@ impl Scene { let particle_system_vulkan_objects = ParticleSystemVulkanObjects::new(device, queue, cs)?; - let mut scene = Scene { + let scene = Scene { screen_width, screen_height, @@ -95,13 +91,11 @@ impl Scene { device: device.clone(), queue: queue.clone(), - map: None, frustum_check: None, renderer, - start_time: Instant::now(), last_frame: Duration::from_secs(0), frame_time: Duration::from_secs(0), @@ -124,19 +118,6 @@ impl Scene { } } -// object handling -impl Scene { - pub fn set_map(&mut self, map_opt: Option>) -> Result<()> { - if let Some(old_map) = self.map.take() { - old_map.disable(self)?; - } - - self.map = map_opt; - - Ok(()) - } -} - impl Scene { pub(crate) fn _world_to_screen_space( (screen_width, screen_height): (f32, f32), @@ -189,12 +170,13 @@ impl Scene { VkCommandBufferBeginInfo::new(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); begin_info.set_inheritance_info(&inheritance_info); - let scene = world.resources.get_mut::(); + let scene = world.resources.get_mut_unchecked::(); let particle_handles = scene.particle_system_vulkan_objects_mut(); + let pipeline = particle_handles.pipeline.clone(); let mut recorder = particle_handles.begin(begin_info)?; - particle_system.animate(&mut recorder, &particle_handles.pipeline, world)?; + particle_system.animate(&mut recorder, &pipeline, world)?; } Ok(()) @@ -405,9 +387,10 @@ impl TScene for Scene { buffer_recorder: &mut CommandBufferRecorder<'_>, images: &TargetMode>>, indices: &TargetMode, + world: &World, ) -> anyhow::Result<()> { self.frame_time = { - let now = self.now(); + let now = world.now(); let d = if self.last_frame < now { now - self.last_frame @@ -430,11 +413,8 @@ impl TScene for Scene { } } - // calculate movements and collision detection when map is present - if self.map.is_some() { - self.update()?; - - // queue particle system commands + // queue particle system commands + { #[cfg(feature = "timings")] let before = Instant::now(); @@ -446,50 +426,54 @@ impl TScene for Scene { .add("particles", Instant::now().duration_since(before)); } - #[cfg(feature = "timings")] - let before = Instant::now(); + // gather entities + let content = { + #[cfg(feature = "timings")] + let before = Instant::now(); - let content = match &self.frustum_check { - Some(frustum_check) => { - let view = self.renderer.view(); - let vp = view.proj() * view.camera().old_view_matrix(); + let content = match &self.frustum_check { + Some(frustum_check) => { + let view = self.renderer.view(); + let vp = view.proj() * view.camera().old_view_matrix(); - let frustum = view.frustum(); - let planes = frustum.planes(); + let frustum = view.frustum(); + let planes = frustum.planes(); - let content: Vec> = self - .entities - .par_values() - .map(|entity_object| { - if frustum_check(entity_object, &vp, &frustum, &planes)? { - Ok(Some(entity_object)) - } else { - Ok(None) - } - }) - .collect::>>>()?; + let content: Vec> = world + .entities() + .map(|entity_object| { + if frustum_check(entity_object, &vp, &frustum, &planes)? { + Ok(Some(entity_object)) + } else { + Ok(None) + } + }) + .collect::>>>()?; - content.into_iter().flatten().collect() - } - None => self - .entities - .par_iter() - .map(|(_entity, entity_object)| entity_object) - .collect(), + content.into_iter().flatten().collect() + } + None => world.entities().collect(), + }; + + #[cfg(feature = "timings")] + self.timings + .add("frustum", Instant::now().duration_since(before)); + + content }; - #[cfg(feature = "timings")] - self.timings - .add("frustum", Instant::now().duration_since(before)); + // render + { + #[cfg(feature = "timings")] + let before = Instant::now(); - #[cfg(feature = "timings")] - let before = Instant::now(); - self.renderer - .process(content, buffer_recorder, images, indices)?; + self.renderer + .process(content, buffer_recorder, images, indices)?; - #[cfg(feature = "timings")] - self.timings - .add("renderer", Instant::now().duration_since(before)); + #[cfg(feature = "timings")] + self.timings + .add("renderer", Instant::now().duration_since(before)); + } Ok(()) } diff --git a/entity_manager/src/entity_manager.rs b/entity_manager/src/entity_manager.rs index 70550a1..0e0d4b3 100644 --- a/entity_manager/src/entity_manager.rs +++ b/entity_manager/src/entity_manager.rs @@ -124,7 +124,11 @@ impl EntityManager { impl AssetLoader for EntityManager { /// Loads an entity file and creates an Entity - fn load_entity(&mut self, assets: AssetHandler<'_>, entity_file: &str) -> Result { + fn load_entity( + &mut self, + mut assets: AssetHandler<'_>, + entity_file: &str, + ) -> Result { // load entity file let file = self.load_entity_file(entity_file); @@ -165,7 +169,10 @@ impl AssetLoader for EntityManager { } } - entity_object.insert_component(Audio::new(assets.context(), entity_parser.sound_map)?); + entity_object.insert_component(Audio::new( + assets.world().resources.get_mut::(), + entity_parser.sound_map, + )?); } Ok(entity_object) diff --git a/entity_manager/src/hitbox.rs b/entity_manager/src/hitbox.rs index 92d8a78..2691bec 100644 --- a/entity_manager/src/hitbox.rs +++ b/entity_manager/src/hitbox.rs @@ -9,7 +9,7 @@ pub enum CollisionEventType { } pub type HitCallback = - dyn FnMut(&mut SceneContents<'_>, Entity, Entity) -> Result + Send + Sync; + dyn FnMut(&mut World, Entity, Entity) -> Result + Send + Sync; // HitBox is basically a cylinder pub struct HitBox { @@ -88,10 +88,7 @@ impl HitBox { pub fn set_event(&mut self, f: F) where - F: FnMut(&mut SceneContents<'_>, Entity, Entity) -> Result - + Send - + Sync - + 'static, + F: FnMut(&mut World, Entity, Entity) -> Result + Send + Sync + 'static, { self.hit_event = Some(Box::new(f)); } @@ -126,12 +123,12 @@ impl HitBox { pub fn collision( &mut self, - scene: &mut SceneContents<'_>, + world: &mut World, me: Entity, collider: Entity, ) -> Result { match &mut self.hit_event { - Some(hit_event) => hit_event(scene, me, collider), + Some(hit_event) => hit_event(world, me, collider), None => Ok(CollisionEventType::Ignore), } } diff --git a/examples/simple_window/src/main.rs b/examples/simple_window/src/main.rs index 3ab8015..ac8a572 100644 --- a/examples/simple_window/src/main.rs +++ b/examples/simple_window/src/main.rs @@ -6,30 +6,7 @@ use engine::prelude::*; fn main() -> Result<()> { let mut world_builder = World::builder(); - let (context, engine, scene) = Engine::new(EngineCreateInfo { - app_info: todo!(), - window_info: todo!(), - os_specific_config: todo!(), - vulkan_debug_info: todo!(), - volume_info: todo!(), - gui_info: todo!(), - enable_backtrace: todo!(), - enable_mouse: todo!(), - enable_keyboard: todo!(), - enable_controller: todo!(), - controller_deadzones: todo!(), - resource_base_path: todo!(), - controller_directories: todo!(), - asset_directories: todo!(), - graphics_info: todo!(), - raytracing_info: todo!(), - rasterizer_info: todo!(), - key_backgrounds: todo!(), - })?; - - world_builder.resources.insert(context); - world_builder.resources.insert(engine); - world_builder.resources.insert(scene); + Engine::new(EngineCreateInfo::default(), &mut world_builder)?; world_builder.build().run() } diff --git a/presentation/src/input/eventsystem.rs b/presentation/src/input/eventsystem.rs index 3ab828c..7bd4881 100644 --- a/presentation/src/input/eventsystem.rs +++ b/presentation/src/input/eventsystem.rs @@ -1,17 +1,16 @@ use sdl2; -use sdl2::controller::Button; -use sdl2::event::{Event as SdlEvent, EventType as SdlEventType, WindowEvent}; -use sdl2::keyboard::Keycode; -use sdl2::mouse::{MouseButton as SdlMouseButton, MouseUtil, MouseWheelDirection}; use sdl2::EventPump; use sdl2::EventSubsystem; use sdl2::GameControllerSubsystem; use sdl2::Sdl; +use sdl2::controller::Button; +use sdl2::event::{Event as SdlEvent, EventType as SdlEventType, WindowEvent}; +use sdl2::keyboard::Keycode; +use sdl2::mouse::{MouseButton as SdlMouseButton, MouseUtil, MouseWheelDirection}; use ui::prelude::*; -use std::ops::Deref; -use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard}; +use std::sync::{Arc, RwLock}; use crate::Result; @@ -76,37 +75,33 @@ pub enum Event { } pub struct EventSystem { - event_pump: RwLock, - mouse: Mutex, - controller_subsystem: Mutex, - event_subsystem: Mutex, + event_pump: EventPump, + mouse: MouseUtil, + controller_subsystem: GameControllerSubsystem, + event_subsystem: EventSubsystem, - controller_deadzones: RwLock, + controller_deadzones: ControllerDeadzones, - selected_controller: RwLock>>>, - connected_controllers: RwLock>>>, + selected_controller: Option>>, + connected_controllers: Vec>>, } impl EventSystem { pub fn new(sdl2_context: &Sdl) -> Result { - let event_system = EventSystem { - event_pump: RwLock::new( - sdl2_context - .event_pump() - .map_err(|s| anyhow::Error::msg(s))?, - ), - mouse: Mutex::new(sdl2_context.mouse()), - controller_subsystem: Mutex::new( - sdl2_context - .game_controller() - .map_err(|s| anyhow::Error::msg(s))?, - ), - event_subsystem: Mutex::new(sdl2_context.event().map_err(|s| anyhow::Error::msg(s))?), + let mut event_system = EventSystem { + event_pump: sdl2_context + .event_pump() + .map_err(|s| anyhow::Error::msg(s))?, + mouse: sdl2_context.mouse(), + controller_subsystem: sdl2_context + .game_controller() + .map_err(|s| anyhow::Error::msg(s))?, + event_subsystem: sdl2_context.event().map_err(|s| anyhow::Error::msg(s))?, - controller_deadzones: RwLock::new(ControllerDeadzones::default()), + controller_deadzones: ControllerDeadzones::default(), - selected_controller: RwLock::new(None), - connected_controllers: RwLock::new(Vec::new()), + selected_controller: None, + connected_controllers: Vec::new(), }; event_system.disable_mouse(); @@ -116,102 +111,81 @@ impl EventSystem { Ok(event_system) } - pub fn enable_mouse(&self) { - let mut event_pump = self.event_pump.write().unwrap(); + pub fn enable_mouse(&mut self) { + self.event_pump.enable_event(SdlEventType::MouseMotion); + self.event_pump.enable_event(SdlEventType::MouseButtonDown); + self.event_pump.enable_event(SdlEventType::MouseButtonUp); - event_pump.enable_event(SdlEventType::MouseMotion); - event_pump.enable_event(SdlEventType::MouseButtonDown); - event_pump.enable_event(SdlEventType::MouseButtonUp); - - self.mouse.lock().unwrap().show_cursor(true); + self.mouse.show_cursor(true); } - pub fn disable_mouse(&self) { - let mut event_pump = self.event_pump.write().unwrap(); + pub fn disable_mouse(&mut self) { + self.event_pump.disable_event(SdlEventType::MouseMotion); + self.event_pump.disable_event(SdlEventType::MouseButtonDown); + self.event_pump.disable_event(SdlEventType::MouseButtonUp); - event_pump.disable_event(SdlEventType::MouseMotion); - event_pump.disable_event(SdlEventType::MouseButtonDown); - event_pump.disable_event(SdlEventType::MouseButtonUp); - - self.mouse.lock().unwrap().show_cursor(false); + self.mouse.show_cursor(false); } - pub fn enable_keyboard(&self) { - let mut event_pump = self.event_pump.write().unwrap(); - - event_pump.enable_event(SdlEventType::KeyUp); - event_pump.enable_event(SdlEventType::KeyDown); + pub fn enable_keyboard(&mut self) { + self.event_pump.enable_event(SdlEventType::KeyUp); + self.event_pump.enable_event(SdlEventType::KeyDown); } - pub fn disable_keyboard(&self) { - let mut event_pump = self.event_pump.write().unwrap(); - - event_pump.disable_event(SdlEventType::KeyUp); - event_pump.disable_event(SdlEventType::KeyDown); + pub fn disable_keyboard(&mut self) { + self.event_pump.disable_event(SdlEventType::KeyUp); + self.event_pump.disable_event(SdlEventType::KeyDown); } - pub fn enable_controller(&self) { - let mut event_pump = self.event_pump.write().unwrap(); - - event_pump.enable_event(SdlEventType::ControllerAxisMotion); - event_pump.enable_event(SdlEventType::ControllerButtonDown); - event_pump.enable_event(SdlEventType::ControllerButtonUp); + pub fn enable_controller(&mut self) { + self.event_pump + .enable_event(SdlEventType::ControllerAxisMotion); + self.event_pump + .enable_event(SdlEventType::ControllerButtonDown); + self.event_pump + .enable_event(SdlEventType::ControllerButtonUp); } - pub fn disable_controller(&self) { - let mut event_pump = self.event_pump.write().unwrap(); - - event_pump.disable_event(SdlEventType::ControllerAxisMotion); - event_pump.disable_event(SdlEventType::ControllerButtonDown); - event_pump.disable_event(SdlEventType::ControllerButtonUp); + pub fn disable_controller(&mut self) { + self.event_pump + .disable_event(SdlEventType::ControllerAxisMotion); + self.event_pump + .disable_event(SdlEventType::ControllerButtonDown); + self.event_pump + .disable_event(SdlEventType::ControllerButtonUp); } - pub fn set_controller_axis_enable_deadzone(&self, deadzone: f32) { - self.controller_deadzones - .write() - .unwrap() - .axis_enable_deadzone = deadzone; + pub fn set_controller_axis_enable_deadzone(&mut self, deadzone: f32) { + self.controller_deadzones.axis_enable_deadzone = deadzone; } - pub fn set_controller_axis_disable_deadzone(&self, deadzone: f32) { - self.controller_deadzones - .write() - .unwrap() - .axis_disable_deadzone = deadzone; + pub fn set_controller_axis_disable_deadzone(&mut self, deadzone: f32) { + self.controller_deadzones.axis_disable_deadzone = deadzone; } - pub fn set_controller_trigger_enable_deadzone(&self, deadzone: f32) { - self.controller_deadzones - .write() - .unwrap() - .trigger_enable_deadzone = deadzone; + pub fn set_controller_trigger_enable_deadzone(&mut self, deadzone: f32) { + self.controller_deadzones.trigger_enable_deadzone = deadzone; } - pub fn set_controller_trigger_disable_deadzone(&self, deadzone: f32) { - self.controller_deadzones - .write() - .unwrap() - .trigger_disable_deadzone = deadzone; + pub fn set_controller_trigger_disable_deadzone(&mut self, deadzone: f32) { + self.controller_deadzones.trigger_disable_deadzone = deadzone; } pub fn quit(&self) -> Result<()> { Ok(self .event_subsystem - .lock() - .unwrap() .push_event(SdlEvent::Quit { timestamp: 0 }) .map_err(|s| anyhow::Error::msg(s))?) } - pub fn poll_events(&self, event_callback: F, mut resize: R) -> Result + pub fn poll_events(&mut self, event_callback: F, mut resize: R) -> Result where F: Fn(Event) -> Result<()>, R: FnMut(u32, u32) -> Result<()>, { let mut controller_axis_changed = false; - let mut event_pump = self.event_pump.write().unwrap(); - for event in event_pump.poll_iter() { + for event in self.event_pump.poll_iter() { match event { SdlEvent::Window { win_event, .. } => match win_event { WindowEvent::Resized(w, h) | WindowEvent::SizeChanged(w, h) => { @@ -288,9 +262,9 @@ impl EventSystem { } if let Ok(controller) = Controller::new( - self.controller_subsystem.lock().unwrap().deref(), + &self.controller_subsystem, which as u32, - self.controller_deadzones.read().unwrap().clone(), + self.controller_deadzones.clone(), ) { let controller = { if cfg!(debug_assertions) { @@ -301,16 +275,10 @@ impl EventSystem { ); } - let mut connected_controllers = - self.connected_controllers.write().unwrap(); - - let mut selected_controller = self.selected_controller.write().unwrap(); - let arc_controller = Arc::new(RwLock::new(controller)); + self.connected_controllers.push(arc_controller.clone()); - connected_controllers.push(arc_controller.clone()); - - if selected_controller.is_none() { + if self.selected_controller.is_none() { if cfg!(debug_assertions) { let contr = arc_controller.read().unwrap(); @@ -321,7 +289,7 @@ impl EventSystem { ); } - *selected_controller = Some(arc_controller.clone()); + self.selected_controller = Some(arc_controller.clone()); } arc_controller @@ -332,11 +300,10 @@ impl EventSystem { } SdlEvent::ControllerDeviceRemoved { which, .. } => { let removed_controller = { - let mut selected_controller = self.selected_controller.write().unwrap(); - - if selected_controller.is_some() { + if self.selected_controller.is_some() { if cfg!(debug_assertions) { - let contr = selected_controller.as_ref().unwrap().read().unwrap(); + let contr = + self.selected_controller.as_ref().unwrap().read().unwrap(); println!( "Remove active controller: {}({})", @@ -346,14 +313,20 @@ impl EventSystem { } // unwrap is save since we just tested for `is_some()` - if selected_controller.as_ref().unwrap().read().unwrap().id() == which { - *selected_controller = None; + if self + .selected_controller + .as_ref() + .unwrap() + .read() + .unwrap() + .id() + == which + { + self.selected_controller = None; } } - let mut connected_controllers = self.connected_controllers.write().unwrap(); - - connected_controllers + self.connected_controllers .iter() .position(|controller_cell| { let controller = controller_cell.read().unwrap(); @@ -361,7 +334,7 @@ impl EventSystem { }) .map(|remove_index| { let removed_controller = - connected_controllers.swap_remove(remove_index); + self.connected_controllers.swap_remove(remove_index); if cfg!(debug_assertions) { let contr = removed_controller.read().unwrap(); @@ -373,17 +346,18 @@ impl EventSystem { } // if we removed the selected controller, take the controller at the first position if possible - if selected_controller.is_none() - && !connected_controllers.is_empty() + if self.selected_controller.is_none() + && !self.connected_controllers.is_empty() { if cfg!(debug_assertions) { println!( "Set active controller: {}", - connected_controllers[0].read().unwrap().name() + self.connected_controllers[0].read().unwrap().name() ); } - *selected_controller = Some(connected_controllers[0].clone()); + self.selected_controller = + Some(self.connected_controllers[0].clone()); } removed_controller @@ -436,9 +410,7 @@ impl EventSystem { // which, .. } => { - let mut selected_controller = self.selected_controller.write().unwrap(); - - if let Some(controller) = selected_controller.as_mut() { + if let Some(controller) = self.selected_controller.as_mut() { let mut controller = controller.write().unwrap(); // // only update axis, when selected controller made the change @@ -481,7 +453,7 @@ impl EventSystem { } if controller_axis_changed { - if let Some(controller) = self.selected_controller.read().unwrap().as_ref() { + if let Some(controller) = &self.selected_controller { let (left_trigger, right_trigger) = { let mut controller_lock = controller.write().unwrap(); @@ -516,23 +488,21 @@ impl EventSystem { Ok(true) } - pub fn controllers(&self) -> RwLockReadGuard<'_, Vec>>> { - self.connected_controllers.read().unwrap() + pub fn controllers(&self) -> &[Arc>] { + &self.connected_controllers } - pub fn active_controller(&self) -> Result>>> { - Ok(self.selected_controller.read().unwrap().clone()) + pub fn active_controller(&self) -> &Option>> { + &self.selected_controller } - pub fn set_active_controller(&self, controller: &Arc>) { + pub fn set_active_controller(&mut self, controller: &Arc>) { if let Some(res) = self .connected_controllers - .read() - .unwrap() .iter() .find(|c| Arc::ptr_eq(c, controller)) { - *self.selected_controller.write().unwrap() = Some(res.clone()); + self.selected_controller = Some(res.clone()); } } } diff --git a/presentation/src/presentationcore.rs b/presentation/src/presentationcore.rs index f92b551..49059a6 100644 --- a/presentation/src/presentationcore.rs +++ b/presentation/src/presentationcore.rs @@ -111,7 +111,7 @@ impl PresentationCore { }) } - pub fn poll_events(&self, event_callback: F, resize_event: R) -> Result + pub fn poll_events(&mut self, event_callback: F, resize_event: R) -> Result where F: Fn(Event) -> Result<()>, R: FnMut(u32, u32) -> Result<()>, @@ -123,6 +123,10 @@ impl PresentationCore { &self.event_system } + pub fn event_system_mut(&mut self) -> &mut EventSystem { + &mut self.event_system + } + pub fn activate_vulkan_instance_extensions( &self, extensions: &mut InstanceExtensions, diff --git a/presentation/src/renderbackend.rs b/presentation/src/renderbackend.rs index 48fc328..608f941 100644 --- a/presentation/src/renderbackend.rs +++ b/presentation/src/renderbackend.rs @@ -171,10 +171,11 @@ impl RenderBackend { } // make a call to the connected scene - world.resources.get_mut::().process( + world.resources.get_mut_unchecked::().process( &mut buffer_recorder, &*self.swapchain_images.lock().unwrap(), &image_indices, + world, )?; // post processing diff --git a/presentation/src/traits.rs b/presentation/src/traits.rs index 494eb26..9da6df4 100644 --- a/presentation/src/traits.rs +++ b/presentation/src/traits.rs @@ -14,6 +14,7 @@ pub trait TScene: Send + Sync { buffer_recorder: &mut CommandBufferRecorder<'_>, images: &TargetMode>>, indices: &TargetMode, + world: &World, ) -> Result<()>; fn resize(