Fix engine for new concept

This commit is contained in:
hodasemi 2025-02-27 14:14:29 +01:00
parent 4e8f652ffd
commit 5513558f3d
24 changed files with 546 additions and 577 deletions

0
.zed/settings.json Normal file
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: Mutex<SoundHandler>, sound_handler: SoundHandler,
os_specific: OsSpecific, os_specific: OsSpecific,
@ -61,12 +61,11 @@ impl Context {
} }
#[cfg(feature = "sound")] #[cfg(feature = "sound")]
pub fn sound(&self) -> MutexGuard<'_, SoundHandler> { pub fn sound(&mut self) -> &mut SoundHandler {
self.sound_handler.lock().unwrap() &mut self.sound_handler
} }
pub fn run<C>(&self, world: &mut World) -> Result<()> { pub fn next_frame<C>(&mut self, world: &mut World) -> Result<bool> {
'running: loop {
let render_core = self.render_core.clone(); let render_core = self.render_core.clone();
match self.presentation.poll_events( match self.presentation.poll_events(
@ -82,7 +81,7 @@ impl Context {
) { ) {
Ok(res) => { Ok(res) => {
if !res { if !res {
break 'running; return Ok(false);
} }
} }
Err(err) => { Err(err) => {
@ -93,13 +92,10 @@ impl Context {
} }
if !self.render_core_mut().next_frame(world)? { if !self.render_core_mut().next_frame(world)? {
break 'running; return Ok(false);
}
} }
self.render_core_mut().clear_post_processing_routines(); 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>> + '_ {
@ -129,17 +125,17 @@ impl Context {
self.core.queue() self.core.queue()
} }
pub fn controllers(&self) -> RwLockReadGuard<'_, Vec<Arc<RwLock<Controller>>>> { pub fn controllers(&self) -> &[Arc<RwLock<Controller>>] {
self.presentation.event_system().controllers() self.presentation.event_system().controllers()
} }
pub fn active_controller(&self) -> Result<Option<Arc<RwLock<Controller>>>> { pub fn active_controller(&self) -> &Option<Arc<RwLock<Controller>>> {
Ok(self.presentation.event_system().active_controller()?) self.presentation.event_system().active_controller()
} }
pub fn set_active_controller(&self, controller: &Arc<RwLock<Controller>>) { pub fn set_active_controller(&mut self, controller: &Arc<RwLock<Controller>>) {
self.presentation self.presentation
.event_system() .event_system_mut()
.set_active_controller(controller) .set_active_controller(controller)
} }
} }
@ -184,7 +180,7 @@ impl ContextInterface for Context {
} }
#[cfg(feature = "sound")] #[cfg(feature = "sound")]
fn sound_handler(&self) -> MutexGuard<'_, SoundHandler> { fn sound_handler(&mut self) -> &mut SoundHandler {
self.sound() self.sound()
} }
} }
@ -402,22 +398,22 @@ impl ContextBuilder {
let vr_mode = self.get_vr_mode(); let vr_mode = self.get_vr_mode();
let presentation = let mut 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() .event_system_mut()
.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() .event_system_mut()
.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() .event_system_mut()
.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() .event_system_mut()
.set_controller_trigger_disable_deadzone( .set_controller_trigger_disable_deadzone(
self.controller_deadzones.trigger_disable_deadzone, self.controller_deadzones.trigger_disable_deadzone,
); );
@ -440,15 +436,15 @@ impl ContextBuilder {
)?; )?;
if self.enable_mouse { if self.enable_mouse {
presentation.event_system().enable_mouse(); presentation.event_system_mut().enable_mouse();
} }
if self.enable_keyboard { if self.enable_keyboard {
presentation.event_system().enable_keyboard(); presentation.event_system_mut().enable_keyboard();
} }
if self.enable_controller { if self.enable_controller {
presentation.event_system().enable_controller(); presentation.event_system_mut().enable_controller();
} }
Ok(Context { Ok(Context {
@ -457,7 +453,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: Mutex::new(self.create_sound_handler()?), sound_handler: self.create_sound_handler()?,
os_specific, os_specific,

View file

@ -9,8 +9,6 @@ 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,6 +4,8 @@ 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>>,
@ -32,6 +34,10 @@ 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>())
@ -42,6 +48,10 @@ 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,12 +79,16 @@ 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 now(&self) -> Duration { pub fn entities(&self) -> impl Iterator<Item = &EntityObject> {
self.start_time.elapsed() self.entities.values()
} }
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::{
atomic::{AtomicU32, Ordering},
Arc, RwLock, RwLockReadGuard, Arc, RwLock, RwLockReadGuard,
atomic::{AtomicU32, Ordering},
}; };
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: &Arc<Context>, context: &Context,
engine_settings: &Arc<EngineSettings>, engine_settings: &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 engine_settings = engine_settings.clone(); let render_type = engine_settings.graphics_info()?.render_type;
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,13 +63,7 @@ impl AssetCache {
} }
let gltf_asset = GltfAsset::new(&path)?; let gltf_asset = GltfAsset::new(&path)?;
let asset = Asset::new( let asset = Asset::new(&device, &queue, render_type, gltf_asset, &name)?;
&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 {
engine_settings: Arc<EngineSettings>, gltf_directory: AssetPath,
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: Arc<EngineSettings>) -> Result<AssetManager> { pub(crate) fn new(engine_settings: &EngineSettings) -> Result<AssetManager> {
let mut asset_manager = AssetManager { let mut asset_manager = AssetManager {
engine_settings, gltf_directory: engine_settings.gltf_directory().clone(),
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,
context: &Arc<Context>, world: &World,
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,7 +91,12 @@ impl AssetManager {
} }
} }
AssetCache::new(context, &self.engine_settings, assets, names) AssetCache::new(
world.resources.get::<Context>(),
world.resources.get::<EngineSettings>(),
assets,
names,
)
} }
/// Clears all loaded files /// Clears all loaded files
@ -111,9 +116,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.engine_settings.gltf_directory(), ".gltf")?; super::search_file_names(&self.gltf_directory, ".gltf")?;
let (mut glb_file_list, glb_file_map) = 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); gltf_file_list.append(&mut glb_file_list);
@ -127,7 +132,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.resources.get::<Context>(), asset_file, true)?; let asset = self.load_gltf_asset(world, asset_file, true)?;
let mut entity_object = world.new_entity(); let mut entity_object = world.new_entity();
@ -166,7 +171,11 @@ impl AssetManager {
let asset = Asset::new( let asset = Asset::new(
context.device(), context.device(),
context.queue(), context.queue(),
self.engine_settings.graphics_info()?.render_type, world
.resources
.get::<EngineSettings>()
.graphics_info()?
.render_type,
gltf_asset, gltf_asset,
asset_path, asset_path,
)?; )?;
@ -196,7 +205,7 @@ impl AssetManager {
pub fn async_load_gltf_file<'a, 'b>( pub fn async_load_gltf_file<'a, 'b>(
&self, &self,
context: &Arc<Context>, world: &World,
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();
@ -214,12 +223,15 @@ 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 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 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();
@ -231,13 +243,7 @@ impl AssetManager {
let gltf_asset = GltfAsset::new(&path)?; let gltf_asset = GltfAsset::new(&path)?;
let asset = Asset::new( let asset = Asset::new(&device, &queue, render_type, gltf_asset, &file_name)?;
&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();
@ -264,7 +270,10 @@ 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, context: &Context, gltf_file: &str, add: bool) -> Result<Asset> { fn load_gltf_asset(&mut self, world: &World, 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();
@ -283,7 +292,7 @@ impl AssetManager {
let asset = Asset::new( let asset = Asset::new(
context.device(), context.device(),
context.queue(), context.queue(),
self.engine_settings.graphics_info()?.render_type, engine_settings.graphics_info()?.render_type,
gltf_asset, gltf_asset,
gltf_file, gltf_file,
)?; )?;

View file

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

View file

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

View file

@ -1,56 +1,17 @@
#![allow(clippy::type_complexity)] #![allow(clippy::type_complexity)]
use super::asset_handler::AssetHandler; use super::engine_object::*;
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::assetmanager::AssetManager; use crate::assets::asset_manager::AssetManager;
use crate::prelude::*; use crate::prelude::*;
use std::sync::{Arc, RwLock, RwLockReadGuard}; use std::collections::HashMap;
use std::{collections::HashMap, marker::PhantomData}; use std::sync::{Arc, RwLock};
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>);
@ -73,37 +34,34 @@ 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,
resource_base_path: String, pub(crate) resource_base_path: String,
} }
impl Engine { impl Engine {
pub fn new(#[allow(unused)] mut create_info: EngineCreateInfo<'_>) -> Result<Self> { pub fn new(
if let Font::Path(path) = &mut create_info.gui_info.font { #[allow(unused)] mut create_info: EngineCreateInfo<'_>,
path.set_prefix(&create_info.resource_base_path); world: &mut WorldBuilder,
} ) -> Result<()> {
create_info.gui_info.resource_directory.assume_prefix_free();
create_info create_info
.controller_directories .controller_directories
.xbox_path .xbox_path
.set_prefix(&create_info.resource_base_path); .as_mut()
.map(|p| p.set_prefix(&create_info.resource_base_path));
create_info create_info
.controller_directories .controller_directories
.steam_path .steam_path
.set_prefix(&create_info.resource_base_path); .as_mut()
.map(|p| p.set_prefix(&create_info.resource_base_path));
create_info create_info
.controller_directories .controller_directories
.ps4_path .ps4_path
.set_prefix(&create_info.resource_base_path); .as_mut()
.map(|p| p.set_prefix(&create_info.resource_base_path));
create_info create_info
.asset_directories .asset_directories
@ -129,7 +87,7 @@ impl Engine {
// --------------- context -------------------- // --------------- context --------------------
let context = { let mut 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;
@ -182,10 +140,9 @@ impl Engine {
}; };
// update sound handler center // update sound handler center
{ context
let sound_handler = context.sound(); .sound()
sound_handler.set_direction(vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0))?; .set_direction(vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0))?;
}
// --------------- settings ------------------- // --------------- settings -------------------
@ -198,7 +155,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 = Arc::new(EngineSettings::new( let engine_settings = EngineSettings::new(
&context, &context,
create_info.graphics_info, create_info.graphics_info,
create_info.raytracing_info, create_info.raytracing_info,
@ -207,15 +164,26 @@ 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);
@ -227,105 +195,62 @@ 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 input = Input { direction_mapping }; let engine = Engine {
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,
};
engine_settings, world.resources.insert(context);
}) world.resources.insert(engine);
} world.resources.insert(engine_settings);
pub fn set_game_object<E>(&self, engine_object: Option<E>) -> Result<()> world.add_system(Self::main_system);
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 loading_screen<T, R, L, G>( // pub fn set_game_object<E>(&self, engine_object: Option<E>) -> Result<()>
&self, // where
gui: Option<Arc<G>>, // E: EngineObject + Send + Sync,
loader: L, // {
on_ready: R, // self.context().set_context_object(match engine_object {
) -> Result<()> // Some(engine_object) => Some(ContextObjectImpl::new(
where // self.graphical.context.clone(),
R: Fn(T) -> anyhow::Result<()> + 'static + Send + Sync, // engine_object,
T: Send + Sync + 'static, // self.graphical.input.clone(),
L: FnOnce() -> T + Send + Sync + 'static, // self.gui_handler().clone(),
G: TopLevelGui + TopGui + Send + Sync + 'static, // )?),
{ // None => None,
LoadingScreen::load(self.context(), gui, loader, on_ready) // });
}
pub fn new_point_light(&self) -> Result<Light> { // Ok(())
Light::point_light(self.context().device()) // }
}
pub fn new_directional_light(&self) -> Result<Light> { // pub fn loading_screen<T, R, L, G>(
Light::directional_light(self.context().device()) // &self,
} // gui: Option<Arc<G>>,
// loader: L,
pub fn new_spot_light(&self) -> Result<Light> { // on_ready: R,
Light::spot_light(self.context().device()) // ) -> Result<()>
} // where
// R: Fn(T) -> anyhow::Result<()> + 'static + Send + Sync,
pub fn controller_icon(&self, button: ControllerButton) -> Result<Arc<Image>> { // T: Send + Sync + 'static,
Ok(self.settings().controller_icon(self, button)?.unwrap_or( // L: FnOnce() -> T + Send + Sync + 'static,
self.settings() // G: TopLevelGui + TopGui + Send + Sync + 'static,
.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 assets(&self) -> AssetHandler<'_> { pub fn main_system(world: &mut World) -> Result<()> {
AssetHandler { //
asset_manager: &self.asset_manager,
context: &self.graphical.context, Ok(())
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

@ -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<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; use anyhow::{Result, bail};
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: AssetPath, pub xbox_path: Option<AssetPath>,
pub steam_path: AssetPath, pub steam_path: Option<AssetPath>,
pub ps4_path: AssetPath, pub ps4_path: Option<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: &Arc<Context>, context: &Context,
mut graphics_info: GraphicsInfo, mut graphics_info: GraphicsInfo,
raytracing_info: RaytracingInfo, raytracing_info: RaytracingInfo,
rasterizer_info: RasterizerInfo, rasterizer_info: RasterizerInfo,
@ -191,15 +191,25 @@ impl EngineSettings {
pub fn controller_icon( pub fn controller_icon(
&self, &self,
engine: &Engine, context: &Context,
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(engine.context())?; self.check_controller(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(
engine, context,
button, button,
*controller_type, *controller_type,
)?)), )?)),
@ -209,7 +219,7 @@ impl EngineSettings {
pub fn controller_button_for( pub fn controller_button_for(
&self, &self,
engine: &Engine, context: &Context,
button: ControllerButton, button: ControllerButton,
controller: ControllerType, controller: ControllerType,
) -> Result<Arc<Image>> { ) -> Result<Arc<Image>> {
@ -219,26 +229,27 @@ impl EngineSettings {
return Ok(image.clone()); return Ok(image.clone());
} }
let image_path = match controller { let image_path_opt = match controller {
ControllerType::PS4 => AssetPath::from(( ControllerType::PS4 => self.controller_directories.ps4_path.as_ref().map(|path| {
self.controller_directories.ps4_path.full_path(), AssetPath::from((path.full_path(), Self::ps4_input_map_to_texture(&button)))
Self::ps4_input_map_to_texture(&button), }),
)), ControllerType::Steam => self.controller_directories.steam_path.as_ref().map(|path| {
ControllerType::Steam => AssetPath::from(( AssetPath::from((path.full_path(), Self::steam_input_map_to_texture(&button)))
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| {
ControllerType::XBox => AssetPath::from(( AssetPath::from((path.full_path(), Self::xbox_input_map_to_texture(&button)))
self.controller_directories.xbox_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)? let image = Image::from_file(image_path)?
.attach_sampler(Sampler::nearest_sampler().build(ctx.device())?) .attach_sampler(Sampler::nearest_sampler().build(context.device())?)
.build(ctx.device(), ctx.queue())?; .build(context.device(), context.queue())?;
map.insert(button, image.clone()); map.insert(button, image.clone());
@ -336,8 +347,8 @@ impl EngineSettings {
} }
} }
fn check_controller(&self, context: &Arc<Context>) -> Result<()> { fn check_controller(&self, context: &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,7 +1,8 @@
pub mod engine; pub mod engine;
pub mod enginesettings; pub mod engine_settings;
pub mod engineobject; pub mod engine_object;
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,18 +7,13 @@ pub use loading_screen::*;
pub use crate::scene::prelude::*; pub use crate::scene::prelude::*;
pub use crate::engine::{ pub use crate::engine::{
// engine_object_data::*, asset_handler::{AssetHandler, AssetLoader},
engineobject::{ engine::*,
EngineObject, engine_create_info::EngineCreateInfo,
// EngineObjectHelper 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::{ pub use serde::{
Deserialize, Deserializer, Serialize, Serializer, Deserialize, Deserializer, Serialize, Serializer,
ser::{SerializeMap, SerializeSeq, SerializeStruct}, ser::{SerializeMap, SerializeSeq, SerializeStruct},
@ -27,7 +22,7 @@ pub use serde::{
pub use ecs::*; pub use ecs::*;
pub use ron; pub use ron;
pub use crate::assets::assetcache::AssetCache; pub use crate::assets::asset_cache::AssetCache;
pub use asset::*; pub use asset::*;

View file

@ -16,12 +16,11 @@ 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: &Arc<Context>, context: &mut 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();
@ -43,12 +42,11 @@ 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: &Arc<Context>, context: &mut Context,
data_prefix: &str, data_prefix: &str,
sounds: Vec<(String, AssetPath)>, sounds: Vec<(String, AssetPath)>,
) -> Result<Self> { ) -> Result<Self> {
@ -75,10 +73,14 @@ impl Audio {
Ok(()) 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) { if let Some(audio) = self.custom_sounds.get_mut(sound_type) {
*audio = self *audio = context
.context
.sound() .sound()
.load_sound(path, "sfx", SoundInterpretation::Spatial)?; .load_sound(path, "sfx", SoundInterpretation::Spatial)?;
} }
@ -101,9 +103,9 @@ impl Audio {
Ok(()) Ok(())
} }
fn clear(&mut self) -> Result<()> { fn clear(&mut self, context: &mut Context) -> Result<()> {
for sound in self.custom_sounds.values() { for sound in self.custom_sounds.values() {
self.context.sound().remove_sound(sound)?; context.sound().remove_sound(sound)?;
} }
Ok(()) Ok(())
@ -147,10 +149,15 @@ impl Audio {
Ok(()) 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( self.custom_sounds.insert(
sound_type.to_string(), sound_type.to_string(),
self.context context
.sound() .sound()
.load_sound(path, "sfx", SoundInterpretation::Spatial)?, .load_sound(path, "sfx", SoundInterpretation::Spatial)?,
); );
@ -168,8 +175,14 @@ 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>())
} }
} }
@ -178,13 +191,3 @@ 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,7 +18,6 @@ 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;
@ -32,18 +31,15 @@ pub struct Scene {
device: Arc<Device>, device: Arc<Device>,
queue: Arc<Mutex<Queue>>, queue: Arc<Mutex<Queue>>,
pub(crate) render_type: SceneType, render_type: SceneType,
pub(crate) map: Option<Box<dyn Map>>, last_frame: Duration,
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
pub(crate) renderer: Box<dyn RenderingFrontEnd + Send + Sync>, renderer: Box<dyn RenderingFrontEnd + Send + Sync>,
pub(crate) frustum_check: Option< 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
@ -51,10 +47,10 @@ pub struct Scene {
>, >,
>, >,
pub(crate) particle_system_vulkan_objects: ParticleSystemVulkanObjects, particle_system_vulkan_objects: ParticleSystemVulkanObjects,
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
pub(crate) timings: Timings, timings: Timings,
} }
impl Scene { impl Scene {
@ -87,7 +83,7 @@ impl Scene {
let particle_system_vulkan_objects = ParticleSystemVulkanObjects::new(device, queue, cs)?; let particle_system_vulkan_objects = ParticleSystemVulkanObjects::new(device, queue, cs)?;
let mut scene = Scene { let scene = Scene {
screen_width, screen_width,
screen_height, screen_height,
@ -95,13 +91,11 @@ 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),
@ -124,19 +118,6 @@ 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),
@ -189,12 +170,13 @@ 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::<Scene>(); let scene = world.resources.get_mut_unchecked::<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, &particle_handles.pipeline, world)?; particle_system.animate(&mut recorder, &pipeline, world)?;
} }
Ok(()) Ok(())
@ -405,9 +387,10 @@ 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 = self.now(); let now = world.now();
let d = if self.last_frame < now { let d = if self.last_frame < now {
now - self.last_frame 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")] #[cfg(feature = "timings")]
let before = Instant::now(); let before = Instant::now();
@ -446,6 +426,8 @@ impl TScene for Scene {
.add("particles", Instant::now().duration_since(before)); .add("particles", Instant::now().duration_since(before));
} }
// gather entities
let content = {
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
let before = Instant::now(); let before = Instant::now();
@ -457,9 +439,8 @@ impl TScene for Scene {
let frustum = view.frustum(); let frustum = view.frustum();
let planes = frustum.planes(); let planes = frustum.planes();
let content: Vec<Option<&EntityObject>> = self let content: Vec<Option<&EntityObject>> = world
.entities .entities()
.par_values()
.map(|entity_object| { .map(|entity_object| {
if frustum_check(entity_object, &vp, &frustum, &planes)? { if frustum_check(entity_object, &vp, &frustum, &planes)? {
Ok(Some(entity_object)) Ok(Some(entity_object))
@ -471,25 +452,28 @@ impl TScene for Scene {
content.into_iter().flatten().collect() content.into_iter().flatten().collect()
} }
None => self None => world.entities().collect(),
.entities
.par_iter()
.map(|(_entity, entity_object)| entity_object)
.collect(),
}; };
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
self.timings self.timings
.add("frustum", Instant::now().duration_since(before)); .add("frustum", Instant::now().duration_since(before));
content
};
// render
{
#[cfg(feature = "timings")] #[cfg(feature = "timings")]
let before = Instant::now(); let before = Instant::now();
self.renderer self.renderer
.process(content, buffer_recorder, images, indices)?; .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,7 +124,11 @@ 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(&mut self, assets: AssetHandler<'_>, entity_file: &str) -> Result<EntityObject> { fn load_entity(
&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);
@ -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::<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 SceneContents<'_>, Entity, Entity) -> Result<CollisionEventType> + Send + Sync; dyn FnMut(&mut World, Entity, Entity) -> Result<CollisionEventType> + Send + Sync;
// HitBox is basically a cylinder // HitBox is basically a cylinder
pub struct HitBox { pub struct HitBox {
@ -88,10 +88,7 @@ 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 SceneContents<'_>, Entity, Entity) -> Result<CollisionEventType> F: FnMut(&mut World, Entity, Entity) -> Result<CollisionEventType> + Send + Sync + 'static,
+ Send
+ Sync
+ 'static,
{ {
self.hit_event = Some(Box::new(f)); self.hit_event = Some(Box::new(f));
} }
@ -126,12 +123,12 @@ impl HitBox {
pub fn collision( pub fn collision(
&mut self, &mut self,
scene: &mut SceneContents<'_>, world: &mut World,
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(scene, me, collider), Some(hit_event) => hit_event(world, me, collider),
None => Ok(CollisionEventType::Ignore), None => Ok(CollisionEventType::Ignore),
} }
} }

View file

@ -6,30 +6,7 @@ use engine::prelude::*;
fn main() -> Result<()> { fn main() -> Result<()> {
let mut world_builder = World::builder(); let mut world_builder = World::builder();
let (context, engine, scene) = Engine::new(EngineCreateInfo { Engine::new(EngineCreateInfo::default(), &mut world_builder)?;
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,17 +1,16 @@
use sdl2; 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::EventPump;
use sdl2::EventSubsystem; use sdl2::EventSubsystem;
use sdl2::GameControllerSubsystem; use sdl2::GameControllerSubsystem;
use sdl2::Sdl; 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 ui::prelude::*;
use std::ops::Deref; use std::sync::{Arc, RwLock};
use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard};
use crate::Result; use crate::Result;
@ -76,37 +75,33 @@ pub enum Event {
} }
pub struct EventSystem { pub struct EventSystem {
event_pump: RwLock<EventPump>, event_pump: EventPump,
mouse: Mutex<MouseUtil>, mouse: MouseUtil,
controller_subsystem: Mutex<GameControllerSubsystem>, controller_subsystem: GameControllerSubsystem,
event_subsystem: Mutex<EventSubsystem>, event_subsystem: EventSubsystem,
controller_deadzones: RwLock<ControllerDeadzones>, controller_deadzones: ControllerDeadzones,
selected_controller: RwLock<Option<Arc<RwLock<Controller>>>>, selected_controller: Option<Arc<RwLock<Controller>>>,
connected_controllers: RwLock<Vec<Arc<RwLock<Controller>>>>, connected_controllers: 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 event_system = EventSystem { let mut event_system = EventSystem {
event_pump: RwLock::new( event_pump: sdl2_context
sdl2_context
.event_pump() .event_pump()
.map_err(|s| anyhow::Error::msg(s))?, .map_err(|s| anyhow::Error::msg(s))?,
), mouse: sdl2_context.mouse(),
mouse: Mutex::new(sdl2_context.mouse()), controller_subsystem: sdl2_context
controller_subsystem: Mutex::new(
sdl2_context
.game_controller() .game_controller()
.map_err(|s| anyhow::Error::msg(s))?, .map_err(|s| anyhow::Error::msg(s))?,
), event_subsystem: sdl2_context.event().map_err(|s| anyhow::Error::msg(s))?,
event_subsystem: Mutex::new(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), selected_controller: None,
connected_controllers: RwLock::new(Vec::new()), connected_controllers: Vec::new(),
}; };
event_system.disable_mouse(); event_system.disable_mouse();
@ -116,102 +111,81 @@ impl EventSystem {
Ok(event_system) Ok(event_system)
} }
pub fn enable_mouse(&self) { pub fn enable_mouse(&mut self) {
let mut event_pump = self.event_pump.write().unwrap(); 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); self.mouse.show_cursor(true);
event_pump.enable_event(SdlEventType::MouseButtonDown);
event_pump.enable_event(SdlEventType::MouseButtonUp);
self.mouse.lock().unwrap().show_cursor(true);
} }
pub fn disable_mouse(&self) { pub fn disable_mouse(&mut self) {
let mut event_pump = self.event_pump.write().unwrap(); 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); self.mouse.show_cursor(false);
event_pump.disable_event(SdlEventType::MouseButtonDown);
event_pump.disable_event(SdlEventType::MouseButtonUp);
self.mouse.lock().unwrap().show_cursor(false);
} }
pub fn enable_keyboard(&self) { pub fn enable_keyboard(&mut self) {
let mut event_pump = self.event_pump.write().unwrap(); self.event_pump.enable_event(SdlEventType::KeyUp);
self.event_pump.enable_event(SdlEventType::KeyDown);
event_pump.enable_event(SdlEventType::KeyUp);
event_pump.enable_event(SdlEventType::KeyDown);
} }
pub fn disable_keyboard(&self) { pub fn disable_keyboard(&mut self) {
let mut event_pump = self.event_pump.write().unwrap(); self.event_pump.disable_event(SdlEventType::KeyUp);
self.event_pump.disable_event(SdlEventType::KeyDown);
event_pump.disable_event(SdlEventType::KeyUp);
event_pump.disable_event(SdlEventType::KeyDown);
} }
pub fn enable_controller(&self) { pub fn enable_controller(&mut self) {
let mut event_pump = self.event_pump.write().unwrap(); self.event_pump
.enable_event(SdlEventType::ControllerAxisMotion);
event_pump.enable_event(SdlEventType::ControllerAxisMotion); self.event_pump
event_pump.enable_event(SdlEventType::ControllerButtonDown); .enable_event(SdlEventType::ControllerButtonDown);
event_pump.enable_event(SdlEventType::ControllerButtonUp); self.event_pump
.enable_event(SdlEventType::ControllerButtonUp);
} }
pub fn disable_controller(&self) { pub fn disable_controller(&mut self) {
let mut event_pump = self.event_pump.write().unwrap(); self.event_pump
.disable_event(SdlEventType::ControllerAxisMotion);
event_pump.disable_event(SdlEventType::ControllerAxisMotion); self.event_pump
event_pump.disable_event(SdlEventType::ControllerButtonDown); .disable_event(SdlEventType::ControllerButtonDown);
event_pump.disable_event(SdlEventType::ControllerButtonUp); self.event_pump
.disable_event(SdlEventType::ControllerButtonUp);
} }
pub fn set_controller_axis_enable_deadzone(&self, deadzone: f32) { pub fn set_controller_axis_enable_deadzone(&mut self, deadzone: f32) {
self.controller_deadzones self.controller_deadzones.axis_enable_deadzone = deadzone;
.write()
.unwrap()
.axis_enable_deadzone = deadzone;
} }
pub fn set_controller_axis_disable_deadzone(&self, deadzone: f32) { pub fn set_controller_axis_disable_deadzone(&mut self, deadzone: f32) {
self.controller_deadzones self.controller_deadzones.axis_disable_deadzone = deadzone;
.write()
.unwrap()
.axis_disable_deadzone = deadzone;
} }
pub fn set_controller_trigger_enable_deadzone(&self, deadzone: f32) { pub fn set_controller_trigger_enable_deadzone(&mut self, deadzone: f32) {
self.controller_deadzones self.controller_deadzones.trigger_enable_deadzone = deadzone;
.write()
.unwrap()
.trigger_enable_deadzone = deadzone;
} }
pub fn set_controller_trigger_disable_deadzone(&self, deadzone: f32) { pub fn set_controller_trigger_disable_deadzone(&mut self, deadzone: f32) {
self.controller_deadzones self.controller_deadzones.trigger_disable_deadzone = deadzone;
.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>(&self, event_callback: F, mut resize: R) -> Result<bool> pub fn poll_events<F, R>(&mut 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 event_pump.poll_iter() { for event in self.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) => {
@ -288,9 +262,9 @@ impl EventSystem {
} }
if let Ok(controller) = Controller::new( if let Ok(controller) = Controller::new(
self.controller_subsystem.lock().unwrap().deref(), &self.controller_subsystem,
which as u32, which as u32,
self.controller_deadzones.read().unwrap().clone(), self.controller_deadzones.clone(),
) { ) {
let controller = { let controller = {
if cfg!(debug_assertions) { 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)); let arc_controller = Arc::new(RwLock::new(controller));
self.connected_controllers.push(arc_controller.clone());
connected_controllers.push(arc_controller.clone()); if self.selected_controller.is_none() {
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();
@ -321,7 +289,7 @@ impl EventSystem {
); );
} }
*selected_controller = Some(arc_controller.clone()); self.selected_controller = Some(arc_controller.clone());
} }
arc_controller arc_controller
@ -332,11 +300,10 @@ impl EventSystem {
} }
SdlEvent::ControllerDeviceRemoved { which, .. } => { SdlEvent::ControllerDeviceRemoved { which, .. } => {
let removed_controller = { let removed_controller = {
let mut selected_controller = self.selected_controller.write().unwrap(); if self.selected_controller.is_some() {
if selected_controller.is_some() {
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
let contr = selected_controller.as_ref().unwrap().read().unwrap(); let contr =
self.selected_controller.as_ref().unwrap().read().unwrap();
println!( println!(
"Remove active controller: {}({})", "Remove active controller: {}({})",
@ -346,14 +313,20 @@ impl EventSystem {
} }
// unwrap is save since we just tested for `is_some()` // unwrap is save since we just tested for `is_some()`
if selected_controller.as_ref().unwrap().read().unwrap().id() == which { if self
*selected_controller = None; .selected_controller
.as_ref()
.unwrap()
.read()
.unwrap()
.id()
== which
{
self.selected_controller = None;
} }
} }
let mut connected_controllers = self.connected_controllers.write().unwrap(); self.connected_controllers
connected_controllers
.iter() .iter()
.position(|controller_cell| { .position(|controller_cell| {
let controller = controller_cell.read().unwrap(); let controller = controller_cell.read().unwrap();
@ -361,7 +334,7 @@ impl EventSystem {
}) })
.map(|remove_index| { .map(|remove_index| {
let removed_controller = let removed_controller =
connected_controllers.swap_remove(remove_index); self.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();
@ -373,17 +346,18 @@ 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 selected_controller.is_none() if self.selected_controller.is_none()
&& !connected_controllers.is_empty() && !self.connected_controllers.is_empty()
{ {
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
println!( println!(
"Set active controller: {}", "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 removed_controller
@ -436,9 +410,7 @@ impl EventSystem {
// which, // which,
.. ..
} => { } => {
let mut selected_controller = self.selected_controller.write().unwrap(); if let Some(controller) = self.selected_controller.as_mut() {
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
@ -481,7 +453,7 @@ impl EventSystem {
} }
if controller_axis_changed { 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 (left_trigger, right_trigger) = {
let mut controller_lock = controller.write().unwrap(); let mut controller_lock = controller.write().unwrap();
@ -516,23 +488,21 @@ impl EventSystem {
Ok(true) Ok(true)
} }
pub fn controllers(&self) -> RwLockReadGuard<'_, Vec<Arc<RwLock<Controller>>>> { pub fn controllers(&self) -> &[Arc<RwLock<Controller>>] {
self.connected_controllers.read().unwrap() &self.connected_controllers
} }
pub fn active_controller(&self) -> Result<Option<Arc<RwLock<Controller>>>> { pub fn active_controller(&self) -> &Option<Arc<RwLock<Controller>>> {
Ok(self.selected_controller.read().unwrap().clone()) &self.selected_controller
} }
pub fn set_active_controller(&self, controller: &Arc<RwLock<Controller>>) { pub fn set_active_controller(&mut 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.write().unwrap() = Some(res.clone()); self.selected_controller = Some(res.clone());
} }
} }
} }

View file

@ -111,7 +111,7 @@ impl PresentationCore {
}) })
} }
pub fn poll_events<F, R>(&self, event_callback: F, resize_event: R) -> Result<bool> pub fn poll_events<F, R>(&mut 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,6 +123,10 @@ 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,10 +171,11 @@ impl<S: TScene + 'static> RenderBackend<S> {
} }
// make a call to the connected scene // make a call to the connected scene
world.resources.get_mut::<S>().process( world.resources.get_mut_unchecked::<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,6 +14,7 @@ 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(