diff --git a/sc2/ChangeLog b/sc2/ChangeLog index 6ebd1e764..630bcae2b 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,5 @@ Changes towards version 0.5: +- Setup menu split into four submenus - Michael - Fixed fallback in getHomeDir() for when $HOME is not defined on *nix - SvdB - %APPDATA% fallback no longer to "../userdata", but to "./userdata", diff --git a/sc2/content/lbm/setupmenu.1.png b/sc2/content/lbm/setupmenu.1.png new file mode 100644 index 000000000..08f38a95f Binary files /dev/null and b/sc2/content/lbm/setupmenu.1.png differ diff --git a/sc2/content/lbm/setupmenu.2.png b/sc2/content/lbm/setupmenu.2.png new file mode 100644 index 000000000..5431a6780 Binary files /dev/null and b/sc2/content/lbm/setupmenu.2.png differ diff --git a/sc2/content/lbm/setupmenu.3.png b/sc2/content/lbm/setupmenu.3.png new file mode 100644 index 000000000..97d93a07d Binary files /dev/null and b/sc2/content/lbm/setupmenu.3.png differ diff --git a/sc2/content/lbm/setupmenu.ani b/sc2/content/lbm/setupmenu.ani index 1e3c934e4..e26440c80 100644 --- a/sc2/content/lbm/setupmenu.ani +++ b/sc2/content/lbm/setupmenu.ani @@ -1 +1,5 @@ setupmenu.0.png -1 -1 0 0 +setupmenu.1.png -1 -1 0 0 +setupmenu.2.png -1 -1 0 0 +setupmenu.3.png -1 -1 0 0 + diff --git a/sc2/src/sc2code/libs/graphics/widgets.c b/sc2/src/sc2code/libs/graphics/widgets.c index d7003eabb..001d082e9 100644 --- a/sc2/src/sc2code/libs/graphics/widgets.c +++ b/sc2/src/sc2code/libs/graphics/widgets.c @@ -171,12 +171,12 @@ Widget_DrawChoice (WIDGET *_self, int x, int y) } font_DrawText (&t); - home_x = t.baseline.x + 3 * (SCREEN_WIDTH / 8); + home_x = t.baseline.x + 3 * (SCREEN_WIDTH / ((self->maxcolumns + 1) * 2)); home_y = t.baseline.y; t.align = ALIGN_CENTER; for (i = 0; i < self->numopts; i++) { - t.baseline.x = home_x + ((i % 3) * (SCREEN_WIDTH / 4)); + t.baseline.x = home_x + ((i % 3) * (SCREEN_WIDTH / (self->maxcolumns + 1))); t.baseline.y = home_y + (8 * (i / 3)); t.pStr = self->options[i].optname; if ((widget_focus == _self) && @@ -235,6 +235,35 @@ Widget_DrawButton (WIDGET *_self, int x, int y) (void) x; } +void +Widget_DrawLabel (WIDGET *_self, int x, int y) +{ + WIDGET_LABEL *self = (WIDGET_LABEL *)_self; + COLOR oldtext = SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); +; FONT oldfont = SetContextFont (StarConFont); + FONTEFFECT oldFontEffect = SetContextFontEffect (0, 0, 0); + TEXT t; + int i; + + t.baseline.x = 160; + t.baseline.y = y; + t.align = ALIGN_CENTER; + t.valign = VALIGN_BOTTOM; + t.CharCount = ~0; + + for (i = 0; i < self->line_count; i++) + { + t.pStr = self->lines[i]; + font_DrawText (&t); + t.baseline.y += 8; + } + SetContextFontEffect (oldFontEffect.type, oldFontEffect.from, oldFontEffect.to); + SetContextFont (oldfont); + SetContextForeGroundColor (oldtext); + (void) x; +} + int Widget_HeightChoice (WIDGET *_self) { @@ -255,7 +284,15 @@ Widget_HeightOneLine (WIDGET *_self) return 8; } -int Widget_WidthFullScreen (WIDGET *_self) +int +Widget_HeightLabel (WIDGET *_self) +{ + WIDGET_LABEL *self = (WIDGET_LABEL *)_self; + return self->line_count * 8; +} + +int +Widget_WidthFullScreen (WIDGET *_self) { (void)_self; return SCREEN_WIDTH; @@ -312,6 +349,14 @@ Widget_ReceiveFocusMenuScreen (WIDGET *_self, int event) return FALSE; } +int +Widget_ReceiveFocusRefuseFocus (WIDGET *self, int event) +{ + (void)self; + (void)event; + return FALSE; +} + int Widget_HandleEventIgnoreAll (WIDGET *self, int event) { diff --git a/sc2/src/sc2code/libs/graphics/widgets.h b/sc2/src/sc2code/libs/graphics/widgets.h index 2ef43ec31..99f089eef 100644 --- a/sc2/src/sc2code/libs/graphics/widgets.h +++ b/sc2/src/sc2code/libs/graphics/widgets.h @@ -69,6 +69,7 @@ typedef struct _widget_choice { int (*width)(struct _widget *self); const char *category; int numopts; + int maxcolumns; CHOICE_OPTION *options; int selected, highlighted; } WIDGET_CHOICE; @@ -84,6 +85,17 @@ typedef struct _widget_button { const char *tooltip[3]; } WIDGET_BUTTON; +typedef struct _widget_label { + struct _widget *parent; + int (*handleEvent)(struct _widget *self, int event); + int (*receiveFocus)(struct _widget *self, int event); + void (*draw)(struct _widget *self, int x, int y); + int (*height)(struct _widget *self); + int (*width)(struct _widget *self); + int line_count; + const char **lines; +} WIDGET_LABEL; + void DrawShadowedBox (PRECT r, COLOR bg, COLOR dark, COLOR medium); int Widget_Event (int event); @@ -93,6 +105,7 @@ int Widget_Event (int event); int Widget_ReceiveFocusMenuScreen (WIDGET *_self, int event); int Widget_ReceiveFocusChoice (WIDGET *_self, int event); int Widget_ReceiveFocusButton (WIDGET *_self, int event); +int Widget_ReceiveFocusRefuseFocus (WIDGET *_self, int event); int Widget_HandleEventMenuScreen (WIDGET *_self, int event); int Widget_HandleEventChoice (WIDGET *_self, int event); @@ -101,11 +114,33 @@ int Widget_HandleEventIgnoreAll (WIDGET *_self, int event); int Widget_HeightChoice (WIDGET *_self); int Widget_HeightFullScreen (WIDGET *_self); int Widget_HeightOneLine (WIDGET *_self); +int Widget_HeightLabel (WIDGET *_self); int Widget_WidthFullScreen (WIDGET *_self); void Widget_DrawMenuScreen (WIDGET *_self, int x, int y); void Widget_DrawChoice (WIDGET *_self, int x, int y); void Widget_DrawButton (WIDGET *_self, int x, int y); +void Widget_DrawLabel (WIDGET *_self, int x, int y); + +/* "Constructor" macros */ + +#define BUTTON_INIT(handler, name, ttip1, ttip2, ttip3) { \ + NULL, handler, Widget_ReceiveFocusButton, Widget_DrawButton, \ + Widget_HeightOneLine, Widget_WidthFullScreen, \ + (name), { (ttip1), (ttip2), (ttip3) } } + +#define CHOICE_PREFACE NULL, Widget_HandleEventChoice, \ + Widget_ReceiveFocusChoice, Widget_DrawChoice, \ + Widget_HeightChoice, Widget_WidthFullScreen + +#define LABEL_PREFACE NULL, Widget_HandleEventIgnoreAll, \ + Widget_ReceiveFocusRefuseFocus, Widget_DrawLabel, \ + Widget_HeightLabel, Widget_WidthFullScreen + +#define MENU_SCREEN_PREFACE NULL, Widget_HandleEventMenuScreen, \ + Widget_ReceiveFocusMenuScreen, \ + Widget_DrawMenuScreen, Widget_HeightFullScreen, \ + Widget_WidthFullScreen #endif /* _WIDGETS_H */ diff --git a/sc2/src/sc2code/setupmenu.c b/sc2/src/sc2code/setupmenu.c index 68d17d710..80c569533 100644 --- a/sc2/src/sc2code/setupmenu.c +++ b/sc2/src/sc2code/setupmenu.c @@ -41,18 +41,14 @@ typedef SETUP_MENU_STATE *PSETUP_MENU_STATE; static BOOLEAN DoSetupMenu (PSETUP_MENU_STATE pInputState); static BOOLEAN done; +static WIDGET *current, *next; -static int -quit_main_menu (WIDGET *self, int event) -{ - if (event == WIDGET_EVENT_SELECT) - { - done = TRUE; - return TRUE; - } - (void)self; - return FALSE; -} +static int quit_main_menu (WIDGET *self, int event); +static int quit_sub_menu (WIDGET *self, int event); +static int do_graphics (WIDGET *self, int event); +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 CHOICE_OPTION scaler_opts[] = { { "None", @@ -228,47 +224,190 @@ static CHOICE_OPTION bpp_opts[] = { #define RES_OPTS 2 #endif -#define NUM_OPTS 9 - -#define CHOICE_PREFACE NULL, Widget_HandleEventChoice, Widget_ReceiveFocusChoice, Widget_DrawChoice, Widget_HeightChoice, Widget_WidthFullScreen - static WIDGET_CHOICE cmdline_opts[] = { - { CHOICE_PREFACE, "Resolution", RES_OPTS, resdriver_opts, 0, 0}, - { CHOICE_PREFACE, "Color depth", 3, bpp_opts, 0, 0 }, - { CHOICE_PREFACE, "Scaler", 5, scaler_opts, 0, 0 }, - { CHOICE_PREFACE, "Scanlines", 2, scanlines_opts, 0, 0 }, - { CHOICE_PREFACE, "Menu Style", 2, menu_opts, 0, 0 }, - { CHOICE_PREFACE, "Font Style", 2, font_opts, 0, 0 }, - { CHOICE_PREFACE, "Scan Style", 2, scan_opts, 0, 0 }, - { CHOICE_PREFACE, "Scroll Style", 2, scroll_opts, 0, 0 }, - { CHOICE_PREFACE, "Subtitles", 2, subtitles_opts, 0, 0 } }; + { CHOICE_PREFACE, "Resolution", RES_OPTS, 3, resdriver_opts, 0, 0}, + { CHOICE_PREFACE, "Color depth", 3, 3, bpp_opts, 0, 0 }, + { CHOICE_PREFACE, "Scaler", 5, 3, scaler_opts, 0, 0 }, + { CHOICE_PREFACE, "Scanlines", 2, 3, scanlines_opts, 0, 0 }, + { CHOICE_PREFACE, "Menu Style", 2, 2, menu_opts, 0, 0 }, + { CHOICE_PREFACE, "Font Style", 2, 2, font_opts, 0, 0 }, + { CHOICE_PREFACE, "Scan Style", 2, 2, scan_opts, 0, 0 }, + { CHOICE_PREFACE, "Scroll Style", 2, 2, scroll_opts, 0, 0 }, + { CHOICE_PREFACE, "Subtitles", 2, 2, subtitles_opts, 0, 0 }, + { CHOICE_PREFACE, "Music Driver", 2, 3, music_opts, 0, 0 } }; -static WIDGET_BUTTON quit_button = { - NULL, quit_main_menu, Widget_ReceiveFocusButton, Widget_DrawButton, - Widget_HeightOneLine, Widget_WidthFullScreen, - "Quit Setup Menu", {"Return to the main menu.", "", ""} }; +static WIDGET_BUTTON quit_button = BUTTON_INIT (quit_main_menu, + "Quit Setup Menu", + "Return to the main menu.", "", ""); -static WIDGET *opt_widgets[] = { +static WIDGET_BUTTON prev_button = BUTTON_INIT (quit_sub_menu, + "Return to Main Menu", + "Save changes and return to main menu.", + "Changes will not be applied until", + "you quit setup entirely."); + +static WIDGET_BUTTON graphics_button = BUTTON_INIT (do_graphics, "Graphics Options", + "Configure display options for UQM.", + "Graphics drivers, resolution, and scalers.", ""); + +static WIDGET_BUTTON engine_button = BUTTON_INIT (do_engine, "PC/3do Compatibility Options", + "Configure behavior of UQM", + "to more closely match the PC or 3do behavior.", ""); + +static WIDGET_BUTTON resources_button = BUTTON_INIT (do_resources, "Resources Options", + "Configure UQM Addon Packs.", "", "Currently unimplemented."); + +static WIDGET_BUTTON keyconfig_button = BUTTON_INIT (do_keyconfig, "Configure Controls", + "Set up keyboard and joystick controls.", "", "Currently unimplemented."); + +static const char *incomplete_msg[] = { + "This part of the configuration", + "has not yet been implemented.", + "", + "Expect it in a future version." }; + +static WIDGET_LABEL incomplete_label = { + LABEL_PREFACE, + 4, incomplete_msg }; + +static WIDGET *main_widgets[] = { + (WIDGET *)(&graphics_button), + (WIDGET *)(&engine_button), + (WIDGET *)(&resources_button), + (WIDGET *)(&keyconfig_button), + (WIDGET *)(&quit_button) }; + +static WIDGET *graphics_widgets[] = { (WIDGET *)(&cmdline_opts[0]), (WIDGET *)(&cmdline_opts[1]), (WIDGET *)(&cmdline_opts[2]), (WIDGET *)(&cmdline_opts[3]), + (WIDGET *)(&prev_button) }; + +static WIDGET *engine_widgets[] = { (WIDGET *)(&cmdline_opts[4]), (WIDGET *)(&cmdline_opts[5]), (WIDGET *)(&cmdline_opts[6]), (WIDGET *)(&cmdline_opts[7]), (WIDGET *)(&cmdline_opts[8]), - (WIDGET *)(&quit_button) } ; + (WIDGET *)(&prev_button) }; +static WIDGET *incomplete_widgets[] = { + (WIDGET *)(&incomplete_label), + (WIDGET *)(&prev_button) }; + static WIDGET_MENU_SCREEN menu = { - NULL, Widget_HandleEventMenuScreen, Widget_ReceiveFocusMenuScreen, - Widget_DrawMenuScreen, Widget_HeightFullScreen, Widget_WidthFullScreen, + MENU_SCREEN_PREFACE, "Ur-Quan Masters Setup", "", { {0, 0}, NULL }, - 10, opt_widgets, + 5, main_widgets, + 0 }; + +static WIDGET_MENU_SCREEN graphics_menu = { + MENU_SCREEN_PREFACE, + "Ur-Quan Masters Setup", + "Graphics Options", + { {0, 0}, NULL }, + 5, graphics_widgets, 0 }; +static WIDGET_MENU_SCREEN engine_menu = { + MENU_SCREEN_PREFACE, + "Ur-Quan Masters Setup", + "3do/PC Options", + { {0, 0}, NULL }, + 6, engine_widgets, + 0 }; + +static WIDGET_MENU_SCREEN resources_menu = { + MENU_SCREEN_PREFACE, + "Ur-Quan Masters Setup", + "Addon Packs", + { {0, 0}, NULL }, + 2, incomplete_widgets, + 0 }; + +static WIDGET_MENU_SCREEN keyconfig_menu = { + MENU_SCREEN_PREFACE, + "Ur-Quan Masters Setup", + "Controls Setup", + { {0, 0}, NULL }, + 2, incomplete_widgets, + 0 }; + +static int +quit_main_menu (WIDGET *self, int event) +{ + if (event == WIDGET_EVENT_SELECT) + { + next = NULL; + return TRUE; + } + (void)self; + return FALSE; +} + +static int +quit_sub_menu (WIDGET *self, int event) +{ + if (event == WIDGET_EVENT_SELECT) + { + next = (WIDGET *)(&menu); + return TRUE; + } + (void)self; + return FALSE; +} + +static int +do_graphics (WIDGET *self, int event) +{ + if (event == WIDGET_EVENT_SELECT) + { + next = (WIDGET *)(&graphics_menu); + return TRUE; + } + (void)self; + return FALSE; +} + +static int +do_engine (WIDGET *self, int event) +{ + if (event == WIDGET_EVENT_SELECT) + { + next = (WIDGET *)(&engine_menu); + return TRUE; + } + (void)self; + return FALSE; +} + +static int +do_resources (WIDGET *self, int event) +{ + if (event == WIDGET_EVENT_SELECT) + { + next = (WIDGET *)(&resources_menu); + return TRUE; + } + (void)self; + return FALSE; +} + +static int +do_keyconfig (WIDGET *self, int event) +{ + if (event == WIDGET_EVENT_SELECT) + { + next = (WIDGET *)(&keyconfig_menu); + return TRUE; + } + (void)self; + return FALSE; +} + #define NUM_STEPS 20 #define X_STEP (SCREEN_WIDTH / NUM_STEPS) #define Y_STEP (SCREEN_HEIGHT / NUM_STEPS) @@ -322,20 +461,49 @@ DoSetupMenu (PSETUP_MENU_STATE pInputState) if (!pInputState->initialized) { SetDefaultMenuRepeatDelay (); - SetTransitionSource (NULL); pInputState->NextTime = GetTimeCounter (); SetDefaults (); - (*menu.receiveFocus) ((WIDGET *)(&menu), WIDGET_EVENT_DOWN); + + current = NULL; + next = (WIDGET *)(&menu); + + pInputState->initialized = TRUE; } if (!menu.bgStamp.frame) { + FRAME f = CaptureDrawable (LoadCelFile (MENU_BKG)); menu.bgStamp.origin.x = 0; menu.bgStamp.origin.y = 0; - menu.bgStamp.frame = CaptureDrawable (LoadCelFile (MENU_BKG)); + menu.bgStamp.frame = SetAbsFrameIndex (f, 0); + graphics_menu.bgStamp.origin.x = 0; + graphics_menu.bgStamp.origin.y = 0; + graphics_menu.bgStamp.frame = SetAbsFrameIndex (f, 1); + engine_menu.bgStamp.origin.x = 0; + engine_menu.bgStamp.origin.y = 0; + engine_menu.bgStamp.frame = SetAbsFrameIndex (f, 2); + resources_menu.bgStamp.origin.x = 0; + resources_menu.bgStamp.origin.y = 0; + resources_menu.bgStamp.frame = SetAbsFrameIndex (f, 3); + keyconfig_menu.bgStamp.origin.x = 0; + keyconfig_menu.bgStamp.origin.y = 0; + keyconfig_menu.bgStamp.frame = SetAbsFrameIndex (f, 1); + } + if (current != next) + { + SetTransitionSource (NULL); + (*next->receiveFocus) (next, WIDGET_EVENT_DOWN); } BatchGraphics (); - (*menu.draw)((WIDGET *)(&menu), 0, 0); + (*next->draw)(next, 0, 0); + + if (current != next) + { + ScreenTransition (3, NULL); + current = next; + } + + UnbatchGraphics (); if (PulsedInputState.key[KEY_MENU_UP]) { @@ -358,16 +526,10 @@ DoSetupMenu (PSETUP_MENU_STATE pInputState) Widget_Event (WIDGET_EVENT_SELECT); } - if (!pInputState->initialized) - { - pInputState->initialized = TRUE; - ScreenTransition (3, NULL); - } - UnbatchGraphics (); SleepThreadUntil (pInputState->NextTime + MENU_FRAME_RATE); pInputState->NextTime = GetTimeCounter (); return !((GLOBAL (CurrentActivity) & CHECK_ABORT) || - PulsedInputState.key[KEY_MENU_CANCEL] || done); + PulsedInputState.key[KEY_MENU_CANCEL] || (next == NULL)); } void