aboutsummaryrefslogtreecommitdiff
path: root/src/input/binding.rs
diff options
context:
space:
mode:
authorArne Dußin2021-01-17 14:19:59 +0100
committerArne Dußin2021-01-17 14:19:59 +0100
commitb019d10df4080fdb0ab57445040d24f9b14abdac (patch)
tree268305b1024f8a15a88eb72f593fcfab0f0e8d61 /src/input/binding.rs
parentb58e965327deef14d6414a912bb6698c6f745ce9 (diff)
parent51b7747e62c189d430318c67368a5c84e50ece61 (diff)
downloadgraf_karto-b019d10df4080fdb0ab57445040d24f9b14abdac.tar.gz
graf_karto-b019d10df4080fdb0ab57445040d24f9b14abdac.zip
Merge branch 'master' into net
Diffstat (limited to 'src/input/binding.rs')
-rw-r--r--src/input/binding.rs123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/input/binding.rs b/src/input/binding.rs
new file mode 100644
index 0000000..386fb66
--- /dev/null
+++ b/src/input/binding.rs
@@ -0,0 +1,123 @@
+//! Bindings module, which is a key combination that does something when pressed.
+
+use super::Button;
+use raylib::RaylibHandle;
+use serde::{Deserialize, Serialize};
+
+/// Binding struct, which holds any number of buttons (keyboard and mouse may be mixed, if desired)
+#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub struct Binding {
+ buttons: Vec<Button>,
+}
+
+impl Binding {
+ /// Create a new binding from a range of buttons. The button order does not matter, but at least
+ /// one button must be supplied.
+ pub fn new(buttons: Vec<Button>) -> Self {
+ if buttons.is_empty() {
+ panic!("Tried to create a binding without any keys.");
+ }
+
+ Self { buttons }
+ }
+
+ /// Returns `true` if only mouse buttons are present in this binding, otherwise false.
+ pub fn mouse_only(&self) -> bool {
+ for button in &self.buttons {
+ match button {
+ Button::Mouse(_) => continue,
+ _ => return false,
+ }
+ }
+
+ true
+ }
+
+ /// Returns `true` if only keyboard buttons are present in this binding, otherwise false.
+ pub fn keyboard_only(&self) -> bool {
+ for button in &self.buttons {
+ match button {
+ Button::Scancode(_) | Button::Text(_) => continue,
+ _ => return false,
+ }
+ }
+
+ true
+ }
+
+ /// Returns `true` if at least one mouse button is required for this binding to work.
+ pub fn has_mouse_component(&self) -> bool {
+ self.buttons.iter().any(|b| {
+ if let Button::Mouse(_) = b {
+ true
+ } else {
+ false
+ }
+ })
+ }
+
+ /// Returns `true` if at least one keyboard button is required for this binding to work.
+ pub fn has_keyboard_component(&self) -> bool {
+ self.buttons.iter().any(|b| match b {
+ Button::Scancode(_) | Button::Text(_) => true,
+ _ => false,
+ })
+ }
+
+ /// Checks if this binding was pressed this frame. Heavily dependent on input struct working
+ /// correctly.
+ pub(super) fn is_pressed(
+ &self,
+ allow_mouse: bool,
+ allow_keyboard: bool,
+ text: &str,
+ rl: &RaylibHandle,
+ ) -> bool {
+ let mut distinct_press = false;
+ for button in &self.buttons {
+ match *button {
+ Button::Mouse(mouse_button) => {
+ if !allow_mouse || !rl.is_mouse_button_down(mouse_button.into()) {
+ return false;
+ }
+
+ /* Check if the button has been pressed in this frame exactly.
+ * This prevents activating the same keybinding every frame
+ * while the buttons are being held down.
+ */
+ if rl.is_mouse_button_pressed(mouse_button.into()) {
+ distinct_press = true;
+ }
+ }
+ Button::Scancode(code) => {
+ if !allow_keyboard || !rl.is_key_down(code.into()) {
+ return false;
+ }
+
+ // Check the same as with the mouse button.
+ if rl.is_key_pressed(code.into()) {
+ distinct_press = true;
+ }
+ }
+ Button::Text(c) => {
+ if !allow_keyboard || !text.contains(c) {
+ return false;
+ }
+
+ // Always distinct, since on triggering, the text is cleared.
+ distinct_press = true;
+ }
+ }
+ }
+
+ distinct_press
+ }
+}
+
+impl From<Button> for Binding {
+ fn from(button: Button) -> Self {
+ Self {
+ buttons: vec![button],
+ }
+ }
+}