Skip to content
Snippets Groups Projects
Commit 2f194e47 authored by Joseph Walton-Rivers's avatar Joseph Walton-Rivers
Browse files

basic controller support

parent 28e5527d
No related branches found
No related tags found
No related merge requests found
......@@ -2,3 +2,4 @@ build/
cmake-build-debug/
cmake-build-debug-coverage/
.idea/
imgui.ini
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
......@@ -13,6 +13,8 @@
#include <fggl/debug/debug.h>
#include <fggl/data/storage.hpp>
#include <imgui.h>
template <typename T> int sgn(T val) {
return (T(0) < val) - (val < T(0));
}
......@@ -109,6 +111,7 @@ int main(int argc, char* argv[]) {
// build our main window
fggl::gfx::Window win( fggl::gfx::Input::instance() );
win.title("FGGL Demo");
win.fullscreen( true );
// opengl time
......@@ -117,7 +120,7 @@ int main(int argc, char* argv[]) {
// debug layer
fggl::debug::DebugUI debug(win);
debug.visible(false);
debug.visible(true);
// storage API
fggl::data::Storage storage;
......@@ -194,6 +197,8 @@ int main(int argc, char* argv[]) {
fggl::gfx::Input& input = fggl::gfx::Input::instance();
bool joystickWindow = true;
float time = 0.0f;
float dt = 16.0f;
while( !win.closeRequested() ) {
......@@ -210,6 +215,97 @@ int main(int argc, char* argv[]) {
process_arcball(win, ecs, input, camEnt);
}
// imgui joystick debug
ImGui::Begin("Joysticks", &joystickWindow);
for ( int i=0; i<16; i++ ) {
bool present = input.hasJoystick(i);
std::string title = "Joystick " + std::to_string(i);
if ( ImGui::TreeNode(title.c_str()) ) {
ImGui::Text("present: %s", present ? "yes" : "no" );
if ( present ) {
const fggl::gfx::Joystick& joyData = input.joystick(i);
ImGui::Text( "%s", joyData.name );
ImGui::Text( "gamepad: %s", joyData.gamepad ? "yes" : "no" );
ImGui::Text( "axes: %d, buttons: %d, hats: %d", joyData.axisCount, joyData.buttonCount, joyData.hatCount);
if (ImGui::TreeNode("axis##2")) {
// dump data
for ( int axid = 0; axid < joyData.axisCount; axid++ ) {
ImGui::Text("axis %d, value: %f", axid, joyData.axes[axid] );
}
ImGui::TreePop();
}
if (ImGui::TreeNode("buttons##2")) {
// dump data
for ( int btnid = 0; btnid < joyData.buttonCount; btnid++ ) {
ImGui::Text("button %d, value: %s", btnid, joyData.buttons[btnid] == GLFW_PRESS ? "down" : "up" );
}
ImGui::TreePop();
}
if (ImGui::TreeNode("hats##2")) {
// dump data
for ( int btnid = 0; btnid < joyData.hatCount; btnid++ ) {
ImGui::Text("button %d, value: %d", btnid, joyData.hats[btnid] );
}
ImGui::TreePop();
}
}
ImGui::TreePop();
ImGui::Separator();
}
}
ImGui::End();
// imgui gamepad debug
ImGui::Begin("GamePad", &joystickWindow);
for ( int i=0; i<16; i++ ) {
std::string title = "GamePad " + std::to_string(i);
bool present = input.hasJoystick(i);
if ( ImGui::TreeNode(title.c_str()) ) {
ImGui::Text("present: %s", present ? "yes" : "no" );
if ( present ) {
if ( ImGui::TreeNode("buttons##2") ) {
for ( auto& btn : fggl::gfx::PadButtons ) {
auto label = fggl::gfx::PadButtonLabels[ (int) btn ];
ImGui::Text( "%s: %i %i %i", label.c_str(),
input.padDown(i, btn),
input.padPressed(i, btn),
input.padReleased(i, btn)
);
}
ImGui::TreePop();
}
if ( ImGui::TreeNode("axes##2") ) {
for ( auto& axis : fggl::gfx::PadAxes ) {
auto label = fggl::gfx::PadAxisLabels[ (int) axis ];
ImGui::Text("%s: %f %f", label.c_str(),
input.padAxis(i, axis),
input.padAxisDelta(i, axis)
);
}
ImGui::TreePop();
}
}
ImGui::TreePop();
ImGui::Separator();
}
}
ImGui::End();
/* float amount = glm::radians( time / 2048.0f * 360.0f );
auto spinners = ecs.getEntityWith<fggl::math::Transform>();
for ( auto entity : spinners ) {
......
......@@ -6,23 +6,36 @@
using fggl::gfx::Input;
Input::Input() : m_mouse_curr(), m_mouse_last(), m_joydata(), m_joysticks() {
Input::Input() : m_mouse_curr(), m_mouse_last(), m_joydata(), m_joysticks(), m_pad_last(), m_pad_curr() {
clear();
}
void Input::clear() {
// reset mouse data
m_mouse_curr.cursor[0] = 0.0;
m_mouse_curr.cursor[1] = 0.0;
m_mouse_curr.scroll[0] = 0.0;
m_mouse_curr.scroll[1] = 0.0;
m_mouse_curr.buttons = 0x00;
m_mouse_last = m_mouse_curr;
// reset pad data
for ( auto& pad : m_pad_curr ) {
pad.present = false;
pad.buttons.reset();
for (int i=0; i<6; i++){
pad.axes[i] = 0.0f;
}
}
m_pad_last = m_pad_curr;
}
void Input::frame() {
m_mouse_last = m_mouse_curr;
m_mouse_curr.scroll[0] = 0.0;
m_mouse_curr.scroll[1] = 0.0;
m_pad_last = m_pad_curr;
}
void Input::mousePos(double x, double y) {
......@@ -81,7 +94,7 @@ bool Input::mouseReleased(const MouseButton btn) const {
}
void Input::joystickConnect(int id, Joystick &data){
std::cout << "JOYSTICK TIME: " << data.name << std::endl;
// joystick data is polled, so we need to call this every frame >.<
m_joysticks[id] = true;
m_joydata[id] = data;
}
......@@ -92,6 +105,34 @@ void Input::joystickDisconnect( int id ){
m_joydata[id] = Joystick();
}
bool Input::joystick(int id) const {
bool Input::hasJoystick(int id) const {
return m_joysticks[id];
}
const fggl::gfx::Joystick& Input::joystick(int id) const {
return m_joydata[id];
}
void Input::padState(int id, const PadState& state) {
m_pad_curr[id] = state;
}
bool Input::padDown(int id, PadButton btn) {
return m_pad_curr[id].buttons[(int)btn];
}
bool Input::padPressed(int id, PadButton btn) {
return m_pad_curr[id].buttons[(int)btn] && !m_pad_last[id].buttons[(int)btn];
}
bool Input::padReleased(int id, PadButton btn) {
return !m_pad_curr[id].buttons[(int)btn] && m_pad_last[id].buttons[(int)btn];
}
float Input::padAxis(int id, PadAxis axis) {
return m_pad_curr[id].axes[(int)axis];
}
float Input::padAxisDelta(int id, PadAxis axis) {
return m_pad_last[id].axes[(int)axis] - m_pad_curr[id].axes[(int)axis];
}
......@@ -23,6 +23,89 @@ namespace fggl::gfx {
char buttons;
};
enum class PadButton {
A,
B,
X,
Y,
BUMPER_LEFT,
BUMPER_RIGHT,
BACK,
START,
GUIDE,
THUMB_LEFT,
THUMB_RIGHT,
DPAD_UP,
DPAD_RIGHT,
DPAD_DOWN,
DPAD_LEFT
};
constexpr std::array<PadButton, 15> PadButtons = {
PadButton::A,
PadButton::B,
PadButton::X,
PadButton::Y,
PadButton::BUMPER_LEFT,
PadButton::BUMPER_RIGHT,
PadButton::BACK,
PadButton::START,
PadButton::GUIDE,
PadButton::THUMB_LEFT,
PadButton::THUMB_RIGHT,
PadButton::DPAD_UP,
PadButton::DPAD_RIGHT,
PadButton::DPAD_DOWN,
PadButton::DPAD_LEFT
};
const std::array<const std::string, 15> PadButtonLabels = {
"A",
"B",
"X",
"Y",
"Left Bumper",
"Right Bumper",
"Back",
"Start",
"Guide",
"Left Thumb",
"Right Thumb",
"DPad Up",
"DPad Right",
"DPad Down",
"DPad left"
};
enum class PadAxis {
LEFT_X,
LEFT_Y,
RIGHT_X,
RIGHT_Y,
TRIGGER_LEFT,
TRIGGER_RIGHT
};
constexpr std::array<PadAxis,6> PadAxes = {
PadAxis::LEFT_X,
PadAxis::LEFT_Y,
PadAxis::RIGHT_X,
PadAxis::RIGHT_Y,
PadAxis::TRIGGER_LEFT,
PadAxis::TRIGGER_RIGHT
};
const std::array<const std::string, 15> PadAxisLabels = {
"Left (x)",
"Left (y)",
"Right (x)",
"Right (y)",
"Left Trigger",
"Right Trigger"
};
struct PadState {
std::bitset<PadButtons.size()> buttons;
float axes[PadAxes.size()];
bool present;
};
struct Joystick {
const char* name = nullptr;
const float* axes = nullptr;
......@@ -31,6 +114,7 @@ namespace fggl::gfx {
int hatCount = 0;
int axisCount = 0;
int buttonCount = 0;
bool gamepad = false;
};
class Input {
......@@ -84,7 +168,18 @@ namespace fggl::gfx {
void joystickConnect(int id, Joystick& data);
void joystickDisconnect(int id);
bool joystick(int id) const;
bool hasJoystick(int id) const;
const Joystick& joystick(int id) const;
// gamepads
void padState(int id, const PadState& state);
bool padDown(int id, PadButton btn);
bool padPressed(int id, PadButton btn);
bool padReleased(int id, PadButton btn);
float padAxis(int id, PadAxis axis);
float padAxisDelta(int id, PadAxis axis);
private:
Input();
......@@ -92,6 +187,8 @@ namespace fggl::gfx {
MouseInputState m_mouse_last;
std::bitset<16> m_joysticks;
std::array<Joystick, 16> m_joydata;
std::array<PadState, 16> m_pad_curr;
std::array<PadState, 16> m_pad_last;
};
};
......
......@@ -38,16 +38,54 @@ static void fggl_input_mouse_btn(GLFWwindow* window, int btn, int action, int mo
input.mouseBtn( buttonBit, action == GLFW_PRESS );
}
static void fggl_activate_joystick(Input& input, int jid) {
fggl::gfx::Joystick data;
data.name = glfwGetJoystickName(jid);
data.axes = glfwGetJoystickAxes(jid, &data.axisCount);
data.buttons = glfwGetJoystickButtons(jid, &data.buttonCount);
data.hats = glfwGetJoystickHats(jid, &data.hatCount);
data.gamepad = glfwJoystickIsGamepad(jid);
input.joystickConnect(jid, data);
if ( data.gamepad ) {
GLFWgamepadstate state;
glfwGetGamepadState(jid, &state);
fggl::gfx::PadState padState;
for (int i=0; i<=GLFW_GAMEPAD_BUTTON_LAST; i++) {
padState.buttons[i] = state.buttons[i];
}
for (int i=0; i<=GLFW_GAMEPAD_AXIS_LAST; i++) {
padState.axes[i] = state.axes[i];
}
input.padState(jid, padState);
}
}
static void fggl_joystick_init() {
Input& input = Input::instance();
for (int jid=0; jid<16; jid++) {
if ( glfwJoystickPresent(jid) ) {
fggl_activate_joystick(input, jid);
}
}
}
static void fggl_joystick_poll() {
Input& input = Input::instance();
for (int jid=0; jid<16; jid++) {
if ( glfwJoystickPresent(jid) ) {
fggl_activate_joystick(input, jid);
}
}
}
static void fggl_joystick(int jid, int state) {
Input& input = Input::instance();
if ( state == GLFW_CONNECTED ) {
fggl::gfx::Joystick data;
data.name = glfwGetJoystickName(jid);
data.axes = glfwGetJoystickAxes(jid, &data.axisCount);
data.buttons = glfwGetJoystickButtons(jid, &data.buttonCount);
data.hats = glfwGetJoystickHats(jid, &data.hatCount);
input.joystickConnect(jid, data);
fggl_activate_joystick(input, jid);
} else if ( state == GLFW_DISCONNECTED ) {
input.joystickDisconnect(jid);
}
......@@ -62,6 +100,10 @@ Context::Context() {
int code = glfwGetError(error);
throw std::runtime_error( *error );
}
// joysticks are global
fggl_joystick_init();
glfwSetJoystickCallback(fggl_joystick);
}
Context::~Context() {
......@@ -70,6 +112,7 @@ Context::~Context() {
void Context::pollEvents() {
glfwPollEvents();
fggl_joystick_poll();
}
Window::Window(Input& input) : m_window(nullptr), m_input(input) {
......@@ -91,7 +134,6 @@ Window::Window(Input& input) : m_window(nullptr), m_input(input) {
glfwSetScrollCallback(m_window, fggl_input_scroll);
glfwSetCursorPosCallback(m_window, fggl_input_cursor);
glfwSetMouseButtonCallback(m_window, fggl_input_mouse_btn);
glfwSetJoystickCallback(fggl_joystick);
}
Window::~Window() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment