You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
		
		
		
		
		
			
		
			
				
					
					
						
							345 lines
						
					
					
						
							11 KiB
						
					
					
				
			
		
		
	
	
							345 lines
						
					
					
						
							11 KiB
						
					
					
				//======================================================================== | 
						|
// Joystick input test | 
						|
// Copyright (c) Camilla Löwy <elmindreda@glfw.org> | 
						|
// | 
						|
// This software is provided 'as-is', without any express or implied | 
						|
// warranty. In no event will the authors be held liable for any damages | 
						|
// arising from the use of this software. | 
						|
// | 
						|
// Permission is granted to anyone to use this software for any purpose, | 
						|
// including commercial applications, and to alter it and redistribute it | 
						|
// freely, subject to the following restrictions: | 
						|
// | 
						|
// 1. The origin of this software must not be misrepresented; you must not | 
						|
//    claim that you wrote the original software. If you use this software | 
						|
//    in a product, an acknowledgment in the product documentation would | 
						|
//    be appreciated but is not required. | 
						|
// | 
						|
// 2. Altered source versions must be plainly marked as such, and must not | 
						|
//    be misrepresented as being the original software. | 
						|
// | 
						|
// 3. This notice may not be removed or altered from any source | 
						|
//    distribution. | 
						|
// | 
						|
//======================================================================== | 
						|
// | 
						|
// This test displays the state of every button and axis of every connected | 
						|
// joystick and/or gamepad | 
						|
// | 
						|
//======================================================================== | 
						|
 | 
						|
#include <glad/gl.h> | 
						|
#define GLFW_INCLUDE_NONE | 
						|
#include <GLFW/glfw3.h> | 
						|
 | 
						|
#define NK_IMPLEMENTATION | 
						|
#define NK_INCLUDE_FIXED_TYPES | 
						|
#define NK_INCLUDE_FONT_BAKING | 
						|
#define NK_INCLUDE_DEFAULT_FONT | 
						|
#define NK_INCLUDE_DEFAULT_ALLOCATOR | 
						|
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT | 
						|
#define NK_INCLUDE_STANDARD_VARARGS | 
						|
#define NK_BUTTON_TRIGGER_ON_RELEASE | 
						|
#include <nuklear.h> | 
						|
 | 
						|
#define NK_GLFW_GL2_IMPLEMENTATION | 
						|
#include <nuklear_glfw_gl2.h> | 
						|
 | 
						|
#include <stdio.h> | 
						|
#include <string.h> | 
						|
#include <stdlib.h> | 
						|
 | 
						|
#ifdef _MSC_VER | 
						|
#define strdup(x) _strdup(x) | 
						|
#endif | 
						|
 | 
						|
static GLFWwindow* window; | 
						|
static int joysticks[GLFW_JOYSTICK_LAST + 1]; | 
						|
static int joystick_count = 0; | 
						|
 | 
						|
static void error_callback(int error, const char* description) | 
						|
{ | 
						|
    fprintf(stderr, "Error: %s\n", description); | 
						|
} | 
						|
 | 
						|
static void joystick_callback(int jid, int event) | 
						|
{ | 
						|
    if (event == GLFW_CONNECTED) | 
						|
        joysticks[joystick_count++] = jid; | 
						|
    else if (event == GLFW_DISCONNECTED) | 
						|
    { | 
						|
        int i; | 
						|
 | 
						|
        for (i = 0;  i < joystick_count;  i++) | 
						|
        { | 
						|
            if (joysticks[i] == jid) | 
						|
                break; | 
						|
        } | 
						|
 | 
						|
        for (i = i + 1;  i < joystick_count;  i++) | 
						|
            joysticks[i - 1] = joysticks[i]; | 
						|
 | 
						|
        joystick_count--; | 
						|
    } | 
						|
 | 
						|
    if (!glfwGetWindowAttrib(window, GLFW_FOCUSED)) | 
						|
        glfwRequestWindowAttention(window); | 
						|
} | 
						|
 | 
						|
static void drop_callback(GLFWwindow* window, int count, const char* paths[]) | 
						|
{ | 
						|
    int i; | 
						|
 | 
						|
    for (i = 0;  i < count;  i++) | 
						|
    { | 
						|
        long size; | 
						|
        char* text; | 
						|
        FILE* stream = fopen(paths[i], "rb"); | 
						|
        if (!stream) | 
						|
            continue; | 
						|
 | 
						|
        fseek(stream, 0, SEEK_END); | 
						|
        size = ftell(stream); | 
						|
        fseek(stream, 0, SEEK_SET); | 
						|
 | 
						|
        text = malloc(size + 1); | 
						|
        text[size] = '\0'; | 
						|
        if (fread(text, 1, size, stream) == size) | 
						|
            glfwUpdateGamepadMappings(text); | 
						|
 | 
						|
        free(text); | 
						|
        fclose(stream); | 
						|
    } | 
						|
} | 
						|
 | 
						|
static const char* joystick_label(int jid) | 
						|
{ | 
						|
    static char label[1024]; | 
						|
    snprintf(label, sizeof(label), "%i: %s", jid + 1, glfwGetJoystickName(jid)); | 
						|
    return label; | 
						|
} | 
						|
 | 
						|
static void hat_widget(struct nk_context* nk, unsigned char state) | 
						|
{ | 
						|
    float radius; | 
						|
    struct nk_rect area; | 
						|
    struct nk_vec2 center; | 
						|
 | 
						|
    if (nk_widget(&area, nk) == NK_WIDGET_INVALID) | 
						|
        return; | 
						|
 | 
						|
    center = nk_vec2(area.x + area.w / 2.f, area.y + area.h / 2.f); | 
						|
    radius = NK_MIN(area.w, area.h) / 2.f; | 
						|
 | 
						|
    nk_stroke_circle(nk_window_get_canvas(nk), | 
						|
                     nk_rect(center.x - radius, | 
						|
                             center.y - radius, | 
						|
                             radius * 2.f, | 
						|
                             radius * 2.f), | 
						|
                     1.f, | 
						|
                     nk_rgb(175, 175, 175)); | 
						|
 | 
						|
    if (state) | 
						|
    { | 
						|
        const float angles[] = | 
						|
        { | 
						|
            0.f,           0.f, | 
						|
            NK_PI * 1.5f,  NK_PI * 1.75f, | 
						|
            NK_PI,         0.f, | 
						|
            NK_PI * 1.25f, 0.f, | 
						|
            NK_PI * 0.5f,  NK_PI * 0.25f, | 
						|
            0.f,           0.f, | 
						|
            NK_PI * 0.75f, 0.f, | 
						|
        }; | 
						|
        const float cosa = nk_cos(angles[state]); | 
						|
        const float sina = nk_sin(angles[state]); | 
						|
        const struct nk_vec2 p0 = nk_vec2(0.f, -radius); | 
						|
        const struct nk_vec2 p1 = nk_vec2( radius / 2.f, -radius / 3.f); | 
						|
        const struct nk_vec2 p2 = nk_vec2(-radius / 2.f, -radius / 3.f); | 
						|
 | 
						|
        nk_fill_triangle(nk_window_get_canvas(nk), | 
						|
                         center.x + cosa * p0.x + sina * p0.y, | 
						|
                         center.y + cosa * p0.y - sina * p0.x, | 
						|
                         center.x + cosa * p1.x + sina * p1.y, | 
						|
                         center.y + cosa * p1.y - sina * p1.x, | 
						|
                         center.x + cosa * p2.x + sina * p2.y, | 
						|
                         center.y + cosa * p2.y - sina * p2.x, | 
						|
                         nk_rgb(175, 175, 175)); | 
						|
    } | 
						|
} | 
						|
 | 
						|
int main(void) | 
						|
{ | 
						|
    int jid, hat_buttons = GLFW_FALSE; | 
						|
    struct nk_context* nk; | 
						|
    struct nk_font_atlas* atlas; | 
						|
 | 
						|
    memset(joysticks, 0, sizeof(joysticks)); | 
						|
 | 
						|
    glfwSetErrorCallback(error_callback); | 
						|
 | 
						|
    if (!glfwInit()) | 
						|
        exit(EXIT_FAILURE); | 
						|
 | 
						|
    glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); | 
						|
    glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE); | 
						|
 | 
						|
    window = glfwCreateWindow(800, 600, "Joystick Test", NULL, NULL); | 
						|
    if (!window) | 
						|
    { | 
						|
        glfwTerminate(); | 
						|
        exit(EXIT_FAILURE); | 
						|
    } | 
						|
 | 
						|
    glfwMakeContextCurrent(window); | 
						|
    gladLoadGL(glfwGetProcAddress); | 
						|
    glfwSwapInterval(1); | 
						|
 | 
						|
    nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS); | 
						|
    nk_glfw3_font_stash_begin(&atlas); | 
						|
    nk_glfw3_font_stash_end(); | 
						|
 | 
						|
    for (jid = GLFW_JOYSTICK_1;  jid <= GLFW_JOYSTICK_LAST;  jid++) | 
						|
    { | 
						|
        if (glfwJoystickPresent(jid)) | 
						|
            joysticks[joystick_count++] = jid; | 
						|
    } | 
						|
 | 
						|
    glfwSetJoystickCallback(joystick_callback); | 
						|
    glfwSetDropCallback(window, drop_callback); | 
						|
 | 
						|
    while (!glfwWindowShouldClose(window)) | 
						|
    { | 
						|
        int i, width, height; | 
						|
 | 
						|
        glfwGetWindowSize(window, &width, &height); | 
						|
 | 
						|
        glClear(GL_COLOR_BUFFER_BIT); | 
						|
        nk_glfw3_new_frame(); | 
						|
 | 
						|
        if (nk_begin(nk, | 
						|
                     "Joysticks", | 
						|
                     nk_rect(width - 200.f, 0.f, 200.f, (float) height), | 
						|
                     NK_WINDOW_MINIMIZABLE | | 
						|
                     NK_WINDOW_TITLE)) | 
						|
        { | 
						|
            nk_layout_row_dynamic(nk, 30, 1); | 
						|
 | 
						|
            nk_checkbox_label(nk, "Hat buttons", &hat_buttons); | 
						|
 | 
						|
            if (joystick_count) | 
						|
            { | 
						|
                for (i = 0;  i < joystick_count;  i++) | 
						|
                { | 
						|
                    if (nk_button_label(nk, joystick_label(joysticks[i]))) | 
						|
                        nk_window_set_focus(nk, joystick_label(joysticks[i])); | 
						|
                } | 
						|
            } | 
						|
            else | 
						|
                nk_label(nk, "No joysticks connected", NK_TEXT_LEFT); | 
						|
        } | 
						|
 | 
						|
        nk_end(nk); | 
						|
 | 
						|
        for (i = 0;  i < joystick_count;  i++) | 
						|
        { | 
						|
            if (nk_begin(nk, | 
						|
                         joystick_label(joysticks[i]), | 
						|
                         nk_rect(i * 20.f, i * 20.f, 550.f, 570.f), | 
						|
                         NK_WINDOW_BORDER | | 
						|
                         NK_WINDOW_MOVABLE | | 
						|
                         NK_WINDOW_SCALABLE | | 
						|
                         NK_WINDOW_MINIMIZABLE | | 
						|
                         NK_WINDOW_TITLE)) | 
						|
            { | 
						|
                int j, axis_count, button_count, hat_count; | 
						|
                const float* axes; | 
						|
                const unsigned char* buttons; | 
						|
                const unsigned char* hats; | 
						|
                GLFWgamepadstate state; | 
						|
 | 
						|
                nk_layout_row_dynamic(nk, 30, 1); | 
						|
                nk_labelf(nk, NK_TEXT_LEFT, "Hardware GUID %s", | 
						|
                          glfwGetJoystickGUID(joysticks[i])); | 
						|
                nk_label(nk, "Joystick state", NK_TEXT_LEFT); | 
						|
 | 
						|
                axes = glfwGetJoystickAxes(joysticks[i], &axis_count); | 
						|
                buttons = glfwGetJoystickButtons(joysticks[i], &button_count); | 
						|
                hats = glfwGetJoystickHats(joysticks[i], &hat_count); | 
						|
 | 
						|
                if (!hat_buttons) | 
						|
                    button_count -= hat_count * 4; | 
						|
 | 
						|
                for (j = 0;  j < axis_count;  j++) | 
						|
                    nk_slide_float(nk, -1.f, axes[j], 1.f, 0.1f); | 
						|
 | 
						|
                nk_layout_row_dynamic(nk, 30, 12); | 
						|
 | 
						|
                for (j = 0;  j < button_count;  j++) | 
						|
                { | 
						|
                    char name[16]; | 
						|
                    snprintf(name, sizeof(name), "%i", j + 1); | 
						|
                    nk_select_label(nk, name, NK_TEXT_CENTERED, buttons[j]); | 
						|
                } | 
						|
 | 
						|
                nk_layout_row_dynamic(nk, 30, 8); | 
						|
 | 
						|
                for (j = 0;  j < hat_count;  j++) | 
						|
                    hat_widget(nk, hats[j]); | 
						|
 | 
						|
                nk_layout_row_dynamic(nk, 30, 1); | 
						|
 | 
						|
                if (glfwGetGamepadState(joysticks[i], &state)) | 
						|
                { | 
						|
                    int hat = 0; | 
						|
                    const char* names[GLFW_GAMEPAD_BUTTON_LAST + 1 - 4] = | 
						|
                    { | 
						|
                        "A", "B", "X", "Y", | 
						|
                        "LB", "RB", | 
						|
                        "Back", "Start", "Guide", | 
						|
                        "LT", "RT", | 
						|
                    }; | 
						|
 | 
						|
                    nk_labelf(nk, NK_TEXT_LEFT, | 
						|
                              "Gamepad state: %s", | 
						|
                              glfwGetGamepadName(joysticks[i])); | 
						|
 | 
						|
                    nk_layout_row_dynamic(nk, 30, 2); | 
						|
 | 
						|
                    for (j = 0;  j <= GLFW_GAMEPAD_AXIS_LAST;  j++) | 
						|
                        nk_slide_float(nk, -1.f, state.axes[j], 1.f, 0.1f); | 
						|
 | 
						|
                    nk_layout_row_dynamic(nk, 30, GLFW_GAMEPAD_BUTTON_LAST + 1 - 4); | 
						|
 | 
						|
                    for (j = 0;  j <= GLFW_GAMEPAD_BUTTON_LAST - 4;  j++) | 
						|
                        nk_select_label(nk, names[j], NK_TEXT_CENTERED, state.buttons[j]); | 
						|
 | 
						|
                    if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_UP]) | 
						|
                        hat |= GLFW_HAT_UP; | 
						|
                    if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_RIGHT]) | 
						|
                        hat |= GLFW_HAT_RIGHT; | 
						|
                    if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_DOWN]) | 
						|
                        hat |= GLFW_HAT_DOWN; | 
						|
                    if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_LEFT]) | 
						|
                        hat |= GLFW_HAT_LEFT; | 
						|
 | 
						|
                    nk_layout_row_dynamic(nk, 30, 8); | 
						|
                    hat_widget(nk, hat); | 
						|
                } | 
						|
                else | 
						|
                    nk_label(nk, "Joystick has no gamepad mapping", NK_TEXT_LEFT); | 
						|
            } | 
						|
 | 
						|
            nk_end(nk); | 
						|
        } | 
						|
 | 
						|
        nk_glfw3_render(NK_ANTI_ALIASING_ON); | 
						|
 | 
						|
        glfwSwapBuffers(window); | 
						|
        glfwPollEvents(); | 
						|
    } | 
						|
 | 
						|
    glfwTerminate(); | 
						|
    exit(EXIT_SUCCESS); | 
						|
} | 
						|
 | 
						|
 |