Use resources from the resource manager, implement startup systems
This commit is contained in:
parent
a1c3cd6d99
commit
bd21e62cba
|
@ -1716,12 +1716,12 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
|||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.3"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
|
||||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -27,7 +27,6 @@ tobj = { version = "3.2.1", features = [
|
|||
instant = "0.1"
|
||||
async-trait = "0.1.65"
|
||||
glam = { version = "0.24.0", features = ["bytemuck"] }
|
||||
petgraph = "0.6.3"
|
||||
gilrs-core = "0.5.6"
|
||||
syn = "2.0.26"
|
||||
quote = "1.0.29"
|
||||
|
@ -36,3 +35,4 @@ atomicell = "0.1.9"
|
|||
aligned-vec = "0.5.0"
|
||||
tracing-appender = "0.2.2"
|
||||
stopwatch = "0.0.7"
|
||||
petgraph = "0.6.4"
|
||||
|
|
|
@ -28,7 +28,7 @@ impl From<io::Error> for LoaderError {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait ResourceLoader {
|
||||
pub trait ResourceLoader: Send + Sync {
|
||||
fn extensions(&self) -> &[&str];
|
||||
fn does_support_file(&self, path: &str) -> bool;
|
||||
fn load(&self, path: &str) -> Result<Arc<dyn ResourceStorage>, LoaderError>;
|
||||
|
|
|
@ -1,31 +1,29 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use petgraph::{prelude::StableDiGraph, stable_graph::NodeIndex, visit::Topo};
|
||||
use tracing::warn;
|
||||
|
||||
use crate::game::Controls;
|
||||
|
||||
pub use edict::*;
|
||||
|
||||
pub mod components;
|
||||
pub mod events;
|
||||
pub use events::*;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use petgraph::{stable_graph::{StableDiGraph, NodeIndex}, visit::Topo};
|
||||
use tracing::warn;
|
||||
|
||||
/// A trait that represents a simple system
|
||||
pub trait SimpleSystem {
|
||||
fn setup(&mut self, controls: &mut Controls) -> anyhow::Result<()> {
|
||||
fn setup(&mut self, world: &mut World) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// todo: make async?
|
||||
fn execute_mut(&mut self, controls: &mut Controls) -> anyhow::Result<()>;
|
||||
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()>;
|
||||
}
|
||||
|
||||
impl<S> SimpleSystem for S
|
||||
where S: FnMut(&mut edict::World) -> anyhow::Result<()>
|
||||
{
|
||||
fn execute_mut(&mut self, controls: &mut Controls) -> anyhow::Result<()> {
|
||||
self(controls.world)
|
||||
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()> {
|
||||
self(world)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,9 +42,9 @@ impl BatchedSystem {
|
|||
}
|
||||
|
||||
impl SimpleSystem for BatchedSystem {
|
||||
fn execute_mut(&mut self, controls: &mut Controls) -> anyhow::Result<()> {
|
||||
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()> {
|
||||
for system in self.systems.iter_mut() {
|
||||
system.execute_mut(controls)?;
|
||||
system.execute_mut(world)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -122,13 +120,13 @@ impl SystemDispatcher {
|
|||
true
|
||||
}
|
||||
|
||||
pub(crate) fn execute_systems(&mut self, controls: &mut Controls) {
|
||||
pub(crate) fn execute_systems(&mut self, world: &mut World) {
|
||||
let mut topo = Topo::new(&self.graph);
|
||||
|
||||
while let Some(nx) = topo.next(&self.graph) {
|
||||
let node = self.graph.node_weight_mut(nx).unwrap();
|
||||
|
||||
match node.system.execute_mut(controls) {
|
||||
match node.system.execute_mut(world) {
|
||||
Ok(()) => {},
|
||||
Err(e) => {
|
||||
warn!("System execution of {} resulted in an error! '{}'.", node.name, e);
|
||||
|
@ -144,8 +142,8 @@ impl SystemDispatcher {
|
|||
}
|
||||
|
||||
impl SimpleSystem for SystemDispatcher {
|
||||
fn execute_mut(&mut self, controls: &mut Controls) -> anyhow::Result<()> {
|
||||
self.execute_systems(controls);
|
||||
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()> {
|
||||
self.execute_systems(world);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
46
src/game.rs
46
src/game.rs
|
@ -68,15 +68,11 @@ impl GameLoop {
|
|||
}
|
||||
|
||||
async fn update(&mut self) {
|
||||
let mut controls = Controls {
|
||||
world: &mut self.world,
|
||||
};
|
||||
|
||||
if let Err(e) = self.engine_sys_dispatcher.execute_mut(&mut controls) {
|
||||
if let Err(e) = self.engine_sys_dispatcher.execute_mut(&mut self.world) {
|
||||
error!("Error when executing engine ecs systems: '{}'", e);
|
||||
}
|
||||
|
||||
if let Err(e) = self.user_sys_dispatcher.execute_mut(&mut controls) {
|
||||
if let Err(e) = self.user_sys_dispatcher.execute_mut(&mut self.world) {
|
||||
error!("Error when executing user ecs systems: '{}'", e);
|
||||
}
|
||||
}
|
||||
|
@ -224,9 +220,10 @@ impl GameLoop {
|
|||
}
|
||||
|
||||
pub struct Game {
|
||||
pub world: Option<edict::World>,
|
||||
world: Option<edict::World>,
|
||||
plugins: VecDeque<Box<dyn Plugin>>,
|
||||
system_dispatcher: Option<SystemDispatcher>,
|
||||
startup_systems: VecDeque<Box<dyn SimpleSystem>>,
|
||||
}
|
||||
|
||||
impl Default for Game {
|
||||
|
@ -235,6 +232,7 @@ impl Default for Game {
|
|||
world: Some(edict::World::new()),
|
||||
plugins: VecDeque::new(),
|
||||
system_dispatcher: Some(SystemDispatcher::new()),
|
||||
startup_systems: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -244,6 +242,13 @@ impl Game {
|
|||
Self::default()
|
||||
}
|
||||
|
||||
/// Get the world of this game
|
||||
pub fn world(&mut self) -> &mut edict::World {
|
||||
// world is always `Some`, so unwrapping is safe
|
||||
self.world.as_mut().unwrap()
|
||||
}
|
||||
|
||||
/// Add a system to the ecs world
|
||||
pub fn with_system<S>(&mut self, name: &str, system: S, depends: &[&str]) -> &mut Self
|
||||
where
|
||||
S: SimpleSystem + 'static
|
||||
|
@ -254,7 +259,18 @@ impl Game {
|
|||
self
|
||||
}
|
||||
|
||||
/// Add a plugin to the game
|
||||
/// Add a startup system that will be ran right after plugins are setup.
|
||||
/// They will only be ran once
|
||||
pub fn with_startup_system<S>(&mut self, system: S) -> &mut Self
|
||||
where
|
||||
S: SimpleSystem + 'static
|
||||
{
|
||||
self.startup_systems.push_back(Box::new(system));
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a plugin to the game. These will be executed before the window is initiated and opened
|
||||
pub fn with_plugin<P>(&mut self, plugin: P) -> &mut Self
|
||||
where
|
||||
P: Plugin + 'static
|
||||
|
@ -264,12 +280,16 @@ impl Game {
|
|||
self
|
||||
}
|
||||
|
||||
/// Override the default (empty) world
|
||||
///
|
||||
/// This isn't recommended, you should create a startup system and add it to `with_startup_system`
|
||||
pub fn with_world(&mut self, world: edict::World) -> &mut Self {
|
||||
self.world = Some(world);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Start the game
|
||||
pub async fn run(&mut self) {
|
||||
// init logging
|
||||
let (stdout_layer, _stdout_nb) = non_blocking(std::io::stdout());
|
||||
|
@ -286,11 +306,19 @@ impl Game {
|
|||
plugin.as_ref().setup(self);
|
||||
}
|
||||
|
||||
let mut world = self.world.take().unwrap_or_else(|| edict::World::new());
|
||||
|
||||
// run startup systems
|
||||
while let Some(mut startup) = self.startup_systems.pop_front() {
|
||||
let startup = startup.as_mut();
|
||||
startup.setup(&mut world).expect("World returned an error!");
|
||||
startup.execute_mut(&mut world).expect("World returned an error!");
|
||||
}
|
||||
|
||||
// start winit event loops
|
||||
let event_loop = EventLoop::new();
|
||||
let window = Arc::new(WindowBuilder::new().build(&event_loop).unwrap());
|
||||
|
||||
let world = self.world.take().unwrap_or_else(|| edict::World::new());
|
||||
let system_dispatcher = self.system_dispatcher.take().unwrap();
|
||||
let mut g_loop = GameLoop::new(Arc::clone(&window), world, system_dispatcher).await;
|
||||
g_loop.on_init().await;
|
||||
|
|
|
@ -313,9 +313,7 @@ impl InputSystem {
|
|||
}
|
||||
|
||||
impl SimpleSystem for InputSystem {
|
||||
fn execute_mut(&mut self, controls: &mut crate::game::Controls) -> anyhow::Result<()> {
|
||||
let world = &mut controls.world;
|
||||
|
||||
fn execute_mut(&mut self, world: &mut edict::World) -> anyhow::Result<()> {
|
||||
let queue = world.get_resource_mut::<EventQueue>()
|
||||
.map(|q| q.read_events::<InputEvent>()).flatten();
|
||||
|
||||
|
|
15
src/lib.rs
15
src/lib.rs
|
@ -8,17 +8,6 @@ pub mod input;
|
|||
pub mod castable_any;
|
||||
pub mod plugin;
|
||||
|
||||
use plugin::Plugin;
|
||||
pub use lyra_resource as assets;
|
||||
|
||||
use crate::input::InputPlugin;
|
||||
|
||||
/// Default plugins of Lyra. Make sure to have these added to the Game first
|
||||
#[derive(Default)]
|
||||
pub struct DefaultPlugins;
|
||||
|
||||
impl Plugin for DefaultPlugins {
|
||||
fn setup(&self, game: &mut game::Game) {
|
||||
// setup input
|
||||
InputPlugin::default().setup(game);
|
||||
}
|
||||
}
|
||||
pub use plugin::DefaultPlugins;
|
|
@ -1,4 +1,7 @@
|
|||
use lyra_resource::ResourceManager;
|
||||
|
||||
use crate::game::Game;
|
||||
use crate::input::InputPlugin;
|
||||
|
||||
/// A Plugin is something you can add to a `Game` that can be used to define systems, or spawn initial entities.
|
||||
pub trait Plugin {
|
||||
|
@ -74,3 +77,24 @@ impl_tuple_plugin_set! { (C0, 0) (C1, 1) (C2, 2) (C3, 3) (C4, 4) (C5, 5) (C6, 6)
|
|||
impl_tuple_plugin_set! { (C0, 0) (C1, 1) (C2, 2) (C3, 3) (C4, 4) (C5, 5) (C6, 6) (C7, 7) (C8, 8) (C9, 9) (C10, 10) (C11, 11) (C12, 12) }
|
||||
impl_tuple_plugin_set! { (C0, 0) (C1, 1) (C2, 2) (C3, 3) (C4, 4) (C5, 5) (C6, 6) (C7, 7) (C8, 8) (C9, 9) (C10, 10) (C11, 11) (C12, 12) (C13, 13) }
|
||||
impl_tuple_plugin_set! { (C0, 0) (C1, 1) (C2, 2) (C3, 3) (C4, 4) (C5, 5) (C6, 6) (C7, 7) (C8, 8) (C9, 9) (C10, 10) (C11, 11) (C12, 12) (C13, 13) (C14, 14) }
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ResourceManagerPlugin;
|
||||
|
||||
impl Plugin for ResourceManagerPlugin {
|
||||
fn setup(&self, game: &mut Game) {
|
||||
game.world().insert_resource(ResourceManager::new());
|
||||
}
|
||||
}
|
||||
|
||||
/// Default plugins of Lyra. Make sure to have these added to the Game first
|
||||
#[derive(Default)]
|
||||
pub struct DefaultPlugins;
|
||||
|
||||
impl Plugin for DefaultPlugins {
|
||||
fn setup(&self, game: &mut Game) {
|
||||
// setup input
|
||||
InputPlugin::default().setup(game);
|
||||
ResourceManagerPlugin::default().setup(game);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
use super::texture::Texture;
|
||||
use std::sync::Arc;
|
||||
|
||||
use lyra_resource::{Texture, Resource};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Material {
|
||||
pub shader_id: u32,
|
||||
pub texture: Texture,
|
||||
pub texture: Arc<Resource<Texture>>,
|
||||
}
|
|
@ -462,8 +462,9 @@ impl BasicRenderer {
|
|||
|
||||
let (vertex_buffer, buffer_indices) = self.create_vertex_index_buffers(mesh);
|
||||
|
||||
let texture_img = &model.material.texture;
|
||||
let diffuse_texture = RenderTexture::from_image(&self.device, &self.queue, &texture_img.img, 0, None).unwrap();
|
||||
let model_texture = &model.material.texture;
|
||||
let image = &model_texture.data.as_ref().unwrap().image;
|
||||
let diffuse_texture = RenderTexture::from_image(&self.device, &self.queue, image, None).unwrap();
|
||||
|
||||
let texture_bind_group_layout =
|
||||
self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use image::GenericImageView;
|
||||
use lyra_resource::{Resource, Texture};
|
||||
|
||||
#[derive(Clone)]
|
||||
/* #[derive(Clone)]
|
||||
pub struct Texture {
|
||||
texture_id: u32,
|
||||
pub img: image::DynamicImage,
|
||||
|
@ -17,14 +18,13 @@ impl Texture {
|
|||
img,
|
||||
})
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub struct RenderTexture {
|
||||
texture_id: u32,
|
||||
texture: Arc<wgpu::Texture>,
|
||||
view: Arc<wgpu::TextureView>,
|
||||
sampler: Arc<wgpu::Sampler>,
|
||||
|
@ -33,12 +33,12 @@ pub struct RenderTexture {
|
|||
impl RenderTexture {
|
||||
pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
|
||||
|
||||
pub fn from_bytes(device: &wgpu::Device, queue: &wgpu::Queue, bytes: &[u8], texture_id: u32, label: &str) -> anyhow::Result<Self> {
|
||||
pub fn from_bytes(device: &wgpu::Device, queue: &wgpu::Queue, bytes: &[u8], label: &str) -> anyhow::Result<Self> {
|
||||
let img = image::load_from_memory(bytes)?;
|
||||
Self::from_image(device, queue, &img, texture_id, Some(label))
|
||||
Self::from_image(device, queue, &img, Some(label))
|
||||
}
|
||||
|
||||
pub fn from_image(device: &wgpu::Device, queue: &wgpu::Queue, img: &image::DynamicImage, texture_id: u32, label: Option<&str>) -> anyhow::Result<Self> {
|
||||
pub fn from_image(device: &wgpu::Device, queue: &wgpu::Queue, img: &image::DynamicImage, label: Option<&str>) -> anyhow::Result<Self> {
|
||||
let rgba = img.to_rgba8();
|
||||
let dimensions = img.dimensions();
|
||||
|
||||
|
@ -90,16 +90,16 @@ impl RenderTexture {
|
|||
);
|
||||
|
||||
Ok(Self {
|
||||
texture_id,
|
||||
texture: Arc::new(texture),
|
||||
view: Arc::new(view),
|
||||
sampler: Arc::new(sampler),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update_texture(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, texture: &Texture) {
|
||||
let rgba = texture.img.to_rgba8();
|
||||
let dimensions = texture.img.dimensions();
|
||||
pub fn update_texture(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, texture: &Arc<Resource<Texture>>) {
|
||||
let texture = &texture.data.as_ref().unwrap().image;
|
||||
let rgba = texture.to_rgba8();
|
||||
let dimensions = texture.dimensions();
|
||||
let size = wgpu::Extent3d {
|
||||
width: dimensions.0,
|
||||
height: dimensions.1,
|
||||
|
@ -162,7 +162,6 @@ impl RenderTexture {
|
|||
texture: Arc::new(texture),
|
||||
view: Arc::new(view),
|
||||
sampler: Arc::new(sampler),
|
||||
texture_id: 0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue