Просмотр исходного кода

input: start implementing controller features directly in the input device.

legacy
Sam Hocevar 5 лет назад
Родитель
Сommit
fe66f12e53
11 измененных файлов: 216 добавлений и 151 удалений
  1. +7
    -6
      doc/tutorial/07_input.cpp
  2. +1
    -1
      doc/tutorial/11_fractal.cpp
  3. +30
    -51
      doc/tutorial/12_voronoi.cpp
  4. +1
    -1
      src/application/android-app.cpp
  5. +5
    -5
      src/ui/controller.cpp
  6. +1
    -1
      src/ui/controller.h
  7. +1
    -1
      src/ui/d3d9-input.cpp
  8. +10
    -10
      src/ui/gui.cpp
  9. +18
    -4
      src/ui/input.cpp
  10. +121
    -51
      src/ui/input.h
  11. +21
    -20
      src/ui/sdl-input.cpp

+ 7
- 6
doc/tutorial/07_input.cpp Просмотреть файл

@@ -31,10 +31,10 @@ public:
# ifdef OLD_SCHOOL
m_controller->SetInputCount(KEY_MAX, AXIS_MAX);

auto keyboard = input::get()->keyboard();
auto keyboard = input::keyboard();
m_controller->GetKey(KEY_MANUAL_ROTATION).Bind(g_name_keyboard, "Space");

auto mouse = input::get()->mouse();
auto mouse = input::mouse();
if (mouse)
{
m_controller->GetKey(KEY_DRAG_MESH).Bind(g_name_mouse, "Left");
@@ -119,20 +119,21 @@ public:
/* Handle mouse */
if (true)
{
if (m_controller->IsKeyPressed(KEY_DRAG_MESH))
auto mouse = input::mouse();

if (mouse->button(input::button::BTN_Left))
{
input::get()->mouse_capture(true);
mouse->capture(true);
m_pitch_angle -= m_controller->GetAxisValue(AXIS_DRAG_PITCH) * seconds * 0.1f;
m_yaw_angle += m_controller->GetAxisValue(AXIS_DRAG_YAW) * seconds * 0.1f;
}
else
{
input::get()->mouse_capture(false);
mouse->capture(false);
if (m_autorot)
m_yaw_angle += seconds * 0.2f;
}

auto mouse = input::get()->mouse();
m_text->SetText(lol::format(
"cursor: (%0.3f, %0.3f) - pixel (%d, %d)",
mouse->get_cursor_uv(0).x, mouse->get_cursor_uv(0).y,


+ 1
- 1
doc/tutorial/11_fractal.cpp Просмотреть файл

@@ -157,7 +157,7 @@ public:
{
WorldEntity::tick_game(seconds);

ivec2 mousepos = input::get()->mouse()->get_cursor_pixel(0);
ivec2 mousepos = input::mouse()->get_cursor_pixel(0);

int prev_frame = (m_frame + 4) % 4;
m_frame = (m_frame + 1) % 4;


+ 30
- 51
doc/tutorial/12_voronoi.cpp Просмотреть файл

@@ -28,18 +28,6 @@ LOLFX_RESOURCE_DECLARE(12_voronoi_distance);
LOLFX_RESOURCE_DECLARE(12_distance);
LOLFX_RESOURCE_DECLARE(12_texture_to_screen);

enum
{
KEY_ESC,
KEY_PUSH,
KEY_POP,
KEY_F1,
KEY_F2,
KEY_F3,

KEY_MAX
};

enum FboType
{
SrcVoronoiFbo,
@@ -66,24 +54,17 @@ public:
m_time = .0f;
m_timer = -1.0f;
mode = 0;
m_controller = new Controller("Default");
m_controller->GetKey(KEY_ESC).Bind(g_name_keyboard, "Escape");
m_controller->GetKey(KEY_PUSH).Bind(g_name_keyboard, "p");
m_controller->GetKey(KEY_POP).Bind(g_name_keyboard, "o");
m_controller->GetKey(KEY_F1).Bind(g_name_keyboard, "F1");
m_controller->GetKey(KEY_F2).Bind(g_name_keyboard, "F2");
m_controller->GetKey(KEY_F3).Bind(g_name_keyboard, "F3");
}

virtual void tick_game(float seconds)
{
WorldEntity::tick_game(seconds);

{
//Shutdown logic
if (m_controller->WasKeyReleasedThisFrame(KEY_ESC))
Ticker::Shutdown();
}
auto keyboard = input::keyboard();
// Shutdown logic
if (keyboard->key_released(input::key::SC_Escape))
Ticker::Shutdown();

m_time += seconds;
m_hotspot = 0.4f * vec3((float)lol::sin(m_time * 4.0) + (float)lol::cos(m_time * 5.3),
@@ -170,34 +151,33 @@ public:
m_cur_fbo = VoronoiFbo;
}

auto keyboard = input::keyboard();

if (keyboard->key_released(input::key::SC_O))
voronoi_points.pop();
else if (keyboard->key_released(input::key::SC_P))
voronoi_points.push(vec3(rand<float>(512.f), rand<float>(512.f), .0f),
vec2(64.f + rand<float>(64.f), 64.f + rand<float>(64.f)));
else if (keyboard->key_released(input::key::SC_F1))
m_cur_fbo = SrcVoronoiFbo;
else if (keyboard->key_released(input::key::SC_F2))
m_cur_fbo = VoronoiFbo;
else if (keyboard->key_released(input::key::SC_F3))
{
//Shutdown logic
if (m_controller->WasKeyReleasedThisFrame(KEY_POP))
voronoi_points.pop();
else if (m_controller->WasKeyReleasedThisFrame(KEY_PUSH))
voronoi_points.push(vec3(rand<float>(512.f), rand<float>(512.f), .0f),
vec2(64.f + rand<float>(64.f), 64.f + rand<float>(64.f)));
else if (m_controller->WasKeyReleasedThisFrame(KEY_F1))
m_cur_fbo = SrcVoronoiFbo;
else if (m_controller->WasKeyReleasedThisFrame(KEY_F2))
m_cur_fbo = VoronoiFbo;
else if (m_controller->WasKeyReleasedThisFrame(KEY_F3))
voronoi_points.clear();
if (mode == 0)
{
voronoi_points.clear();
if (mode == 0)
{
int i = 4;
while (i-- > 0)
voronoi_points.push(vec3(rand<float>(512.f), rand<float>(512.f), .0f),
vec2(64.f + rand<float>(64.f), 64.f + rand<float>(64.f))
//vec2::zero
);
mode = 1;
}
else
{
mode = 0;
}
int i = 4;
while (i-- > 0)
voronoi_points.push(vec3(rand<float>(512.f), rand<float>(512.f), .0f),
vec2(64.f + rand<float>(64.f), 64.f + rand<float>(64.f))
//vec2::zero
);
mode = 1;
}
else
{
mode = 0;
}
}

@@ -381,7 +361,6 @@ public:
}

private:
Controller* m_controller;
array<vec3, vec2> voronoi_points;
array<vec2> m_vertices;
std::shared_ptr<Shader> m_screen_shader;


+ 1
- 1
src/application/android-app.cpp Просмотреть файл

@@ -193,7 +193,7 @@ void lol::AndroidAppData::DestroyDisplay()
*/
int32_t lol::AndroidAppData::HandleInput(AInputEvent* event)
{
auto mouse = input::get()->mouse();
auto mouse = input::mouse();

switch (AInputEvent_getType(event))
{


+ 5
- 5
src/ui/controller.cpp Просмотреть файл

@@ -200,10 +200,10 @@ float AxisBinding::RetrieveCurrentValue()
for (int i = 0; i < m_keybindings.count(); ++i)
{
float value = 0.0f;
m_keybindings[i].m1->key(m_keybindings[i].m2);
value += m_keybindings[i].m1->key(m_keybindings[i].m3) ? 1.0f : 0.0f;
m_keybindings[i].m1->key((input::key)m_keybindings[i].m2);
value += m_keybindings[i].m1->key((input::key)m_keybindings[i].m3) ? 1.0f : 0.0f;
if (m_keybindings[i].m2 != -1)
value += m_keybindings[i].m1->key(m_keybindings[i].m2) ? -1.0f : 0.0f;
value += m_keybindings[i].m1->key((input::key)m_keybindings[i].m2) ? -1.0f : 0.0f;

if (value > max_positive)
max_positive = value;
@@ -371,7 +371,7 @@ void Controller::BindProfile(InputProfile const& setup)
m_profile = setup;

// Keyboard
m_keyboard = input::get()->keyboard();
m_keyboard = input::keyboard();
if (m_keyboard)
{
for (InputProfile::KeyboardKey& key : m_profile.m_keys)
@@ -379,7 +379,7 @@ void Controller::BindProfile(InputProfile const& setup)
}

// Mouse
m_mouse = input::get()->mouse();
m_mouse = input::mouse();
if (m_mouse)
{
for (InputProfile::MouseKey& key : m_profile.m_mouse_keys)


+ 1
- 1
src/ui/controller.h Просмотреть файл

@@ -56,7 +56,7 @@ protected:
m_previous = m_current;
m_current = false;
for (int i = 0; i < m_keybindings.count(); ++i)
m_current = m_current || m_keybindings[i].m1->key(m_keybindings[i].m2);
m_current = m_current || m_keybindings[i].m1->key((input::key)m_keybindings[i].m2);
}

/** m1 is the InputDevice, m2 is the key index on the InputDevice */


+ 1
- 1
src/ui/d3d9-input.cpp Просмотреть файл

@@ -145,7 +145,7 @@ void D3d9Input::tick_game(float seconds)

int key_index = (1 << b) > XINPUT_GAMEPAD_RIGHT_SHOULDER ? b - 2 : b;

m_data->m_joysticks[i].m2->internal_set_key(key_index, ((uint16_t)(state.Gamepad.wButtons) >> b) & 1);
m_data->m_joysticks[i].m2->internal_set_button((input::button)key_index, ((uint16_t)(state.Gamepad.wButtons) >> b) & 1);
}
}
#endif


+ 10
- 10
src/ui/gui.cpp Просмотреть файл

@@ -207,8 +207,8 @@ void gui::tick_game(float seconds)
{
super::tick_game(seconds);

auto keyboard = input::get()->keyboard();
auto mouse = input::get()->mouse();
auto keyboard = input::keyboard();
auto mouse = input::mouse();

ImGuiIO& io = ImGui::GetIO();

@@ -233,13 +233,13 @@ void gui::tick_game(float seconds)
io.MouseDrawCursor = true;

// Update Keyboard
io.KeyCtrl = m_controller->IsKeyPressed((int)input::key::SC_LCtrl)
|| m_controller->IsKeyPressed((int)input::key::SC_RCtrl);
io.KeyShift = m_controller->IsKeyPressed((int)input::key::SC_LShift)
|| m_controller->IsKeyPressed((int)input::key::SC_RShift);
io.KeyCtrl = keyboard->key(input::key::SC_LCtrl)
|| keyboard->key(input::key::SC_RCtrl);
io.KeyShift = keyboard->key(input::key::SC_LShift)
|| keyboard->key(input::key::SC_RShift);

for (input::key k : input::all_keys())
io.KeysDown[(int)k] = m_controller->IsKeyPressed((int)k);
io.KeysDown[(int)k] = keyboard->key(k);

// Update text input
if (io.WantTextInput)
@@ -259,9 +259,9 @@ void gui::tick_game(float seconds)
//msg::debug("%.2f/%.2f\n", io.MousePos.x, io.MousePos.y);
io.MouseWheel = m_controller->GetAxisValue(axis_enum::Scroll);

io.MouseDown[0] = m_controller->IsKeyPressed(key_enum::LeftClick);
io.MouseDown[1] = m_controller->IsKeyPressed(key_enum::RightClick);
io.MouseDown[2] = m_controller->IsKeyPressed(key_enum::MiddleClick);
io.MouseDown[0] = mouse->button(input::button::BTN_Left);
io.MouseDown[1] = mouse->button(input::button::BTN_Right);
io.MouseDown[2] = mouse->button(input::button::BTN_Middle);
// FIXME: handle key_enum::Focus?

// Start the frame


+ 18
- 4
src/ui/input.cpp Просмотреть файл

@@ -47,11 +47,11 @@ input::input()

// Create default mouse device
m_mouse = std::make_shared<InputDevice>(g_name_mouse.c_str());
m_mouse->AddKey(g_name_mouse_key_left.c_str());
m_mouse->AddKey(g_name_mouse_key_middle.c_str());
m_mouse->AddKey(g_name_mouse_key_right.c_str());
m_mouse->AddButton((int)input::button::BTN_Left, g_name_mouse_key_left.c_str());
m_mouse->AddButton((int)input::button::BTN_Middle, g_name_mouse_key_middle.c_str());
m_mouse->AddButton((int)input::button::BTN_Right, g_name_mouse_key_right.c_str());
m_mouse->AddButton((int)input::button::BTN_Focus, g_name_mouse_key_in_screen.c_str());
// Added to manage if mouse is in the screen or not.
m_mouse->AddKey(g_name_mouse_key_in_screen.c_str());
m_mouse->AddAxis(g_name_mouse_axis_x.c_str());
m_mouse->AddAxis(g_name_mouse_axis_y.c_str());
m_mouse->AddAxis(g_name_mouse_axis_xpixel.c_str());
@@ -130,6 +130,20 @@ void InputDevice::AddKey(int index, const char* name)
m_key_names[index] = name;
}

void InputDevice::AddButton(int index, const char* name)
{
if (index == -1)
index = (int)m_button_names.size();

while (index >= (int)m_button_names.size())
{
m_button_names.push_back("");
m_buttons.push_back(false);
}

m_button_names[index] = name;
}

void InputDevice::AddAxis(int index, const char* name, float sensitivity)
{
if (index == -1)


+ 121
- 51
src/ui/input.h Просмотреть файл

@@ -15,6 +15,7 @@

#include <string>
#include <vector>
#include <unordered_set>
#include <memory>

namespace lol
@@ -29,6 +30,7 @@ const std::string g_name_mouse_key_left("Left");
const std::string g_name_mouse_key_middle("Middle");
const std::string g_name_mouse_key_right("Right");
const std::string g_name_mouse_key_in_screen("InScreen");

const std::string g_name_mouse_axis_x("X");
const std::string g_name_mouse_axis_y("Y");
const std::string g_name_mouse_axis_xpixel("XPixel");
@@ -36,6 +38,45 @@ const std::string g_name_mouse_axis_ypixel("YPixel");
const std::string g_name_mouse_axis_scroll("Scroll");
const std::string g_name_mouse_cursor("Cursor");

class input
{
public:
static std::shared_ptr<input> get();

// Default devices

static std::shared_ptr<class InputDevice> keyboard() { return get()->m_keyboard; }
static std::shared_ptr<class InputDevice> mouse() { return get()->m_mouse; }

// Keyboard API

enum class key : uint16_t
{
#define _SC(id, str, name) SC_##name = id,
#include "ui/keys.inc"
};

enum class button : uint16_t
{
BTN_Left,
BTN_Right,
BTN_Middle,
BTN_Focus,
};

static std::vector<key> const &all_keys();
static std::string const &key_to_name(key k);
static key name_to_key(std::string const &name);

// Joystick API

private:
input();

std::shared_ptr<class InputDevice> m_keyboard;
std::shared_ptr<class InputDevice> m_mouse;
};

class InputDevice
{
public:
@@ -76,6 +117,46 @@ public:
return GetItemIndex(name, m_axis_names);
}

//
// Bindings section
//

void bind(input::key key, uint16_t event);
void unbind(input::key key, uint16_t event);

void bind(input::button button, uint16_t event);
void unbind(input::button button, uint16_t event);

//
// Key, button etc. state
//

// Get the current state of the given key
bool key(input::key key) const { return m_keys[(int)key]; }

bool key_released(input::key key) const
{
return m_released_keys.find(key) != m_released_keys.end();
}

bool key_pressed(input::key key) const
{
return m_pressed_keys.find(key) != m_pressed_keys.end();
}

// Get the current state of the given button
bool button(input::button button) const { return m_buttons[(int)button]; }

bool button_released(input::button button) const
{
return m_released_buttons.find(button) != m_released_buttons.end();
}

bool button_pressed(input::button button) const
{
return m_pressed_buttons.find(button) != m_pressed_buttons.end();
}

//
// Keyboard-specific section
//
@@ -86,17 +167,19 @@ public:
/** Get the current state of all keys */
std::vector<bool> const &keys() const { return m_keys; }

/** Get the current state of the given key, true being pressed and
* false being released */
bool key(int index) const { return m_keys[index]; }

/** Gets the latest contents of text input. */
std::string text();

bool capture_text();
void capture_text(bool status);

//
// Mouse-specific section
//

// Gets and sets whether the mouse cursor should be captured.
void capture(bool value) { m_capture = value; }
bool capture() const { return m_capture; }

/** Gets the current value of the given axis. Devices should try to
* clamp this value between -1 and 1, though it is not guaranteed. */
@@ -169,6 +252,13 @@ public:
AddKey(-1, name);
}

void AddButton(int id, char const * name);

inline void AddButton(char const * name)
{
AddButton(-1, name);
}

void AddAxis(int id, char const * name, float sensitivity = 1.0f);

inline void AddAxis(char const * name, float sensitivity = 1.0f)
@@ -184,15 +274,32 @@ public:
}

/* Internal functions for the platform-specific drivers. */
void internal_begin_frame()
{
m_pressed_keys.clear();
m_released_keys.clear();
m_pressed_buttons.clear();
m_released_buttons.clear();
}

void internal_set_cursor(int id, vec2 const & position, ivec2 const & pixel)
{
m_cursors[id].uv = position;
m_cursors[id].pixel = pixel;
}

void internal_set_key(int id, bool state)
void internal_set_key(input::key key, bool state)
{
if (m_keys[(int)key] != state)
(state ? m_pressed_keys : m_released_keys).insert(key);
m_keys[(int)key] = state;
}

void internal_set_button(input::button button, bool state)
{
m_keys[id] = state;
if (m_buttons[(int)button] != state)
(state ? m_pressed_buttons : m_released_buttons).insert(button);
m_buttons[(int)button] = state;
}

void internal_add_text(std::string const &text)
@@ -211,11 +318,15 @@ protected:
std::string m_name;

std::vector<std::string> m_key_names;
std::vector<std::string> m_button_names;
std::vector<std::string> m_axis_names;
std::vector<std::string> m_cursor_names;

/** Key states (pressed/released) */
/** Key and button states (pressed/released) */
std::vector<bool> m_keys;
std::unordered_set<input::key> m_pressed_keys, m_released_keys;
std::vector<bool> m_buttons;
std::unordered_set<input::button> m_pressed_buttons, m_released_buttons;

/** Text input state */
std::string m_text;
@@ -228,6 +339,9 @@ protected:
struct cursor_state { vec2 uv; ivec2 pixel; };
std::vector<cursor_state> m_cursors;

// Capture (for mouse devices)
bool m_capture = false;

private:
static array<InputDevice*> devices;

@@ -251,49 +365,5 @@ private:
}
};

class input
{
public:
static std::shared_ptr<input> get();

// Default devices

std::shared_ptr<InputDevice> keyboard() { return m_keyboard; }
std::shared_ptr<InputDevice> mouse() { return m_mouse; }

// Keyboard API

enum class key : uint16_t
{
#define _SC(id, str, name) SC_##name = id,
#include "ui/keys.inc"
};

static std::vector<key> const &all_keys();
static std::string const &key_to_name(key k);
static key name_to_key(std::string const &name);

// Internal keyboard API (TODO: move to input device class?)

void internal_set_key(key k, bool state);
void internal_add_text(std::string const &text);

// Mouse API

/** Gets and sets whether the mouse cursor should be captured. */
void mouse_capture(bool value) { m_mouse_capture = value; }
bool mouse_capture() const { return m_mouse_capture; }

// Joystick API

private:
input();

std::shared_ptr<InputDevice> m_keyboard;
std::shared_ptr<InputDevice> m_mouse;

bool m_mouse_capture = false;
};

} /* namespace lol */


+ 21
- 20
src/ui/sdl-input.cpp Просмотреть файл

@@ -131,8 +131,8 @@ void SdlInput::tick(float seconds)
/* FIXME: maybe we should make use of this? */
UNUSED(seconds);

auto keyboard = input::get()->keyboard();
auto mouse = input::get()->mouse();
auto keyboard = input::keyboard();
auto mouse = input::mouse();

/* Pump all joystick events because no event is coming to us. */
# if SDL_FORCE_POLL_JOYSTICK && !__EMSCRIPTEN__
@@ -140,12 +140,13 @@ void SdlInput::tick(float seconds)
for (int j = 0; j < m_joysticks.count(); j++)
{
for (int i = 0; i < SDL_JoystickNumButtons(m_joysticks[j].m1); i++)
m_joysticks[j].m2->internal_set_key(i, SDL_JoystickGetButton(m_joysticks[j].m1, i) != 0);
m_joysticks[j].m2->internal_set_button((input::button)i, SDL_JoystickGetButton(m_joysticks[j].m1, i) != 0);
for (int i = 0; i < SDL_JoystickNumAxes(m_joysticks[j].m1); i++)
m_joysticks[j].m2->internal_set_axis(i, (float)SDL_JoystickGetAxis(m_joysticks[j].m1, i) / 32768.f);
}
# endif

keyboard->internal_begin_frame();
mouse->internal_set_axis(4, 0);

if (keyboard->capture_text())
@@ -165,29 +166,29 @@ void SdlInput::tick(float seconds)

case SDL_KEYDOWN:
case SDL_KEYUP:
switch (int sc = event.key.keysym.scancode)
switch (auto sc = (input::key)event.key.keysym.scancode)
{
// Lock management
case (int)input::key::SC_CapsLock:
case (int)input::key::SC_ScrollLock:
case (int)input::key::SC_NumLockClear:
case input::key::SC_CapsLock:
case input::key::SC_ScrollLock:
case input::key::SC_NumLockClear:
// Update status on key down only
if (event.type == SDL_KEYDOWN)
{
int sc2 = sc;
auto sc2 = sc;
switch (sc)
{
case (int)input::key::SC_CapsLock:
sc2 = (int)input::key::SC_CapsLockStatus;
case input::key::SC_CapsLock:
sc2 = input::key::SC_CapsLockStatus;
break;
case (int)input::key::SC_ScrollLock:
sc2 = (int)input::key::SC_ScrollLockStatus;
case input::key::SC_ScrollLock:
sc2 = input::key::SC_ScrollLockStatus;
break;
case (int)input::key::SC_NumLockClear:
sc2 = (int)input::key::SC_NumLockClearStatus;
case input::key::SC_NumLockClear:
sc2 = input::key::SC_NumLockClearStatus;
break;
}
keyboard->internal_set_key(sc2, !keyboard->key((int)sc2));
keyboard->internal_set_key(sc2, !keyboard->key(sc2));
}
LOL_ATTR_FALLTHROUGH
default:
@@ -205,7 +206,7 @@ void SdlInput::tick(float seconds)
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
//event.button.which
mouse->internal_set_key(event.button.button - 1, event.type == SDL_MOUSEBUTTONDOWN);
mouse->internal_set_button((input::button)(event.button.button - 1), event.type == SDL_MOUSEBUTTONDOWN);
break;
case SDL_MOUSEWHEEL:
mouse->internal_set_axis(4, (float)event.button.y);
@@ -216,11 +217,11 @@ void SdlInput::tick(float seconds)
{
case SDL_WINDOWEVENT_ENTER:
case SDL_WINDOWEVENT_FOCUS_GAINED:
mouse->internal_set_key(3, true);
mouse->internal_set_button(input::button::BTN_Focus, true);
break;
case SDL_WINDOWEVENT_LEAVE:
case SDL_WINDOWEVENT_FOCUS_LOST:
mouse->internal_set_key(3, false);
mouse->internal_set_button(input::button::BTN_Focus, false);
break;
case SDL_WINDOWEVENT_RESIZED:
Video::Resize(ivec2(event.window.data1, event.window.data2));
@@ -247,9 +248,9 @@ void SdlInput::tick(float seconds)
SDL_GetMouseState(&mouse_pos.x, &mouse_pos.y);
mouse_pos.y = Video::GetSize().y - 1 - mouse_pos.y;

if (input::get()->mouse_capture() != m_mousecapture)
if (mouse->capture() != m_mousecapture)
{
m_mousecapture = input::get()->mouse_capture();
m_mousecapture = mouse->capture();
SDL_SetRelativeMouseMode(m_mousecapture ? SDL_TRUE : SDL_FALSE);
mouse_pos = ivec2(m_app * .5f);



Загрузка…
Отмена
Сохранить