Skip to content

Commit 2ec7f33

Browse files
Example mostly works
1 parent 303d6dc commit 2ec7f33

File tree

1 file changed

+132
-20
lines changed

1 file changed

+132
-20
lines changed

examples/ecs/per_entity_events.rs

Lines changed: 132 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ fn main() {
2727
// as vanilla components or resources
2828
.add_event::<CycleColorAction>()
2929
.add_event::<AddNumberAction>()
30-
.init_resource::<Selected>()
3130
.add_startup_system(setup.system())
3231
.add_system(select_entity.system())
3332
.add_system(
@@ -38,29 +37,32 @@ fn main() {
3837
)
3938
.add_system(cycle_color.system().label("action_handling"))
4039
.add_system(add_number.system().label("action_handling"))
40+
.add_system(scale_selected.system().after("action_handling"))
4141
.add_system(update_text_color.system().after("action_handling"))
4242
.run()
4343
}
4444

4545
// Tracks which entity is selected
46-
#[derive(Default)]
47-
struct Selected(Option<Entity>);
46+
struct Selected {
47+
entity: Entity,
48+
}
4849
// Marks entities as selectable
4950
struct Selectable;
5051
#[derive(Bundle)]
5152
struct InteractableBundle {
5253
#[bundle]
53-
text_bundle: Text2dBundle,
54+
text_bundle: TextBundle,
5455
selectable: Selectable,
5556
rainbow: Rainbow,
5657
cycle_color_events: Events<CycleColorAction>,
5758
add_number_events: Events<AddNumberAction>,
5859
}
5960

6061
impl InteractableBundle {
62+
// FIXME: fix position
6163
fn new(x: f32, y: f32, font_handle: &Handle<Font>) -> Self {
6264
InteractableBundle {
63-
text_bundle: Text2dBundle {
65+
text_bundle: TextBundle {
6466
text: Text::with_section(
6567
"0",
6668
TextStyle {
@@ -127,38 +129,145 @@ impl From<&Rainbow> for Color {
127129
struct CycleColorAction;
128130
// Or store data to be responded to
129131
struct AddNumberAction {
130-
number: u32,
132+
number: u8,
131133
}
132134

133135
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
136+
// Don't forget to include a camera!
137+
commands.spawn_bundle(UiCameraBundle::default());
138+
134139
let font_handle = asset_server.load("fonts/FiraSans-Bold.ttf");
135-
commands.spawn_bundle(InteractableBundle::new(-200.0, 0.0, &font_handle));
136-
commands.spawn_bundle(InteractableBundle::new(0.0, 0.0, &font_handle));
137-
commands.spawn_bundle(InteractableBundle::new(200.0, 0.0, &font_handle));
140+
// Spawns the first entity, and grabs the Entity id that is being allocated
141+
let first_entity = commands
142+
.spawn_bundle(InteractableBundle::new(-200.0, 400.0, &font_handle))
143+
.id();
144+
commands.insert_resource(Selected {
145+
entity: first_entity,
146+
});
147+
148+
commands.spawn_bundle(InteractableBundle::new(0.0, 400.0, &font_handle));
149+
commands.spawn_bundle(InteractableBundle::new(200.0, 400.0, &font_handle));
150+
}
151+
152+
enum CycleBehavior {
153+
Forward,
154+
Back,
138155
}
139156

140157
/// Cycles through entities appropriately based on input
141-
fn select_entity(mut query: Query<(Entity, &mut Text), With<Selectable>>, selected: Res<Selected>) {
158+
fn select_entity(
159+
mut query: Query<Entity, With<Selectable>>,
160+
mut selected: ResMut<Selected>,
161+
keyboard_input: Res<Input<KeyCode>>,
162+
) {
163+
let cycle_behavior: CycleBehavior = if keyboard_input.just_pressed(KeyCode::Tab) {
164+
if keyboard_input.pressed(KeyCode::LShift) || keyboard_input.pressed(KeyCode::RShift) {
165+
CycleBehavior::Back
166+
} else {
167+
CycleBehavior::Forward
168+
}
169+
} else if keyboard_input.just_pressed(KeyCode::Right) {
170+
CycleBehavior::Forward
171+
} else if keyboard_input.just_pressed(KeyCode::Left) {
172+
CycleBehavior::Back
173+
} else {
174+
return;
175+
};
176+
177+
let mut entities = Vec::<Entity>::new();
178+
// FIXME: Move to `.for_each` when https://github.com/bevyengine/bevy/issues/753 is resolved
179+
query.for_each_mut(|entity| entities.push(entity.clone()));
180+
181+
let current_position = entities.iter().position(|&e| e == selected.entity).unwrap() as isize;
182+
183+
let new_position = match cycle_behavior {
184+
// We have to convert to isize for this step to avoid underflows when current_postion == 0
185+
CycleBehavior::Forward => (current_position + 1).rem_euclid(entities.len() as isize),
186+
CycleBehavior::Back => (current_position - 1).rem_euclid(entities.len() as isize),
187+
};
188+
189+
selected.entity = entities[new_position as usize];
190+
}
191+
192+
fn scale_selected(
193+
mut query: Query<(Entity, &mut Text), With<Selectable>>,
194+
selected: Res<Selected>,
195+
) {
196+
// Only do work when the selection is changed
197+
if !selected.is_changed() {
198+
return;
199+
}
200+
201+
for (entity, mut text) in query.iter_mut() {
202+
if entity == selected.entity {
203+
text.sections[0].style.font_size = 90.0;
204+
} else {
205+
text.sections[0].style.font_size = 60.0;
206+
}
207+
}
142208
}
143209

144210
// FIXME: make this work using `EventWriter<T>` syntax and specialized behavior
211+
// FIXME: all input events are duplicated, due to just_pressed behavior
145212
/// Dispatches actions to entities based on the input
146213
/// Note that we can store several events at once!
147-
/// Try pressing both "Enter" and "Space" at once to cycle colors twice,
148-
/// Or both "1" and "3" to add 4 all at once to the selected display
214+
/// Try pressing both "Enter" and "Space" at the same time to cycle colors twice,
215+
/// Or both "1" and "3" to add 4 all at the same time to the selected display
149216
fn input_dispatch(
150-
mut query: Query<(
151-
&'static EventWriter<CycleColorAction>,
152-
&'static EventWriter<AddNumberAction>,
153-
)>,
217+
mut query: Query<
218+
(&mut Events<CycleColorAction>, &mut Events<AddNumberAction>),
219+
With<Selectable>,
220+
>,
154221
selected: Res<Selected>,
222+
keyboard_input: Res<Input<KeyCode>>,
155223
) {
224+
let (mut cycle_actions, mut add_actions) = query.get_mut(selected.entity).unwrap();
225+
226+
// Inputs for cycling colors
227+
// Normally, you'd probably want to use || on the inputs here,
228+
// but we're demonstrating the ability to process multiple events at once
229+
if keyboard_input.just_pressed(KeyCode::Return) {
230+
cycle_actions.send(CycleColorAction);
231+
}
232+
if keyboard_input.just_pressed(KeyCode::Space) {
233+
cycle_actions.send(CycleColorAction);
234+
}
235+
236+
// Inputs for sending numbers to be added
237+
if keyboard_input.just_pressed(KeyCode::Key1) {
238+
add_actions.send(AddNumberAction { number: 1 });
239+
}
240+
if keyboard_input.just_pressed(KeyCode::Key2) {
241+
add_actions.send(AddNumberAction { number: 2 });
242+
}
243+
if keyboard_input.just_pressed(KeyCode::Key3) {
244+
add_actions.send(AddNumberAction { number: 3 });
245+
}
246+
if keyboard_input.just_pressed(KeyCode::Key4) {
247+
add_actions.send(AddNumberAction { number: 4 });
248+
}
249+
if keyboard_input.just_pressed(KeyCode::Key5) {
250+
add_actions.send(AddNumberAction { number: 5 });
251+
}
252+
if keyboard_input.just_pressed(KeyCode::Key6) {
253+
add_actions.send(AddNumberAction { number: 6 });
254+
}
255+
if keyboard_input.just_pressed(KeyCode::Key7) {
256+
add_actions.send(AddNumberAction { number: 7 });
257+
}
258+
if keyboard_input.just_pressed(KeyCode::Key8) {
259+
add_actions.send(AddNumberAction { number: 8 });
260+
}
261+
if keyboard_input.just_pressed(KeyCode::Key9) {
262+
add_actions.send(AddNumberAction { number: 9 });
263+
}
156264
}
157265

158266
// FIXME: make this work using `EventReader<T>` syntax and specialized behavior
159-
fn cycle_color(mut query: Query<(&mut Rainbow, &'static EventReader<CycleColorAction>)>) {
160-
for (mut rainbow, cycle_color_action_queue) in query.iter_mut() {
161-
for _ in cycle_color_action_queue.iter() {
267+
fn cycle_color(mut query: Query<(&mut Rainbow, &mut Events<CycleColorAction>)>) {
268+
for (mut rainbow, action_queue) in query.iter_mut() {
269+
let mut reader = action_queue.get_reader();
270+
for _ in reader.iter(&action_queue) {
162271
*rainbow = rainbow.next().unwrap();
163272
}
164273
}
@@ -177,7 +286,10 @@ fn add_number(mut query: Query<(&mut Text, &Events<AddNumberAction>)>) {
177286
for (mut text, action_queue) in query.iter_mut() {
178287
let mut reader = action_queue.get_reader();
179288
for action in reader.iter(&action_queue) {
180-
// TODO: add the number
289+
let current_number: u8 = text.sections[0].value.clone().parse().unwrap();
290+
// Wrap addition, rather than overflowing
291+
let new_number = (current_number + action.number) % std::u8::MAX;
292+
text.sections[0].value = new_number.to_string();
181293
}
182294
}
183295
}

0 commit comments

Comments
 (0)