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

View file

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

View file

@ -4,6 +4,8 @@ use std::{
mem::transmute,
};
use utilities::prelude::{remove_life_time, remove_life_time_mut};
#[derive(Default)]
pub struct Resources {
map: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
@ -32,6 +34,10 @@ impl Resources {
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> {
self.map
.get(&TypeId::of::<T>())
@ -42,6 +48,10 @@ impl Resources {
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> {
self.map
.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 {
self.entity_object_manager.create_entity()
}
pub fn now(&self) -> Duration {
self.start_time.elapsed()
pub fn entities(&self) -> impl Iterator<Item = &EntityObject> {
self.entities.values()
}
pub fn entity(

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -9,7 +9,7 @@ pub enum CollisionEventType {
}
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
pub struct HitBox {
@ -88,10 +88,7 @@ impl HitBox {
pub fn set_event<F>(&mut self, f: F)
where
F: FnMut(&mut SceneContents<'_>, Entity, Entity) -> Result<CollisionEventType>
+ Send
+ Sync
+ 'static,
F: FnMut(&mut World, Entity, Entity) -> Result<CollisionEventType> + Send + Sync + 'static,
{
self.hit_event = Some(Box::new(f));
}
@ -126,12 +123,12 @@ impl HitBox {
pub fn collision(
&mut self,
scene: &mut SceneContents<'_>,
world: &mut World,
me: Entity,
collider: Entity,
) -> Result<CollisionEventType> {
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),
}
}

View file

@ -6,30 +6,7 @@ use engine::prelude::*;
fn main() -> Result<()> {
let mut world_builder = World::builder();
let (context, engine, scene) = Engine::new(EngineCreateInfo {
app_info: todo!(),
window_info: todo!(),
os_specific_config: todo!(),
vulkan_debug_info: todo!(),
volume_info: todo!(),
gui_info: todo!(),
enable_backtrace: todo!(),
enable_mouse: todo!(),
enable_keyboard: todo!(),
enable_controller: todo!(),
controller_deadzones: todo!(),
resource_base_path: todo!(),
controller_directories: todo!(),
asset_directories: todo!(),
graphics_info: todo!(),
raytracing_info: todo!(),
rasterizer_info: todo!(),
key_backgrounds: todo!(),
})?;
world_builder.resources.insert(context);
world_builder.resources.insert(engine);
world_builder.resources.insert(scene);
Engine::new(EngineCreateInfo::default(), &mut world_builder)?;
world_builder.build().run()
}

View file

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

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
F: Fn(Event) -> Result<()>,
R: FnMut(u32, u32) -> Result<()>,
@ -123,6 +123,10 @@ impl PresentationCore {
&self.event_system
}
pub fn event_system_mut(&mut self) -> &mut EventSystem {
&mut self.event_system
}
pub fn activate_vulkan_instance_extensions(
&self,
extensions: &mut InstanceExtensions,

View file

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

View file

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