|
|
@@ -21,22 +21,9 @@ |
|
|
|
namespace lol |
|
|
|
{ |
|
|
|
|
|
|
|
extern const std::string g_name_mouse; |
|
|
|
extern const std::string g_name_keyboard; |
|
|
|
extern std::string g_name_joystick(const uint64_t num); |
|
|
|
|
|
|
|
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, |
|
|
@@ -70,226 +57,210 @@ public: |
|
|
|
RightShoulder, |
|
|
|
}; |
|
|
|
|
|
|
|
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: |
|
|
|
InputDevice(std::string const &name) |
|
|
|
: m_name(name), |
|
|
|
m_input_active(false) |
|
|
|
class device |
|
|
|
{ |
|
|
|
devices.push_unique(this); |
|
|
|
} |
|
|
|
public: |
|
|
|
device(std::string const &name) : m_name(name) {} |
|
|
|
|
|
|
|
~InputDevice() |
|
|
|
{ |
|
|
|
for (int i = 0; i < devices.count(); ++i) |
|
|
|
class mouse; |
|
|
|
class keyboard; |
|
|
|
class joystick; |
|
|
|
|
|
|
|
/** Gets the name of this input device */ |
|
|
|
const std::string& GetName() const |
|
|
|
{ |
|
|
|
if (devices[i] == this) |
|
|
|
{ |
|
|
|
devices.remove(i); |
|
|
|
return; |
|
|
|
} |
|
|
|
return m_name; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** Gets the name of this input device */ |
|
|
|
const std::string& GetName() const |
|
|
|
{ |
|
|
|
return m_name; |
|
|
|
} |
|
|
|
// |
|
|
|
// Bindings section |
|
|
|
// |
|
|
|
|
|
|
|
/** Gets the index of the corresponding key, needed to call GetKey */ |
|
|
|
int GetKeyIndex(std::string const &name) const |
|
|
|
{ |
|
|
|
return GetItemIndex(name, m_key_names); |
|
|
|
} |
|
|
|
void bind(input::key key, uint16_t event); |
|
|
|
void unbind(input::key key, uint16_t event); |
|
|
|
|
|
|
|
/** Gets the index of the corresponding axis, needed to call GetAxis */ |
|
|
|
int GetAxisIndex(std::string const &name) const |
|
|
|
{ |
|
|
|
return GetItemIndex(name, m_axis_names); |
|
|
|
} |
|
|
|
void bind(input::button button, uint16_t event); |
|
|
|
void unbind(input::button button, uint16_t event); |
|
|
|
|
|
|
|
// |
|
|
|
// Bindings section |
|
|
|
// |
|
|
|
void bind(input::axis axis, uint16_t event); |
|
|
|
void unbind(input::axis axis, uint16_t event); |
|
|
|
|
|
|
|
void bind(input::key key, uint16_t event); |
|
|
|
void unbind(input::key key, uint16_t event); |
|
|
|
// |
|
|
|
// Key, button etc. state |
|
|
|
// |
|
|
|
|
|
|
|
void bind(input::button button, uint16_t event); |
|
|
|
void unbind(input::button button, uint16_t event); |
|
|
|
// Get the current state of the given key |
|
|
|
bool key(input::key key) const |
|
|
|
{ |
|
|
|
return (size_t)key >= m_keys.size() ? false : m_keys[(int)key]; |
|
|
|
} |
|
|
|
|
|
|
|
void bind(input::axis axis, uint16_t event); |
|
|
|
void unbind(input::axis axis, uint16_t event); |
|
|
|
bool key_released(input::key key) const |
|
|
|
{ |
|
|
|
return m_released_keys.find(key) != m_released_keys.end(); |
|
|
|
} |
|
|
|
|
|
|
|
// |
|
|
|
// Key, button etc. state |
|
|
|
// |
|
|
|
bool key_pressed(input::key key) const |
|
|
|
{ |
|
|
|
return m_pressed_keys.find(key) != m_pressed_keys.end(); |
|
|
|
} |
|
|
|
|
|
|
|
// Get the current state of the given key |
|
|
|
bool key(input::key key) const { return m_keys[(int)key]; } |
|
|
|
// Get the current state of the given button |
|
|
|
bool button(input::button button) const |
|
|
|
{ |
|
|
|
return (size_t)button >= m_buttons.size() ? false : m_buttons[(int)button]; |
|
|
|
} |
|
|
|
|
|
|
|
bool key_released(input::key key) const |
|
|
|
{ |
|
|
|
return m_released_keys.find(key) != m_released_keys.end(); |
|
|
|
} |
|
|
|
bool button_released(input::button button) const |
|
|
|
{ |
|
|
|
return m_released_buttons.find(button) != m_released_buttons.end(); |
|
|
|
} |
|
|
|
|
|
|
|
bool key_pressed(input::key key) const |
|
|
|
{ |
|
|
|
return m_pressed_keys.find(key) != m_pressed_keys.end(); |
|
|
|
} |
|
|
|
bool button_pressed(input::button button) const |
|
|
|
{ |
|
|
|
return m_pressed_buttons.find(button) != m_pressed_buttons.end(); |
|
|
|
} |
|
|
|
|
|
|
|
// Get the current state of the given button |
|
|
|
bool button(input::button button) const { return m_buttons[(int)button]; } |
|
|
|
// Get the current state of the given axis |
|
|
|
float axis(input::axis axis) const |
|
|
|
{ |
|
|
|
return (size_t)axis >= m_axes.size() ? 0.0f : m_axes[(int)axis]; |
|
|
|
} |
|
|
|
|
|
|
|
bool button_released(input::button button) const |
|
|
|
{ |
|
|
|
return m_released_buttons.find(button) != m_released_buttons.end(); |
|
|
|
} |
|
|
|
bool axis_changed(input::axis axis) const |
|
|
|
{ |
|
|
|
return m_changed_axes.find(axis) != m_changed_axes.end(); |
|
|
|
} |
|
|
|
|
|
|
|
bool button_pressed(input::button button) const |
|
|
|
{ |
|
|
|
return m_pressed_buttons.find(button) != m_pressed_buttons.end(); |
|
|
|
} |
|
|
|
// TODO: axis sensitivity was removed |
|
|
|
|
|
|
|
// Get the current state of the given axis |
|
|
|
float axis(input::axis axis) const { return m_axes[(int)axis]; } |
|
|
|
// |
|
|
|
// Keyboard-specific section |
|
|
|
// |
|
|
|
|
|
|
|
bool axis_changed(input::axis axis) const |
|
|
|
{ |
|
|
|
return m_changed_axes.find(axis) != m_changed_axes.end(); |
|
|
|
} |
|
|
|
/** Get the names of all available keys on this device */ |
|
|
|
std::vector<std::string> const& key_names() const { return m_key_names; } |
|
|
|
|
|
|
|
// TODO: axis sensitivity was removed |
|
|
|
/** Get the current state of all keys */ |
|
|
|
std::vector<bool> const &keys() const { return m_keys; } |
|
|
|
|
|
|
|
// |
|
|
|
// Keyboard-specific section |
|
|
|
// |
|
|
|
/** Gets the latest contents of text input. */ |
|
|
|
std::string text(); |
|
|
|
|
|
|
|
/** Get the names of all available keys on this device */ |
|
|
|
std::vector<std::string> const& key_names() const { return m_key_names; } |
|
|
|
bool capture_text(); |
|
|
|
void capture_text(bool status); |
|
|
|
|
|
|
|
/** Get the current state of all keys */ |
|
|
|
std::vector<bool> const &keys() const { return m_keys; } |
|
|
|
// |
|
|
|
// Mouse-specific section |
|
|
|
// |
|
|
|
|
|
|
|
/** Gets the latest contents of text input. */ |
|
|
|
std::string text(); |
|
|
|
// Gets and sets whether the mouse cursor should be captured. |
|
|
|
void capture(bool value) { m_capture = value; } |
|
|
|
bool capture() const { return m_capture; } |
|
|
|
|
|
|
|
bool capture_text(); |
|
|
|
void capture_text(bool status); |
|
|
|
public: |
|
|
|
/** Internal functions that allow to construct an input device |
|
|
|
* dynamically, when the keys, axis and cursors are not known at |
|
|
|
* compile time. */ |
|
|
|
void internal_add_key(input::key, char const *name); |
|
|
|
void internal_add_button(input::button, char const *name); |
|
|
|
void internal_add_axis(input::axis, char const *name); |
|
|
|
|
|
|
|
// |
|
|
|
// Mouse-specific section |
|
|
|
// |
|
|
|
/* 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(); |
|
|
|
m_changed_axes.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
// Gets and sets whether the mouse cursor should be captured. |
|
|
|
void capture(bool value) { m_capture = value; } |
|
|
|
bool capture() const { return m_capture; } |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
/** Gets an input device by its name */ |
|
|
|
static InputDevice* Get(std::string const &name) |
|
|
|
{ |
|
|
|
for (int i = 0; i < devices.count(); ++i) |
|
|
|
void internal_set_button(input::button button, bool state) |
|
|
|
{ |
|
|
|
if (devices[i]->m_name == name) |
|
|
|
return devices[i]; |
|
|
|
if (m_buttons[(int)button] != state) |
|
|
|
(state ? m_pressed_buttons : m_released_buttons).insert(button); |
|
|
|
m_buttons[(int)button] = state; |
|
|
|
} |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
public: |
|
|
|
/** Internal functions that allow to construct an InputDevice |
|
|
|
* dynamically, when the keys, axis and cursors are not known at |
|
|
|
* compile time. */ |
|
|
|
void internal_add_key(input::key, char const *name); |
|
|
|
void internal_add_button(input::button, char const *name); |
|
|
|
void internal_add_axis(input::axis, char const *name); |
|
|
|
|
|
|
|
/* 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(); |
|
|
|
m_changed_axes.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
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_axis(input::axis axis, float value) |
|
|
|
{ |
|
|
|
if (m_axes[(int)axis] != value) |
|
|
|
m_changed_axes.insert(axis); |
|
|
|
m_axes[(int)axis] = value; |
|
|
|
} |
|
|
|
|
|
|
|
void internal_set_button(input::button button, bool 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) |
|
|
|
{ |
|
|
|
m_text += text; |
|
|
|
} |
|
|
|
|
|
|
|
void internal_set_axis(input::axis axis, float value) |
|
|
|
{ |
|
|
|
if (m_axes[(int)axis] != value) |
|
|
|
m_changed_axes.insert(axis); |
|
|
|
m_axes[(int)axis] = value; |
|
|
|
} |
|
|
|
protected: |
|
|
|
std::string m_name; |
|
|
|
|
|
|
|
void internal_add_text(std::string const &text) |
|
|
|
{ |
|
|
|
m_text += text; |
|
|
|
} |
|
|
|
std::vector<std::string> m_key_names; |
|
|
|
std::vector<std::string> m_button_names; |
|
|
|
std::vector<std::string> m_axis_names; |
|
|
|
|
|
|
|
protected: |
|
|
|
// TODO: hide all of this in a InputDeviceData? |
|
|
|
/** 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; |
|
|
|
std::vector<float> m_axes; |
|
|
|
std::unordered_set<input::axis> m_changed_axes; |
|
|
|
|
|
|
|
std::string m_name; |
|
|
|
// Text input state |
|
|
|
std::string m_text; |
|
|
|
bool m_input_active = false; |
|
|
|
|
|
|
|
std::vector<std::string> m_key_names; |
|
|
|
std::vector<std::string> m_button_names; |
|
|
|
std::vector<std::string> m_axis_names; |
|
|
|
// Capture (for mouse devices) |
|
|
|
bool m_capture = false; |
|
|
|
}; |
|
|
|
|
|
|
|
/** 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; |
|
|
|
std::vector<float> m_axes; |
|
|
|
std::unordered_set<input::axis> m_changed_axes; |
|
|
|
// Default devices |
|
|
|
|
|
|
|
// Text input state |
|
|
|
std::string m_text; |
|
|
|
bool m_input_active; |
|
|
|
static std::shared_ptr<class device::keyboard> keyboard() { return get()->m_keyboard; } |
|
|
|
static std::shared_ptr<class device::mouse> mouse() { return get()->m_mouse; } |
|
|
|
static std::shared_ptr<class device::joystick> joystick(int n); |
|
|
|
|
|
|
|
// Capture (for mouse devices) |
|
|
|
bool m_capture = false; |
|
|
|
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); |
|
|
|
|
|
|
|
private: |
|
|
|
static array<InputDevice*> devices; |
|
|
|
input(); |
|
|
|
|
|
|
|
template <typename... T> |
|
|
|
int GetItemIndex(std::string const &name, std::vector<std::string, T...> const& a) const |
|
|
|
{ |
|
|
|
for (size_t i = 0; i < a.size(); ++i) |
|
|
|
if (a[i] == name) |
|
|
|
return (int)i; |
|
|
|
return -1; |
|
|
|
} |
|
|
|
static std::shared_ptr<input> get(); |
|
|
|
|
|
|
|
std::shared_ptr<device::keyboard> m_keyboard; |
|
|
|
std::shared_ptr<device::mouse> m_mouse; |
|
|
|
std::map<int, std::shared_ptr<device::joystick>> m_joysticks; |
|
|
|
}; |
|
|
|
|
|
|
|
class input::device::mouse : public input::device |
|
|
|
{ |
|
|
|
public: |
|
|
|
mouse(std::string const &name) : input::device(name) {} |
|
|
|
}; |
|
|
|
|
|
|
|
class input::device::keyboard : public input::device |
|
|
|
{ |
|
|
|
public: |
|
|
|
keyboard(std::string const &name) : input::device(name) {} |
|
|
|
}; |
|
|
|
|
|
|
|
class input::device::joystick : public input::device |
|
|
|
{ |
|
|
|
public: |
|
|
|
joystick(std::string const &name) : input::device(name) {} |
|
|
|
}; |
|
|
|
|
|
|
|
} /* namespace lol */ |
|
|
|