Compare commits

..

1 commit

Author SHA1 Message Date
b52cdaefab Update Rust crate rusqlite to 0.33.0 2025-02-27 06:02:37 +00:00
24 changed files with 578 additions and 547 deletions

View file

View file

@ -36,7 +36,7 @@ pub struct Context {
render_core: Arc<RwLock<Box<dyn RenderCore>>>, render_core: Arc<RwLock<Box<dyn RenderCore>>>,
#[cfg(feature = "sound")] #[cfg(feature = "sound")]
sound_handler: SoundHandler, sound_handler: Mutex<SoundHandler>,
os_specific: OsSpecific, os_specific: OsSpecific,
@ -61,41 +61,45 @@ impl Context {
} }
#[cfg(feature = "sound")] #[cfg(feature = "sound")]
pub fn sound(&mut self) -> &mut SoundHandler { pub fn sound(&self) -> MutexGuard<'_, SoundHandler> {
&mut self.sound_handler self.sound_handler.lock().unwrap()
} }
pub fn next_frame<C>(&mut self, world: &mut World) -> Result<bool> { pub fn run<C>(&self, world: &mut World) -> Result<()> {
let render_core = self.render_core.clone(); 'running: loop {
let render_core = self.render_core.clone();
match self.presentation.poll_events( match self.presentation.poll_events(
|event| { |event| {
// TODO // TODO
// if let Some(ctx_obj) = world.resources.get_mut_opt::<C>() { // if let Some(ctx_obj) = world.resources.get_mut_opt::<C>() {
// ctx_obj.event(event)?; // ctx_obj.event(event)?;
// } // }
Ok(()) Ok(())
}, },
|w, h| render_core.write().unwrap().resize(world, w, h), |w, h| render_core.write().unwrap().resize(world, w, h),
) { ) {
Ok(res) => { Ok(res) => {
if !res { if !res {
return Ok(false); break 'running;
}
}
Err(err) => {
if let Some(fallback) = &self.fallback {
(fallback)(err)?;
}
} }
} }
Err(err) => {
if let Some(fallback) = &self.fallback { if !self.render_core_mut().next_frame(world)? {
(fallback)(err)?; break 'running;
}
} }
} }
if !self.render_core_mut().next_frame(world)? { self.render_core_mut().clear_post_processing_routines();
return Ok(false);
}
Ok(true) Ok(())
} }
pub fn render_core(&self) -> impl Deref<Target = Box<dyn RenderCore>> + '_ { pub fn render_core(&self) -> impl Deref<Target = Box<dyn RenderCore>> + '_ {
@ -125,17 +129,17 @@ impl Context {
self.core.queue() self.core.queue()
} }
pub fn controllers(&self) -> &[Arc<RwLock<Controller>>] { pub fn controllers(&self) -> RwLockReadGuard<'_, Vec<Arc<RwLock<Controller>>>> {
self.presentation.event_system().controllers() self.presentation.event_system().controllers()
} }
pub fn active_controller(&self) -> &Option<Arc<RwLock<Controller>>> { pub fn active_controller(&self) -> Result<Option<Arc<RwLock<Controller>>>> {
self.presentation.event_system().active_controller() Ok(self.presentation.event_system().active_controller()?)
} }
pub fn set_active_controller(&mut self, controller: &Arc<RwLock<Controller>>) { pub fn set_active_controller(&self, controller: &Arc<RwLock<Controller>>) {
self.presentation self.presentation
.event_system_mut() .event_system()
.set_active_controller(controller) .set_active_controller(controller)
} }
} }
@ -180,7 +184,7 @@ impl ContextInterface for Context {
} }
#[cfg(feature = "sound")] #[cfg(feature = "sound")]
fn sound_handler(&mut self) -> &mut SoundHandler { fn sound_handler(&self) -> MutexGuard<'_, SoundHandler> {
self.sound() self.sound()
} }
} }
@ -398,22 +402,22 @@ impl ContextBuilder {
let vr_mode = self.get_vr_mode(); let vr_mode = self.get_vr_mode();
let mut presentation = let presentation =
PresentationCore::new(vr_mode, &self.window_create_info, self.app_info.clone())?; PresentationCore::new(vr_mode, &self.window_create_info, self.app_info.clone())?;
presentation presentation
.event_system_mut() .event_system()
.set_controller_axis_enable_deadzone(self.controller_deadzones.axis_enable_deadzone); .set_controller_axis_enable_deadzone(self.controller_deadzones.axis_enable_deadzone);
presentation presentation
.event_system_mut() .event_system()
.set_controller_axis_disable_deadzone(self.controller_deadzones.axis_disable_deadzone); .set_controller_axis_disable_deadzone(self.controller_deadzones.axis_disable_deadzone);
presentation presentation
.event_system_mut() .event_system()
.set_controller_trigger_enable_deadzone( .set_controller_trigger_enable_deadzone(
self.controller_deadzones.trigger_enable_deadzone, self.controller_deadzones.trigger_enable_deadzone,
); );
presentation presentation
.event_system_mut() .event_system()
.set_controller_trigger_disable_deadzone( .set_controller_trigger_disable_deadzone(
self.controller_deadzones.trigger_disable_deadzone, self.controller_deadzones.trigger_disable_deadzone,
); );
@ -436,15 +440,15 @@ impl ContextBuilder {
)?; )?;
if self.enable_mouse { if self.enable_mouse {
presentation.event_system_mut().enable_mouse(); presentation.event_system().enable_mouse();
} }
if self.enable_keyboard { if self.enable_keyboard {
presentation.event_system_mut().enable_keyboard(); presentation.event_system().enable_keyboard();
} }
if self.enable_controller { if self.enable_controller {
presentation.event_system_mut().enable_controller(); presentation.event_system().enable_controller();
} }
Ok(Context { Ok(Context {
@ -453,7 +457,7 @@ impl ContextBuilder {
render_core: Arc::new(RwLock::new(render_core)), render_core: Arc::new(RwLock::new(render_core)),
#[cfg(feature = "sound")] #[cfg(feature = "sound")]
sound_handler: self.create_sound_handler()?, sound_handler: Mutex::new(self.create_sound_handler()?),
os_specific, os_specific,

View file

@ -9,6 +9,8 @@ use serde::{Deserialize, Serialize};
use crate::{ComponentDebug, ComponentNotFoundError, EntityComponent, MultiMut, TypeMap}; use crate::{ComponentDebug, ComponentNotFoundError, EntityComponent, MultiMut, TypeMap};
pub const COMPONENT_SEPARATOR: char = '§';
#[derive(Debug)] #[derive(Debug)]
pub struct EntityNotFoundError { pub struct EntityNotFoundError {
entity: Entity, entity: Entity,

View file

@ -4,8 +4,6 @@ use std::{
mem::transmute, mem::transmute,
}; };
use utilities::prelude::{remove_life_time, remove_life_time_mut};
#[derive(Default)] #[derive(Default)]
pub struct Resources { pub struct Resources {
map: HashMap<TypeId, Box<dyn Any + Send + Sync>>, map: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
@ -34,10 +32,6 @@ impl Resources {
self.get_opt::<T>().unwrap() self.get_opt::<T>().unwrap()
} }
pub fn get_unchecked<'a, T: Any + Send + Sync>(&self) -> &'a T {
unsafe { remove_life_time(self.get::<T>()) }
}
pub fn get_opt<T: Any + Send + Sync>(&self) -> Option<&T> { pub fn get_opt<T: Any + Send + Sync>(&self) -> Option<&T> {
self.map self.map
.get(&TypeId::of::<T>()) .get(&TypeId::of::<T>())
@ -48,10 +42,6 @@ impl Resources {
self.get_mut_opt::<T>().unwrap() self.get_mut_opt::<T>().unwrap()
} }
pub fn get_mut_unchecked<'a, T: Any + Send + Sync>(&mut self) -> &'a mut T {
unsafe { remove_life_time_mut(self.get_mut::<T>()) }
}
pub fn get_mut_opt<T: Any + Send + Sync>(&mut self) -> Option<&mut T> { pub fn get_mut_opt<T: Any + Send + Sync>(&mut self) -> Option<&mut T> {
self.map self.map
.get_mut(&TypeId::of::<T>()) .get_mut(&TypeId::of::<T>())

View file

@ -79,16 +79,12 @@ impl World {
} }
} }
pub fn now(&self) -> Duration {
self.start_time.elapsed()
}
pub fn new_entity(&mut self) -> EntityObject { pub fn new_entity(&mut self) -> EntityObject {
self.entity_object_manager.create_entity() self.entity_object_manager.create_entity()
} }
pub fn entities(&self) -> impl Iterator<Item = &EntityObject> { pub fn now(&self) -> Duration {
self.entities.values() self.start_time.elapsed()
} }
pub fn entity( pub fn entity(

View file

@ -6,8 +6,8 @@ use crate::prelude::*;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{ use std::sync::{
Arc, RwLock, RwLockReadGuard,
atomic::{AtomicU32, Ordering}, atomic::{AtomicU32, Ordering},
Arc, RwLock, RwLockReadGuard,
}; };
use std::thread; use std::thread;
@ -25,8 +25,8 @@ pub struct AssetCache {
impl AssetCache { impl AssetCache {
pub(crate) fn new( pub(crate) fn new(
context: &Context, context: &Arc<Context>,
engine_settings: &EngineSettings, engine_settings: &Arc<EngineSettings>,
loaded_assets: impl IntoIterator<Item = (String, Asset)>, loaded_assets: impl IntoIterator<Item = (String, Asset)>,
names: impl IntoIterator<Item = (AssetPath, String)>, names: impl IntoIterator<Item = (AssetPath, String)>,
) -> Result<Self> { ) -> Result<Self> {
@ -52,7 +52,7 @@ impl AssetCache {
let device = context.device().clone(); let device = context.device().clone();
let queue = context.queue().clone(); let queue = context.queue().clone();
let render_type = engine_settings.graphics_info()?.render_type; let engine_settings = engine_settings.clone();
let rw_lock_assets = rw_lock_assets.clone(); let rw_lock_assets = rw_lock_assets.clone();
let ready_count = ready_count.clone(); let ready_count = ready_count.clone();
@ -63,7 +63,13 @@ impl AssetCache {
} }
let gltf_asset = GltfAsset::new(&path)?; let gltf_asset = GltfAsset::new(&path)?;
let asset = Asset::new(&device, &queue, render_type, gltf_asset, &name)?; let asset = Asset::new(
&device,
&queue,
engine_settings.graphics_info()?.render_type,
gltf_asset,
&name,
)?;
{ {
let mut locked_assets = rw_lock_assets.write().unwrap(); let mut locked_assets = rw_lock_assets.write().unwrap();

View file

@ -9,7 +9,7 @@ use std::sync::{Arc, RwLock};
use std::thread; use std::thread;
pub struct AssetManager { pub struct AssetManager {
gltf_directory: AssetPath, engine_settings: Arc<EngineSettings>,
gltf_file_list: Vec<String>, gltf_file_list: Vec<String>,
@ -22,9 +22,9 @@ pub struct AssetManager {
impl AssetManager { impl AssetManager {
/// Constructor for `AssetManager`, creates lists of '.gltf' and '.ent' files /// Constructor for `AssetManager`, creates lists of '.gltf' and '.ent' files
pub(crate) fn new(engine_settings: &EngineSettings) -> Result<AssetManager> { pub(crate) fn new(engine_settings: Arc<EngineSettings>) -> Result<AssetManager> {
let mut asset_manager = AssetManager { let mut asset_manager = AssetManager {
gltf_directory: engine_settings.gltf_directory().clone(), engine_settings,
gltf_file_list: Vec::new(), gltf_file_list: Vec::new(),
gltf_file_map: HashMap::new(), gltf_file_map: HashMap::new(),
@ -65,7 +65,7 @@ impl AssetManager {
pub fn create_cache_with<'a, 'b>( pub fn create_cache_with<'a, 'b>(
&mut self, &mut self,
world: &World, context: &Arc<Context>,
asset_names: impl IntoIterator<Item = &'b &'b str> + Clone, asset_names: impl IntoIterator<Item = &'b &'b str> + Clone,
) -> Result<AssetCache> { ) -> Result<AssetCache> {
let mut assets = Vec::new(); let mut assets = Vec::new();
@ -91,12 +91,7 @@ impl AssetManager {
} }
} }
AssetCache::new( AssetCache::new(context, &self.engine_settings, assets, names)
world.resources.get::<Context>(),
world.resources.get::<EngineSettings>(),
assets,
names,
)
} }
/// Clears all loaded files /// Clears all loaded files
@ -116,9 +111,9 @@ impl AssetManager {
/// Updates the lists of all '.gltf' and '.ent' files /// Updates the lists of all '.gltf' and '.ent' files
pub fn update_files(&mut self) -> Result<()> { pub fn update_files(&mut self) -> Result<()> {
let (mut gltf_file_list, gltf_file_map) = let (mut gltf_file_list, gltf_file_map) =
super::search_file_names(&self.gltf_directory, ".gltf")?; super::search_file_names(self.engine_settings.gltf_directory(), ".gltf")?;
let (mut glb_file_list, glb_file_map) = let (mut glb_file_list, glb_file_map) =
super::search_file_names(&self.gltf_directory, ".glb")?; super::search_file_names(self.engine_settings.gltf_directory(), ".glb")?;
gltf_file_list.append(&mut glb_file_list); gltf_file_list.append(&mut glb_file_list);
@ -132,7 +127,7 @@ impl AssetManager {
/// Creates an empty `EditableEntity` /// Creates an empty `EditableEntity`
pub fn load_asset_file(&mut self, world: &mut World, asset_file: &str) -> Result<EntityObject> { pub fn load_asset_file(&mut self, world: &mut World, asset_file: &str) -> Result<EntityObject> {
// load asset // load asset
let asset = self.load_gltf_asset(world, asset_file, true)?; let asset = self.load_gltf_asset(world.resources.get::<Context>(), asset_file, true)?;
let mut entity_object = world.new_entity(); let mut entity_object = world.new_entity();
@ -171,11 +166,7 @@ impl AssetManager {
let asset = Asset::new( let asset = Asset::new(
context.device(), context.device(),
context.queue(), context.queue(),
world self.engine_settings.graphics_info()?.render_type,
.resources
.get::<EngineSettings>()
.graphics_info()?
.render_type,
gltf_asset, gltf_asset,
asset_path, asset_path,
)?; )?;
@ -205,7 +196,7 @@ impl AssetManager {
pub fn async_load_gltf_file<'a, 'b>( pub fn async_load_gltf_file<'a, 'b>(
&self, &self,
world: &World, context: &Arc<Context>,
files: impl IntoIterator<Item = &'b &'b str>, files: impl IntoIterator<Item = &'b &'b str>,
) -> Result<()> { ) -> Result<()> {
let mut asset_files: Vec<(AssetPath, String)> = Vec::new(); let mut asset_files: Vec<(AssetPath, String)> = Vec::new();
@ -223,15 +214,12 @@ impl AssetManager {
} }
} }
let context = world.resources.get::<Context>();
let engine_settings = world.resources.get::<EngineSettings>();
// naively spawn for every file a thread // naively spawn for every file a thread
// TODO: spawn thread dependent on the cpu core count // TODO: spawn thread dependent on the cpu core count
for (path, file_name) in asset_files { for (path, file_name) in asset_files {
let device = context.device().clone(); let device = context.device().clone();
let queue = context.queue().clone(); let queue = context.queue().clone();
let render_type = engine_settings.graphics_info()?.render_type; let engine_settings = self.engine_settings.clone();
let loaded_gltf_files = self.loaded_gltf_files.clone(); let loaded_gltf_files = self.loaded_gltf_files.clone();
let queued_for_async_load = self.queued_for_async_load.clone(); let queued_for_async_load = self.queued_for_async_load.clone();
@ -243,7 +231,13 @@ impl AssetManager {
let gltf_asset = GltfAsset::new(&path)?; let gltf_asset = GltfAsset::new(&path)?;
let asset = Asset::new(&device, &queue, render_type, gltf_asset, &file_name)?; let asset = Asset::new(
&device,
&queue,
engine_settings.graphics_info()?.render_type,
gltf_asset,
&file_name,
)?;
{ {
let mut gltf_files_lock = loaded_gltf_files.write().unwrap(); let mut gltf_files_lock = loaded_gltf_files.write().unwrap();
@ -270,10 +264,7 @@ impl AssetManager {
/// checks if the '.gltf' file with given name is already loaded, if not, loads it /// 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 /// add - if true, adds the asset to the internal map
fn load_gltf_asset(&mut self, world: &World, gltf_file: &str, add: bool) -> Result<Asset> { fn load_gltf_asset(&mut self, context: &Context, gltf_file: &str, add: bool) -> Result<Asset> {
let context = world.resources.get::<Context>();
let engine_settings = world.resources.get::<EngineSettings>();
loop { loop {
let queued_lock = self.queued_for_async_load.read().unwrap(); let queued_lock = self.queued_for_async_load.read().unwrap();
@ -292,7 +283,7 @@ impl AssetManager {
let asset = Asset::new( let asset = Asset::new(
context.device(), context.device(),
context.queue(), context.queue(),
engine_settings.graphics_info()?.render_type, self.engine_settings.graphics_info()?.render_type,
gltf_asset, gltf_asset,
gltf_file, gltf_file,
)?; )?;

View file

@ -1,5 +1,5 @@
pub mod asset_cache; pub mod assetcache;
pub mod asset_manager; pub mod assetmanager;
use std::{collections::HashMap, path::Path}; use std::{collections::HashMap, path::Path};

View file

@ -1,4 +1,8 @@
use crate::assets::asset_manager::AssetManager; use std::marker::PhantomData;
use std::sync::{Arc, RwLock};
use crate::assets::assetmanager::AssetManager;
use crate::prelude::*; use crate::prelude::*;
@ -8,69 +12,80 @@ pub trait AssetLoader {
fn load_entity(&mut self, assets: AssetHandler<'_>, entity_file: &str) -> Result<EntityObject>; fn load_entity(&mut self, assets: AssetHandler<'_>, entity_file: &str) -> Result<EntityObject>;
} }
#[derive(Clone, Copy)]
pub struct AssetHandler<'a> { pub struct AssetHandler<'a> {
world: &'a mut World, pub(crate) asset_manager: &'a RwLock<AssetManager>,
asset_manager: &'a mut AssetManager,
resource_base_path: String, pub(crate) resource_base_path: &'a String,
pub(crate) phantom_data: PhantomData<&'a ()>,
} }
impl<'a> AssetHandler<'a> { impl<'a> AssetHandler<'a> {
pub fn create(world: &'a mut World) -> Self { pub fn context(&self) -> &Arc<Context> {
let asset_manager = world.resources.get_mut_unchecked::<AssetManager>(); self.context
let engine = world.resources.get::<Engine>();
Self {
asset_manager,
resource_base_path: engine.resource_base_path.clone(),
world,
}
} }
pub fn update_file_cache(&mut self) -> Result<()> { pub fn update_file_cache(&self) -> Result<()> {
self.asset_manager.update_files() self.asset_manager.write().unwrap().update_files()
} }
pub fn preload_assets<'b>(&self, files: impl IntoIterator<Item = &'b &'b str>) -> Result<()> { pub fn preload_assets<'b>(&self, files: impl IntoIterator<Item = &'b &'b str>) -> Result<()> {
self.asset_manager.async_load_gltf_file(self.world, files) self.asset_manager
.read()
.unwrap()
.async_load_gltf_file(self.context, files)
} }
pub fn create_cache<'b>( pub fn create_cache<'b>(
&mut self, &self,
names: impl IntoIterator<Item = &'b &'b str> + Clone, names: impl IntoIterator<Item = &'b &'b str> + Clone,
) -> Result<AssetCache> { ) -> Result<AssetCache> {
self.asset_manager.create_cache_with(self.world, names) self.asset_manager
.write()
.unwrap()
.create_cache_with(self.context, names)
} }
pub fn insert_cache(&self, cache: &AssetCache) -> Result<()> { pub fn insert_cache(&self, cache: &AssetCache) -> Result<()> {
self.asset_manager.insert_cached_assets(cache) self.asset_manager
.read()
.unwrap()
.insert_cached_assets(cache)
} }
pub fn clear(&mut self) -> Result<()> { pub fn clear(&self) -> Result<()> {
self.asset_manager.clear() self.asset_manager.write().unwrap().clear()
} }
pub fn gltf_files(&self) -> Result<Vec<String>> { pub fn gltf_files(&self) -> Result<Vec<String>> {
Ok(self.asset_manager.gltf_files().clone()) Ok(self.asset_manager.read().unwrap().gltf_files().clone())
} }
pub fn create_entity(&mut self, asset_file: &str) -> Result<EntityObject> { pub fn create_entity(&self, asset_file: &str) -> Result<EntityObject> {
self.asset_manager.load_asset_file(self.world, asset_file) self.asset_manager.write().unwrap().load_asset_file(
self.context,
self.entity_object_manager,
asset_file,
)
} }
pub fn create_entity_absolute(&mut self, asset_path: &str) -> Result<EntityObject> { pub fn create_entity_absolute(&self, asset_path: &str) -> Result<EntityObject> {
self.asset_manager self.asset_manager
.load_asset_file_absolute(self.world, asset_path) .write()
.unwrap()
.load_asset_file_absolute(self.context, self.entity_object_manager, asset_path)
} }
pub fn empty_entity(&mut self) -> EntityObject { pub fn empty_entity(&self) -> EntityObject {
self.world.new_entity() self.entity_object_manager.create_entity()
} }
pub fn resource_base_path(&self) -> &str { pub fn resource_base_path(&self) -> &str {
&self.resource_base_path self.resource_base_path
} }
pub fn world(&mut self) -> &mut World { pub(crate) fn get_entity_id(&self) -> u32 {
&mut self.world self.entity_object_manager.fetch_add_entity_id()
} }
} }

View file

@ -1,17 +1,56 @@
#![allow(clippy::type_complexity)] #![allow(clippy::type_complexity)]
use super::engine_object::*; use super::asset_handler::AssetHandler;
use super::engine_settings::EngineSettings;
use super::engineobject::*;
use super::enginesettings::EngineSettings;
use anyhow::Result; use anyhow::Result;
use assetpath::AssetPath; use assetpath::AssetPath;
use context::prelude::cgmath::vec3; use context::prelude::cgmath::vec3;
use loading_screen::LoadingScreen;
use crate::assets::asset_manager::AssetManager; use crate::assets::assetmanager::AssetManager;
use crate::prelude::*; use crate::prelude::*;
use std::collections::HashMap; use std::sync::{Arc, RwLock, RwLockReadGuard};
use std::sync::{Arc, RwLock}; 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<String, f32>,
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,
}
struct GuiPostProcess(Arc<GuiHandler>); struct GuiPostProcess(Arc<GuiHandler>);
@ -34,34 +73,37 @@ impl context::prelude::PostProcess for GuiPostProcess {
} }
pub struct Engine { pub struct Engine {
engine_settings: Arc<EngineSettings>,
gui_handler: Arc<GuiHandler>,
gui_post_process: Arc<GuiPostProcess>,
input: Arc<RwLock<Input>>, input: Arc<RwLock<Input>>,
// loads and keeps track of raw data // loads and keeps track of raw data
asset_manager: AssetManager, asset_manager: AssetManager,
pub(crate) resource_base_path: String, resource_base_path: String,
} }
impl Engine { impl Engine {
pub fn new( pub fn new(#[allow(unused)] mut create_info: EngineCreateInfo<'_>) -> Result<Self> {
#[allow(unused)] mut create_info: EngineCreateInfo<'_>, if let Font::Path(path) = &mut create_info.gui_info.font {
world: &mut WorldBuilder, path.set_prefix(&create_info.resource_base_path);
) -> Result<()> { }
create_info.gui_info.resource_directory.assume_prefix_free();
create_info create_info
.controller_directories .controller_directories
.xbox_path .xbox_path
.as_mut() .set_prefix(&create_info.resource_base_path);
.map(|p| p.set_prefix(&create_info.resource_base_path));
create_info create_info
.controller_directories .controller_directories
.steam_path .steam_path
.as_mut() .set_prefix(&create_info.resource_base_path);
.map(|p| p.set_prefix(&create_info.resource_base_path));
create_info create_info
.controller_directories .controller_directories
.ps4_path .ps4_path
.as_mut() .set_prefix(&create_info.resource_base_path);
.map(|p| p.set_prefix(&create_info.resource_base_path));
create_info create_info
.asset_directories .asset_directories
@ -87,7 +129,7 @@ impl Engine {
// --------------- context -------------------- // --------------- context --------------------
let mut context = { let context = {
create_info.app_info.engine_name = "EngineNameNeeded".to_string(); create_info.app_info.engine_name = "EngineNameNeeded".to_string();
create_info.app_info.engine_version = 1; create_info.app_info.engine_version = 1;
@ -140,9 +182,10 @@ impl Engine {
}; };
// update sound handler center // update sound handler center
context {
.sound() let sound_handler = context.sound();
.set_direction(vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0))?; sound_handler.set_direction(vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0))?;
}
// --------------- settings ------------------- // --------------- settings -------------------
@ -155,7 +198,7 @@ impl Engine {
.ok_or_else(|| anyhow::Error::msg("No proper render type could be found"))?; .ok_or_else(|| anyhow::Error::msg("No proper render type could be found"))?;
} }
let engine_settings = EngineSettings::new( let engine_settings = Arc::new(EngineSettings::new(
&context, &context,
create_info.graphics_info, create_info.graphics_info,
create_info.raytracing_info, create_info.raytracing_info,
@ -164,26 +207,15 @@ impl Engine {
create_info.asset_directories, create_info.asset_directories,
create_info.key_backgrounds, create_info.key_backgrounds,
create_info.resource_base_path.clone(), 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<dyn ContextInterface>),
)?; )?;
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 // default keyboard navigation
let mut direction_mapping = HashMap::new(); let mut direction_mapping = HashMap::new();
// direction_mapping.insert(Keycode::A, GuiDirection::Left); // direction_mapping.insert(Keycode::A, GuiDirection::Left);
@ -195,62 +227,105 @@ impl Engine {
direction_mapping.insert(Keycode::Up, GuiDirection::Up); direction_mapping.insert(Keycode::Up, GuiDirection::Up);
direction_mapping.insert(Keycode::Down, GuiDirection::Down); direction_mapping.insert(Keycode::Down, GuiDirection::Down);
let engine = Engine { let input = Input { direction_mapping };
input: Arc::new(RwLock::new(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)),
asset_manager, asset_manager,
resource_base_path: create_info.resource_base_path, resource_base_path: create_info.resource_base_path,
};
world.resources.insert(context); engine_settings,
world.resources.insert(engine); })
world.resources.insert(engine_settings); }
world.add_system(Self::main_system); pub fn set_game_object<E>(&self, engine_object: Option<E>) -> 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,
});
Ok(()) Ok(())
} }
// pub fn set_game_object<E>(&self, engine_object: Option<E>) -> Result<()> pub fn loading_screen<T, R, L, G>(
// where &self,
// E: EngineObject + Send + Sync, gui: Option<Arc<G>>,
// { loader: L,
// self.context().set_context_object(match engine_object { on_ready: R,
// Some(engine_object) => Some(ContextObjectImpl::new( ) -> Result<()>
// self.graphical.context.clone(), where
// engine_object, R: Fn(T) -> anyhow::Result<()> + 'static + Send + Sync,
// self.graphical.input.clone(), T: Send + Sync + 'static,
// self.gui_handler().clone(), L: FnOnce() -> T + Send + Sync + 'static,
// )?), G: TopLevelGui + TopGui + Send + Sync + 'static,
// None => None, {
// }); LoadingScreen::load(self.context(), gui, loader, on_ready)
}
// Ok(()) pub fn new_point_light(&self) -> Result<Light> {
// } Light::point_light(self.context().device())
}
// pub fn loading_screen<T, R, L, G>( pub fn new_directional_light(&self) -> Result<Light> {
// &self, Light::directional_light(self.context().device())
// gui: Option<Arc<G>>, }
// loader: L,
// on_ready: R, pub fn new_spot_light(&self) -> Result<Light> {
// ) -> Result<()> Light::spot_light(self.context().device())
// where }
// R: Fn(T) -> anyhow::Result<()> + 'static + Send + Sync,
// T: Send + Sync + 'static, pub fn controller_icon(&self, button: ControllerButton) -> Result<Arc<Image>> {
// L: FnOnce() -> T + Send + Sync + 'static, Ok(self.settings().controller_icon(self, button)?.unwrap_or(
// G: TopLevelGui + TopGui + Send + Sync + 'static, self.settings()
// { .controller_button_for(self, button, ControllerType::XBox)?,
// LoadingScreen::load(self.context(), gui, loader, on_ready) ))
// } }
pub fn build_path(&self, path: &str) -> AssetPath { pub fn build_path(&self, path: &str) -> AssetPath {
(self.resource_base_path.as_str(), path).into() (self.resource_base_path.as_str(), path).into()
} }
pub fn main_system(world: &mut World) -> Result<()> { pub fn assets(&self) -> AssetHandler<'_> {
// AssetHandler {
asset_manager: &self.asset_manager,
Ok(()) context: &self.graphical.context,
resource_base_path: &self.resource_base_path,
phantom_data: PhantomData,
}
}
}
// getter
impl Engine {
pub fn settings(&self) -> &Arc<EngineSettings> {
&self.engine_settings
}
}
impl Drop for Engine {
fn drop(&mut self) {
self.context
.render_core()
.remove_post_processing_routine(self.gui_post_process.clone());
} }
} }

View file

@ -1,97 +0,0 @@
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<String, f32>,
pub gui_info: Option<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,
}
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(),
}
}
}

View file

@ -1,4 +1,4 @@
use anyhow::{Result, bail}; use anyhow::Result;
use assetpath::AssetPath; use assetpath::AssetPath;
use crate::prelude::*; use crate::prelude::*;
@ -54,9 +54,9 @@ pub struct RasterizerInfo {
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct ControllerPictureDirectories { pub struct ControllerPictureDirectories {
pub xbox_path: Option<AssetPath>, pub xbox_path: AssetPath,
pub steam_path: Option<AssetPath>, pub steam_path: AssetPath,
pub ps4_path: Option<AssetPath>, pub ps4_path: AssetPath,
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
@ -97,7 +97,7 @@ pub struct EngineSettings {
impl EngineSettings { impl EngineSettings {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
context: &Context, context: &Arc<Context>,
mut graphics_info: GraphicsInfo, mut graphics_info: GraphicsInfo,
raytracing_info: RaytracingInfo, raytracing_info: RaytracingInfo,
rasterizer_info: RasterizerInfo, rasterizer_info: RasterizerInfo,
@ -191,25 +191,15 @@ impl EngineSettings {
pub fn controller_icon( pub fn controller_icon(
&self, &self,
context: &Context, engine: &Engine,
button: ControllerButton,
) -> Result<Arc<Image>> {
Ok(self
._controller_icon(context, button)?
.unwrap_or(self.controller_button_for(context, button, ControllerType::XBox)?))
}
fn _controller_icon(
&self,
context: &Context,
button: ControllerButton, button: ControllerButton,
) -> Result<Option<Arc<Image>>> { ) -> Result<Option<Arc<Image>>> {
// TODO: don't check it every time we request a button // TODO: don't check it every time we request a button
self.check_controller(context)?; self.check_controller(engine.context())?;
match self.current_controller_type.read().unwrap().as_ref() { match self.current_controller_type.read().unwrap().as_ref() {
Some(controller_type) => Ok(Some(self.controller_button_for( Some(controller_type) => Ok(Some(self.controller_button_for(
context, engine,
button, button,
*controller_type, *controller_type,
)?)), )?)),
@ -219,7 +209,7 @@ impl EngineSettings {
pub fn controller_button_for( pub fn controller_button_for(
&self, &self,
context: &Context, engine: &Engine,
button: ControllerButton, button: ControllerButton,
controller: ControllerType, controller: ControllerType,
) -> Result<Arc<Image>> { ) -> Result<Arc<Image>> {
@ -229,27 +219,26 @@ impl EngineSettings {
return Ok(image.clone()); return Ok(image.clone());
} }
let image_path_opt = match controller { let image_path = match controller {
ControllerType::PS4 => self.controller_directories.ps4_path.as_ref().map(|path| { ControllerType::PS4 => AssetPath::from((
AssetPath::from((path.full_path(), Self::ps4_input_map_to_texture(&button))) self.controller_directories.ps4_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::Steam => AssetPath::from((
}), self.controller_directories.steam_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))) ControllerType::XBox => AssetPath::from((
}), self.controller_directories.xbox_path.full_path(),
Self::xbox_input_map_to_texture(&button),
)),
}; };
let image_path = match image_path_opt { let ctx = engine.context();
Some(p) => p,
None => bail!("path not set"),
};
let image = Image::from_file(image_path)? let image = Image::from_file(image_path)?
.attach_sampler(Sampler::nearest_sampler().build(context.device())?) .attach_sampler(Sampler::nearest_sampler().build(ctx.device())?)
.build(context.device(), context.queue())?; .build(ctx.device(), ctx.queue())?;
map.insert(button, image.clone()); map.insert(button, image.clone());
@ -347,8 +336,8 @@ impl EngineSettings {
} }
} }
fn check_controller(&self, context: &Context) -> Result<()> { fn check_controller(&self, context: &Arc<Context>) -> Result<()> {
let active_controller = context.active_controller(); let active_controller = context.active_controller()?;
match &active_controller { match &active_controller {
// there is an controller connected // there is an controller connected

View file

@ -1,8 +1,7 @@
pub mod engine; pub mod engine;
pub mod engine_settings; pub mod enginesettings;
pub mod engine_object; pub mod engineobject;
pub mod asset_handler; pub mod asset_handler;
pub mod engine_create_info;
// pub mod engine_object_data; // pub mod engine_object_data;

View file

@ -7,13 +7,18 @@ pub use loading_screen::*;
pub use crate::scene::prelude::*; pub use crate::scene::prelude::*;
pub use crate::engine::{ pub use crate::engine::{
asset_handler::{AssetHandler, AssetLoader}, // engine_object_data::*,
engine::*, engineobject::{
engine_create_info::EngineCreateInfo, EngineObject,
engine_object::{EngineEvent, EngineObject}, // EngineObjectHelper
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::{ pub use serde::{
Deserialize, Deserializer, Serialize, Serializer, Deserialize, Deserializer, Serialize, Serializer,
ser::{SerializeMap, SerializeSeq, SerializeStruct}, ser::{SerializeMap, SerializeSeq, SerializeStruct},
@ -22,7 +27,7 @@ pub use serde::{
pub use ecs::*; pub use ecs::*;
pub use ron; pub use ron;
pub use crate::assets::asset_cache::AssetCache; pub use crate::assets::assetcache::AssetCache;
pub use asset::*; pub use asset::*;

View file

@ -16,11 +16,12 @@ pub struct Audio {
current_state: Option<Arc<Sound>>, current_state: Option<Arc<Sound>>,
position: Vector3<f32>, position: Vector3<f32>,
context: Arc<Context>,
} }
impl Audio { impl Audio {
pub fn new( pub fn new(
context: &mut Context, context: &Arc<Context>,
sounds: impl Into<Option<HashMap<String, AssetPath>>>, sounds: impl Into<Option<HashMap<String, AssetPath>>>,
) -> Result<Self> { ) -> Result<Self> {
let mut sound_map = HashMap::new(); let mut sound_map = HashMap::new();
@ -42,11 +43,12 @@ impl Audio {
current_state: None, current_state: None,
position: Vector3::zero(), position: Vector3::zero(),
context: context.clone(),
}) })
} }
pub fn from_info( pub fn from_info(
context: &mut Context, context: &Arc<Context>,
data_prefix: &str, data_prefix: &str,
sounds: Vec<(String, AssetPath)>, sounds: Vec<(String, AssetPath)>,
) -> Result<Self> { ) -> Result<Self> {
@ -73,14 +75,10 @@ impl Audio {
Ok(()) Ok(())
} }
pub fn set_sound( pub fn set_sound(&mut self, path: AssetPath, sound_type: &str) -> Result<()> {
&mut self,
context: &mut Context,
path: AssetPath,
sound_type: &str,
) -> Result<()> {
if let Some(audio) = self.custom_sounds.get_mut(sound_type) { if let Some(audio) = self.custom_sounds.get_mut(sound_type) {
*audio = context *audio = self
.context
.sound() .sound()
.load_sound(path, "sfx", SoundInterpretation::Spatial)?; .load_sound(path, "sfx", SoundInterpretation::Spatial)?;
} }
@ -103,9 +101,9 @@ impl Audio {
Ok(()) Ok(())
} }
fn clear(&mut self, context: &mut Context) -> Result<()> { fn clear(&mut self) -> Result<()> {
for sound in self.custom_sounds.values() { for sound in self.custom_sounds.values() {
context.sound().remove_sound(sound)?; self.context.sound().remove_sound(sound)?;
} }
Ok(()) Ok(())
@ -149,15 +147,10 @@ impl Audio {
Ok(()) Ok(())
} }
pub fn add_custom_sound( pub fn add_custom_sound(&mut self, path: AssetPath, sound_type: &str) -> Result<()> {
&mut self,
context: &mut Context,
path: AssetPath,
sound_type: &str,
) -> Result<()> {
self.custom_sounds.insert( self.custom_sounds.insert(
sound_type.to_string(), sound_type.to_string(),
context self.context
.sound() .sound()
.load_sound(path, "sfx", SoundInterpretation::Spatial)?, .load_sound(path, "sfx", SoundInterpretation::Spatial)?,
); );
@ -175,14 +168,8 @@ impl EntityComponent for Audio {
self.play(ON_ENABLE_SOUND, false) self.play(ON_ENABLE_SOUND, false)
} }
fn disable(&mut self, world: &mut World) -> Result<()> { fn disable(&mut self, _world: &mut World) -> Result<()> {
self.play(ON_DISABLE_SOUND, false)?; self.play(ON_DISABLE_SOUND, false)
if let Some(sound) = &self.current_state {
sound.stop_looping().unwrap();
}
self.clear(world.resources.get_mut::<Context>())
} }
} }
@ -191,3 +178,13 @@ impl ComponentDebug for Audio {
"Audio" "Audio"
} }
} }
impl Drop for Audio {
fn drop(&mut self) {
if let Some(sound) = &self.current_state {
sound.stop_looping().unwrap();
}
self.clear().unwrap();
}
}

View file

@ -18,6 +18,7 @@ use rayon::prelude::*;
use utilities::prelude::cgmath::{Matrix4, Vector3, vec3}; use utilities::prelude::cgmath::{Matrix4, Vector3, vec3};
use std::sync::Mutex; use std::sync::Mutex;
use std::time::Instant;
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
use std::time::Instant; use std::time::Instant;
@ -31,15 +32,18 @@ pub struct Scene {
device: Arc<Device>, device: Arc<Device>,
queue: Arc<Mutex<Queue>>, queue: Arc<Mutex<Queue>>,
render_type: SceneType, pub(crate) render_type: SceneType,
last_frame: Duration, pub(crate) map: Option<Box<dyn Map>>,
frame_time: Duration,
pub(crate) start_time: Instant,
pub(crate) last_frame: Duration,
pub(crate) frame_time: Duration,
// renderer of this scene // renderer of this scene
renderer: Box<dyn RenderingFrontEnd + Send + Sync>, pub(crate) renderer: Box<dyn RenderingFrontEnd + Send + Sync>,
frustum_check: Option< pub(crate) frustum_check: Option<
Box< Box<
dyn Fn(&EntityObject, &Matrix4<f32>, &ViewFrustum, &FrustumPlanes) -> Result<bool> dyn Fn(&EntityObject, &Matrix4<f32>, &ViewFrustum, &FrustumPlanes) -> Result<bool>
+ Send + Send
@ -47,10 +51,10 @@ pub struct Scene {
>, >,
>, >,
particle_system_vulkan_objects: ParticleSystemVulkanObjects, pub(crate) particle_system_vulkan_objects: ParticleSystemVulkanObjects,
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
timings: Timings, pub(crate) timings: Timings,
} }
impl Scene { impl Scene {
@ -83,7 +87,7 @@ impl Scene {
let particle_system_vulkan_objects = ParticleSystemVulkanObjects::new(device, queue, cs)?; let particle_system_vulkan_objects = ParticleSystemVulkanObjects::new(device, queue, cs)?;
let scene = Scene { let mut scene = Scene {
screen_width, screen_width,
screen_height, screen_height,
@ -91,11 +95,13 @@ impl Scene {
device: device.clone(), device: device.clone(),
queue: queue.clone(), queue: queue.clone(),
map: None,
frustum_check: None, frustum_check: None,
renderer, renderer,
start_time: Instant::now(),
last_frame: Duration::from_secs(0), last_frame: Duration::from_secs(0),
frame_time: Duration::from_secs(0), frame_time: Duration::from_secs(0),
@ -118,6 +124,19 @@ impl Scene {
} }
} }
// object handling
impl Scene {
pub fn set_map(&mut self, map_opt: Option<Box<dyn Map>>) -> Result<()> {
if let Some(old_map) = self.map.take() {
old_map.disable(self)?;
}
self.map = map_opt;
Ok(())
}
}
impl Scene { impl Scene {
pub(crate) fn _world_to_screen_space( pub(crate) fn _world_to_screen_space(
(screen_width, screen_height): (f32, f32), (screen_width, screen_height): (f32, f32),
@ -170,13 +189,12 @@ impl Scene {
VkCommandBufferBeginInfo::new(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); VkCommandBufferBeginInfo::new(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
begin_info.set_inheritance_info(&inheritance_info); begin_info.set_inheritance_info(&inheritance_info);
let scene = world.resources.get_mut_unchecked::<Scene>(); let scene = world.resources.get_mut::<Scene>();
let particle_handles = scene.particle_system_vulkan_objects_mut(); let particle_handles = scene.particle_system_vulkan_objects_mut();
let pipeline = particle_handles.pipeline.clone();
let mut recorder = particle_handles.begin(begin_info)?; let mut recorder = particle_handles.begin(begin_info)?;
particle_system.animate(&mut recorder, &pipeline, world)?; particle_system.animate(&mut recorder, &particle_handles.pipeline, world)?;
} }
Ok(()) Ok(())
@ -387,10 +405,9 @@ impl TScene for Scene {
buffer_recorder: &mut CommandBufferRecorder<'_>, buffer_recorder: &mut CommandBufferRecorder<'_>,
images: &TargetMode<Vec<Arc<Image>>>, images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>, indices: &TargetMode<usize>,
world: &World,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
self.frame_time = { self.frame_time = {
let now = world.now(); let now = self.now();
let d = if self.last_frame < now { let d = if self.last_frame < now {
now - self.last_frame now - self.last_frame
@ -413,8 +430,11 @@ impl TScene for Scene {
} }
} }
// queue particle system commands // calculate movements and collision detection when map is present
{ if self.map.is_some() {
self.update()?;
// queue particle system commands
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
let before = Instant::now(); let before = Instant::now();
@ -426,54 +446,50 @@ impl TScene for Scene {
.add("particles", Instant::now().duration_since(before)); .add("particles", Instant::now().duration_since(before));
} }
// gather entities #[cfg(feature = "timings")]
let content = { let before = Instant::now();
#[cfg(feature = "timings")]
let before = Instant::now();
let content = match &self.frustum_check { let content = match &self.frustum_check {
Some(frustum_check) => { Some(frustum_check) => {
let view = self.renderer.view(); let view = self.renderer.view();
let vp = view.proj() * view.camera().old_view_matrix(); let vp = view.proj() * view.camera().old_view_matrix();
let frustum = view.frustum(); let frustum = view.frustum();
let planes = frustum.planes(); let planes = frustum.planes();
let content: Vec<Option<&EntityObject>> = world let content: Vec<Option<&EntityObject>> = self
.entities() .entities
.map(|entity_object| { .par_values()
if frustum_check(entity_object, &vp, &frustum, &planes)? { .map(|entity_object| {
Ok(Some(entity_object)) if frustum_check(entity_object, &vp, &frustum, &planes)? {
} else { Ok(Some(entity_object))
Ok(None) } else {
} Ok(None)
}) }
.collect::<Result<Vec<Option<&EntityObject>>>>()?; })
.collect::<Result<Vec<Option<&EntityObject>>>>()?;
content.into_iter().flatten().collect() content.into_iter().flatten().collect()
} }
None => world.entities().collect(), None => self
}; .entities
.par_iter()
#[cfg(feature = "timings")] .map(|(_entity, entity_object)| entity_object)
self.timings .collect(),
.add("frustum", Instant::now().duration_since(before));
content
}; };
// render #[cfg(feature = "timings")]
{ self.timings
#[cfg(feature = "timings")] .add("frustum", Instant::now().duration_since(before));
let before = Instant::now();
self.renderer #[cfg(feature = "timings")]
.process(content, buffer_recorder, images, indices)?; let before = Instant::now();
self.renderer
.process(content, buffer_recorder, images, indices)?;
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
self.timings self.timings
.add("renderer", Instant::now().duration_since(before)); .add("renderer", Instant::now().duration_since(before));
}
Ok(()) Ok(())
} }

View file

@ -124,11 +124,7 @@ impl EntityManager {
impl AssetLoader for EntityManager { impl AssetLoader for EntityManager {
/// Loads an entity file and creates an Entity /// Loads an entity file and creates an Entity
fn load_entity( fn load_entity(&mut self, assets: AssetHandler<'_>, entity_file: &str) -> Result<EntityObject> {
&mut self,
mut assets: AssetHandler<'_>,
entity_file: &str,
) -> Result<EntityObject> {
// load entity file // load entity file
let file = self.load_entity_file(entity_file); let file = self.load_entity_file(entity_file);
@ -169,10 +165,7 @@ impl AssetLoader for EntityManager {
} }
} }
entity_object.insert_component(Audio::new( entity_object.insert_component(Audio::new(assets.context(), entity_parser.sound_map)?);
assets.world().resources.get_mut::<Context>(),
entity_parser.sound_map,
)?);
} }
Ok(entity_object) Ok(entity_object)

View file

@ -9,7 +9,7 @@ pub enum CollisionEventType {
} }
pub type HitCallback = pub type HitCallback =
dyn FnMut(&mut World, Entity, Entity) -> Result<CollisionEventType> + Send + Sync; dyn FnMut(&mut SceneContents<'_>, Entity, Entity) -> Result<CollisionEventType> + Send + Sync;
// HitBox is basically a cylinder // HitBox is basically a cylinder
pub struct HitBox { pub struct HitBox {
@ -88,7 +88,10 @@ impl HitBox {
pub fn set_event<F>(&mut self, f: F) pub fn set_event<F>(&mut self, f: F)
where where
F: FnMut(&mut World, Entity, Entity) -> Result<CollisionEventType> + Send + Sync + 'static, F: FnMut(&mut SceneContents<'_>, Entity, Entity) -> Result<CollisionEventType>
+ Send
+ Sync
+ 'static,
{ {
self.hit_event = Some(Box::new(f)); self.hit_event = Some(Box::new(f));
} }
@ -123,12 +126,12 @@ impl HitBox {
pub fn collision( pub fn collision(
&mut self, &mut self,
world: &mut World, scene: &mut SceneContents<'_>,
me: Entity, me: Entity,
collider: Entity, collider: Entity,
) -> Result<CollisionEventType> { ) -> Result<CollisionEventType> {
match &mut self.hit_event { match &mut self.hit_event {
Some(hit_event) => hit_event(world, me, collider), Some(hit_event) => hit_event(scene, me, collider),
None => Ok(CollisionEventType::Ignore), None => Ok(CollisionEventType::Ignore),
} }
} }

View file

@ -6,7 +6,30 @@ use engine::prelude::*;
fn main() -> Result<()> { fn main() -> Result<()> {
let mut world_builder = World::builder(); let mut world_builder = World::builder();
Engine::new(EngineCreateInfo::default(), &mut 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);
world_builder.build().run() world_builder.build().run()
} }

View file

@ -1,16 +1,17 @@
use sdl2; use sdl2;
use sdl2::EventPump;
use sdl2::EventSubsystem;
use sdl2::GameControllerSubsystem;
use sdl2::Sdl;
use sdl2::controller::Button; use sdl2::controller::Button;
use sdl2::event::{Event as SdlEvent, EventType as SdlEventType, WindowEvent}; use sdl2::event::{Event as SdlEvent, EventType as SdlEventType, WindowEvent};
use sdl2::keyboard::Keycode; use sdl2::keyboard::Keycode;
use sdl2::mouse::{MouseButton as SdlMouseButton, MouseUtil, MouseWheelDirection}; use sdl2::mouse::{MouseButton as SdlMouseButton, MouseUtil, MouseWheelDirection};
use sdl2::EventPump;
use sdl2::EventSubsystem;
use sdl2::GameControllerSubsystem;
use sdl2::Sdl;
use ui::prelude::*; use ui::prelude::*;
use std::sync::{Arc, RwLock}; use std::ops::Deref;
use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard};
use crate::Result; use crate::Result;
@ -75,33 +76,37 @@ pub enum Event {
} }
pub struct EventSystem { pub struct EventSystem {
event_pump: EventPump, event_pump: RwLock<EventPump>,
mouse: MouseUtil, mouse: Mutex<MouseUtil>,
controller_subsystem: GameControllerSubsystem, controller_subsystem: Mutex<GameControllerSubsystem>,
event_subsystem: EventSubsystem, event_subsystem: Mutex<EventSubsystem>,
controller_deadzones: ControllerDeadzones, controller_deadzones: RwLock<ControllerDeadzones>,
selected_controller: Option<Arc<RwLock<Controller>>>, selected_controller: RwLock<Option<Arc<RwLock<Controller>>>>,
connected_controllers: Vec<Arc<RwLock<Controller>>>, connected_controllers: RwLock<Vec<Arc<RwLock<Controller>>>>,
} }
impl EventSystem { impl EventSystem {
pub fn new(sdl2_context: &Sdl) -> Result<EventSystem> { pub fn new(sdl2_context: &Sdl) -> Result<EventSystem> {
let mut event_system = EventSystem { let event_system = EventSystem {
event_pump: sdl2_context event_pump: RwLock::new(
.event_pump() sdl2_context
.map_err(|s| anyhow::Error::msg(s))?, .event_pump()
mouse: sdl2_context.mouse(), .map_err(|s| anyhow::Error::msg(s))?,
controller_subsystem: sdl2_context ),
.game_controller() mouse: Mutex::new(sdl2_context.mouse()),
.map_err(|s| anyhow::Error::msg(s))?, controller_subsystem: Mutex::new(
event_subsystem: sdl2_context.event().map_err(|s| anyhow::Error::msg(s))?, 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))?),
controller_deadzones: ControllerDeadzones::default(), controller_deadzones: RwLock::new(ControllerDeadzones::default()),
selected_controller: None, selected_controller: RwLock::new(None),
connected_controllers: Vec::new(), connected_controllers: RwLock::new(Vec::new()),
}; };
event_system.disable_mouse(); event_system.disable_mouse();
@ -111,81 +116,102 @@ impl EventSystem {
Ok(event_system) Ok(event_system)
} }
pub fn enable_mouse(&mut self) { pub fn enable_mouse(&self) {
self.event_pump.enable_event(SdlEventType::MouseMotion); let mut event_pump = self.event_pump.write().unwrap();
self.event_pump.enable_event(SdlEventType::MouseButtonDown);
self.event_pump.enable_event(SdlEventType::MouseButtonUp);
self.mouse.show_cursor(true); 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);
} }
pub fn disable_mouse(&mut self) { pub fn disable_mouse(&self) {
self.event_pump.disable_event(SdlEventType::MouseMotion); let mut event_pump = self.event_pump.write().unwrap();
self.event_pump.disable_event(SdlEventType::MouseButtonDown);
self.event_pump.disable_event(SdlEventType::MouseButtonUp);
self.mouse.show_cursor(false); 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);
} }
pub fn enable_keyboard(&mut self) { pub fn enable_keyboard(&self) {
self.event_pump.enable_event(SdlEventType::KeyUp); let mut event_pump = self.event_pump.write().unwrap();
self.event_pump.enable_event(SdlEventType::KeyDown);
event_pump.enable_event(SdlEventType::KeyUp);
event_pump.enable_event(SdlEventType::KeyDown);
} }
pub fn disable_keyboard(&mut self) { pub fn disable_keyboard(&self) {
self.event_pump.disable_event(SdlEventType::KeyUp); let mut event_pump = self.event_pump.write().unwrap();
self.event_pump.disable_event(SdlEventType::KeyDown);
event_pump.disable_event(SdlEventType::KeyUp);
event_pump.disable_event(SdlEventType::KeyDown);
} }
pub fn enable_controller(&mut self) { pub fn enable_controller(&self) {
self.event_pump let mut event_pump = self.event_pump.write().unwrap();
.enable_event(SdlEventType::ControllerAxisMotion);
self.event_pump event_pump.enable_event(SdlEventType::ControllerAxisMotion);
.enable_event(SdlEventType::ControllerButtonDown); event_pump.enable_event(SdlEventType::ControllerButtonDown);
self.event_pump event_pump.enable_event(SdlEventType::ControllerButtonUp);
.enable_event(SdlEventType::ControllerButtonUp);
} }
pub fn disable_controller(&mut self) { pub fn disable_controller(&self) {
self.event_pump let mut event_pump = self.event_pump.write().unwrap();
.disable_event(SdlEventType::ControllerAxisMotion);
self.event_pump event_pump.disable_event(SdlEventType::ControllerAxisMotion);
.disable_event(SdlEventType::ControllerButtonDown); event_pump.disable_event(SdlEventType::ControllerButtonDown);
self.event_pump event_pump.disable_event(SdlEventType::ControllerButtonUp);
.disable_event(SdlEventType::ControllerButtonUp);
} }
pub fn set_controller_axis_enable_deadzone(&mut self, deadzone: f32) { pub fn set_controller_axis_enable_deadzone(&self, deadzone: f32) {
self.controller_deadzones.axis_enable_deadzone = deadzone; self.controller_deadzones
.write()
.unwrap()
.axis_enable_deadzone = deadzone;
} }
pub fn set_controller_axis_disable_deadzone(&mut self, deadzone: f32) { pub fn set_controller_axis_disable_deadzone(&self, deadzone: f32) {
self.controller_deadzones.axis_disable_deadzone = deadzone; self.controller_deadzones
.write()
.unwrap()
.axis_disable_deadzone = deadzone;
} }
pub fn set_controller_trigger_enable_deadzone(&mut self, deadzone: f32) { pub fn set_controller_trigger_enable_deadzone(&self, deadzone: f32) {
self.controller_deadzones.trigger_enable_deadzone = deadzone; self.controller_deadzones
.write()
.unwrap()
.trigger_enable_deadzone = deadzone;
} }
pub fn set_controller_trigger_disable_deadzone(&mut self, deadzone: f32) { pub fn set_controller_trigger_disable_deadzone(&self, deadzone: f32) {
self.controller_deadzones.trigger_disable_deadzone = deadzone; self.controller_deadzones
.write()
.unwrap()
.trigger_disable_deadzone = deadzone;
} }
pub fn quit(&self) -> Result<()> { pub fn quit(&self) -> Result<()> {
Ok(self Ok(self
.event_subsystem .event_subsystem
.lock()
.unwrap()
.push_event(SdlEvent::Quit { timestamp: 0 }) .push_event(SdlEvent::Quit { timestamp: 0 })
.map_err(|s| anyhow::Error::msg(s))?) .map_err(|s| anyhow::Error::msg(s))?)
} }
pub fn poll_events<F, R>(&mut self, event_callback: F, mut resize: R) -> Result<bool> pub fn poll_events<F, R>(&self, event_callback: F, mut resize: R) -> Result<bool>
where where
F: Fn(Event) -> Result<()>, F: Fn(Event) -> Result<()>,
R: FnMut(u32, u32) -> Result<()>, R: FnMut(u32, u32) -> Result<()>,
{ {
let mut controller_axis_changed = false; let mut controller_axis_changed = false;
let mut event_pump = self.event_pump.write().unwrap();
for event in self.event_pump.poll_iter() { for event in event_pump.poll_iter() {
match event { match event {
SdlEvent::Window { win_event, .. } => match win_event { SdlEvent::Window { win_event, .. } => match win_event {
WindowEvent::Resized(w, h) | WindowEvent::SizeChanged(w, h) => { WindowEvent::Resized(w, h) | WindowEvent::SizeChanged(w, h) => {
@ -262,9 +288,9 @@ impl EventSystem {
} }
if let Ok(controller) = Controller::new( if let Ok(controller) = Controller::new(
&self.controller_subsystem, self.controller_subsystem.lock().unwrap().deref(),
which as u32, which as u32,
self.controller_deadzones.clone(), self.controller_deadzones.read().unwrap().clone(),
) { ) {
let controller = { let controller = {
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
@ -275,10 +301,16 @@ impl EventSystem {
); );
} }
let arc_controller = Arc::new(RwLock::new(controller)); let mut connected_controllers =
self.connected_controllers.push(arc_controller.clone()); self.connected_controllers.write().unwrap();
if self.selected_controller.is_none() { let mut selected_controller = self.selected_controller.write().unwrap();
let arc_controller = Arc::new(RwLock::new(controller));
connected_controllers.push(arc_controller.clone());
if selected_controller.is_none() {
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
let contr = arc_controller.read().unwrap(); let contr = arc_controller.read().unwrap();
@ -289,7 +321,7 @@ impl EventSystem {
); );
} }
self.selected_controller = Some(arc_controller.clone()); *selected_controller = Some(arc_controller.clone());
} }
arc_controller arc_controller
@ -300,10 +332,11 @@ impl EventSystem {
} }
SdlEvent::ControllerDeviceRemoved { which, .. } => { SdlEvent::ControllerDeviceRemoved { which, .. } => {
let removed_controller = { let removed_controller = {
if self.selected_controller.is_some() { let mut selected_controller = self.selected_controller.write().unwrap();
if selected_controller.is_some() {
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
let contr = let contr = selected_controller.as_ref().unwrap().read().unwrap();
self.selected_controller.as_ref().unwrap().read().unwrap();
println!( println!(
"Remove active controller: {}({})", "Remove active controller: {}({})",
@ -313,20 +346,14 @@ impl EventSystem {
} }
// unwrap is save since we just tested for `is_some()` // unwrap is save since we just tested for `is_some()`
if self if selected_controller.as_ref().unwrap().read().unwrap().id() == which {
.selected_controller *selected_controller = None;
.as_ref()
.unwrap()
.read()
.unwrap()
.id()
== which
{
self.selected_controller = None;
} }
} }
self.connected_controllers let mut connected_controllers = self.connected_controllers.write().unwrap();
connected_controllers
.iter() .iter()
.position(|controller_cell| { .position(|controller_cell| {
let controller = controller_cell.read().unwrap(); let controller = controller_cell.read().unwrap();
@ -334,7 +361,7 @@ impl EventSystem {
}) })
.map(|remove_index| { .map(|remove_index| {
let removed_controller = let removed_controller =
self.connected_controllers.swap_remove(remove_index); connected_controllers.swap_remove(remove_index);
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
let contr = removed_controller.read().unwrap(); let contr = removed_controller.read().unwrap();
@ -346,18 +373,17 @@ impl EventSystem {
} }
// if we removed the selected controller, take the controller at the first position if possible // if we removed the selected controller, take the controller at the first position if possible
if self.selected_controller.is_none() if selected_controller.is_none()
&& !self.connected_controllers.is_empty() && !connected_controllers.is_empty()
{ {
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
println!( println!(
"Set active controller: {}", "Set active controller: {}",
self.connected_controllers[0].read().unwrap().name() connected_controllers[0].read().unwrap().name()
); );
} }
self.selected_controller = *selected_controller = Some(connected_controllers[0].clone());
Some(self.connected_controllers[0].clone());
} }
removed_controller removed_controller
@ -410,7 +436,9 @@ impl EventSystem {
// which, // which,
.. ..
} => { } => {
if let Some(controller) = self.selected_controller.as_mut() { let mut selected_controller = self.selected_controller.write().unwrap();
if let Some(controller) = selected_controller.as_mut() {
let mut controller = controller.write().unwrap(); let mut controller = controller.write().unwrap();
// // only update axis, when selected controller made the change // // only update axis, when selected controller made the change
@ -453,7 +481,7 @@ impl EventSystem {
} }
if controller_axis_changed { if controller_axis_changed {
if let Some(controller) = &self.selected_controller { if let Some(controller) = self.selected_controller.read().unwrap().as_ref() {
let (left_trigger, right_trigger) = { let (left_trigger, right_trigger) = {
let mut controller_lock = controller.write().unwrap(); let mut controller_lock = controller.write().unwrap();
@ -488,21 +516,23 @@ impl EventSystem {
Ok(true) Ok(true)
} }
pub fn controllers(&self) -> &[Arc<RwLock<Controller>>] { pub fn controllers(&self) -> RwLockReadGuard<'_, Vec<Arc<RwLock<Controller>>>> {
&self.connected_controllers self.connected_controllers.read().unwrap()
} }
pub fn active_controller(&self) -> &Option<Arc<RwLock<Controller>>> { pub fn active_controller(&self) -> Result<Option<Arc<RwLock<Controller>>>> {
&self.selected_controller Ok(self.selected_controller.read().unwrap().clone())
} }
pub fn set_active_controller(&mut self, controller: &Arc<RwLock<Controller>>) { pub fn set_active_controller(&self, controller: &Arc<RwLock<Controller>>) {
if let Some(res) = self if let Some(res) = self
.connected_controllers .connected_controllers
.read()
.unwrap()
.iter() .iter()
.find(|c| Arc::ptr_eq(c, controller)) .find(|c| Arc::ptr_eq(c, controller))
{ {
self.selected_controller = Some(res.clone()); *self.selected_controller.write().unwrap() = Some(res.clone());
} }
} }
} }

View file

@ -111,7 +111,7 @@ impl PresentationCore {
}) })
} }
pub fn poll_events<F, R>(&mut self, event_callback: F, resize_event: R) -> Result<bool> pub fn poll_events<F, R>(&self, event_callback: F, resize_event: R) -> Result<bool>
where where
F: Fn(Event) -> Result<()>, F: Fn(Event) -> Result<()>,
R: FnMut(u32, u32) -> Result<()>, R: FnMut(u32, u32) -> Result<()>,
@ -123,10 +123,6 @@ impl PresentationCore {
&self.event_system &self.event_system
} }
pub fn event_system_mut(&mut self) -> &mut EventSystem {
&mut self.event_system
}
pub fn activate_vulkan_instance_extensions( pub fn activate_vulkan_instance_extensions(
&self, &self,
extensions: &mut InstanceExtensions, extensions: &mut InstanceExtensions,

View file

@ -171,11 +171,10 @@ impl<S: TScene + 'static> RenderBackend<S> {
} }
// make a call to the connected scene // make a call to the connected scene
world.resources.get_mut_unchecked::<S>().process( world.resources.get_mut::<S>().process(
&mut buffer_recorder, &mut buffer_recorder,
&*self.swapchain_images.lock().unwrap(), &*self.swapchain_images.lock().unwrap(),
&image_indices, &image_indices,
world,
)?; )?;
// post processing // post processing

View file

@ -14,7 +14,6 @@ pub trait TScene: Send + Sync {
buffer_recorder: &mut CommandBufferRecorder<'_>, buffer_recorder: &mut CommandBufferRecorder<'_>,
images: &TargetMode<Vec<Arc<Image>>>, images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>, indices: &TargetMode<usize>,
world: &World,
) -> Result<()>; ) -> Result<()>;
fn resize( fn resize(