Switch to lyra-ecs systems, move ecs mod to scene mod, reexport lyra-ecs as ecs

This commit is contained in:
SeanOMik 2023-12-26 23:48:46 -05:00
parent 0a0ac0ae6f
commit 09bba5b3b3
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
37 changed files with 208 additions and 236 deletions

1
Cargo.lock generated
View File

@ -2335,7 +2335,6 @@ dependencies = [
"anyhow",
"async-std",
"fps_counter",
"lyra-ecs",
"lyra-engine",
"tracing",
]

View File

@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
lyra-engine = { path = "../../", version = "0.0.1" }
lyra-ecs = { path = "../../lyra-ecs"}
#lyra-ecs = { path = "../../lyra-ecs"}
anyhow = "1.0.75"
async-std = "1.12.0"
tracing = "0.1.37"

View File

@ -1,12 +1,10 @@
use std::ops::Deref;
use std::{ops::Deref, ptr::NonNull};
use lyra_ecs::{Component, world::World};
use lyra_engine::{
ecs::{components::{camera::CameraComponent, DeltaTime}, EventQueue, SimpleSystem},
game::Game,
input::{InputButtons, KeyCode, MouseMotion},
math::{Quat, Vec3, EulerRot},
plugin::Plugin,
plugin::Plugin, ecs::{system::System, world::World, Access, Component}, DeltaTime, EventQueue, scene::CameraComponent,
};
#[derive(Clone, Component)]
@ -44,14 +42,15 @@ impl FreeFlyCamera {
pub struct FreeFlyCameraPlugin;
impl SimpleSystem for FreeFlyCameraPlugin {
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()> {
impl System for FreeFlyCameraPlugin {
fn execute(&mut self, mut world: NonNull<World>) -> anyhow::Result<()> {
let world = unsafe { world.as_mut() };
let mut camera_rot = Vec3::default();
let delta_time = **world.get_resource::<DeltaTime>();
let events = world
.try_get_resource_mut::<EventQueue>()
.try_get_resource::<EventQueue>()
.and_then(|q| q.read_events::<MouseMotion>());
let keys = world
@ -153,6 +152,10 @@ impl SimpleSystem for FreeFlyCameraPlugin {
Ok(())
}
fn world_access(&self) -> lyra_engine::ecs::Access {
Access::Write
}
}
impl Plugin for FreeFlyCameraPlugin {

View File

@ -1,4 +1,6 @@
use lyra_engine::{math::{self, Vec3}, ecs::{components::{transform::TransformComponent, camera::CameraComponent, model::ModelComponent, DeltaTime}, EventQueue, SimpleSystem, Criteria, CriteriaSchedule, BatchedSystem, lyra_ecs::{Component, world::World}}, math::Transform, input::{KeyCode, InputButtons, MouseMotion, ActionHandler, Layout, Action, ActionKind, LayoutId, ActionMapping, Binding, ActionSource, ActionMappingId, InputActionPlugin, ActionState}, game::Game, plugin::Plugin, render::{window::{CursorGrabMode, WindowOptions}, light::{PointLight, directional::DirectionalLight, SpotLight}}, change_tracker::Ct};
use std::ptr::NonNull;
use lyra_engine::{math::{self, Vec3}, math::Transform, input::{KeyCode, InputButtons, MouseMotion, ActionHandler, Layout, Action, ActionKind, LayoutId, ActionMapping, Binding, ActionSource, ActionMappingId, InputActionPlugin, ActionState}, game::Game, plugin::Plugin, render::{window::{CursorGrabMode, WindowOptions}, light::{PointLight, directional::DirectionalLight, SpotLight}}, change_tracker::Ct, ecs::{system::{Criteria, CriteriaSchedule, BatchedSystem, IntoSystem}, world::World, Component}, DeltaTime, scene::{TransformComponent, ModelComponent, CameraComponent}};
use lyra_engine::assets::{ResourceManager, Model};
mod free_fly_camera;
@ -39,7 +41,8 @@ impl FixedTimestep {
}
impl Criteria for FixedTimestep {
fn can_run(&mut self, world: &mut World, check_count: u32) -> CriteriaSchedule {
fn can_run(&mut self, mut world: NonNull<World>, check_count: u32) -> CriteriaSchedule {
let world = unsafe { world.as_mut() };
if check_count == 0 {
let delta_time = world.get_resource::<DeltaTime>();
self.accumulator += **delta_time;
@ -218,7 +221,7 @@ async fn main() {
let mut sys = BatchedSystem::new();
sys.with_criteria(FixedTimestep::new(45));
sys.with_system(spin_system);
sys.with_system(spin_system.into_system());
//sys.with_system(fps_system);
game.with_system("fixed", sys, &[]);
@ -263,7 +266,7 @@ async fn main() {
Game::initialize().await
.with_plugin(lyra_engine::DefaultPlugins)
.with_startup_system(setup_sys)
.with_startup_system(setup_sys.into_system())
.with_plugin(action_handler_plugin)
//.with_plugin(fps_plugin)
.with_plugin(jiggle_plugin)

View File

@ -1,21 +1,16 @@
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
#[proc_macro_derive(Component)]
pub fn derive_component(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as DeriveInput);
//let generics = input.generics.clone()
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let type_ident = &input.ident;
//type_ident.span().
let type_name = type_ident.to_string();
proc_macro::TokenStream::from(quote! {
impl #impl_generics ::lyra_ecs::Component for #type_ident #ty_generics #where_clause {
impl #impl_generics lyra_engine::ecs::Component for #type_ident #ty_generics #where_clause {
fn name() -> &'static str {
#type_name
}

View File

@ -3,31 +3,37 @@ use crate::world::World;
extern crate self as lyra_ecs;
//mod lyra_ecs { pub use super::*; }
mod archetype;
pub(crate) mod lyra_engine {
pub(crate) mod ecs {
pub use super::super::*;
}
}
pub mod archetype;
pub use archetype::*;
pub mod world;
pub use world::*;
mod bundle;
pub mod bundle;
pub use bundle::*;
mod component;
pub mod component;
pub use component::*;
mod query;
pub use query::*;
pub mod query;
//pub use query::*;
mod component_info;
pub mod component_info;
pub use component_info::*;
mod resource;
pub mod resource;
pub use resource::*;
mod system;
pub use system::*;
pub mod system;
//pub use system::*;
mod tick;
pub mod tick;
pub use tick::*;
pub use lyra_ecs_derive::*;

View File

@ -208,7 +208,7 @@ impl<T: 'static> AsQuery for &mut T {
mod tests {
use std::{any::TypeId, mem::size_of, marker::PhantomData, ptr::NonNull};
use crate::{world::{World, Entity, EntityId}, archetype::{Archetype, ArchetypeId}, query::View, tests::Vec2, bundle::Bundle, Fetch, DynTypeId, Tick};
use crate::{world::{World, Entity, EntityId}, archetype::{Archetype, ArchetypeId}, query::{View, Fetch}, tests::Vec2, bundle::Bundle, DynTypeId, Tick};
use super::{QueryBorrow, QueryBorrowMut, FetchBorrowMut};

View File

@ -1,10 +1,12 @@
use std::{ptr::NonNull, cell::Ref};
use crate::{Fetch, world::World, Query, ComponentColumn, ComponentInfo};
use crate::{world::World, ComponentColumn, ComponentInfo};
pub mod view;
pub use view::*;
use super::Fetch;
/// Data that rust does not know the type of
pub struct DynamicType {
pub info: ComponentInfo,

View File

@ -1,6 +1,6 @@
use std::ops::Range;
use crate::{world::World, Archetype, ArchetypeEntityId, Fetch, ArchetypeId};
use crate::{world::World, Archetype, ArchetypeEntityId, ArchetypeId, query::Fetch};
use super::{QueryDynamicType, FetchDynamicType, DynamicType};
@ -104,7 +104,7 @@ impl<'a> Iterator for DynamicViewIter<'a> {
mod tests {
use std::{alloc::Layout, ptr::NonNull};
use crate::{world::World, MemoryLayout, ComponentInfo, DynTypeId, DynamicBundle, dynamic::QueryDynamicType};
use crate::{world::World, MemoryLayout, ComponentInfo, DynTypeId, DynamicBundle, query::dynamic::QueryDynamicType};
use super::DynamicView;

View File

@ -1,6 +1,6 @@
use crate::{world::{Entity, World}, archetype::{Archetype, ArchetypeId}, AsQuery};
use crate::{world::{Entity, World}, archetype::{Archetype, ArchetypeId}};
use super::{Fetch, Query};
use super::{Fetch, Query, AsQuery};
pub struct EntitiesFetch {
entities: Vec<Entity>,

View File

@ -152,7 +152,7 @@ impl<R: ResourceObject> AsQuery for QueryResourceMut<R> {
}
#[cfg(test)]
mod tests {
use crate::{world::World, tests::{Vec2, Vec3}, QueryResourceMut};
use crate::{world::World, tests::{Vec2, Vec3}, query::QueryResourceMut};
use super::QueryResource;

View File

@ -1,6 +1,8 @@
use std::marker::PhantomData;
use crate::{ComponentColumn, Fetch, Tick, DynTypeId, Query, world::World, AsQuery};
use crate::{ComponentColumn, Tick, DynTypeId, world::World};
use super::{Query, Fetch, AsQuery};
#[derive(Clone, Copy, Debug, Default)]
pub struct TickOf<T> {

View File

@ -1,12 +1,14 @@
use lyra_ecs::world::World;
use super::{SimpleSystem, Criteria};
use crate::Access;
use super::{System, Criteria};
/// A system that executes a batch of systems in order that they were given.
/// You can optionally add criteria that must pass before the systems are
/// executed.
pub struct BatchedSystem {
systems: Vec<Box<dyn SimpleSystem>>,
systems: Vec<Box<dyn System>>,
criteria: Vec<Box<dyn Criteria>>,
criteria_checks: u32,
}
@ -23,7 +25,7 @@ impl BatchedSystem {
pub fn with_system<S>(&mut self, system: S) -> &mut Self
where
S: SimpleSystem + 'static
S: System + 'static
{
self.systems.push(Box::new(system));
self
@ -38,8 +40,16 @@ impl BatchedSystem {
}
}
impl SimpleSystem for BatchedSystem {
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()> {
impl System for BatchedSystem {
fn world_access(&self) -> crate::Access {
if self.systems.iter().any(|s| s.world_access() == Access::Write) {
Access::Write
} else {
Access::Read
}
}
fn execute(&mut self, world: std::ptr::NonNull<World>) -> anyhow::Result<()> {
let mut can_run = true;
let mut check_again = false;
@ -60,13 +70,13 @@ impl SimpleSystem for BatchedSystem {
if can_run {
for system in self.systems.iter_mut() {
system.execute_mut(world)?;
system.execute(world)?;
}
}
if check_again {
self.criteria_checks += 1;
self.execute_mut(world)?;
self.execute(world)?;
}
self.criteria_checks = 0;

View File

@ -1,5 +1,8 @@
use std::ptr::NonNull;
use lyra_ecs::world::World;
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum CriteriaSchedule {
Yes,
No,
@ -13,13 +16,14 @@ pub trait Criteria {
/// Parameters:
/// * `world` - The ecs world.
/// * `check_count` - The amount of times the Criteria has been checked this tick.
fn can_run(&mut self, world: &mut World, check_count: u32) -> CriteriaSchedule;
fn can_run(&mut self, world: NonNull<World>, check_count: u32) -> CriteriaSchedule;
}
impl<F> Criteria for F
where F: FnMut(&mut World, u32) -> CriteriaSchedule
{
fn can_run(&mut self, world: &mut World, check_count: u32) -> CriteriaSchedule {
self(world, check_count)
fn can_run(&mut self, mut world: NonNull<World>, check_count: u32) -> CriteriaSchedule {
let world_mut = unsafe { world.as_mut() };
self(world_mut, check_count)
}
}

View File

@ -1,6 +1,8 @@
use std::{collections::{HashMap, VecDeque, HashSet}, ptr::NonNull};
use crate::{System, world::World};
use super::System;
use crate::world::World;
#[derive(thiserror::Error, Debug)]
pub enum GraphExecutorError {
@ -55,8 +57,7 @@ impl GraphExecutor {
}
/// Executes the systems in the graph
pub fn execute(&mut self, world: &World, stop_on_error: bool) -> Result<Vec<GraphExecutorError>, GraphExecutorError> {
let world = NonNull::from(world);
pub fn execute(&mut self, world: NonNull<World>, stop_on_error: bool) -> Result<Vec<GraphExecutorError>, GraphExecutorError> {
let mut stack = VecDeque::new();
let mut visited = HashSet::new();
@ -106,7 +107,9 @@ impl GraphExecutor {
#[cfg(test)]
mod tests {
use crate::{View, QueryBorrow, tests::Vec2, IntoSystem, world::World, Resource, ResourceMut};
use std::ptr::NonNull;
use crate::{world::World, query::{ResourceMut, View}, system::IntoSystem};
use super::GraphExecutor;
@ -150,7 +153,7 @@ mod tests {
exec.insert_system("a", a_system.into_system(), &[]);
exec.insert_system("b", b_system.into_system(), &["a"]);
exec.execute(&world, true).unwrap();
exec.execute(NonNull::from(&world), true).unwrap();
println!("Executed systems");
let order = world.get_resource::<Vec<String>>();

View File

@ -1,16 +1,30 @@
use std::{ptr::NonNull, marker::PhantomData, cell::{Ref, RefMut}};
use crate::{world::World, View, Query, Access, ResourceObject};
use crate::{world::World, Access, ResourceObject, query::{Query, View}};
pub mod graph;
pub use graph::*;
pub mod criteria;
pub use criteria::*;
pub mod batched;
pub use batched::*;
/// A system that does not mutate the world
pub trait System {
/// A method that indicates the type of access of the world the system requires.
fn world_access(&self) -> Access;
/// The actual execution of the system.
fn execute(&mut self, world: NonNull<World>) -> anyhow::Result<()>;
/// A setup step of the System, called before `execute` ever runs.
fn setup(&self, world: NonNull<World>) -> anyhow::Result<()> {
Ok(())
}
}
/// A trait for converting something into a system.
pub trait IntoSystem<T> {
type System: System;
@ -61,6 +75,21 @@ macro_rules! impl_fn_system_tuple {
}
}
/* impl<F, $($name: FnArg,)+> IntoSystem for F
where
F: FnMut($($name,)+) -> anyhow::Result<()>,
F: for<'a> FnMut($(<$name::Fetcher as FnArgFetcher>::Arg<'a>,)+) -> anyhow::Result<()>,
{
type System = FnSystem<F, ($($name::Fetcher,)+)>;
fn into_system(self) -> Self::System {
FnSystem {
args: ($($name::Fetcher::new(),)+),
inner: self
}
}
} */
impl<F, $($name: FnArg,)+> IntoSystem<($($name,)+)> for F
where
F: FnMut($($name,)+) -> anyhow::Result<()>,
@ -223,7 +252,7 @@ impl<R: ResourceObject> FnArgFetcher for ResourceMutArgFetcher<R> {
mod tests {
use std::{ptr::NonNull, cell::RefMut};
use crate::{tests::{Vec2, Vec3}, View, QueryBorrow, world::World};
use crate::{tests::{Vec2, Vec3}, world::World, query::{QueryBorrow, View}};
use super::{System, IntoSystem};
struct SomeCounter(u32);
@ -311,6 +340,35 @@ mod tests {
assert_eq!(counter.0, 20);
}
#[test]
fn function_system() {
let mut world = World::new();
world.spawn((Vec2::rand(), Vec3::rand()));
world.spawn((Vec2::rand(), Vec3::rand()));
world.add_resource(SomeCounter(0));
let test_system = |world: &World| -> anyhow::Result<()> {
let mut counter = world.get_resource_mut::<SomeCounter>();
counter.0 += 10;
Ok(())
};
test_system.into_system().execute(NonNull::from(&world)).unwrap();
fn test_system(world: &mut World) -> anyhow::Result<()> {
let mut counter = world.get_resource_mut::<SomeCounter>();
counter.0 += 10;
Ok(())
}
test_system.into_system().execute(NonNull::from(&world)).unwrap();
let counter = world.get_resource::<SomeCounter>();
assert_eq!(counter.0, 20);
}
#[test]
fn resource_system() {
let mut world = World::new();

View File

@ -1,15 +1,23 @@
use lyra_ecs_derive::Component;
use rand::Rng;
use crate::Component;
use crate::lyra_engine;
//use crate::lyra_ecs;
/// This source file includes some common things that tests are using.
#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd, Component)]
#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)]
pub struct Vec2 {
pub x: f32,
pub y: f32,
}
impl Component for Vec2 {
fn name() -> &'static str {
"Vec2"
}
}
impl Vec2 {
pub fn new(x: f32, y: f32) -> Self {
Self {

View File

@ -1,6 +1,6 @@
use std::{collections::{HashMap, VecDeque}, any::TypeId, cell::{Ref, RefMut}, ptr::NonNull};
use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, component::Component, query::{ViewIter, View}, resource::ResourceData, Query, AsQuery, dynamic::{DynamicViewIter, QueryDynamicType, DynamicView}, ViewOne, ComponentInfo, DynTypeId, TickTracker, Tick};
use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, component::Component, query::{Query, ViewIter, View, AsQuery}, resource::ResourceData, query::{dynamic::{DynamicViewIter, QueryDynamicType, DynamicView}, ViewOne}, ComponentInfo, DynTypeId, TickTracker, Tick};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct EntityId(pub u64);
@ -300,7 +300,7 @@ impl World {
mod tests {
use std::ops::Deref;
use crate::{tests::{Vec2, Vec3}, TickOf};
use crate::{tests::{Vec2, Vec3}, query::TickOf};
use super::World;

View File

@ -1,7 +1,7 @@
use std::borrow::BorrowMut;
use instant::Instant;
use lyra_ecs::{Component, world::World};
use lyra_ecs::{Component, world::World, system::IntoSystem};
use crate::plugin::Plugin;
@ -36,6 +36,6 @@ pub struct DeltaTimePlugin;
impl Plugin for DeltaTimePlugin {
fn setup(&self, game: &mut crate::game::Game) {
game.world().add_resource(DeltaTime(0.0, None));
game.with_system("delta_time", delta_time_system, &[]);
game.with_system("delta_time", delta_time_system.into_system(), &[]);
}
}

View File

@ -1,9 +0,0 @@
pub use lyra_ecs;
pub mod components;
pub mod events;
pub use events::*;
pub mod system;
pub use system::*;

View File

@ -1,127 +0,0 @@
pub mod batched;
pub use batched::*;
pub mod criteria;
pub use criteria::*;
use lyra_ecs::world::World;
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, _world: &mut World) -> anyhow::Result<()> {
Ok(())
}
// todo: make async?
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()>;
}
impl<S> SimpleSystem for S
where S: FnMut(&mut World) -> anyhow::Result<()>
{
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()> {
self(world)
}
}
struct SystemGraphNode {
name: String,
#[allow(dead_code)]
dependent_on: Vec<String>, // TODO
system: Box<dyn SimpleSystem>,
}
struct SystemGraphEdge {
}
/// Dispatcher for multiple systems.
///
/// This struct uses a graph for finding executing systems with dependencies.
/// At some point this will be multithreaded.
pub struct SystemDispatcher {
graph: StableDiGraph<SystemGraphNode, SystemGraphEdge>,
node_refs: HashMap<String, NodeIndex>,
}
impl Default for SystemDispatcher {
fn default() -> Self {
Self {
graph: StableDiGraph::new(),
node_refs: HashMap::new(),
}
}
}
impl SystemDispatcher {
pub fn new() -> Self {
Self::default()
}
/// Adds a SimpleSystem to the SystemGraph.
///
/// WARN: Ensure that no cycles are created, this will cause the systems graph to not be sortable by topological sort,
/// and will cause a panic later on in the engine.
///
/// TODO: Return false if a cycle was created, making it impossible to know when to dispatch them. This will mean that the System would not of had been added.
pub fn add_system<S>(&mut self, name: &str, system: S, dependencies: &[&str]) -> bool
where
S: SimpleSystem + 'static
{
let name = name.to_string();
let dependencies: Vec<String> = dependencies.iter().map(|s| s.to_string()).collect();
let system = Box::new(system) as Box<dyn SimpleSystem>;
let added_index =
self.graph.add_node(SystemGraphNode {
name: name.to_string(),
dependent_on: dependencies.clone(),
system,
});
// store name ref to the graph node
self.node_refs.insert(name, added_index);
// find the dependencies in node_refs and add edges directed towards the new node
for depend in dependencies.into_iter() {
let idx = self.node_refs
.get(&depend)
.expect("Dependency not found!");
self.graph.add_edge(*idx, added_index, SystemGraphEdge { });
}
true
}
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(world) {
Ok(()) => {},
Err(e) => {
warn!("System execution of {} resulted in an error! '{}'.", node.name, e);
// TODO: Find some way to stop traversing down a topopath in the graph executor and continue down a different one.
// This might require a custom topopath implementation (preferably iterative). It would have to ensure that it
// doesn't run other systems that are dependent on that failed system.
return;
}
}
}
}
}
impl SimpleSystem for SystemDispatcher {
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()> {
self.execute_systems(world);
Ok(())
}
}

View File

@ -1,8 +1,8 @@
use std::{sync::Arc, collections::VecDeque};
use std::{sync::Arc, collections::VecDeque, ptr::NonNull};
use async_std::task::block_on;
use lyra_ecs::world::World;
use lyra_ecs::{world::World, system::{GraphExecutor, System}};
use tracing::{info, error, Level, debug};
use tracing_appender::non_blocking;
use tracing_subscriber::{
@ -13,7 +13,7 @@ use tracing_subscriber::{
use winit::{window::{WindowBuilder, Window}, event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, DeviceEvent}, event_loop::{EventLoop, ControlFlow}};
use crate::{render::{renderer::{Renderer, BasicRenderer}, window::WindowOptions}, input::InputEvent, ecs::{SimpleSystem, SystemDispatcher, EventQueue, Events}, plugin::Plugin, change_tracker::Ct};
use crate::{render::{renderer::{Renderer, BasicRenderer}, window::WindowOptions}, input::InputEvent, plugin::Plugin, change_tracker::Ct, EventQueue};
pub struct Controls<'a> {
pub world: &'a mut World,
@ -37,18 +37,18 @@ struct GameLoop {
world: World,
/// higher priority systems
engine_sys_dispatcher: SystemDispatcher,
user_sys_dispatcher: SystemDispatcher,
engine_sys_dispatcher: GraphExecutor,
user_sys_dispatcher: GraphExecutor,
}
impl GameLoop {
pub async fn new(window: Arc<Window>, world: World, user_systems: SystemDispatcher) -> GameLoop {
pub async fn new(window: Arc<Window>, world: World, user_systems: GraphExecutor) -> GameLoop {
Self {
window: Arc::clone(&window),
renderer: Box::new(BasicRenderer::create_with_window(window).await),
world,
engine_sys_dispatcher: SystemDispatcher::new(),
engine_sys_dispatcher: GraphExecutor::new(),
user_sys_dispatcher: user_systems,
}
}
@ -67,11 +67,12 @@ impl GameLoop {
}
async fn update(&mut self) {
if let Err(e) = self.engine_sys_dispatcher.execute_mut(&mut self.world) {
let world_ptr = NonNull::from(&self.world);
if let Err(e) = self.engine_sys_dispatcher.execute(world_ptr, true) {
error!("Error when executing engine ecs systems: '{}'", e);
}
if let Err(e) = self.user_sys_dispatcher.execute_mut(&mut self.world) {
if let Err(e) = self.user_sys_dispatcher.execute(world_ptr, true) {
error!("Error when executing user ecs systems: '{}'", e);
}
}
@ -205,8 +206,8 @@ impl GameLoop {
pub struct Game {
world: Option<World>,
plugins: VecDeque<Box<dyn Plugin>>,
system_dispatcher: Option<SystemDispatcher>,
startup_systems: VecDeque<Box<dyn SimpleSystem>>,
system_dispatcher: Option<GraphExecutor>,
startup_systems: VecDeque<Box<dyn System>>,
}
impl Default for Game {
@ -214,7 +215,7 @@ impl Default for Game {
Self {
world: Some(World::new()),
plugins: VecDeque::new(),
system_dispatcher: Some(SystemDispatcher::new()),
system_dispatcher: Some(GraphExecutor::new()),
startup_systems: VecDeque::new(),
}
}
@ -234,10 +235,10 @@ impl Game {
/// 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
S: System + 'static
{
let system_dispatcher = self.system_dispatcher.as_mut().unwrap();
system_dispatcher.add_system(name, system, depends);
system_dispatcher.insert_system(name, system, depends);
self
}
@ -246,7 +247,7 @@ impl Game {
/// They will only be ran once
pub fn with_startup_system<S>(&mut self, system: S) -> &mut Self
where
S: SimpleSystem + 'static
S: System + 'static
{
self.startup_systems.push_back(Box::new(system));
@ -294,8 +295,9 @@ impl Game {
// 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!");
let world_ptr = NonNull::from(&world);
startup.setup(world_ptr).expect("World returned an error!");
startup.execute(world_ptr).expect("World returned an error!");
}
// start winit event loops

View File

@ -1,6 +1,6 @@
use std::{collections::HashMap, cell::RefCell, borrow::BorrowMut, ops::Deref};
use lyra_ecs::world::World;
use lyra_ecs::{world::World, system::IntoSystem};
use crate::{castable_any::CastableAny, plugin::Plugin};
@ -424,6 +424,6 @@ pub struct InputActionPlugin;
impl Plugin for InputActionPlugin {
fn setup(&self, game: &mut crate::game::Game) {
game.with_system("input_actions", actions_system, &[]);
game.with_system("input_actions", actions_system.into_system(), &[]);
}
}

View File

@ -1,8 +1,10 @@
use std::ptr::NonNull;
use glam::Vec2;
use lyra_ecs::world::World;
use winit::event::MouseScrollDelta;
use crate::{ecs::{SimpleSystem, EventQueue}, plugin::Plugin,};
use crate::{EventQueue, plugin::Plugin};
use super::{events::*, InputButtons, InputEvent};
@ -96,8 +98,9 @@ impl InputSystem {
}
}
impl SimpleSystem for InputSystem {
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()> {
impl crate::ecs::system::System for InputSystem {
fn execute(&mut self, mut world: NonNull<World>) -> anyhow::Result<()> {
let world = unsafe { world.as_mut() };
let queue = world.try_get_resource_mut::<EventQueue>()
.and_then(|q| q.read_events::<InputEvent>());
@ -113,6 +116,10 @@ impl SimpleSystem for InputSystem {
Ok(())
}
fn world_access(&self) -> lyra_ecs::Access {
lyra_ecs::Access::Write
}
}
/// Plugin that runs InputSystem

View File

@ -2,16 +2,26 @@
#![feature(lint_reasons)]
#![feature(trait_alias)]
extern crate self as lyra_engine;
pub mod game;
pub mod render;
pub mod resources;
pub mod ecs;
pub mod math;
pub mod input;
pub mod castable_any;
pub mod plugin;
pub mod change_tracker;
pub mod events;
pub use events::*;
pub mod delta_time;
pub use delta_time::*;
pub mod scene;
pub use lyra_resource as assets;
pub use lyra_ecs as ecs;
pub use plugin::DefaultPlugins;

View File

@ -1,7 +1,7 @@
use lyra_resource::ResourceManager;
use crate::ecs::EventsPlugin;
use crate::ecs::components::DeltaTimePlugin;
use crate::EventsPlugin;
use crate::DeltaTimePlugin;
use crate::game::Game;
use crate::input::InputPlugin;
use crate::render::window::WindowPlugin;

View File

@ -1,6 +1,6 @@
use winit::dpi::PhysicalSize;
use crate::{math::{Angle, OPENGL_TO_WGPU_MATRIX}, ecs::components::camera::CameraComponent};
use crate::{math::{Angle, OPENGL_TO_WGPU_MATRIX}, scene::CameraComponent};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CameraProjectionMode {

View File

@ -2,7 +2,7 @@ pub mod point;
pub mod directional;
pub mod spotlight;
use lyra_ecs::{Entity, Tick, world::World, Entities, TickOf};
use lyra_ecs::{Entity, Tick, world::World, query::{Entities, TickOf}};
pub use point::*;
pub use directional::*;
pub use spotlight::*;
@ -15,7 +15,7 @@ use wgpu::util::DeviceExt;
use std::mem;
use crate::{math::Transform, ecs::components::TransformComponent};
use crate::{math::Transform, scene::TransformComponent};
use self::directional::DirectionalLight;

View File

@ -7,20 +7,19 @@ use std::borrow::Cow;
use glam::Vec3;
use instant::Instant;
use itertools::izip;
use lyra_ecs::{Entity, Entities, TickOf};
use lyra_ecs::Entity;
use lyra_ecs::query::{Entities, TickOf};
use lyra_ecs::world::World;
use tracing::{debug, warn};
use wgpu::{BindGroup, BindGroupLayout, Limits};
use wgpu::util::DeviceExt;
use winit::window::Window;
use crate::ecs::components::camera::CameraComponent;
use crate::ecs::components::model::ModelComponent;
use crate::ecs::components::transform::TransformComponent;
use crate::math::{Transform, self};
use crate::render::light::PointLightUniform;
use crate::render::material::MaterialUniform;
use crate::render::render_buffer::{BufferWrapperBuilder, BindGroupPair};
use crate::scene::{ModelComponent, TransformComponent, CameraComponent};
use super::camera::{RenderCamera, CameraUniform};
use super::desc_buf_lay::DescVertexBufferLayout;

View File

@ -1,13 +1,13 @@
use std::{sync::Arc, collections::VecDeque};
use glam::{Vec2, IVec2};
use lyra_ecs::world::World;
use lyra_ecs::{world::World, system::IntoSystem};
use tracing::{warn, error};
use winit::{window::{Window, Fullscreen}, dpi::{LogicalPosition, LogicalSize, PhysicalPosition}, error::ExternalError};
pub use winit::window::{CursorGrabMode, CursorIcon, Icon, Theme, WindowButtons, WindowLevel};
use crate::{plugin::Plugin, change_tracker::Ct, ecs::EventQueue, input::InputEvent};
use crate::{plugin::Plugin, change_tracker::Ct, input::InputEvent, EventQueue};
#[derive(Default, Clone)]
pub enum WindowMode {
@ -374,6 +374,6 @@ impl Plugin for WindowPlugin {
let window_options = WindowOptions::default();
game.world().add_resource(Ct::new(window_options));
game.with_system("window_updater", window_updater_system, &[]);
game.with_system("window_updater", window_updater_system.into_system(), &[]);
}
}

5
src/ecs/components/mod.rs → src/scene/mod.rs Executable file → Normal file
View File

@ -11,7 +11,4 @@ pub mod camera;
pub use camera::*;
pub mod free_fly_camera;
pub use free_fly_camera::*;
pub mod delta_time;
pub use delta_time::*;
pub use free_fly_camera::*;