Fix circular dependencies in workspace

This commit is contained in:
Tony Klink 2024-04-02 19:12:59 -06:00
parent 960e2f8a37
commit 173cfe2acf
Signed by: klink
GPG key ID: 85175567C4D19231
11 changed files with 148 additions and 72 deletions

View file

@ -1,315 +0,0 @@
#![warn(dead_code)]
use crate::{
debug_gui::DebugGuiStack,
events::Events,
module::{Module, ModulesStack, RenderModule as ThreadLocalModule, RenderModulesStack},
};
use anyhow::Result;
use flax::{component, Schedule, World};
use vulkano::device::DeviceFeatures;
use vulkano_util::{
context::{VulkanoConfig, VulkanoContext},
window::VulkanoWindows,
};
use winit::{
event::{Event, WindowEvent},
window::WindowId,
};
component! {
window_id: WindowId,
resources,
}
#[allow(dead_code)]
pub struct App {
name: String,
modules: ModulesStack,
thread_local_modules: RenderModulesStack,
world: World,
schedule: Schedule,
events: Events,
rx: flume::Receiver<AppEvent>,
running: bool,
event_cleanup_time: std::time::Duration,
vk_context: VulkanoContext,
vk_windows: VulkanoWindows,
debug_gui_stack: DebugGuiStack,
}
impl App {
pub fn new() -> Self {
let mut events = Events::new();
let (tx, rx) = flume::unbounded();
events.subscribe_custom(tx);
let schedule = Schedule::builder().build();
let vk_config = VulkanoConfig {
device_features: DeviceFeatures {
dynamic_rendering: true,
..Default::default()
},
..Default::default()
};
let vk_context = VulkanoContext::new(vk_config);
let vk_windows = VulkanoWindows::default();
Self {
name: "Khors".into(),
modules: ModulesStack::new(),
thread_local_modules: RenderModulesStack::new(),
world: World::new(),
schedule,
events,
rx,
running: false,
event_cleanup_time: std::time::Duration::from_secs(60),
vk_context,
vk_windows,
debug_gui_stack: DebugGuiStack::default(),
}
}
pub fn run(&mut self) -> Result<()> {
self.running = true;
self.schedule.execute_par(&mut self.world).unwrap();
let vk_context = &mut self.vk_context;
let vk_windows = &mut self.vk_windows;
let world = &mut self.world;
let events = &mut self.events;
let frame_time = std::time::Duration::from_millis(16);
let gui_stack = &mut self.debug_gui_stack;
for module in self.modules.iter_mut() {
module.on_update(world, events, frame_time)?;
}
for module in self.thread_local_modules.iter_mut() {
module.on_update(gui_stack, vk_context, vk_windows, world, events, frame_time)?;
}
self.handle_events();
Ok(())
}
pub fn create_window<T>(&mut self, event_loop: &winit::event_loop::EventLoopWindowTarget<T>)
where
T: Clone + Send + Sync,
{
let vk_window_id = self.vk_windows.create_window(
event_loop,
&self.vk_context,
&vulkano_util::window::WindowDescriptor {
title: self.name.clone(),
present_mode: vulkano::swapchain::PresentMode::Mailbox,
..Default::default()
},
|_| {},
);
let renderer = self.vk_windows.get_renderer(vk_window_id).unwrap();
self.world
.set(resources(), window_id(), vk_window_id)
.unwrap();
self.debug_gui_stack
.add_gui(vk_window_id, event_loop, renderer, true, false);
}
pub fn process_event_loop<T>(
&mut self,
event: winit::event::Event<T>,
_elwt: &winit::event_loop::EventLoopWindowTarget<T>,
) -> Result<bool>
where
T: Clone + Send + Sync,
{
match &event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
return Ok(true);
}
Event::WindowEvent {
event: WindowEvent::Focused(_),
..
} => self.events().send(event.clone()),
Event::WindowEvent {
event: WindowEvent::Resized(..) | WindowEvent::ScaleFactorChanged { .. },
window_id,
} => self
.vk_windows
.get_renderer_mut(*window_id)
.unwrap()
.resize(),
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
window_id,
} => 'redraw: {
// Tasks for redrawing:
// 1. Update state based on events
// 2. Compute & Render
// 3. Reset input state
// 4. Update time & title
// The rendering part goes here:
match self
.vk_windows
.get_renderer(*window_id)
.unwrap()
.window_size()
{
[w, h] => {
// Skip this frame when minimized.
if w == 0.0 || h == 0.0 {
break 'redraw;
}
}
}
self.run()?;
}
Event::WindowEvent { window_id, event } => {
let window = self.vk_windows.get_window(*window_id).unwrap();
let gui = self.debug_gui_stack.get_mut(*window_id).unwrap();
gui.update(window, event);
}
Event::AboutToWait => {
self.vk_windows.iter().for_each(|(window_id, _)| {
self.vk_windows
.get_window(*window_id)
.unwrap()
.request_redraw()
});
}
_ => (),
}
Ok(false)
}
pub fn handle_events(&mut self) {
for event in self.rx.try_iter() {
match event {
AppEvent::Exit => self.running = false,
}
}
}
#[allow(dead_code)]
pub fn set_schedule(&mut self, schedule: Schedule) {
self.schedule = schedule;
}
#[allow(dead_code)]
pub fn world(&self) -> &World {
&self.world
}
#[allow(dead_code)]
pub fn world_mut(&mut self) -> &mut World {
&mut self.world
}
pub fn events(&self) -> &Events {
&self.events
}
#[allow(dead_code)]
pub fn events_mut(&mut self) -> &mut Events {
&mut self.events
}
/// Pushes a module from the provided init closure to to the top of the layer stack. The provided
/// closure to construct the layer takes in the world and events.
pub fn push_render_module<F, T>(&mut self, func: F)
where
F: FnOnce(
&mut VulkanoContext,
&mut VulkanoWindows,
&mut Schedule,
&mut World,
&mut Events,
) -> T,
T: 'static + ThreadLocalModule,
{
let module = func(
&mut self.vk_context,
&mut self.vk_windows,
&mut self.schedule,
&mut self.world,
&mut self.events,
);
self.thread_local_modules.push(module);
}
/// Pushes a layer from the provided init closure to to the top of the layer stack. The provided
/// closure to construct the layer takes in the world and events.
pub fn push_module<F, T>(&mut self, func: F)
where
F: FnOnce(&mut Schedule, &mut World, &mut Events) -> T,
T: 'static + Module,
{
let module = func(&mut self.schedule, &mut self.world, &mut self.events);
self.modules.push(module);
}
/// Pushes a module from the provided init closure to to the top of the module stack. The provided
/// closure to construct the module takes in the world and events, and may return an error which
/// is propagated to the callee.
#[allow(dead_code)]
pub fn try_push_module<F, T, E>(&mut self, func: F) -> Result<(), E>
where
F: FnOnce(&mut World, &mut Events) -> Result<T, E>,
T: 'static + Module,
{
let module = func(&mut self.world, &mut self.events)?;
self.modules.push(module);
Ok(())
}
/// Inserts a module from the provided init closure to to the top of the module stack. The provided
/// closure to construct the module takes in the world and events.
#[allow(dead_code)]
pub fn insert_module<F, T>(&mut self, index: usize, func: F)
where
F: FnOnce(&mut World, &mut Events) -> T,
T: 'static + Module,
{
let module = func(&mut self.world, &mut self.events);
self.modules.insert(index, module);
}
/// Pushes a module from the provided init closure to to the top of the module stack. The provided
/// closure to construct the module takes in the world and events, and may return an error which
/// is propagated to the callee.
#[allow(dead_code)]
pub fn try_insert_module<F, T, E>(&mut self, index: usize, func: F) -> Result<(), E>
where
F: FnOnce(&mut World, &mut Events) -> Result<T, E>,
T: 'static + Module,
{
let module = func(&mut self.world, &mut self.events)?;
self.modules.insert(index, module);
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[allow(dead_code)]
pub enum AppEvent {
Exit,
}
impl Default for App {
fn default() -> Self {
Self::new()
}
}

View file

@ -1,49 +0,0 @@
use std::collections::HashMap;
use egui_vulkano::{Gui, GuiConfig};
use vulkano_util::renderer::VulkanoWindowRenderer;
use winit::{event_loop::EventLoopWindowTarget, window::WindowId};
#[derive(Default)]
pub struct DebugGuiStack {
guis: HashMap<WindowId, Gui>,
}
impl DebugGuiStack {
pub fn add_gui<T>(
&mut self,
window_id: WindowId,
event_loop: &EventLoopWindowTarget<T>,
renderer: &VulkanoWindowRenderer,
is_overlay: bool,
allow_srgb_render_target: bool,
) where
T: Clone + Send + Sync,
{
let gui = Gui::new(
event_loop,
renderer.surface().clone(),
renderer.graphics_queue().clone(),
renderer.swapchain_format(),
GuiConfig {
is_overlay,
allow_srgb_render_target,
..Default::default()
},
);
self.guis.insert(window_id, gui);
}
pub fn remove_gui(&mut self, window_id: WindowId) {
self.guis.remove(&window_id).unwrap();
}
pub fn get(&mut self, window_id: WindowId) -> Option<&Gui> {
self.guis.get(&window_id)
}
pub fn get_mut(&mut self, window_id: WindowId) -> Option<&mut Gui> {
self.guis.get_mut(&window_id)
}
}

View file

@ -1,5 +1,3 @@
pub mod app;
pub mod events;
pub mod module;
pub mod time;
pub mod debug_gui;

View file

@ -5,10 +5,13 @@ use flax::World;
use super::events::Events;
use super::debug_gui::DebugGuiStack;
pub trait Module {
fn on_update(&mut self, world: &mut World, events: &mut Events, frame_time: Duration) -> Result<()>;
fn on_update(
&mut self,
world: &mut World,
events: &mut Events,
frame_time: Duration,
) -> Result<()>;
}
pub struct ModulesStack {
@ -17,7 +20,9 @@ pub struct ModulesStack {
impl ModulesStack {
pub fn new() -> Self {
Self { modules: Vec::new() }
Self {
modules: Vec::new(),
}
}
pub fn iter(&self) -> std::slice::Iter<Box<dyn Module>> {
@ -64,63 +69,3 @@ impl<'a> IntoIterator for &'a mut ModulesStack {
self.iter_mut()
}
}
// THREAD LOCAL STUFF
pub trait RenderModule {
fn on_update(&mut self, gui_stack: &mut DebugGuiStack, vk_context: &mut vulkano_util::context::VulkanoContext, vk_windows: &mut vulkano_util::window::VulkanoWindows, world: &mut World, events: &mut Events, frame_time: Duration) -> Result<()>;
}
pub struct RenderModulesStack {
modules: Vec<Box<dyn RenderModule>>,
}
impl RenderModulesStack {
pub fn new() -> Self {
Self { modules: Vec::new() }
}
pub fn iter(&self) -> std::slice::Iter<Box<dyn RenderModule>> {
self.modules.iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<Box<dyn RenderModule>> {
self.modules.iter_mut()
}
pub fn push<T: 'static + RenderModule>(&mut self, layer: T) {
let layer = Box::new(layer);
self.modules.push(layer);
}
pub fn insert<T: 'static + RenderModule>(&mut self, index: usize, layer: T) {
let layer = Box::new(layer);
self.modules.insert(index, layer);
}
}
impl Default for RenderModulesStack {
fn default() -> Self {
Self::new()
}
}
impl<'a> IntoIterator for &'a RenderModulesStack {
type Item = &'a Box<dyn RenderModule>;
type IntoIter = std::slice::Iter<'a, Box<dyn RenderModule>>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a mut RenderModulesStack {
type Item = &'a mut Box<dyn RenderModule>;
type IntoIter = std::slice::IterMut<'a, Box<dyn RenderModule>>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}