Improve abstraction of the engine

- Improved camera controls
- Introduce new convenience function ecsr.load_mesh_from_gltf
- Abstract out the glium stuff to allow for more backends in the future.
  We're still tied to winit though as it can be used with any of the
  major graphics libraries in the Rust ecosystem.
This commit is contained in:
reo 2025-07-19 00:15:21 +03:00
parent 97195fbd05
commit a3d3f641cd
10 changed files with 115 additions and 74 deletions

View file

@ -12,6 +12,11 @@ pub struct ECSRenderer {
}
impl ECSRenderer {
pub fn from_display_handle(handle: &crate::window::DisplayHandle) -> anyhow::Result<Self> {
let world = World::new();
let renderer = crate::render::GliumRenderer::new(handle.as_inner().clone())?;
Ok(Self { renderer, world })
}
pub fn new(renderer: GliumRenderer, world: World) -> Self {
Self { renderer, world }
}
@ -45,4 +50,13 @@ impl ECSRenderer {
pub fn render_into<S: glium::Surface>(&mut self, target: &mut S) {
self.renderer.render_into(&self.world, target);
}
pub fn load_mesh_from_gltf<P: AsRef<std::path::Path> + std::fmt::Debug>(
&mut self,
path: P,
transform: Transform,
) -> anyhow::Result<Entity> {
let model = crate::gltf_loader::load_gltf(path, self.renderer.display())?;
Ok(self.spawn_mesh(model, transform))
}
}

View file

@ -3,7 +3,9 @@ pub mod model;
pub mod gltf_loader;
pub mod render;
pub mod ecs_renderer;
pub mod window;
pub use camera::Camera;
pub use render::GliumRenderer;
pub use ecs_renderer::ECSRenderer;
pub use window::{DisplayHandle, init_window as init_render_window};

View file

@ -160,4 +160,8 @@ impl GliumRenderer {
self.draw_scene(world, &mut frame);
frame.finish().unwrap();
}
pub fn display(&self) -> &glium::Display<WindowSurface> {
&self.display
}
}

View file

@ -0,0 +1,28 @@
use glium::backend::glutin::SimpleWindowBuilder;
use glium::glutin::surface::WindowSurface;
use glium::Display;
use anyhow::Result;
use winit::event_loop::EventLoop;
use winit::window::Window;
#[derive(Clone)]
pub struct DisplayHandle(Display<WindowSurface>);
impl DisplayHandle {
pub fn as_inner(&self) -> &Display<WindowSurface> {
&self.0
}
}
pub fn init_window<T>(
event_loop: &EventLoop<T>,
title: &str,
size: (u32, u32),
) -> Result<(Window, DisplayHandle)> {
let (window, display) = SimpleWindowBuilder::new()
.with_title(title)
.with_inner_size(size.0, size.1)
.build(event_loop);
Ok((window, DisplayHandle(display)))
}