From e0366a964f3bbca2e1fdff3c1ea5a11448238cf4 Mon Sep 17 00:00:00 2001 From: mcmartin Date: Sun, 27 Aug 2006 15:01:37 +0000 Subject: [PATCH] Next phase of online keyconfig; editable names of templates, and some other groundwork for the next steps. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2424 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/ChangeLog | 1 + sc2/content/lbm/setupmenu.txt | 90 ++++++++----- sc2/src/options.c | 1 + sc2/src/options.h | 13 ++ sc2/src/sc2code/libs/graphics/widgets.c | 7 ++ sc2/src/sc2code/libs/graphics/widgets.h | 2 + sc2/src/sc2code/libs/input/input_common.c | 1 - sc2/src/sc2code/setupmenu.c | 146 ++++++++++++++++++---- sc2/src/starcon2.c | 60 +++++++++ 9 files changed, 268 insertions(+), 53 deletions(-) diff --git a/sc2/ChangeLog b/sc2/ChangeLog index 2fd393383..fa70fdb70 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,5 @@ Changes towards version 0.6: +- Input templates can now be renamed, both online and off - Michael - Fixed an integer-size error that was causing crashes on AMD64, from Solomon Peachy (#895) - Michael - Added some generic lib code to be used by future code. - SvdB diff --git a/sc2/content/lbm/setupmenu.txt b/sc2/content/lbm/setupmenu.txt index 966e20838..51176bd1b 100644 --- a/sc2/content/lbm/setupmenu.txt +++ b/sc2/content/lbm/setupmenu.txt @@ -9,6 +9,7 @@ Audio Options Resources Options Controls Setup Advanced Options +Edit Controls #(CHOICES) Resolution @@ -31,6 +32,7 @@ Sound Quality Slave Shields Player One Player Two +Control Set #(CAT_0_OPTS) 320x240 @@ -304,81 +306,95 @@ Slave shields pulsate. This mimics the 3do verion. #(CAT_18_OPTS) -Keyboard #1 -Keyboard #2 -Keyboard #3 -Joystick #1 -Joystick #2 -Joystick #3 +Placeholder +Placeholder +Placeholder +Placeholder +Placeholder +Placeholder #(CAT_18_OPT_0_DESC) -Player 1 uses the Keyboard 1 template. Player 1 controls the bottom player in Super Melee, and the entire Full Game. #(CAT_18_OPT_1_DESC) -Player 1 uses the Keyboard 2 template. Player 1 controls the bottom player in Super Melee, and the entire Full Game. #(CAT_18_OPT_2_DESC) -Player 1 uses the Keyboard 3 template. Player 1 controls the bottom player in Super Melee, and the entire Full Game. #(CAT_18_OPT_3_DESC) -Player 1 uses the Joystick 1 template. Player 1 controls the bottom player in Super Melee, and the entire Full Game. #(CAT_18_OPT_4_DESC) -Player 1 uses the Joystick 2 template. Player 1 controls the bottom player in Super Melee, and the entire Full Game. #(CAT_18_OPT_5_DESC) -Player 1 uses the Joystick 3 template. Player 1 controls the bottom player in Super Melee, and the entire Full Game. #(CAT_19_OPTS) -Keyboard #1 -Keyboard #2 -Keyboard #3 -Joystick #1 -Joystick #2 -Joystick #3 +Placeholder +Placeholder +Placeholder +Placeholder +Placeholder +Placeholder #(CAT_19_OPT_0_DESC) -Player 2 uses the Keyboard 1 template. Player 2 controls the top player in Super Melee. #(CAT_19_OPT_1_DESC) -Player 2 uses the Keyboard 2 template. Player 2 controls the top player in Super Melee. #(CAT_19_OPT_2_DESC) -Player 2 uses the Keyboard 3 template. Player 2 controls the top player in Super Melee. #(CAT_19_OPT_3_DESC) -Player 2 uses the Joystick 1 template. Player 2 controls the top player in Super Melee. #(CAT_19_OPT_4_DESC) -Player 2 uses the Joystick 2 template. Player 2 controls the top player in Super Melee. #(CAT_19_OPT_5_DESC) -Player 2 uses the Joystick 3 template. Player 2 controls the top player in Super Melee. +#(CAT_20_OPTS) +Placeholder +Placeholder +Placeholder +Placeholder +Placeholder +Placeholder + +#(CAT_20_OPT_0_DESC) +Select the control template to edit. + +#(CAT_20_OPT_1_DESC) +Select the control template to edit. + +#(CAT_20_OPT_2_DESC) +Select the control template to edit. + +#(CAT_20_OPT_3_DESC) +Select the control template to edit. + +#(CAT_20_OPT_4_DESC) +Select the control template to edit. + +#(CAT_20_OPT_5_DESC) +Select the control template to edit. + #(SLIDERS) Music Volume SFX Volume @@ -402,6 +418,8 @@ Sound Options Resources Options Configure Controls Advanced Options +Edit Controls +Back to Control Select #(BUTTON_0_DESC) Return to the main menu. @@ -436,9 +454,16 @@ Currently partially implemented. Select underlying drivers or other hardware-dependent options. +#(BUTTON_8_DESC) +Edit key control sets. + +#(BUTTON_9_DESC) +Return to control set selection screen. + #(LABELS) Incomplete -Keyconfig incomplete +Keyconfig header +Editkey header #(LABEL_0) This part of the configuration @@ -447,7 +472,14 @@ has not yet been implemented. Expect it in a future version. #(LABEL_1) -Control templates are currently defined -in the KEYS.CFG file stored near your -save games. A future UQM version will -offer in-game key configuration. +To view or edit key controls, +select the option below: + +#(LABEL_2) +Controls + +#(TEXT_ENTRIES) +Name + +#(TEXT_ENTRIES_INITIAL) +Placeholder diff --git a/sc2/src/options.c b/sc2/src/options.c index f481522f2..8e938cdd9 100644 --- a/sc2/src/options.c +++ b/sc2/src/options.c @@ -58,6 +58,7 @@ uio_DirList *availableAddons; extern uio_Repository *repository; extern uio_DirHandle *rootDir; +INPUT_TEMPLATE input_templates[6]; static const char *findFileInDirs (const char *locs[], int numLocs, const char *file); diff --git a/sc2/src/options.h b/sc2/src/options.h index 833e3c25e..c0f5ed9c7 100644 --- a/sc2/src/options.h +++ b/sc2/src/options.h @@ -49,6 +49,19 @@ extern uio_DirHandle *meleeDir; extern uio_DirList *availableAddons; +/* These get edited by TEXTENTRY widgets, so they should have room to + * hold as much as one of them allows by default. */ +typedef struct _input_template { + char name[30]; + + /* This should eventually also hold things like Joystick Port + * and whether or not joysticks are enabled at all, and + * possibly the whole configuration scheme. If we do that, we + * can actually ditch much of VControl. */ +} INPUT_TEMPLATE; + +extern INPUT_TEMPLATE input_templates[6]; + void prepareContentDir (const char *contentDirName, const char **addons); void prepareConfigDir (const char *configDirName); void prepareMeleeDir (void); diff --git a/sc2/src/sc2code/libs/graphics/widgets.c b/sc2/src/sc2code/libs/graphics/widgets.c index 093c12719..f694f661d 100644 --- a/sc2/src/sc2code/libs/graphics/widgets.c +++ b/sc2/src/sc2code/libs/graphics/widgets.c @@ -600,8 +600,15 @@ Widget_HandleEventChoice (WIDGET *_self, int event) self->highlighted = 0; return TRUE; case WIDGET_EVENT_SELECT: + { + int oldval = self->selected; self->selected = self->highlighted; + if (self->onChange) + { + (*(self->onChange))(self, oldval); + } return TRUE; + } default: return FALSE; } diff --git a/sc2/src/sc2code/libs/graphics/widgets.h b/sc2/src/sc2code/libs/graphics/widgets.h index bdba438f0..bba6c0626 100644 --- a/sc2/src/sc2code/libs/graphics/widgets.h +++ b/sc2/src/sc2code/libs/graphics/widgets.h @@ -74,6 +74,7 @@ typedef struct _widget_choice { int maxcolumns; CHOICE_OPTION *options; int selected, highlighted; + void (*onChange)(struct _widget_choice *self, int oldval); } WIDGET_CHOICE; typedef struct _widget_button { @@ -130,6 +131,7 @@ typedef struct _widget_textentry { // handleEventSelect is an overridable callback event // called by the default handleEvent implementation // can be NULL, in which case SELECT is ignored + void (*onChange)(struct _widget_textentry *self); const char *category; char value[WIDGET_TEXTENTRY_WIDTH]; int maxlen; diff --git a/sc2/src/sc2code/libs/input/input_common.c b/sc2/src/sc2code/libs/input/input_common.c index 52e690612..14b80d3f3 100644 --- a/sc2/src/sc2code/libs/input/input_common.c +++ b/sc2/src/sc2code/libs/input/input_common.c @@ -20,4 +20,3 @@ #include "inpintrn.h" volatile BOOLEAN ExitRequested, GamePaused; - diff --git a/sc2/src/sc2code/setupmenu.c b/sc2/src/sc2code/setupmenu.c index fcbd8d14c..a613335b3 100644 --- a/sc2/src/sc2code/setupmenu.c +++ b/sc2/src/sc2code/setupmenu.c @@ -58,6 +58,10 @@ static int do_engine (WIDGET *self, int event); static int do_resources (WIDGET *self, int event); static int do_keyconfig (WIDGET *self, int event); 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); + #ifdef HAVE_OPENGL #define RES_OPTS 4 @@ -65,11 +69,11 @@ static int do_advanced (WIDGET *self, int event); #define RES_OPTS 2 #endif -#define MENU_COUNT 7 -#define CHOICE_COUNT 20 +#define MENU_COUNT 8 +#define CHOICE_COUNT 21 #define SLIDER_COUNT 3 -#define BUTTON_COUNT 8 -#define LABEL_COUNT 2 +#define BUTTON_COUNT 10 +#define LABEL_COUNT 3 #define TEXTENTRY_COUNT 1 /* The space for our widgets */ @@ -85,23 +89,26 @@ static WIDGET_TEXTENTRY textentries[TEXTENTRY_COUNT]; typedef int (*HANDLER)(WIDGET *, int); static int choice_widths[CHOICE_COUNT] = { - 3, 2, 3, 3, 2, 2, 2, 2, 2, - 2, 2, 2, 3, 2, 2, 3, 3, 2, - 3, 3 }; + 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 2, 2, 3, 3, 2, 3, 3, + 3 }; static HANDLER button_handlers[BUTTON_COUNT] = { quit_main_menu, quit_sub_menu, do_graphics, do_engine, - do_audio, do_resources, do_keyconfig, do_advanced }; + do_audio, do_resources, do_keyconfig, do_advanced, do_editkeys, + do_keyconfig }; static int menu_sizes[MENU_COUNT] = { - 8, 5, 6, 9, 2, 4, + 7, 5, 6, 9, 2, 5, #ifdef HAVE_OPENGL - 5 }; + 5, #else - 4 }; + 4, #endif + 4 +}; -static int menu_bgs[MENU_COUNT] = { 0, 1, 1, 2, 3, 1, 2 }; +static int menu_bgs[MENU_COUNT] = { 0, 1, 1, 2, 3, 1, 2, 1 }; /* These refer to uninitialized widgets, but that's OK; we'll fill * them in before we touch them */ @@ -112,7 +119,6 @@ static WIDGET *main_widgets[] = { (WIDGET *)(&buttons[5]), (WIDGET *)(&buttons[6]), (WIDGET *)(&buttons[7]), - (WIDGET *)(&textentries[0]), (WIDGET *)(&buttons[0]) }; static WIDGET *graphics_widgets[] = { @@ -154,15 +160,22 @@ static WIDGET *keyconfig_widgets[] = { (WIDGET *)(&choices[18]), (WIDGET *)(&choices[19]), (WIDGET *)(&labels[1]), + (WIDGET *)(&buttons[8]), (WIDGET *)(&buttons[1]) }; +static WIDGET *editkeys_widgets[] = { + (WIDGET *)(&choices[20]), + (WIDGET *)(&labels[2]), + (WIDGET *)(&textentries[0]), + (WIDGET *)(&buttons[9]) }; + static WIDGET *incomplete_widgets[] = { (WIDGET *)(&labels[0]), (WIDGET *)(&buttons[1]) }; static WIDGET **menu_widgets[MENU_COUNT] = { main_widgets, graphics_widgets, audio_widgets, engine_widgets, - incomplete_widgets, keyconfig_widgets, advanced_widgets }; + incomplete_widgets, keyconfig_widgets, advanced_widgets, editkeys_widgets }; static int quit_main_menu (WIDGET *self, int event) @@ -267,6 +280,39 @@ do_advanced (WIDGET *self, int event) return FALSE; } +static int +do_editkeys (WIDGET *self, int event) +{ + if (event == WIDGET_EVENT_SELECT) + { + next = (WIDGET *)(&menus[7]); + /* Prepare the components */ + choices[20].selected = 0; + strncpy (textentries[0].value, input_templates[0].name, textentries[0].maxlen); + textentries[0].value[textentries[0].maxlen] = 0; + (*next->receiveFocus) (next, WIDGET_EVENT_DOWN); + return TRUE; + } + (void)self; + return FALSE; +} + +static void +change_template (WIDGET_CHOICE *self, int oldval) +{ + strncpy (textentries[0].value, input_templates[self->selected].name, WIDGET_TEXTENTRY_WIDTH); + textentries[0].value[WIDGET_TEXTENTRY_WIDTH-1] = 0; +} + +static void +rename_template (WIDGET_TEXTENTRY *self) +{ + strncpy (input_templates[choices[20].selected].name, self->value, WIDGET_TEXTENTRY_WIDTH); + /* TODO: This will have to change if the size of the input_templates name is changed */ + input_templates[choices[20].selected].name[WIDGET_TEXTENTRY_WIDTH-1] = 0; + +} + #define NUM_STEPS 20 #define X_STEP (SCREEN_WIDTH / NUM_STEPS) #define Y_STEP (SCREEN_HEIGHT / NUM_STEPS) @@ -306,6 +352,7 @@ SetDefaults (void) choices[17].selected = opts.shield; choices[18].selected = opts.player1; choices[19].selected = opts.player2; + choices[20].selected = 0; sliders[0].value = opts.musicvol; sliders[1].value = opts.sfxvol; @@ -474,6 +521,13 @@ OnTextEntryEvent (WIDGET_TEXTENTRY *widget) { // editing failed (canceled) -- revert the changes utf8StringCopy (widget->value, widget->maxlen, revert_buf); } + else + { + if (widget->onChange) + { + (*(widget->onChange))(widget); + } + } widget->state = WTE_NORMAL; redraw_menu (); @@ -539,7 +593,6 @@ init_widgets (void) /* Options */ if (SplitString (GetStringAddress (SetAbsStringTableIndex (SetupTab, 2)), '\n', 100, buffer, bank) != CHOICE_COUNT) { - /* TODO: Ignore extras instead of dying. */ log_add (log_Fatal, "PANIC: Incorrect number of Choice Options"); exit (EXIT_FAILURE); } @@ -558,6 +611,7 @@ init_widgets (void) choices[i].selected = 0; choices[i].highlighted = 0; choices[i].maxcolumns = choice_widths[i]; + choices[i].onChange = NULL; } /* Fill in the options now */ @@ -607,6 +661,17 @@ init_widgets (void) /* The first choice is resolution, and is handled specially */ choices[0].numopts = RES_OPTS; + /* Choices 18-20 are also special, being the names of the key configurations */ + for (i = 0; i < 6; i++) + { + choices[18].options[i].optname = input_templates[i].name; + choices[19].options[i].optname = input_templates[i].name; + choices[20].options[i].optname = input_templates[i].name; + } + + /* Choice 20 has a special onChange handler, too. */ + choices[20].onChange = change_template; + /* Sliders */ if (index >= count) { @@ -755,14 +820,18 @@ init_widgets (void) } } - /* Check for garbage at the end */ - if (index < count) + /* Text Entry boxes */ + if (index >= count) { - log_add (log_Warning, "WARNING: Setup strings had %d garbage entries at the end.", - count - index); + log_add (log_Fatal, "PANIC: String table cut short while reading text entries"); + exit (EXIT_FAILURE); } - /* Hardcode the test textentry for now. */ + if (SplitString (GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)), '\n', 100, buffer, bank) != TEXTENTRY_COUNT) + { + log_add (log_Fatal, "PANIC: Incorrect number of Text Entries"); + exit (EXIT_FAILURE); + } for (i = 0; i < TEXTENTRY_COUNT; i++) { textentries[i].parent = NULL; @@ -772,15 +841,38 @@ init_widgets (void) textentries[i].height = Widget_HeightOneLine; textentries[i].width = Widget_WidthFullScreen; textentries[i].handleEventSelect = OnTextEntryEvent; - textentries[i].category = NULL; + textentries[i].category = buffer[i]; textentries[i].value[0] = 0; textentries[i].maxlen = WIDGET_TEXTENTRY_WIDTH-1; textentries[i].state = WTE_NORMAL; textentries[i].cursor_pos = 0; } - textentries[0].category = "TestText"; - strcpy (textentries[0].value, "Sample value"); + if (index >= count) + { + log_add (log_Fatal, "PANIC: String table cut short while reading text entries"); + exit (EXIT_FAILURE); + } + + if (SplitString (GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)), '\n', 100, buffer, bank) != TEXTENTRY_COUNT) + { + /* TODO: Ignore extras instead of dying. */ + log_add (log_Fatal, "PANIC: Incorrect number of Text Entries"); + exit (EXIT_FAILURE); + } + for (i = 0; i < TEXTENTRY_COUNT; i++) + { + strncpy (textentries[i].value, buffer[i], textentries[i].maxlen); + textentries[i].value[textentries[i].maxlen] = 0; + } + textentries[0].onChange = rename_template; + + /* Check for garbage at the end */ + if (index < count) + { + log_add (log_Warning, "WARNING: Setup strings had %d garbage entries at the end.", + count - index); + } } static void @@ -1015,6 +1107,7 @@ SetGlobalOptions (GLOBALOPTS *opts) int NewWidth = ScreenWidthActual; int NewHeight = ScreenHeightActual; int NewDriver = GraphicsDriver; + int i; NewGfxFlags &= ~TFB_GFXFLAGS_SCALE_ANY; @@ -1172,5 +1265,12 @@ SetGlobalOptions (GLOBALOPTS *opts) SetMusicVolume (musicVolume); SetSpeechVolume (speechVolumeScale); + res_PutString ("config.keys.1.name", input_templates[0].name); + res_PutString ("config.keys.2.name", input_templates[1].name); + res_PutString ("config.keys.3.name", input_templates[2].name); + res_PutString ("config.keys.4.name", input_templates[3].name); + res_PutString ("config.keys.5.name", input_templates[4].name); + res_PutString ("config.keys.6.name", input_templates[5].name); + res_SaveFilename (configDir, "uqm.cfg", "config."); } diff --git a/sc2/src/starcon2.c b/sc2/src/starcon2.c index 2864da6b6..7cca8d59e 100644 --- a/sc2/src/starcon2.c +++ b/sc2/src/starcon2.c @@ -354,6 +354,66 @@ main (int argc, char *argv[]) parseVolume (res_GetString ("config.speechvol"), &options.speechVolumeScale, "speech volume"); } + if (res_HasKey ("config.keys.1.name")) + { + strncpy(input_templates[0].name, res_GetString ("config.keys.1.name"), 30); + input_templates[0].name[29] = 0; + } + else + { + strcpy (input_templates[0].name, "Keyboard 1"); + res_PutString ("config.keys.1.name", input_templates[0].name); + } + if (res_HasKey ("config.keys.2.name")) + { + strncpy(input_templates[1].name, res_GetString ("config.keys.2.name"), 30); + input_templates[1].name[29] = 0; + } + else + { + strcpy (input_templates[1].name, "Keyboard 2"); + res_PutString ("config.keys.2.name", input_templates[1].name); + } + if (res_HasKey ("config.keys.3.name")) + { + strncpy(input_templates[2].name, res_GetString ("config.keys.3.name"), 30); + input_templates[2].name[29] = 0; + } + else + { + strcpy (input_templates[2].name, "Keyboard 3"); + res_PutString ("config.keys.3.name", input_templates[2].name); + } + if (res_HasKey ("config.keys.4.name")) + { + strncpy(input_templates[3].name, res_GetString ("config.keys.4.name"), 30); + input_templates[3].name[29] = 0; + } + else + { + strcpy (input_templates[3].name, "Joystick 1"); + res_PutString ("config.keys.4.name", input_templates[3].name); + } + if (res_HasKey ("config.keys.5.name")) + { + strncpy(input_templates[4].name, res_GetString ("config.keys.5.name"), 30); + input_templates[4].name[29] = 0; + } + else + { + strcpy (input_templates[4].name, "Joystick 2"); + res_PutString ("config.keys.5.name", input_templates[4].name); + } + if (res_HasKey ("config.keys.6.name")) + { + strncpy(input_templates[5].name, res_GetString ("config.keys.6.name"), 30); + input_templates[5].name[29] = 0; + } + else + { + strcpy (input_templates[5].name, "Joystick 3"); + res_PutString ("config.keys.6.name", input_templates[5].name); + } optionsResult = parseOptions (argc, argv, &options); if (optionsResult != 0)