diff --git a/src/chord.rs b/src/chord.rs index e1c4428..5e0da45 100644 --- a/src/chord.rs +++ b/src/chord.rs @@ -1,9 +1,8 @@ use bevy::{ - input::keyboard::KeyCode, - reflect::{Enum, Reflect}, + input::keyboard::KeyCode, prelude::{Deref, DerefMut, Resource}, reflect::{Enum, Reflect} }; -use std::fmt; +use std::{collections::VecDeque, fmt}; use keyseq::Modifiers; @@ -56,3 +55,10 @@ impl From for KeyChord { pub(crate) fn is_modifier(key: KeyCode) -> bool { !Modifiers::from(key).is_empty() } + +/// Manually add key chords to be processed as through they were pressed by the +/// user. +/// +/// Normally this does not need to be manipulated. It is a kind of escape hatch. +#[derive(Resource, Debug, Deref, DerefMut, Default)] +pub struct KeyChordQueue(pub VecDeque); diff --git a/src/lib.rs b/src/lib.rs index 2b7884b..6cf22a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,10 +2,6 @@ #![doc = include_str!("../README.md")] #![forbid(missing_docs)] -pub use chord::KeyChord; -pub use plugin::InputSequencePlugin; -pub use time_limit::TimeLimit; - pub mod action; pub mod cache; mod chord; @@ -15,6 +11,10 @@ pub mod input_sequence; mod plugin; mod time_limit; +pub use chord::{KeyChord, KeyChordQueue}; +pub use plugin::{InputSequencePlugin}; +pub use time_limit::TimeLimit; + pub use keyseq::{ bevy::{pkey as key, pkeyseq as keyseq}, Modifiers, @@ -24,8 +24,7 @@ pub use keyseq::{ pub mod prelude { pub use super::input_sequence::{ButtonSequence, InputSequence, KeySequence}; pub use super::{action, keyseq, InputSequencePlugin, Modifiers, TimeLimit}; - - pub use super::chord::KeyChord; + pub use super::{KeyChordQueue, KeyChord}; pub use super::cond_system::IntoCondSystem; pub use std::time::Duration; } diff --git a/src/plugin.rs b/src/plugin.rs index 1fb7cb4..510bd5c 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -20,7 +20,7 @@ use std::collections::{HashMap, VecDeque}; use crate::{ cache::InputSequenceCache, - chord::is_modifier, + chord::{KeyChordQueue, is_modifier}, frame_time::FrameTime, input_sequence::{ButtonSequence, InputSequence, KeySequence}, KeyChord, Modifiers, @@ -53,6 +53,7 @@ impl Plugin for InputSequencePlugin { { // Add key sequence. app.init_resource::>(); + app.init_resource::(); for (schedule, set) in &self.schedules { if let Some(set) = set { @@ -233,6 +234,7 @@ fn key_sequence_matcher( mut cache: ResMut>, frame_count: Res, mut commands: Commands, + mut keychord_queue: ResMut, ) { let mods = Modifiers::from(&keys); let now = FrameTime { @@ -240,14 +242,15 @@ fn key_sequence_matcher( time: time.elapsed_seconds(), }; let maybe_start = last_times.front().cloned(); - let mut input = keys + let mut input = keychord_queue.drain(..).chain( + keys .get_just_pressed() .filter(|k| !is_modifier(**k)) .map(|k| { let chord = KeyChord(mods, *k); last_times.push_back(now.clone()); chord - }) + })) .peekable(); if input.peek().is_none() { return; @@ -297,11 +300,22 @@ where None => { search.reset(); // This could be the start of a new sequence. - if search.query(&k).is_none() { - // This may not be necessary. - search.reset(); + // + // Let's check it. + match search.query(&k) { + Some(Answer::Match) => { + let result = Some(search.value().unwrap()); + search.reset(); + result + } + Some(Answer::PrefixAndMatch) => Some(search.value().unwrap()), + Some(Answer::Prefix) => None, + None => { + // This may not be necessary. + search.reset(); + None + } } - None } } })