mirror of
https://github.com/NoelFB/blah.git
synced 2024-11-25 16:18:57 +08:00
simplifying input backend & input state update
This commit is contained in:
parent
b7e318e420
commit
d7cef352a5
|
@ -53,7 +53,7 @@ namespace Blah
|
|||
AppEventFn on_render;
|
||||
|
||||
// Callback when the user has requested the application close.
|
||||
// For example, pressing the Close button
|
||||
// For example, pressing the Close button, ALT+F4, etc
|
||||
// By default this calls `App::exit()`
|
||||
AppEventFn on_exit_request;
|
||||
|
||||
|
|
|
@ -228,119 +228,6 @@ namespace Blah
|
|||
constexpr int max_keyboard_keys = 512;
|
||||
}
|
||||
|
||||
struct ControllerState
|
||||
{
|
||||
// The name of the gamepad, or NULL if not connected
|
||||
const char* name;
|
||||
|
||||
// Whether this gamepad is connected
|
||||
bool is_connected;
|
||||
|
||||
// Whether this gamepad is a standard Game Controller
|
||||
bool is_gamepad;
|
||||
|
||||
// The total button count for this controller
|
||||
int button_count;
|
||||
|
||||
// The total axis count for this controller
|
||||
int axis_count;
|
||||
|
||||
// An array holding the pressed state of each button
|
||||
bool pressed[Input::max_controller_buttons];
|
||||
|
||||
// An array holding the down state of each button
|
||||
bool down[Input::max_controller_buttons];
|
||||
|
||||
// An array holding the released state of each button
|
||||
bool released[Input::max_controller_buttons];
|
||||
|
||||
// An array holding the value state of each axis
|
||||
float axis[Input::max_controller_axis];
|
||||
|
||||
// Timestamp, in milliseconds, since each button was last pressed
|
||||
u64 button_timestamp[Input::max_controller_buttons];
|
||||
|
||||
// Timestamp, in milliseconds, since each axis last had a value set
|
||||
u64 axis_timestamp[Input::max_controller_axis];
|
||||
|
||||
// The USB Vendor ID
|
||||
u16 vendor;
|
||||
|
||||
// The USB Product ID
|
||||
u16 product;
|
||||
|
||||
// the Product Version
|
||||
u16 version;
|
||||
};
|
||||
|
||||
struct KeyboardState
|
||||
{
|
||||
// whether a key was pressed this frame
|
||||
bool pressed[Input::max_keyboard_keys];
|
||||
|
||||
// whether a key is currently held
|
||||
bool down[Input::max_keyboard_keys];
|
||||
|
||||
// whether a key was released this frame
|
||||
bool released[Input::max_keyboard_keys];
|
||||
|
||||
// the timestamp for the key being pressed
|
||||
u64 timestamp[Input::max_keyboard_keys];
|
||||
|
||||
// current text input this frame
|
||||
String text;
|
||||
|
||||
// Checks if the Left or Right Ctrl Key is down
|
||||
bool ctrl();
|
||||
|
||||
// Checks if the Left or Right Shift Key is down
|
||||
bool shift();
|
||||
|
||||
// Checks if the Left or Right Alt Key is down
|
||||
bool alt();
|
||||
};
|
||||
|
||||
struct MouseState
|
||||
{
|
||||
// whether a button was pressed this frame
|
||||
bool pressed[Input::max_mouse_buttons];
|
||||
|
||||
// whether a button was held this frame
|
||||
bool down[Input::max_mouse_buttons];
|
||||
|
||||
// whether a button was released this frame
|
||||
bool released[Input::max_mouse_buttons];
|
||||
|
||||
// the timestamp for the button being pressed
|
||||
u64 timestamp[Input::max_mouse_buttons];
|
||||
|
||||
// mouse position in screen coordinates
|
||||
Vec2 screen_position;
|
||||
|
||||
// mouse position in pixel coordinates
|
||||
Vec2 draw_position;
|
||||
|
||||
// mouse position on the window
|
||||
Vec2 position;
|
||||
|
||||
// mouse wheel value this frame
|
||||
Point wheel;
|
||||
};
|
||||
|
||||
// An Input State, which stores the state for gamepads, keyboard, and mouse
|
||||
struct InputState
|
||||
{
|
||||
// All the Gamepads. Note that not all gamepads are necessarily connected,
|
||||
// and each one must be checked before use.
|
||||
ControllerState controllers[Input::max_controllers];
|
||||
|
||||
// The current Keyboard state
|
||||
KeyboardState keyboard;
|
||||
|
||||
// The current Mouse state
|
||||
MouseState mouse;
|
||||
};
|
||||
|
||||
// Keyboard Keys
|
||||
struct Keys
|
||||
{
|
||||
|
@ -394,6 +281,152 @@ namespace Blah
|
|||
};
|
||||
using MouseButton = MouseButtons::Enumeration;
|
||||
|
||||
// Controller State
|
||||
struct ControllerState
|
||||
{
|
||||
// The name of the gamepad, or NULL if not connected
|
||||
String name;
|
||||
|
||||
// Whether this gamepad is connected
|
||||
bool is_connected;
|
||||
|
||||
// Whether this gamepad is a standard Game Controller
|
||||
bool is_gamepad;
|
||||
|
||||
// The total button count for this controller
|
||||
int button_count;
|
||||
|
||||
// The total axis count for this controller
|
||||
int axis_count;
|
||||
|
||||
// An array holding the pressed state of each button
|
||||
bool pressed[Input::max_controller_buttons];
|
||||
|
||||
// An array holding the down state of each button
|
||||
bool down[Input::max_controller_buttons];
|
||||
|
||||
// An array holding the released state of each button
|
||||
bool released[Input::max_controller_buttons];
|
||||
|
||||
// An array holding the value state of each axis
|
||||
float axis[Input::max_controller_axis];
|
||||
|
||||
// Timestamp, in milliseconds, since each button was last pressed
|
||||
u64 button_timestamp[Input::max_controller_buttons];
|
||||
|
||||
// Timestamp, in milliseconds, since each axis last had a value set
|
||||
u64 axis_timestamp[Input::max_controller_axis];
|
||||
|
||||
// The USB Vendor ID
|
||||
u16 vendor;
|
||||
|
||||
// The USB Product ID
|
||||
u16 product;
|
||||
|
||||
// the Product Version
|
||||
u16 version;
|
||||
|
||||
// marks the controller as connected
|
||||
void on_connect(const String& name, bool is_gamepad, int button_count, int axis_count, u16 vendor, u16 product, u16 version);
|
||||
|
||||
// marks the controller as disconnected
|
||||
void on_disconnect();
|
||||
|
||||
// invokes a button press
|
||||
void on_press(Button button);
|
||||
|
||||
// invokes a button release
|
||||
void on_release(Button button);
|
||||
|
||||
// invokes an axis movement
|
||||
void on_axis(Axis axis, float value);
|
||||
};
|
||||
|
||||
// Keyboard State
|
||||
struct KeyboardState
|
||||
{
|
||||
// whether a key was pressed this frame
|
||||
bool pressed[Input::max_keyboard_keys];
|
||||
|
||||
// whether a key is currently held
|
||||
bool down[Input::max_keyboard_keys];
|
||||
|
||||
// whether a key was released this frame
|
||||
bool released[Input::max_keyboard_keys];
|
||||
|
||||
// the timestamp for the key being pressed
|
||||
u64 timestamp[Input::max_keyboard_keys];
|
||||
|
||||
// current text input this frame
|
||||
String text;
|
||||
|
||||
// Checks if the Left or Right Ctrl Key is down
|
||||
bool ctrl();
|
||||
|
||||
// Checks if the Left or Right Shift Key is down
|
||||
bool shift();
|
||||
|
||||
// Checks if the Left or Right Alt Key is down
|
||||
bool alt();
|
||||
|
||||
// invokes a key press
|
||||
void on_press(Key key);
|
||||
|
||||
// invokes a key release
|
||||
void on_release(Key key);
|
||||
};
|
||||
|
||||
// Mouse State
|
||||
struct MouseState
|
||||
{
|
||||
// whether a button was pressed this frame
|
||||
bool pressed[Input::max_mouse_buttons];
|
||||
|
||||
// whether a button was held this frame
|
||||
bool down[Input::max_mouse_buttons];
|
||||
|
||||
// whether a button was released this frame
|
||||
bool released[Input::max_mouse_buttons];
|
||||
|
||||
// the timestamp for the button being pressed
|
||||
u64 timestamp[Input::max_mouse_buttons];
|
||||
|
||||
// mouse position in screen coordinates
|
||||
Vec2 screen_position;
|
||||
|
||||
// mouse position in pixel coordinates
|
||||
Vec2 draw_position;
|
||||
|
||||
// mouse position on the window
|
||||
Vec2 position;
|
||||
|
||||
// mouse wheel value this frame
|
||||
Point wheel;
|
||||
|
||||
// invokes a key press
|
||||
void on_press(MouseButton button);
|
||||
|
||||
// invokes a mouse movement
|
||||
void on_move(const Vec2& position, const Vec2& screen_position);
|
||||
|
||||
// invokes a key release
|
||||
void on_release(MouseButton button);
|
||||
};
|
||||
|
||||
// An Input State, which stores the state for gamepads, keyboard, and mouse
|
||||
struct InputState
|
||||
{
|
||||
// All the Gamepads. Note that not all gamepads are necessarily connected,
|
||||
// and each one must be checked before use.
|
||||
ControllerState controllers[Input::max_controllers];
|
||||
|
||||
// The current Keyboard state
|
||||
KeyboardState keyboard;
|
||||
|
||||
// The current Mouse state
|
||||
MouseState mouse;
|
||||
};
|
||||
|
||||
class ButtonBinding;
|
||||
using ButtonBindingRef = Ref<ButtonBinding>;
|
||||
|
||||
|
|
|
@ -40,9 +40,6 @@ namespace
|
|||
|
||||
void app_iterate()
|
||||
{
|
||||
// poll system events
|
||||
PlatformBackend::frame();
|
||||
|
||||
// update at a fixed timerate
|
||||
// TODO: allow a non-fixed step update?
|
||||
{
|
||||
|
@ -91,8 +88,10 @@ namespace
|
|||
Time::previous_seconds = Time::seconds;
|
||||
Time::seconds += Time::delta;
|
||||
|
||||
InputBackend::frame();
|
||||
GraphicsBackend::frame();
|
||||
InputBackend::update_state();
|
||||
PlatformBackend::update(Input::state);
|
||||
InputBackend::update_bindings();
|
||||
GraphicsBackend::update();
|
||||
|
||||
if (app_config.on_update != nullptr)
|
||||
app_config.on_update();
|
||||
|
|
202
src/input.cpp
202
src/input.cpp
|
@ -11,7 +11,6 @@ using namespace Blah;
|
|||
|
||||
namespace
|
||||
{
|
||||
InputState g_next_state;
|
||||
InputState g_empty_state;
|
||||
ControllerState g_empty_controller;
|
||||
Vector<WeakRef<ButtonBinding>> g_buttons;
|
||||
|
@ -25,57 +24,54 @@ InputState Blah::Input::last_state;
|
|||
void InputBackend::init()
|
||||
{
|
||||
g_empty_controller.name = "Disconnected";
|
||||
for (int i = 0; i < Blah::Input::max_controllers; i++)
|
||||
for (int i = 0; i < Input::max_controllers; i++)
|
||||
g_empty_state.controllers[i].name = g_empty_controller.name;
|
||||
|
||||
Input::last_state = g_empty_state;
|
||||
Input::state = g_empty_state;
|
||||
g_next_state = g_empty_state;
|
||||
g_buttons.dispose();
|
||||
g_axes.dispose();
|
||||
g_sticks.dispose();
|
||||
}
|
||||
|
||||
void InputBackend::frame()
|
||||
void InputBackend::update_state()
|
||||
{
|
||||
// cycle states
|
||||
Input::last_state = Input::state;
|
||||
Input::state = g_next_state;
|
||||
|
||||
// copy state, clear pressed / released values
|
||||
// update other state for next frame
|
||||
for (int i = 0; i < Input::max_keyboard_keys; i++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
Input::state.keyboard.pressed[i] = false;
|
||||
Input::state.keyboard.released[i] = false;
|
||||
}
|
||||
|
||||
// update bindings
|
||||
for (int i = 0; i < Input::max_mouse_buttons; i++)
|
||||
{
|
||||
Input::state.mouse.pressed[i] = false;
|
||||
Input::state.mouse.released[i] = false;
|
||||
}
|
||||
|
||||
Input::state.mouse.wheel = Point::zero;
|
||||
Input::state.keyboard.text.clear();
|
||||
|
||||
for (int i = 0; i < Input::max_controllers; i++)
|
||||
{
|
||||
ControllerState& controller = Input::state.controllers[i];
|
||||
|
||||
if (!controller.is_connected)
|
||||
controller.name.clear();
|
||||
|
||||
for (int j = 0; j < Input::max_controller_buttons; j++)
|
||||
{
|
||||
controller.pressed[j] = false;
|
||||
controller.released[j] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputBackend::update_bindings()
|
||||
{
|
||||
for (int i = 0; i < g_buttons.size(); i++)
|
||||
{
|
||||
if (g_buttons[i].use_count() <= 0)
|
||||
|
@ -116,133 +112,99 @@ void InputBackend::frame()
|
|||
}
|
||||
}
|
||||
|
||||
void InputBackend::on_mouse_move(float x, float y)
|
||||
void MouseState::on_move(const Vec2& pos, const Vec2& screen_pos)
|
||||
{
|
||||
g_next_state.mouse.position.x = x;
|
||||
g_next_state.mouse.position.y = y;
|
||||
position = pos;
|
||||
screen_position = screen_pos;
|
||||
|
||||
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;
|
||||
draw_position.x = (position.x / (float)size.x) * draw.x;
|
||||
draw_position.y = (position.y / (float)size.y) * draw.y;
|
||||
}
|
||||
|
||||
void InputBackend::on_mouse_screen_move(float x, float y)
|
||||
void MouseState::on_press(MouseButton button)
|
||||
{
|
||||
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)
|
||||
if (button >= 0 && button < 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;
|
||||
down[button] = true;
|
||||
pressed[button] = true;
|
||||
timestamp[button] = Time::ticks;
|
||||
}
|
||||
}
|
||||
|
||||
void InputBackend::on_mouse_up(MouseButton button)
|
||||
void MouseState::on_release(MouseButton button)
|
||||
{
|
||||
int i = (int)button;
|
||||
if (i >= 0 && i < Blah::Input::max_mouse_buttons)
|
||||
if (button >= 0 && button < Input::max_mouse_buttons)
|
||||
{
|
||||
g_next_state.mouse.down[i] = false;
|
||||
g_next_state.mouse.released[i] = true;
|
||||
down[button] = false;
|
||||
released[button] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InputBackend::on_key_down(Key key)
|
||||
void KeyboardState::on_press(Key key)
|
||||
{
|
||||
int i = (int)key;
|
||||
if (i >= 0 && i < Blah::Input::max_keyboard_keys)
|
||||
if (key >= 0 && key < 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;
|
||||
down[key] = true;
|
||||
pressed[key] = true;
|
||||
timestamp[key] = Time::ticks;
|
||||
}
|
||||
}
|
||||
|
||||
void InputBackend::on_mouse_wheel(Point wheel)
|
||||
void KeyboardState::on_release(Key key)
|
||||
{
|
||||
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)
|
||||
if (key >= 0 && key < Input::max_keyboard_keys)
|
||||
{
|
||||
g_next_state.keyboard.down[i] = false;
|
||||
g_next_state.keyboard.released[i] = true;
|
||||
down[key] = false;
|
||||
released[key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InputBackend::on_text_utf8(const char* text)
|
||||
void ControllerState::on_connect(const String& name, bool is_gamepad, int button_count, int axis_count, u16 vendor, u16 product, u16 version)
|
||||
{
|
||||
g_next_state.keyboard.text += text;
|
||||
*this = g_empty_controller;
|
||||
this->name = name;
|
||||
this->is_connected = true;
|
||||
this->is_gamepad = is_gamepad;
|
||||
this->button_count = button_count;
|
||||
this->axis_count = axis_count;
|
||||
this->vendor = vendor;
|
||||
this->product = product;
|
||||
this->version = version;
|
||||
}
|
||||
|
||||
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)
|
||||
void ControllerState::on_disconnect()
|
||||
{
|
||||
if (index < Blah::Input::max_controllers)
|
||||
*this = g_empty_controller;
|
||||
}
|
||||
|
||||
void ControllerState::on_press(Button button)
|
||||
{
|
||||
if (button >= 0 && button < Input::max_controller_buttons && button < button_count)
|
||||
{
|
||||
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;
|
||||
down[button] = true;
|
||||
pressed[button] = true;
|
||||
button_timestamp[button] = Time::ticks;
|
||||
}
|
||||
}
|
||||
|
||||
void InputBackend::on_controller_disconnect(int index)
|
||||
void ControllerState::on_release(Button button)
|
||||
{
|
||||
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)
|
||||
if (button >= 0 && button < Input::max_controller_buttons && button < 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;
|
||||
down[button] = false;
|
||||
released[button] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InputBackend::on_button_up(int index, int button)
|
||||
void ControllerState::on_axis(Axis index, float value)
|
||||
{
|
||||
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)
|
||||
if (index >= 0 && index < Input::max_controller_axis && index < axis_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;
|
||||
axis[index] = value;
|
||||
axis_timestamp[index] = Time::ticks;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace Blah
|
|||
Renderer renderer();
|
||||
|
||||
// Called once per frame
|
||||
void frame();
|
||||
void update();
|
||||
|
||||
// Called before rendering begins
|
||||
void before_render();
|
||||
|
|
|
@ -792,7 +792,7 @@ namespace Blah
|
|||
return state.features;
|
||||
}
|
||||
|
||||
void GraphicsBackend::frame()
|
||||
void GraphicsBackend::update()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@ namespace Blah
|
|||
return features;
|
||||
}
|
||||
|
||||
void GraphicsBackend::frame() {}
|
||||
void GraphicsBackend::update() {}
|
||||
void GraphicsBackend::before_render() {}
|
||||
void GraphicsBackend::after_render() {}
|
||||
|
||||
|
|
|
@ -1159,7 +1159,7 @@ namespace Blah
|
|||
return gl.features;
|
||||
}
|
||||
|
||||
void GraphicsBackend::frame() {}
|
||||
void GraphicsBackend::update() {}
|
||||
void GraphicsBackend::before_render() {}
|
||||
void GraphicsBackend::after_render() {}
|
||||
|
||||
|
|
|
@ -5,50 +5,13 @@ namespace Blah
|
|||
{
|
||||
namespace InputBackend
|
||||
{
|
||||
// This is called internally by the app, and initializes the input state
|
||||
// Initializes the Input State
|
||||
void init();
|
||||
|
||||
// This is called internally by the app, and updates the input state
|
||||
void frame();
|
||||
// Steps the input state
|
||||
void update_state();
|
||||
|
||||
// Call this when the Mouse moves relative to the window
|
||||
void on_mouse_move(float x, float y);
|
||||
|
||||
// Call this when the Mouse moves relative to the screen
|
||||
void on_mouse_screen_move(float x, float y);
|
||||
|
||||
// Call this when a Mouse Button is pressed
|
||||
void on_mouse_down(MouseButton button);
|
||||
|
||||
// Call this when a Mouse Button is released
|
||||
void on_mouse_up(MouseButton button);
|
||||
|
||||
// Call this when the Mouse Wheel moves
|
||||
void on_mouse_wheel(Point wheel);
|
||||
|
||||
// Call this when a keyboard key is pressed
|
||||
void on_key_down(Key key);
|
||||
|
||||
// Call this when a keyboard key is released
|
||||
void on_key_up(Key key);
|
||||
|
||||
// Call this on Text Input
|
||||
void on_text_utf8(const char* text);
|
||||
|
||||
// Call this when a Controller is connected. Note that the Name parameter must be kept valid
|
||||
// until on_controller_disconnect is called with the same index.
|
||||
void on_controller_connect(int index, const char* name, int isGamepad, int buttonCount, int axisCount, u16 vendor, u16 product, u16 version);
|
||||
|
||||
// Call this when a controller is disconnected
|
||||
void on_controller_disconnect(int index);
|
||||
|
||||
// Call this when a controller button is pressed
|
||||
void on_button_down(int index, int button);
|
||||
|
||||
// Call this when a controller button is released
|
||||
void on_button_up(int index, int button);
|
||||
|
||||
/// Call this when a controller axis is moved
|
||||
void on_axis_move(int index, int axis, float value);
|
||||
// Updates bindings
|
||||
void update_bindings();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <blah/common.h>
|
||||
#include <blah/filesystem.h>
|
||||
#include <blah/input.h>
|
||||
#include <blah/containers/vector.h>
|
||||
|
||||
namespace Blah
|
||||
|
@ -25,7 +26,7 @@ namespace Blah
|
|||
u64 ticks();
|
||||
|
||||
// Called every frame
|
||||
void frame();
|
||||
void update(InputState& state);
|
||||
|
||||
// Sleeps the current thread
|
||||
void sleep(int milliseconds);
|
||||
|
|
|
@ -164,11 +164,6 @@ namespace Blah
|
|||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
|
||||
#endif
|
||||
}
|
||||
// enable DirectX
|
||||
else if (App::renderer() == Renderer::D3D11)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// create the window
|
||||
|
@ -246,16 +241,18 @@ namespace Blah
|
|||
// Macro defined by X11 conflicts with MouseButton enum
|
||||
#undef None
|
||||
|
||||
void PlatformBackend::frame()
|
||||
void PlatformBackend::update(InputState& state)
|
||||
{
|
||||
// update the mouse every frame
|
||||
{
|
||||
int winX, winY, x, y;
|
||||
SDL_GetWindowPosition(window, &winX, &winY);
|
||||
int win_x, win_y, x, y;
|
||||
|
||||
SDL_GetWindowPosition(window, &win_x, &win_y);
|
||||
SDL_GetGlobalMouseState(&x, &y);
|
||||
|
||||
InputBackend::on_mouse_move((float)(x - winX), (float)(y - winY));
|
||||
InputBackend::on_mouse_screen_move((float)x, (float)y);
|
||||
state.mouse.on_move(
|
||||
Vec2((float)(x - win_x), (float)(y - win_y)),
|
||||
Vec2((float)x, (float)y));
|
||||
}
|
||||
|
||||
// poll normal events
|
||||
|
@ -278,7 +275,8 @@ namespace Blah
|
|||
btn = MouseButton::Right;
|
||||
else if (event.button.button == SDL_BUTTON_MIDDLE)
|
||||
btn = MouseButton::Middle;
|
||||
InputBackend::on_mouse_down(btn);
|
||||
|
||||
state.mouse.on_press(btn);
|
||||
}
|
||||
else if (event.type == SDL_MOUSEBUTTONUP)
|
||||
{
|
||||
|
@ -289,26 +287,27 @@ namespace Blah
|
|||
btn = MouseButton::Right;
|
||||
else if (event.button.button == SDL_BUTTON_MIDDLE)
|
||||
btn = MouseButton::Middle;
|
||||
InputBackend::on_mouse_up(btn);
|
||||
|
||||
state.mouse.on_release(btn);
|
||||
}
|
||||
else if (event.type == SDL_MOUSEWHEEL)
|
||||
{
|
||||
InputBackend::on_mouse_wheel(Point(event.wheel.x, event.wheel.y));
|
||||
state.mouse.wheel = Point(event.wheel.x, event.wheel.y);
|
||||
}
|
||||
// Keyboard
|
||||
else if (event.type == SDL_KEYDOWN)
|
||||
{
|
||||
if (event.key.repeat == 0)
|
||||
InputBackend::on_key_down((Key)event.key.keysym.scancode);
|
||||
state.keyboard.on_press((Key)event.key.keysym.scancode);
|
||||
}
|
||||
else if (event.type == SDL_KEYUP)
|
||||
{
|
||||
if (event.key.repeat == 0)
|
||||
InputBackend::on_key_up((Key)event.key.keysym.scancode);
|
||||
state.keyboard.on_release((Key)event.key.keysym.scancode);
|
||||
}
|
||||
else if (event.type == SDL_TEXTINPUT)
|
||||
{
|
||||
InputBackend::on_text_utf8(event.text.text);
|
||||
state.keyboard.text += event.text.text;
|
||||
}
|
||||
// Joystick Controller
|
||||
else if (event.type == SDL_JOYDEVICEADDED)
|
||||
|
@ -325,7 +324,7 @@ namespace Blah
|
|||
auto product = SDL_JoystickGetProduct(ptr);
|
||||
auto version = SDL_JoystickGetProductVersion(ptr);
|
||||
|
||||
InputBackend::on_controller_connect(index, name, 0, button_count, axis_count, vendor, product, version);
|
||||
state.controllers[index].on_connect(name, 0, button_count, axis_count, vendor, product, version);
|
||||
}
|
||||
}
|
||||
else if (event.type == SDL_JOYDEVICEREMOVED)
|
||||
|
@ -335,7 +334,7 @@ namespace Blah
|
|||
{
|
||||
if (SDL_IsGameController(index) == SDL_FALSE)
|
||||
{
|
||||
InputBackend::on_controller_disconnect(index);
|
||||
state.controllers[index].on_disconnect();
|
||||
SDL_JoystickClose(joysticks[index]);
|
||||
}
|
||||
}
|
||||
|
@ -346,7 +345,7 @@ namespace Blah
|
|||
if (index >= 0)
|
||||
{
|
||||
if (SDL_IsGameController(index) == SDL_FALSE)
|
||||
InputBackend::on_button_down(index, event.jbutton.button);
|
||||
state.controllers[index].on_press((Button)event.jbutton.button);
|
||||
}
|
||||
}
|
||||
else if (event.type == SDL_JOYBUTTONUP)
|
||||
|
@ -355,7 +354,7 @@ namespace Blah
|
|||
if (index >= 0)
|
||||
{
|
||||
if (SDL_IsGameController(index) == SDL_FALSE)
|
||||
InputBackend::on_button_up(index, event.jbutton.button);
|
||||
state.controllers[index].on_release((Button)event.jbutton.button);
|
||||
}
|
||||
}
|
||||
else if (event.type == SDL_JOYAXISMOTION)
|
||||
|
@ -370,7 +369,7 @@ namespace Blah
|
|||
value = event.jaxis.value / 32767.0f;
|
||||
else
|
||||
value = event.jaxis.value / 32768.0f;
|
||||
InputBackend::on_axis_move(index, event.jaxis.axis, value);
|
||||
state.controllers[index].on_axis((Axis)event.jaxis.axis, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -386,7 +385,7 @@ namespace Blah
|
|||
auto product = SDL_GameControllerGetProduct(ptr);
|
||||
auto version = SDL_GameControllerGetProductVersion(ptr);
|
||||
|
||||
InputBackend::on_controller_connect(index, name, 1, 15, 6, vendor, product, version);
|
||||
state.controllers[index].on_connect(name, 1, 15, 6, vendor, product, version);
|
||||
}
|
||||
}
|
||||
else if (event.type == SDL_CONTROLLERDEVICEREMOVED)
|
||||
|
@ -394,7 +393,7 @@ namespace Blah
|
|||
auto index = find_gamepad_index(event.cdevice.which);
|
||||
if (index >= 0)
|
||||
{
|
||||
InputBackend::on_controller_disconnect(index);
|
||||
state.controllers[index].on_disconnect();
|
||||
SDL_GameControllerClose(gamepads[index]);
|
||||
}
|
||||
}
|
||||
|
@ -403,11 +402,11 @@ namespace Blah
|
|||
auto index = find_gamepad_index(event.cdevice.which);
|
||||
if (index >= 0)
|
||||
{
|
||||
int button = (int)Button::None;
|
||||
Button button = Button::None;
|
||||
if (event.cbutton.button >= 0 && event.cbutton.button < 15)
|
||||
button = event.cbutton.button; // NOTE: These map directly to Engine Buttons enum!
|
||||
button = (Button)event.cbutton.button; // NOTE: These map directly to Engine Buttons enum!
|
||||
|
||||
InputBackend::on_button_down(index, button);
|
||||
state.controllers[index].on_press(button);
|
||||
}
|
||||
}
|
||||
else if (event.type == SDL_CONTROLLERBUTTONUP)
|
||||
|
@ -415,11 +414,11 @@ namespace Blah
|
|||
auto index = find_gamepad_index(event.cdevice.which);
|
||||
if (index >= 0)
|
||||
{
|
||||
int button = (int)Button::None;
|
||||
Button button = Button::None;
|
||||
if (event.cbutton.button >= 0 && event.cbutton.button < 15)
|
||||
button = event.cbutton.button; // NOTE: These map directly to Engine Buttons enum!
|
||||
button = (Button)event.cbutton.button; // NOTE: These map directly to Engine Buttons enum!
|
||||
|
||||
InputBackend::on_button_up(index, button);
|
||||
state.controllers[index].on_release(button);
|
||||
}
|
||||
}
|
||||
else if (event.type == SDL_CONTROLLERAXISMOTION)
|
||||
|
@ -427,9 +426,9 @@ namespace Blah
|
|||
auto index = find_gamepad_index(event.cdevice.which);
|
||||
if (index >= 0)
|
||||
{
|
||||
int axis = (int)Axis::None;
|
||||
Axis axis = Axis::None;
|
||||
if (event.caxis.axis >= 0 && event.caxis.axis < 6)
|
||||
axis = event.caxis.axis; // NOTE: These map directly to Engine Axis enum!
|
||||
axis = (Axis)event.caxis.axis; // NOTE: These map directly to Engine Axis enum!
|
||||
|
||||
float value;
|
||||
if (event.caxis.value >= 0)
|
||||
|
@ -437,7 +436,7 @@ namespace Blah
|
|||
else
|
||||
value = event.caxis.value / 32768.0f;
|
||||
|
||||
InputBackend::on_axis_move(index, axis, value);
|
||||
state.controllers[index].on_axis(axis, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,9 @@ namespace Blah
|
|||
RECT g_windowed_position;
|
||||
bool g_fullscreen = false;
|
||||
|
||||
// current input state
|
||||
InputState* g_input_state = nullptr;
|
||||
|
||||
// Converts Windows scancode to Blah key
|
||||
Key scancode_to_key(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
|
@ -329,35 +332,35 @@ namespace Blah
|
|||
|
||||
// Mouse Input
|
||||
case WM_LBUTTONDOWN:
|
||||
InputBackend::on_mouse_down(MouseButton::Left);
|
||||
g_input_state->mouse.on_press(MouseButton::Left);
|
||||
return 0;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
InputBackend::on_mouse_up(MouseButton::Left);
|
||||
g_input_state->mouse.on_release(MouseButton::Left);
|
||||
return 0;
|
||||
|
||||
case WM_RBUTTONDOWN:
|
||||
InputBackend::on_mouse_down(MouseButton::Right);
|
||||
g_input_state->mouse.on_press(MouseButton::Right);
|
||||
return 0;
|
||||
|
||||
case WM_RBUTTONUP:
|
||||
InputBackend::on_mouse_up(MouseButton::Right);
|
||||
g_input_state->mouse.on_release(MouseButton::Right);
|
||||
return 0;
|
||||
|
||||
case WM_MBUTTONDOWN:
|
||||
InputBackend::on_mouse_down(MouseButton::Middle);
|
||||
g_input_state->mouse.on_press(MouseButton::Middle);
|
||||
return 0;
|
||||
|
||||
case WM_MBUTTONUP:
|
||||
InputBackend::on_mouse_up(MouseButton::Middle);
|
||||
g_input_state->mouse.on_release(MouseButton::Middle);
|
||||
return 0;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
InputBackend::on_mouse_move((float)((u16)lParam), (float)(lParam >> 16));
|
||||
g_input_state->mouse.on_move(Vec2((float)((u16)lParam), (float)(lParam >> 16)), Vec2::zero);
|
||||
return 0;
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
InputBackend::on_mouse_wheel(Point(0, GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA));
|
||||
g_input_state->mouse.wheel = Point(0, GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA);
|
||||
return 0;
|
||||
|
||||
// Text Input
|
||||
|
@ -369,7 +372,7 @@ namespace Blah
|
|||
String result;
|
||||
result.append((u32)wParam);
|
||||
if (result.length() > 0)
|
||||
InputBackend::on_text_utf8(result.cstr());
|
||||
g_input_state->keyboard.text += result.cstr();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -382,7 +385,7 @@ namespace Blah
|
|||
{
|
||||
auto key = scancode_to_key(wParam, lParam);
|
||||
if (key != Key::Unknown)
|
||||
InputBackend::on_key_down(key);
|
||||
g_input_state->keyboard.on_press(key);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -392,7 +395,7 @@ namespace Blah
|
|||
{
|
||||
auto key = scancode_to_key(wParam, lParam);
|
||||
if (key != Key::Unknown)
|
||||
InputBackend::on_key_up(key);
|
||||
g_input_state->keyboard.on_release(key);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -400,8 +403,10 @@ namespace Blah
|
|||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
void PlatformBackend::frame()
|
||||
void PlatformBackend::update(InputState& state)
|
||||
{
|
||||
g_input_state = &state;
|
||||
|
||||
// Catch & Dispatch Window Messages
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
|
@ -850,4 +855,4 @@ namespace Blah
|
|||
}
|
||||
}
|
||||
|
||||
#endif // BLAH_PLATFORM_WINDOWS
|
||||
#endif // BLAH_PLATFORM_WIN32
|
||||
|
|
Loading…
Reference in New Issue
Block a user