bevy_input_sequence/cache/
button.rs

1//! Cache the trie for reuse.
2use crate::input_sequence::InputSequence;
3use bevy::{
4    ecs::prelude::Resource,
5    prelude::{Entity, GamepadButton, In},
6};
7use std::collections::HashMap;
8use trie_rs::{
9    inc_search::{IncSearch, Position},
10    map::{Trie, TrieBuilder},
11};
12
13/// Contains the trie for gamepad button sequences.
14#[derive(Resource, Default)]
15pub struct ButtonSequenceCache {
16    trie: Option<Trie<GamepadButton, InputSequence<GamepadButton, In<Entity>>>>,
17    position: HashMap<Entity, Position>,
18}
19
20impl ButtonSequenceCache {
21    /// Retrieve the cached trie without iterating through `sequences`. Or if
22    /// the cache has been invalidated, build and cache a new trie using the
23    /// `sequences` iterator.
24    pub fn trie<'a>(
25        &mut self,
26        sequences: impl Iterator<Item = &'a InputSequence<GamepadButton, In<Entity>>>,
27    ) -> &Trie<GamepadButton, InputSequence<GamepadButton, In<Entity>>> {
28        self.trie.get_or_insert_with(|| {
29            let mut builder: TrieBuilder<GamepadButton, InputSequence<GamepadButton, In<Entity>>> =
30                TrieBuilder::new();
31            for sequence in sequences {
32                builder.insert(sequence.acts.clone(), sequence.clone());
33            }
34            // info!(
35            //     "Building trie for {} input sequences.",
36            //     A::short_type_path()
37            // );
38            assert!(
39                self.position.is_empty(),
40                "Position should be none when rebuilding trie"
41            );
42            builder.build()
43        })
44    }
45
46    /// Store a search.
47    pub fn store(&mut self, key: Entity, position: Position) {
48        self.position.insert(key, position);
49    }
50
51    /// Recall a search OR create a new search.
52    pub fn recall<'a, 'b>(
53        &'b mut self,
54        key: Entity,
55        sequences: impl Iterator<Item = &'a InputSequence<GamepadButton, In<Entity>>>,
56    ) -> IncSearch<'a, GamepadButton, InputSequence<GamepadButton, In<Entity>>>
57    where
58        'b: 'a,
59    {
60        let position = self.position.get(&key).cloned();
61        let trie = self.trie(sequences);
62        position
63            .map(move |p| IncSearch::resume(trie, p))
64            .unwrap_or_else(move || trie.inc_search())
65    }
66
67    // impl<'i, A, I> ButtonSequenceCache<'i, A, I>
68    // where
69    //     A: Ord + Clone + Send + Sync + TypePath + 'static,
70    //     I: SystemInput + Send + Sync,
71    //     I::Inner<'i>: Clone + Eq + Hash + 'static,
72    // {
73    //     // /// Retrieve the cached trie without iterating through `sequences`. Or if
74    //     // /// the cache has been invalidated, build and cache a new trie using the
75    //     // /// `sequences` iterator.
76    //     // pub fn trie<'a>(
77    //     //     &mut self,
78    //     //     sequences: impl Iterator<Item = &'a InputSequence<A, I>>,
79    //     // ) -> &Trie<A, InputSequence<A, I>> {
80    //     //     self.trie.get_or_insert_with(|| {
81    //     //         let mut builder: TrieBuilder<A, InputSequence<A, I>> = TrieBuilder::new();
82    //     //         for sequence in sequences {
83    //     //             builder.insert(sequence.acts.clone(), sequence.clone());
84    //     //         }
85    //     //         // info!(
86    //     //         //     "Building trie for {} input sequences.",
87    //     //         //     A::short_type_path()
88    //     //         // );
89    //     //         assert!(
90    //     //             self.position.is_empty(),
91    //     //             "Position should be none when rebuilding trie"
92    //     //         );
93    //     //         builder.build()
94    //     //     })
95    //     // }
96
97    //     // /// Store a search.
98    //     // pub fn store(&mut self, key: I, position: Position) {
99    //     //     self.position.insert(key, position);
100    //     // }
101
102    //     // /// Recall a search OR create a new search.
103    //     // pub fn recall<'a, 'b>(
104    //     //     &'b mut self,
105    //     //     key: I,
106    //     //     sequences: impl Iterator<Item = &'a InputSequence<A, I>>,
107    //     // ) -> IncSearch<'a, A, InputSequence<A, I>>
108    //     // where
109    //     //     'b: 'a,
110    //     // {
111    //     //     let position = self.position.get(&key).cloned();
112    //     //     let trie = self.trie(sequences);
113    //     //     position
114    //     //         .map(move |p| IncSearch::resume(trie, p))
115    //     //         .unwrap_or_else(move || trie.inc_search())
116    //     // }
117    // }
118
119    /// Clears the cache.
120    pub fn reset(&mut self) {
121        self.trie = None;
122        self.position.clear();
123    }
124}