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

Add removal_detection example #945

Merged
merged 2 commits into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ current changes on git with [previous release tags][git_tag_comparison].
## Unreleased

### Added

- [`bevy_log`][836]
- Adds logging functionality as a Plugin.
- Changes internal logging to work with the new implementation.
Expand All @@ -21,7 +22,10 @@ current changes on git with [previous release tags][git_tag_comparison].
- [Added `set_cursor_position` to `Window`][917]
- [Added new Bevy reflection system][926]
- Replaces the properties system
- [Add removal_detection example][945]

### Changed

- [FileAssetIo includes full path on error][821]
- [Removed ECS query APIs that could easily violate safety from the public interface][829]
- [Changed Query filter API to be easier to understand][834]
Expand All @@ -33,7 +37,9 @@ current changes on git with [previous release tags][git_tag_comparison].
- Created getters to get `Time` state and made members private.
- Modifying `Time`'s values directly is no longer possible outside of bevy.
- [Use `mailbox` instead of `fifo` for vsync on supported systems][920]

### Fixed

- [Fixed typos in KeyCode identifiers][857]
- [Don't draw text that isn't visible][893]
- [Use `instant::Instant` for WASM compatibility][895]
Expand All @@ -60,6 +66,7 @@ current changes on git with [previous release tags][git_tag_comparison].
[926]: https://github.com/bevyengine/bevy/pull/926
[931]: https://github.com/bevyengine/bevy/pull/931
[934]: https://github.com/bevyengine/bevy/pull/934
[945]: https://github.com/bevyengine/bevy/pull/945
[955]: https://github.com/bevyengine/bevy/pull/955

## Version 0.3.0 (2020-11-03)
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,10 @@ path = "examples/window/multiple_windows.rs"
name = "window_settings"
path = "examples/window/window_settings.rs"

[[example]]
name = "removal_detection"
path = "examples/ecs/removal_detection.rs"

[[example]]
name = "hello_wasm"
path = "examples/wasm/hello_wasm.rs"
Expand Down
74 changes: 74 additions & 0 deletions examples/ecs/removal_detection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// This example shows how you can know when a `Component` has been removed, so you can react to it.

use bevy::prelude::*;

fn main() {
// Information regarding removed `Component`s is discarded at the end of each frame, so you need
// to react to the removal before the frame is over.
//
// Also, `Components` are removed via a `Command`. `Command`s are applied after a stage has
// finished executing. So you need to react to the removal at some stage after the
// `Component` is removed.
//
// With these constraints in mind we make sure to place the system that removes a `Component` on
// the `stage::UPDATE` stage, and the system that reacts on the removal on the
// `stage::POST_UPDATE` stage.
App::build()
.add_plugins(DefaultPlugins)
.add_startup_system(setup.system())
.add_system_to_stage(stage::UPDATE, remove_component.system())
.add_system_to_stage(stage::POST_UPDATE, react_on_removal.system())
.run();
}

// This `Struct` is just used for convenience in this example. This is the `Component` we'll be
// giving to the `Entity` so we have a `Component` to remove in `remove_component()`.
struct MyComponent;

fn setup(
commands: &mut Commands,
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
let texture = asset_server.load("branding/icon.png");

commands
.spawn(Camera2dBundle::default())
.spawn(SpriteBundle {
material: materials.add(texture.into()),
..Default::default()
})
.with(MyComponent); // Add the `Component`.
}

fn remove_component(
time: Res<Time>,
commands: &mut Commands,
query: Query<Entity, With<MyComponent>>,
) {
// After two seconds have passed the `Component` is removed.
if time.seconds_since_startup() > 2.0 {
if let Some(entity) = query.iter().next() {
commands.remove_one::<MyComponent>(entity);
}
}
}

fn react_on_removal(
mut materials: ResMut<Assets<ColorMaterial>>,
query: Query<(Entity, &Handle<ColorMaterial>)>,
) {
// Note: usually this isn't how you would handle a `Query`. In this example it makes things
// a bit easier to read.
let (query_entity, material) = query.iter().next().unwrap();

// `Query.removed<T>` returns an array with the `Entity`s in the `Query` that had its
// `Component` `T` (in this case `MyComponent`) removed at some point earlier during the frame.
for entity in query.removed::<MyComponent>() {
// We compare the `Entity` that had its `MyComponent` `Component` removed with the `Entity`
// in the current `Query`. If they match all red is removed from the material.
if query_entity == *entity {
materials.get_mut(material).unwrap().color.set_r(0.0);
}
}
}