gooey/interface/controller/
bindings.rs

1//! Serializable parameterized bindings
2
3use derive_builder::Builder;
4use serde::{Deserialize, Serialize};
5
6use crate::{application, Application};
7use crate::interface::controller::controls;
8use crate::interface::view::input;
9
10use super::Controls;
11
12pub use BindingsBuilder as Builder;
13
14/// Associates inputs with controls for a specific application
15#[derive(Clone, Debug, Builder, Deserialize, Serialize)]
16#[builder(pattern="owned", build_fn(skip), setter(strip_option))]
17pub struct Bindings <A : Application = application::Default> {
18  #[builder(default)]
19  #[serde(skip_serializing_if = "Vec::is_empty")]
20  pub buttons    : Vec <controls::button::Binding <A::ButtonControls>>,
21  #[builder(default)]
22  #[serde(skip_serializing_if = "Option::is_none")]
23  pub any_button : Option <controls::button::Control <A::ButtonControls>>,
24  #[builder(default)]
25  #[serde(skip_serializing_if = "Option::is_none")]
26  pub system     : Option <controls::system::Control <A::SystemControls>>,
27  #[builder(default)]
28  #[serde(skip_serializing_if = "Option::is_none")]
29  pub text       : Option <controls::text::Control <A::TextControls>>,
30  #[builder(default)]
31  #[serde(skip_serializing_if = "Option::is_none")]
32  pub motion     : Option <controls::motion::Control <A::MotionControls>>,
33  #[builder(default)]
34  #[serde(skip_serializing_if = "Option::is_none")]
35  pub pointer    : Option <controls::pointer::Control <A::PointerControls>>
36  // TODO: axis bindings: each axis can be bound to a different function
37  // TODO: other bindings
38}
39
40impl <A : Application> Bindings <A> {
41  /// Get a subset of the bindings for the given controls
42  pub fn get_bindings (&self, controls : &Controls) -> Self {
43    let buttons = {
44      let mut buttons = vec![];
45      for c in controls.buttons.iter() {
46        let mut found : Vec <controls::button::Binding <_>> = self.buttons.iter()
47          .filter (|controls::button::Binding (controls, _, _)| controls == c)
48          .cloned().collect();
49        if found.is_empty() {
50          log::debug!("get_bindings: unbound controls: {c:?}");
51        } else {
52          buttons.append (&mut found);
53        }
54      }
55      buttons
56    };
57    let any_button = self.any_button.clone()
58      .filter (|control| controls.buttons.contains (&control.0));
59    let system     = self.system.clone().filter (|control|
60      Some (control) == controls.system.clone().map (Into::into).as_ref());
61    let text       = self.text.clone().filter (|control|
62      Some (control) == controls.text.clone().map (Into::into).as_ref());
63    let motion     = self.motion.clone().filter (|control|
64      Some (control) == controls.motion.clone().map (Into::into).as_ref());
65    let pointer    = self.pointer.clone().filter (|control|
66      Some (control) == controls.pointer.clone().map (Into::into).as_ref());
67    Bindings { buttons, any_button, system, text, motion, pointer }
68  }
69
70  /// Returns an empty vector if the controls was unbound
71  pub fn get_buttons (&self, control : &controls::Button)
72    -> Vec <input::Button>
73  {
74    use controls::button;
75    let mut buttons = vec![];
76    for button::Binding (c, button, _) in self.buttons.iter() {
77      if c == control {
78        buttons.push (*button);
79      }
80    }
81    buttons
82  }
83}
84
85impl <A : Application> Bindings <A> {
86  pub const fn empty() -> Self {
87    Bindings {
88      buttons:    vec![],
89      any_button: None,
90      system:     None,
91      text:       None,
92      motion:     None,
93      pointer:    None
94    }
95  }
96}
97
98impl <A : Application> BindingsBuilder <A> {
99  pub const fn new() -> Self {
100    BindingsBuilder {
101      buttons:    None,
102      any_button: None,
103      system:     None,
104      text:       None,
105      motion:     None,
106      pointer:    None
107    }
108  }
109
110  pub fn build (self) -> Bindings <A> {
111    Bindings {
112      buttons:    self.buttons.unwrap_or_default(),
113      any_button: self.any_button.unwrap_or_default(),
114      system:     self.system.unwrap_or_default(),
115      text:       self.text.unwrap_or_default(),
116      motion:     self.motion.unwrap_or_default(),
117      pointer:    self.pointer.unwrap_or_default()
118    }
119  }
120}