Compare commits

..

1 commit

Author SHA1 Message Date
392b7d93db Update Rust crate itertools to 0.14.0 2025-02-27 06:02:26 +00:00
24 changed files with 578 additions and 547 deletions

View file

View file

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

View file

@ -9,6 +9,8 @@ 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,8 +4,6 @@ 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>>,
@ -34,10 +32,6 @@ 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>())
@ -48,10 +42,6 @@ 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,16 +79,12 @@ 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 entities(&self) -> impl Iterator<Item = &EntityObject> {
self.entities.values()
pub fn now(&self) -> Duration {
self.start_time.elapsed()
}
pub fn entity(

View file

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

View file

@ -9,7 +9,7 @@ use std::sync::{Arc, RwLock};
use std::thread;
pub struct AssetManager {
gltf_directory: AssetPath,
engine_settings: Arc<EngineSettings>,
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: &EngineSettings) -> Result<AssetManager> {
pub(crate) fn new(engine_settings: Arc<EngineSettings>) -> Result<AssetManager> {
let mut asset_manager = AssetManager {
gltf_directory: engine_settings.gltf_directory().clone(),
engine_settings,
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,
world: &World,
context: &Arc<Context>,
asset_names: impl IntoIterator<Item = &'b &'b str> + Clone,
) -> Result<AssetCache> {
let mut assets = Vec::new();
@ -91,12 +91,7 @@ impl AssetManager {
}
}
AssetCache::new(
world.resources.get::<Context>(),
world.resources.get::<EngineSettings>(),
assets,
names,
)
AssetCache::new(context, &self.engine_settings, assets, names)
}
/// Clears all loaded files
@ -116,9 +111,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.gltf_directory, ".gltf")?;
super::search_file_names(self.engine_settings.gltf_directory(), ".gltf")?;
let (mut glb_file_list, glb_file_map) =
super::search_file_names(&self.gltf_directory, ".glb")?;
super::search_file_names(self.engine_settings.gltf_directory(), ".glb")?;
gltf_file_list.append(&mut glb_file_list);
@ -132,7 +127,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, asset_file, true)?;
let asset = self.load_gltf_asset(world.resources.get::<Context>(), asset_file, true)?;
let mut entity_object = world.new_entity();
@ -171,11 +166,7 @@ impl AssetManager {
let asset = Asset::new(
context.device(),
context.queue(),
world
.resources
.get::<EngineSettings>()
.graphics_info()?
.render_type,
self.engine_settings.graphics_info()?.render_type,
gltf_asset,
asset_path,
)?;
@ -205,7 +196,7 @@ impl AssetManager {
pub fn async_load_gltf_file<'a, 'b>(
&self,
world: &World,
context: &Arc<Context>,
files: impl IntoIterator<Item = &'b &'b str>,
) -> Result<()> {
let mut asset_files: Vec<(AssetPath, String)> = Vec::new();
@ -223,15 +214,12 @@ impl AssetManager {
}
}
let context = world.resources.get::<Context>();
let engine_settings = world.resources.get::<EngineSettings>();
// naively spawn for every file a thread
// 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 render_type = engine_settings.graphics_info()?.render_type;
let engine_settings = self.engine_settings.clone();
let loaded_gltf_files = self.loaded_gltf_files.clone();
let queued_for_async_load = self.queued_for_async_load.clone();
@ -243,7 +231,13 @@ impl AssetManager {
let gltf_asset = GltfAsset::new(&path)?;
let asset = Asset::new(&device, &queue, render_type, gltf_asset, &file_name)?;
let asset = Asset::new(
&device,
&queue,
engine_settings.graphics_info()?.render_type,
gltf_asset,
&file_name,
)?;
{
let mut gltf_files_lock = loaded_gltf_files.write().unwrap();
@ -270,10 +264,7 @@ 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, world: &World, gltf_file: &str, add: bool) -> Result<Asset> {
let context = world.resources.get::<Context>();
let engine_settings = world.resources.get::<EngineSettings>();
fn load_gltf_asset(&mut self, context: &Context, gltf_file: &str, add: bool) -> Result<Asset> {
loop {
let queued_lock = self.queued_for_async_load.read().unwrap();
@ -292,7 +283,7 @@ impl AssetManager {
let asset = Asset::new(
context.device(),
context.queue(),
engine_settings.graphics_info()?.render_type,
self.engine_settings.graphics_info()?.render_type,
gltf_asset,
gltf_file,
)?;

View file

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

View file

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

View file

@ -1,17 +1,56 @@
#![allow(clippy::type_complexity)]
use super::engine_object::*;
use super::engine_settings::EngineSettings;
use super::asset_handler::AssetHandler;
use super::engineobject::*;
use super::enginesettings::EngineSettings;
use anyhow::Result;
use assetpath::AssetPath;
use context::prelude::cgmath::vec3;
use loading_screen::LoadingScreen;
use crate::assets::asset_manager::AssetManager;
use crate::assets::assetmanager::AssetManager;
use crate::prelude::*;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
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,
}
struct GuiPostProcess(Arc<GuiHandler>);
@ -34,34 +73,37 @@ 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,
pub(crate) resource_base_path: String,
resource_base_path: String,
}
impl Engine {
pub fn new(
#[allow(unused)] mut create_info: EngineCreateInfo<'_>,
world: &mut WorldBuilder,
) -> Result<()> {
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();
create_info
.controller_directories
.xbox_path
.as_mut()
.map(|p| p.set_prefix(&create_info.resource_base_path));
.set_prefix(&create_info.resource_base_path);
create_info
.controller_directories
.steam_path
.as_mut()
.map(|p| p.set_prefix(&create_info.resource_base_path));
.set_prefix(&create_info.resource_base_path);
create_info
.controller_directories
.ps4_path
.as_mut()
.map(|p| p.set_prefix(&create_info.resource_base_path));
.set_prefix(&create_info.resource_base_path);
create_info
.asset_directories
@ -87,7 +129,7 @@ impl Engine {
// --------------- context --------------------
let mut context = {
let context = {
create_info.app_info.engine_name = "EngineNameNeeded".to_string();
create_info.app_info.engine_version = 1;
@ -140,9 +182,10 @@ impl Engine {
};
// update sound handler center
context
.sound()
.set_direction(vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0))?;
{
let sound_handler = context.sound();
sound_handler.set_direction(vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0))?;
}
// --------------- settings -------------------
@ -155,7 +198,7 @@ impl Engine {
.ok_or_else(|| anyhow::Error::msg("No proper render type could be found"))?;
}
let engine_settings = EngineSettings::new(
let engine_settings = Arc::new(EngineSettings::new(
&context,
create_info.graphics_info,
create_info.raytracing_info,
@ -164,26 +207,15 @@ 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);
@ -195,62 +227,105 @@ impl Engine {
direction_mapping.insert(Keycode::Up, GuiDirection::Up);
direction_mapping.insert(Keycode::Down, GuiDirection::Down);
let engine = Engine {
input: Arc::new(RwLock::new(Input { direction_mapping })),
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)),
asset_manager,
resource_base_path: create_info.resource_base_path,
};
world.resources.insert(context);
world.resources.insert(engine);
world.resources.insert(engine_settings);
engine_settings,
})
}
world.add_system(Self::main_system);
pub fn set_game_object<E>(&self, engine_object: Option<E>) -> Result<()>
where
E: EngineObject + Send + Sync,
{
self.context().set_context_object(match engine_object {
Some(engine_object) => Some(ContextObjectImpl::new(
self.graphical.context.clone(),
engine_object,
self.graphical.input.clone(),
self.gui_handler().clone(),
)?),
None => None,
});
Ok(())
}
// 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 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)
}
// Ok(())
// }
pub fn new_point_light(&self) -> Result<Light> {
Light::point_light(self.context().device())
}
// 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 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 build_path(&self, path: &str) -> AssetPath {
(self.resource_base_path.as_str(), path).into()
}
pub fn main_system(world: &mut World) -> Result<()> {
//
pub fn assets(&self) -> AssetHandler<'_> {
AssetHandler {
asset_manager: &self.asset_manager,
Ok(())
context: &self.graphical.context,
resource_base_path: &self.resource_base_path,
phantom_data: PhantomData,
}
}
}
// getter
impl Engine {
pub fn settings(&self) -> &Arc<EngineSettings> {
&self.engine_settings
}
}
impl Drop for Engine {
fn drop(&mut self) {
self.context
.render_core()
.remove_post_processing_routine(self.gui_post_process.clone());
}
}

View file

@ -1,97 +0,0 @@
use std::collections::HashMap;
use crate::prelude::*;
#[derive(Debug, Clone)]
pub struct EngineCreateInfo<'a> {
pub app_info: ApplicationInfo,
pub window_info: WindowCreateInfo,
pub os_specific_config: OsSpecificConfig,
pub vulkan_debug_info: VulkanDebugInfo,
pub volume_info: HashMap<String, f32>,
pub gui_info: Option<GuiHandlerCreateInfo<'a>>,
pub enable_backtrace: bool,
pub enable_mouse: bool,
pub enable_keyboard: bool,
pub enable_controller: bool,
pub controller_deadzones: ControllerDeadzones,
pub resource_base_path: String,
// engine settings
pub controller_directories: ControllerPictureDirectories,
pub asset_directories: AssetDirectories,
pub graphics_info: GraphicsInfo,
pub raytracing_info: RaytracingInfo,
pub rasterizer_info: RasterizerInfo,
pub key_backgrounds: ButtonBackgrounds,
}
impl<'a> Default for EngineCreateInfo<'a> {
fn default() -> Self {
Self {
app_info: ApplicationInfo {
application_name: "Default Application Name".to_string(),
application_version: 1,
engine_name: "Default Engine Name".to_string(),
engine_version: 1,
},
window_info: WindowCreateInfo {
title: "Default Window Title".to_string(),
width: 1600,
height: 900,
fullscreen: false,
requested_display: None,
},
os_specific_config: OsSpecificConfig {
enable_game_mode: true,
},
vulkan_debug_info: VulkanDebugInfo {
debugging: false,
steam_layer: false,
verbose: false,
renderdoc: false,
},
volume_info: HashMap::new(),
gui_info: None,
enable_backtrace: true,
enable_mouse: true,
enable_keyboard: true,
enable_controller: true,
controller_deadzones: ControllerDeadzones::default(),
resource_base_path: String::new(),
controller_directories: ControllerPictureDirectories::default(),
asset_directories: AssetDirectories::default(),
graphics_info: GraphicsInfo {
sample_count: VK_SAMPLE_COUNT_4_BIT,
render_type: SceneType::Raytracer,
render_scale: 1.0,
vsync: true,
},
raytracing_info: RaytracingInfo {
triangles_per_as: 8,
accelerate_buffer_size: 1024,
stack_size: 32,
max_lights: 32,
recursion_depth: 3,
use_default_pipeline: true,
max_samplers: 1024,
},
rasterizer_info: RasterizerInfo {
shadow_image_size: 1024,
enable_lighting: true,
use_deferred: false,
use_shadow_maps: false,
},
key_backgrounds: ButtonBackgrounds::default(),
}
}
}

View file

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

View file

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

View file

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

View file

@ -16,11 +16,12 @@ pub struct Audio {
current_state: Option<Arc<Sound>>,
position: Vector3<f32>,
context: Arc<Context>,
}
impl Audio {
pub fn new(
context: &mut Context,
context: &Arc<Context>,
sounds: impl Into<Option<HashMap<String, AssetPath>>>,
) -> Result<Self> {
let mut sound_map = HashMap::new();
@ -42,11 +43,12 @@ impl Audio {
current_state: None,
position: Vector3::zero(),
context: context.clone(),
})
}
pub fn from_info(
context: &mut Context,
context: &Arc<Context>,
data_prefix: &str,
sounds: Vec<(String, AssetPath)>,
) -> Result<Self> {
@ -73,14 +75,10 @@ impl Audio {
Ok(())
}
pub fn set_sound(
&mut self,
context: &mut Context,
path: AssetPath,
sound_type: &str,
) -> Result<()> {
pub fn set_sound(&mut self, path: AssetPath, sound_type: &str) -> Result<()> {
if let Some(audio) = self.custom_sounds.get_mut(sound_type) {
*audio = context
*audio = self
.context
.sound()
.load_sound(path, "sfx", SoundInterpretation::Spatial)?;
}
@ -103,9 +101,9 @@ impl Audio {
Ok(())
}
fn clear(&mut self, context: &mut Context) -> Result<()> {
fn clear(&mut self) -> Result<()> {
for sound in self.custom_sounds.values() {
context.sound().remove_sound(sound)?;
self.context.sound().remove_sound(sound)?;
}
Ok(())
@ -149,15 +147,10 @@ impl Audio {
Ok(())
}
pub fn add_custom_sound(
&mut self,
context: &mut Context,
path: AssetPath,
sound_type: &str,
) -> Result<()> {
pub fn add_custom_sound(&mut self, path: AssetPath, sound_type: &str) -> Result<()> {
self.custom_sounds.insert(
sound_type.to_string(),
context
self.context
.sound()
.load_sound(path, "sfx", SoundInterpretation::Spatial)?,
);
@ -175,14 +168,8 @@ impl EntityComponent for Audio {
self.play(ON_ENABLE_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>())
fn disable(&mut self, _world: &mut World) -> Result<()> {
self.play(ON_DISABLE_SOUND, false)
}
}
@ -191,3 +178,13 @@ 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,6 +18,7 @@ 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;
@ -31,15 +32,18 @@ pub struct Scene {
device: Arc<Device>,
queue: Arc<Mutex<Queue>>,
render_type: SceneType,
pub(crate) render_type: SceneType,
last_frame: Duration,
frame_time: Duration,
pub(crate) map: Option<Box<dyn Map>>,
pub(crate) start_time: Instant,
pub(crate) last_frame: Duration,
pub(crate) frame_time: Duration,
// renderer of this scene
renderer: Box<dyn RenderingFrontEnd + Send + Sync>,
pub(crate) renderer: Box<dyn RenderingFrontEnd + Send + Sync>,
frustum_check: Option<
pub(crate) frustum_check: Option<
Box<
dyn Fn(&EntityObject, &Matrix4<f32>, &ViewFrustum, &FrustumPlanes) -> Result<bool>
+ Send
@ -47,10 +51,10 @@ pub struct Scene {
>,
>,
particle_system_vulkan_objects: ParticleSystemVulkanObjects,
pub(crate) particle_system_vulkan_objects: ParticleSystemVulkanObjects,
#[cfg(feature = "timings")]
timings: Timings,
pub(crate) timings: Timings,
}
impl Scene {
@ -83,7 +87,7 @@ impl Scene {
let particle_system_vulkan_objects = ParticleSystemVulkanObjects::new(device, queue, cs)?;
let scene = Scene {
let mut scene = Scene {
screen_width,
screen_height,
@ -91,11 +95,13 @@ 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),
@ -118,6 +124,19 @@ impl Scene {
}
}
// object handling
impl Scene {
pub fn set_map(&mut self, map_opt: Option<Box<dyn Map>>) -> Result<()> {
if let Some(old_map) = self.map.take() {
old_map.disable(self)?;
}
self.map = map_opt;
Ok(())
}
}
impl Scene {
pub(crate) fn _world_to_screen_space(
(screen_width, screen_height): (f32, f32),
@ -170,13 +189,12 @@ 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_unchecked::<Scene>();
let scene = world.resources.get_mut::<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, &pipeline, world)?;
particle_system.animate(&mut recorder, &particle_handles.pipeline, world)?;
}
Ok(())
@ -387,10 +405,9 @@ 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 = world.now();
let now = self.now();
let d = if self.last_frame < now {
now - self.last_frame
@ -413,8 +430,11 @@ impl TScene for Scene {
}
}
// queue particle system commands
{
// calculate movements and collision detection when map is present
if self.map.is_some() {
self.update()?;
// queue particle system commands
#[cfg(feature = "timings")]
let before = Instant::now();
@ -426,54 +446,50 @@ impl TScene for Scene {
.add("particles", Instant::now().duration_since(before));
}
// gather entities
let content = {
#[cfg(feature = "timings")]
let before = Instant::now();
#[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>> = 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>>>>()?;
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>>>>()?;
content.into_iter().flatten().collect()
}
None => world.entities().collect(),
};
#[cfg(feature = "timings")]
self.timings
.add("frustum", Instant::now().duration_since(before));
content
content.into_iter().flatten().collect()
}
None => self
.entities
.par_iter()
.map(|(_entity, entity_object)| entity_object)
.collect(),
};
// render
{
#[cfg(feature = "timings")]
let before = Instant::now();
#[cfg(feature = "timings")]
self.timings
.add("frustum", Instant::now().duration_since(before));
self.renderer
.process(content, buffer_recorder, images, indices)?;
#[cfg(feature = "timings")]
let before = Instant::now();
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,11 +124,7 @@ impl EntityManager {
impl AssetLoader for EntityManager {
/// Loads an entity file and creates an Entity
fn load_entity(
&mut self,
mut assets: AssetHandler<'_>,
entity_file: &str,
) -> Result<EntityObject> {
fn load_entity(&mut self, assets: AssetHandler<'_>, entity_file: &str) -> Result<EntityObject> {
// load entity file
let file = self.load_entity_file(entity_file);
@ -169,10 +165,7 @@ impl AssetLoader for EntityManager {
}
}
entity_object.insert_component(Audio::new(
assets.world().resources.get_mut::<Context>(),
entity_parser.sound_map,
)?);
entity_object.insert_component(Audio::new(assets.context(), entity_parser.sound_map)?);
}
Ok(entity_object)

View file

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

View file

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

View file

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

View file

@ -111,7 +111,7 @@ impl PresentationCore {
})
}
pub fn poll_events<F, R>(&mut self, event_callback: F, resize_event: R) -> Result<bool>
pub fn poll_events<F, R>(&self, event_callback: F, resize_event: R) -> Result<bool>
where
F: Fn(Event) -> Result<()>,
R: FnMut(u32, u32) -> Result<()>,
@ -123,10 +123,6 @@ 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,11 +171,10 @@ impl<S: TScene + 'static> RenderBackend<S> {
}
// make a call to the connected scene
world.resources.get_mut_unchecked::<S>().process(
world.resources.get_mut::<S>().process(
&mut buffer_recorder,
&*self.swapchain_images.lock().unwrap(),
&image_indices,
world,
)?;
// post processing

View file

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