Skip to content

Commit f1a3505

Browse files
authored
Merge pull request #10 from shanecelis/master
Bump keyseq to 0.4.0 and add `action::trigger*` convenience systems, CHANGE NOTATION, and prep for bevy-input-sequence 0.6.0 release.
2 parents 5719b11 + 96ff851 commit f1a3505

File tree

17 files changed

+355
-156
lines changed

17 files changed

+355
-156
lines changed

CHANGELOG.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,21 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
## [0.4.0] - 2024-04-23
5+
## [unreleased]
6+
7+
## [0.6.0] - 2024-11-24
8+
9+
- Add `action::trigger` and `action::trigger_targets` convenience systems.
10+
- Bump keyseq to 0.4.0, which changes notation to be more standard: `Ctrl-A`
11+
instead of `ctrl-A`.
12+
13+
## [0.5.0] - 2024-06-05
14+
15+
### Features
16+
- Optimize look ups to incrementally search using O(log n) instead of O(m^2 log n). See [PR #7](https://github.com/not-elm/bevy-input-sequence/pull/7) for more details.
17+
18+
### Bugs
19+
- Fix bug where "W A S D" and "A S" sequences would match the latter pattern when "W A S P" was typed.
620

721
## [0.4.0] - 2024-04-23
822

@@ -12,7 +26,7 @@ All notable changes to this project will be documented in this file.
1226
- Use plugin.
1327
- Can configure schedule and system set.
1428
- Remove `GamepadEvent`; use system with input `In<Gamepad>`.
15-
- Add `IntoCondSystem` that adds `only_if()` conditions to `IntoSystems`.
29+
- Add `IntoCondSystem` that adds `only_if()` conditi:ons to `IntoSystems`.
1630
- Add `only_if` example.
1731
- Add `prelude` module for glob imports.
1832

Cargo.toml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "bevy-input-sequence"
3-
description = "Recognizes input sequences and send events"
4-
version = "0.5.0"
3+
description = "Recognizes and acts on input sequences"
4+
version = "0.6.0"
55
edition = "2021"
66
authors = ["elm", "Shane Celis <shane.celis@gmail.com>"]
77
keywords = [
@@ -18,26 +18,22 @@ readme = "README.md"
1818
license = "MIT OR Apache-2.0"
1919
repository = "https://github.com/elm-register/bevy-input-sequence"
2020

21-
2221
[[example]]
2322
name = "keycode"
2423
path = "examples/keycode.rs"
2524

26-
2725
[[example]]
2826
name = "gamepad_button"
2927
path = "examples/gamepad_button.rs"
3028

31-
3229
[[example]]
3330
name = "multiple_input"
3431
path = "examples/multiple_input.rs"
3532

36-
3733
[dependencies]
3834
bevy = { version = "0.14", default-features = false, features = [] }
3935
trie-rs = { version = "0.4" }
40-
keyseq = { version = "0.3.0", features = [ "bevy" ] }
36+
keyseq = { version = "0.4.1", features = [ "bevy" ] }
4137

4238
[dev-dependencies]
4339
bevy = "0.14"

README.md

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# bevy-input-sequence
22

3-
Detect input sequences from the keyboard or a gamepad.
3+
Recognizes and acts on input sequences from the keyboard or a gamepad.
44

55
# Use Cases
66

@@ -42,6 +42,7 @@ fn main() {
4242
}
4343

4444
fn setup(mut commands: Commands) {
45+
// Add key sequence.
4546
commands.add(
4647
KeySequence::new(say_hello,
4748
keyseq! { H I })
@@ -63,11 +64,11 @@ with `action::send_event()`.
6364
use bevy::prelude::*;
6465
use bevy_input_sequence::prelude::*;
6566

66-
// Define an event
67+
/// Define an event.
6768
#[derive(Event, Clone, Debug)]
6869
struct MyEvent;
6970

70-
// Add event as an key sequence
71+
/// Add event as an key sequence.
7172
fn main() {
7273
App::new()
7374
.add_plugins(MinimalPlugins)
@@ -80,7 +81,7 @@ fn main() {
8081
fn setup(mut commands: Commands) {
8182
commands.add(
8283
KeySequence::new(action::send_event(MyEvent),
83-
keyseq! { ctrl-E L M })
84+
keyseq! { Ctrl-E L M })
8485
);
8586
}
8687

@@ -101,11 +102,11 @@ take an input of `Gamepad`.
101102
use bevy::prelude::*;
102103
use bevy_input_sequence::prelude::*;
103104

104-
// Define an event
105+
/// Define an event.
105106
#[derive(Event, Clone, Debug)]
106107
struct MyEvent(Gamepad);
107108

108-
// Add event as an key sequence
109+
/// Add event as an key sequence.
109110
fn main() {
110111
App::new()
111112
.add_plugins(MinimalPlugins)
@@ -132,6 +133,41 @@ fn check_events(mut events: EventReader<MyEvent>) {
132133
}
133134
```
134135

136+
## Trigger an Event on Key Sequence
137+
138+
You can also trigger an event with `action::trigger()` or `action::trigger_targets()`.
139+
140+
```rust
141+
use bevy::prelude::*;
142+
use bevy_input_sequence::prelude::*;
143+
144+
/// Define an event.
145+
#[derive(Event, Clone, Debug)]
146+
struct MyEvent;
147+
148+
/// Add event as an key sequence.
149+
fn main() {
150+
App::new()
151+
.add_plugins(MinimalPlugins)
152+
.add_plugins(InputSequencePlugin::default())
153+
.add_event::<MyEvent>()
154+
.add_systems(Startup, setup)
155+
.observe(check_trigger)
156+
.update(); // Normally you'd run it here.
157+
}
158+
159+
fn setup(mut commands: Commands) {
160+
commands.add(
161+
KeySequence::new(action::trigger(MyEvent),
162+
keyseq! { Ctrl-E L M })
163+
);
164+
}
165+
166+
fn check_trigger(mut trigger: Trigger<MyEvent>) {
167+
info!("got event {:?}", trigger.event());
168+
}
169+
```
170+
135171
## KeySequence Creation Patterns
136172

137173
`KeySequence::new` now returns `KeySequenceBuilder`, which implements `Command`.
@@ -147,20 +183,20 @@ struct MyEvent;
147183
fn create_key_sequence(mut commands: Commands) {
148184
commands.add(KeySequence::new(
149185
action::send_event(bevy::app::AppExit::default()),
150-
keyseq! { ctrl-E L M }
186+
keyseq! { Ctrl-E L M }
151187
));
152188
}
153189

154190
fn create_key_sequence_and_add_it_to_an_entity(mut commands: Commands) {
155-
let parent = commands.spawn_empty().id();
156-
commands.entity(parent).add(KeySequence::new(
191+
let id = commands.spawn_empty().id();
192+
commands.entity(id).add(KeySequence::new(
157193
action::send_event(MyEvent),
158-
keyseq! { ctrl-E L M }
194+
keyseq! { Ctrl-E L M }
159195
));
160196
// OR
161197
commands.spawn_empty().add(KeySequence::new(
162198
action::send_event(MyEvent),
163-
keyseq! { ctrl-E L M }
199+
keyseq! { Ctrl-E L M }
164200
));
165201
}
166202
```
@@ -178,7 +214,7 @@ fn create_key_sequence_within_command(mut commands: Commands) {
178214
commands.add(|world: &mut World| {
179215
let builder = KeySequence::new(
180216
move || { info!("got it"); },
181-
keyseq! { ctrl-E L M }
217+
keyseq! { Ctrl-E L M }
182218
);
183219
let key_sequence: KeySequence = builder.build(world);
184220
// And then put it somewhere? It ought to go as a component.
@@ -199,7 +235,7 @@ cargo run --example keycode
199235

200236
## keymod
201237

202-
The `keymod` example recognizes `ctrl-W ctrl-D ctrl-S ctrl-A` and fires an event.
238+
The `keymod` example recognizes `Ctrl-W Ctrl-D Ctrl-S Ctrl-A` and fires an event.
203239

204240
``` sh
205241
cargo run --example keymod
@@ -254,8 +290,8 @@ cargo run --example run_if
254290

255291
| bevy-input-sequence | bevy |
256292
|---------------------|------|
257-
| 0.5 | 0.14 |
258-
| 0.3 ~ 0.4.0 | 0.13 |
293+
| 0.5 ~ 0.6 | 0.14 |
294+
| 0.3 ~ 0.4 | 0.13 |
259295
| 0.2 | 0.12 |
260296
| 0.1 | 0.11 |
261297

examples/keycode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ fn setup(mut commands: Commands) {
3939
commands.add(
4040
KeySequence::new(
4141
action::send_event(MyEvent(Direction::CounterClockwise)),
42-
keyseq!(W A S D),
42+
keyseq!{ W A S D },
4343
)
4444
.time_limit(Duration::from_secs(1)),
4545
);

examples/keymod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ fn setup(mut commands: Commands) {
1818
commands.add(
1919
KeySequence::new(
2020
action::send_event(MyEvent),
21-
keyseq!(ctrl-W ctrl-D ctrl-S ctrl-A),
21+
keyseq! { Ctrl-W Ctrl-D Ctrl-S Ctrl-A },
2222
)
2323
.time_limit(Duration::from_secs(1)),
2424
);
25-
println!("Press ctrl-W ctrl-D ctrl-S ctrl-A to emit event.");
25+
println!("Press Ctrl-W Ctrl-D Ctrl-S Ctrl-A to emit event.");
2626
}
2727

2828
fn input_sequence_event_system(mut er: EventReader<MyEvent>) {

examples/multiple_input.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn main() {
1717

1818
fn setup(mut commands: Commands) {
1919
commands.add(
20-
KeySequence::new(action::send_event(MyEvent(1, None)), keyseq!(W D S A))
20+
KeySequence::new(action::send_event(MyEvent(1, None)), keyseq! { W D S A })
2121
.time_limit(Duration::from_secs(5)),
2222
);
2323

@@ -35,7 +35,7 @@ fn setup(mut commands: Commands) {
3535
);
3636

3737
commands.add(
38-
KeySequence::new(action::send_event(MyEvent(3, None)), keyseq!(W A S D))
38+
KeySequence::new(action::send_event(MyEvent(3, None)), keyseq! { W A S D })
3939
.time_limit(Duration::from_secs(5)),
4040
);
4141

examples/only_if.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ fn main() {
3030
fn setup(mut commands: Commands) {
3131
commands.add(KeySequence::new(
3232
action::send_event(GlobalEvent),
33-
keyseq!(Escape),
33+
keyseq! { Escape },
3434
));
3535
commands.add(
3636
KeySequence::new(
3737
action::send_event(MyEvent).only_if(in_state(AppState::Game)),
38-
keyseq!(Space),
38+
keyseq! { Space },
3939
)
4040
.time_limit(Duration::from_secs(1)),
4141
);

examples/run_if.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn setup(mut commands: Commands) {
3131
commands.add(
3232
KeySequence::new(
3333
action::send_event(MyEvent).only_if(in_state(AppState::Game)),
34-
keyseq!(Space),
34+
keyseq! { Space },
3535
)
3636
.time_limit(Duration::from_secs(1)),
3737
);

src/action.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Common actions to do on key sequence matches
22
use bevy::ecs::{
33
event::{Event, EventWriter},
4+
observer::TriggerTargets,
5+
prelude::Commands,
46
system::In,
57
};
68

@@ -25,6 +27,23 @@ pub fn send_event<E: Event + Clone>(event: E) -> impl FnMut(EventWriter<E>) {
2527
}
2628
}
2729

30+
/// Trigger an event.
31+
pub fn trigger<E: Event + Clone>(event: E) -> impl FnMut(Commands) {
32+
move |mut commands: Commands| {
33+
commands.trigger(event.clone());
34+
}
35+
}
36+
37+
/// Trigger an event with targets.
38+
pub fn trigger_targets<E: Event + Clone, T: TriggerTargets + Clone>(
39+
event: E,
40+
targets: T,
41+
) -> impl FnMut(Commands) {
42+
move |mut commands: Commands| {
43+
commands.trigger_targets(event.clone(), targets.clone());
44+
}
45+
}
46+
2847
/// Sends an event with input, .e.g, [ButtonSequence](crate::input_sequence::ButtonSequence) provides a [Gamepad](bevy::input::gamepad::Gamepad) identifier.
2948
pub fn send_event_with_input<E: Event, Input: 'static, F: FnMut(Input) -> E>(
3049
mut f: F,

src/chord.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use bevy::{
22
input::keyboard::KeyCode,
3+
prelude::{Deref, DerefMut, Resource},
34
reflect::{Enum, Reflect},
45
};
56

6-
use std::fmt;
7+
use std::{collections::VecDeque, fmt};
78

89
use keyseq::Modifiers;
910

@@ -56,3 +57,10 @@ impl From<KeyCode> for KeyChord {
5657
pub(crate) fn is_modifier(key: KeyCode) -> bool {
5758
!Modifiers::from(key).is_empty()
5859
}
60+
61+
/// Manually add key chords to be processed as through they were pressed by the
62+
/// user.
63+
///
64+
/// Normally this does not need to be manipulated. It is a kind of escape hatch.
65+
#[derive(Resource, Debug, Deref, DerefMut, Default)]
66+
pub struct KeyChordQueue(pub VecDeque<KeyChord>);

0 commit comments

Comments
 (0)