Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Resource trait opt-in, requiring #[derive(Resource)] #5007

Closed
wants to merge 10 commits into from
3 changes: 2 additions & 1 deletion crates/bevy_app/src/ci_testing.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
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.
///
/// 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<u32>,
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_app/src/schedule_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_asset/src/asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
RefChange, RefChangeChannel, SourceInfo, SourceMeta,
};
use anyhow::Result;
use bevy_ecs::system::{Res, ResMut};
use bevy_ecs::system::{Res, ResMut, Resource};
use bevy_log::warn;
use bevy_tasks::IoTaskPool;
use bevy_utils::{Entry, HashMap, Uuid};
Expand Down Expand Up @@ -59,7 +59,7 @@ pub struct AssetServerInternal {
}

/// Loads assets from the filesystem on background threads
#[derive(Clone)]
#[derive(Clone, Resource)]
pub struct AssetServer {
pub(crate) server: Arc<AssetServerInternal>,
}
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_asset/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
use bevy_app::App;
use bevy_ecs::{
event::{EventWriter, Events},
system::ResMut,
system::{ResMut, Resource},
world::FromWorld,
};
use bevy_utils::HashMap;
Expand Down Expand Up @@ -62,7 +62,7 @@ impl<T: Asset> Debug for AssetEvent<T> {
/// Remember, if there are no Strong handles for an asset (i.e. they have all been dropped), the
/// asset will unload. Make sure you always have a Strong handle when you want to keep an asset
/// loaded!
#[derive(Debug)]
#[derive(Debug, Resource)]
pub struct Assets<T: Asset> {
assets: HashMap<HandleId, T>,
events: Events<AssetEvent<T>>,
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_asset/src/debug_asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use bevy_app::{App, Plugin};
use bevy_ecs::{
event::Events,
schedule::SystemLabel,
system::{NonSendMut, Res, ResMut, SystemState},
system::{NonSendMut, Res, ResMut, Resource, SystemState},
};
use bevy_tasks::{IoTaskPool, TaskPoolBuilder};
use bevy_utils::HashMap;
Expand Down Expand Up @@ -44,6 +44,8 @@ pub struct DebugAssetAppRun;
/// Currently only hot reloads assets stored in the `crates` folder.
#[derive(Default)]
pub struct DebugAssetServerPlugin;

#[derive(Resource)]
pub struct HandleMap<T: Asset> {
pub handles: HashMap<Handle<T>, Handle<T>>,
}
Expand Down
6 changes: 5 additions & 1 deletion crates/bevy_asset/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ pub use loader::*;
pub use path::*;

use bevy_app::{prelude::Plugin, App};
use bevy_ecs::schedule::{StageLabel, SystemStage};
use bevy_ecs::{
schedule::{StageLabel, SystemStage},
system::Resource,
};

/// The names of asset stages in an App Schedule
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]
Expand All @@ -43,6 +46,7 @@ pub enum AssetStage {
#[derive(Default)]
pub struct AssetPlugin;

#[derive(Resource)]
pub struct AssetServerSettings {
pub asset_folder: String,
/// Whether to watch for changes in asset files. Requires the `filesystem_watcher` feature,
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_audio/src/audio.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{AudioSink, AudioSource, Decodable};
use bevy_asset::{Asset, Handle, HandleId};
use bevy_ecs::system::Resource;
use parking_lot::RwLock;
use std::{collections::VecDeque, fmt};

Expand All @@ -13,6 +14,7 @@ use std::{collections::VecDeque, fmt};
/// audio.play(asset_server.load("my_sound.ogg"));
/// }
/// ```
#[derive(Resource)]
pub struct Audio<Source = AudioSource>
where
Source: Asset + Decodable,
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_core/src/task_pool_options.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use bevy_ecs::prelude::Resource;
use bevy_tasks::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool, TaskPoolBuilder};
use bevy_utils::tracing::trace;

Expand Down Expand Up @@ -33,7 +34,7 @@ impl TaskPoolThreadAssignmentPolicy {
/// Helper for configuring and creating the default task pools. For end-users who want full control,
/// insert the default task pools into the resource map manually. If the pools are already inserted,
/// this helper will do nothing.
#[derive(Clone)]
#[derive(Clone, Resource)]
pub struct DefaultTaskPoolOptions {
/// If the number of physical cores is less than min_total_threads, force using
/// min_total_threads
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_diagnostic/src/diagnostic.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use bevy_ecs::system::Resource;
use bevy_log::warn;
use bevy_utils::{Duration, Instant, StableHashMap, Uuid};
use std::{borrow::Cow, collections::VecDeque};
Expand Down Expand Up @@ -136,7 +137,7 @@ impl Diagnostic {
}

/// A collection of [Diagnostic]s
#[derive(Debug, Default)]
#[derive(Debug, Default, Resource)]
pub struct Diagnostics {
// This uses a [`StableHashMap`] to ensure that the iteration order is deterministic between
// runs when all diagnostics are inserted in the same order.
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_diagnostic/src/frame_time_diagnostics_plugin.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::{Diagnostic, DiagnosticId, Diagnostics};
use bevy_app::prelude::*;
use bevy_ecs::system::{Res, ResMut};
use bevy_ecs::system::{Res, ResMut, Resource};
use bevy_time::Time;

/// Adds "frame time" diagnostic to an App, specifically "frame time", "fps" and "frame count"
#[derive(Default)]
pub struct FrameTimeDiagnosticsPlugin;

#[derive(Resource)]
pub struct FrameTimeDiagnosticsState {
frame_count: u64,
}
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_diagnostic/src/log_diagnostics_plugin.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{Diagnostic, DiagnosticId, Diagnostics};
use bevy_app::prelude::*;
use bevy_ecs::system::{Res, ResMut};
use bevy_ecs::system::{Res, ResMut, Resource};
use bevy_log::{debug, info};
use bevy_time::{Time, Timer};
use bevy_utils::Duration;
Expand All @@ -13,6 +13,7 @@ pub struct LogDiagnosticsPlugin {
}

/// State used by the [`LogDiagnosticsPlugin`]
#[derive(Resource)]
struct LogDiagnosticsState {
timer: Timer,
filter: Option<Vec<DiagnosticId>>,
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/examples/change_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fn main() {
}

// This struct will be used as a Resource keeping track of the total amount of spawned entities
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it has a derive Resource, this first sentence is superfluous

However I'm happy leaving this, for a doc consistency pass at some point in the future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep; IMO this will be easier to do in a follow-up PR, where we can search our dev docs site for "resource" and make a call.

#[derive(Debug)]
#[derive(Debug, Resource)]
struct EntityCounter {
pub value: i32,
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/examples/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down
18 changes: 18 additions & 0 deletions crates/bevy_ecs/macros/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{quote, ToTokens};
use syn::{parse_macro_input, parse_quote, DeriveInput, Error, Ident, Path, Result};

pub fn derive_resource(input: TokenStream) -> TokenStream {
let mut ast = parse_macro_input!(input as DeriveInput);
let bevy_ecs_path: Path = crate::bevy_ecs_path();

ast.generics
.make_where_clause()
.predicates
.push(parse_quote! { Self: Send + Sync + 'static });

let struct_name = &ast.ident;
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();

TokenStream::from(quote! {
impl #impl_generics #bevy_ecs_path::component::Resource for #struct_name #type_generics #where_clause {
}
})
}

pub fn derive_component(input: TokenStream) -> TokenStream {
let mut ast = parse_macro_input!(input as DeriveInput);
let bevy_ecs_path: Path = crate::bevy_ecs_path();
Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_ecs/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,11 @@ pub(crate) fn bevy_ecs_path() -> syn::Path {
BevyManifest::default().get_path("bevy_ecs")
}

#[proc_macro_derive(Resource)]
pub fn derive_resource(input: TokenStream) -> TokenStream {
component::derive_resource(input)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this live in the component module?

I guess it's fine.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My argument here is that it should change in concert with the derive Component macro, so should live together.

I was thinking about renaming the module, but struggled to find a clear enough blanket name.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think both components and resources can be viewed as storage.

}

#[proc_macro_derive(Component, attributes(component))]
pub fn derive_component(input: TokenStream) -> TokenStream {
component::derive_component(input)
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/change_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ pub(crate) struct Ticks<'a> {
pub(crate) change_tick: u32,
}

/// Unique mutable borrow of a resource.
/// Unique mutable borrow of a [`Resource`].
///
/// See the [`World`](crate::world::World) documentation to see the usage of a resource.
///
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/component.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_ecs/src/event.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down Expand Up @@ -128,7 +128,7 @@ struct EventInstance<E: Event> {
/// [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<E: Event> {
/// Holds the oldest still active events.
/// Note that a.start_event_count + a.len() should always === events_b.start_event_count.
Expand Down
Loading