feat: bindings deduplication

This commit is contained in:
2026-09-05 04:13:44 +00:00
parent a75fb650e3
commit d80bd8b03a
+40 -4
View File
@@ -495,10 +495,16 @@ impl<Gs: GameState> Default for Bindings<Gs> {
impl<Gs: GameState> Bindings<Gs> {
pub fn new(bindings: Vec<Binding<Gs>>) -> Self {
Self {
list: bindings,
let mut result = Self {
list: Vec::with_capacity(bindings.len()),
..Default::default()
};
// To avoid duplicates
for binding in bindings {
result.force_push(binding);
}
result
}
pub fn customizable(mut self) -> Self {
@@ -517,6 +523,9 @@ impl<Gs: GameState> Bindings<Gs> {
}
pub fn force_push(&mut self, binding: Binding<Gs>) {
if self.list.contains(&binding) {
return;
}
self.list.push(binding);
}
@@ -525,7 +534,7 @@ impl<Gs: GameState> Bindings<Gs> {
warn!("You try to push binding to immutable bindings");
return;
}
self.list.push(binding);
self.force_push(binding);
}
pub fn clear(&mut self) {
@@ -716,9 +725,16 @@ impl<A: Action, Gs: GameState> Controls<A, Gs> {
}
}
#[cfg(all(test, feature = "logical-keyboard"))]
#[cfg(all(
test,
feature = "logical-keyboard",
not(feature = "serialize"),
not(feature = "reflect"),
not(feature = "inspector-egui")
))]
mod tests {
use super::*;
use bevy_state::state::States;
#[test]
fn keyboard_variants_are_distinct() {
@@ -727,4 +743,24 @@ mod tests {
assert_ne!(physical, logical);
}
#[derive(States, PartialEq, Eq, Clone, Hash, Debug, Default)]
enum TestState {
#[default]
Playing,
}
impl crate::contract::GameState for TestState {}
#[test]
fn bindings_reject_duplicates() {
let binding: Binding<TestState> =
Binding::from_single(InputType::Keyboard(Keyboard::KeyCode(KeyCode::KeyH)));
let mut bindings = Bindings::new(vec![binding.clone(), binding.clone()]).customizable();
bindings.push(binding.clone());
bindings.force_push(binding);
assert_eq!(bindings.iter().count(), 1);
}
}