/* * Portions of this file are copyright Rebirth contributors and licensed as * described in COPYING.txt. * Portions of this file are copyright Parallax Software and licensed * according to the Parallax license below. * See COPYING.txt for license details. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines to configure keyboard, joystick, etc.. * */ #include #include #include #include #include #include #include #include #include #include "dxxerror.h" #include "pstypes.h" #include "gr.h" #include "window.h" #include "console.h" #include "palette.h" #include "physfsx.h" #include "game.h" #include "gamefont.h" #include "iff.h" #include "u_mem.h" #include "kconfig.h" #include "gauges.h" #include "rbaudio.h" #include "render.h" #include "digi.h" #include "key.h" #include "mouse.h" #include "newmenu.h" #include "endlevel.h" #include "multi.h" #include "timer.h" #include "text.h" #include "player.h" #include "menu.h" #include "automap.h" #include "args.h" #include "lighting.h" #include "ai.h" #include "cntrlcen.h" #include "collide.h" #include "playsave.h" #include "screens.h" #if DXX_USE_OGL #include "ogl_init.h" #endif #include "compiler-lengthof.h" #include "compiler-range_for.h" #ifndef RELEASE #define TABLE_CREATION 1 #endif using std::min; using std::max; using std::plus; using std::minus; // Array used to 'blink' the cursor while waiting for a keypress. const array fades{{ 1,1,1,2,2,3,4,4,5,6,8,9,10,12,13,15, 16,17,19,20,22,23,24,26,27,28,28,29,30,30,31,31, 31,31,31,30,30,29,28,28,27,26,24,23,22,20,19,17, 16,15,13,12,10,9,8,6,5,4,4,3,2,2,1,1 }}; const array invert_text{{"N", "Y"}}; #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK joybutton_text_t joybutton_text; #endif #if DXX_MAX_AXES_PER_JOYSTICK joyaxis_text_t joyaxis_text; #endif constexpr char mouseaxis_text[][8] = { "L/R", "F/B", "WHEEL" }; constexpr char mousebutton_text[][8] = { "LEFT", "RIGHT", "MID", "M4", "M5", "M6", "M7", "M8", "M9", "M10","M11","M12","M13","M14","M15","M16" }; const array system_keys{{ KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_MINUS, KEY_EQUAL, KEY_PRINT_SCREEN, // KEY_*LOCK should always be last since we wanna skip these if -nostickykeys KEY_CAPSLOCK, KEY_SCROLLOCK, KEY_NUMLOCK }}; control_info Controls; fix Cruise_speed=0; #define BT_KEY 0 #define BT_MOUSE_BUTTON 1 #define BT_MOUSE_AXIS 2 #define BT_JOY_BUTTON 3 #define BT_JOY_AXIS 4 #define BT_INVERT 5 #define STATE_BIT1 1 #define STATE_BIT2 2 #define STATE_BIT3 4 #define STATE_BIT4 8 #define STATE_BIT5 16 #define INFO_Y (188) namespace dcx { const array DefaultKeySettingsRebirth{{ 0x2,0xff,0xff,0x3,0xff,0xff,0x4,0xff,0xff,0x5,0xff,0xff,0x6,0xff,0xff,0x7,0xff,0xff,0x8,0xff,0xff,0x9,0xff,0xff,0xa,0xff,0xff,0xb,0xff,0xff }}; namespace { struct kc_mitem { uint8_t value; // what key,button,etc }; } } namespace dsx { namespace { struct kc_item { const short x, y; // x, y pos of label const short xinput; // x pos of input field const int8_t w2; // length of input field const uint8_t u,d,l,r; // neighboring field ids for cursor navigation const uint8_t type; const uint8_t state_bit; union { uint8_t control_info::state_controls_t::*const ci_state_ptr; uint8_t control_info::state_controls_t::*const ci_count_ptr; }; }; struct kc_menu : embed_window_pointer_t { const char *litems; const kc_item *items; kc_mitem *mitems; const char *title; unsigned nitems; unsigned citem; ubyte changing; ubyte q_fade_i; // for flashing the question mark ubyte mouse_state; array old_maxis; #if DXX_MAX_AXES_PER_JOYSTICK array old_jaxis; #endif }; } const array, 3> DefaultKeySettings{{ #if defined(DXX_BUILD_DESCENT_I) {{0xc8,0x48,0xd0,0x50,0xcb,0x4b,0xcd,0x4d,0x38,0xff,0xff,0x4f,0xff,0x51,0xff,0x4a,0xff,0x4e,0xff,0xff,0x10,0x47,0x12,0x49,0x1d,0x9d,0x39,0xff,0x21,0xff,0x1e,0xff,0x2c,0xff,0x30,0xff,0x13,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf,0xff,0x33,0x0,0x34,0x0}}, {{0x0,0x1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1,0x0,0x0,0x0,0xff,0x0,0xff,0x0,0xff,0x0,0xff,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0,0x0}}, {{0x0,0x1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1,0x0,0x0,0x0,0xff,0x0,0xff,0x0,0xff,0x0,0xff,0x0,0xff,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}, #elif defined(DXX_BUILD_DESCENT_II) {{0xc8,0x48,0xd0,0x50,0xcb,0x4b,0xcd,0x4d,0x38,0xff,0xff,0x4f,0xff,0x51,0xff,0x4a,0xff,0x4e,0xff,0xff,0x10,0x47,0x12,0x49,0x1d,0x9d,0x39,0xff,0x21,0xff,0x1e,0xff,0x2c,0xff,0x30,0xff,0x13,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf,0xff,0x1f,0xff,0x33,0xff,0x34,0xff,0x23,0xff,0x14,0xff,0xff,0xff,0x0,0x0}}, {{0x0,0x1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1,0x0,0x0,0x0,0xff,0x0,0xff,0x0,0xff,0x0,0xff,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0,0x0,0x0,0x0}}, {{0x0,0x1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1,0x0,0x0,0x0,0xff,0x0,0xff,0x0,0xff,0x0,0xff,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0}}, #endif }}; // id, x, y, w1, w2, u, d, l, r, text, type, value constexpr kc_item kc_keyboard[] = { #if defined(DXX_BUILD_DESCENT_I) { 15, 49, 86, 26, 43, 2, 49, 1, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_pitch_forward} }, { 15, 49,115, 26, 48, 3, 0, 24, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_pitch_forward} }, #elif defined(DXX_BUILD_DESCENT_II) { 15, 49, 86, 26, 55, 2, 56, 1, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_pitch_forward} }, { 15, 49,115, 26, 50, 3, 0, 24, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_pitch_forward} }, #endif { 15, 57, 86, 26, 0, 4, 25, 3, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_pitch_backward} }, { 15, 57,115, 26, 1, 5, 2, 26, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_pitch_backward} }, { 15, 65, 86, 26, 2, 6, 27, 5, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_heading_left} }, { 15, 65,115, 26, 3, 7, 4, 28, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_heading_left} }, { 15, 73, 86, 26, 4, 8, 29, 7, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_heading_right} }, { 15, 73,115, 26, 5, 9, 6, 34, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_heading_right} }, { 15, 85, 86, 26, 6, 10, 35, 9, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::slide_on} }, { 15, 85,115, 26, 7, 11, 8, 36, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::slide_on} }, { 15, 93, 86, 26, 8, 12, 37, 11, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_slide_left} }, { 15, 93,115, 26, 9, 13, 10, 44, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_slide_left} }, { 15,101, 86, 26, 10, 14, 45, 13, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_slide_right} }, { 15,101,115, 26, 11, 15, 12, 30, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_slide_right} }, { 15,109, 86, 26, 12, 16, 31, 15, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_slide_up} }, { 15,109,115, 26, 13, 17, 14, 32, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_slide_up} }, { 15,117, 86, 26, 14, 18, 33, 17, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_slide_down} }, #if defined(DXX_BUILD_DESCENT_I) { 15,117,115, 26, 15, 19, 16, 38, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_slide_down} }, { 15,129, 86, 26, 16, 20, 39, 19, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::bank_on} }, { 15,129,115, 26, 17, 21, 18, 40, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::bank_on} }, { 15,137, 86, 26, 18, 22, 41, 21, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_bank_left} }, { 15,137,115, 26, 19, 23, 20, 42, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_bank_left} }, { 15,145, 86, 26, 20, 46, 43, 23, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_bank_right} }, { 15,145,115, 26, 21, 47, 22, 46, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_bank_right} }, {158, 49,241, 26, 49, 26, 1, 25, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::fire_primary} }, {158, 49,270, 26, 42, 27, 24, 2, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::fire_primary} }, #elif defined(DXX_BUILD_DESCENT_II) { 15,117,115, 26, 15, 19, 16, 46, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_slide_down} }, { 15,129, 86, 26, 16, 20, 47, 19, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::bank_on} }, { 15,129,115, 26, 17, 21, 18, 38, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::bank_on} }, { 15,137, 86, 26, 18, 22, 39, 21, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_bank_left} }, { 15,137,115, 26, 19, 23, 20, 40, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_bank_left} }, { 15,145, 86, 26, 20, 48, 41, 23, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::key_bank_right} }, { 15,145,115, 26, 21, 49, 22, 42, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::key_bank_right} }, {158, 49,241, 26, 51, 26, 1, 25, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::fire_primary} }, {158, 49,270, 26, 56, 27, 24, 2, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::fire_primary} }, #endif {158, 57,241, 26, 24, 28, 3, 27, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::fire_secondary} }, {158, 57,270, 26, 25, 29, 26, 4, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::fire_secondary} }, {158, 65,241, 26, 26, 34, 5, 29, BT_KEY, 0, {&control_info::state_controls_t::fire_flare} }, {158, 65,270, 26, 27, 35, 28, 6, BT_KEY, 0, {&control_info::state_controls_t::fire_flare} }, {158,105,241, 26, 44, 32, 13, 31, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::accelerate} }, {158,105,270, 26, 45, 33, 30, 14, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::accelerate} }, #if defined(DXX_BUILD_DESCENT_I) {158,113,241, 26, 30, 38, 15, 33, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::reverse} }, {158,113,270, 26, 31, 39, 32, 16, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::reverse} }, #elif defined(DXX_BUILD_DESCENT_II) {158,113,241, 26, 30, 46, 15, 33, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::reverse} }, {158,113,270, 26, 31, 47, 32, 16, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::reverse} }, #endif {158, 73,241, 26, 28, 36, 7, 35, BT_KEY, 0, {&control_info::state_controls_t::drop_bomb} }, {158, 73,270, 26, 29, 37, 34, 8, BT_KEY, 0, {&control_info::state_controls_t::drop_bomb} }, {158, 85,241, 26, 34, 44, 9, 37, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::rear_view} }, {158, 85,270, 26, 35, 45, 36, 10, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::rear_view} }, #if defined(DXX_BUILD_DESCENT_I) {158,125,241, 26, 32, 40, 17, 39, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::cruise_plus} }, {158,125,270, 26, 33, 41, 38, 18, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::cruise_plus} }, {158,133,241, 26, 38, 42, 19, 41, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::cruise_minus} }, {158,133,270, 26, 39, 43, 40, 20, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::cruise_minus} }, {158,141,241, 26, 40, 25, 21, 43, BT_KEY, 0, {&control_info::state_controls_t::cruise_off} }, {158,141,270, 26, 41, 0, 42, 22, BT_KEY, 0, {&control_info::state_controls_t::cruise_off} }, #elif defined(DXX_BUILD_DESCENT_II) {158,133,241, 26, 46, 40, 19, 39, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::cruise_plus} }, {158,133,270, 26, 47, 41, 38, 20, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::cruise_plus} }, {158,141,241, 26, 38, 42, 21, 41, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::cruise_minus} }, {158,141,270, 26, 39, 43, 40, 22, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::cruise_minus} }, {158,149,241, 26, 40, 52, 23, 43, BT_KEY, 0, {&control_info::state_controls_t::cruise_off} }, {158,149,270, 26, 41, 53, 42, 48, BT_KEY, 0, {&control_info::state_controls_t::cruise_off} }, #endif {158, 93,241, 26, 36, 30, 11, 45, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::automap} }, {158, 93,270, 26, 37, 31, 44, 12, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::automap} }, #if defined(DXX_BUILD_DESCENT_I) { 15,157, 86, 26, 22, 48, 23, 47, BT_KEY, 0, {&control_info::state_controls_t::cycle_primary} }, { 15,157,115, 26, 23, 49, 46, 48, BT_KEY, 0, {&control_info::state_controls_t::cycle_primary} }, { 15,165, 86, 26, 46, 1, 47, 49, BT_KEY, 0, {&control_info::state_controls_t::cycle_secondary} }, { 15,165,115, 26, 47, 24, 48, 0, BT_KEY, 0, {&control_info::state_controls_t::cycle_secondary} }, #elif defined(DXX_BUILD_DESCENT_II) {158,121,241, 26, 32, 38, 17, 47, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::afterburner} }, {158,121,270, 26, 33, 39, 46, 18, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::afterburner} }, { 15,161, 86, 26, 22, 50, 43, 49, BT_KEY, 0, {&control_info::state_controls_t::cycle_primary} }, { 15,161,115, 26, 23, 51, 48, 52, BT_KEY, 0, {&control_info::state_controls_t::cycle_primary} }, { 15,169, 86, 26, 48, 1, 53, 51, BT_KEY, 0, {&control_info::state_controls_t::cycle_secondary} }, { 15,169,115, 26, 49, 24, 50, 54, BT_KEY, 0, {&control_info::state_controls_t::cycle_secondary} }, {158,163,241, 26, 42, 54, 49, 53, BT_KEY, 0, {&control_info::state_controls_t::headlight} }, {158,163,270, 26, 43, 55, 52, 50, BT_KEY, 0, {&control_info::state_controls_t::headlight} }, {158,171,241, 26, 52, 56, 51, 55, BT_KEY, STATE_BIT1, {&control_info::state_controls_t::energy_to_shield} }, {158,171,270, 26, 53, 0, 54, 56, BT_KEY, STATE_BIT2, {&control_info::state_controls_t::energy_to_shield} }, {158,179,241, 26, 54, 25, 55, 0, BT_KEY, 0, {&control_info::state_controls_t::toggle_bomb} }, #endif }; constexpr const char *kcl_keyboard = "Pitch forward\0" "Pitch backward\0" "Turn left\0" "Turn right\0" "Slide on\0" "Slide left\0" "Slide right\0" "Slide up\0" "Slide down\0" "Bank on\0" "Bank left\0" "Bank right\0" "Fire primary\0" "Fire secondary\0" "Fire flare\0" "Accelerate\0" "Reverse\0" "Drop Bomb\0" "REAR VIEW\0" "Cruise Faster\0" "Cruise Slower\0" "Cruise Off\0" "Automap\0" #if defined(DXX_BUILD_DESCENT_II) "Afterburner\0" #endif "Cycle Primary\0" "Cycle Second.\0" #if defined(DXX_BUILD_DESCENT_II) "Headlight\0" "Energy->Shield\0" "Toggle Bomb\0" #endif ; static array kcm_keyboard; #if DXX_MAX_JOYSTICKS #if DXX_MAX_AXES_PER_JOYSTICK #define DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH(I) I #else #define DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH(I) (static_cast(I), 0) #endif #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK #define DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(I) I #else #define DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(I) (static_cast(I), 0) #endif constexpr kc_item kc_joystick[] = { #if defined(DXX_BUILD_DESCENT_I) { 22, 46,104, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 15, 1, 24, 29, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::fire_primary} }, { 22, 54,104, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 0, 4, 34, 30, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::fire_secondary} }, { 22, 78,104, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 26, 3, 37, 31, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::accelerate} }, { 22, 86,104, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 2, 25, 38, 32, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::reverse} }, { 22, 62,104, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 1, 26, 35, 33, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::fire_flare} }, {174, 46,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 23, 6, 29, 34, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::slide_on} }, {174, 54,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 5, 7, 30, 35, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_slide_left} }, {174, 62,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 6, 8, 33, 36, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_slide_right} }, {174, 70,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 7, 9, 43, 37, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_slide_up} }, {174, 78,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 8, 10, 31, 38, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_slide_down} }, {174, 86,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 9, 11, 32, 39, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::bank_on} }, {174, 94,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 10, 12, 42, 40, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_bank_left} }, {174,102,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 11, 44, 28, 41, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_bank_right} }, { 22,154, 73, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH(26), 47, 15, 47, 14, BT_JOY_AXIS, 0, {NULL} }, { 22,154,121, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH( 8), 27, 16, 13, 17, BT_INVERT, 0, {NULL} }, #elif defined(DXX_BUILD_DESCENT_II) { 22, 46,102, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 15, 1, 24, 31, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::fire_primary} }, { 22, 54,102, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 0, 4, 36, 32, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::fire_secondary} }, { 22, 78,102, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 26, 3, 39, 33, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::accelerate} }, { 22, 86,102, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 2, 25, 40, 34, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::reverse} }, { 22, 62,102, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 1, 26, 37, 35, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::fire_flare} }, {174, 46,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 23, 6, 31, 36, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::slide_on} }, {174, 54,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 5, 7, 32, 37, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_slide_left} }, {174, 62,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 6, 8, 35, 38, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_slide_right} }, {174, 70,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 7, 9, 45, 39, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_slide_up} }, {174, 78,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 8, 10, 33, 40, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_slide_down} }, {174, 86,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 9, 11, 34, 41, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::bank_on} }, {174, 94,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 10, 12, 44, 42, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_bank_left} }, {174,102,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 11, 28, 46, 43, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::btn_bank_right} }, { 22,154, 73, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH(26), 55, 15, 55, 14, BT_JOY_AXIS, 0, {NULL} }, { 22,154,121, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH( 8), 50, 16, 13, 17, BT_INVERT, 0, {NULL} }, #endif { 22,162, 73, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH(26), 13, 0, 18, 16, BT_JOY_AXIS, 0, {NULL} }, #if defined(DXX_BUILD_DESCENT_I) { 22,162,121, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH( 8), 14, 29, 15, 19, BT_INVERT, 0, {NULL} }, {164,154,222, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH(26), 28, 19, 14, 18, BT_JOY_AXIS, 0, {NULL} }, {164,154,270, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH( 8), 45, 20, 17, 15, BT_INVERT, 0, {NULL} }, #elif defined(DXX_BUILD_DESCENT_II) { 22,162,121, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH( 8), 14, 31, 15, 19, BT_INVERT, 0, {NULL} }, {164,154,222, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH(26), 51, 19, 14, 18, BT_JOY_AXIS, 0, {NULL} }, {164,154,270, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH( 8), 54, 20, 17, 15, BT_INVERT, 0, {NULL} }, #endif {164,162,222, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH(26), 17, 21, 16, 20, BT_JOY_AXIS, 0, {NULL} }, {164,162,270, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH( 8), 18, 22, 19, 21, BT_INVERT, 0, {NULL} }, {164,170,222, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH(26), 19, 23, 20, 22, BT_JOY_AXIS, 0, {NULL} }, {164,170,270, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH( 8), 20, 24, 21, 23, BT_INVERT, 0, {NULL} }, {164,178,222, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH(26), 21, 5, 22, 24, BT_JOY_AXIS, 0, {NULL} }, #if defined(DXX_BUILD_DESCENT_I) {164,178,270, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH( 8), 22, 34, 23, 0, BT_INVERT, 0, {NULL} }, { 22, 94,104, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 3, 27, 39, 42, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::rear_view} }, { 22, 70,104, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 4, 2, 36, 43, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::drop_bomb} }, { 22,102,104, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 25, 14, 40, 28, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::automap} }, { 22,102,133, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 42, 17, 27, 12, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::automap} }, { 22, 46,133, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 16, 30, 0, 5, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::fire_primary} }, { 22, 54,133, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 29, 33, 1, 6, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::fire_secondary} }, { 22, 78,133, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 43, 32, 2, 9, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::accelerate} }, { 22, 86,133, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 31, 42, 3, 10, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::reverse} }, { 22, 62,133, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 30, 43, 4, 7, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::fire_flare} }, {174, 46,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 24, 35, 5, 1, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::slide_on} }, {174, 54,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 34, 36, 6, 4, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_slide_left} }, {174, 62,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 35, 37, 7, 26, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_slide_right} }, {174, 70,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 36, 38, 8, 2, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_slide_up} }, {174, 78,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 37, 39, 9, 3, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_slide_down} }, {174, 86,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 38, 40, 10, 25, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::bank_on} }, {174, 94,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 39, 41, 11, 27, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_bank_left} }, {174,102,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 40, 46, 12, 44, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_bank_right} }, { 22, 94,133, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 32, 28, 25, 11, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::rear_view} }, { 22, 70,133, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 33, 31, 26, 8, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::drop_bomb} }, {174,110,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 12, 45, 41, 46, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::cycle_primary} }, {174,118,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 44, 18, 46, 47, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::cycle_secondary} }, {174,110,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 41, 47, 44, 45, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::cycle_primary} }, {174,118,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 46, 13, 45, 13, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::cycle_secondary} }, #elif defined(DXX_BUILD_DESCENT_II) {164,178,270, DXX_KCONFIG_ITEM_JOY_AXIS_WIDTH( 8), 22, 36, 23, 0, BT_INVERT, 0, {NULL} }, { 22, 94,102, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 3, 27, 41, 44, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::rear_view} }, { 22, 70,102, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 4, 2, 38, 45, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::drop_bomb} }, { 22,102,102, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 25, 30, 42, 46, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::afterburner} }, {174,110,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 12, 29, 49, 47, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::cycle_primary} }, {174,118,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 28, 54, 53, 48, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::cycle_secondary} }, { 22,110,102, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 27, 52, 43, 49, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::headlight} }, { 22, 46,132, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 16, 32, 0, 5, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::fire_primary} }, { 22, 54,132, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 31, 35, 1, 6, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::fire_secondary} }, { 22, 78,132, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 45, 34, 2, 9, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::accelerate} }, { 22, 86,132, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 33, 44, 3, 10, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::reverse} }, { 22, 62,132, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 32, 45, 4, 7, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::fire_flare} }, {174, 46,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 24, 37, 5, 1, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::slide_on} }, {174, 54,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 36, 38, 6, 4, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_slide_left} }, {174, 62,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 37, 39, 7, 26, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_slide_right} }, {174, 70,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 38, 40, 8, 2, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_slide_up} }, {174, 78,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 39, 41, 9, 3, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_slide_down} }, {174, 86,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 40, 42, 10, 25, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::bank_on} }, {174, 94,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 41, 43, 11, 27, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_bank_left} }, {174,102,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 42, 47, 12, 30, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::btn_bank_right} }, { 22, 94,132, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 34, 46, 25, 11, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::rear_view} }, { 22, 70,132, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 35, 33, 26, 8, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::drop_bomb} }, { 22,102,132, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 44, 49, 27, 12, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::afterburner} }, {174,110,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 43, 48, 28, 52, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::cycle_primary} }, {174,118,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 47, 55, 29, 50, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::cycle_secondary} }, { 22,110,132, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 46, 53, 30, 28, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::headlight} }, { 22,126,102, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 52, 14, 48, 51, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::automap} }, { 22,126,132, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 53, 17, 50, 54, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::automap} }, { 22,118,102, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 30, 50, 47, 53, BT_JOY_BUTTON, STATE_BIT3, {&control_info::state_controls_t::energy_to_shield} }, { 22,118,132, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 49, 51, 52, 29, BT_JOY_BUTTON, STATE_BIT4, {&control_info::state_controls_t::energy_to_shield} }, {174,126,248, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 29, 18, 51, 55, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::toggle_bomb} }, {174,126,278, DXX_KCONFIG_ITEM_JOY_BUTTON_WIDTH(26), 48, 13, 54, 13, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::toggle_bomb} }, #endif }; constexpr const char *kcl_joystick = "Fire primary\0" "Fire secondary\0" "Accelerate\0" "Reverse\0" "Fire flare\0" "Slide on\0" "Slide left\0" "Slide right\0" "Slide up\0" "Slide down\0" "Bank on\0" "Bank left\0" "Bank right\0" "Pitch U/D\0" "Turn L/R\0" "Slide L/R\0" "Slide U/D\0" "Bank L/R\0" "Throttle\0" "Rear view\0" "Drop bomb\0" #if defined(DXX_BUILD_DESCENT_I) "Automap\0" #elif defined(DXX_BUILD_DESCENT_II) "Afterburner\0" "Cycle Primary\0" "Cycle Secondary\0" "Headlight\0" #endif "Fire primary\0" "Fire secondary\0" "Accelerate\0" "Reverse\0" "Fire flare\0" "Slide on\0" "Slide left\0" "Slide right\0" "Slide up\0" "Slide down\0" "Bank on\0" "Bank left\0" "Bank right\0" "Rear view\0" "Drop bomb\0" #if defined(DXX_BUILD_DESCENT_I) "Cycle Primary\0" "Cycle Secondary\0" "\0" // Cycle Primary "\0" // Cycle Secondary #elif defined(DXX_BUILD_DESCENT_II) "\0" // Afterburner "\0" // Cycle Primary "\0" // Cycle Secondary "\0" // Headlight "Automap\0" "Energy->Shield\0" "Toggle Bomb\0" #endif ; static array kcm_joystick; #endif constexpr kc_item kc_mouse[] = { { 25, 46,110, 26, 19, 1, 20, 5, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::fire_primary} }, { 25, 54,110, 26, 0, 4, 5, 6, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::fire_secondary} }, { 25, 78,110, 26, 26, 3, 8, 9, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::accelerate} }, { 25, 86,110, 26, 2, 25, 9, 10, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::reverse} }, { 25, 62,110, 26, 1, 26, 6, 7, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::fire_flare} }, {180, 46,239, 26, 23, 6, 0, 1, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::slide_on} }, {180, 54,239, 26, 5, 7, 1, 4, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::btn_slide_left} }, {180, 62,239, 26, 6, 8, 4, 26, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::btn_slide_right} }, {180, 70,239, 26, 7, 9, 26, 2, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::btn_slide_up} }, {180, 78,239, 26, 8, 10, 2, 3, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::btn_slide_down} }, {180, 86,239, 26, 9, 11, 3, 25, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::bank_on} }, {180, 94,239, 26, 10, 12, 25, 27, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::btn_bank_left} }, {180,102,239, 26, 11, 22, 27, 28, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::btn_bank_right} }, #if defined(DXX_BUILD_DESCENT_I) { 25,154, 83, 26, 24, 15, 28, 14, BT_MOUSE_AXIS, 0, {NULL} }, { 25,154,131, 8, 28, 16, 13, 21, BT_INVERT, 0, {NULL} }, #elif defined(DXX_BUILD_DESCENT_II) { 25,154, 83, 26, 24, 15, 29, 14, BT_MOUSE_AXIS, 0, {NULL} }, { 25,154,131, 8, 29, 16, 13, 21, BT_INVERT, 0, {NULL} }, #endif { 25,162, 83, 26, 13, 17, 22, 16, BT_MOUSE_AXIS, 0, {NULL} }, { 25,162,131, 8, 14, 18, 15, 23, BT_INVERT, 0, {NULL} }, { 25,170, 83, 26, 15, 19, 24, 18, BT_MOUSE_AXIS, 0, {NULL} }, { 25,170,131, 8, 16, 20, 17, 19, BT_INVERT, 0, {NULL} }, { 25,178, 83, 26, 17, 0, 18, 20, BT_MOUSE_AXIS, 0, {NULL} }, { 25,178,131, 8, 18, 21, 19, 0, BT_INVERT, 0, {NULL} }, {180,154,238, 26, 20, 23, 14, 22, BT_MOUSE_AXIS, 0, {NULL} }, {180,154,286, 8, 12, 24, 21, 15, BT_INVERT, 0, {NULL} }, {180,162,238, 26, 21, 5, 16, 24, BT_MOUSE_AXIS, 0, {NULL} }, {180,162,286, 8, 22, 13, 23, 17, BT_INVERT, 0, {NULL} }, { 25, 94,110, 26, 3, 27, 10, 11, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::rear_view} }, { 25, 70,110, 26, 4, 2, 7, 8, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::drop_bomb} }, #if defined(DXX_BUILD_DESCENT_I) { 25,102,110, 26, 25, 28, 11, 12, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::cycle_primary} }, { 25,110,110, 26, 27, 14, 12, 13, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::cycle_secondary} }, #elif defined(DXX_BUILD_DESCENT_II) { 25,102,110, 26, 25, 28, 11, 12, BT_MOUSE_BUTTON, STATE_BIT5, {&control_info::state_controls_t::afterburner} }, { 25,110,110, 26, 27, 29, 12, 29, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::cycle_primary} }, { 25,118,110, 26, 28, 14, 28, 13, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::cycle_secondary} }, #endif }; constexpr const char *kcl_mouse = "Fire primary\0" "Fire secondary\0" "Accelerate\0" "reverse\0" "Fire flare\0" "Slide on\0" "Slide left\0" "Slide right\0" "Slide up\0" "Slide down\0" "Bank on\0" "Bank left\0" "Bank right\0" "Pitch U/D\0" "Turn L/R\0" "Slide L/R\0" "Slide U/D\0" "Bank L/R\0" "Throttle\0" "REAR VIEW\0" "Drop Bomb\0" #if defined(DXX_BUILD_DESCENT_II) "Afterburner\0" #endif "Cycle Primary\0" "Cycle Secondary\0" ; static array kcm_mouse; #if defined(DXX_BUILD_DESCENT_I) #define D2X_EXTENDED_WEAPON_STRING(X) #elif defined(DXX_BUILD_DESCENT_II) #define D2X_EXTENDED_WEAPON_STRING(X) X #endif #define WEAPON_STRING_LASER D2X_EXTENDED_WEAPON_STRING("(SUPER)") "LASER CANNON" #define WEAPON_STRING_VULCAN "VULCAN" D2X_EXTENDED_WEAPON_STRING("/GAUSS") " CANNON" #define WEAPON_STRING_SPREADFIRE "SPREADFIRE" D2X_EXTENDED_WEAPON_STRING("/HELIX") " CANNON" #define WEAPON_STRING_PLASMA "PLASMA" D2X_EXTENDED_WEAPON_STRING("/PHOENIX") " CANNON" #define WEAPON_STRING_FUSION "FUSION" D2X_EXTENDED_WEAPON_STRING("/OMEGA") " CANNON" #define WEAPON_STRING_CONCUSSION "CONCUSSION" D2X_EXTENDED_WEAPON_STRING("/FLASH") " MISSILE" #define WEAPON_STRING_HOMING "HOMING" D2X_EXTENDED_WEAPON_STRING("/GUIDED") " MISSILE" #define WEAPON_STRING_PROXIMITY "PROXIMITY BOMB" D2X_EXTENDED_WEAPON_STRING("/SMART MINE") #define WEAPON_STRING_SMART "SMART" D2X_EXTENDED_WEAPON_STRING("/MERCURY") " MISSILE" #define WEAPON_STRING_MEGA "MEGA" D2X_EXTENDED_WEAPON_STRING("/EARTHSHAKER") " MISSILE" #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK #define DXX_KCONFIG_ITEM_JOY_WIDTH(I) I #else #define DXX_KCONFIG_ITEM_JOY_WIDTH(I) (static_cast(I), 0) #endif constexpr kc_item kc_rebirth[] = { { 15, 69,157, 26, 29, 3, 29, 1, BT_KEY, 0, {&control_info::state_controls_t::select_weapon} }, { 15, 69,215, DXX_KCONFIG_ITEM_JOY_WIDTH(26), 27, 4, 0, 2, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15, 69,273, 26, 28, 5, 1, 3, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15, 77,157, 26, 0, 6, 2, 4, BT_KEY, 0, {&control_info::state_controls_t::select_weapon} }, { 15, 77,215, DXX_KCONFIG_ITEM_JOY_WIDTH(26), 1, 7, 3, 5, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15, 77,273, 26, 2, 8, 4, 6, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15, 85,157, 26, 3, 9, 5, 7, BT_KEY, 0, {&control_info::state_controls_t::select_weapon} }, { 15, 85,215, DXX_KCONFIG_ITEM_JOY_WIDTH(26), 4, 10, 6, 8, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15, 85,273, 26, 5, 11, 7, 9, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15, 93,157, 26, 6, 12, 8, 10, BT_KEY, 0, {&control_info::state_controls_t::select_weapon} }, { 15, 93,215, DXX_KCONFIG_ITEM_JOY_WIDTH(26), 7, 13, 9, 11, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15, 93,273, 26, 8, 14, 10, 12, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,101,157, 26, 9, 15, 11, 13, BT_KEY, 0, {&control_info::state_controls_t::select_weapon} }, { 15,101,215, DXX_KCONFIG_ITEM_JOY_WIDTH(26), 10, 16, 12, 14, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,101,273, 26, 11, 17, 13, 15, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,109,157, 26, 12, 18, 14, 16, BT_KEY, 0, {&control_info::state_controls_t::select_weapon} }, { 15,109,215, DXX_KCONFIG_ITEM_JOY_WIDTH(26), 13, 19, 15, 17, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,109,273, 26, 14, 20, 16, 18, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,117,157, 26, 15, 21, 17, 19, BT_KEY, 0, {&control_info::state_controls_t::select_weapon} }, { 15,117,215, DXX_KCONFIG_ITEM_JOY_WIDTH(26), 16, 22, 18, 20, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,117,273, 26, 17, 23, 19, 21, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,125,157, 26, 18, 24, 20, 22, BT_KEY, 0, {&control_info::state_controls_t::select_weapon} }, { 15,125,215, DXX_KCONFIG_ITEM_JOY_WIDTH(26), 19, 25, 21, 23, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,125,273, 26, 20, 26, 22, 24, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,133,157, 26, 21, 27, 23, 25, BT_KEY, 0, {&control_info::state_controls_t::select_weapon} }, { 15,133,215, DXX_KCONFIG_ITEM_JOY_WIDTH(26), 22, 28, 24, 26, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,133,273, 26, 23, 29, 25, 27, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,141,157, 26, 24, 1, 26, 28, BT_KEY, 0, {&control_info::state_controls_t::select_weapon} }, { 15,141,215, DXX_KCONFIG_ITEM_JOY_WIDTH(26), 25, 2, 27, 29, BT_JOY_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, { 15,141,273, 26, 26, 0, 28, 0, BT_MOUSE_BUTTON, 0, {&control_info::state_controls_t::select_weapon} }, }; constexpr const char *kcl_rebirth = WEAPON_STRING_LASER "\0" WEAPON_STRING_VULCAN "\0" WEAPON_STRING_SPREADFIRE "\0" WEAPON_STRING_PLASMA "\0" WEAPON_STRING_FUSION "\0" WEAPON_STRING_CONCUSSION "\0" WEAPON_STRING_HOMING "\0" WEAPON_STRING_PROXIMITY "\0" WEAPON_STRING_SMART "\0" WEAPON_STRING_MEGA "\0" ; static array kcm_rebirth; } static void kc_drawinput(grs_canvas &, const kc_item &item, kc_mitem &mitem, int is_current, const char *label); static void kc_change_key( kc_menu &menu,const d_event &event, kc_mitem& mitem ); #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK static void kc_change_joybutton( kc_menu &menu,const d_event &event, kc_mitem& mitem ); #endif static void kc_change_mousebutton( kc_menu &menu,const d_event &event, kc_mitem& mitem ); #if DXX_MAX_AXES_PER_JOYSTICK static void kc_change_joyaxis( kc_menu &menu,const d_event &event, kc_mitem& mitem ); #endif static void kc_change_mouseaxis( kc_menu &menu,const d_event &event, kc_mitem& mitem ); static void kc_change_invert( kc_menu *menu, kc_mitem * item ); namespace dsx { static void kc_drawquestion(grs_canvas &, kc_menu *menu, const kc_item *item); } #ifdef TABLE_CREATION static const kc_item *find_item_at(const kc_item *const ib, const kc_item *const ie, int x, int y) { const auto predicate = [=](const kc_item &i) { return i.xinput == x && i.y == y; }; return std::find_if(ib, ie, predicate); } namespace { class find_item_single { uint_fast32_t current; const uint_fast32_t limit; public: find_item_single(uint_fast32_t c, uint_fast32_t l) : current(c), limit(l) { } uint_fast32_t value() const { return current; } /* Return true on reset, false otherwise */ bool decrement() { if (current) return -- current, false; return current = limit - 1, true; } /* Return true on reset, false otherwise */ bool increment() { if (current != limit) return ++ current, false; return current = 0, true; } }; class find_item_state { find_item_single x, y; public: find_item_state(const kc_item &citem, const uint_fast32_t xl, const uint_fast32_t yl) : x(citem.xinput, xl), y(citem.y, yl) { } uint_fast32_t x_value() const { return x.value(); } uint_fast32_t y_value() const { return y.value(); } bool x_decrement() { return x.decrement(); } bool y_decrement() { return y.decrement(); } bool x_increment() { return x.increment(); } bool y_increment() { return y.increment(); } }; } template static inline std::ptrdiff_t find_next_item(const kc_item *const ib, const kc_item *const ie, find_item_state state) { bool looped = false; for (;;) { if (unlikely((state.*outer_step)())) if (unlikely((state.*inner_step)())) { if (unlikely(looped)) /* Sanity check. If looped is true and inner_step * returned true again, then the entire area has * already been searched. */ return std::distance(ib, ie); looped = true; } auto i = find_item_at(ib, ie, state.x_value(), state.y_value()); if (i != ie) return std::distance(ib, i); } } static std::ptrdiff_t find_next_item_up(const kc_item *const ib, const kc_item *const ie, const find_item_state &state) { return find_next_item<&find_item_state::y_decrement, &find_item_state::x_decrement>(ib, ie, state); } static std::ptrdiff_t find_next_item_down(const kc_item *const ib, const kc_item *const ie, const find_item_state &state) { return find_next_item<&find_item_state::y_increment, &find_item_state::x_increment>(ib, ie, state); } static std::ptrdiff_t find_next_item_right(const kc_item *const ib, const kc_item *const ie, const find_item_state &state) { return find_next_item<&find_item_state::x_increment, &find_item_state::y_increment>(ib, ie, state); } static std::ptrdiff_t find_next_item_left(const kc_item *const ib, const kc_item *const ie, const find_item_state &state) { return find_next_item<&find_item_state::x_decrement, &find_item_state::y_decrement>(ib, ie, state); } constexpr char btype_text[][13] = { "KEY", "MOUSE_BUTTON", "MOUSE_AXIS", "JOY_BUTTON", "JOY_AXIS", "INVERT" }; template static void print_create_table_items(PHYSFS_File *fp, const char *type, const char *litems, const kc_item (&items)[N]) { PHYSFSX_printf( fp, "\nstatic const kc_item kc_%s[] = {\n", type ); const grs_bitmap &cv_bitmap = grd_curcanv->cv_bitmap; const uint_fast32_t bm_w = cv_bitmap.bm_w, bm_h = cv_bitmap.bm_h; range_for (auto &i, items) { short u,d,l,r; const auto ib = begin(items); const auto ie = end(items); const find_item_state s{i, bm_w, bm_h}; u = find_next_item_up(ib, ie, s); d = find_next_item_down(ib, ie, s); l = find_next_item_left(ib, ie, s); r = find_next_item_right(ib, ie, s); PHYSFSX_printf( fp, "\t{ %3d,%3d,%3d,%3d,%3hd,%3hd,%3hd,%3hd, BT_%s },\n", i.x, i.y, i.xinput, i.w2, u, d, l, r, btype_text[i.type] ); } PHYSFSX_printf( fp, "};\n" "static const char *const kcl_%s =\n", type); const char *litem = litems; for (unsigned i=0; i < N; ++i ) { PHYSFSX_printf( fp, "\t\"%s\\0\"\n", litem); litem += strlen(litem) + 1; } PHYSFSX_printf( fp, ";\n" "static kc_mitem kcm_%1$s[lengthof(kc_%1$s)];\n", type ); } #endif static const char *get_item_text(const kc_item &item, const kc_mitem &mitem, char (&buf)[10]) { if (mitem.value==255) { return ""; } else { switch( item.type ) { case BT_KEY: return key_properties[mitem.value].key_text; case BT_MOUSE_BUTTON: return mousebutton_text[mitem.value]; case BT_MOUSE_AXIS: return mouseaxis_text[mitem.value]; #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK case BT_JOY_BUTTON: if (joybutton_text.size() > mitem.value) return &joybutton_text[mitem.value][0]; else { snprintf(buf, sizeof(buf), "BTN%2d", mitem.value + 1); return buf; } break; #else (void)buf; #endif #if DXX_MAX_AXES_PER_JOYSTICK case BT_JOY_AXIS: if (joyaxis_text.size() > mitem.value) return &joyaxis_text[mitem.value][0]; else { snprintf(buf, sizeof(buf), "AXIS%2d", mitem.value + 1); return buf; } break; #else (void)buf; #endif case BT_INVERT: return invert_text[mitem.value]; default: return NULL; } } } static int get_item_height(const grs_font &cv_font, const kc_item &item, const kc_mitem &mitem) { int h; char buf[10]; const char *btext; btext = get_item_text(item, mitem, buf); if (!btext) return 0; gr_get_string_size(cv_font, btext, nullptr, &h, nullptr); return h; } static void kc_gr_2y_string(grs_canvas &canvas, const char *const s, const font_y_scaled_float y, const font_x_scaled_float x0, const font_x_scaled_float x1) { int w, h; gr_get_string_size(*canvas.cv_font, s, &w, &h, nullptr); gr_string(canvas, x0, y, s, w, h); gr_string(canvas, x1, y, s, w, h); } static void kconfig_draw(kc_menu *menu) { grs_canvas * save_canvas = grd_curcanv; const auto &&fspacx = FSPACX(); const auto &&fspacy = FSPACY(); int w = fspacx(290), h = fspacy(170); gr_set_current_canvas(NULL); nm_draw_background(*grd_curcanv, ((SWIDTH - w) / 2) - BORDERX, ((SHEIGHT - h) / 2) - BORDERY, ((SWIDTH - w) / 2) + w + BORDERX, ((SHEIGHT - h) / 2) + h + BORDERY); gr_set_current_canvas(window_get_canvas(*menu->wind)); auto &canvas = *grd_curcanv; const grs_font *save_font = canvas.cv_font; gr_set_curfont(canvas, MEDIUM3_FONT); Assert(!strchr( menu->title, '\n' )); gr_string(canvas, 0x8000, fspacy(8), menu->title); gr_set_curfont(canvas, GAME_FONT); gr_set_fontcolor(canvas, BM_XRGB(28, 28, 28), -1); gr_string(canvas, 0x8000, fspacy(21), "Enter changes, ctrl-d deletes, ctrl-r resets defaults, ESC exits"); gr_set_fontcolor(canvas, BM_XRGB(28, 28, 28), -1); if ( menu->items == kc_keyboard ) { gr_set_fontcolor(canvas, BM_XRGB(31, 27, 6), -1); const uint8_t color = BM_XRGB(31,27,6); const auto &&fspacx98 = fspacx(98); const auto &&fspacx128 = fspacx(128); const auto &&fspacy42 = fspacy(42); gr_rect(canvas, fspacx98, fspacy42, fspacx(106), fspacy42, color); // horiz/left gr_rect(canvas, fspacx(120), fspacy42, fspacx128, fspacy42, color); // horiz/right const auto &&fspacy44 = fspacy(44); gr_rect(canvas, fspacx98, fspacy42, fspacx98, fspacy44, color); // vert/left gr_rect(canvas, fspacx128, fspacy42, fspacx128, fspacy44, color); // vert/right const auto &&fspacx253 = fspacx(253); const auto &&fspacx283 = fspacx(283); gr_rect(canvas, fspacx253, fspacy42, fspacx(261), fspacy42, color); // horiz/left gr_rect(canvas, fspacx(275), fspacy42, fspacx283, fspacy42, color); // horiz/right gr_rect(canvas, fspacx253, fspacy42, fspacx253, fspacy44, color); // vert/left gr_rect(canvas, fspacx283, fspacy42, fspacx283, fspacy44, color); // vert/right kc_gr_2y_string(canvas, "OR", fspacy(40), fspacx(109), fspacx(264)); } #if DXX_MAX_JOYSTICKS else if ( menu->items == kc_joystick ) { gr_set_fontcolor(canvas, BM_XRGB(31, 27, 6), -1); #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK gr_string(canvas, 0x8000, fspacy(30), TXT_BUTTONS); #endif #if DXX_MAX_AXES_PER_JOYSTICK const auto &&fspacy145 = fspacy(145); gr_string(canvas, 0x8000, fspacy(137), TXT_AXES); gr_set_fontcolor(canvas, BM_XRGB(28, 28, 28), -1); kc_gr_2y_string(canvas, TXT_AXIS, fspacy145, fspacx(81), fspacx(230)); kc_gr_2y_string(canvas, TXT_INVERT, fspacy145, fspacx(111), fspacx(260)); #endif gr_set_fontcolor(canvas, BM_XRGB(31, 27, 6), -1); #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK const uint8_t color = BM_XRGB(31, 27, 6); const auto &&fspacx115 = fspacx(115); const auto &&fspacy40 = fspacy(40); gr_rect(canvas, fspacx115, fspacy40, fspacx(123), fspacy40, color); // horiz/left const auto &&fspacx145 = fspacx(145); gr_rect(canvas, fspacx(137), fspacy40, fspacx145, fspacy40, color); // horiz/right const auto &&fspacx261 = fspacx(261); gr_rect(canvas, fspacx261, fspacy40, fspacx(269), fspacy40, color); // horiz/left const auto &&fspacx291 = fspacx(291); gr_rect(canvas, fspacx(283), fspacy40, fspacx291, fspacy40, color); // horiz/right const auto &&fspacy42 = fspacy(42); gr_rect(canvas, fspacx115, fspacy40, fspacx115, fspacy42, color); // vert/left gr_rect(canvas, fspacx145, fspacy40, fspacx145, fspacy42, color); // vert/right gr_rect(canvas, fspacx261, fspacy40, fspacx261, fspacy42, color); // vert/left gr_rect(canvas, fspacx291, fspacy40, fspacx291, fspacy42, color); // vert/right const auto &&fspacy38 = fspacy(38); kc_gr_2y_string(canvas, "OR", fspacy38, fspacx(126), fspacx(272)); #endif } #endif else if ( menu->items == kc_mouse ) { gr_set_fontcolor(canvas, BM_XRGB(31, 27, 6), -1); gr_string(canvas, 0x8000, fspacy(35), TXT_BUTTONS); gr_string(canvas, 0x8000, fspacy(137), TXT_AXES); gr_set_fontcolor(canvas, BM_XRGB(28, 28, 28), -1); const auto &&fspacy145 = fspacy(145); kc_gr_2y_string(canvas, TXT_AXIS, fspacy145, fspacx( 87), fspacx(242)); kc_gr_2y_string(canvas, TXT_INVERT, fspacy145, fspacx(120), fspacx(274)); } else if ( menu->items == kc_rebirth ) { gr_set_fontcolor(canvas, BM_XRGB(31, 27, 6), -1); const auto &&fspacy60 = fspacy(60); gr_string(canvas, fspacx(152), fspacy60, "KEYBOARD"); #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK gr_string(canvas, fspacx(210), fspacy60, "JOYSTICK"); #endif gr_string(canvas, fspacx(273), fspacy60, "MOUSE"); } unsigned citem = menu->citem; const char *current_label = NULL; const char *litem = menu->litems; for (unsigned i=0; i < menu->nitems; i++ ) { int next_label = (i + 1 >= menu->nitems || menu->items[i + 1].y != menu->items[i].y); if (i == citem) current_label = litem; else if (menu->items[i].w2) kc_drawinput(canvas, menu->items[i], menu->mitems[i], 0, next_label ? litem : nullptr); if (next_label) litem += strlen(litem) + 1; } kc_drawinput(canvas, menu->items[citem], menu->mitems[citem], 1, current_label); if (menu->changing) { const char *s; switch( menu->items[menu->citem].type ) { case BT_KEY: s = TXT_PRESS_NEW_KEY; break; case BT_MOUSE_BUTTON: s = TXT_PRESS_NEW_MBUTTON; break; case BT_MOUSE_AXIS: s = TXT_MOVE_NEW_MSE_AXIS; break; #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK case BT_JOY_BUTTON: s = TXT_PRESS_NEW_JBUTTON; break; #endif #if DXX_MAX_AXES_PER_JOYSTICK case BT_JOY_AXIS: s = TXT_MOVE_NEW_JOY_AXIS; break; #endif default: s = nullptr; break; } if (s) gr_string(canvas, 0x8000, fspacy(INFO_Y), s); kc_drawquestion(canvas, menu, &menu->items[menu->citem]); } gr_set_fontcolor(canvas, BM_XRGB(28, 28, 28), -1); canvas.cv_font = save_font; gr_set_current_canvas( save_canvas ); } static void kconfig_start_changing(kc_menu *menu) { if (menu->items[menu->citem].type == BT_INVERT) { kc_change_invert(menu, &menu->mitems[menu->citem]); return; } menu->q_fade_i = 0; // start question mark flasher menu->changing = 1; } static inline int in_bounds(unsigned mx, unsigned my, unsigned x1, unsigned xw, unsigned y1, unsigned yh) { if (mx <= x1) return 0; if (my <= y1) return 0; if (mx >= x1 + xw) return 0; if (my >= y1 + yh) return 0; return 1; } static window_event_result kconfig_mouse(window *wind,const d_event &event, kc_menu *menu) { grs_canvas * save_canvas = grd_curcanv; int mx, my, mz, x1, y1; window_event_result rval = window_event_result::ignored; gr_set_current_canvas(window_get_canvas(*wind)); auto &canvas = *grd_curcanv; if (menu->mouse_state) { int item_height; mouse_get_pos(&mx, &my, &mz); const auto &&fspacx = FSPACX(); const auto &&fspacy = FSPACY(); for (unsigned i=0; initems; i++ ) { item_height = get_item_height(*canvas.cv_font, menu->items[i], menu->mitems[i]); x1 = canvas.cv_bitmap.bm_x + fspacx(menu->items[i].xinput); y1 = canvas.cv_bitmap.bm_y + fspacy(menu->items[i].y); if (in_bounds(mx, my, x1, fspacx(menu->items[i].w2), y1, item_height)) { menu->citem = i; rval = window_event_result::handled; break; } } } else if (event.type == EVENT_MOUSE_BUTTON_UP) { int item_height; mouse_get_pos(&mx, &my, &mz); item_height = get_item_height(*canvas.cv_font, menu->items[menu->citem], menu->mitems[menu->citem]); const auto &&fspacx = FSPACX(); x1 = canvas.cv_bitmap.bm_x + fspacx(menu->items[menu->citem].xinput); y1 = canvas.cv_bitmap.bm_y + FSPACY(menu->items[menu->citem].y); if (in_bounds(mx, my, x1, fspacx(menu->items[menu->citem].w2), y1, item_height)) { kconfig_start_changing(menu); rval = window_event_result::handled; } else { // Click out of changing mode - kreatordxx menu->changing = 0; rval = window_event_result::handled; } } gr_set_current_canvas(save_canvas); return rval; } template static void reset_mitem_values(array &m, const array &c) { for (std::size_t i = 0; i != min(M, C); ++i) m[i].value = c[i]; } static void step_citem_past_empty_cell(unsigned &citem, const kc_item *const items, const uint8_t kc_item::*const next) { do { citem = items[citem].*next; } while (!items[citem].w2); } static window_event_result kconfig_key_command(window *, const d_event &event, kc_menu *menu) { int k; k = event_key_get(event); // when changing, process no keys instead of ESC if (menu->changing && (k != -2 && k != KEY_ESC)) return window_event_result::ignored; switch (k) { case KEY_CTRLED+KEY_D: menu->mitems[menu->citem].value = 255; return window_event_result::handled; case KEY_CTRLED+KEY_R: if ( menu->items==kc_keyboard ) reset_mitem_values(kcm_keyboard, DefaultKeySettings[0]); #if DXX_MAX_JOYSTICKS else if (menu->items == kc_joystick) reset_mitem_values(kcm_joystick, DefaultKeySettings[1]); #endif else if (menu->items == kc_mouse) reset_mitem_values(kcm_mouse, DefaultKeySettings[2]); else if (menu->items == kc_rebirth) reset_mitem_values(kcm_rebirth, DefaultKeySettingsRebirth); return window_event_result::handled; case KEY_DELETE: menu->mitems[menu->citem].value=255; return window_event_result::handled; case KEY_UP: case KEY_PAD8: step_citem_past_empty_cell(menu->citem, menu->items, &kc_item::u); return window_event_result::handled; case KEY_DOWN: case KEY_PAD2: step_citem_past_empty_cell(menu->citem, menu->items, &kc_item::d); return window_event_result::handled; case KEY_LEFT: case KEY_PAD4: step_citem_past_empty_cell(menu->citem, menu->items, &kc_item::l); return window_event_result::handled; case KEY_RIGHT: case KEY_PAD6: step_citem_past_empty_cell(menu->citem, menu->items, &kc_item::r); return window_event_result::handled; case KEY_ENTER: case KEY_PADENTER: kconfig_start_changing(menu); return window_event_result::handled; case -2: case KEY_ESC: if (menu->changing) menu->changing = 0; else { return window_event_result::close; } return window_event_result::handled; #ifdef TABLE_CREATION case KEY_F12: if (auto fp = PHYSFSX_openWriteBuffered("kconfig.cod")) { PHYSFSX_printf( fp, "const ubyte DefaultKeySettings[3][MAX_CONTROLS] = {\n" ); for (unsigned i=0; i<3; i++ ) { PHYSFSX_printf( fp, "{0x%2x", PlayerCfg.KeySettings[i][0] ); for (int j=1; jmouse_state = 0; break; case EVENT_MOUSE_BUTTON_DOWN: case EVENT_MOUSE_BUTTON_UP: if (menu->changing && (menu->items[menu->citem].type == BT_MOUSE_BUTTON) && (event.type == EVENT_MOUSE_BUTTON_UP)) { kc_change_mousebutton(*menu, event, menu->mitems[menu->citem] ); menu->mouse_state = (event.type == EVENT_MOUSE_BUTTON_DOWN); return window_event_result::handled; } if (event_mouse_get_button(event) == MBTN_RIGHT) { if (!menu->changing) { return window_event_result::close; } return window_event_result::handled; } else if (event_mouse_get_button(event) != MBTN_LEFT) return window_event_result::ignored; menu->mouse_state = (event.type == EVENT_MOUSE_BUTTON_DOWN); return kconfig_mouse(wind, event, menu); case EVENT_MOUSE_MOVED: if (menu->changing && menu->items[menu->citem].type == BT_MOUSE_AXIS) kc_change_mouseaxis(*menu, event, menu->mitems[menu->citem]); else event_mouse_get_delta( event, &menu->old_maxis[0], &menu->old_maxis[1], &menu->old_maxis[2]); break; #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK case EVENT_JOYSTICK_BUTTON_DOWN: if (menu->changing && menu->items[menu->citem].type == BT_JOY_BUTTON) kc_change_joybutton(*menu, event, menu->mitems[menu->citem]); break; #endif #if DXX_MAX_AXES_PER_JOYSTICK case EVENT_JOYSTICK_MOVED: if (menu->changing && menu->items[menu->citem].type == BT_JOY_AXIS) kc_change_joyaxis(*menu, event, menu->mitems[menu->citem]); else { const auto &av = event_joystick_get_axis(event); const auto &axis = av.axis; const auto &value = av.value; menu->old_jaxis[axis] = value; } break; #endif case EVENT_KEY_COMMAND: { window_event_result rval = kconfig_key_command(wind, event, menu); if (rval != window_event_result::ignored) return rval; if (menu->changing && menu->items[menu->citem].type == BT_KEY) kc_change_key(*menu, event, menu->mitems[menu->citem]); return window_event_result::ignored; } case EVENT_IDLE: kconfig_mouse(wind, event, menu); break; case EVENT_WINDOW_DRAW: if (menu->changing) timer_delay(f0_1/10); else timer_delay2(50); kconfig_draw(menu); break; case EVENT_WINDOW_CLOSE: delete menu; // Update save values... for (unsigned i=0; i < lengthof(kc_keyboard); i++ ) PlayerCfg.KeySettings[0][i] = kcm_keyboard[i].value; #if DXX_MAX_JOYSTICKS for (unsigned i=0; i < lengthof(kc_joystick); i++ ) PlayerCfg.KeySettings[1][i] = kcm_joystick[i].value; #endif for (unsigned i=0; i < lengthof(kc_mouse); i++ ) PlayerCfg.KeySettings[2][i] = kcm_mouse[i].value; for (unsigned i=0; i < lengthof(kc_rebirth); i++) PlayerCfg.KeySettingsRebirth[i] = kcm_rebirth[i].value; return window_event_result::ignored; // continue closing default: return window_event_result::ignored; } return window_event_result::handled; } } static void kconfig_sub(const char *litems, const kc_item * items,kc_mitem *mitems,int nitems, const char *title) { set_screen_mode(SCREEN_MENU); kc_set_controls(); kc_menu *menu = new kc_menu{}; menu->items = items; menu->litems = litems; menu->mitems = mitems; menu->nitems = nitems; menu->title = title; menu->citem = 0; if (!items[0].w2) step_citem_past_empty_cell(menu->citem, items, &kc_item::r); menu->changing = 0; menu->mouse_state = 0; const auto &&fspacx = FSPACX(); const auto &&fspacy = FSPACY(); if (!(menu->wind = window_create(grd_curscreen->sc_canvas, (SWIDTH - fspacx(320)) / 2, (SHEIGHT - fspacy(200)) / 2, fspacx(320), fspacy(200), kconfig_handler, menu))) delete menu; } template static void kconfig_sub(const char *litems, const kc_item (&items)[N], array &mitems, const char *title) { kconfig_sub(litems, items, mitems.data(), N, title); } static void kc_drawinput(grs_canvas &canvas, const kc_item &item, kc_mitem &mitem, const int is_current, const char *const label) { char buf[10]; const char *btext; const auto &&fspacx = FSPACX(); const auto &&fspacy = FSPACY(); unsigned r, g, b; if (label) { if (is_current) r = 20 * 2, g = 20 * 2, b = 29 * 2; else r = 15 * 2, g = 15 * 2, b = 24 * 2; gr_set_fontcolor(canvas, gr_find_closest_color(r, g, b), -1); gr_string(canvas, fspacx(item.x), fspacy(item.y), label); } btext = get_item_text(item, mitem, buf); if (!btext) return; { if (is_current) r = 21 * 2, g = 0, b = 24 * 2; else r = 16 * 2, g = 0, b = 19 * 2; int x, w, h; const uint8_t color = gr_find_closest_color(r, g, b); gr_get_string_size(*canvas.cv_font, btext, &w, &h, nullptr); const auto &&fspacx_item_xinput = fspacx(item.xinput); const auto &&fspacy_item_y = fspacy(item.y); gr_urect(canvas, fspacx_item_xinput, fspacy(item.y - 1), fspacx(item.xinput + item.w2), fspacy_item_y + h, color); gr_set_fontcolor(canvas, BM_XRGB(28, 28, 28), -1); x = fspacx_item_xinput + ((fspacx(item.w2) - w) / 2); gr_string(canvas, x, fspacy_item_y, btext, w, h); } } namespace dsx { static void kc_drawquestion(grs_canvas &canvas, kc_menu *const menu, const kc_item *const item) { #if defined(DXX_BUILD_DESCENT_I) const uint8_t color = gr_fade_table[fades[menu->q_fade_i]][BM_XRGB(21,0,24)]; #elif defined(DXX_BUILD_DESCENT_II) const uint8_t color = BM_XRGB(21*fades[menu->q_fade_i]/31,0,24*fades[menu->q_fade_i]/31); #endif menu->q_fade_i++; if (menu->q_fade_i>63) menu->q_fade_i=0; int w, h; gr_get_string_size(*canvas.cv_font, "?", &w, &h, nullptr); const auto &&fspacx = FSPACX(); const auto &&fspacy = FSPACY(); const auto &&fspacx_item_xinput = fspacx(item->xinput); const auto &&fspacy_item_y = fspacy(item->y); gr_urect(canvas, fspacx_item_xinput, fspacy(item->y - 1), fspacx(item->xinput + item->w2), fspacy_item_y + h, color); gr_set_fontcolor(canvas, BM_XRGB(28, 28, 28), -1); const auto x = fspacx_item_xinput + ((fspacx(item->w2) - w) / 2); gr_string(canvas, x, fspacy_item_y, "?", w, h); } } static void kc_set_exclusive_binding(kc_menu &menu, kc_mitem &mitem, unsigned type, unsigned value) { for (unsigned i=0; i < menu.nitems; i++ ) { if ( (&menu.mitems[i] != &mitem) && (menu.items[i].type==type) && (menu.mitems[i].value==value) ) { menu.mitems[i].value = 255; } } mitem.value = value; menu.changing = 0; } static void kc_change_key( kc_menu &menu,const d_event &event, kc_mitem &mitem ) { ubyte keycode = 255; Assert(event.type == EVENT_KEY_COMMAND); keycode = event_key_get_raw(event); auto e = end(system_keys); if (unlikely(CGameArg.CtlNoStickyKeys)) e = std::prev(e, 3); const auto predicate = [keycode](uint8_t k) { return keycode == k; }; if (std::any_of(begin(system_keys), e, predicate)) return; kc_set_exclusive_binding(menu, mitem, BT_KEY, keycode); } #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK static void kc_change_joybutton( kc_menu &menu,const d_event &event, kc_mitem &mitem ) { int button = 255; Assert(event.type == EVENT_JOYSTICK_BUTTON_DOWN); button = event_joystick_get_button(event); kc_set_exclusive_binding(menu, mitem, BT_JOY_BUTTON, button); } #endif static void kc_change_mousebutton( kc_menu &menu,const d_event &event, kc_mitem &mitem) { int button; Assert(event.type == EVENT_MOUSE_BUTTON_DOWN || event.type == EVENT_MOUSE_BUTTON_UP); button = event_mouse_get_button(event); kc_set_exclusive_binding(menu, mitem, BT_MOUSE_BUTTON, button); } #if DXX_MAX_AXES_PER_JOYSTICK static void kc_change_joyaxis( kc_menu &menu,const d_event &event, kc_mitem &mitem ) { const auto &av = event_joystick_get_axis(event); const auto &axis = av.axis; const auto &value = av.value; if ( abs(value-menu.old_jaxis[axis])<32 ) return; con_printf(CON_DEBUG, "Axis Movement detected: Axis %i", axis); kc_set_exclusive_binding(menu, mitem, BT_JOY_AXIS, axis); } #endif static void kc_change_mouseaxis( kc_menu &menu,const d_event &event, kc_mitem &mitem ) { int dx, dy, dz; Assert(event.type == EVENT_MOUSE_MOVED); event_mouse_get_delta( event, &dx, &dy, &dz ); uint8_t code; if (abs(dz) > 5) code = 2; else if (abs(dy) > 5) code = 1; else if (abs(dx) > 5) code = 0; else return; kc_set_exclusive_binding(menu, mitem, BT_MOUSE_AXIS, code); } static void kc_change_invert( kc_menu *menu, kc_mitem * item ) { if (item->value) item->value = 0; else item->value = 1; menu->changing = 0; // in case we were changing something else } void kconfig(const kconfig_type n) { switch (n) { #define kconfig_case(TYPE,TITLE) \ case kconfig_type::TYPE: \ kconfig_sub(kcl_##TYPE, kc_##TYPE, kcm_##TYPE, TITLE); \ break; kconfig_case(keyboard, "KEYBOARD"); #if DXX_MAX_JOYSTICKS kconfig_case(joystick, "JOYSTICK"); #endif kconfig_case(mouse, "MOUSE"); kconfig_case(rebirth, "WEAPON KEYS"); #undef kconfig_case default: Int3(); return; } } static void input_button_matched(const kc_item& item, int down) { if (item.state_bit) { if (!item.ci_state_ptr) throw std::logic_error("NULL state pointer with non-zero state bit"); if (down) Controls.state.*item.ci_state_ptr |= item.state_bit; else Controls.state.*item.ci_state_ptr &= ~item.state_bit; } else { if (item.ci_count_ptr != NULL && down) Controls.state.*item.ci_count_ptr += 1; } } template class F> static void adjust_ramped_keyboard_field(float& keydown_time, ubyte& state, fix& time, const float& sensitivity, const int& speed_factor, const int& speed_divisor = 1) #define adjust_ramped_keyboard_field(F, M, ...) \ (adjust_ramped_keyboard_field(Controls.down_time.M, Controls.state.M, __VA_ARGS__)) { if (state) { if (keydown_time < F1_0) keydown_time += (static_cast(FrameTime)*6.66)*(static_cast(sensitivity+1)/17); // values based on observation that the original game uses a keyboard ramp of 8 frames. Full sensitivity should reflect 60FPS behaviour, half sensitivity reflects 30FPS behaviour (give or take a frame). time = F()(time, speed_factor / speed_divisor * (keydown_time / F1_0)); } else keydown_time = 0; } template static void adjust_axis_field(fix& time, const array &axes, unsigned value, unsigned invert, const int& sensitivity) { if (value == 255) return; fix amount = (axes.at(value) * sensitivity) / 8; if ( !invert ) // If not inverted... time -= amount; else time += amount; } static void clamp_value(fix& value, const fix& lower, const fix& upper) { value = min(max(value, lower), upper); } static void clamp_symmetric_value(fix& value, const fix& bound) { clamp_value(value, -bound, bound); } #if DXX_MAX_AXES_PER_JOYSTICK static void convert_raw_joy_axis(const uint_fast32_t player_cfg_index, const uint_fast32_t i) { const auto raw_joy_axis = Controls.raw_joy_axis[i]; const auto joy_axis = (abs(raw_joy_axis) <= (128 * PlayerCfg.JoystickLinear[player_cfg_index]) / 16) ? (raw_joy_axis * (FrameTime * PlayerCfg.JoystickSpeed[player_cfg_index]) / 16) : (raw_joy_axis * FrameTime); Controls.joy_axis[i] = joy_axis / 128; } static void convert_raw_joy_axis(const uint_fast32_t kcm_index, const uint_fast32_t player_cfg_index, const uint_fast32_t i) { if (i != kcm_joystick[kcm_index].value) return; convert_raw_joy_axis(player_cfg_index, i); } #endif static inline void adjust_button_time(fix &o, uint8_t add, uint8_t sub, fix v) { if (add) { if (sub) return; o += v; } else if (sub) o -= v; } static void clamp_kconfig_control_with_overrun(fix &value, const fix &bound, fix &excess, const fix &ebound) { /* Assume no integer overflow here */ value += excess; const auto ivalue = value; clamp_symmetric_value(value, bound); excess = ivalue - value; clamp_symmetric_value(excess, ebound); } static unsigned allow_uncapped_turning() { const auto game_mode = Game_mode; if (!(game_mode & GM_MULTI)) return PlayerCfg.MouselookFlags & MouselookMode::Singleplayer; return PlayerCfg.MouselookFlags & Netgame.MouselookFlags & ((game_mode & GM_MULTI_COOP) ? MouselookMode::MPCoop : MouselookMode::MPAnarchy); } void kconfig_read_controls(const d_event &event, int automap_flag) { static fix64 mouse_delta_time = 0; #ifndef NDEBUG // --- Don't do anything if in debug mode --- if ( keyd_pressed[KEY_DELETE] ) { Controls = {}; return; } #endif Controls.pitch_time = Controls.vertical_thrust_time = Controls.heading_time = Controls.sideways_thrust_time = Controls.bank_time = Controls.forward_thrust_time = 0; const auto frametime = FrameTime; switch (event.type) { case EVENT_KEY_COMMAND: case EVENT_KEY_RELEASE: { const auto &&key = event_key_get_raw(event); if (key < 255) { for (uint_fast32_t i = 0; i < lengthof(kc_keyboard); i++) { if (kcm_keyboard[i].value == key) { input_button_matched(kc_keyboard[i], (event.type==EVENT_KEY_COMMAND)); } } if (!automap_flag && event.type == EVENT_KEY_COMMAND) for (uint_fast32_t i = 0, j = 0; i < 28; i += 3, j++) if (kcm_rebirth[i].value == key) { Controls.state.select_weapon = j+1; break; } } } break; #if DXX_MAX_BUTTONS_PER_JOYSTICK || DXX_MAX_HATS_PER_JOYSTICK case EVENT_JOYSTICK_BUTTON_DOWN: case EVENT_JOYSTICK_BUTTON_UP: if (!(PlayerCfg.ControlType & CONTROL_USING_JOYSTICK)) break; { const auto &&button = event_joystick_get_button(event); if (button < 255) { for (uint_fast32_t i = 0; i < lengthof(kc_joystick); i++) { if (kc_joystick[i].type == BT_JOY_BUTTON && kcm_joystick[i].value == button) { input_button_matched(kc_joystick[i], (event.type==EVENT_JOYSTICK_BUTTON_DOWN)); } } if (!automap_flag && event.type == EVENT_JOYSTICK_BUTTON_DOWN) for (uint_fast32_t i = 1, j = 0; i < 29; i += 3, j++) if (kcm_rebirth[i].value == button) { Controls.state.select_weapon = j+1; break; } } break; } #endif case EVENT_MOUSE_BUTTON_DOWN: case EVENT_MOUSE_BUTTON_UP: if (!(PlayerCfg.ControlType & CONTROL_USING_MOUSE)) break; { const auto &&button = event_mouse_get_button(event); if (button < 255) { for (uint_fast32_t i = 0; i < lengthof(kc_mouse); i++) { if (kc_mouse[i].type == BT_MOUSE_BUTTON && kcm_mouse[i].value == button) { input_button_matched(kc_mouse[i], (event.type==EVENT_MOUSE_BUTTON_DOWN)); } } if (!automap_flag && event.type == EVENT_MOUSE_BUTTON_DOWN) for (uint_fast32_t i = 2, j = 0; i < 30; i += 3, j++) if (kcm_rebirth[i].value == button) { Controls.state.select_weapon = j+1; break; } } } break; #if DXX_MAX_AXES_PER_JOYSTICK case EVENT_JOYSTICK_MOVED: { int joy_null_value = 0; if (!(PlayerCfg.ControlType & CONTROL_USING_JOYSTICK)) break; const auto &av = event_joystick_get_axis(event); const auto &axis = av.axis; auto value = av.value; if (axis == kcm_joystick[13].value) // Pitch U/D Deadzone joy_null_value = PlayerCfg.JoystickDead[1]*8; else if (axis == kcm_joystick[15].value) // Turn L/R Deadzone joy_null_value = PlayerCfg.JoystickDead[0]*8; else if (axis == kcm_joystick[17].value) // Slide L/R Deadzone joy_null_value = PlayerCfg.JoystickDead[2]*8; else if (axis == kcm_joystick[19].value) // Slide U/D Deadzone joy_null_value = PlayerCfg.JoystickDead[3]*8; else if (axis == kcm_joystick[21].value) // Bank Deadzone joy_null_value = PlayerCfg.JoystickDead[4]*8; else if (axis == kcm_joystick[23].value) // Throttle - default deadzone joy_null_value = PlayerCfg.JoystickDead[5]*3; if (value > joy_null_value) value = ((value - joy_null_value) * 128) / (128 - joy_null_value); else if (value < -joy_null_value) value = ((value + joy_null_value) * 128) / (128 - joy_null_value); else value = 0; Controls.raw_joy_axis[axis] = value; break; } #endif case EVENT_MOUSE_MOVED: { if (!(PlayerCfg.ControlType & CONTROL_USING_MOUSE)) break; if (PlayerCfg.MouseFlightSim) { int ax[3]; event_mouse_get_delta( event, &ax[0], &ax[1], &ax[2] ); for (uint_fast32_t i = 0; i <= 2; i++) { int mouse_null_value = (i==2?16:PlayerCfg.MouseFSDead*8); Controls.raw_mouse_axis[i] += ax[i]; clamp_symmetric_value(Controls.raw_mouse_axis[i], MOUSEFS_DELTA_RANGE); if (Controls.raw_mouse_axis[i] > mouse_null_value) Controls.mouse_axis[i] = (((Controls.raw_mouse_axis[i] - mouse_null_value) * MOUSEFS_DELTA_RANGE) / (MOUSEFS_DELTA_RANGE - mouse_null_value) * frametime) / MOUSEFS_DELTA_RANGE; else if (Controls.raw_mouse_axis[i] < -mouse_null_value) Controls.mouse_axis[i] = (((Controls.raw_mouse_axis[i] + mouse_null_value) * MOUSEFS_DELTA_RANGE) / (MOUSEFS_DELTA_RANGE - mouse_null_value) * frametime) / MOUSEFS_DELTA_RANGE; else Controls.mouse_axis[i] = 0; } } else { event_mouse_get_delta( event, &Controls.raw_mouse_axis[0], &Controls.raw_mouse_axis[1], &Controls.raw_mouse_axis[2] ); Controls.mouse_axis[0] = (Controls.raw_mouse_axis[0] * frametime) / 8; Controls.mouse_axis[1] = (Controls.raw_mouse_axis[1] * frametime) / 8; Controls.mouse_axis[2] = (Controls.raw_mouse_axis[2] * frametime); mouse_delta_time = timer_query() + DESIGNATED_GAME_FRAMETIME; } break; } case EVENT_IDLE: default: if (!PlayerCfg.MouseFlightSim && mouse_delta_time < timer_query()) { Controls.mouse_axis[0] = Controls.mouse_axis[1] = Controls.mouse_axis[2] = 0; mouse_delta_time = timer_query() + DESIGNATED_GAME_FRAMETIME; } break; } #if DXX_MAX_AXES_PER_JOYSTICK for (int i = 0; i < JOY_MAX_AXES; i++) { convert_raw_joy_axis(15, 0, i); // Turn L/R convert_raw_joy_axis(13, 1, i); // Pitch U/D convert_raw_joy_axis(17, 2, i); // Slide L/R convert_raw_joy_axis(19, 3, i); // Slide U/D convert_raw_joy_axis(21, 4, i); // Bank convert_raw_joy_axis(23, 5, i); // Throttle } #endif const auto speed_factor = (cheats.turbo ? 2 : 1) * frametime; //------------ Read pitch_time ----------- if ( !Controls.state.slide_on ) { // From keyboard... adjust_ramped_keyboard_field(plus, key_pitch_forward, Controls.pitch_time, PlayerCfg.KeyboardSens[1], speed_factor, 2); adjust_ramped_keyboard_field(minus, key_pitch_backward, Controls.pitch_time, PlayerCfg.KeyboardSens[1], speed_factor, 2); // From joystick... #if DXX_MAX_AXES_PER_JOYSTICK adjust_axis_field(Controls.pitch_time, Controls.joy_axis, kcm_joystick[13].value, kcm_joystick[14].value, PlayerCfg.JoystickSens[1]); #endif // From mouse... adjust_axis_field(Controls.pitch_time, Controls.mouse_axis, kcm_mouse[13].value, kcm_mouse[14].value, PlayerCfg.MouseSens[1]); } else Controls.pitch_time = 0; //----------- Read vertical_thrust_time ----------------- if ( Controls.state.slide_on ) { // From keyboard... adjust_ramped_keyboard_field(plus, key_pitch_forward, Controls.vertical_thrust_time, PlayerCfg.KeyboardSens[3], speed_factor); adjust_ramped_keyboard_field(minus, key_pitch_backward, Controls.vertical_thrust_time, PlayerCfg.KeyboardSens[3], speed_factor); // From joystick... // NOTE: Use Slide U/D invert setting #if DXX_MAX_AXES_PER_JOYSTICK adjust_axis_field(Controls.vertical_thrust_time, Controls.joy_axis, kcm_joystick[13].value, !kcm_joystick[20].value, PlayerCfg.JoystickSens[3]); #endif // From mouse... adjust_axis_field(Controls.vertical_thrust_time, Controls.mouse_axis, kcm_mouse[13].value, kcm_mouse[20].value, PlayerCfg.MouseSens[3]); } // From keyboard... adjust_ramped_keyboard_field(plus, key_slide_up, Controls.vertical_thrust_time, PlayerCfg.KeyboardSens[3], speed_factor); adjust_ramped_keyboard_field(minus, key_slide_down, Controls.vertical_thrust_time, PlayerCfg.KeyboardSens[3], speed_factor); // From buttons... adjust_button_time(Controls.vertical_thrust_time, Controls.state.btn_slide_up, Controls.state.btn_slide_down, speed_factor); // From joystick... #if DXX_MAX_AXES_PER_JOYSTICK adjust_axis_field(Controls.vertical_thrust_time, Controls.joy_axis, kcm_joystick[19].value, !kcm_joystick[20].value, PlayerCfg.JoystickSens[3]); #endif // From mouse... adjust_axis_field(Controls.vertical_thrust_time, Controls.mouse_axis, kcm_mouse[19].value, !kcm_mouse[20].value, PlayerCfg.MouseSens[3]); //---------- Read heading_time ----------- if (!Controls.state.slide_on && !Controls.state.bank_on) { // From keyboard... adjust_ramped_keyboard_field(plus, key_heading_right, Controls.heading_time, PlayerCfg.KeyboardSens[0], speed_factor); adjust_ramped_keyboard_field(minus, key_heading_left, Controls.heading_time, PlayerCfg.KeyboardSens[0], speed_factor); // From joystick... #if DXX_MAX_AXES_PER_JOYSTICK adjust_axis_field(Controls.heading_time, Controls.joy_axis, kcm_joystick[15].value, !kcm_joystick[16].value, PlayerCfg.JoystickSens[0]); #endif // From mouse... adjust_axis_field(Controls.heading_time, Controls.mouse_axis, kcm_mouse[15].value, !kcm_mouse[16].value, PlayerCfg.MouseSens[0]); } else Controls.heading_time = 0; //----------- Read sideways_thrust_time ----------------- if ( Controls.state.slide_on ) { // From keyboard... adjust_ramped_keyboard_field(plus, key_heading_right, Controls.sideways_thrust_time, PlayerCfg.KeyboardSens[2], speed_factor); adjust_ramped_keyboard_field(minus, key_heading_left, Controls.sideways_thrust_time, PlayerCfg.KeyboardSens[2], speed_factor); // From joystick... #if DXX_MAX_AXES_PER_JOYSTICK adjust_axis_field(Controls.sideways_thrust_time, Controls.joy_axis, kcm_joystick[15].value, !kcm_joystick[18].value, PlayerCfg.JoystickSens[2]); #endif // From mouse... adjust_axis_field(Controls.sideways_thrust_time, Controls.mouse_axis, kcm_mouse[15].value, !kcm_mouse[18].value, PlayerCfg.MouseSens[2]); } // From keyboard... adjust_ramped_keyboard_field(plus, key_slide_right, Controls.sideways_thrust_time, PlayerCfg.KeyboardSens[2], speed_factor); adjust_ramped_keyboard_field(minus, key_slide_left, Controls.sideways_thrust_time, PlayerCfg.KeyboardSens[2], speed_factor); // From buttons... adjust_button_time(Controls.sideways_thrust_time, Controls.state.btn_slide_right, Controls.state.btn_slide_left, speed_factor); // From joystick... #if DXX_MAX_AXES_PER_JOYSTICK adjust_axis_field(Controls.sideways_thrust_time, Controls.joy_axis, kcm_joystick[17].value, !kcm_joystick[18].value, PlayerCfg.JoystickSens[2]); #endif // From mouse... adjust_axis_field(Controls.sideways_thrust_time, Controls.mouse_axis, kcm_mouse[17].value, !kcm_mouse[18].value, PlayerCfg.MouseSens[2]); //----------- Read bank_time ----------------- if ( Controls.state.bank_on ) { // From keyboard... adjust_ramped_keyboard_field(plus, key_heading_left, Controls.bank_time, PlayerCfg.KeyboardSens[4], speed_factor); adjust_ramped_keyboard_field(minus, key_heading_right, Controls.bank_time, PlayerCfg.KeyboardSens[4], speed_factor); // From joystick... #if DXX_MAX_AXES_PER_JOYSTICK adjust_axis_field(Controls.bank_time, Controls.joy_axis, kcm_joystick[15].value, kcm_joystick[22].value, PlayerCfg.JoystickSens[4]); #endif // From mouse... adjust_axis_field(Controls.bank_time, Controls.mouse_axis, kcm_mouse[15].value, !kcm_mouse[22].value, PlayerCfg.MouseSens[4]); } // From keyboard... adjust_ramped_keyboard_field(plus, key_bank_left, Controls.bank_time, PlayerCfg.KeyboardSens[4], speed_factor); adjust_ramped_keyboard_field(minus, key_bank_right, Controls.bank_time, PlayerCfg.KeyboardSens[4], speed_factor); // From buttons... adjust_button_time(Controls.bank_time, Controls.state.btn_bank_left, Controls.state.btn_bank_right, speed_factor); // From joystick... #if DXX_MAX_AXES_PER_JOYSTICK adjust_axis_field(Controls.bank_time, Controls.joy_axis, kcm_joystick[21].value, kcm_joystick[22].value, PlayerCfg.JoystickSens[4]); #endif // From mouse... adjust_axis_field(Controls.bank_time, Controls.mouse_axis, kcm_mouse[21].value, !kcm_mouse[22].value, PlayerCfg.MouseSens[4]); //----------- Read forward_thrust_time ------------- // From keyboard/buttons... adjust_button_time(Controls.forward_thrust_time, Controls.state.accelerate, Controls.state.reverse, speed_factor); // From joystick... #if DXX_MAX_AXES_PER_JOYSTICK adjust_axis_field(Controls.forward_thrust_time, Controls.joy_axis, kcm_joystick[23].value, kcm_joystick[24].value, PlayerCfg.JoystickSens[5]); #endif // From mouse... adjust_axis_field(Controls.forward_thrust_time, Controls.mouse_axis, kcm_mouse[23].value, kcm_mouse[24].value, PlayerCfg.MouseSens[5]); //----------- Read cruise-control-type of throttle. if ( Controls.state.cruise_off > 0 ) Controls.state.cruise_off = Cruise_speed = 0; else { adjust_button_time(Cruise_speed, Controls.state.cruise_plus, Controls.state.cruise_minus, speed_factor * 80); clamp_value(Cruise_speed, 0, i2f(100)); if (Controls.forward_thrust_time == 0) Controls.forward_thrust_time = fixmul(Cruise_speed, frametime) / 100; } //----------- Clamp values between -FrameTime and FrameTime clamp_kconfig_control_with_overrun(Controls.vertical_thrust_time, frametime, Controls.excess_vertical_thrust_time, frametime * PlayerCfg.MouseOverrun[3]); clamp_kconfig_control_with_overrun(Controls.sideways_thrust_time, frametime, Controls.excess_sideways_thrust_time, frametime * PlayerCfg.MouseOverrun[2]); clamp_kconfig_control_with_overrun(Controls.forward_thrust_time, frametime, Controls.excess_forward_thrust_time, frametime * PlayerCfg.MouseOverrun[5]); if (!allow_uncapped_turning()) { clamp_kconfig_control_with_overrun(Controls.pitch_time, frametime / 2, Controls.excess_pitch_time, frametime * PlayerCfg.MouseOverrun[1]); clamp_kconfig_control_with_overrun(Controls.heading_time, frametime, Controls.excess_heading_time, frametime * PlayerCfg.MouseOverrun[0]); clamp_kconfig_control_with_overrun(Controls.bank_time, frametime, Controls.excess_bank_time, frametime * PlayerCfg.MouseOverrun[4]); } } void reset_cruise(void) { Cruise_speed=0; } void kc_set_controls() { for (unsigned i=0; i < lengthof(kc_keyboard); i++ ) kcm_keyboard[i].value = PlayerCfg.KeySettings[0][i]; #if DXX_MAX_JOYSTICKS for (unsigned i=0; i < lengthof(kc_joystick); i++ ) { kcm_joystick[i].value = PlayerCfg.KeySettings[1][i]; if (kc_joystick[i].type == BT_INVERT ) { if (kcm_joystick[i].value!=1) kcm_joystick[i].value = 0; PlayerCfg.KeySettings[1][i] = kcm_joystick[i].value; } } #endif for (unsigned i=0; i < lengthof(kc_mouse); i++ ) { kcm_mouse[i].value = PlayerCfg.KeySettings[2][i]; if (kc_mouse[i].type == BT_INVERT ) { if (kcm_mouse[i].value!=1) kcm_mouse[i].value = 0; PlayerCfg.KeySettings[2][i] = kcm_mouse[i].value; } } for (unsigned i=0; i < lengthof(kc_rebirth); i++ ) kcm_rebirth[i].value = PlayerCfg.KeySettingsRebirth[i]; }