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}