bevy_input_sequence/cache/
button.rs

1//! Cache the trie for reuse.
2use crate::input_sequence::InputSequence;
3use bevy::prelude::{Entity, GamepadButton, In, Resource};
4use std::collections::HashMap;
5use trie_rs::{
6    inc_search::{IncSearch, Position},
7    map::{Trie, TrieBuilder},
8};
9
10/// Contains the trie for gamepad button sequences.
11#[derive(Resource, Default)]
12pub struct ButtonSequenceCache {
13    trie: Option<Trie<GamepadButton, InputSequence<GamepadButton, In<Entity>>>>,
14    position: HashMap<Entity, Position>,
15}
16
17impl ButtonSequenceCache {
18    /// Retrieve the cached trie without iterating through `sequences`. Or if
19    /// the cache has been invalidated, build and cache a new trie using the
20    /// `sequences` iterator.
21    pub fn trie<'a>(
22        &mut self,
23        sequences: impl Iterator<Item = &'a InputSequence<GamepadButton, In<Entity>>>,
24    ) -> &Trie<GamepadButton, InputSequence<GamepadButton, In<Entity>>> {
25        self.trie.get_or_insert_with(|| {
26            let mut builder: TrieBuilder<GamepadButton, InputSequence<GamepadButton, In<Entity>>> =
27                TrieBuilder::new();
28            for sequence in sequences {
29                builder.insert(sequence.acts.clone(), sequence.clone());
30            }
31            // info!(
32            //     "Building trie for {} input sequences.",
33            //     A::short_type_path()
34            // );
35            assert!(
36                self.position.is_empty(),
37                "Position should be none when rebuilding trie"
38            );
39            builder.build()
40        })
41    }
42
43    /// Store a search.
44    pub fn store(&mut self, key: Entity, position: Position) {
45        self.position.insert(key, position);
46    }
47
48    /// Recall a search OR create a new search.
49    pub fn recall<'a, 'b>(
50        &'b mut self,
51        key: Entity,
52        sequences: impl Iterator<Item = &'a InputSequence<GamepadButton, In<Entity>>>,
53    ) -> IncSearch<'a, GamepadButton, InputSequence<GamepadButton, In<Entity>>>
54    where
55        'b: 'a,
56    {
57        let position = self.position.get(&key).cloned();
58        let trie = self.trie(sequences);
59        position
60            .map(move |p| IncSearch::resume(trie, p))
61            .unwrap_or_else(move || trie.inc_search())
62    }
63
64    /// Clears the cache.
65    pub fn reset(&mut self) {
66        self.trie = None;
67        self.position.clear();
68    }
69}