2022-05-16 13:53:20 +00:00
|
|
|
//! Renders a lot of sprites to allow performance testing.
|
|
|
|
//! See <https://github.com/bevyengine/bevy/pull/1492>
|
|
|
|
//!
|
2023-05-09 16:19:42 +00:00
|
|
|
//! This example sets up many sprites in different sizes, rotations, and scales in the world.
|
|
|
|
//! It also moves the camera over them to see how well frustum culling works.
|
2022-07-14 11:03:13 +00:00
|
|
|
//!
|
|
|
|
//! Add the `--colored` arg to run with color tinted sprites. This will cause the sprites to be rendered
|
|
|
|
//! in multiple batches, reducing performance but useful for testing.
|
2022-05-16 13:53:20 +00:00
|
|
|
|
2021-03-25 01:46:22 +00:00
|
|
|
use bevy::{
|
|
|
|
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
|
|
|
|
prelude::*,
|
2023-01-19 00:38:28 +00:00
|
|
|
window::{PresentMode, WindowPlugin},
|
2021-03-25 01:46:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
use rand::Rng;
|
|
|
|
|
|
|
|
const CAMERA_SPEED: f32 = 1000.0;
|
|
|
|
|
2022-07-14 11:03:13 +00:00
|
|
|
const COLORS: [Color; 3] = [Color::BLUE, Color::WHITE, Color::RED];
|
|
|
|
|
Make `Resource` trait opt-in, requiring `#[derive(Resource)]` V2 (#5577)
*This PR description is an edited copy of #5007, written by @alice-i-cecile.*
# Objective
Follow-up to https://github.com/bevyengine/bevy/pull/2254. The `Resource` trait currently has a blanket implementation for all types that meet its bounds.
While ergonomic, this results in several drawbacks:
* it is possible to make confusing, silent mistakes such as inserting a function pointer (Foo) rather than a value (Foo::Bar) as a resource
* it is challenging to discover if a type is intended to be used as a resource
* we cannot later add customization options (see the [RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/27-derive-component.md) for the equivalent choice for Component).
* dependencies can use the same Rust type as a resource in invisibly conflicting ways
* raw Rust types used as resources cannot preserve privacy appropriately, as anyone able to access that type can read and write to internal values
* we cannot capture a definitive list of possible resources to display to users in an editor
## Notes to reviewers
* Review this commit-by-commit; there's effectively no back-tracking and there's a lot of churn in some of these commits.
*ira: My commits are not as well organized :')*
* I've relaxed the bound on Local to Send + Sync + 'static: I don't think these concerns apply there, so this can keep things simple. Storing e.g. a u32 in a Local is fine, because there's a variable name attached explaining what it does.
* I think this is a bad place for the Resource trait to live, but I've left it in place to make reviewing easier. IMO that's best tackled with https://github.com/bevyengine/bevy/issues/4981.
## Changelog
`Resource` is no longer automatically implemented for all matching types. Instead, use the new `#[derive(Resource)]` macro.
## Migration Guide
Add `#[derive(Resource)]` to all types you are using as a resource.
If you are using a third party type as a resource, wrap it in a tuple struct to bypass orphan rules. Consider deriving `Deref` and `DerefMut` to improve ergonomics.
`ClearColor` no longer implements `Component`. Using `ClearColor` as a component in 0.8 did nothing.
Use the `ClearColorConfig` in the `Camera3d` and `Camera2d` components instead.
Co-authored-by: Alice <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: devil-ira <justthecooldude@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-08-08 21:36:35 +00:00
|
|
|
#[derive(Resource)]
|
2022-07-14 11:03:13 +00:00
|
|
|
struct ColorTint(bool);
|
|
|
|
|
2021-03-25 01:46:22 +00:00
|
|
|
fn main() {
|
2021-07-27 20:21:06 +00:00
|
|
|
App::new()
|
2022-07-14 11:03:13 +00:00
|
|
|
.insert_resource(ColorTint(
|
|
|
|
std::env::args().nth(1).unwrap_or_default() == "--colored",
|
|
|
|
))
|
2022-05-16 13:53:20 +00:00
|
|
|
// Since this is also used as a benchmark, we want it to display performance data.
|
2023-06-21 20:51:03 +00:00
|
|
|
.add_plugins((
|
|
|
|
LogDiagnosticsPlugin::default(),
|
|
|
|
FrameTimeDiagnosticsPlugin,
|
|
|
|
DefaultPlugins.set(WindowPlugin {
|
|
|
|
primary_window: Some(Window {
|
|
|
|
present_mode: PresentMode::AutoNoVsync,
|
|
|
|
..default()
|
|
|
|
}),
|
Plugins own their settings. Rework PluginGroup trait. (#6336)
# Objective
Fixes #5884 #2879
Alternative to #2988 #5885 #2886
"Immutable" Plugin settings are currently represented as normal ECS resources, which are read as part of plugin init. This presents a number of problems:
1. If a user inserts the plugin settings resource after the plugin is initialized, it will be silently ignored (and use the defaults instead)
2. Users can modify the plugin settings resource after the plugin has been initialized. This creates a false sense of control over settings that can no longer be changed.
(1) and (2) are especially problematic and confusing for the `WindowDescriptor` resource, but this is a general problem.
## Solution
Immutable Plugin settings now live on each Plugin struct (ex: `WindowPlugin`). PluginGroups have been reworked to support overriding plugin values. This also removes the need for the `add_plugins_with` api, as the `add_plugins` api can use the builder pattern directly. Settings that can be used at runtime continue to be represented as ECS resources.
Plugins are now configured like this:
```rust
app.add_plugin(AssetPlugin {
watch_for_changes: true,
..default()
})
```
PluginGroups are now configured like this:
```rust
app.add_plugins(DefaultPlugins
.set(AssetPlugin {
watch_for_changes: true,
..default()
})
)
```
This is an alternative to #2988, which is similar. But I personally prefer this solution for a couple of reasons:
* ~~#2988 doesn't solve (1)~~ #2988 does solve (1) and will panic in that case. I was wrong!
* This PR directly ties plugin settings to Plugin types in a 1:1 relationship, rather than a loose "setup resource" <-> plugin coupling (where the setup resource is consumed by the first plugin that uses it).
* I'm not a huge fan of overloading the ECS resource concept and implementation for something that has very different use cases and constraints.
## Changelog
- PluginGroups can now be configured directly using the builder pattern. Individual plugin values can be overridden by using `plugin_group.set(SomePlugin {})`, which enables overriding default plugin values.
- `WindowDescriptor` plugin settings have been moved to `WindowPlugin` and `AssetServerSettings` have been moved to `AssetPlugin`
- `app.add_plugins_with` has been replaced by using `add_plugins` with the builder pattern.
## Migration Guide
The `WindowDescriptor` settings have been moved from a resource to `WindowPlugin::window`:
```rust
// Old (Bevy 0.8)
app
.insert_resource(WindowDescriptor {
width: 400.0,
..default()
})
.add_plugins(DefaultPlugins)
// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(WindowPlugin {
window: WindowDescriptor {
width: 400.0,
..default()
},
..default()
}))
```
The `AssetServerSettings` resource has been removed in favor of direct `AssetPlugin` configuration:
```rust
// Old (Bevy 0.8)
app
.insert_resource(AssetServerSettings {
watch_for_changes: true,
..default()
})
.add_plugins(DefaultPlugins)
// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(AssetPlugin {
watch_for_changes: true,
..default()
}))
```
`add_plugins_with` has been replaced by `add_plugins` in combination with the builder pattern:
```rust
// Old (Bevy 0.8)
app.add_plugins_with(DefaultPlugins, |group| group.disable::<AssetPlugin>());
// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.build().disable::<AssetPlugin>());
```
2022-10-24 21:20:33 +00:00
|
|
|
..default()
|
2023-01-19 00:38:28 +00:00
|
|
|
}),
|
2023-06-21 20:51:03 +00:00
|
|
|
))
|
2023-03-18 01:45:34 +00:00
|
|
|
.add_systems(Startup, setup)
|
|
|
|
.add_systems(
|
|
|
|
Update,
|
|
|
|
(print_sprite_count, move_camera.after(print_sprite_count)),
|
|
|
|
)
|
2022-02-13 22:33:55 +00:00
|
|
|
.run();
|
2021-03-25 01:46:22 +00:00
|
|
|
}
|
|
|
|
|
2022-07-14 11:03:13 +00:00
|
|
|
fn setup(mut commands: Commands, assets: Res<AssetServer>, color_tint: Res<ColorTint>) {
|
2022-07-13 19:13:46 +00:00
|
|
|
warn!(include_str!("warning_string.txt"));
|
|
|
|
|
2021-03-25 01:46:22 +00:00
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
|
|
|
|
let tile_size = Vec2::splat(64.0);
|
|
|
|
let map_size = Vec2::splat(320.0);
|
|
|
|
|
|
|
|
let half_x = (map_size.x / 2.0) as i32;
|
|
|
|
let half_y = (map_size.y / 2.0) as i32;
|
|
|
|
|
2021-12-14 03:58:23 +00:00
|
|
|
let sprite_handle = assets.load("branding/icon.png");
|
2021-03-25 01:46:22 +00:00
|
|
|
|
2021-09-10 19:13:14 +00:00
|
|
|
// Spawns the camera
|
2022-09-25 18:03:53 +00:00
|
|
|
|
|
|
|
commands.spawn(Camera2dBundle::default());
|
2021-03-25 01:46:22 +00:00
|
|
|
|
2021-09-10 19:13:14 +00:00
|
|
|
// Builds and spawns the sprites
|
|
|
|
let mut sprites = vec![];
|
2021-03-25 01:46:22 +00:00
|
|
|
for y in -half_y..half_y {
|
|
|
|
for x in -half_x..half_x {
|
|
|
|
let position = Vec2::new(x as f32, y as f32);
|
|
|
|
let translation = (position * tile_size).extend(rng.gen::<f32>());
|
|
|
|
let rotation = Quat::from_rotation_z(rng.gen::<f32>());
|
|
|
|
let scale = Vec3::splat(rng.gen::<f32>() * 2.0);
|
|
|
|
|
2021-09-10 19:13:14 +00:00
|
|
|
sprites.push(SpriteBundle {
|
2021-12-14 03:58:23 +00:00
|
|
|
texture: sprite_handle.clone(),
|
2021-03-25 01:46:22 +00:00
|
|
|
transform: Transform {
|
|
|
|
translation,
|
|
|
|
rotation,
|
|
|
|
scale,
|
|
|
|
},
|
2021-12-14 03:58:23 +00:00
|
|
|
sprite: Sprite {
|
|
|
|
custom_size: Some(tile_size),
|
2022-07-14 11:03:13 +00:00
|
|
|
color: if color_tint.0 {
|
|
|
|
COLORS[rng.gen_range(0..3)]
|
|
|
|
} else {
|
|
|
|
Color::WHITE
|
|
|
|
},
|
2022-03-01 20:52:09 +00:00
|
|
|
..default()
|
2021-12-14 03:58:23 +00:00
|
|
|
},
|
2022-03-01 20:52:09 +00:00
|
|
|
..default()
|
2021-03-25 01:46:22 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2021-09-10 19:13:14 +00:00
|
|
|
commands.spawn_batch(sprites);
|
2021-03-25 01:46:22 +00:00
|
|
|
}
|
|
|
|
|
2021-09-10 19:13:14 +00:00
|
|
|
// System for rotating and translating the camera
|
2022-02-03 23:56:57 +00:00
|
|
|
fn move_camera(time: Res<Time>, mut camera_query: Query<&mut Transform, With<Camera>>) {
|
2021-09-10 20:23:50 +00:00
|
|
|
let mut camera_transform = camera_query.single_mut();
|
2022-07-01 03:58:54 +00:00
|
|
|
camera_transform.rotate_z(time.delta_seconds() * 0.5);
|
2021-09-10 19:13:14 +00:00
|
|
|
*camera_transform = *camera_transform
|
|
|
|
* Transform::from_translation(Vec3::X * CAMERA_SPEED * time.delta_seconds());
|
2021-03-25 01:46:22 +00:00
|
|
|
}
|
|
|
|
|
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328)
# Objective
A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like:
```rust
#[derive(Component)]
struct Items(Vec<String>);
fn give_sword(query: Query<&mut Items>) {
query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom"));
}
```
> We could then define another struct that wraps `Vec<String>` without anything clashing in the query.
However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this.
Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations.
## Solution
Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field:
```rust
#[derive(Deref)]
struct Foo(String);
#[derive(Deref, DerefMut)]
struct Bar {
name: String,
}
```
This allows us to then remove that pesky `.0`:
```rust
#[derive(Component, Deref, DerefMut)]
struct Items(Vec<String>);
fn give_sword(query: Query<&mut Items>) {
query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom"));
}
```
### Alternatives
There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now).
### Considerations
One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree.
### Additional Context
Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630))
---
## Changelog
- Add `Deref` derive macro (exported to prelude)
- Add `DerefMut` derive macro (exported to prelude)
- Updated most newtypes in examples to use one or both derives
Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
|
|
|
#[derive(Deref, DerefMut)]
|
2022-02-03 23:56:57 +00:00
|
|
|
struct PrintingTimer(Timer);
|
|
|
|
|
|
|
|
impl Default for PrintingTimer {
|
|
|
|
fn default() -> Self {
|
Replace the `bool` argument of `Timer` with `TimerMode` (#6247)
As mentioned in #2926, it's better to have an explicit type that clearly communicates the intent of the timer mode rather than an opaque boolean, which can be only understood when knowing the signature or having to look up the documentation.
This also opens up a way to merge different timers, such as `Stopwatch`, and possibly future ones, such as `DiscreteStopwatch` and `DiscreteTimer` from #2683, into one struct.
Signed-off-by: Lena Milizé <me@lvmn.org>
# Objective
Fixes #2926.
## Solution
Introduce `TimerMode` which replaces the `bool` argument of `Timer` constructors. A `Default` value for `TimerMode` is `Once`.
---
## Changelog
### Added
- `TimerMode` enum, along with variants `TimerMode::Once` and `TimerMode::Repeating`
### Changed
- Replace `bool` argument of `Timer::new` and `Timer::from_seconds` with `TimerMode`
- Change `repeating: bool` field of `Timer` with `mode: TimerMode`
## Migration Guide
- Replace `Timer::new(duration, false)` with `Timer::new(duration, TimerMode::Once)`.
- Replace `Timer::new(duration, true)` with `Timer::new(duration, TimerMode::Repeating)`.
- Replace `Timer::from_seconds(seconds, false)` with `Timer::from_seconds(seconds, TimerMode::Once)`.
- Replace `Timer::from_seconds(seconds, true)` with `Timer::from_seconds(seconds, TimerMode::Repeating)`.
- Change `timer.repeating()` to `timer.mode() == TimerMode::Repeating`.
2022-10-17 13:47:01 +00:00
|
|
|
Self(Timer::from_seconds(1.0, TimerMode::Repeating))
|
2022-02-03 23:56:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-10 19:13:14 +00:00
|
|
|
// System for printing the number of sprites on every tick of the timer
|
2022-02-03 23:56:57 +00:00
|
|
|
fn print_sprite_count(time: Res<Time>, mut timer: Local<PrintingTimer>, sprites: Query<&Sprite>) {
|
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328)
# Objective
A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like:
```rust
#[derive(Component)]
struct Items(Vec<String>);
fn give_sword(query: Query<&mut Items>) {
query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom"));
}
```
> We could then define another struct that wraps `Vec<String>` without anything clashing in the query.
However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this.
Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations.
## Solution
Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field:
```rust
#[derive(Deref)]
struct Foo(String);
#[derive(Deref, DerefMut)]
struct Bar {
name: String,
}
```
This allows us to then remove that pesky `.0`:
```rust
#[derive(Component, Deref, DerefMut)]
struct Items(Vec<String>);
fn give_sword(query: Query<&mut Items>) {
query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom"));
}
```
### Alternatives
There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now).
### Considerations
One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree.
### Additional Context
Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630))
---
## Changelog
- Add `Deref` derive macro (exported to prelude)
- Add `DerefMut` derive macro (exported to prelude)
- Updated most newtypes in examples to use one or both derives
Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
|
|
|
timer.tick(time.delta());
|
2021-03-25 01:46:22 +00:00
|
|
|
|
bevy_derive: Add derives for `Deref` and `DerefMut` (#4328)
# Objective
A common pattern in Rust is the [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html). This is an especially useful pattern in Bevy as it allows us to give common/foreign types different semantics (such as allowing it to implement `Component` or `FromWorld`) or to simply treat them as a "new type" (clever). For example, it allows us to wrap a common `Vec<String>` and do things like:
```rust
#[derive(Component)]
struct Items(Vec<String>);
fn give_sword(query: Query<&mut Items>) {
query.single_mut().0.push(String::from("Flaming Poisoning Raging Sword of Doom"));
}
```
> We could then define another struct that wraps `Vec<String>` without anything clashing in the query.
However, one of the worst parts of this pattern is the ugly `.0` we have to write in order to access the type we actually care about. This is why people often implement `Deref` and `DerefMut` in order to get around this.
Since it's such a common pattern, especially for Bevy, it makes sense to add a derive macro to automatically add those implementations.
## Solution
Added a derive macro for `Deref` and another for `DerefMut` (both exported into the prelude). This works on all structs (including tuple structs) as long as they only contain a single field:
```rust
#[derive(Deref)]
struct Foo(String);
#[derive(Deref, DerefMut)]
struct Bar {
name: String,
}
```
This allows us to then remove that pesky `.0`:
```rust
#[derive(Component, Deref, DerefMut)]
struct Items(Vec<String>);
fn give_sword(query: Query<&mut Items>) {
query.single_mut().push(String::from("Flaming Poisoning Raging Sword of Doom"));
}
```
### Alternatives
There are other alternatives to this such as by using the [`derive_more`](https://crates.io/crates/derive_more) crate. However, it doesn't seem like we need an entire crate just yet since we only need `Deref` and `DerefMut` (for now).
### Considerations
One thing to consider is that the Rust std library recommends _not_ using `Deref` and `DerefMut` for things like this: "`Deref` should only be implemented for smart pointers to avoid confusion" ([reference](https://doc.rust-lang.org/std/ops/trait.Deref.html)). Personally, I believe it makes sense to use it in the way described above, but others may disagree.
### Additional Context
Discord: https://discord.com/channels/691052431525675048/692572690833473578/956648422163746827 (controversiality discussed [here](https://discord.com/channels/691052431525675048/692572690833473578/956711911481835630))
---
## Changelog
- Add `Deref` derive macro (exported to prelude)
- Add `DerefMut` derive macro (exported to prelude)
- Updated most newtypes in examples to use one or both derives
Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
2022-03-29 02:10:06 +00:00
|
|
|
if timer.just_finished() {
|
2023-09-08 21:46:54 +00:00
|
|
|
info!("Sprites: {}", sprites.iter().count());
|
2021-03-25 01:46:22 +00:00
|
|
|
}
|
|
|
|
}
|