2021-05-10 08:23:02 +08:00
|
|
|
#include <blah/input.h>
|
|
|
|
#include <blah/app.h>
|
|
|
|
#include <blah/time.h>
|
|
|
|
#include <blah/common.h>
|
|
|
|
#include <blah/numerics/point.h>
|
|
|
|
#include <blah/numerics/calc.h>
|
|
|
|
#include "internal/input_backend.h"
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
using namespace Blah;
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
InputState g_next_state;
|
|
|
|
InputState g_empty_state;
|
|
|
|
ControllerState g_empty_controller;
|
2021-05-10 09:37:31 +08:00
|
|
|
Vector<WeakRef<ButtonBinding>> g_buttons;
|
2021-05-10 08:23:02 +08:00
|
|
|
Vector<WeakRef<AxisBinding>> g_axes;
|
|
|
|
Vector<WeakRef<StickBinding>> g_sticks;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
InputState Blah::Input::state;
|
|
|
|
InputState Blah::Input::last_state;
|
|
|
|
|
2021-05-10 08:23:02 +08:00
|
|
|
void InputBackend::init()
|
|
|
|
{
|
|
|
|
g_empty_controller.name = "Disconnected";
|
|
|
|
for (int i = 0; i < Blah::Input::max_controllers; i++)
|
|
|
|
g_empty_state.controllers[i].name = g_empty_controller.name;
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
Input::last_state = g_empty_state;
|
|
|
|
Input::state = g_empty_state;
|
2021-05-10 08:23:02 +08:00
|
|
|
g_next_state = g_empty_state;
|
2021-05-10 09:37:31 +08:00
|
|
|
g_buttons.dispose();
|
2021-05-10 08:23:02 +08:00
|
|
|
g_axes.dispose();
|
|
|
|
g_sticks.dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::frame()
|
|
|
|
{
|
|
|
|
// cycle states
|
2021-05-10 09:37:31 +08:00
|
|
|
Input::last_state = Input::state;
|
|
|
|
Input::state = g_next_state;
|
2021-05-10 08:23:02 +08:00
|
|
|
|
|
|
|
// copy state, clear pressed / released values
|
|
|
|
{
|
|
|
|
for (int i = 0; i < Blah::Input::max_keyboard_keys; i++)
|
|
|
|
{
|
|
|
|
g_next_state.keyboard.pressed[i] = false;
|
|
|
|
g_next_state.keyboard.released[i] = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < Blah::Input::max_mouse_buttons; i++)
|
|
|
|
{
|
|
|
|
g_next_state.mouse.pressed[i] = false;
|
|
|
|
g_next_state.mouse.released[i] = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_next_state.mouse.wheel = Point::zero;
|
|
|
|
g_next_state.keyboard.text.clear();
|
|
|
|
|
|
|
|
for (int i = 0; i < Blah::Input::max_controllers; i++)
|
|
|
|
{
|
|
|
|
ControllerState* controller = &(g_next_state.controllers[i]);
|
|
|
|
|
|
|
|
if (!controller->is_connected)
|
|
|
|
controller->name = nullptr;
|
|
|
|
|
|
|
|
for (int j = 0; j < Blah::Input::max_controller_buttons; j++)
|
|
|
|
{
|
|
|
|
controller->pressed[j] = false;
|
|
|
|
controller->released[j] = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// update bindings
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
for (int i = 0; i < g_buttons.size(); i++)
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
if (g_buttons[i].use_count() <= 0)
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
g_buttons.erase(i);
|
2021-05-10 08:23:02 +08:00
|
|
|
i--;
|
|
|
|
}
|
2021-05-10 09:37:31 +08:00
|
|
|
else if (auto binding = g_buttons[i].lock())
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
binding->update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < g_axes.size(); i++)
|
|
|
|
{
|
|
|
|
if (g_axes[i].use_count() <= 0)
|
|
|
|
{
|
|
|
|
g_axes.erase(i);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
else if (auto binding = g_axes[i].lock())
|
|
|
|
{
|
|
|
|
binding->update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < g_sticks.size(); i++)
|
|
|
|
{
|
|
|
|
if (g_sticks[i].use_count() <= 0)
|
|
|
|
{
|
|
|
|
g_sticks.erase(i);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
else if (auto binding = g_sticks[i].lock())
|
|
|
|
{
|
|
|
|
binding->update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_mouse_move(float x, float y)
|
|
|
|
{
|
|
|
|
g_next_state.mouse.position.x = x;
|
|
|
|
g_next_state.mouse.position.y = y;
|
|
|
|
|
|
|
|
Point size = Point(App::width(), App::height());
|
|
|
|
Point draw = Point(App::draw_width(), App::draw_height());
|
|
|
|
|
|
|
|
g_next_state.mouse.draw_position.x = (x / (float)size.x) * draw.x;
|
|
|
|
g_next_state.mouse.draw_position.y = (y / (float)size.y) * draw.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_mouse_screen_move(float x, float y)
|
|
|
|
{
|
|
|
|
g_next_state.mouse.screen_position.x = x;
|
|
|
|
g_next_state.mouse.screen_position.y = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_mouse_down(MouseButton button)
|
|
|
|
{
|
|
|
|
int i = (int)button;
|
|
|
|
if (i >= 0 && i < Blah::Input::max_mouse_buttons)
|
|
|
|
{
|
|
|
|
g_next_state.mouse.down[i] = true;
|
|
|
|
g_next_state.mouse.pressed[i] = true;
|
|
|
|
g_next_state.mouse.timestamp[i] = Time::ticks;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_mouse_up(MouseButton button)
|
|
|
|
{
|
|
|
|
int i = (int)button;
|
|
|
|
if (i >= 0 && i < Blah::Input::max_mouse_buttons)
|
|
|
|
{
|
|
|
|
g_next_state.mouse.down[i] = false;
|
|
|
|
g_next_state.mouse.released[i] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_key_down(Key key)
|
|
|
|
{
|
|
|
|
int i = (int)key;
|
|
|
|
if (i >= 0 && i < Blah::Input::max_keyboard_keys)
|
|
|
|
{
|
|
|
|
g_next_state.keyboard.down[i] = true;
|
|
|
|
g_next_state.keyboard.pressed[i] = true;
|
|
|
|
g_next_state.keyboard.timestamp[i] = Time::ticks;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_mouse_wheel(Point wheel)
|
|
|
|
{
|
|
|
|
g_next_state.mouse.wheel = wheel;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_key_up(Key key)
|
|
|
|
{
|
|
|
|
int i = (int)key;
|
|
|
|
if (i >= 0 && i < Blah::Input::max_keyboard_keys)
|
|
|
|
{
|
|
|
|
g_next_state.keyboard.down[i] = false;
|
|
|
|
g_next_state.keyboard.released[i] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_text_utf8(const char* text)
|
|
|
|
{
|
|
|
|
g_next_state.keyboard.text += text;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_controller_connect(int index, const char* name, int is_gamepad, int button_count, int axis_count, u16 vendor, u16 product, u16 version)
|
|
|
|
{
|
|
|
|
if (index < Blah::Input::max_controllers)
|
|
|
|
{
|
|
|
|
ControllerState* controller = &(g_next_state.controllers[index]);
|
|
|
|
*controller = g_empty_controller;
|
|
|
|
controller->name = name;
|
|
|
|
controller->is_connected = true;
|
|
|
|
controller->is_gamepad = is_gamepad;
|
|
|
|
controller->button_count = button_count;
|
|
|
|
controller->axis_count = axis_count;
|
|
|
|
controller->vendor = vendor;
|
|
|
|
controller->product = product;
|
|
|
|
controller->version = version;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_controller_disconnect(int index)
|
|
|
|
{
|
|
|
|
if (index < Blah::Input::max_controllers)
|
|
|
|
g_next_state.controllers[index] = g_empty_controller;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_button_down(int index, int button)
|
|
|
|
{
|
|
|
|
if (index < Blah::Input::max_controllers &&
|
|
|
|
button < Blah::Input::max_controller_buttons &&
|
|
|
|
g_next_state.controllers[index].is_connected &&
|
|
|
|
button < g_next_state.controllers[index].button_count)
|
|
|
|
{
|
|
|
|
g_next_state.controllers[index].down[button] = true;
|
|
|
|
g_next_state.controllers[index].pressed[button] = true;
|
|
|
|
g_next_state.controllers[index].button_timestamp[button] = Time::ticks;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_button_up(int index, int button)
|
|
|
|
{
|
|
|
|
if (index < Blah::Input::max_controllers &&
|
|
|
|
button < Blah::Input::max_controller_buttons &&
|
|
|
|
g_next_state.controllers[index].is_connected &&
|
|
|
|
button < g_next_state.controllers[index].button_count)
|
|
|
|
{
|
|
|
|
g_next_state.controllers[index].down[button] = false;
|
|
|
|
g_next_state.controllers[index].released[button] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBackend::on_axis_move(int index, int axis, float value)
|
|
|
|
{
|
|
|
|
if (index < Blah::Input::max_controllers &&
|
|
|
|
axis < Blah::Input::max_controller_axis &&
|
|
|
|
g_next_state.controllers[index].is_connected &&
|
|
|
|
axis < g_next_state.controllers[index].axis_count)
|
|
|
|
{
|
|
|
|
g_next_state.controllers[index].axis[axis] = value;
|
|
|
|
g_next_state.controllers[index].axis_timestamp[axis] = Time::ticks;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
bool KeyboardState::ctrl()
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return down[Key::LeftControl] || down[Key::RightControl];
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
bool KeyboardState::shift()
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return down[Key::LeftShift] || down[Key::RightShift];
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
bool KeyboardState::alt()
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return down[Key::LeftAlt] || down[Key::RightAlt];
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
Vec2 Input::mouse()
|
|
|
|
{
|
|
|
|
return state.mouse.position;
|
|
|
|
}
|
2021-05-10 08:23:02 +08:00
|
|
|
|
|
|
|
Vec2 Input::mouse_draw()
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.mouse.draw_position;
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Vec2 Input::mouse_screen()
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.mouse.screen_position;
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Input::pressed(MouseButton button)
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.mouse.pressed[button];
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Input::down(MouseButton button)
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.mouse.down[button];
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Input::released(MouseButton button)
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.mouse.released[button];
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Point Input::mouse_wheel()
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.mouse.wheel;
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Input::pressed(Key key)
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.keyboard.pressed[key];
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Input::down(Key key)
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.keyboard.down[key];
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Input::released(Key key)
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.keyboard.released[key];
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Input::ctrl()
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.keyboard.ctrl();
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Input::shift()
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.keyboard.shift();
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Input::alt()
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
return state.keyboard.alt();
|
2021-05-10 08:23:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const char* Input::name_of(Key key)
|
|
|
|
{
|
|
|
|
switch (key)
|
|
|
|
{
|
|
|
|
#define DEFINE_KEY(name, value) case Key::name: return #name;
|
|
|
|
BLAH_KEY_DEFINITIONS
|
|
|
|
#undef DEFINE_KEY
|
|
|
|
}
|
|
|
|
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* Input::name_of(Button button)
|
|
|
|
{
|
|
|
|
switch (button)
|
|
|
|
{
|
|
|
|
#define DEFINE_BTN(name, value) case Button::name: return #name;
|
|
|
|
BLAH_BUTTON_DEFINITIONS
|
|
|
|
#undef DEFINE_BTN
|
|
|
|
}
|
|
|
|
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBindingRef Input::register_binding(const ButtonBinding& binding)
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
auto result = std::make_shared<ButtonBinding>(binding);
|
|
|
|
g_buttons.push_back(WeakRef<ButtonBinding>(result));
|
2021-05-10 08:23:02 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
AxisBindingRef Input::register_binding(const AxisBinding& binding)
|
|
|
|
{
|
|
|
|
auto result = std::make_shared<AxisBinding>(binding);
|
|
|
|
g_axes.push_back(WeakRef<AxisBinding>(result));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
StickBindingRef Input::register_binding(const StickBinding& binding)
|
|
|
|
{
|
|
|
|
auto result = std::make_shared<StickBinding>(binding);
|
|
|
|
g_sticks.push_back(WeakRef<StickBinding>(result));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBinding::TriggerBind::TriggerBind(Axis axis)
|
2021-05-10 08:23:02 +08:00
|
|
|
: axis(axis)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBinding::TriggerBind::TriggerBind(int controller, Axis axis, float threshold, bool positive)
|
2021-05-10 08:23:02 +08:00
|
|
|
: controller(controller), axis(axis), threshold(threshold), positive(positive)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
bool ButtonBinding::TriggerBind::is_down(float axis_value) const
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
if ((axis_value > 0 && positive) || (axis_value < 0 && !positive))
|
|
|
|
{
|
|
|
|
if (Calc::abs(axis_value) >= threshold)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBinding::ButtonBind::ButtonBind(Button button)
|
2021-05-10 08:23:02 +08:00
|
|
|
: button(button) {}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBinding::ButtonBind::ButtonBind(int controller, Button button)
|
2021-05-10 08:23:02 +08:00
|
|
|
: controller(controller), button(button) {}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
bool ButtonBinding::pressed() const
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
if (m_press_consumed)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (m_last_press_time >= 0 && (Time::seconds - m_last_press_time) <= press_buffer)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return m_pressed;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
bool ButtonBinding::released() const
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
if (m_release_consumed)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (m_last_release_time >= 0 && (Time::seconds - m_last_release_time) <= release_buffer)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return m_released;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
bool ButtonBinding::down() const
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
return m_down;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
float ButtonBinding::value() const
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
return m_value;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
int ButtonBinding::sign() const
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
return (int)Calc::sign(m_value);
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
double ButtonBinding::timestamp() const
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
return m_last_timestamp;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
void ButtonBinding::update()
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
m_press_consumed = false;
|
|
|
|
m_release_consumed = false;
|
|
|
|
|
|
|
|
if (get_pressed())
|
|
|
|
{
|
|
|
|
m_last_timestamp = Time::seconds;
|
|
|
|
m_last_press_time = Time::seconds;
|
|
|
|
m_pressed = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_pressed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (get_released())
|
|
|
|
{
|
|
|
|
m_last_release_time = Time::seconds;
|
|
|
|
m_released = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_released = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_down = get_down();
|
|
|
|
m_value = get_value();
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
void ButtonBinding::consume_press()
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
m_press_consumed = true;
|
|
|
|
m_last_press_time = -1;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
void ButtonBinding::consume_release()
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
m_release_consumed = true;
|
|
|
|
m_last_release_time = -1;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBinding& ButtonBinding::add(Key key)
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
keys.push_back(key);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBinding& ButtonBinding::add(ButtonBind button)
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
buttons.push_back(button);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBinding& ButtonBinding::add(TriggerBind trigger)
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
triggers.push_back(trigger);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBinding& ButtonBinding::add(MouseButton button)
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
mouse.push_back(button);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBinding& ButtonBinding::add_left_trigger(int controller, float threshold)
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
triggers.push_back(TriggerBind(controller, Axis::LeftTrigger, threshold, true));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBinding& ButtonBinding::add_right_trigger(int controller, float threshold)
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
triggers.push_back(TriggerBind(controller, Axis::RightTrigger, threshold, true));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
ButtonBinding& ButtonBinding::set_controller(int index)
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
for (auto& it : buttons)
|
|
|
|
it.controller = index;
|
|
|
|
for (auto& it : triggers)
|
|
|
|
it.controller = index;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
void ButtonBinding::clear()
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
keys.clear();
|
|
|
|
buttons.clear();
|
|
|
|
triggers.clear();
|
|
|
|
mouse.clear();
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
bool ButtonBinding::get_pressed() const
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
for (auto& it : keys)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.keyboard.pressed[it])
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
for (auto& it : mouse)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.mouse.pressed[it])
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
for (auto& it : buttons)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.controllers[it.controller].pressed[it.button])
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
for (auto& it : triggers)
|
|
|
|
{
|
|
|
|
if (it.controller < 0 || it.controller >= Input::max_controllers)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
|
|
|
|
continue;
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
if (it.is_down(Input::state.controllers[it.controller].axis[(int)it.axis]) &&
|
|
|
|
!it.is_down(Input::last_state.controllers[it.controller].axis[(int)it.axis]))
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
bool ButtonBinding::get_released() const
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
for (auto& it : keys)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.keyboard.released[it])
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
for (auto& it : mouse)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.mouse.released[it])
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
for (auto& it : buttons)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.controllers[it.controller].released[it.button])
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
for (auto& it : triggers)
|
|
|
|
{
|
|
|
|
if (it.controller < 0 || it.controller >= Input::max_controllers)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
|
|
|
|
continue;
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
if (!it.is_down(Input::state.controllers[it.controller].axis[(int)it.axis]) &&
|
|
|
|
it.is_down(Input::last_state.controllers[it.controller].axis[(int)it.axis]))
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
bool ButtonBinding::get_down() const
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
for (auto& it : keys)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.keyboard.down[it])
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
for (auto& it : mouse)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.mouse.down[it])
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
for (auto& it : buttons)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.controllers[it.controller].down[it.button])
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
for (auto& it : triggers)
|
|
|
|
{
|
|
|
|
if (it.controller < 0 || it.controller >= Input::max_controllers)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
|
|
|
|
continue;
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
if (it.is_down(Input::state.controllers[it.controller].axis[(int)it.axis]))
|
2021-05-10 08:23:02 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
float ButtonBinding::get_value() const
|
2021-05-10 08:23:02 +08:00
|
|
|
{
|
|
|
|
for (auto& it : keys)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.keyboard.down[it])
|
2021-05-10 08:23:02 +08:00
|
|
|
return 1.0f;
|
|
|
|
|
|
|
|
for (auto& it : mouse)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.mouse.down[it])
|
2021-05-10 08:23:02 +08:00
|
|
|
return 1.0f;
|
|
|
|
|
|
|
|
for (auto& it : buttons)
|
2021-05-10 09:37:31 +08:00
|
|
|
if (Input::state.controllers[it.controller].down[it.button])
|
2021-05-10 08:23:02 +08:00
|
|
|
return 1.0f;
|
|
|
|
|
|
|
|
float highest = 0;
|
|
|
|
|
|
|
|
for (auto& it : triggers)
|
|
|
|
{
|
|
|
|
if (it.controller < 0 || it.controller >= Input::max_controllers)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
|
|
|
|
continue;
|
|
|
|
|
2021-05-10 09:37:31 +08:00
|
|
|
float raw_value = Input::state.controllers[it.controller].axis[(int)it.axis];
|
2021-05-10 08:23:02 +08:00
|
|
|
|
|
|
|
if (it.is_down(raw_value))
|
|
|
|
{
|
|
|
|
float mapped_value = Calc::clamped_map(Calc::abs(raw_value), it.threshold, 1.0f, 0.0f, 1.0f);
|
|
|
|
if (mapped_value > highest)
|
|
|
|
highest = mapped_value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return highest;
|
|
|
|
}
|
|
|
|
|
|
|
|
float AxisBinding::value() const
|
|
|
|
{
|
|
|
|
float neg = negative.value();
|
|
|
|
float pos = positive.value();
|
|
|
|
|
|
|
|
// neither are down
|
|
|
|
if (neg <= 0 && pos <= 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// negative-only is down
|
|
|
|
if (neg > 0 && pos <= 0)
|
|
|
|
return -neg;
|
|
|
|
|
|
|
|
// positive-only is down
|
|
|
|
if (pos > 0 && neg <= 0)
|
|
|
|
return pos;
|
|
|
|
|
|
|
|
// both are down:
|
|
|
|
|
|
|
|
// overlap cancel out
|
|
|
|
if (overlap == Overlap::Cancel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// overlap takes older
|
|
|
|
if (overlap == Overlap::Older)
|
|
|
|
{
|
|
|
|
if (negative.timestamp() < positive.timestamp())
|
|
|
|
return -neg;
|
|
|
|
else
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
// overlap takes newer
|
|
|
|
if (negative.timestamp() > positive.timestamp())
|
|
|
|
return -neg;
|
|
|
|
else
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
int AxisBinding::sign() const
|
|
|
|
{
|
|
|
|
return (int)Calc::sign(value());
|
|
|
|
}
|
|
|
|
|
|
|
|
void AxisBinding::update()
|
|
|
|
{
|
|
|
|
negative.update();
|
|
|
|
positive.update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AxisBinding::consume_press()
|
|
|
|
{
|
|
|
|
negative.consume_press();
|
|
|
|
positive.consume_press();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AxisBinding::consume_release()
|
|
|
|
{
|
|
|
|
negative.consume_release();
|
|
|
|
positive.consume_release();
|
|
|
|
}
|
|
|
|
|
|
|
|
AxisBinding& AxisBinding::add_left_stick_x(int controller, float threshold)
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
negative.add(ButtonBinding::TriggerBind(controller, Axis::LeftX, threshold, false));
|
|
|
|
positive.add(ButtonBinding::TriggerBind(controller, Axis::LeftX, threshold, true));
|
2021-05-10 08:23:02 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
AxisBinding& AxisBinding::add_left_stick_y(int controller, float threshold)
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
negative.add(ButtonBinding::TriggerBind(controller, Axis::LeftY, threshold, false));
|
|
|
|
positive.add(ButtonBinding::TriggerBind(controller, Axis::LeftY, threshold, true));
|
2021-05-10 08:23:02 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
AxisBinding& AxisBinding::add_right_stick_x(int controller, float threshold)
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
negative.add(ButtonBinding::TriggerBind(controller, Axis::RightX, threshold, false));
|
|
|
|
positive.add(ButtonBinding::TriggerBind(controller, Axis::RightX, threshold, true));
|
2021-05-10 08:23:02 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
AxisBinding& AxisBinding::add_right_stick_y(int controller, float threshold)
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
negative.add(ButtonBinding::TriggerBind(controller, Axis::RightY, threshold, false));
|
|
|
|
positive.add(ButtonBinding::TriggerBind(controller, Axis::RightY, threshold, true));
|
2021-05-10 08:23:02 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
AxisBinding& AxisBinding::set_controller(int index)
|
|
|
|
{
|
|
|
|
negative.set_controller(index);
|
|
|
|
positive.set_controller(index);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AxisBinding::clear()
|
|
|
|
{
|
|
|
|
negative.clear();
|
|
|
|
positive.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
Vec2 StickBinding::value() const
|
|
|
|
{
|
|
|
|
Vec2 result = Vec2(x.value(), y.value());
|
|
|
|
if (round_threshold > 0 && result.length() < round_threshold)
|
|
|
|
return Vec2::zero;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
Point StickBinding::sign() const
|
|
|
|
{
|
|
|
|
Vec2 result = value();
|
|
|
|
return Point((int)Calc::sign(result.x), (int)Calc::sign(result.y));
|
|
|
|
}
|
|
|
|
|
|
|
|
void StickBinding::update()
|
|
|
|
{
|
|
|
|
x.update();
|
|
|
|
y.update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void StickBinding::consume_press()
|
|
|
|
{
|
|
|
|
x.consume_press();
|
|
|
|
y.consume_press();
|
|
|
|
}
|
|
|
|
|
|
|
|
void StickBinding::consume_release()
|
|
|
|
{
|
|
|
|
x.consume_release();
|
|
|
|
y.consume_release();
|
|
|
|
}
|
|
|
|
|
|
|
|
StickBinding& StickBinding::add_dpad(int controller)
|
|
|
|
{
|
2021-05-10 09:37:31 +08:00
|
|
|
x.negative.add(ButtonBinding::ButtonBind(controller, Button::Left));
|
|
|
|
x.positive.add(ButtonBinding::ButtonBind(controller, Button::Right));
|
|
|
|
y.negative.add(ButtonBinding::ButtonBind(controller, Button::Up));
|
|
|
|
y.positive.add(ButtonBinding::ButtonBind(controller, Button::Down));
|
2021-05-10 08:23:02 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
StickBinding& StickBinding::add_left_stick(int controller, float threshold)
|
|
|
|
{
|
|
|
|
x.add_left_stick_x(controller, threshold);
|
|
|
|
y.add_left_stick_y(controller, threshold);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
StickBinding& StickBinding::add_right_stick(int controller, float threshold)
|
|
|
|
{
|
|
|
|
x.add_right_stick_x(controller, threshold);
|
|
|
|
y.add_right_stick_y(controller, threshold);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
StickBinding& StickBinding::set_controller(int index)
|
|
|
|
{
|
|
|
|
x.set_controller(index);
|
|
|
|
y.set_controller(index);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StickBinding::clear()
|
|
|
|
{
|
|
|
|
x.clear();
|
|
|
|
y.clear();
|
|
|
|
}
|
|
|
|
|