From 24d7c09a12ec93da86fb69200f5f745d2757eb51 Mon Sep 17 00:00:00 2001 From: Alice Date: Mon, 13 Jun 2022 18:25:40 -0400 Subject: [PATCH] Derive resource everywhere --- crates/bevy_app/src/ci_testing.rs | 3 +- crates/bevy_app/src/schedule_runner.rs | 3 +- crates/bevy_ecs/examples/change_detection.rs | 2 +- crates/bevy_ecs/examples/resources.rs | 2 +- crates/bevy_ecs/src/component.rs | 2 +- crates/bevy_ecs/src/event.rs | 4 +- crates/bevy_ecs/src/lib.rs | 85 +++++---- .../src/schedule/executor_parallel.rs | 10 +- crates/bevy_ecs/src/schedule/stage.rs | 175 +++++++++--------- crates/bevy_ecs/src/schedule/state.rs | 99 +++++----- crates/bevy_ecs/src/system/commands/mod.rs | 18 +- .../bevy_ecs/src/system/exclusive_system.rs | 28 +-- crates/bevy_ecs/src/system/mod.rs | 108 +++++++---- crates/bevy_ecs/src/system/system_param.rs | 1 + crates/bevy_ecs/src/world/mod.rs | 3 +- crates/bevy_ecs/src/world/world_cell.rs | 66 ++++--- 16 files changed, 341 insertions(+), 268 deletions(-) diff --git a/crates/bevy_app/src/ci_testing.rs b/crates/bevy_app/src/ci_testing.rs index 66206d91095c3..17d8d929d6a4c 100644 --- a/crates/bevy_app/src/ci_testing.rs +++ b/crates/bevy_app/src/ci_testing.rs @@ -1,6 +1,7 @@ use crate::{app::AppExit, App}; use serde::Deserialize; +use bevy_ecs::prelude::Resource; use bevy_utils::tracing::info; /// A configuration struct for automated CI testing. @@ -8,7 +9,7 @@ use bevy_utils::tracing::info; /// It gets used when the `bevy_ci_testing` feature is enabled to automatically /// exit a Bevy app when run through the CI. This is needed because otherwise /// Bevy apps would be stuck in the game loop and wouldn't allow the CI to progress. -#[derive(Deserialize)] +#[derive(Deserialize, Resource)] pub struct CiTestingConfig { /// The number of frames after which Bevy should exit. pub exit_after: Option, diff --git a/crates/bevy_app/src/schedule_runner.rs b/crates/bevy_app/src/schedule_runner.rs index aa63ce1a8b3d0..04535c045dd9d 100644 --- a/crates/bevy_app/src/schedule_runner.rs +++ b/crates/bevy_app/src/schedule_runner.rs @@ -3,6 +3,7 @@ use crate::{ plugin::Plugin, }; use bevy_ecs::event::{Events, ManualEventReader}; +use bevy_ecs::prelude::Resource; use bevy_utils::{Duration, Instant}; #[cfg(target_arch = "wasm32")] @@ -34,7 +35,7 @@ impl Default for RunMode { /// The configuration information for the [`ScheduleRunnerPlugin`]. /// /// It gets added as a [`Resource`](bevy_ecs::system::Resource) inside of the [`ScheduleRunnerPlugin`]. -#[derive(Copy, Clone, Default)] +#[derive(Copy, Clone, Default, Resource)] pub struct ScheduleRunnerSettings { /// Determines whether the [`Schedule`](bevy_ecs::schedule::Schedule) is run once or repeatedly. pub run_mode: RunMode, diff --git a/crates/bevy_ecs/examples/change_detection.rs b/crates/bevy_ecs/examples/change_detection.rs index 1a3e135b654e2..1f2af2e35c812 100644 --- a/crates/bevy_ecs/examples/change_detection.rs +++ b/crates/bevy_ecs/examples/change_detection.rs @@ -40,7 +40,7 @@ fn main() { } // This struct will be used as a Resource keeping track of the total amount of spawned entities -#[derive(Debug)] +#[derive(Debug, Resource)] struct EntityCounter { pub value: i32, } diff --git a/crates/bevy_ecs/examples/resources.rs b/crates/bevy_ecs/examples/resources.rs index c6700a6b9ed9d..3127f52d90732 100644 --- a/crates/bevy_ecs/examples/resources.rs +++ b/crates/bevy_ecs/examples/resources.rs @@ -27,7 +27,7 @@ fn main() { } // Counter resource to be increased and read by systems -#[derive(Debug)] +#[derive(Debug, Resource)] struct Counter { pub value: i32, } diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index fdcb2a0d0d974..c5f6b1793d996 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -1,6 +1,6 @@ //! Types for declaring and storing [`Component`]s. -use crate::{ +pub use crate::{ change_detection::MAX_CHANGE_AGE, storage::{SparseSetIndex, Storages}, system::Resource, diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index 22af1b3ed2dff..33b94c3926804 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -1,7 +1,7 @@ //! Event handling types. use crate as bevy_ecs; -use crate::system::{Local, Res, ResMut, SystemParam}; +use crate::system::{Local, Res, ResMut, SystemParam, Resource}; use bevy_utils::tracing::trace; use std::ops::{Deref, DerefMut}; use std::{ @@ -128,7 +128,7 @@ struct EventInstance { /// [Example usage.](https://github.com/bevyengine/bevy/blob/latest/examples/ecs/event.rs) /// [Example usage standalone.](https://github.com/bevyengine/bevy/blob/latest/bevy_ecs/examples/events.rs) /// -#[derive(Debug)] +#[derive(Debug, Resource)] pub struct Events { /// Holds the oldest still active events. /// Note that a.start_event_count + a.len() should always === events_b.start_event_count. diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index 66d1d250ceb9d..faf6995d732f8 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -57,6 +57,7 @@ mod tests { component::{Component, ComponentId}, entity::Entity, query::{Added, ChangeTrackers, Changed, FilteredAccess, With, Without, WorldQuery}, + system::Resource, world::{Mut, World}, }; use bevy_tasks::{ComputeTaskPool, TaskPool}; @@ -68,7 +69,7 @@ mod tests { }, }; - #[derive(Component, Debug, PartialEq, Eq, Clone, Copy)] + #[derive(Component, Resource, Debug, PartialEq, Eq, Clone, Copy)] struct A(usize); #[derive(Component, Debug, PartialEq, Eq, Clone, Copy)] struct B(usize); @@ -1002,16 +1003,24 @@ mod tests { #[test] fn resource() { + use crate::system::Resource; + + #[derive(Resource, PartialEq, Debug)] + struct Num(i32); + + #[derive(Resource, PartialEq, Debug)] + struct BigNum(u64); + let mut world = World::default(); - assert!(world.get_resource::().is_none()); - assert!(!world.contains_resource::()); - assert!(!world.is_resource_added::()); - assert!(!world.is_resource_changed::()); + assert!(world.get_resource::().is_none()); + assert!(!world.contains_resource::()); + assert!(!world.is_resource_added::()); + assert!(!world.is_resource_changed::()); - world.insert_resource(123); + world.insert_resource(Num(123)); let resource_id = world .components() - .get_resource_id(TypeId::of::()) + .get_resource_id(TypeId::of::()) .unwrap(); let archetype_component_id = world .archetypes() @@ -1019,61 +1028,61 @@ mod tests { .get_archetype_component_id(resource_id) .unwrap(); - assert_eq!(*world.resource::(), 123); - assert!(world.contains_resource::()); - assert!(world.is_resource_added::()); - assert!(world.is_resource_changed::()); + assert_eq!(world.resource::().0, 123); + assert!(world.contains_resource::()); + assert!(world.is_resource_added::()); + assert!(world.is_resource_changed::()); - world.insert_resource(456u64); - assert_eq!(*world.resource::(), 456u64); + world.insert_resource(BigNum(456)); + assert_eq!(world.resource::().0, 456u64); - world.insert_resource(789u64); - assert_eq!(*world.resource::(), 789); + world.insert_resource(BigNum(789)); + assert_eq!(world.resource::().0, 789); { - let mut value = world.resource_mut::(); - assert_eq!(*value, 789); - *value = 10; + let mut value = world.resource_mut::(); + assert_eq!(value.0, 789); + value.0 = 10; } assert_eq!( - world.resource::(), - &10, + world.resource::().0, + 10, "resource changes are preserved" ); assert_eq!( - world.remove_resource::(), - Some(10), + world.remove_resource::(), + Some(BigNum(10)), "removed resource has the correct value" ); assert_eq!( - world.get_resource::(), + world.get_resource::(), None, "removed resource no longer exists" ); assert_eq!( - world.remove_resource::(), + world.remove_resource::(), None, "double remove returns nothing" ); - world.insert_resource(1u64); + world.insert_resource(BigNum(1)); assert_eq!( - world.get_resource::(), - Some(&1u64), + world.get_resource::(), + Some(&BigNum(1)), "re-inserting resources works" ); assert_eq!( - world.get_resource::(), - Some(&123), + world.get_resource::(), + Some(&Num(123)), "other resources are unaffected" ); let current_resource_id = world .components() - .get_resource_id(TypeId::of::()) + .get_resource_id(TypeId::of::()) .unwrap(); assert_eq!( resource_id, current_resource_id, @@ -1119,7 +1128,7 @@ mod tests { assert_eq!( e.get::(), None, - "i32 is in the removed bundle, so it should not exist" + "Num is in the removed bundle, so it should not exist" ); assert_eq!( e.get::(), @@ -1324,12 +1333,12 @@ mod tests { #[test] fn resource_scope() { let mut world = World::default(); - world.insert_resource::(0); - world.resource_scope(|world: &mut World, mut value: Mut| { - *value += 1; - assert!(!world.contains_resource::()); + world.insert_resource(A(0)); + world.resource_scope(|world: &mut World, mut value: Mut| { + value.0 += 1; + assert!(!world.contains_resource::()); }); - assert_eq!(*world.resource::(), 1); + assert_eq!(world.resource::().0, 1); } #[test] @@ -1366,7 +1375,7 @@ mod tests { fn clear_entities() { let mut world = World::default(); - world.insert_resource::(0); + world.insert_resource(A(0)); world.spawn().insert(A(1)); world.spawn().insert(SparseStored(1)); @@ -1395,7 +1404,7 @@ mod tests { "world should not have any entities" ); assert_eq!( - *world.resource::(), + world.resource::().0, 0, "world should still contain resources" ); diff --git a/crates/bevy_ecs/src/schedule/executor_parallel.rs b/crates/bevy_ecs/src/schedule/executor_parallel.rs index c82924b0e276c..7367b6ab2911e 100644 --- a/crates/bevy_ecs/src/schedule/executor_parallel.rs +++ b/crates/bevy_ecs/src/schedule/executor_parallel.rs @@ -324,8 +324,12 @@ mod tests { use crate as bevy_ecs; use crate::component::Component; + use crate::system::Resource; + #[derive(Component)] struct W(T); + #[derive(Resource, Default)] + struct Counter(usize); fn receive_events(world: &World) -> Vec { let mut events = Vec::new(); @@ -354,9 +358,9 @@ mod tests { #[test] fn resources() { let mut world = World::new(); - world.insert_resource(0usize); - fn wants_mut(_: ResMut) {} - fn wants_ref(_: Res) {} + world.init_resource::(); + fn wants_mut(_: ResMut) {} + fn wants_ref(_: Res) {} let mut stage = SystemStage::parallel() .with_system(wants_mut) .with_system(wants_mut); diff --git a/crates/bevy_ecs/src/schedule/stage.rs b/crates/bevy_ecs/src/schedule/stage.rs index ff26ced892a6f..d1ca79358bca8 100644 --- a/crates/bevy_ecs/src/schedule/stage.rs +++ b/crates/bevy_ecs/src/schedule/stage.rs @@ -958,15 +958,22 @@ mod tests { use crate as bevy_ecs; use crate::component::Component; + use crate::system::Resource; + #[derive(Component)] struct W(T); + #[derive(Resource)] + struct R(usize); + + #[derive(Resource, Default)] + struct EntityCount(Vec); fn make_exclusive(tag: usize) -> impl FnMut(&mut World) { - move |world| world.resource_mut::>().push(tag) + move |world| world.resource_mut::().0.push(tag) } - fn make_parallel(tag: usize) -> impl FnMut(ResMut>) { - move |mut resource: ResMut>| resource.push(tag) + fn make_parallel(tag: usize) -> impl FnMut(ResMut) { + move |mut resource: ResMut| resource.0.push(tag) } fn every_other_time(mut has_ran: Local) -> ShouldRun { @@ -981,48 +988,48 @@ mod tests { #[test] fn insertion_points() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(0).exclusive_system().at_start()) .with_system(make_parallel(1)) .with_system(make_exclusive(2).exclusive_system().before_commands()) .with_system(make_exclusive(3).exclusive_system().at_end()); stage.run(&mut world); - assert_eq!(*world.resource_mut::>(), vec![0, 1, 2, 3]); + assert_eq!(world.resource_mut::().0, vec![0, 1, 2, 3]); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 0, 1, 2, 3] ); - world.resource_mut::>().clear(); + world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(2).exclusive_system().before_commands()) .with_system(make_exclusive(3).exclusive_system().at_end()) .with_system(make_parallel(1)) .with_system(make_exclusive(0).exclusive_system().at_start()); stage.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 1, 2, 3]); + assert_eq!(world.resource::().0, vec![0, 1, 2, 3]); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 0, 1, 2, 3] ); - world.resource_mut::>().clear(); + world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() .with_system(make_parallel(2).exclusive_system().before_commands()) .with_system(make_parallel(3).exclusive_system().at_end()) .with_system(make_parallel(1)) .with_system(make_parallel(0).exclusive_system().at_start()); stage.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 1, 2, 3]); + assert_eq!(world.resource::().0, vec![0, 1, 2, 3]); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 0, 1, 2, 3] ); } @@ -1030,7 +1037,7 @@ mod tests { #[test] fn exclusive_after() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(1).exclusive_system().label("1").after("0")) .with_system(make_exclusive(2).exclusive_system().after("1")) @@ -1038,13 +1045,13 @@ mod tests { stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 1, 2, 0, 1, 2]); + assert_eq!(world.resource::().0, vec![0, 1, 2, 0, 1, 2]); } #[test] fn exclusive_before() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(1).exclusive_system().label("1").before("2")) .with_system(make_exclusive(2).exclusive_system().label("2")) @@ -1052,13 +1059,13 @@ mod tests { stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 1, 2, 0, 1, 2]); + assert_eq!(world.resource::().0, vec![0, 1, 2, 0, 1, 2]); } #[test] fn exclusive_mixed() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(2).exclusive_system().label("2")) .with_system(make_exclusive(1).exclusive_system().after("0").before("2")) @@ -1069,7 +1076,7 @@ mod tests { stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 4, 0, 1, 2, 3, 4] ); } @@ -1077,7 +1084,7 @@ mod tests { #[test] fn exclusive_multiple_labels() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system( make_exclusive(1) @@ -1095,9 +1102,9 @@ mod tests { stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 1, 2, 0, 1, 2]); + assert_eq!(world.resource::().0, vec![0, 1, 2, 0, 1, 2]); - world.resource_mut::>().clear(); + world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(2).exclusive_system().after("01").label("2")) .with_system(make_exclusive(1).exclusive_system().label("01").after("0")) @@ -1108,11 +1115,11 @@ mod tests { stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 4, 0, 1, 2, 3, 4] ); - world.resource_mut::>().clear(); + world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(2).exclusive_system().label("234").label("2")) .with_system( @@ -1134,7 +1141,7 @@ mod tests { stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 4, 0, 1, 2, 3, 4] ); } @@ -1142,7 +1149,7 @@ mod tests { #[test] fn exclusive_redundant_constraints() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system( make_exclusive(2) @@ -1173,7 +1180,7 @@ mod tests { stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 4, 0, 1, 2, 3, 4] ); } @@ -1181,7 +1188,7 @@ mod tests { #[test] fn exclusive_mixed_across_sets() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(2).exclusive_system().label("2")) .with_system_set( @@ -1195,7 +1202,7 @@ mod tests { stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 4, 0, 1, 2, 3, 4] ); } @@ -1203,7 +1210,7 @@ mod tests { #[test] fn exclusive_run_criteria() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(0).exclusive_system().before("1")) .with_system_set( @@ -1218,7 +1225,7 @@ mod tests { stage.run(&mut world); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 0, 2, 0, 1, 2, 0, 2] ); } @@ -1227,7 +1234,7 @@ mod tests { #[should_panic] fn exclusive_cycle_1() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(0).exclusive_system().label("0").after("0")); stage.run(&mut world); @@ -1237,7 +1244,7 @@ mod tests { #[should_panic] fn exclusive_cycle_2() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(0).exclusive_system().label("0").after("1")) .with_system(make_exclusive(1).exclusive_system().label("1").after("0")); @@ -1248,7 +1255,7 @@ mod tests { #[should_panic] fn exclusive_cycle_3() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_exclusive(0).exclusive_system().label("0")) .with_system(make_exclusive(1).exclusive_system().after("0").before("2")) @@ -1259,7 +1266,7 @@ mod tests { #[test] fn parallel_after() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_parallel(1).after("0").label("1")) .with_system(make_parallel(2).after("1")) @@ -1267,13 +1274,13 @@ mod tests { stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 1, 2, 0, 1, 2]); + assert_eq!(world.resource::().0, vec![0, 1, 2, 0, 1, 2]); } #[test] fn parallel_before() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_parallel(1).label("1").before("2")) .with_system(make_parallel(2).label("2")) @@ -1281,13 +1288,13 @@ mod tests { stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 1, 2, 0, 1, 2]); + assert_eq!(world.resource::().0, vec![0, 1, 2, 0, 1, 2]); } #[test] fn parallel_mixed() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_parallel(2).label("2")) .with_system(make_parallel(1).after("0").before("2")) @@ -1298,7 +1305,7 @@ mod tests { stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 4, 0, 1, 2, 3, 4] ); } @@ -1306,7 +1313,7 @@ mod tests { #[test] fn parallel_multiple_labels() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_parallel(1).label("first").after("0")) .with_system(make_parallel(2).after("first")) @@ -1314,9 +1321,9 @@ mod tests { stage.run(&mut world); stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 1, 2, 0, 1, 2]); + assert_eq!(world.resource::().0, vec![0, 1, 2, 0, 1, 2]); - world.resource_mut::>().clear(); + world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() .with_system(make_parallel(2).after("01").label("2")) .with_system(make_parallel(1).label("01").after("0")) @@ -1327,11 +1334,11 @@ mod tests { stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 4, 0, 1, 2, 3, 4] ); - world.resource_mut::>().clear(); + world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() .with_system(make_parallel(2).label("234").label("2")) .with_system(make_parallel(1).before("234").after("0")) @@ -1342,7 +1349,7 @@ mod tests { stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 4, 0, 1, 2, 3, 4] ); } @@ -1350,7 +1357,7 @@ mod tests { #[test] fn parallel_redundant_constraints() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system( make_parallel(2) @@ -1376,7 +1383,7 @@ mod tests { stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 4, 0, 1, 2, 3, 4] ); } @@ -1384,7 +1391,7 @@ mod tests { #[test] fn parallel_mixed_across_sets() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_parallel(2).label("2")) .with_system_set( @@ -1398,7 +1405,7 @@ mod tests { stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 4, 0, 1, 2, 3, 4] ); } @@ -1407,7 +1414,7 @@ mod tests { fn parallel_run_criteria() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system( make_parallel(0) @@ -1420,9 +1427,9 @@ mod tests { stage.set_executor(Box::new(SingleThreadedExecutor::default())); stage.run(&mut world); stage.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 1, 1, 0, 1, 1]); + assert_eq!(world.resource::().0, vec![0, 1, 1, 0, 1, 1]); - world.resource_mut::>().clear(); + world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() .with_system(make_parallel(0).before("1")) .with_system_set( @@ -1437,12 +1444,12 @@ mod tests { stage.run(&mut world); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 0, 2, 0, 1, 2, 0, 2] ); // Reusing criteria. - world.resource_mut::>().clear(); + world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() .with_system_run_criteria(every_other_time.label("every other time")) .with_system(make_parallel(0).before("1")) @@ -1464,13 +1471,13 @@ mod tests { stage.run(&mut world); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 0, 3, 0, 1, 2, 3, 0, 3] ); assert_eq!(stage.run_criteria.len(), 1); // Piping criteria. - world.resource_mut::>().clear(); + world.resource_mut::().0.clear(); fn eot_piped(input: In, has_ran: Local) -> ShouldRun { if let ShouldRun::Yes | ShouldRun::YesAndCheckAgain = input.0 { every_other_time(has_ran) @@ -1505,13 +1512,13 @@ mod tests { stage.run(&mut world); } assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 4, 0, 0, 1, 0, 0, 1, 2, 3, 4, 0, 0, 1, 0, 0, 1, 2, 3, 4] ); assert_eq!(stage.run_criteria.len(), 3); // Discarding extra criteria with matching labels. - world.resource_mut::>().clear(); + world.resource_mut::().0.clear(); let mut stage = SystemStage::parallel() .with_system(make_parallel(0).before("1")) @@ -1528,7 +1535,7 @@ mod tests { stage.run(&mut world); stage.run(&mut world); assert_eq!( - *world.resource::>(), + world.resource::().0, vec![0, 1, 2, 3, 0, 3, 0, 1, 2, 3, 0, 3] ); assert_eq!(stage.run_criteria.len(), 1); @@ -1548,7 +1555,7 @@ mod tests { #[should_panic] fn parallel_cycle_1() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel().with_system(make_parallel(0).label("0").after("0")); stage.run(&mut world); } @@ -1557,7 +1564,7 @@ mod tests { #[should_panic] fn parallel_cycle_2() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_parallel(0).label("0").after("1")) .with_system(make_parallel(1).label("1").after("0")); @@ -1569,7 +1576,7 @@ mod tests { fn parallel_cycle_3() { let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(make_parallel(0).label("0")) .with_system(make_parallel(1).after("0").before("2")) @@ -1606,7 +1613,7 @@ mod tests { } fn empty() {} - fn resource(_: ResMut) {} + fn resource(_: ResMut) {} fn component(_: Query<&mut W>) {} let mut world = World::new(); @@ -1976,47 +1983,41 @@ mod tests { #[test] fn archetype_update_single_executor() { - fn query_count_system( - mut entity_count: ResMut, - query: Query, - ) { - *entity_count = query.iter().count(); + fn query_count_system(mut entity_count: ResMut, query: Query) { + *entity_count = R(query.iter().count()); } let mut world = World::new(); - world.insert_resource(0_usize); + world.insert_resource(R(0)); let mut stage = SystemStage::single(query_count_system); let entity = world.spawn().insert_bundle(()).id(); stage.run(&mut world); - assert_eq!(*world.resource::(), 1); + assert_eq!(world.resource::().0, 1); world.get_entity_mut(entity).unwrap().insert(W(1)); stage.run(&mut world); - assert_eq!(*world.resource::(), 1); + assert_eq!(world.resource::().0, 1); } #[test] fn archetype_update_parallel_executor() { - fn query_count_system( - mut entity_count: ResMut, - query: Query, - ) { - *entity_count = query.iter().count(); + fn query_count_system(mut entity_count: ResMut, query: Query) { + *entity_count = R(query.iter().count()); } let mut world = World::new(); - world.insert_resource(0_usize); + world.insert_resource(R(0)); let mut stage = SystemStage::parallel(); stage.add_system(query_count_system); let entity = world.spawn().insert_bundle(()).id(); stage.run(&mut world); - assert_eq!(*world.resource::(), 1); + assert_eq!(world.resource::().0, 1); world.get_entity_mut(entity).unwrap().insert(W(1)); stage.run(&mut world); - assert_eq!(*world.resource::(), 1); + assert_eq!(world.resource::().0, 1); } #[test] @@ -2038,12 +2039,12 @@ mod tests { commands.spawn().insert(Foo); } - fn count_entities(query: Query<&Foo>, mut res: ResMut>) { - res.push(query.iter().len()); + fn count_entities(query: Query<&Foo>, mut res: ResMut) { + res.0.push(query.iter().len()); } let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(spawn_entity.label("spawn")) .with_system_set( @@ -2055,7 +2056,7 @@ mod tests { stage.run(&mut world); stage.run(&mut world); stage.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 2]); + assert_eq!(world.resource::().0, vec![0, 2]); } #[test] @@ -2077,12 +2078,12 @@ mod tests { commands.spawn().insert(Foo); } - fn count_entities(query: Query<&Foo>, mut res: ResMut>) { - res.push(query.iter().len()); + fn count_entities(query: Query<&Foo>, mut res: ResMut) { + res.0.push(query.iter().len()); } let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage_spawn = SystemStage::parallel().with_system(spawn_entity); let mut stage_count = SystemStage::parallel() .with_run_criteria(even_number_of_entities_critiera) @@ -2095,6 +2096,6 @@ mod tests { stage_spawn.run(&mut world); stage_count.run(&mut world); stage_spawn.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 2]); + assert_eq!(world.resource::().0, vec![0, 2]); } } diff --git a/crates/bevy_ecs/src/schedule/state.rs b/crates/bevy_ecs/src/schedule/state.rs index 1693f0adce7e3..6b6a84a1008c7 100644 --- a/crates/bevy_ecs/src/schedule/state.rs +++ b/crates/bevy_ecs/src/schedule/state.rs @@ -3,13 +3,15 @@ use crate::{ RunCriteriaDescriptor, RunCriteriaDescriptorCoercion, RunCriteriaLabel, ShouldRun, SystemSet, }, - system::{In, IntoChainSystem, Local, Res, ResMut}, + system::{In, IntoChainSystem, Local, Res, ResMut, Resource}, }; use std::{ any::TypeId, fmt::{self, Debug}, hash::Hash, }; +// Required for derive macros +use crate as bevy_ecs; pub trait StateData: Send + Sync + Clone + Eq + Debug + Hash + 'static {} impl StateData for T where T: Send + Sync + Clone + Eq + Debug + Hash + 'static {} @@ -21,7 +23,7 @@ impl StateData for T where T: Send + Sync + Clone + Eq + Debug + Hash + 'stat /// * Pop removes the current state, and unpauses the last paused state /// * Set replaces the active state with a new one /// * Replace unwinds the state stack, and replaces the entire stack with a single new state -#[derive(Debug)] +#[derive(Debug, Resource)] pub struct State { transition: Option>, /// The current states in the stack. @@ -531,9 +533,12 @@ mod test { #[test] fn state_test() { + #[derive(Resource, Default)] + struct NameList(Vec<&'static str>); + let mut world = World::default(); - world.insert_resource(Vec::<&'static str>::new()); + world.init_resource::(); world.insert_resource(State::new(MyState::S1)); let mut stage = SystemStage::parallel(); @@ -542,55 +547,55 @@ mod test { stage .add_system_set( State::on_enter_set(MyState::S1) - .with_system(|mut r: ResMut>| r.push("startup")), + .with_system(|mut r: ResMut| r.0.push("startup")), ) .add_system_set(State::on_update_set(MyState::S1).with_system( - |mut r: ResMut>, mut s: ResMut>| { - r.push("update S1"); + |mut r: ResMut, mut s: ResMut>| { + r.0.push("update S1"); s.overwrite_replace(MyState::S2).unwrap(); }, )) .add_system_set( State::on_enter_set(MyState::S2) - .with_system(|mut r: ResMut>| r.push("enter S2")), + .with_system(|mut r: ResMut| r.0.push("enter S2")), ) .add_system_set(State::on_update_set(MyState::S2).with_system( - |mut r: ResMut>, mut s: ResMut>| { - r.push("update S2"); + |mut r: ResMut, mut s: ResMut>| { + r.0.push("update S2"); s.overwrite_replace(MyState::S3).unwrap(); }, )) .add_system_set( State::on_exit_set(MyState::S2) - .with_system(|mut r: ResMut>| r.push("exit S2")), + .with_system(|mut r: ResMut| r.0.push("exit S2")), ) .add_system_set( State::on_enter_set(MyState::S3) - .with_system(|mut r: ResMut>| r.push("enter S3")), + .with_system(|mut r: ResMut| r.0.push("enter S3")), ) .add_system_set(State::on_update_set(MyState::S3).with_system( - |mut r: ResMut>, mut s: ResMut>| { - r.push("update S3"); + |mut r: ResMut, mut s: ResMut>| { + r.0.push("update S3"); s.overwrite_push(MyState::S4).unwrap(); }, )) .add_system_set( State::on_pause_set(MyState::S3) - .with_system(|mut r: ResMut>| r.push("pause S3")), + .with_system(|mut r: ResMut| r.0.push("pause S3")), ) .add_system_set(State::on_update_set(MyState::S4).with_system( - |mut r: ResMut>, mut s: ResMut>| { - r.push("update S4"); + |mut r: ResMut, mut s: ResMut>| { + r.0.push("update S4"); s.overwrite_push(MyState::S5).unwrap(); }, )) .add_system_set(State::on_inactive_update_set(MyState::S4).with_system( - (|mut r: ResMut>| r.push("inactive S4")).label("inactive s4"), + (|mut r: ResMut| r.0.push("inactive S4")).label("inactive s4"), )) .add_system_set( State::on_update_set(MyState::S5).with_system( - (|mut r: ResMut>, mut s: ResMut>| { - r.push("update S5"); + (|mut r: ResMut, mut s: ResMut>| { + r.0.push("update S5"); s.overwrite_push(MyState::S6).unwrap(); }) .after("inactive s4"), @@ -598,15 +603,15 @@ mod test { ) .add_system_set( State::on_inactive_update_set(MyState::S5).with_system( - (|mut r: ResMut>| r.push("inactive S5")) + (|mut r: ResMut| r.0.push("inactive S5")) .label("inactive s5") .after("inactive s4"), ), ) .add_system_set( State::on_update_set(MyState::S6).with_system( - (|mut r: ResMut>, mut s: ResMut>| { - r.push("update S6"); + (|mut r: ResMut, mut s: ResMut>| { + r.0.push("update S6"); s.overwrite_push(MyState::Final).unwrap(); }) .after("inactive s5"), @@ -614,11 +619,11 @@ mod test { ) .add_system_set( State::on_resume_set(MyState::S4) - .with_system(|mut r: ResMut>| r.push("resume S4")), + .with_system(|mut r: ResMut| r.0.push("resume S4")), ) .add_system_set( State::on_exit_set(MyState::S5) - .with_system(|mut r: ResMut>| r.push("exit S4")), + .with_system(|mut r: ResMut| r.0.push("exit S4")), ); const EXPECTED: &[&str] = &[ @@ -648,9 +653,9 @@ mod test { ]; stage.run(&mut world); - let mut collected = world.resource_mut::>(); + let mut collected = world.resource_mut::(); let mut count = 0; - for (found, expected) in collected.drain(..).zip(EXPECTED) { + for (found, expected) in collected.0.drain(..).zip(EXPECTED) { assert_eq!(found, *expected); count += 1; } @@ -669,26 +674,32 @@ mod test { Main, } - fn should_run_once(mut flag: ResMut, test_name: Res<&'static str>) { - assert!(!*flag, "{:?}", *test_name); - *flag = true; + #[derive(Resource)] + struct Flag(bool); + + #[derive(Resource)] + struct Name(&'static str); + + fn should_run_once(mut flag: ResMut, test_name: Res) { + assert!(!flag.0, "{:?}", test_name.0); + flag.0 = true; } let mut world = World::new(); world.insert_resource(State::new(AppState::Main)); - world.insert_resource(false); - world.insert_resource("control"); + world.insert_resource(Flag(false)); + world.insert_resource(Name("control")); let mut stage = SystemStage::parallel().with_system(should_run_once); stage.run(&mut world); - assert!(*world.resource::(), "after control"); + assert!(world.resource::().0, "after control"); - world.insert_resource(false); - world.insert_resource("test"); + world.insert_resource(Flag(false)); + world.insert_resource(Name("test")); let mut stage = SystemStage::parallel() .with_system_set(State::::get_driver()) .with_system(should_run_once); stage.run(&mut world); - assert!(*world.resource::(), "after test"); + assert!(world.resource::().0, "after test"); } #[test] @@ -706,8 +717,11 @@ mod test { EnterFinish, } + #[derive(Resource, Default)] + struct LoadStatusStack(Vec); + let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); world.insert_resource(State::new(LoadState::Load)); let mut stage = SystemStage::parallel(); @@ -717,15 +731,16 @@ mod test { stage .add_system_set( State::on_enter_set(LoadState::Load) - .with_system(|mut r: ResMut>| r.push(LoadStatus::EnterLoad)), + .with_system(|mut r: ResMut| r.0.push(LoadStatus::EnterLoad)), ) .add_system_set( State::on_exit_set(LoadState::Load) - .with_system(|mut r: ResMut>| r.push(LoadStatus::ExitLoad)), + .with_system(|mut r: ResMut| r.0.push(LoadStatus::ExitLoad)), ) .add_system_set( - State::on_enter_set(LoadState::Finish) - .with_system(|mut r: ResMut>| r.push(LoadStatus::EnterFinish)), + State::on_enter_set(LoadState::Finish).with_system( + |mut r: ResMut| r.0.push(LoadStatus::EnterFinish), + ), ); stage.run(&mut world); @@ -762,9 +777,9 @@ mod test { LoadStatus::EnterFinish, ]; - let mut collected = world.resource_mut::>(); + let mut collected = world.resource_mut::(); let mut count = 0; - for (found, expected) in collected.drain(..).zip(EXPECTED) { + for (found, expected) in collected.0.drain(..).zip(EXPECTED) { assert_eq!(found, *expected); count += 1; } diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index bf40e13fb98b1..d9af56557094f 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -799,7 +799,7 @@ mod tests { use crate::{ self as bevy_ecs, component::Component, - system::{CommandQueue, Commands}, + system::{CommandQueue, Commands, Resource}, world::World, }; use std::sync::{ @@ -826,7 +826,7 @@ mod tests { } } - #[derive(Component)] + #[derive(Component, Resource)] struct W(T); fn simple_command(world: &mut World) { @@ -937,21 +937,21 @@ mod tests { let mut queue = CommandQueue::default(); { let mut commands = Commands::new(&mut queue, &world); - commands.insert_resource(123); - commands.insert_resource(456.0); + commands.insert_resource(W(123i32)); + commands.insert_resource(W(456.0f64)); } queue.apply(&mut world); - assert!(world.contains_resource::()); - assert!(world.contains_resource::()); + assert!(world.contains_resource::>()); + assert!(world.contains_resource::>()); { let mut commands = Commands::new(&mut queue, &world); // test resource removal - commands.remove_resource::(); + commands.remove_resource::>(); } queue.apply(&mut world); - assert!(!world.contains_resource::()); - assert!(world.contains_resource::()); + assert!(!world.contains_resource::>()); + assert!(world.contains_resource::>()); } } diff --git a/crates/bevy_ecs/src/system/exclusive_system.rs b/crates/bevy_ecs/src/system/exclusive_system.rs index 46d2e9eb8c091..9cc166d257ea0 100644 --- a/crates/bevy_ecs/src/system/exclusive_system.rs +++ b/crates/bevy_ecs/src/system/exclusive_system.rs @@ -112,7 +112,7 @@ mod tests { entity::Entity, query::With, schedule::{Stage, SystemStage}, - system::{Commands, IntoExclusiveSystem, Query, ResMut}, + system::{Commands, IntoExclusiveSystem, Query, ResMut, Resource}, world::World, }; @@ -123,49 +123,55 @@ mod tests { fn parallel_with_commands_as_exclusive() { let mut world = World::new(); + #[derive(Resource)] + struct Counter(usize); + fn removal( mut commands: Commands, query: Query>, - mut counter: ResMut, + mut counter: ResMut, ) { for entity in query.iter() { - *counter += 1; + counter.0 += 1; commands.entity(entity).remove::(); } } let mut stage = SystemStage::parallel().with_system(removal); world.spawn().insert(Foo(0.0f32)); - world.insert_resource(0usize); + world.insert_resource(Counter(0)); stage.run(&mut world); stage.run(&mut world); - assert_eq!(*world.resource::(), 1); + assert_eq!(world.resource::().0, 1); let mut stage = SystemStage::parallel().with_system(removal.exclusive_system()); world.spawn().insert(Foo(0.0f32)); - world.insert_resource(0usize); + world.insert_resource(Counter(0)); stage.run(&mut world); stage.run(&mut world); - assert_eq!(*world.resource::(), 1); + assert_eq!(world.resource::().0, 1); } #[test] fn update_archetype_for_exclusive_system_coerced() { + #[derive(Resource, Default)] + struct CountEntities(Vec); + fn spawn_entity(mut commands: crate::prelude::Commands) { commands.spawn().insert(Foo(0.0)); } - fn count_entities(query: Query<&Foo>, mut res: ResMut>) { - res.push(query.iter().len()); + fn count_entities(query: Query<&Foo>, mut res: ResMut) { + res.0.push(query.iter().len()); } let mut world = World::new(); - world.insert_resource(Vec::::new()); + world.init_resource::(); let mut stage = SystemStage::parallel() .with_system(spawn_entity) .with_system(count_entities.exclusive_system()); stage.run(&mut world); stage.run(&mut world); - assert_eq!(*world.resource::>(), vec![0, 1]); + assert_eq!(world.resource::().0, vec![0, 1]); } } diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index 04d14f9afe652..2e97165ea4714 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -111,22 +111,28 @@ mod tests { schedule::{Schedule, Stage, SystemStage}, system::{ Commands, IntoExclusiveSystem, IntoSystem, Local, NonSend, NonSendMut, ParamSet, Query, - RemovedComponents, Res, ResMut, System, SystemState, + RemovedComponents, Res, ResMut, Resource, System, SystemState, }, world::{FromWorld, World}, }; - #[derive(Component, Debug, Eq, PartialEq, Default)] + #[derive(Resource, PartialEq, Debug)] + enum SystemRan { + Yes, + No, + } + + #[derive(Component, Resource, Debug, Eq, PartialEq, Default)] struct A; - #[derive(Component)] + #[derive(Component, Resource)] struct B; - #[derive(Component)] + #[derive(Component, Resource)] struct C; - #[derive(Component)] + #[derive(Component, Resource)] struct D; - #[derive(Component)] + #[derive(Component, Resource)] struct E; - #[derive(Component)] + #[derive(Component, Resource)] struct F; #[derive(Component)] @@ -159,7 +165,7 @@ mod tests { #[test] fn query_system_gets() { fn query_system( - mut ran: ResMut, + mut ran: ResMut, entity_query: Query>, b_query: Query<&B>, a_c_query: Query<(&A, &C)>, @@ -199,11 +205,11 @@ mod tests { "entity 3 should have D" ); - *ran = true; + *ran = SystemRan::Yes; } let mut world = World::default(); - world.insert_resource(false); + world.insert_resource(SystemRan::No); world.spawn().insert_bundle((A,)); world.spawn().insert_bundle((A, B)); world.spawn().insert_bundle((A, C)); @@ -211,14 +217,14 @@ mod tests { run_system(&mut world, query_system); - assert!(*world.resource::(), "system ran"); + assert_eq!(*world.resource::(), SystemRan::Yes); } #[test] fn or_param_set_system() { // Regression test for issue #762 fn query_system( - mut ran: ResMut, + mut ran: ResMut, mut set: ParamSet<( Query<(), Or<(Changed, Changed)>>, Query<(), Or<(Added, Added)>>, @@ -230,24 +236,33 @@ mod tests { assert_eq!(changed, 1); assert_eq!(added, 1); - *ran = true; + *ran = SystemRan::Yes; } let mut world = World::default(); - world.insert_resource(false); + world.insert_resource(SystemRan::No); world.spawn().insert_bundle((A, B)); run_system(&mut world, query_system); - assert!(*world.resource::(), "system ran"); + assert_eq!(*world.resource::(), SystemRan::Yes); } #[test] fn changed_resource_system() { + use crate::system::Resource; + + #[derive(Resource)] + struct Flipper(bool); + + #[derive(Resource)] struct Added(usize); + + #[derive(Resource)] struct Changed(usize); + fn incr_e_on_flip( - value: Res, + value: Res, mut changed: ResMut, mut added: ResMut, ) { @@ -261,7 +276,7 @@ mod tests { } let mut world = World::default(); - world.insert_resource(false); + world.insert_resource(Flipper(false)); world.insert_resource(Added(0)); world.insert_resource(Changed(0)); @@ -282,7 +297,7 @@ mod tests { assert_eq!(world.resource::().0, 1); assert_eq!(world.resource::().0, 1); - *world.resource_mut::() = true; + world.resource_mut::().0 = true; schedule.run(&mut world); assert_eq!(world.resource::().0, 1); assert_eq!(world.resource::().0, 2); @@ -406,7 +421,7 @@ mod tests { run_system(&mut world, sys); } - #[derive(Default)] + #[derive(Default, Resource)] struct BufferRes { _buffer: Vec, } @@ -449,36 +464,42 @@ mod tests { #[test] fn local_system() { let mut world = World::default(); - world.insert_resource(1u32); - world.insert_resource(false); + world.insert_resource(ProtoFoo { value: 1 }); + world.insert_resource(SystemRan::No); + struct Foo { value: u32, } + #[derive(Resource)] + struct ProtoFoo { + value: u32, + } + impl FromWorld for Foo { fn from_world(world: &mut World) -> Self { Foo { - value: *world.resource::() + 1, + value: world.resource::().value + 1, } } } - fn sys(local: Local, mut modified: ResMut) { + fn sys(local: Local, mut system_ran: ResMut) { assert_eq!(local.value, 2); - *modified = true; + *system_ran = SystemRan::Yes; } run_system(&mut world, sys); // ensure the system actually ran - assert!(*world.resource::()); + assert_eq!(*world.resource::(), SystemRan::Yes); } #[test] fn non_send_option_system() { let mut world = World::default(); - world.insert_resource(false); + world.insert_resource(SystemRan::No); struct NotSend1(std::rc::Rc); struct NotSend2(std::rc::Rc); world.insert_non_send_resource(NotSend1(std::rc::Rc::new(0))); @@ -486,34 +507,38 @@ mod tests { fn sys( op: Option>, mut _op2: Option>, - mut run: ResMut, + mut system_ran: ResMut, ) { op.expect("NonSend should exist"); - *run = true; + *system_ran = SystemRan::Yes; } run_system(&mut world, sys); // ensure the system actually ran - assert!(*world.resource::()); + assert_eq!(*world.resource::(), SystemRan::Yes); } #[test] fn non_send_system() { let mut world = World::default(); - world.insert_resource(false); + world.insert_resource(SystemRan::No); struct NotSend1(std::rc::Rc); struct NotSend2(std::rc::Rc); world.insert_non_send_resource(NotSend1(std::rc::Rc::new(1))); world.insert_non_send_resource(NotSend2(std::rc::Rc::new(2))); - fn sys(_op: NonSend, mut _op2: NonSendMut, mut run: ResMut) { - *run = true; + fn sys( + _op: NonSend, + mut _op2: NonSendMut, + mut system_ran: ResMut, + ) { + *system_ran = SystemRan::Yes; } run_system(&mut world, sys); - assert!(*world.resource::()); + assert_eq!(*world.resource::(), SystemRan::Yes); } #[test] @@ -525,13 +550,16 @@ mod tests { let spurious_entity = world.spawn().id(); // Track which entities we want to operate on + #[derive(Resource)] struct Despawned(Entity); world.insert_resource(Despawned(entity_to_despawn)); + + #[derive(Resource)] struct Removed(Entity); world.insert_resource(Removed(entity_to_remove_w_from)); // Verify that all the systems actually ran - #[derive(Default)] + #[derive(Default, Resource)] struct NSystems(usize); world.insert_resource(NSystems::default()); @@ -587,7 +615,7 @@ mod tests { #[test] fn world_collections_system() { let mut world = World::default(); - world.insert_resource(false); + world.insert_resource(SystemRan::No); world.spawn().insert_bundle((W(42), W(true))); fn sys( archetypes: &Archetypes, @@ -595,7 +623,7 @@ mod tests { entities: &Entities, bundles: &Bundles, query: Query>>, - mut modified: ResMut, + mut system_ran: ResMut, ) { assert_eq!(query.iter().count(), 1, "entity exists"); for entity in query.iter() { @@ -619,13 +647,13 @@ mod tests { "entity's bundle components exactly match entity's archetype components" ); } - *modified = true; + *system_ran = SystemRan::Yes; } run_system(&mut world, sys); // ensure the system actually ran - assert!(*world.resource::()); + assert_eq!(*world.resource::(), SystemRan::Yes); } #[test] @@ -723,7 +751,7 @@ mod tests { #[test] fn read_system_state() { - #[derive(Eq, PartialEq, Debug)] + #[derive(Eq, PartialEq, Debug, Resource)] struct A(usize); #[derive(Component, Eq, PartialEq, Debug)] @@ -746,7 +774,7 @@ mod tests { #[test] fn write_system_state() { - #[derive(Eq, PartialEq, Debug)] + #[derive(Resource, Eq, PartialEq, Debug)] struct A(usize); #[derive(Component, Eq, PartialEq, Debug)] diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index e0ec4892f31fa..d15c206492e6d 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1,4 +1,5 @@ pub use crate::change_detection::{NonSendMut, ResMut}; +pub use bevy_ecs_macros::Resource; use crate::{ archetype::{Archetype, Archetypes}, bundle::Bundles, diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 71ee4c7a3716b..f7160cb2fd034 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1509,6 +1509,7 @@ mod tests { change_detection::DetectChanges, component::{ComponentDescriptor, ComponentId, StorageType}, ptr::OwningPtr, + system::Resource, }; use bevy_ecs_macros::Component; use std::{ @@ -1635,7 +1636,7 @@ mod tests { ); } - #[derive(Component)] + #[derive(Resource)] struct TestResource(u32); #[test] diff --git a/crates/bevy_ecs/src/world/world_cell.rs b/crates/bevy_ecs/src/world/world_cell.rs index 5a1fff6cdf9a2..96f8a9348fb6a 100644 --- a/crates/bevy_ecs/src/world/world_cell.rs +++ b/crates/bevy_ecs/src/world/world_cell.rs @@ -318,40 +318,46 @@ impl<'w> WorldCell<'w> { #[cfg(test)] mod tests { use super::BASE_ACCESS; - use crate::{archetype::ArchetypeId, world::World}; + use crate as bevy_ecs; + use crate::{archetype::ArchetypeId, system::Resource, world::World}; use std::any::TypeId; + #[derive(Resource)] + struct A(u32); + #[derive(Resource)] + struct B(u64); + #[test] fn world_cell() { let mut world = World::default(); - world.insert_resource(1u32); - world.insert_resource(1u64); + world.insert_resource(A(1)); + world.insert_resource(B(1)); let cell = world.cell(); { - let mut a = cell.resource_mut::(); - assert_eq!(1, *a); - *a = 2; + let mut a = cell.resource_mut::(); + assert_eq!(1, a.0); + a.0 = 2; } { - let a = cell.resource::(); - assert_eq!(2, *a, "ensure access is dropped"); + let a = cell.resource::(); + assert_eq!(2, a.0, "ensure access is dropped"); - let b = cell.resource::(); + let a2 = cell.resource::(); assert_eq!( - 2, *b, + 2, a2.0, "ensure multiple immutable accesses can occur at the same time" ); } { - let a = cell.resource_mut::(); + let a = cell.resource_mut::(); assert_eq!( - 2, *a, + 2, a.0, "ensure both immutable accesses are dropped, enabling a new mutable access" ); - let b = cell.resource::(); + let b = cell.resource::(); assert_eq!( - 1, *b, + 1, b.0, "ensure multiple non-conflicting mutable accesses can occur at the same time" ); } @@ -360,13 +366,13 @@ mod tests { #[test] fn world_access_reused() { let mut world = World::default(); - world.insert_resource(1u32); + world.insert_resource(A(1)); { let cell = world.cell(); { - let mut a = cell.resource_mut::(); - assert_eq!(1, *a); - *a = 2; + let mut a = cell.resource_mut::(); + assert_eq!(1, a.0); + a.0 = 2; } } @@ -393,39 +399,39 @@ mod tests { #[should_panic] fn world_cell_double_mut() { let mut world = World::default(); - world.insert_resource(1u32); + world.insert_resource(A(1)); let cell = world.cell(); - let _value_a = cell.resource_mut::(); - let _value_b = cell.resource_mut::(); + let _value_a = cell.resource_mut::(); + let _value_b = cell.resource_mut::(); } #[test] #[should_panic] fn world_cell_ref_and_mut() { let mut world = World::default(); - world.insert_resource(1u32); + world.insert_resource(A(1)); let cell = world.cell(); - let _value_a = cell.resource::(); - let _value_b = cell.resource_mut::(); + let _value_a = cell.resource::(); + let _value_b = cell.resource_mut::(); } #[test] #[should_panic] fn world_cell_mut_and_ref() { let mut world = World::default(); - world.insert_resource(1u32); + world.insert_resource(A(1)); let cell = world.cell(); - let _value_a = cell.resource_mut::(); - let _value_b = cell.resource::(); + let _value_a = cell.resource_mut::(); + let _value_b = cell.resource::(); } #[test] #[should_panic] fn world_cell_ref_and_ref() { let mut world = World::default(); - world.insert_resource(1u32); + world.insert_resource(A(1)); let cell = world.cell(); - let _value_a = cell.resource_mut::(); - let _value_b = cell.resource::(); + let _value_a = cell.resource_mut::(); + let _value_b = cell.resource::(); } }