Compare commits

..

3 commits

Author SHA1 Message Date
70b03e10ef Update Rust crate ron to 0.10.0 2025-04-10 21:02:21 +00:00
49da5c947d Start generalizing event system 2025-04-10 22:14:17 +02:00
5ee7edf31b Rework render system 2025-04-10 20:09:20 +02:00
15 changed files with 366 additions and 296 deletions

View file

@ -58,18 +58,18 @@ impl Context {
&mut self.sound_handler &mut self.sound_handler
} }
pub fn next_frame<'a, C, F>(&mut self, world: &mut World, mut f: F) -> Result<bool> pub fn events<'a, F>(&mut self, world: &World, mut f: F) -> Result<bool>
where where
C: ResourceTrait + Send + Sync + 'static, F: FnMut(Event<'_>) -> Result<()> + Send + Sync + 'a,
F: FnMut(&mut World, &mut C, Event<'_>) -> Result<()> + Send + Sync + 'a,
{ {
let render_core = self.render_core.clone(); let render_core = self.render_core.clone();
let consumer = world.resources.get_mut_unchecked::<C>();
let w = unsafe { remove_life_time_mut(world) };
match self.presentation.poll_events( match self.presentation.poll_events(
|event| f(w, consumer, event), |event| f(event),
|w, h| render_core.write().unwrap().resize(world, w, h), |w, h| {
render_core.write().unwrap().resize(world, w, h);
Ok(())
},
) { ) {
Ok(res) => { Ok(res) => {
if !res { if !res {
@ -84,11 +84,26 @@ impl Context {
} }
} }
if !self.render_core_mut().next_frame(world)? { Ok(true)
return Ok(false);
} }
Ok(true) pub fn start_frame(&self, world: &World) -> Result<()> {
self.render_core_mut().begin_frame(world)
}
pub fn render<F>(&self, render: F) -> Result<()>
where
F: FnOnce(
&mut CommandBufferRecorder<'_>,
&TargetMode<Vec<Arc<Image>>>,
&TargetMode<usize>,
) -> Result<()>,
{
self.render_core_mut().render(render)
}
pub fn end_frame(&self, world: &World) -> Result<()> {
self.render_core_mut().end_frame(world)
} }
pub fn render_core(&self) -> impl Deref<Target = RenderCore> + '_ { pub fn render_core(&self) -> impl Deref<Target = RenderCore> + '_ {

View file

@ -14,33 +14,6 @@ use crate::prelude::*;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
#[derive(Resource)]
pub struct GuiHandlerRenderer;
impl TScene for GuiHandlerRenderer {
fn process(
&mut self,
buffer_recorder: &mut CommandBufferRecorder<'_>,
_images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>,
world: &mut World,
) -> Result<()> {
let gui_handler: &mut GuiHandler = world.resources.get_mut()?;
gui_handler.process(buffer_recorder, indices)
}
fn resize(
&mut self,
window_width: f32,
window_height: f32,
images: &TargetMode<Vec<Arc<Image>>>,
world: &mut World,
) -> Result<()> {
let gui_handler: &mut GuiHandler = world.resources.get_mut()?;
gui_handler.resize(window_width as u32, window_height as u32, images)
}
}
#[derive(Resource)] #[derive(Resource)]
pub struct Engine { pub struct Engine {
pub(crate) resource_base_path: String, pub(crate) resource_base_path: String,
@ -173,11 +146,6 @@ impl Engine {
let asset_manager = AssetManager::new(&engine_settings)?; let asset_manager = AssetManager::new(&engine_settings)?;
let gui_handler = GuiHandler::new(create_info.gui_info, &context)?; let gui_handler = GuiHandler::new(create_info.gui_info, &context)?;
context
.render_core_mut()
.add_render_routine::<GuiHandlerRenderer>(10_000_000);
context.render_core_mut().add_render_routine::<Scene>(100);
world.resources.insert(context); world.resources.insert(context);
Scene::new( Scene::new(
@ -195,7 +163,6 @@ impl Engine {
direction_mapping.insert(Keycode::Down, GuiDirection::Down); direction_mapping.insert(Keycode::Down, GuiDirection::Down);
world.resources.insert(gui_handler); world.resources.insert(gui_handler);
world.resources.insert(GuiHandlerRenderer);
world.resources.insert(InputMap { direction_mapping }); world.resources.insert(InputMap { direction_mapping });
world.resources.insert(asset_manager); world.resources.insert(asset_manager);
world.resources.insert(Engine { world.resources.insert(Engine {
@ -203,7 +170,11 @@ impl Engine {
}); });
world.resources.insert(engine_settings); world.resources.insert(engine_settings);
world.add_system(1_000_000, Self::main_system::<T>); world.add_system(1, Self::start_frame);
world.add_system(u32::MAX, Self::end_frame);
world.add_system(100, Self::render_scene);
world.add_system(10_000_000, Self::render_gui);
Ok(()) Ok(())
} }
@ -246,20 +217,46 @@ impl Engine {
} }
impl Engine { impl Engine {
fn main_system<T: ResourceTrait + EventConsumer>(world: &mut World) -> Result<bool> { fn start_frame(world: &World, _commands: &mut Commands, context: &mut Context) -> Result<bool> {
let gui_handler = world.resources.get_mut_unchecked::<GuiHandler>(); context.start_frame(world)?;
let input_map = world.resources.get_unchecked::<InputMap>();
let context = world.resources.get_unchecked::<Context>();
let res = world.resources.get_mut_unchecked::<Context>().next_frame( Ok(true)
world, }
|world, consumer: &mut T, event| {
Self::event(world, context, gui_handler, input_map, consumer, event) fn end_frame(world: &World, _commands: &mut Commands, context: &mut Context) -> Result<bool> {
context.end_frame(world)?;
Ok(true)
}
fn render_scene(
world: &World,
_commands: &mut Commands,
context: &mut Context,
scene: &mut Scene,
) -> Result<bool> {
context.render(
|recorder: &mut CommandBufferRecorder<'_>,
images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>| {
scene.process(recorder, images, indices, world)
}, },
)?; )?;
gui_handler.process_callbacks(world)?; Ok(true)
}
Ok(res) fn render_gui(
_commands: &mut Commands,
context: &mut Context,
gui_handler: &mut GuiHandler,
) -> Result<bool> {
context.render(
|recorder: &mut CommandBufferRecorder<'_>,
_images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>| { gui_handler.process(recorder, indices) },
)?;
Ok(true)
} }
} }

View file

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
use anyhow::Result; use anyhow::Result;
use ecs::Resource; use ecs::{Resource, resources::Resource as ResourceTrait};
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug)] #[derive(Debug)]
@ -28,89 +28,118 @@ pub enum EngineEvent<'a> {
FileDrop(String), FileDrop(String),
} }
pub trait EventConsumer: Send + Sync + 'static {
fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()>;
}
#[derive(Resource)] #[derive(Resource)]
pub struct InputMap { pub struct InputMap {
pub direction_mapping: HashMap<Keycode, GuiDirection>, pub direction_mapping: HashMap<Keycode, GuiDirection>,
} }
pub trait EventSystem<Func, T> {
fn event_system(world_builder: &mut WorldBuilder, func: Func);
}
impl<Func, T> EventSystem<Func, T> for Engine
where
Func: Fn(&mut T, &mut Commands, EngineEvent<'_>) -> Result<()> + Send + Sync + 'static,
T: ResourceTrait,
{
fn event_system(world_builder: &mut WorldBuilder, func: Func) {
world_builder.add_system(
0,
|world: &World,
commands: &mut Commands,
consumer: &mut T,
gui_handler: &mut GuiHandler,
input_map: &mut InputMap,
context: &mut Context|
-> Result<bool> {
let res = context.events(world, |event| {
Self::event(commands, gui_handler, input_map, consumer, event, func)
})?;
gui_handler.process_callbacks(commands)?;
Ok(res)
},
)
}
}
impl Engine { impl Engine {
pub(crate) fn event<T: EventConsumer>( pub(crate) fn event<T>(
world: &mut World, commands: &mut Commands,
context: &Context,
gui_handler: &mut GuiHandler, gui_handler: &mut GuiHandler,
input: &InputMap, input: &InputMap,
consumer: &mut T, consumer: &mut T,
event: Event<'_>, event: Event<'_>,
func: Func,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
match event { match event {
Event::MouseMotion(x, y) => { Event::MouseMotion(x, y) => {
gui_handler.set_mouse_pos(x, y)?; gui_handler.set_mouse_pos(x, y)?;
consumer.event(world, EngineEvent::MouseMotion(x, y))?; consumer.event(commands, EngineEvent::MouseMotion(x, y))?;
} }
Event::MouseButtonDown(mouse_button) => { Event::MouseButtonDown(mouse_button) => {
if !gui_handler.mouse_down(mouse_button)? { if !gui_handler.mouse_down(mouse_button)? {
consumer.event(world, EngineEvent::MouseButtonDown(mouse_button))?; consumer.event(commands, EngineEvent::MouseButtonDown(mouse_button))?;
} }
} }
Event::MouseButtonUp(mouse_button) => { Event::MouseButtonUp(mouse_button) => {
if !gui_handler.mouse_up(mouse_button)? { if !gui_handler.mouse_up(mouse_button)? {
consumer.event(world, EngineEvent::MouseButtonUp(mouse_button))?; consumer.event(commands, EngineEvent::MouseButtonUp(mouse_button))?;
} }
} }
Event::MouseWheel(x, y, direction) => { Event::MouseWheel(x, y, direction) => {
consumer.event(world, EngineEvent::MouseWheel(x, y, direction))? consumer.event(commands, EngineEvent::MouseWheel(x, y, direction))?
} }
Event::KeyDown(keycode) => { Event::KeyDown(keycode) => {
Self::key_down_event(world, context, gui_handler, input, consumer, keycode)?; Self::key_down_event(commands, gui_handler, input, consumer, keycode)?;
} }
Event::KeyUp(keycode) => { Event::KeyUp(keycode) => {
Self::key_up_event(world, gui_handler, input, consumer, keycode)?; Self::key_up_event(commands, gui_handler, input, consumer, keycode)?;
} }
Event::TextInput(text) => { Event::TextInput(text) => {
Self::text_input(gui_handler, text)?; Self::text_input(gui_handler, text)?;
} }
Event::ControllerButtonDown(controller, button) => { Event::ControllerButtonDown(controller, button) => {
Self::button_down_event(world, gui_handler, consumer, controller, button)?; Self::button_down_event(commands, gui_handler, consumer, controller, button)?;
} }
Event::ControllerButtonUp(controller, button) => { Event::ControllerButtonUp(controller, button) => {
Self::button_up_event(world, consumer, controller, button)?; Self::button_up_event(commands, consumer, controller, button)?;
} }
Event::ControllerAxis(controller) => { Event::ControllerAxis(controller) => {
if !gui_handler.check_navigatable() { if !gui_handler.check_navigatable() {
Self::axis_event(world, consumer, &controller)? Self::axis_event(commands, consumer, &controller)?
} else { } else {
gui_handler.update_selection(controller.direction())?; gui_handler.update_selection(controller.direction())?;
} }
} }
Event::ControllerAdded(controller) => { Event::ControllerAdded(controller) => {
Self::controller_added(world, consumer, controller)? Self::controller_added(commands, consumer, controller)?
} }
Event::ControllerRemoved(controller) => { Event::ControllerRemoved(controller) => {
Self::controller_removed(world, consumer, controller)? Self::controller_removed(commands, consumer, controller)?
} }
Event::JoystickAxis(joystick, axis_index, value) => consumer.event( Event::JoystickAxis(joystick, axis_index, value) => consumer.event(
world, commands,
EngineEvent::JoystickAxis(joystick, axis_index, value), EngineEvent::JoystickAxis(joystick, axis_index, value),
)?, )?,
Event::JoystickButtonDown(joystick) => { Event::JoystickButtonDown(joystick) => {
consumer.event(world, EngineEvent::JoystickButtonDown(joystick))? consumer.event(commands, EngineEvent::JoystickButtonDown(joystick))?
} }
Event::JoystickButtonUp(joystick) => { Event::JoystickButtonUp(joystick) => {
consumer.event(world, EngineEvent::JoystickButtonUp(joystick))? consumer.event(commands, EngineEvent::JoystickButtonUp(joystick))?
} }
Event::JoystickAdded(joystick) => { Event::JoystickAdded(joystick) => {
consumer.event(world, EngineEvent::JoystickAdded(joystick))? consumer.event(commands, EngineEvent::JoystickAdded(joystick))?
} }
Event::JoystickRemoved(joystick) => { Event::JoystickRemoved(joystick) => {
consumer.event(world, EngineEvent::JoystickRemoved(joystick))? consumer.event(commands, EngineEvent::JoystickRemoved(joystick))?
} }
Event::FileDrop(filename) => consumer.event(world, EngineEvent::FileDrop(filename))?, Event::FileDrop(filename) => {
consumer.event(commands, EngineEvent::FileDrop(filename))?
}
} }
Ok(()) Ok(())
@ -120,29 +149,29 @@ impl Engine {
impl Engine { impl Engine {
#[inline] #[inline]
fn controller_added<T: EventConsumer>( fn controller_added<T: EventConsumer>(
world: &mut World, commands: &mut Commands,
consumer: &mut T, consumer: &mut T,
controller: &Controller, controller: &Controller,
) -> Result<()> { ) -> Result<()> {
consumer.event(world, EngineEvent::ControllerAdded(controller))?; consumer.event(commands, EngineEvent::ControllerAdded(controller))?;
Ok(()) Ok(())
} }
#[inline] #[inline]
fn controller_removed<T: EventConsumer>( fn controller_removed<T: EventConsumer>(
world: &mut World, commands: &mut Commands,
consumer: &mut T, consumer: &mut T,
controller: &Controller, controller: &Controller,
) -> Result<()> { ) -> Result<()> {
consumer.event(world, EngineEvent::ControllerRemoved(controller))?; consumer.event(commands, EngineEvent::ControllerRemoved(controller))?;
Ok(()) Ok(())
} }
#[inline] #[inline]
fn key_up_event<T: EventConsumer>( fn key_up_event<T: EventConsumer>(
world: &mut World, commands: &mut Commands,
gui_handler: &mut GuiHandler, gui_handler: &mut GuiHandler,
input: &InputMap, input: &InputMap,
consumer: &mut T, consumer: &mut T,
@ -154,15 +183,14 @@ impl Engine {
return Ok(()); return Ok(());
} }
consumer.event(world, EngineEvent::KeyUp(keycode))?; consumer.event(commands, EngineEvent::KeyUp(keycode))?;
Ok(()) Ok(())
} }
#[inline] #[inline]
fn key_down_event<T: EventConsumer>( fn key_down_event<T: EventConsumer>(
world: &mut World, commands: &mut Commands,
context: &Context,
gui_handler: &mut GuiHandler, gui_handler: &mut GuiHandler,
input: &InputMap, input: &InputMap,
consumer: &mut T, consumer: &mut T,
@ -186,50 +214,49 @@ impl Engine {
} }
} }
Keycode::Escape => { Keycode::Escape => {
if gui_handler.decline_topgui(world)? { if gui_handler.decline_topgui(commands)? {
return Ok(()); return Ok(());
} }
} }
Keycode::V => {
if let Some(writeable) = gui_handler.writeable() {
if let Some(content) = context.window_config().clipboard_content()? {
writeable.set_text(gui_handler, content)?;
}
}
}
_ => (), _ => (),
} }
consumer.event(world, EngineEvent::KeyDown(keycode))?; consumer.event(commands, EngineEvent::KeyDown(keycode))?;
Ok(()) Ok(())
} }
#[inline] #[inline]
fn button_up_event<T: EventConsumer>( fn button_up_event<T: EventConsumer>(
world: &mut World, commands: &mut Commands,
consumer: &mut T, consumer: &mut T,
controller: &Controller, controller: &Controller,
button: ControllerButton, button: ControllerButton,
) -> Result<()> { ) -> Result<()> {
consumer.event(world, EngineEvent::ControllerButtonUp(controller, button))?; consumer.event(
commands,
EngineEvent::ControllerButtonUp(controller, button),
)?;
Ok(()) Ok(())
} }
#[inline] #[inline]
fn button_down_event<T: EventConsumer>( fn button_down_event<T: EventConsumer>(
world: &mut World, commands: &mut Commands,
gui_handler: &mut GuiHandler, gui_handler: &mut GuiHandler,
consumer: &mut T, consumer: &mut T,
controller: &Controller, controller: &Controller,
button: ControllerButton, button: ControllerButton,
) -> Result<()> { ) -> Result<()> {
if gui_handler.check_navigatable() { if gui_handler.check_navigatable() {
Self::check_button_down(world, gui_handler, consumer, controller, button)?; Self::check_button_down(commands, gui_handler, consumer, controller, button)?;
} else { } else {
consumer.event(world, EngineEvent::ControllerButtonDown(controller, button))?; consumer.event(
commands,
EngineEvent::ControllerButtonDown(controller, button),
)?;
} }
Ok(()) Ok(())
@ -237,12 +264,12 @@ impl Engine {
#[inline] #[inline]
fn axis_event<T: EventConsumer>( fn axis_event<T: EventConsumer>(
world: &mut World, commands: &mut Commands,
consumer: &mut T, consumer: &mut T,
controller: &Controller, controller: &Controller,
) -> Result<()> { ) -> Result<()> {
consumer.event( consumer.event(
world, commands,
EngineEvent::ControllerAxis(controller, controller.controller_axis()), EngineEvent::ControllerAxis(controller, controller.controller_axis()),
)?; )?;
@ -251,7 +278,7 @@ impl Engine {
#[inline] #[inline]
fn check_button_down<T: EventConsumer>( fn check_button_down<T: EventConsumer>(
world: &mut World, commands: &mut Commands,
gui_handler: &mut GuiHandler, gui_handler: &mut GuiHandler,
consumer: &mut T, consumer: &mut T,
controller: &Controller, controller: &Controller,
@ -265,31 +292,31 @@ impl Engine {
} }
ControllerButton::B => { ControllerButton::B => {
if gui_handler.decline_topgui(world)? { if gui_handler.decline_topgui(commands)? {
return Ok(()); return Ok(());
} }
} }
ControllerButton::RightButton => { ControllerButton::RightButton => {
if gui_handler.next_tab_topgui(world, false)? { if gui_handler.next_tab_topgui(commands, false)? {
return Ok(()); return Ok(());
} }
} }
ControllerButton::LeftButton => { ControllerButton::LeftButton => {
if gui_handler.previous_tab_topgui(world, false)? { if gui_handler.previous_tab_topgui(commands, false)? {
return Ok(()); return Ok(());
} }
} }
ControllerButton::RightTrigger => { ControllerButton::RightTrigger => {
if gui_handler.next_tab_topgui(world, true)? { if gui_handler.next_tab_topgui(commands, true)? {
return Ok(()); return Ok(());
} }
} }
ControllerButton::LeftTrigger => { ControllerButton::LeftTrigger => {
if gui_handler.previous_tab_topgui(world, true)? { if gui_handler.previous_tab_topgui(commands, true)? {
return Ok(()); return Ok(());
} }
} }
@ -333,8 +360,11 @@ impl Engine {
_ => (), _ => (),
} }
if !gui_handler.accept_custom_selection(world, button)? { if !gui_handler.accept_custom_selection(commands, button)? {
consumer.event(world, EngineEvent::ControllerButtonDown(controller, button))?; consumer.event(
commands,
EngineEvent::ControllerButtonDown(controller, button),
)?;
} }
Ok(()) Ok(())

View file

@ -10,7 +10,7 @@ pub use crate::engine::{
asset_handler::{AssetHandler, AssetLoader}, asset_handler::{AssetHandler, AssetLoader},
engine::*, engine::*,
engine_create_info::EngineCreateInfo, engine_create_info::EngineCreateInfo,
engine_event_handling::{EngineEvent, EventConsumer}, engine_event_handling::{EngineEvent, EventConsumer, EventSystem},
engine_settings::*, engine_settings::*,
}; };

View file

@ -383,7 +383,7 @@ impl TScene for Scene {
buffer_recorder: &mut CommandBufferRecorder<'_>, buffer_recorder: &mut CommandBufferRecorder<'_>,
images: &TargetMode<Vec<Arc<Image>>>, images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>, indices: &TargetMode<usize>,
world: &mut World, world: &World,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
self.frame_time = { self.frame_time = {
let now = world.now(); let now = world.now();
@ -484,7 +484,7 @@ impl TScene for Scene {
window_width: f32, window_width: f32,
window_height: f32, window_height: f32,
images: &TargetMode<Vec<Arc<Image>>>, images: &TargetMode<Vec<Arc<Image>>>,
_world: &mut World, _world: &World,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
self.screen_width = window_width; self.screen_width = window_width;
self.screen_height = window_height; self.screen_height = window_height;

View file

@ -109,11 +109,14 @@ impl InputSettings {
pub struct Game; pub struct Game;
impl Game { impl Game {
pub fn update(&mut self, world: &mut World) -> Result<()> { pub fn update(
&mut self,
commands: &mut Commands,
scene: &mut Scene,
camera_control: &mut FreeCameraControl,
) -> Result<()> {
if FREE_CAMERA_CONTROL { if FREE_CAMERA_CONTROL {
let now = world.now(); let now = commands.now();
let (scene, camera_control): (&mut Scene, &mut FreeCameraControl) =
world.resources.get_mut()?;
camera_control.update(now, scene.view_mut())?; camera_control.update(now, scene.view_mut())?;
} }
@ -121,7 +124,7 @@ impl Game {
Ok(()) Ok(())
} }
pub fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> { pub fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> {
if let Some(event) = Self::motion_concepts(world, event)? { if let Some(event) = Self::motion_concepts(world, event)? {
match event { match event {
EngineEvent::JoystickAdded(joystick) => { EngineEvent::JoystickAdded(joystick) => {

View file

@ -14,12 +14,15 @@ pub enum GameState {
} }
impl GameState { impl GameState {
pub fn update(world: &mut World) -> Result<bool> { pub fn update(
let me = world.resources.get_mut_unchecked::<Self>(); commands: &mut Commands,
game_state: &mut GameState,
match me { scene: &mut Scene,
GameState::Startup => *me = GameState::Game(Game), camera_control: &mut FreeCameraControl,
GameState::Game(game) => game.update(world)?, ) -> Result<bool> {
match game_state {
GameState::Startup => *game_state = GameState::Game(Game),
GameState::Game(game) => game.update(commands, scene, camera_control)?,
} }
Ok(true) Ok(true)
@ -27,10 +30,10 @@ impl GameState {
} }
impl EventConsumer for GameState { impl EventConsumer for GameState {
fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> { fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> {
match self { match self {
GameState::Startup => (), GameState::Startup => (),
GameState::Game(game) => game.event(world, event)?, GameState::Game(game) => game.event(commands, event)?,
} }
Ok(()) Ok(())

View file

@ -3,14 +3,32 @@ use anyhow::Result;
use ecs::*; use ecs::*;
use engine::prelude::*; use engine::prelude::*;
struct CameraControlStart;
struct CameraControlEnd;
struct CameraControlMove {
x: u32,
y: u32,
}
fn main() -> Result<()> { fn main() -> Result<()> {
let mut world_builder = World::builder(); let mut world_builder = World::builder();
Engine::new::<GameState>(EngineCreateInfo::default(), &mut world_builder)?; Engine::new::<GameState>(EngineCreateInfo::default(), &mut world_builder)?;
Engine::event_system(&mut world_builder);
world_builder.add_system(10, GameState::update); world_builder.add_system(10, GameState::update);
world_builder.resources.insert(GameState::default()); world_builder.resources.insert(GameState::default());
world_builder.events.register_event::<CameraControlStart>();
world_builder.events.register_event::<CameraControlEnd>();
world_builder.events.register_event::<CameraControlMove>();
world_builder.events.add_reader(Game::enable_camera_control);
world_builder
.events
.add_reader(Game::disable_camera_control);
world_builder.events.add_reader(Game::update_mouse);
let scene: &mut Scene = world_builder.resources.get_mut()?; let scene: &mut Scene = world_builder.resources.get_mut()?;
let view = scene.view_mut(); let view = scene.view_mut();
let camera_control = FreeCameraControl::new(view)?; let camera_control = FreeCameraControl::new(view)?;
@ -28,12 +46,10 @@ enum GameState {
} }
impl GameState { impl GameState {
fn update(world: &mut World) -> Result<bool> { fn update(commands: &mut Commands, game_state: &mut GameState) -> Result<bool> {
let me = world.resources.get_mut_unchecked::<Self>(); match game_state {
GameState::Startup => *game_state = GameState::Game(Game),
match me { GameState::Game(game) => game.update(commands)?,
GameState::Startup => *me = GameState::Game(Game),
GameState::Game(game) => game.update(world)?,
} }
Ok(true) Ok(true)
@ -41,10 +57,10 @@ impl GameState {
} }
impl EventConsumer for GameState { impl EventConsumer for GameState {
fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> { fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> {
match self { match self {
GameState::Startup => (), GameState::Startup => (),
GameState::Game(game) => game.event(world, event)?, GameState::Game(game) => game.event(commands, event)?,
} }
Ok(()) Ok(())
@ -54,26 +70,48 @@ impl EventConsumer for GameState {
struct Game; struct Game;
impl Game { impl Game {
fn update(&mut self, _world: &mut World) -> Result<()> { fn enable_camera_control(
_: &CameraControlStart,
_commands: &mut Commands,
camera_control: &mut FreeCameraControl,
) -> Result<()> {
camera_control.mouse_down();
Ok(()) Ok(())
} }
fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> { fn disable_camera_control(
_: &CameraControlEnd,
_commands: &mut Commands,
camera_control: &mut FreeCameraControl,
) -> Result<()> {
camera_control.mouse_release();
Ok(())
}
fn update_mouse(
camera_move: &CameraControlMove,
_commands: &mut Commands,
camera_control: &mut FreeCameraControl,
scene: &mut Scene,
) -> Result<()> {
camera_control.mouse_move(camera_move.x, camera_move.y, scene.view_mut())?;
Ok(())
}
fn update(&mut self, _commands: &mut Commands) -> Result<()> {
Ok(())
}
fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> {
match event { match event {
EngineEvent::MouseButtonDown(MouseButton::Left) => { EngineEvent::MouseButtonDown(MouseButton::Left) => {
let camera_control: &mut FreeCameraControl = world.resources.get_mut()?; commands.write_event(CameraControlStart)
camera_control.mouse_down();
}
EngineEvent::MouseButtonUp(MouseButton::Left) => {
let camera_control: &mut FreeCameraControl = world.resources.get_mut()?;
camera_control.mouse_release();
}
EngineEvent::MouseMotion(x, y) => {
let (scene, camera_control): (&mut Scene, &mut FreeCameraControl) =
world.resources.get_mut()?;
camera_control.mouse_move(x, y, scene.view_mut())?;
} }
EngineEvent::MouseButtonUp(MouseButton::Left) => commands.write_event(CameraControlEnd),
EngineEvent::MouseMotion(x, y) => commands.write_event(CameraControlMove { x, y }),
_ => (), _ => (),
} }

View file

@ -1,5 +1,5 @@
use context::prelude::*; use context::prelude::*;
use ecs::World; use ecs::Commands;
use std::{ use std::{
sync::{ sync::{
@ -26,13 +26,18 @@ where
T: Send + Sync + 'static, T: Send + Sync + 'static,
G: TopLevelGui + TopGui + Send + Sync + 'static, G: TopLevelGui + TopGui + Send + Sync + 'static,
{ {
pub fn load<R, L>(world: &mut World, gui: Arc<G>, loader: L) -> Result<Self> pub fn load<R, L>(
commands: &mut Commands,
gui_handler: &mut GuiHandler,
gui: Arc<G>,
loader: L,
) -> Result<Self>
where where
R: Fn(T) -> Result<()> + Send + Sync + 'static, R: Fn(T) -> Result<()> + Send + Sync + 'static,
T: Send + Sync + 'static, T: Send + Sync + 'static,
L: FnOnce() -> T + Send + Sync + 'static, L: FnOnce() -> T + Send + Sync + 'static,
{ {
gui.enable(world)?; gui.enable(commands, gui_handler)?;
let (sender, receiver) = channel(); let (sender, receiver) = channel();
@ -61,8 +66,12 @@ where
} }
} }
pub fn take_result(mut self, world: &mut World) -> Result<T> { pub fn take_result(
self.gui.disable(world)?; mut self,
commands: &mut Commands,
gui_handler: &mut GuiHandler,
) -> Result<T> {
self.gui.disable(commands, gui_handler)?;
self.result self.result
.take() .take()
.ok_or(anyhow!("missing loading screen payload!")) .ok_or(anyhow!("missing loading screen payload!"))

View file

@ -1,12 +1,10 @@
use crate::Result; use crate::Result;
use crate::prelude::*;
use cgmath::{Matrix4, SquareMatrix}; use cgmath::{Matrix4, SquareMatrix};
use ecs::World; use ecs::World;
use ui::prelude::*; use ui::prelude::*;
use vulkan_rs::prelude::*; use vulkan_rs::prelude::*;
use std::any::TypeId;
use std::ops::Deref; use std::ops::Deref;
use std::sync::{ use std::sync::{
Arc, Mutex, RwLock, Arc, Mutex, RwLock,
@ -49,52 +47,6 @@ impl Default for VRTransformations {
} }
} }
struct SceneHandle {
type_id: TypeId,
priority: u32,
render: Box<
dyn FnMut(
&mut CommandBufferRecorder<'_>,
&TargetMode<Vec<Arc<Image>>>,
&TargetMode<usize>,
&mut World,
) -> Result<()>
+ Send
+ Sync
+ 'static,
>,
resize: Box<
dyn FnMut(f32, f32, &TargetMode<Vec<Arc<Image>>>, &mut World) -> Result<()>
+ Send
+ Sync
+ 'static,
>,
}
impl SceneHandle {
fn new<T: TScene>(priority: u32) -> Self {
Self {
type_id: TypeId::of::<T>(),
priority,
render: Box::new(|recorder, images, indices, world| {
world
.resources
.get_mut_unchecked::<T>()
.process(recorder, images, indices, world)
}),
resize: Box::new(|width, height, images, world| {
world
.resources
.get_mut_unchecked::<T>()
.resize(width, height, images, world)
}),
}
}
}
pub struct RenderBackend { pub struct RenderBackend {
device: Arc<Device>, device: Arc<Device>,
queue: Arc<Mutex<Queue>>, queue: Arc<Mutex<Queue>>,
@ -106,10 +58,12 @@ pub struct RenderBackend {
clear_color: RwLock<VkClearColorValue>, clear_color: RwLock<VkClearColorValue>,
command_buffer: Arc<CommandBuffer>, command_buffer: Arc<CommandBuffer>,
buffer_recorder: Option<CommandBufferRecorder<'static>>,
render_routines: Vec<SceneHandle>,
} }
unsafe impl Send for RenderBackend {}
unsafe impl Sync for RenderBackend {}
impl RenderBackend { impl RenderBackend {
pub fn new( pub fn new(
device: &Arc<Device>, device: &Arc<Device>,
@ -137,8 +91,7 @@ impl RenderBackend {
clear_color: RwLock::new(VkClearColorValue::float32([0.0, 0.0, 0.0, 1.0])), clear_color: RwLock::new(VkClearColorValue::float32([0.0, 0.0, 0.0, 1.0])),
command_buffer, command_buffer,
buffer_recorder: None,
render_routines: Vec::new(),
}) })
} }
@ -160,11 +113,7 @@ impl RenderBackend {
*self.clear_color.write().unwrap() = VkClearColorValue::float32(clear_color); *self.clear_color.write().unwrap() = VkClearColorValue::float32(clear_color);
} }
pub fn render( pub fn begin_frame(&mut self, image_indices: TargetMode<usize>) -> Result<()> {
&mut self,
world: &mut World,
image_indices: TargetMode<usize>,
) -> Result<&Arc<CommandBuffer>> {
// begin main command buffer // begin main command buffer
let mut buffer_recorder = self.command_buffer.begin(VkCommandBufferBeginInfo::new( let mut buffer_recorder = self.command_buffer.begin(VkCommandBufferBeginInfo::new(
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
@ -212,27 +161,39 @@ impl RenderBackend {
} }
} }
// make a call to the connected scenes self.buffer_recorder = Some(unsafe { std::mem::transmute(buffer_recorder) });
self.render_routines
.iter_mut() Ok(())
.try_for_each(|scene_handle| { }
(scene_handle.render)(
&mut buffer_recorder, pub fn render<F>(&mut self, image_indices: TargetMode<usize>, render: F) -> Result<()>
where
F: FnOnce(
&mut CommandBufferRecorder<'_>,
&TargetMode<Vec<Arc<Image>>>,
&TargetMode<usize>,
) -> Result<()>,
{
render(
self.buffer_recorder.as_mut().unwrap(),
&*self.swapchain_images.lock().unwrap(), &*self.swapchain_images.lock().unwrap(),
&image_indices, &image_indices,
world, )?;
)
})?;
Ok(&self.command_buffer) Ok(())
}
pub fn end_frame(&mut self) -> &Arc<CommandBuffer> {
self.buffer_recorder = None;
&self.command_buffer
} }
pub fn resize( pub fn resize(
&mut self, &mut self,
world: &mut World, _world: &World,
images: TargetMode<Vec<Arc<Image>>>, images: TargetMode<Vec<Arc<Image>>>,
width: u32, _width: u32,
height: u32, _height: u32,
) -> Result<()> { ) -> Result<()> {
self.image_count.store( self.image_count.store(
match &images { match &images {
@ -245,32 +206,16 @@ impl RenderBackend {
SeqCst, SeqCst,
); );
self.render_routines // TODO
.iter_mut() // self.render_routines
.try_for_each(|scene_handle| { // .iter_mut()
(scene_handle.resize)(width as f32, height as f32, &images, world) // .try_for_each(|scene_handle| {
})?; // (scene_handle.resize)(width as f32, height as f32, &images, world)
// })?;
Ok(()) Ok(())
} }
/// lower priority means it is more important
pub fn add_render_routine<T: TScene>(&mut self, priority: u32) {
self.render_routines.push(SceneHandle::new::<T>(priority));
self.render_routines
.sort_by_key(|scene_handle| scene_handle.priority);
}
pub fn remove_render_routine<T: TScene>(&mut self) {
if let Some(index) = self
.render_routines
.iter()
.position(|scene_handle| scene_handle.type_id == TypeId::of::<T>())
{
self.render_routines.remove(index as usize);
}
}
// getter // getter
pub fn image_count(&self) -> usize { pub fn image_count(&self) -> usize {
self.image_count.load(SeqCst) self.image_count.load(SeqCst)

View file

@ -17,7 +17,7 @@ pub trait TScene: Resource + Send + Sync + 'static {
buffer_recorder: &mut CommandBufferRecorder<'_>, buffer_recorder: &mut CommandBufferRecorder<'_>,
images: &TargetMode<Vec<Arc<Image>>>, images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>, indices: &TargetMode<usize>,
world: &mut World, world: &World,
) -> Result<()>; ) -> Result<()>;
fn resize( fn resize(
@ -25,7 +25,7 @@ pub trait TScene: Resource + Send + Sync + 'static {
window_width: f32, window_width: f32,
window_height: f32, window_height: f32,
images: &TargetMode<Vec<Arc<Image>>>, images: &TargetMode<Vec<Arc<Image>>>,
world: &mut World, world: &World,
) -> Result<()>; ) -> Result<()>;
} }
@ -37,15 +37,35 @@ pub enum RenderCore {
} }
impl RenderCore { impl RenderCore {
pub fn next_frame(&mut self, world: &mut World) -> Result<bool> { pub fn begin_frame(&mut self, world: &World) -> Result<()> {
match self { match self {
RenderCore::Wsi(rc) => rc.next_frame(world), RenderCore::Wsi(rc) => rc.start_frame(world),
RenderCore::OpenVR(rc) => rc.next_frame(world), _ => todo!(),
RenderCore::OpenXR(rc) => rc.next_frame(world),
} }
} }
pub fn resize(&mut self, world: &mut World, w: u32, h: u32) -> Result<()> { pub fn render<F>(&mut self, render: F) -> Result<()>
where
F: FnOnce(
&mut CommandBufferRecorder<'_>,
&TargetMode<Vec<Arc<Image>>>,
&TargetMode<usize>,
) -> Result<()>,
{
match self {
RenderCore::Wsi(rc) => rc.render(render),
_ => todo!(),
}
}
pub fn end_frame(&mut self, world: &World) -> Result<()> {
match self {
RenderCore::Wsi(rc) => rc.end_frame(world),
_ => todo!(),
}
}
pub fn resize(&mut self, world: &World, w: u32, h: u32) -> Result<()> {
match self { match self {
RenderCore::Wsi(rc) => rc.resize(world, w, h), RenderCore::Wsi(rc) => rc.resize(world, w, h),
RenderCore::OpenVR(rc) => rc.resize(world, w, h), RenderCore::OpenVR(rc) => rc.resize(world, w, h),
@ -65,23 +85,6 @@ impl RenderCore {
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
} }
/// lower priority means it is more important
pub fn add_render_routine<T: TScene>(&mut self, priority: u32) {
match self {
RenderCore::Wsi(rc) => rc.add_render_routine::<T>(priority),
RenderCore::OpenVR(rc) => rc.add_render_routine::<T>(priority),
RenderCore::OpenXR(rc) => rc.add_render_routine::<T>(priority),
}
}
pub fn remove_render_routine<T: TScene>(&mut self) {
match self {
RenderCore::Wsi(rc) => rc.remove_render_routine::<T>(),
RenderCore::OpenVR(rc) => rc.remove_render_routine::<T>(),
RenderCore::OpenXR(rc) => rc.remove_render_routine::<T>(),
}
}
pub fn set_clear_color(&self, color: [f32; 4]) { pub fn set_clear_color(&self, color: [f32; 4]) {
match self { match self {
RenderCore::Wsi(rc) => rc.set_clear_color(color), RenderCore::Wsi(rc) => rc.set_clear_color(color),

View file

@ -79,11 +79,11 @@ pub mod openvrrendercore {
unimplemented!() unimplemented!()
} }
pub fn resize(&mut self, _: &mut World, _: u32, _: u32) -> Result<()> { pub fn resize(&mut self, _: &World, _: u32, _: u32) -> Result<()> {
unimplemented!() unimplemented!()
} }
pub fn next_frame(&mut self, _: &mut World) -> Result<bool> { pub fn next_frame(&mut self, _: &World) -> Result<bool> {
unimplemented!() unimplemented!()
} }

View file

@ -103,7 +103,7 @@ impl VulkanWindowRenderCore {
Ok((window_render_core, TargetMode::Mono(()))) Ok((window_render_core, TargetMode::Mono(())))
} }
fn aquire_next_image_index(&mut self, world: &mut World) -> Result<()> { fn aquire_next_image_index(&mut self, world: &World) -> Result<()> {
// there was a bug that a windows never reacted after it was minimized // there was a bug that a windows never reacted after it was minimized
// with this timeout, the window has 250ms delay // with this timeout, the window has 250ms delay
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@ -145,7 +145,7 @@ impl VulkanWindowRenderCore {
self.format self.format
} }
pub fn resize(&mut self, world: &mut World, w: u32, h: u32) -> Result<()> { pub fn resize(&mut self, world: &World, w: u32, h: u32) -> Result<()> {
self.swapchain.recreate((w, h))?; self.swapchain.recreate((w, h))?;
let swapchain_images = self.swapchain.wrap_images( let swapchain_images = self.swapchain.wrap_images(
@ -164,14 +164,33 @@ impl VulkanWindowRenderCore {
Ok(()) Ok(())
} }
pub fn next_frame(&mut self, world: &mut World) -> Result<bool> { pub fn start_frame(&mut self, world: &World) -> Result<()> {
self.aquire_next_image_index(world)?; self.aquire_next_image_index(world)?;
self.render_backend
.begin_frame(TargetMode::Mono(self.current_image_index.load(SeqCst)))?;
let command_buffer = self.render_backend.render( Ok(())
world, }
pub fn render<F>(&mut self, render: F) -> Result<()>
where
F: FnOnce(
&mut CommandBufferRecorder<'_>,
&TargetMode<Vec<Arc<Image>>>,
&TargetMode<usize>,
) -> Result<()>,
{
self.render_backend.render(
TargetMode::Mono(self.current_image_index.load(SeqCst)), TargetMode::Mono(self.current_image_index.load(SeqCst)),
render,
)?; )?;
Ok(())
}
pub fn end_frame(&mut self, world: &World) -> Result<()> {
let command_buffer = self.render_backend.end_frame();
let submits = &[SubmitInfo::default() let submits = &[SubmitInfo::default()
.add_wait_semaphore( .add_wait_semaphore(
&*self.image_available_sem.read().unwrap(), &*self.image_available_sem.read().unwrap(),
@ -194,7 +213,7 @@ impl VulkanWindowRenderCore {
let (w, h) = self.wsi.window_size(); let (w, h) = self.wsi.window_size();
self.resize(world, w, h)?; self.resize(world, w, h)?;
self.render_fence.reset(); self.render_fence.reset();
return Ok(true); return Ok(());
} }
// make sure command_buffer is ready // make sure command_buffer is ready
@ -205,22 +224,13 @@ impl VulkanWindowRenderCore {
)?; )?;
self.render_fence.reset(); self.render_fence.reset();
Ok(true) Ok(())
} }
pub fn set_clear_color(&self, color: [f32; 4]) { pub fn set_clear_color(&self, color: [f32; 4]) {
self.render_backend.set_clear_color(color); self.render_backend.set_clear_color(color);
} }
// post process handling
pub fn add_render_routine<T: TScene>(&mut self, priority: u32) {
self.render_backend.add_render_routine::<T>(priority);
}
pub fn remove_render_routine<T: TScene>(&mut self) {
self.render_backend.remove_render_routine::<T>();
}
// getter // getter
pub fn image_count(&self) -> usize { pub fn image_count(&self) -> usize {
self.render_backend.image_count() self.render_backend.image_count()

View file

@ -77,11 +77,11 @@ pub mod openxrrendercore {
unimplemented!() unimplemented!()
} }
pub fn resize(&mut self, _: &mut World, _: u32, _: u32) -> Result<()> { pub fn resize(&mut self, _: &World, _: u32, _: u32) -> Result<()> {
unimplemented!() unimplemented!()
} }
pub fn next_frame(&mut self, _: &mut World) -> Result<bool> { pub fn next_frame(&mut self, _: &World) -> Result<bool> {
unimplemented!() unimplemented!()
} }

View file

@ -55,7 +55,6 @@ impl SkyBox {
.sample_count; .sample_count;
let context = world.resources.get_mut_unchecked::<Context>(); let context = world.resources.get_mut_unchecked::<Context>();
context.render_core_mut().add_render_routine::<Self>(10);
let images = images.into(); let images = images.into();
let cube_map = Image::cube_map([ let cube_map = Image::cube_map([
@ -166,6 +165,7 @@ impl SkyBox {
descriptor_set, descriptor_set,
}; };
world.resources.insert(me); world.resources.insert(me);
world.add_system(10, Self::render_sky_box);
Ok(()) Ok(())
} }
@ -178,6 +178,23 @@ impl SkyBox {
self.enabled = false; self.enabled = false;
} }
fn render_sky_box(
world: &World,
_commands: &mut Commands,
context: &mut Context,
sky_box: &mut SkyBox,
) -> Result<bool> {
context.render(
|recorder: &mut CommandBufferRecorder<'_>,
images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>| {
sky_box.process(recorder, images, indices, world)
},
)?;
Ok(true)
}
fn create_render_target( fn create_render_target(
context: &Context, context: &Context,
images: &TargetMode<Vec<Arc<Image>>>, images: &TargetMode<Vec<Arc<Image>>>,
@ -258,7 +275,7 @@ impl TScene for SkyBox {
buffer_recorder: &mut CommandBufferRecorder<'_>, buffer_recorder: &mut CommandBufferRecorder<'_>,
_images: &TargetMode<Vec<Arc<Image>>>, _images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>, indices: &TargetMode<usize>,
_world: &mut World, _world: &World,
) -> Result<()> { ) -> Result<()> {
if !self.enabled { if !self.enabled {
return Ok(()); return Ok(());
@ -290,7 +307,7 @@ impl TScene for SkyBox {
_window_width: f32, _window_width: f32,
_window_height: f32, _window_height: f32,
images: &TargetMode<Vec<Arc<Image>>>, images: &TargetMode<Vec<Arc<Image>>>,
world: &mut World, world: &World,
) -> Result<()> { ) -> Result<()> {
let sample_count = world let sample_count = world
.resources .resources