Skip to content

Commit bbbc705

Browse files
committed
add callbacks example
1 parent 6af4899 commit bbbc705

File tree

4 files changed

+122
-2
lines changed

4 files changed

+122
-2
lines changed

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,17 @@ description = "Demonstrates loading a compressed asset"
10971097
category = "Assets"
10981098
wasm = false
10991099

1100+
[[example]]
1101+
name = "callbacks"
1102+
path = "examples/asset/callbacks.rs"
1103+
doc-scrape-examples = true
1104+
1105+
[package.metadata.example.callbacks]
1106+
name = "Callbacks"
1107+
description = "Demonstrates using Callbacks"
1108+
category = "Assets"
1109+
wasm = true
1110+
11001111
[[example]]
11011112
name = "custom_asset"
11021113
path = "examples/asset/custom_asset.rs"

crates/bevy_asset/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ pub mod saver;
66
pub mod prelude {
77
#[doc(hidden)]
88
pub use crate::{
9-
Asset, AssetApp, AssetEvent, AssetId, AssetMode, AssetPlugin, AssetServer, Assets, Handle,
10-
UntypedHandle,
9+
Asset, AssetApp, AssetEvent, AssetId, AssetMode, AssetPlugin, AssetServer, Assets,
10+
Callback, Handle, RunCallbackCommands, RunCallbackWorld, UntypedHandle,
1111
};
1212
}
1313

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ Example | Description
184184
[Asset Decompression](../examples/asset/asset_decompression.rs) | Demonstrates loading a compressed asset
185185
[Asset Loading](../examples/asset/asset_loading.rs) | Demonstrates various methods to load assets
186186
[Asset Processing](../examples/asset/processing/asset_processing.rs) | Demonstrates how to process and load custom assets
187+
[Callbacks](../examples/asset/callbacks.rs) | Demonstrates using Callbacks
187188
[Custom Asset](../examples/asset/custom_asset.rs) | Implements a custom asset loader
188189
[Custom Asset IO](../examples/asset/custom_asset_reader.rs) | Implements a custom AssetReader
189190
[Hot Reloading of Assets](../examples/asset/hot_asset_reloading.rs) | Demonstrates automatic reloading of assets when modified on disk

examples/asset/callbacks.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//! Demonstrates the use of [`Callback`]s, which run once when triggered.
2+
//!
3+
//! These can be useful to help structure your logic in a push-based fashion,
4+
//! reducing the overhead of running extremely rarely run systems
5+
//! and improving schedule flexibility. Their advantage over [`SystemId`]s is
6+
//! that they are [`Asset`]s.
7+
//!
8+
//! See the [`RunCallbackWorld::run_callback`](bevy::prelude::RunCallbackWorld::run_callback)
9+
//! docs for more details.
10+
11+
use bevy::prelude::*;
12+
13+
fn main() {
14+
App::new()
15+
.add_plugins(DefaultPlugins)
16+
// `init_asset` must be called for new types of callbacks.
17+
// By default, only `Callback` (no input or output) is inited.
18+
.init_asset::<Callback<PressedDown>>()
19+
.add_systems(Startup, setup)
20+
.add_systems(Update, evaluate_callbacks)
21+
.run();
22+
}
23+
24+
// Need to store the `Handle` to the callback
25+
#[derive(Component)]
26+
struct OnPressedDown(Handle<Callback<PressedDown>>);
27+
28+
// Input and output of `Callback`s must implement `TypePath`
29+
#[derive(TypePath)]
30+
struct PressedDown(Entity);
31+
32+
// Need mutible access to `Assets` to add a callback
33+
fn setup(mut commands: Commands, mut callbacks: ResMut<Assets<Callback<PressedDown>>>) {
34+
// Camera
35+
commands.spawn(Camera2dBundle::default());
36+
37+
// root node
38+
commands
39+
.spawn(NodeBundle {
40+
style: Style {
41+
width: Val::Percent(100.0),
42+
height: Val::Percent(100.0),
43+
justify_content: JustifyContent::Center,
44+
align_items: AlignItems::Center,
45+
..default()
46+
},
47+
..default()
48+
})
49+
.with_children(|parent| {
50+
// button
51+
parent
52+
.spawn((
53+
ButtonBundle {
54+
style: Style {
55+
width: Val::Px(250.0),
56+
height: Val::Px(65.0),
57+
margin: UiRect::all(Val::Px(20.0)),
58+
justify_content: JustifyContent::Center,
59+
align_items: AlignItems::Center,
60+
..default()
61+
},
62+
background_color: Color::TEAL.into(),
63+
..default()
64+
},
65+
// Add callback
66+
OnPressedDown(callbacks.add(Callback::from_system(toggle))),
67+
))
68+
.with_children(|parent| {
69+
// text
70+
parent.spawn(TextBundle::from_section(
71+
"false",
72+
TextStyle {
73+
font_size: 40.0,
74+
color: Color::BLACK,
75+
..default()
76+
},
77+
));
78+
});
79+
});
80+
}
81+
82+
// `Callback`s can be created from any system.
83+
fn toggle(
84+
In(pressed_down): In<PressedDown>,
85+
mut text: Query<&mut Text>,
86+
children: Query<&Children>,
87+
mut value: Local<bool>,
88+
) {
89+
*value = !*value;
90+
let children = children.get(pressed_down.0).unwrap();
91+
let mut text = text.iter_many_mut(children);
92+
let mut text = text.fetch_next().unwrap();
93+
text.sections[0].value = value.to_string();
94+
}
95+
96+
/// Runs the systems associated with each `OnPressedDown` component if button is pressed.
97+
///
98+
/// This could be done in an exclusive system rather than using `Commands` if preferred.
99+
fn evaluate_callbacks(
100+
on_pressed_down: Query<(Entity, &OnPressedDown, &Interaction), Changed<Interaction>>,
101+
mut commands: Commands,
102+
) {
103+
for (entity, on_button_pressed, interaction) in &on_pressed_down {
104+
if *interaction == Interaction::Pressed {
105+
commands.run_callback_with_input(on_button_pressed.0.clone(), PressedDown(entity));
106+
}
107+
}
108+
}

0 commit comments

Comments
 (0)