diff --git a/.github/workflows/linux_vulkan.yml b/.github/workflows/linux_vulkan.yml index d397bb71..cfbecaae 100644 --- a/.github/workflows/linux_vulkan.yml +++ b/.github/workflows/linux_vulkan.yml @@ -18,7 +18,7 @@ jobs: - name: Apt Update run: sudo apt-get update - name: Apt Install - run: sudo apt install make clang libvulkan-dev libgtk-3-dev libudev-dev libasound2-dev --yes --quiet + run: sudo apt install make clang libvulkan-dev libgtk-3-dev --yes --quiet - name: Compile run: | cd armorpaint diff --git a/base/project.js b/base/project.js index d75f5e47..ea8c1a13 100644 --- a/base/project.js +++ b/base/project.js @@ -251,10 +251,14 @@ if (!flags.lite) { project.add_define("IRON_VULKAN"); project.add_define("_POSIX_C_SOURCE=200112L"); project.add_define("_XOPEN_SOURCE=600"); - project.add_lib("asound"); project.add_lib("dl"); - project.add_lib("udev"); project.add_lib("vulkan"); + if (flags.with_audio) { + project.add_lib("asound"); + } + if (flags.with_gamepad) { + project.add_lib("udev"); + } } } @@ -290,6 +294,10 @@ if (flags.with_eval) { project.add_cfiles("tools/amake/alang_eval.c"); } +if (flags.with_gamepad) { + project.add_define("WITH_GAMEPAD"); +} + if (flags.with_iron) { project.add_define("WITH_IRON"); project.add_cfiles("sources/*.c"); diff --git a/base/sources/backends/android_system.c b/base/sources/backends/android_system.c index 13e4f3e5..2c0bff68 100644 --- a/base/sources/backends/android_system.c +++ b/base/sources/backends/android_system.c @@ -162,12 +162,16 @@ static void updateAppForegroundStatus(bool displayIsInitializedValue, bool appIs } } +#ifdef WITH_GAMEPAD + static bool isGamepadEvent(AInputEvent *event) { return ((AInputEvent_getSource(event) & AINPUT_SOURCE_GAMEPAD) == AINPUT_SOURCE_GAMEPAD || (AInputEvent_getSource(event) & AINPUT_SOURCE_JOYSTICK) == AINPUT_SOURCE_JOYSTICK || (AInputEvent_getSource(event) & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD); } +#endif + static bool isPenEvent(AInputEvent *event) { return (AInputEvent_getSource(event) & AINPUT_SOURCE_STYLUS) == AINPUT_SOURCE_STYLUS; } @@ -1188,13 +1192,19 @@ void iron_init(const char *name, int width, int height, struct iron_window_optio gpu_init(win->depth_bits, true); + #ifdef WITH_GAMEPAD iron_internal_gamepad_trigger_connect(0); + #endif } void iron_internal_shutdown(void) { + #ifdef WITH_GAMEPAD iron_internal_gamepad_trigger_disconnect(0); + #endif } +#ifdef WITH_GAMEPAD + const char *iron_gamepad_vendor(int gamepad) { return "Google"; } @@ -1203,6 +1213,8 @@ const char *iron_gamepad_product_name(int gamepad) { return "gamepad"; } +#endif + void initAndroidFileReader(void) { if (activity == NULL) { iron_error("Android activity is NULL"); @@ -1297,19 +1309,12 @@ int iron_window_height() { } void iron_window_resize(int width, int height) {} - void iron_window_move(int x, int y) {} - void iron_window_change_mode(iron_window_mode_t mode) {} - void iron_window_destroy() {} - void iron_window_show() {} - void iron_window_hide() {} - void iron_window_set_title(const char *title) {} - void iron_window_create(iron_window_options_t *win) {} void iron_window_set_resize_callback(void (*callback)(int x, int y, void *data), void *data) { diff --git a/base/sources/backends/ios_system.m b/base/sources/backends/ios_system.m index 03bc25c2..fa7c43c4 100644 --- a/base/sources/backends/ios_system.m +++ b/base/sources/backends/ios_system.m @@ -645,6 +645,8 @@ uint64_t iron_timestamp(void) { return time; } +#ifdef WITH_GAMEPAD + const char *iron_gamepad_vendor(int gamepad) { return "nobody"; } @@ -659,6 +661,8 @@ bool iron_gamepad_connected(int num) { void iron_gamepad_rumble(int gamepad, float left, float right) {} +#endif + int main(int argc, char *argv[]) { int retVal = 0; @autoreleasepool { diff --git a/base/sources/backends/linux_system.c b/base/sources/backends/linux_system.c index 76ee2fd5..f33462b8 100644 --- a/base/sources/backends/linux_system.c +++ b/base/sources/backends/linux_system.c @@ -2,7 +2,6 @@ #include #include #include - #include #include #include @@ -14,13 +13,12 @@ #include #include #include -#include -#include #include +#include +#include #include #include #include -#include #define Button6 6 #define Button7 7 @@ -1156,7 +1154,9 @@ bool iron_internal_handle_messages() { if (!_handle_messages()) { return false; } + #ifdef WITH_GAMEPAD iron_linux_updateHIDGamepads(); + #endif return true; } @@ -1252,7 +1252,11 @@ uint64_t iron_timestamp(void) { void iron_init(const char *name, int width, int height, iron_window_options_t *win) { gettimeofday(&start, NULL); + + #ifdef WITH_GAMEPAD iron_linux_initHIDGamepads(); + #endif + iron_x11_init(); iron_display_init(); iron_set_app_name(name); @@ -1273,7 +1277,11 @@ void iron_init(const char *name, int width, int height, iron_window_options_t *w void iron_internal_shutdown() { gpu_destroy(); + + #ifdef WITH_GAMEPAD iron_linux_closeHIDGamepads(); + #endif + free(clipboardString); xlib.XCloseDisplay(x11_ctx.display); iron_internal_shutdown_callback(); @@ -1579,6 +1587,12 @@ void iron_mouse_get_position(int *x, int *y) { xlib.XQueryPointer(x11_ctx.display, window->window, &inwin, &inchildwin, &rootx, &rooty, x, y, &mask); } +#ifdef WITH_GAMEPAD + +#include +#include +#include + struct HIDGamepad { int idx; char gamepad_dev_name[256]; @@ -1766,3 +1780,5 @@ bool iron_gamepad_connected(int gamepad) { } void iron_gamepad_rumble(int gamepad, float left, float right) {} + +#endif diff --git a/base/sources/backends/linux_system.h b/base/sources/backends/linux_system.h index 18f7a1ff..8dee02e9 100644 --- a/base/sources/backends/linux_system.h +++ b/base/sources/backends/linux_system.h @@ -172,6 +172,8 @@ struct x11_context x11_ctx; void iron_copy_to_clipboard(const char *text); +#ifdef WITH_GAMEPAD void iron_linux_initHIDGamepads(); void iron_linux_updateHIDGamepads(); void iron_linux_closeHIDGamepads(); +#endif diff --git a/base/sources/backends/macos_system.h b/base/sources/backends/macos_system.h index b84d31d8..841f9c51 100644 --- a/base/sources/backends/macos_system.h +++ b/base/sources/backends/macos_system.h @@ -4,9 +4,6 @@ #include #include #include -#include -#include -#include @interface BasicMTKView : MTKView { @private @@ -39,6 +36,8 @@ @end +#ifdef WITH_GAMEPAD + struct HIDGamepad { int padIndex; IOHIDDeviceRef hidDeviceRef; @@ -57,7 +56,7 @@ void HIDGamepad_destroy(struct HIDGamepad *gamepad); void HIDGamepad_bind(struct HIDGamepad *gamepad, IOHIDDeviceRef deviceRef, int padIndex); void HIDGamepad_unbind(struct HIDGamepad *gamepad); -static const int IRON_MAX_HID_DEVICES = 12; +static const int IRON_MAX_HID_DEVICES = 8; // Slots to hold details on connected devices struct HIDManagerDeviceRecord { @@ -73,3 +72,5 @@ struct HIDManager { void HIDManager_init(struct HIDManager *manager); void HIDManager_destroy(struct HIDManager *manager); + +#endif diff --git a/base/sources/backends/macos_system.m b/base/sources/backends/macos_system.m index 0495cc1d..e388ce70 100644 --- a/base/sources/backends/macos_system.m +++ b/base/sources/backends/macos_system.m @@ -428,6 +428,8 @@ void iron_copy_to_clipboard(const char *text) { [board setString:[NSString stringWithUTF8String:text] forType:NSStringPboardType]; } +#ifdef WITH_GAMEPAD + static void inputValueCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDValueRef inIOHIDValueRef); static void valueAvailableCallback(void *inContext, IOReturn inResult, void *inSender); static void reset(struct HIDGamepad *gamepad); @@ -726,6 +728,8 @@ void deviceRemoved(void *inContext, IOReturn inResult, void *inSender, IOHIDDevi } } +#endif + int iron_count_displays(void) { NSArray *screens = [NSScreen screens]; return (int)[screens count]; @@ -841,12 +845,16 @@ uint64_t iron_timestamp(void) { return mach_absolute_time(); } +#ifdef WITH_GAMEPAD + bool iron_gamepad_connected(int num) { return true; } void iron_gamepad_rumble(int gamepad, float left, float right) {} +#endif + bool withAutoreleasepool(bool (*f)(void)) { @autoreleasepool { return f(); diff --git a/base/sources/backends/windows_system.c b/base/sources/backends/windows_system.c index ed0a2350..a64bcd91 100644 --- a/base/sources/backends/windows_system.c +++ b/base/sources/backends/windows_system.c @@ -560,8 +560,13 @@ static void initKeyTranslation() { keyTranslated[VK_OEM_7] = IRON_KEY_QUOTE; } +#ifdef WITH_GAMEPAD + static bool detectGamepad = true; static bool gamepadFound = false; + +#endif + static unsigned r = 0; static wchar_t toUnicode(WPARAM wParam, LPARAM lParam) { @@ -952,7 +957,9 @@ LRESULT WINAPI IronWindowsMessageProcedure(HWND hWnd, UINT msg, WPARAM wParam, L } break; case WM_DEVICECHANGE: + #ifdef WITH_GAMEPAD detectGamepad = true; + #endif break; case WM_DROPFILES: { HDROP hDrop = (HDROP)wParam; @@ -970,6 +977,8 @@ LRESULT WINAPI IronWindowsMessageProcedure(HWND hWnd, UINT msg, WPARAM wParam, L return DefWindowProcW(hWnd, msg, wParam, lParam); } +#ifdef WITH_GAMEPAD + static float axes[12 * 6]; static float buttons[12 * 16]; @@ -1434,6 +1443,8 @@ bool iron_internal_handle_messages() { return true; } +#endif + static bool keyboardshown = false; static char language[3] = {0}; @@ -1534,6 +1545,8 @@ const char **iron_video_formats() { return videoFormats; } +#ifdef WITH_GAMEPAD + bool iron_gamepad_connected(int num) { return isXInputGamepad(num) || isDirectInputGamepad(num); } @@ -1548,6 +1561,8 @@ void iron_gamepad_rumble(int gamepad, float left, float right) { } } +#endif + double iron_frequency() { return (double)frequency.QuadPart; } diff --git a/base/sources/iron.h b/base/sources/iron.h index 60c84310..9bd2494a 100644 --- a/base/sources/iron.h +++ b/base/sources/iron.h @@ -240,8 +240,10 @@ void (*iron_touch_move)(int, int, int); void (*iron_pen_down)(int, int, float); void (*iron_pen_up)(int, int, float); void (*iron_pen_move)(int, int, float); +#ifdef WITH_GAMEPAD void (*iron_gamepad_axis)(int, int, float); void (*iron_gamepad_button)(int, int, float); +#endif void (*iron_save_and_quit)(bool); char *_substring(char *s, int32_t start, int32_t end) { @@ -665,6 +667,8 @@ void _pen_move(int x, int y, float pressure) { #endif } +#ifdef WITH_GAMEPAD + void _gamepad_axis(int gamepad, int axis, float value, void *data) { iron_gamepad_axis(gamepad, axis, value); @@ -681,6 +685,8 @@ void _gamepad_button(int gamepad, int button, float value, void *data) { #endif } +#endif + void _drop_files(wchar_t *file_path, void *data) { // Update mouse position #ifdef IRON_WINDOWS @@ -933,6 +939,8 @@ void iron_set_pen_move_callback(void (*callback)(int, int, float)) { iron_pen_set_move_callback(_pen_move); } +#ifdef WITH_GAMEPAD + void iron_set_gamepad_axis_callback(void (*callback)(int, int, float)) { iron_gamepad_axis = callback; iron_gamepad_set_axis_callback(_gamepad_axis, NULL); @@ -943,6 +951,8 @@ void iron_set_gamepad_button_callback(void (*callback)(int, int, float)) { iron_gamepad_set_button_callback(_gamepad_button, NULL); } +#endif + void gpu_delete_buffer(gpu_buffer_t *buffer) { buffers_to_destroy[buffers_to_destroy_count] = buffer; buffers_to_destroy_count++; diff --git a/base/sources/iron_system.c b/base/sources/iron_system.c index 6e332c4d..8e18279a 100644 --- a/base/sources/iron_system.c +++ b/base/sources/iron_system.c @@ -589,6 +589,8 @@ void iron_internal_surface_trigger_touch_end(int index, int x, int y) { } } +#ifdef WITH_GAMEPAD + static void (*gamepad_connect_callback)(int /*gamepad*/, void * /*userdata*/) = NULL; static void *gamepad_connect_callback_userdata = NULL; static void (*gamepad_disconnect_callback)(int /*gamepad*/, void * /*userdata*/) = NULL; @@ -641,3 +643,5 @@ void iron_internal_gamepad_trigger_button(int gamepad, int button, float value) gamepad_button_callback(gamepad, button, value, gamepad_button_callback_userdata); } } + +#endif diff --git a/base/sources/iron_system.h b/base/sources/iron_system.h index 961340f0..ead04341 100644 --- a/base/sources/iron_system.h +++ b/base/sources/iron_system.h @@ -370,8 +370,9 @@ void iron_internal_surface_trigger_touch_start(int index, int x, int y); void iron_internal_surface_trigger_move(int index, int x, int y); void iron_internal_surface_trigger_touch_end(int index, int x, int y); -#define IRON_GAMEPAD_MAX_COUNT 12 +#ifdef WITH_GAMEPAD +#define IRON_GAMEPAD_MAX_COUNT 8 void iron_gamepad_set_connect_callback(void (*value)(int /*gamepad*/, void * /*userdata*/), void *userdata); void iron_gamepad_set_disconnect_callback(void (*value)(int /*gamepad*/, void * /*userdata*/), void *userdata); void iron_gamepad_set_axis_callback(void (*value)(int /*gamepad*/, int /*axis*/, float /*value*/, void * /*userdata*/), void *userdata); @@ -380,8 +381,9 @@ const char *iron_gamepad_vendor(int gamepad); const char *iron_gamepad_product_name(int gamepad); bool iron_gamepad_connected(int gamepad); void iron_gamepad_rumble(int gamepad, float left, float right); - void iron_internal_gamepad_trigger_connect(int gamepad); void iron_internal_gamepad_trigger_disconnect(int gamepad); void iron_internal_gamepad_trigger_axis(int gamepad, int axis, float value); void iron_internal_gamepad_trigger_button(int gamepad, int button, float value); + +#endif diff --git a/base/sources/ts/iron/input.ts b/base/sources/ts/iron/input.ts index 9be34ea3..c4426979 100644 --- a/base/sources/ts/iron/input.ts +++ b/base/sources/ts/iron/input.ts @@ -7,14 +7,18 @@ function input_reset() { mouse_reset(); pen_reset(); keyboard_reset(); + ///if WITH_GAMEPAD gamepad_reset(); + ///end } function input_end_frame() { mouse_end_frame(); pen_end_frame(); keyboard_end_frame(); + ///if WITH_GAMEPAD gamepad_end_frame(); + ///end } function _input_on_foreground() { @@ -31,7 +35,9 @@ function input_register() { // Reset mouse delta on foreground sys_notify_on_app_state(_input_on_foreground, null, null, null, null); keyboard_reset(); + ///if WITH_GAMEPAD gamepad_reset(); + ///end } let _mouse_buttons: string[] = ["left", "right", "middle", "side1", "side2"]; @@ -686,6 +692,8 @@ function keyboard_up_listener(code: key_code_t) { function keyboard_press_listener(c: string) {} +///if WITH_GAMEPAD + let gamepad_buttons_ps: string[] = ["cross", "circle", "square", "triangle", "l1", "r1", "l2", "r2", "share", "options", "l3", "r3", "up", "down", "left", "right", "home", "touchpad"]; let gamepad_buttons_xbox: string[] = ["a", "b", "x", "y", "l1", "r1", "l2", "r2", "share", "options", "l3", "r3", "up", "down", "left", "right", "home", "touchpad"]; let gamepad_buttons: string[] = gamepad_buttons_ps; @@ -822,6 +830,8 @@ type gamepad_t = { right_stick?: gamepad_stick_t; }; +///end + enum key_code_t { UNKNOWN = 0, BACK = 1, // Android diff --git a/base/sources/ts/iron/sys.ts b/base/sources/ts/iron/sys.ts index 4ef7a9a2..a57e2d0f 100644 --- a/base/sources/ts/iron/sys.ts +++ b/base/sources/ts/iron/sys.ts @@ -72,8 +72,10 @@ function sys_start(ops: iron_window_options_t) { iron_set_pen_down_callback(sys_pen_down_callback); iron_set_pen_up_callback(sys_pen_up_callback); iron_set_pen_move_callback(sys_pen_move_callback); + ///if WITH_GAMEPAD iron_set_gamepad_axis_callback(sys_gamepad_axis_callback); iron_set_gamepad_button_callback(sys_gamepad_button_callback); + ///end input_register(); } @@ -239,6 +241,7 @@ function sys_pen_move_callback(x: i32, y: i32, pressure: f32) { pen_move_listener(x, y, pressure); } +///if WITH_GAMEPAD function sys_gamepad_axis_callback(gamepad: i32, axis: i32, value: f32) { gamepad_axis_listener(gamepad, axis, value); } @@ -246,6 +249,7 @@ function sys_gamepad_axis_callback(gamepad: i32, axis: i32, value: f32) { function sys_gamepad_button_callback(gamepad: i32, button: i32, value: f32) { gamepad_button_listener(gamepad, button, value); } +///end function sys_title(): string { return _sys_window_title; diff --git a/base/tools/make.js b/base/tools/make.js index ec8cde2c..14364eeb 100644 --- a/base/tools/make.js +++ b/base/tools/make.js @@ -2225,6 +2225,7 @@ function load_project(directory, is_root_project) { with_audio: false, with_iron: false, with_eval: false, + with_gamepad: false, embed: false }; }