use crate::input_sequence::InputSequence;
use bevy::prelude::{Entity, GamepadButton, In, Resource};
use std::collections::HashMap;
use trie_rs::{
inc_search::{IncSearch, Position},
map::{Trie, TrieBuilder},
};
#[derive(Resource, Default)]
pub struct ButtonSequenceCache {
trie: Option<Trie<GamepadButton, InputSequence<GamepadButton, In<Entity>>>>,
position: HashMap<Entity, Position>,
}
impl ButtonSequenceCache {
pub fn trie<'a>(
&mut self,
sequences: impl Iterator<Item = &'a InputSequence<GamepadButton, In<Entity>>>,
) -> &Trie<GamepadButton, InputSequence<GamepadButton, In<Entity>>> {
self.trie.get_or_insert_with(|| {
let mut builder: TrieBuilder<GamepadButton, InputSequence<GamepadButton, In<Entity>>> =
TrieBuilder::new();
for sequence in sequences {
builder.insert(sequence.acts.clone(), sequence.clone());
}
assert!(
self.position.is_empty(),
"Position should be none when rebuilding trie"
);
builder.build()
})
}
pub fn store(&mut self, key: Entity, position: Position) {
self.position.insert(key, position);
}
pub fn recall<'a, 'b>(
&'b mut self,
key: Entity,
sequences: impl Iterator<Item = &'a InputSequence<GamepadButton, In<Entity>>>,
) -> IncSearch<'a, GamepadButton, InputSequence<GamepadButton, In<Entity>>>
where
'b: 'a,
{
let position = self.position.get(&key).cloned();
let trie = self.trie(sequences);
position
.map(move |p| IncSearch::resume(trie, p))
.unwrap_or_else(move || trie.inc_search())
}
pub fn reset(&mut self) {
self.trie = None;
self.position.clear();
}
}