diff --git a/sc2/ChangeLog b/sc2/ChangeLog index 564a2be44..ff12c8095 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,5 @@ Changes towards version 0.6: +- Online key configuration menu actually functional now - Michael - Tweak to Lander UI - Special Weapon is now explicitly Lander Escape, just as Warp Escape is - Michael - Default key configuration changed slightly; online display of current diff --git a/sc2/content/lbm/setupmenu.txt b/sc2/content/lbm/setupmenu.txt index cfa4ce588..6ca74135f 100644 --- a/sc2/content/lbm/setupmenu.txt +++ b/sc2/content/lbm/setupmenu.txt @@ -478,6 +478,7 @@ Return to control set selection screen. Incomplete Keyconfig header Editkey header +Editkey dialog #(LABEL_0) This part of the configuration @@ -490,7 +491,12 @@ To view or edit key controls, select the option below: #(LABEL_2) -Controls +Press Return to edit, or Delete to remove + +#(LABEL_3) +Please press the key, button, +or joystick direction you wish +to assign to this action. #(TEXT_ENTRIES) Name diff --git a/sc2/content/starcon.key b/sc2/content/starcon.key index 3e2764842..53f448105 100644 --- a/sc2/content/starcon.key +++ b/sc2/content/starcon.key @@ -1,7 +1,7 @@ # Default UQM input configuration file. -# This is a VCONTROL version 3 config file (UQM 0.5.1 or later). -version 3 +# This is a VCONTROL version 4 config file (UQM 0.5.3 or later). +version 4 # Keyboard control definitions follow this point. Most keys can be # described in a straightforward manner; consult the name table in @@ -63,57 +63,56 @@ Exit: key F10 # Super Melee and the player in the full game. Again, the player has # the option of using either the number pad or the arrow keys. -Keyboard-1-Up: key Up -Keyboard-1-Down: key Down -Keyboard-1-Left: key Left -Keyboard-1-Right: key Right -Keyboard-1-Weapon: key RightControl -Keyboard-1-Special: key RightShift +Template-1-Up: key Up +Template-1-Down: key Down +Template-1-Left: key Left +Template-1-Right: key Right +Template-1-Weapon: key RightControl +Template-1-Special: key RightShift -Keyboard-1-Up: key Keypad-8 -Keyboard-1-Down: key Keypad-2 -Keyboard-1-Left: key Keypad-4 -Keyboard-1-Right: key Keypad-6 -Keyboard-1-Weapon: key Keypad-Enter -Keyboard-1-Special: key Keypad-0 +Template-1-Up: key Keypad-8 +Template-1-Down: key Keypad-2 +Template-1-Left: key Keypad-4 +Template-1-Right: key Keypad-6 +Template-1-Weapon: key Keypad-Enter +Template-1-Special: key Keypad-0 -Keyboard-1-Escape: key Escape +Template-1-Escape: key Escape # WASD for Player 2's default flight controls. We add the key 'd' to # let him move down in the super-melee ship selection. -Keyboard-2-Up: key w -Keyboard-2-Down: key s -Keyboard-2-Left: key a -Keyboard-2-Right: key d -Keyboard-2-Weapon: key v -Keyboard-2-Special: key b -Keyboard-2-Escape: key Escape +Template-2-Up: key w +Template-2-Down: key s +Template-2-Left: key a +Template-2-Right: key d +Template-2-Weapon: key v +Template-2-Special: key b +Template-2-Escape: key Escape # Control Scheme 3: Variant Arrow keys with brackets for firing. -Keyboard-3-Up: key Keypad-8 -Keyboard-3-Down: key Keypad-2 -Keyboard-3-Left: key Keypad-4 -Keyboard-3-Right: key Keypad-6 -Keyboard-3-Up: key Up -Keyboard-3-Down: key Down -Keyboard-3-Left: key Left -Keyboard-3-Right: key Right -Keyboard-3-Weapon: key ] -Keyboard-3-Special: key [ -Keyboard-3-Escape: key Escape - +Template-3-Up: key Keypad-8 +Template-3-Down: key Keypad-2 +Template-3-Left: key Keypad-4 +Template-3-Right: key Keypad-6 +Template-3-Up: key Up +Template-3-Down: key Down +Template-3-Left: key Left +Template-3-Right: key Right +Template-3-Weapon: key ] +Template-3-Special: key [ +Template-3-Escape: key Escape # Control Scheme 4: Shifted WASD keys. -Joystick-1-Up: key e -Joystick-1-Down: key d -Joystick-1-Left: key s -Joystick-1-Right: key f -Joystick-1-Weapon: key q -Joystick-1-Special: key a -Joystick-1-Escape: key Escape +Template-4-Up: key e +Template-4-Down: key d +Template-4-Left: key s +Template-4-Right: key f +Template-4-Weapon: key q +Template-4-Special: key a +Template-4-Escape: key Escape # This is a sample joystick configuration. This is intended to work # primarily under WinXP with a USB analog/digital gamepad. The @@ -125,19 +124,19 @@ Joystick-1-Escape: key Escape joystick 0 threshold 10000 # How far to move before it counts; 0-30000 -Joystick-2-Up: joystick 0 axis 1 negative -Joystick-2-Down: joystick 0 axis 1 positive -Joystick-2-Left: joystick 0 axis 0 negative -Joystick-2-Right: joystick 0 axis 0 positive +Template-5-Up: joystick 0 axis 1 negative +Template-5-Down: joystick 0 axis 1 positive +Template-5-Left: joystick 0 axis 0 negative +Template-5-Right: joystick 0 axis 0 positive -Joystick-2-Up: joystick 0 hat 0 up -Joystick-2-Down: joystick 0 hat 0 down -Joystick-2-Left: joystick 0 hat 0 left -Joystick-2-Right: joystick 0 hat 0 right +Template-5-Up: joystick 0 hat 0 up +Template-5-Down: joystick 0 hat 0 down +Template-5-Left: joystick 0 hat 0 left +Template-5-Right: joystick 0 hat 0 right -Joystick-2-Weapon: joystick 0 button 1 -Joystick-2-Special: joystick 0 button 0 -Joystick-2-Escape: joystick 0 button 6 +Template-5-Weapon: joystick 0 button 0 +Template-5-Special: joystick 0 button 1 +Template-5-Escape: key Escape Menu-Up: joystick 0 axis 1 negative Menu-Down: joystick 0 axis 1 positive @@ -149,28 +148,25 @@ Menu-Down: joystick 0 hat 0 down Menu-Left: joystick 0 hat 0 left Menu-Right: joystick 0 hat 0 right -Menu-Cancel: joystick 0 button 0 -Menu-Select: joystick 0 button 1 -Menu-Page-Up: joystick 0 button 4 -Menu-Page-Down: joystick 0 button 5 -Menu-Zoom-In: joystick 0 button 6 -Menu-Zoom-Out: joystick 0 button 7 +Menu-Cancel: joystick 0 button 1 +Menu-Select: joystick 0 button 0 joystick 1 threshold 10000 # How far to move before it counts; 0-30000 -Joystick-3-Up: joystick 1 axis 1 negative -Joystick-3-Down: joystick 1 axis 1 positive -Joystick-3-Left: joystick 1 axis 0 negative -Joystick-3-Right: joystick 1 axis 0 positive +Template-6-Up: joystick 1 axis 1 negative +Template-6-Down: joystick 1 axis 1 positive +Template-6-Left: joystick 1 axis 0 negative +Template-6-Right: joystick 1 axis 0 positive -Joystick-3-Up: joystick 1 hat 0 up -Joystick-3-Down: joystick 1 hat 0 down -Joystick-3-Left: joystick 1 hat 0 left -Joystick-3-Right: joystick 1 hat 0 right +Template-6-Up: joystick 1 hat 0 up +Template-6-Down: joystick 1 hat 0 down +Template-6-Left: joystick 1 hat 0 left +Template-6-Right: joystick 1 hat 0 right -Joystick-3-Weapon: joystick 1 button 1 -Joystick-3-Special: joystick 1 button 0 -Joystick-3-Escape: joystick 1 button 6 +Template-6-Weapon: joystick 1 button 0 +Template-6-Special: joystick 1 button 1 + +Template-6-Escape: key Escape Menu-Up: joystick 1 axis 1 negative Menu-Down: joystick 1 axis 1 positive @@ -182,9 +178,5 @@ Menu-Down: joystick 1 hat 0 down Menu-Left: joystick 1 hat 0 left Menu-Right: joystick 1 hat 0 right -Menu-Cancel: joystick 1 button 0 -Menu-Select: joystick 1 button 1 -Menu-Page-Up: joystick 1 button 4 -Menu-Page-Down: joystick 1 button 5 -Menu-Zoom-In: joystick 1 button 6 -Menu-Zoom-Out: joystick 1 button 7 +Menu-Cancel: joystick 1 button 1 +Menu-Select: joystick 1 button 0 diff --git a/sc2/src/sc2code/libs/graphics/widgets.c b/sc2/src/sc2code/libs/graphics/widgets.c index cb31a6de6..3b1884a59 100644 --- a/sc2/src/sc2code/libs/graphics/widgets.c +++ b/sc2/src/sc2code/libs/graphics/widgets.c @@ -1,5 +1,6 @@ #include "graphics/gfx_common.h" #include "graphics/widgets.h" +#include "strlib.h" #include "setup.h" #include "units.h" @@ -10,6 +11,8 @@ WIDGET *widget_focus = NULL; #define WIDGET_INACTIVE_COLOR BUILD_COLOR (MAKE_RGB15 (0x18, 0x18, 0x1F), 0x09) #define WIDGET_INACTIVE_SELECTED_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) #define WIDGET_CURSOR_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00) +#define WIDGET_DIALOG_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x14), 0x07) +#define WIDGET_DIALOG_TEXT_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00) void DrawShadowedBox(PRECT r, COLOR bg, COLOR dark, COLOR medium) @@ -50,6 +53,59 @@ DrawShadowedBox(PRECT r, COLOR bg, COLOR dark, COLOR medium) UnbatchGraphics (); } +void +DrawLabelAsWindow(WIDGET_LABEL *label) +{ + COLOR oldfg = SetContextForeGroundColor (WIDGET_DIALOG_TEXT_COLOR); + COLOR dark, medium; + FONT oldfont = SetContextFont (StarConFont); + FRAME oldFontEffect = SetContextFontEffect (NULL); + RECT r; + TEXT t; + int i, win_w, win_h; + + dark = BUILD_COLOR (MAKE_RGB15 (0x8, 0x8, 0x8), 0x1F); + medium = BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19); + + /* Compute the dimensions of the label */ + win_h = label->height ((WIDGET *)label) + 16; + win_w = 0; + for (i = 0; i < label->line_count; i++) + { + int len = utf8StringCount (label->lines[i]); + if (len > win_w) + { + win_w = len; + } + } + win_w = (win_w * 6) + 16; + + BatchGraphics (); + r.corner.x = (SCREEN_WIDTH - win_w) >> 1; + r.corner.y = (SCREEN_HEIGHT - win_h) >> 1; + r.extent.width = win_w; + r.extent.height = win_h; + DrawShadowedBox (&r, WIDGET_DIALOG_COLOR, dark, medium); + + t.baseline.x = r.corner.x + (r.extent.width >> 1); + t.baseline.y = r.corner.y + 16; + for (i = 0; i < label->line_count; i++) + { + t.pStr = label->lines[i]; + t.align = ALIGN_CENTER; + t.valign = VALIGN_BOTTOM; + t.CharCount = (COUNT)~0; + font_DrawText (&t); + t.baseline.y += 8; + } + + UnbatchGraphics (); + + SetContextFontEffect (oldFontEffect); + SetContextFont (oldfont); + SetContextForeGroundColor (oldfg); +} + static void Widget_DrawToolTips (int numlines, const char **tips) { @@ -769,13 +825,25 @@ Widget_HandleEventControlEntry (WIDGET *_self, int event) WIDGET_CONTROLENTRY *self = (WIDGET_CONTROLENTRY *)_self; if (event == WIDGET_EVENT_SELECT) { - /* TODO: Something. */ - (void)self; + if (self->onChange) + { + (self->onChange)(self); + return TRUE; + } + } + if (event == WIDGET_EVENT_DELETE) + { + if (self->onDelete) + { + (self->onDelete)(self); + return TRUE; + } } if ((event == WIDGET_EVENT_RIGHT) || (event == WIDGET_EVENT_LEFT)) { self->highlighted = 1-self->highlighted; + return TRUE; } return FALSE; } diff --git a/sc2/src/sc2code/libs/graphics/widgets.h b/sc2/src/sc2code/libs/graphics/widgets.h index 45e0ad00e..854086465 100644 --- a/sc2/src/sc2code/libs/graphics/widgets.h +++ b/sc2/src/sc2code/libs/graphics/widgets.h @@ -28,6 +28,7 @@ enum { WIDGET_EVENT_RIGHT, WIDGET_EVENT_SELECT, WIDGET_EVENT_CANCEL, + WIDGET_EVENT_DELETE, NUM_WIDGET_EVENTS }; @@ -166,12 +167,16 @@ typedef struct _widget_controlentry { void (*draw)(struct _widget *self, int x, int y); int (*height)(struct _widget *self); int (*width)(struct _widget *self); + void (*onChange)(struct _widget_controlentry *self); + void (*onDelete)(struct _widget_controlentry *self); const char *category; + int controlindex; int highlighted; char controlname[2][WIDGET_CONTROLENTRY_WIDTH]; } WIDGET_CONTROLENTRY; void DrawShadowedBox (PRECT r, COLOR bg, COLOR dark, COLOR medium); +void DrawLabelAsWindow(WIDGET_LABEL *label); int Widget_Event (int event); diff --git a/sc2/src/sc2code/libs/inplib.h b/sc2/src/sc2code/libs/inplib.h index 7b3ea80b1..d898d71b7 100644 --- a/sc2/src/sc2code/libs/inplib.h +++ b/sc2/src/sc2code/libs/inplib.h @@ -21,6 +21,7 @@ #include "memlib.h" #include +#include "libs/uio.h" typedef DWORD INPUT_STATE; @@ -49,6 +50,10 @@ wchar_t GetLastCharacter (void); /* Interrogating the current key configuration */ void InterrogateInputState (int template, int control, int index, char *buffer, int maxlen); +void RemoveInputState (int template, int control, int index); +void RebindInputState (int template, int control, int index); + +void SaveKeyConfiguration (uio_DirHandle *path, const char *fname); #endif /* _INPLIB_H */ diff --git a/sc2/src/sc2code/libs/input/sdl/input.c b/sc2/src/sc2code/libs/input/sdl/input.c index ffd0634dd..2a5814e18 100644 --- a/sc2/src/sc2code/libs/input/sdl/input.c +++ b/sc2/src/sc2code/libs/input/sdl/input.c @@ -27,6 +27,7 @@ #include "controls.h" #include "libs/file.h" #include "libs/log.h" +#include "libs/reslib.h" #include "options.h" @@ -40,7 +41,7 @@ static BOOLEAN InputInitialized = FALSE; static BOOLEAN _in_character_mode = FALSE; -#define VCONTROL_VERSION 3 +#define VCONTROL_VERSION 4 static VControl_NameBinding control_names[] = { { "Menu-Up", (int *)&ImmediateInputState.menu[KEY_MENU_UP] }, @@ -61,48 +62,48 @@ static VControl_NameBinding control_names[] = { { "Menu-Edit-Cancel", (int *)&ImmediateInputState.menu[KEY_MENU_EDIT_CANCEL] }, { "Menu-Search", (int *)&ImmediateInputState.menu[KEY_MENU_SEARCH] }, { "Menu-Next", (int *)&ImmediateInputState.menu[KEY_MENU_NEXT] }, - { "Keyboard-1-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_UP] }, - { "Keyboard-1-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_DOWN] }, - { "Keyboard-1-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_LEFT] }, - { "Keyboard-1-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_RIGHT] }, - { "Keyboard-1-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_WEAPON] }, - { "Keyboard-1-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_SPECIAL] }, - { "Keyboard-1-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_ESCAPE] }, - { "Keyboard-2-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_UP] }, - { "Keyboard-2-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_DOWN] }, - { "Keyboard-2-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_LEFT] }, - { "Keyboard-2-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_RIGHT] }, - { "Keyboard-2-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_WEAPON] }, - { "Keyboard-2-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_SPECIAL] }, - { "Keyboard-2-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_ESCAPE] }, - { "Keyboard-3-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_UP] }, - { "Keyboard-3-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_DOWN] }, - { "Keyboard-3-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_LEFT] }, - { "Keyboard-3-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_RIGHT] }, - { "Keyboard-3-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_WEAPON] }, - { "Keyboard-3-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_SPECIAL] }, - { "Keyboard-3-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_ESCAPE] }, - { "Joystick-1-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_UP] }, - { "Joystick-1-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_DOWN] }, - { "Joystick-1-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_LEFT] }, - { "Joystick-1-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_RIGHT] }, - { "Joystick-1-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_WEAPON] }, - { "Joystick-1-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_SPECIAL] }, - { "Joystick-1-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_ESCAPE] }, - { "Joystick-2-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_UP] }, - { "Joystick-2-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_DOWN] }, - { "Joystick-2-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_LEFT] }, - { "Joystick-2-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_RIGHT] }, - { "Joystick-2-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_WEAPON] }, - { "Joystick-2-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_SPECIAL] }, - { "Joystick-2-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_ESCAPE] }, - { "Joystick-3-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_UP] }, - { "Joystick-3-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_DOWN] }, - { "Joystick-3-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_LEFT] }, - { "Joystick-3-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_RIGHT] }, - { "Joystick-3-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_WEAPON] }, - { "Joystick-3-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_SPECIAL] }, - { "Joystick-3-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_ESCAPE] }, + { "Template-1-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_UP] }, + { "Template-1-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_DOWN] }, + { "Template-1-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_LEFT] }, + { "Template-1-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_RIGHT] }, + { "Template-1-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_WEAPON] }, + { "Template-1-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_SPECIAL] }, + { "Template-1-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_ESCAPE] }, + { "Template-2-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_UP] }, + { "Template-2-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_DOWN] }, + { "Template-2-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_LEFT] }, + { "Template-2-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_RIGHT] }, + { "Template-2-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_WEAPON] }, + { "Template-2-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_SPECIAL] }, + { "Template-2-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_ESCAPE] }, + { "Template-3-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_UP] }, + { "Template-3-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_DOWN] }, + { "Template-3-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_LEFT] }, + { "Template-3-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_RIGHT] }, + { "Template-3-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_WEAPON] }, + { "Template-3-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_SPECIAL] }, + { "Template-3-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_ESCAPE] }, + { "Template-4-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_UP] }, + { "Template-4-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_DOWN] }, + { "Template-4-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_LEFT] }, + { "Template-4-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_RIGHT] }, + { "Template-4-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_WEAPON] }, + { "Template-4-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_SPECIAL] }, + { "Template-4-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_ESCAPE] }, + { "Template-5-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_UP] }, + { "Template-5-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_DOWN] }, + { "Template-5-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_LEFT] }, + { "Template-5-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_RIGHT] }, + { "Template-5-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_WEAPON] }, + { "Template-5-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_SPECIAL] }, + { "Template-5-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_ESCAPE] }, + { "Template-6-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_UP] }, + { "Template-6-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_DOWN] }, + { "Template-6-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_LEFT] }, + { "Template-6-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_RIGHT] }, + { "Template-6-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_WEAPON] }, + { "Template-6-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_SPECIAL] }, + { "Template-6-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_ESCAPE] }, { "Pause", (int *)&ImmediateInputState.menu[KEY_PAUSE] }, { "Exit", (int *)&ImmediateInputState.menu[KEY_EXIT] }, { "Abort", (int *)&ImmediateInputState.menu[KEY_ABORT] }, @@ -408,4 +409,57 @@ InterrogateInputState (int template, int control, int index, char *buffer, int m buffer[0] = 0; } +void +RemoveInputState (int template, int control, int index) +{ + int i; + VCONTROL_GESTURE g; + + VControl_StartIter (&ImmediateInputState.key[template][control]); + i = 0; + while (VControl_NextBinding (&g)) + { + if (i++ < index) + { + continue; + } + VControl_RemoveGestureBinding (&g, &ImmediateInputState.key[template][control]); + return; + } + /* No such gesture! */ + return; +} + +void +RebindInputState (int template, int control, int index) +{ + SDL_Event e; + + /* Remove the old binding on this spot */ + RemoveInputState (template, control, index); + + /* Wait for the next interesting bit of user input */ + VControl_ClearEvent (); + while (!VControl_GetLastEvent (&e)) + { + TaskSwitch (); + } + + /* And now, add the new binding. */ + VControl_AddBinding (&e, &ImmediateInputState.key[template][control]); +} + +void +SaveKeyConfiguration (uio_DirHandle *path, const char *fname) +{ + uio_Stream *f; + + f = res_OpenResFile (path, fname, "wt"); + if (f) + { + VControl_Dump (f); + res_CloseResFile (f); + } +} + #endif diff --git a/sc2/src/sc2code/libs/input/sdl/vcontrol.c b/sc2/src/sc2code/libs/input/sdl/vcontrol.c index f391d7812..ba7438703 100644 --- a/sc2/src/sc2code/libs/input/sdl/vcontrol.c +++ b/sc2/src/sc2code/libs/input/sdl/vcontrol.c @@ -7,6 +7,7 @@ #include "vcontrol_malloc.h" #include "keynames.h" #include "libs/log.h" +#include "libs/reslib.h" /* How many binding slots are allocated at once. */ #define POOL_CHUNK_SIZE 64 @@ -343,7 +344,7 @@ remove_binding (keybinding **ptr, int *target) else { keybinding *prev = *ptr; - while (prev->next != NULL) + while (prev && prev->next != NULL) { if (prev->next->target == target) { @@ -353,6 +354,7 @@ remove_binding (keybinding **ptr, int *target) todel->next = NULL; todel->parent->remaining++; } + prev = prev->next; } } } @@ -437,6 +439,64 @@ VControl_RemoveBinding (SDL_Event *e, int *target) } } +int +VControl_AddGestureBinding (VCONTROL_GESTURE *g, int *target) +{ + int result; + switch (g->type) + { + case VCONTROL_KEY: + result = VControl_AddKeyBinding (g->gesture.key, target); + break; + +#ifdef HAVE_JOYSTICK + case VCONTROL_JOYAXIS: + result = VControl_AddJoyAxisBinding (g->gesture.axis.port, g->gesture.axis.index, (g->gesture.axis.polarity < 0) ? -1 : 1, target); + break; + case VCONTROL_JOYHAT: + result = VControl_AddJoyHatBinding (g->gesture.hat.port, g->gesture.hat.index, g->gesture.hat.dir, target); + break; + case VCONTROL_JOYBUTTON: + result = VControl_AddJoyButtonBinding (g->gesture.button.port, g->gesture.button.index, target); + break; +#endif /* HAVE_JOYSTICK */ + + default: + log_add (log_Warning, "VControl_AddGestureBinding didn't understand argument gesture"); + result = -1; + break; + } + return result; +} + +void +VControl_RemoveGestureBinding (VCONTROL_GESTURE *g, int *target) +{ + switch (g->type) + { + case VCONTROL_KEY: + VControl_RemoveKeyBinding (g->gesture.key, target); + break; + +#ifdef HAVE_JOYSTICK + case VCONTROL_JOYAXIS: + VControl_RemoveJoyAxisBinding (g->gesture.axis.port, g->gesture.axis.index, (g->gesture.axis.polarity < 0) ? -1 : 1, target); + break; + case VCONTROL_JOYHAT: + VControl_RemoveJoyHatBinding (g->gesture.hat.port, g->gesture.hat.index, g->gesture.hat.dir, target); + break; + case VCONTROL_JOYBUTTON: + VControl_RemoveJoyButtonBinding (g->gesture.button.port, g->gesture.button.index, target); + break; +#endif /* HAVE_JOYSTICK */ + + default: + log_add (log_Warning, "VControl_RemoveGestureBinding didn't understand argument gesture"); + break; + } +} + + int VControl_AddKeyBinding (SDLKey symbol, int *target) { @@ -832,6 +892,11 @@ VControl_HandleEvent (const SDL_Event *e) #ifdef HAVE_JOYSTICK case SDL_JOYAXISMOTION: VControl_ProcessJoyAxis (e->jaxis.which, e->jaxis.axis, e->jaxis.value); + if ((e->jaxis.value > 15000) || (e->jaxis.value < -15000)) + { + last_interesting = *e; + event_ready = 1; + } break; case SDL_JOYHATMOTION: VControl_ProcessJoyHat (e->jhat.which, e->jhat.hat, e->jhat.value); @@ -890,22 +955,30 @@ name2target (char *name) } static void -dump_keybindings (FILE *out, keybinding *kb, char *name) +dump_keybindings (uio_Stream *out, keybinding *kb, char *name) { while (kb != NULL) { char *targetname = target2name (kb->target); - fprintf (out, "%s: %s\n", targetname, name); + WriteResFile (targetname, 1, strlen (targetname), out); + PutResFileChar (':', out); + PutResFileChar (' ', out); + WriteResFile (name, 1, strlen (name), out); + PutResFileChar ('\n', out); + kb = kb->next; } } void -VControl_Dump (FILE *out) +VControl_Dump (uio_Stream *out) { int i; char namebuffer[64]; + sprintf (namebuffer, "version %d\n", version); + WriteResFile (namebuffer, 1, strlen (namebuffer), out); + /* Print out keyboard bindings */ for (i = 0; i < SDLK_LAST; i++) { @@ -925,7 +998,9 @@ VControl_Dump (FILE *out) { int j; - fprintf (out, "joystick %d threshold %d\n", i, joysticks[i].threshold); + sprintf (namebuffer, "joystick %d threshold %d\n", i, joysticks[i].threshold); + WriteResFile (namebuffer, 1, strlen (namebuffer), out); + for (j = 0; j < joysticks[i].numaxes; j++) { sprintf (namebuffer, "joystick %d axis %d negative", i, j); diff --git a/sc2/src/sc2code/libs/input/sdl/vcontrol.h b/sc2/src/sc2code/libs/input/sdl/vcontrol.h index ac3e136d0..47a7b1710 100644 --- a/sc2/src/sc2code/libs/input/sdl/vcontrol.h +++ b/sc2/src/sc2code/libs/input/sdl/vcontrol.h @@ -31,6 +31,12 @@ typedef struct { } VCONTROL_GESTURE; /* Control of bindings */ +int VControl_AddBinding (SDL_Event *e, int *target); +void VControl_RemoveBinding (SDL_Event *e, int *target); + +int VControl_AddGestureBinding (VCONTROL_GESTURE *g, int *target); +void VControl_RemoveGestureBinding (VCONTROL_GESTURE *g, int *target); + int VControl_AddKeyBinding (SDLKey symbol, int *target); void VControl_RemoveKeyBinding (SDLKey symbol, int *target); int VControl_AddJoyAxisBinding (int port, int axis, int polarity, int *target); @@ -75,7 +81,9 @@ int VControl_GetConfigFileVersion (void); void VControl_SetConfigFileVersion (int v); /* Dump a configuration file corresponding to the current bindings and names. */ -void VControl_Dump (FILE *out); +void VControl_Dump (uio_Stream *out); +void VControl_SaveFilename (uio_DirHandle *path, const char *fname); + /* Read a configuration file. Returns number of errors encountered. */ int VControl_ReadConfiguration (uio_Stream *in); diff --git a/sc2/src/sc2code/setupmenu.c b/sc2/src/sc2code/setupmenu.c index 6afcbb103..e688a6ae7 100644 --- a/sc2/src/sc2code/setupmenu.c +++ b/sc2/src/sc2code/setupmenu.c @@ -62,7 +62,8 @@ static int do_advanced (WIDGET *self, int event); static int do_editkeys (WIDGET *self, int event); static void change_template (WIDGET_CHOICE *self, int oldval); static void rename_template (WIDGET_TEXTENTRY *self); - +static void rebind_control (WIDGET_CONTROLENTRY *widget); +static void clear_control (WIDGET_CONTROLENTRY *widget); #ifdef HAVE_OPENGL #define RES_OPTS 4 @@ -74,7 +75,7 @@ static void rename_template (WIDGET_TEXTENTRY *self); #define CHOICE_COUNT 21 #define SLIDER_COUNT 3 #define BUTTON_COUNT 10 -#define LABEL_COUNT 3 +#define LABEL_COUNT 4 #define TEXTENTRY_COUNT 1 #define CONTROLENTRY_COUNT 7 @@ -471,6 +472,10 @@ DoSetupMenu (PSETUP_MENU_STATE pInputState) { Widget_Event (WIDGET_EVENT_CANCEL); } + if (PulsedInputState.menu[KEY_MENU_DELETE]) + { + Widget_Event (WIDGET_EVENT_DELETE); + } SleepThreadUntil (pInputState->NextTime + MENU_FRAME_RATE); pInputState->NextTime = GetTimeCounter (); @@ -561,10 +566,34 @@ OnTextEntryEvent (WIDGET_TEXTENTRY *widget) return TRUE; // event handled } +static void +rebind_control (WIDGET_CONTROLENTRY *widget) +{ + int template = choices[20].selected; + int control = widget->controlindex; + int index = widget->highlighted; + + FlushInput (); + DrawLabelAsWindow (&labels[3]); + RebindInputState (template, control, index); + populate_editkeys (template); + FlushInput (); +} + +static void +clear_control (WIDGET_CONTROLENTRY *widget) +{ + int template = choices[20].selected; + int control = widget->controlindex; + int index = widget->highlighted; + + RemoveInputState (template, control, index); + populate_editkeys (template); +} + static stringbank *bank = NULL; static FRAME setup_frame = NULL; - static void init_widgets (void) { @@ -923,7 +952,10 @@ init_widgets (void) controlentries[i].category = buffer[i]; controlentries[i].highlighted = 0; controlentries[i].controlname[0][0] = 0; - controlentries[i].controlname[0][1] = 0; + controlentries[i].controlname[1][0] = 0; + controlentries[i].controlindex = i; + controlentries[i].onChange = rebind_control; + controlentries[i].onDelete = clear_control; } /* Check for garbage at the end */ @@ -1166,7 +1198,6 @@ SetGlobalOptions (GLOBALOPTS *opts) int NewWidth = ScreenWidthActual; int NewHeight = ScreenHeightActual; int NewDriver = GraphicsDriver; - int i; NewGfxFlags &= ~TFB_GFXFLAGS_SCALE_ANY; @@ -1332,4 +1363,5 @@ SetGlobalOptions (GLOBALOPTS *opts) res_PutString ("config.keys.6.name", input_templates[5].name); res_SaveFilename (configDir, "uqm.cfg", "config."); + SaveKeyConfiguration (configDir, "keys.cfg"); }