pub mod axis;
pub mod button;
pub mod manager;
mod plugins;
mod systems;
use std::hash::Hash;
use button::ActionBinding;
pub use plugins::{InputManagementPlugin, InputManagementPluginSimple};
use bevy::{
input::{
gamepad::{GamepadAxis, GamepadButton},
keyboard::KeyCode,
mouse::MouseButton,
},
math::Vec2,
platform::collections::HashMap,
prelude::{Component, Entity, Message},
};
use crate::{
axis::{DualValueBinding, MouseAxis, ValueBinding},
button::ButtonState,
};
pub trait BindEvent: Message {}
impl<T> BindEvent for T where T: Message {}
#[derive(Debug, Clone)]
pub enum InputValue {
Pressed(bool),
Value(f32),
}
impl From<f32> for InputValue {
fn from(value: f32) -> Self {
Self::Value(value)
}
}
impl From<bool> for InputValue {
fn from(value: bool) -> Self {
Self::Pressed(value)
}
}
impl Default for InputValue {
fn default() -> Self {
Self::Pressed(false)
}
}
impl InputValue {
pub fn is_pressed(&self) -> bool {
match self {
InputValue::Pressed(p) => *p,
InputValue::Value(val) => value_to_press(*val),
}
}
pub fn get_value(&self) -> f32 {
match self {
InputValue::Pressed(p) => pressed_to_value(*p),
InputValue::Value(val) => *val,
}
}
}
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum BevyAxisKind {
MouseAxis(MouseAxis),
GamepadAxis(GamepadAxis),
GamepadButton(GamepadButton),
}
impl From<MouseAxis> for BevyAxisKind {
fn from(value: MouseAxis) -> Self {
Self::MouseAxis(value)
}
}
impl From<GamepadAxis> for BevyAxisKind {
fn from(value: GamepadAxis) -> Self {
Self::GamepadAxis(value)
}
}
impl From<GamepadButton> for BevyAxisKind {
fn from(value: GamepadButton) -> Self {
Self::GamepadButton(value)
}
}
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum BevyButtonKind {
GamepadButton(GamepadButton),
KeyCode(KeyCode),
MouseButton(MouseButton),
}
impl From<GamepadButton> for BevyButtonKind {
fn from(value: GamepadButton) -> Self {
Self::GamepadButton(value)
}
}
impl From<KeyCode> for BevyButtonKind {
fn from(value: KeyCode) -> Self {
Self::KeyCode(value)
}
}
impl From<MouseButton> for BevyButtonKind {
fn from(value: MouseButton) -> Self {
Self::MouseButton(value)
}
}
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum BevyInputKind {
Button(BevyButtonKind),
Axis(BevyAxisKind),
}
impl From<BevyButtonKind> for BevyInputKind {
fn from(value: BevyButtonKind) -> Self {
Self::Button(value)
}
}
impl From<BevyAxisKind> for BevyInputKind {
fn from(value: BevyAxisKind) -> Self {
Self::Axis(value)
}
}
impl From<MouseAxis> for BevyInputKind {
fn from(value: MouseAxis) -> Self {
let new: BevyAxisKind = value.into();
new.into()
}
}
impl From<GamepadAxis> for BevyInputKind {
fn from(value: GamepadAxis) -> Self {
let new: BevyAxisKind = value.into();
new.into()
}
}
impl From<GamepadButton> for BevyInputKind {
fn from(value: GamepadButton) -> Self {
let new: BevyButtonKind = value.into();
new.into()
}
}
impl From<KeyCode> for BevyInputKind {
fn from(value: KeyCode) -> Self {
let new: BevyButtonKind = value.into();
new.into()
}
}
impl From<MouseButton> for BevyInputKind {
fn from(value: MouseButton) -> Self {
let new: BevyButtonKind = value.into();
new.into()
}
}
#[derive(Debug, Message)]
pub struct SimpleMessage;
pub enum InputBinding<T> {
Action(ActionBinding<T>),
Value(ValueBinding<T>),
DualValue(DualValueBinding<T>),
}
impl<T> InputBinding<T> {
pub fn mock_press(&mut self, pressed: bool) {
match self {
InputBinding::Action(action_binding) => action_binding.mock(pressed),
InputBinding::Value(value_binding) => value_binding.mock(pressed_to_value(pressed)),
InputBinding::DualValue(dual_value_binding) => {
dual_value_binding.mock_x(pressed_to_value(pressed));
dual_value_binding.mock_y(pressed_to_value(pressed));
}
}
}
pub fn mock_value(&mut self, value: f32) {
match self {
InputBinding::Action(action_binding) => {
action_binding.mock(value_to_press(value));
}
InputBinding::Value(value_binding) => value_binding.mock(value),
InputBinding::DualValue(dual_value_binding) => {
dual_value_binding.mock_x(value);
dual_value_binding.mock_y(value);
}
}
}
pub fn mock_x_value(&mut self, value: f32) {
match self {
InputBinding::Action(action_binding) => {
action_binding.mock(value_to_press(value));
}
InputBinding::Value(value_binding) => value_binding.mock(value),
InputBinding::DualValue(dual_value_binding) => {
dual_value_binding.mock_x(value);
}
}
}
pub fn mock_y_value(&mut self, value: f32) {
match self {
InputBinding::Action(action_binding) => {
action_binding.mock(value_to_press(value));
}
InputBinding::Value(value_binding) => value_binding.mock(value),
InputBinding::DualValue(dual_value_binding) => {
dual_value_binding.mock_y(value);
}
}
}
pub fn mock_clear(&mut self) {
match self {
InputBinding::Action(action_binding) => action_binding.mock_clear(),
InputBinding::Value(value_binding) => value_binding.mock_clear(),
InputBinding::DualValue(dual_value_binding) => {
dual_value_binding.mock_clear();
}
}
}
pub fn input_kinds(&self) -> Vec<BevyInputKind> {
match self {
InputBinding::Action(action_binding) => action_binding.input_kinds(),
InputBinding::Value(value_binding) => value_binding.input_kinds(),
InputBinding::DualValue(dual_value_binding) => dual_value_binding.input_kinds(),
}
}
pub fn state(&self) -> ButtonState {
match self {
InputBinding::Action(action_binding) => *action_binding.state(),
InputBinding::Value(value_binding) => ButtonState {
kind: if value_binding.value() == 0. {
button::ActionableState::Pressed
} else {
button::ActionableState::Released
},
start: value_binding.last_transition(),
},
InputBinding::DualValue(dual_value_binding) => {
let out = dual_value_binding.value();
ButtonState {
kind: if out.x == 0. && out.y == 0. {
button::ActionableState::Released
} else {
button::ActionableState::Pressed
},
start: dual_value_binding.last_transition(),
}
}
}
}
pub fn pressed(&self) -> bool {
match self {
InputBinding::Action(action_binding) => action_binding.pressed(),
InputBinding::Value(value_binding) => value_to_press(value_binding.value()),
InputBinding::DualValue(dual_value_binding) => {
let out = dual_value_binding.value();
value_to_press(out.x) && value_to_press(out.y)
}
}
}
pub fn value(&self) -> f32 {
match self {
InputBinding::Action(action_binding) => pressed_to_value(action_binding.pressed()),
InputBinding::Value(value_binding) => value_binding.value(),
InputBinding::DualValue(dual_value_binding) => {
let out = dual_value_binding.value();
(out.x + out.y) * 0.5
}
}
}
pub fn dual_value(&self) -> Vec2 {
match self {
InputBinding::Action(action_binding) => {
Vec2::splat(pressed_to_value(action_binding.pressed()))
}
InputBinding::Value(value_binding) => Vec2::splat(value_binding.value()),
InputBinding::DualValue(dual_value_binding) => dual_value_binding.value(),
}
}
}
#[inline]
pub fn value_to_press(val: f32) -> bool {
val != 0.
}
#[inline]
pub fn pressed_to_value(pressed: bool) -> f32 {
if pressed { 1.0 } else { 0.0 }
}
pub type InputBindingsSimple<K> = InputBindings<K, SimpleMessage>;
#[derive(Component)]
pub struct InputBindings<K, T: BindEvent> {
pub(crate) bindings: HashMap<K, InputBinding<T>>,
pub(crate) assigned_gamepad: Option<Entity>,
pub(crate) changed: bool,
}
impl<K, T> Default for InputBindings<K, T>
where
K: Eq + Hash,
T: BindEvent,
{
fn default() -> Self {
Self::new()
}
}
impl<K, T> InputBindings<K, T>
where
K: Eq + Hash,
T: BindEvent,
{
pub fn with_action_binding(mut self, name: K, bindings: ActionBinding<T>) -> Self {
self.register_action_binding(name, bindings);
self
}
pub fn with_value_binding(mut self, name: K, bindings: ValueBinding<T>) -> Self {
self.register_value_binding(name, bindings);
self
}
pub fn with_dual_value_binding(mut self, name: K, bindings: DualValueBinding<T>) -> Self {
self.register_dual_value_binding(name, bindings);
self
}
pub(crate) fn change(&mut self) {
self.changed = true;
}
pub(crate) fn changed(&mut self) -> bool {
if self.changed {
self.changed = false;
true
} else {
false
}
}
pub fn register_binding(
&mut self,
name: K,
bindings: InputBinding<T>,
) -> Option<InputBinding<T>> {
self.changed = true;
self.bindings.insert(name, bindings)
}
pub fn register_action_binding(
&mut self,
name: K,
bindings: ActionBinding<T>,
) -> Option<InputBinding<T>> {
self.register_binding(name, InputBinding::Action(bindings))
}
pub fn register_value_binding(
&mut self,
name: K,
bindings: ValueBinding<T>,
) -> Option<InputBinding<T>> {
self.register_binding(name, InputBinding::Value(bindings))
}
pub fn register_dual_value_binding(
&mut self,
name: K,
bindings: DualValueBinding<T>,
) -> Option<InputBinding<T>> {
self.register_binding(name, InputBinding::DualValue(bindings))
}
pub fn new() -> Self {
Self {
bindings: HashMap::default(),
assigned_gamepad: None,
changed: false,
}
}
pub fn get_binding(&self, name: &K) -> Option<&InputBinding<T>> {
self.bindings.get(name)
}
pub fn get_action_state(&self, name: &K) -> ButtonState {
self.get_binding(name)
.map(|binding| binding.state())
.unwrap_or_default()
}
pub fn just_pressed(&self, name: &K) -> bool {
self.get_binding(name)
.map(|binding| binding.state().just_pressed())
.unwrap_or_default()
}
pub fn pressed(&self, name: &K) -> bool {
self.get_binding(name)
.map(|binding| binding.state().pressed())
.unwrap_or_default()
}
pub fn just_released(&self, name: &K) -> bool {
self.get_binding(name)
.map(|binding| binding.state().just_released())
.unwrap_or_default()
}
pub fn released(&self, name: &K) -> bool {
self.get_binding(name)
.map(|binding| binding.state().released())
.unwrap_or_default()
}
pub fn get_value(&self, name: &K) -> f32 {
self.get_binding(name)
.map(|binding| binding.value())
.unwrap_or_default()
}
pub fn get_dual_value(&self, name: &K) -> Vec2 {
self.get_binding(name)
.map(|binding| binding.dual_value())
.unwrap_or_default()
}
}