amethyst_input 0.15.3

Input rebinding
Documentation
use serde::{Deserialize, Serialize};

use super::{Button, ControllerAxis, MouseAxis};

/// Represents any input represented by a float value from -1 to 1.
/// Retrieve the value of this with [axis_value](struct.InputHandler.html#method.axis_value).
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub enum Axis {
    /// Represents an emulated analogue axis made up of pair of digital inputs,
    /// like W and S keyboard buttons or `DPadUp` and `DPadDown` controller buttons.
    Emulated {
        /// Positive button, when pressed down axis value will return 1 if `neg` is not pressed down.
        pos: Button,
        /// Negative button, when pressed down axis value will return -1 if `pos` is not pressed down.
        neg: Button,
    },
    /// Represents an analogue axis of a controller.
    Controller {
        /// A number representing a specific controller, assigned and reused in order of connection.
        controller_id: u32,
        /// The axis being bound
        axis: ControllerAxis,
        /// Whether or not to multiply the axis value by -1.
        invert: bool,
        /// Treat input values from -dead_zone to dead_zone as 0,
        /// linearly interpolate remaining ranges.
        dead_zone: f64,
    },
    /// Represents a mouse as a 2D input device
    Mouse {
        /// The axis being bound
        axis: MouseAxis,
        /// Should the API be allowed to return values outside [-1..1]?
        over_extendable: bool,
        /// Zone to which the movement is relative
        radius: f32,
    },
    /// Represents the wheel on a PC mouse.
    MouseWheel {
        /// If this value is true then this axis is for the horizontal mouse wheel rather than the vertical mouse wheel.
        ///
        /// You almost always want this false.
        horizontal: bool,
    },
    /// Represents multiple input alternatives. Allows to bind more than one input to a single axis.
    Multiple(Vec<Axis>),
}

pub(super) enum Conflict {
    Button,
    ControllerAxis,
    MouseAxis,
    MouseWheelAxis,
}

impl Axis {
    pub(super) fn conflicts_with_button(&self, other: &Button) -> bool {
        match self {
            Axis::Emulated { pos, neg } => other == pos || other == neg,
            Axis::Multiple(axes) => axes.iter().any(|a| a.conflicts_with_button(other)),
            _ => false,
        }
    }

    pub(super) fn conflicts_with_axis(&self, other: &Axis) -> Option<Conflict> {
        if let Axis::Multiple(axes) = other {
            if let Some(inner_conflict) = axes
                .iter()
                .map(|a| self.conflicts_with_axis(a))
                .find(|x| x.is_some())
            {
                return inner_conflict;
            }
        }

        match self {
            Axis::Emulated {
                pos: ref self_pos,
                neg: ref self_neg,
            } => {
                if let Axis::Emulated { pos, neg } = other {
                    if self_pos == pos || self_pos == neg || self_neg == pos || self_neg == neg {
                        return Some(Conflict::Button);
                    }
                }
            }
            Axis::Controller {
                controller_id: ref self_controller_id,
                axis: ref self_axis,
                ..
            } => {
                if let Axis::Controller {
                    controller_id,
                    axis,
                    ..
                } = other
                {
                    if self_controller_id == controller_id && self_axis == axis {
                        return Some(Conflict::ControllerAxis);
                    }
                }
            }
            Axis::Mouse {
                axis: self_axis, ..
            } => {
                if let Axis::Mouse { axis, .. } = other {
                    if self_axis == axis {
                        return Some(Conflict::MouseAxis);
                    }
                }
            }
            Axis::MouseWheel {
                horizontal: self_horizontal,
            } => {
                if let Axis::MouseWheel { horizontal } = other {
                    if self_horizontal == horizontal {
                        return Some(Conflict::MouseWheelAxis);
                    }
                }
            }
            Axis::Multiple(axes) => {
                if let Some(inner_conflict) = axes
                    .iter()
                    .map(|a| a.conflicts_with_axis(other))
                    .find(|x| x.is_some())
                {
                    return inner_conflict;
                }
            }
        }
        None
    }
}