diff --git a/Cargo.lock b/Cargo.lock index 883fc6d..afc9d17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1837,6 +1837,7 @@ dependencies = [ "lyra-scene", "petgraph", "quote", + "rand", "round_mult", "rustc-hash 2.0.0", "syn 2.0.77", diff --git a/crates/lyra-ecs/src/command.rs b/crates/lyra-ecs/src/command.rs index b24180e..b97b86e 100644 --- a/crates/lyra-ecs/src/command.rs +++ b/crates/lyra-ecs/src/command.rs @@ -204,11 +204,11 @@ impl FnArgFetcher for Commands<'_, '_> { CommandQueue::default() } - fn apply_deferred<'a>(mut state: Self::State, mut world_ptr: NonNull<World>) { + fn apply_deferred<'a, 'state>(state: &'state mut Self::State, mut world_ptr: NonNull<World>) { let world = unsafe { world_ptr.as_mut() }; - let mut cmds = Commands::new(&mut state, world); - // safety: Commands has a mut borrow only to entities in the world + let mut cmds = Commands::new(state, world); + // SAFETY: Commands has a mut borrow only to entities in the world let world = unsafe { world_ptr.as_mut() }; cmds.execute(world); } diff --git a/crates/lyra-ecs/src/query/view.rs b/crates/lyra-ecs/src/query/view.rs index 92d4aa6..b26e490 100644 --- a/crates/lyra-ecs/src/query/view.rs +++ b/crates/lyra-ecs/src/query/view.rs @@ -183,7 +183,7 @@ impl<Q: Query> FnArgFetcher for ViewOneState<'_, Q> { ViewOneState::<Q>::new(world, Q::new()) } - fn apply_deferred(_: Self::State, _: NonNull<World>) { } + fn apply_deferred<'state>(_: &'state mut Self::State, _: NonNull<World>) { } fn create_state(_: NonNull<World>) -> Self::State { () } } \ No newline at end of file diff --git a/crates/lyra-ecs/src/query/world_tick.rs b/crates/lyra-ecs/src/query/world_tick.rs index ef344b2..f8e9269 100644 --- a/crates/lyra-ecs/src/query/world_tick.rs +++ b/crates/lyra-ecs/src/query/world_tick.rs @@ -96,7 +96,7 @@ impl FnArgFetcher for WorldTick { WorldTick(world.current_tick()) } - fn apply_deferred(_: Self::State, _: std::ptr::NonNull<World>) { + fn apply_deferred<'state>(_: &'state mut Self::State, _: std::ptr::NonNull<World>) { } } diff --git a/crates/lyra-ecs/src/system/fn_sys.rs b/crates/lyra-ecs/src/system/fn_sys.rs index c0419ee..9cbd3d4 100644 --- a/crates/lyra-ecs/src/system/fn_sys.rs +++ b/crates/lyra-ecs/src/system/fn_sys.rs @@ -29,7 +29,7 @@ pub trait FnArgFetcher { unsafe fn get<'a, 'state>(state: &'state mut Self::State, world: NonNull<World>) -> Self::Arg<'a, 'state>; /// Apply some action after the system was ran. - fn apply_deferred(state: Self::State, world: NonNull<World>); + fn apply_deferred<'state>(state: &'state mut Self::State, world: NonNull<World>); } /// A system that is implemented as a function. @@ -64,22 +64,32 @@ macro_rules! impl_fn_system_tuple { fn execute(&mut self, world: NonNull<World>) -> anyhow::Result<()> { unsafe { paste! { + // initialize state if it hasn't been + if self.arg_state.is_none() { + self.arg_state = Some(vec![ + $( + Box::new($name::create_state(world)) + ),+ + ]); + } + + // safe unwrap since state was just initialized + let mut state_iter = self.arg_state.as_mut().unwrap().iter_mut(); + $( - // get the arg fetcher, create its state, and get the arg - let mut [<state_ $name:lower>]: $name::State = $name::create_state(world); + let mut [<state_ $name:lower>]: &mut $name::State = state_iter.next() + // Safe since state vec is initialized to expected size + //.unwrap() + .expect("state was not initialized to correct size") + .downcast_mut() + // Safe due to the ordering of the arguments ensuring the correct + // types. + .unwrap_or_else(|| panic!("Failed to downcast state '{}' from 'Box<dyn Any>'", + std::any::type_name::<$name::State>())); let [<$name:lower>] = $name::get(&mut [<state_ $name:lower>], world); )+ (self.inner)($( [<$name:lower>] ),+)?; - - let mut state = Vec::new(); - $( - // type erase the now modified state, and store it - let boxed = Box::new([<state_ $name:lower>]) as Box<dyn Any>; - state.push(boxed); - )+ - - self.arg_state = Some(state); } Ok(()) @@ -87,14 +97,16 @@ macro_rules! impl_fn_system_tuple { } fn execute_deferred(&mut self, world: NonNull<World>) -> anyhow::Result<()> { - let state = self.arg_state.as_mut().expect("Somehow there was no state"); - state.reverse(); + let mut state = self.arg_state.as_mut() + .expect("State was never initialized") + .iter_mut(); $( - let arg_state_box = state.pop() - .expect("Missing expected arg state"); - let arg_state = *arg_state_box.downcast::<$name::State>() - .expect("Somehow the state cannot be downcasted from boxed Any"); + let arg_state_box = state.next() + .expect("Invalid number of state was initialized"); + let arg_state = arg_state_box.downcast_mut::<$name::State>() + .unwrap_or_else(|| panic!("Failed to downcast state '{}' from 'Box<dyn Any>'", + std::any::type_name::<$name::State>())); $name::apply_deferred(arg_state, world); )+ @@ -160,7 +172,7 @@ where v } - fn apply_deferred(_: Self::State, _: NonNull<World>) { } + fn apply_deferred<'state>(_: &'state mut Self::State, _: NonNull<World>) { } fn create_state(_: NonNull<World>) -> Self::State { (Q::new(), F::new()) @@ -179,7 +191,7 @@ impl FnArgFetcher for &'_ World { &*world.as_ptr() } - fn apply_deferred(_: Self::State, _: NonNull<World>) { } + fn apply_deferred<'state>(_: &'state mut Self::State, _: NonNull<World>) { } fn create_state(_: NonNull<World>) -> Self::State { () } } @@ -196,7 +208,7 @@ impl FnArgFetcher for &'_ mut World { &mut *world.as_ptr() } - fn apply_deferred(_: Self::State, _: NonNull<World>) { } + fn apply_deferred<'state>(_: &'state mut Self::State, _: NonNull<World>) { } fn create_state(_: NonNull<World>) -> Self::State { () } } @@ -220,7 +232,7 @@ impl<R: ResourceObject> FnArgFetcher for Res<'_, R> { .unwrap_or_else(|| panic!("world is missing resource: {}", std::any::type_name::<R>())) } - fn apply_deferred(_: Self::State, _: NonNull<World>) { } + fn apply_deferred<'state>(_: &'state mut Self::State, _: NonNull<World>) { } fn create_state(_: NonNull<World>) -> Self::State { () } } @@ -236,7 +248,7 @@ impl<R: ResourceObject> FnArgFetcher for ResMut<'_, R> { .unwrap_or_else(|| panic!("world is missing resource: {}", std::any::type_name::<R>())) } - fn apply_deferred(_: Self::State, _: NonNull<World>) { } + fn apply_deferred<'state>(_: &'state mut Self::State, _: NonNull<World>) { } fn create_state(_: NonNull<World>) -> Self::State { () } } diff --git a/crates/lyra-game/Cargo.toml b/crates/lyra-game/Cargo.toml index c0bcc25..dec0e02 100644 --- a/crates/lyra-game/Cargo.toml +++ b/crates/lyra-game/Cargo.toml @@ -42,6 +42,7 @@ bind_match = "0.1.2" round_mult = "0.1.3" fast_poisson = { version = "1.0.0", features = ["single_precision"] } atomic_refcell = "0.1.13" +rand = "0.8.5" [features] -tracy = ["dep:tracing-tracy"] \ No newline at end of file +tracy = ["dep:tracing-tracy"] diff --git a/crates/lyra-game/src/event.rs b/crates/lyra-game/src/event.rs index 10a3e42..fedff19 100644 --- a/crates/lyra-game/src/event.rs +++ b/crates/lyra-game/src/event.rs @@ -77,12 +77,17 @@ pub struct Events<T: Event> { last_cleared_at: Tick, /// Used to indicate when the cursor in readers should be reset to zero. /// This becomes true after the old events are cleared. - reset_cursor: bool, + //reset_cursor: bool, + /// This is set to the amount of elements that were deleted. + /// + /// Its used to decrease the cursor by the amount of elements deleted, instead of resetting + /// to zero to avoid rereading events that are in other levels of the vec. + decrease_cursor_by: Option<usize>, } impl<T: Event> Default for Events<T> { fn default() -> Self { - Self { events: Default::default(), last_cleared_at: Default::default(), reset_cursor: false } + Self { events: Default::default(), last_cleared_at: Default::default(), decrease_cursor_by: None } } } @@ -96,37 +101,36 @@ impl<T: Event> Events<T> { events.push(event); } - pub fn reader(&self) -> EventReader<T> { + /* pub fn reader(&self) -> EventReader<T> { EventReader { events: self.events.clone(), - cursor: Arc::new(AtomicRefCell::new(0)), + //cursor: Arc::new(AtomicRefCell::new(0)), + cursor: Arc::new(AtomicUsize::new(0)), } - } + } */ - pub fn writer(&self) -> EventWriter<T> { + /* pub fn writer(&self) -> EventWriter<T> { EventWriter { events: self.events.clone(), } - } + } */ } -pub struct EventReader<T: Event> { +pub struct EventReader<'state, T: Event> { events: Arc<AtomicRefCell<WaterfallVec<T>>>, - cursor: Arc<AtomicRefCell<usize>>, + cursor: &'state mut usize, } -impl<T: Event> EventReader<T> { - pub fn read(&self) -> Option<atomic_refcell::AtomicRef<T>> { +impl<'state, T: Event> EventReader<'state, T> { + pub fn read(&mut self) -> Option<T> { let events = self.events.borrow(); - let mut cursor = self.cursor.borrow_mut(); - if *cursor >= events.total_len() { + if *self.cursor >= events.total_len() { None } else { - let e = atomic_refcell::AtomicRef::map(events, - |e| e.get(*cursor).unwrap()); - *cursor += 1; - Some(e) + let e = events.get(*self.cursor).unwrap(); + *self.cursor += 1; + Some(e.clone()) } } } @@ -152,12 +156,19 @@ where if last_tick + 2 < world_tick { events.last_cleared_at = *tick; - events.reset_cursor = true; - let mut events = events.events.borrow_mut(); - events.clear_oldest(); + let mut events_fall = events.events.borrow_mut(); + + // Since oldest will be cleared, we need to decrease the cursor by the removed amount + // store the amount it needs to decrease by. + let old_len = events_fall.old.len(); + events_fall.clear_oldest(); + + drop(events_fall); + + events.decrease_cursor_by = Some(old_len); } else { - events.reset_cursor = false; + events.decrease_cursor_by = None; } let mut events = events.events.borrow_mut(); @@ -166,34 +177,36 @@ where Ok(()) } -impl<T: Event> FnArgFetcher for EventReader<T> { - type State = Arc<AtomicRefCell<usize>>; +impl<T: Event> FnArgFetcher for EventReader<'_, T> { + type State = usize; - type Arg<'a, 'state> = EventReader<T>; + type Arg<'b, 'state> = EventReader<'state, T>; fn create_state(_: std::ptr::NonNull<lyra_ecs::World>) -> Self::State { - Arc::new(AtomicRefCell::new(0)) + 0 } - unsafe fn get<'a, 'state>(state: &'state mut Self::State, world: std::ptr::NonNull<lyra_ecs::World>) -> Self::Arg<'a, 'state> { + unsafe fn get<'b, 'state>(state: &'state mut Self::State, world: std::ptr::NonNull<lyra_ecs::World>) -> Self::Arg<'b, 'state> { let world = world.as_ref(); let events = world.get_resource::<Events<T>>() .unwrap_or_else(|| panic!("world missing Events<{}> resource", std::any::type_name::<T>())); - if events.reset_cursor { - let mut state_num = state.borrow_mut(); - *state_num = 0; + if let Some(dec_by) = events.decrease_cursor_by { + // The waterfall vec had its oldest events deleted. + // The cursor needs to be decreased by the amount of elements deleted, instead of resetting + // to zero to avoid rereading events that are in other levels of the vec. + *state = state.checked_sub(dec_by).unwrap_or_default(); } - + let reader = EventReader { events: events.events.clone(), - cursor: state.clone(), + cursor: state, }; reader } - fn apply_deferred(_: Self::State, _: std::ptr::NonNull<lyra_ecs::World>) { } + fn apply_deferred<'state>(_: &'state mut Self::State, _: std::ptr::NonNull<lyra_ecs::World>) { } } impl<T: Event> FnArgFetcher for EventWriter<T> { @@ -209,8 +222,10 @@ impl<T: Event> FnArgFetcher for EventWriter<T> { let world = world.as_ref(); let events = world.get_resource::<Events<T>>() .unwrap_or_else(|| panic!("world missing Events<{}> resource", std::any::type_name::<T>())); - events.writer() + EventWriter { + events: events.events.clone(), + } } - fn apply_deferred(_: Self::State, _: std::ptr::NonNull<lyra_ecs::World>) { } + fn apply_deferred<'state>(_: &'state mut Self::State, _: std::ptr::NonNull<lyra_ecs::World>) { } } \ No newline at end of file diff --git a/crates/lyra-game/src/input/action.rs b/crates/lyra-game/src/input/action.rs index 7189834..1ad1db2 100644 --- a/crates/lyra-game/src/input/action.rs +++ b/crates/lyra-game/src/input/action.rs @@ -493,7 +493,7 @@ impl ActionHandlerBuilder { //fn actions_system(world: &mut World) -> anyhow::Result<()> { fn actions_system( input_btns: Res<InputButtons<KeyCode>>, - mouse_ev: EventReader<MouseMotion>, + mut mouse_ev: EventReader<MouseMotion>, mut handler: ResMut<ActionHandler>, ) -> anyhow::Result<()> { // clear the states of all axises each frame diff --git a/crates/lyra-game/src/input/system.rs b/crates/lyra-game/src/input/system.rs index de54581..ee17c40 100755 --- a/crates/lyra-game/src/input/system.rs +++ b/crates/lyra-game/src/input/system.rs @@ -1,5 +1,3 @@ -use std::ops::Deref; - use glam::Vec2; use lyra_ecs::query::ResMut; use winit::{event::{MouseScrollDelta, WindowEvent}, keyboard::PhysicalKey}; @@ -31,8 +29,8 @@ pub fn input_system( mut key_code_res: ResMut<InputButtons<KeyCode>>, mut mouse_btn_res: ResMut<InputButtons<MouseButton>>, mut touches_res: ResMut<Touches>, - window_ev: EventReader<WindowEvent>, - device_ev: EventReader<DeviceEventPair>, + mut window_ev: EventReader<WindowEvent>, + mut device_ev: EventReader<DeviceEventPair>, mut mouse_scroll_ev: EventWriter<MouseScroll>, mouse_btn_ev: EventWriter<MouseButton>, mouse_exact_ev: EventWriter<MouseExact>, @@ -41,7 +39,7 @@ pub fn input_system( mouse_motion_ev: EventWriter<MouseMotion>, ) -> anyhow::Result<()> { while let Some(event) = window_ev.read() { - match event.deref() { + match event { WindowEvent::KeyboardInput { event, .. } => { write_key_event(&mut key_code_res, event.physical_key, event.state); }, @@ -59,7 +57,7 @@ pub fn input_system( mouse_left_ev.write(CursorLeftWindow); }, WindowEvent::MouseWheel { delta, .. } => { - write_scroll_delta(&mut mouse_scroll_ev, delta); + write_scroll_delta(&mut mouse_scroll_ev, &delta); }, WindowEvent::MouseInput { button, state, .. } => { let button_event = match button { @@ -68,11 +66,11 @@ pub fn input_system( winit::event::MouseButton::Middle => MouseButton::Middle, winit::event::MouseButton::Back => MouseButton::Back, winit::event::MouseButton::Forward => MouseButton::Forward, - winit::event::MouseButton::Other(v) => MouseButton::Other(*v), + winit::event::MouseButton::Other(v) => MouseButton::Other(v), }; mouse_btn_ev.write(button_event); - mouse_btn_res.add_input_from_winit(button_event, *state); + mouse_btn_res.add_input_from_winit(button_event, state); }, WindowEvent::Touch(t) => { let touch = Touch { diff --git a/examples/shadows/src/main.rs b/examples/shadows/src/main.rs index ef71fc3..0a73d61 100644 --- a/examples/shadows/src/main.rs +++ b/examples/shadows/src/main.rs @@ -1,6 +1,6 @@ use lyra_engine::{ assets::ResourceManager, - game::App, + game::{App, GameStages}, gltf::Gltf, input::{ Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource, @@ -12,9 +12,7 @@ use lyra_engine::{ light::{directional::DirectionalLight, SpotLight}, }, scene::{ - CameraBundle, FreeFly3dCamera, FreeFlyCameraPlugin, WorldTransform, ACTLBL_LOOK_LEFT_RIGHT, - ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN, ACTLBL_MOVE_FORWARD_BACKWARD, - ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN, + system_update_world_transforms, CameraBundle, FreeFly3dCamera, FreeFlyCameraPlugin, WorldTransform, ACTLBL_LOOK_LEFT_RIGHT, ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN, ACTLBL_MOVE_FORWARD_BACKWARD, ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN }, }; @@ -90,11 +88,17 @@ async fn main() { }; let mut app = App::new(); - app.with_plugin(lyra_engine::DefaultPlugins); - app.with_plugin(setup_scene_plugin); - app.with_plugin(action_handler_plugin); - //app.with_plugin(camera_debug_plugin) - app.with_plugin(FreeFlyCameraPlugin); + app.with_plugin(lyra_engine::DefaultPlugins) + .with_plugin(setup_scene_plugin) + .with_plugin(action_handler_plugin) + .add_system_to_stage( + GameStages::Last, + "update_world_transforms", + system_update_world_transforms, + &[], + ) + //.with_plugin(camera_debug_plugin) + .with_plugin(FreeFlyCameraPlugin); app.run(); } @@ -120,7 +124,7 @@ fn setup_scene_plugin(app: &mut App) { .request::<Gltf>("../assets/shadows-platform-palmtree.glb") .unwrap(); - palm_tree_platform_gltf.wait_recurse_dependencies_load(); + palm_tree_platform_gltf.wait_recurse_dependencies_load().unwrap(); let palm_tree_platform_mesh = &palm_tree_platform_gltf.data_ref().unwrap().scenes[0]; drop(resman); @@ -236,6 +240,12 @@ fn setup_scene_plugin(app: &mut App) { )); } + /* world.spawn(( + CameraBundle::default(), + Transform::from_xyz(0.0, 0.0, -5.5), + FreeFly3dCamera::default(), + )); */ + let mut pos = Transform::from_xyz(-1.0, -10.0, -1.5); pos.rotate_x(math::Angle::Degrees(-27.0)); pos.rotate_y(math::Angle::Degrees(-90.0));