diff --git a/src/client/menu/header/qmenu.h b/src/client/menu/header/qmenu.h index 2070fa56..9597ebbf 100644 --- a/src/client/menu/header/qmenu.h +++ b/src/client/menu/header/qmenu.h @@ -32,16 +32,18 @@ #define MAXMENUITEMS 64 -#define MTYPE_SLIDER 0 -#define MTYPE_LIST 1 -#define MTYPE_ACTION 2 -#define MTYPE_SPINCONTROL 3 -#define MTYPE_SEPARATOR 4 -#define MTYPE_FIELD 5 +#define MTYPE_SLIDER 0 +#define MTYPE_LIST 1 +#define MTYPE_ACTION 2 +#define MTYPE_SPINCONTROL 3 +#define MTYPE_SEPARATOR 4 +#define MTYPE_FIELD 5 +#define MTYPE_BITMAP 6 -#define QMF_LEFT_JUSTIFY 0x00000001 -#define QMF_GRAYED 0x00000002 -#define QMF_NUMBERSONLY 0x00000004 +#define QMF_LEFT_JUSTIFY 0x00000001 +#define QMF_GRAYED 0x00000002 +#define QMF_NUMBERSONLY 0x00000004 +#define QMF_HIGHLIGHT_IF_FOCUS 0x00000008 enum { KEYS_ALL = 0, @@ -82,6 +84,15 @@ typedef struct void (*cursordraw)(void *self); } menucommon_s; +typedef struct +{ + menucommon_s generic; + char * focuspic; + char * errorpic; + int width; + int height; +} menubitmap_s; + typedef struct { menucommon_s generic; diff --git a/src/client/menu/menu.c b/src/client/menu/menu.c index afecd72e..a325ff0b 100644 --- a/src/client/menu/menu.c +++ b/src/client/menu/menu.c @@ -38,6 +38,7 @@ static int m_main_cursor; /* Number of the frames of the spinning quake logo */ #define NUM_CURSOR_FRAMES 15 +static int m_cursor_width = 0; /* Signals the file system to start the demo loop. */ qboolean menu_startdemoloop; @@ -543,20 +544,57 @@ M_Popup(void) * MAIN MENU */ -#define MAIN_ITEMS 5 +static menuframework_s s_main; +static menubitmap_s s_plaque; +static menubitmap_s s_logo; +static menubitmap_s s_game; +static menubitmap_s s_multiplayer; +static menubitmap_s s_options; +static menubitmap_s s_video; +static menubitmap_s s_quit; static void -M_Main_Draw(void) +GameFunc(void *unused) +{ + M_Menu_Game_f(); +} + +static void +MultiplayerFunc(void *unused) +{ + M_Menu_Multiplayer_f(); +} + +static void +OptionsFunc(void *unused) +{ + M_Menu_Options_f(); +} + +static void +VideoFunc(void *unused) +{ + M_Menu_Video_f(); +} + +static void +QuitFunc(void *unused) +{ + M_Menu_Quit_f(); +} + +static void +InitMainMenu(void) { - int i; - int w, h; - int ystart; - int xoffset; - int widest = -1; - char litname[80]; float scale = SCR_GetMenuScale(); - char *names[] = - { + int i = 0; + int x = 0; + int y = 0; + int w = 0; + int h = 0; + int widest = -1; + + char * names[] = { "m_main_game", "m_main_multiplayer", "m_main_options", @@ -569,95 +607,144 @@ M_Main_Draw(void) { Draw_GetPicSize(&w, &h, names[i]); - if (w > widest) - { + if (w > widest) { widest = w; } } - ystart = (viddef.height / (2 * scale) - 110); - xoffset = (viddef.width / scale - widest + 70) / 2; + x = (viddef.width / scale - widest + 70) / 2; + y = (viddef.height / (2 * scale) - 110); - for (i = 0; names[i] != 0; i++) - { - if (i != m_main_cursor) - { - Draw_PicScaled(xoffset * scale, (ystart + i * 40 + 13) * scale, names[i], scale); - } - } - - strcpy(litname, names[m_main_cursor]); - strcat(litname, "_sel"); - Draw_PicScaled(xoffset * scale, (ystart + m_main_cursor * 40 + 13) * scale, litname, scale); - - M_DrawCursor(xoffset - 25, ystart + m_main_cursor * 40 + 11, - (int)(cls.realtime / 100) % NUM_CURSOR_FRAMES); + memset(&s_main, 0, sizeof( menuframework_s )); Draw_GetPicSize(&w, &h, "m_main_plaque"); - Draw_PicScaled((xoffset - 30 - w) * scale, ystart * scale, "m_main_plaque", scale); - Draw_PicScaled((xoffset - 30 - w) * scale, (ystart + h + 5) * scale, "m_main_logo", scale); + s_plaque.generic.type = MTYPE_BITMAP; + s_plaque.generic.flags = QMF_LEFT_JUSTIFY | QMF_GRAYED; + s_plaque.generic.x = (x - (m_cursor_width + 5) - w); + s_plaque.generic.y = y; + s_plaque.generic.name = "m_main_plaque"; + s_plaque.generic.callback = 0; + s_plaque.focuspic = 0; + + s_logo.generic.type = MTYPE_BITMAP; + s_logo.generic.flags = QMF_LEFT_JUSTIFY | QMF_GRAYED; + s_logo.generic.x = (x - (m_cursor_width + 5) - w); + s_logo.generic.y = y + h + 5; + s_logo.generic.name = "m_main_logo"; + s_logo.generic.callback = 0; + s_logo.focuspic = 0; + + y += 10; + + s_game.generic.type = MTYPE_BITMAP; + s_game.generic.flags = QMF_LEFT_JUSTIFY | QMF_HIGHLIGHT_IF_FOCUS; + s_game.generic.x = x; + s_game.generic.y = y; + s_game.generic.name = "m_main_game"; + s_game.generic.callback = GameFunc; + s_game.focuspic = "m_main_game_sel"; + + Draw_GetPicSize(&w, &h, ( char * )s_game.generic.name); + y += h + 8; + + s_multiplayer.generic.type = MTYPE_BITMAP; + s_multiplayer.generic.flags = QMF_LEFT_JUSTIFY | QMF_HIGHLIGHT_IF_FOCUS; + s_multiplayer.generic.x = x; + s_multiplayer.generic.y = y; + s_multiplayer.generic.name = "m_main_multiplayer"; + s_multiplayer.generic.callback = MultiplayerFunc; + s_multiplayer.focuspic = "m_main_multiplayer_sel"; + + Draw_GetPicSize(&w, &h, ( char * )s_multiplayer.generic.name); + y += h + 8; + + s_options.generic.type = MTYPE_BITMAP; + s_options.generic.flags = QMF_LEFT_JUSTIFY | QMF_HIGHLIGHT_IF_FOCUS; + s_options.generic.x = x; + s_options.generic.y = y; + s_options.generic.name = "m_main_options"; + s_options.generic.callback = OptionsFunc; + s_options.focuspic = "m_main_options_sel"; + + Draw_GetPicSize(&w, &h, ( char * )s_options.generic.name); + y += h + 8; + + s_video.generic.type = MTYPE_BITMAP; + s_video.generic.flags = QMF_LEFT_JUSTIFY | QMF_HIGHLIGHT_IF_FOCUS; + s_video.generic.x = x; + s_video.generic.y = y; + s_video.generic.name = "m_main_video"; + s_video.generic.callback = VideoFunc; + s_video.focuspic = "m_main_video_sel"; + + Draw_GetPicSize(&w, &h, ( char * )s_video.generic.name); + y += h + 8; + + s_quit.generic.type = MTYPE_BITMAP; + s_quit.generic.flags = QMF_LEFT_JUSTIFY | QMF_HIGHLIGHT_IF_FOCUS; + s_quit.generic.x = x; + s_quit.generic.y = y; + s_quit.generic.name = "m_main_quit"; + s_quit.generic.callback = QuitFunc; + s_quit.focuspic = "m_main_quit_sel"; + + Menu_AddItem(&s_main, (void *)&s_plaque); + Menu_AddItem(&s_main, (void *)&s_logo); + Menu_AddItem(&s_main, (void *)&s_game); + Menu_AddItem(&s_main, (void *)&s_multiplayer); + Menu_AddItem(&s_main, (void *)&s_options); + Menu_AddItem(&s_main, (void *)&s_video); + Menu_AddItem(&s_main, (void *)&s_quit); + + Menu_Center(&s_main); +} + + +static void +M_Main_Draw(void) +{ + menucommon_s * item = 0; + int x = 0; + int y = 0; + + item = ( menucommon_s * )s_main.items[s_main.cursor]; + + if (item) { + x = item->x; + y = item->y; + } + + Menu_Draw(&s_main); + M_DrawCursor(x - m_cursor_width, y, + ( int )(cls.realtime / 100) % NUM_CURSOR_FRAMES); } const char * M_Main_Key(int key) { - const char *sound = menu_move_sound; - int menu_key = Key_GetMenuKey(key); - - switch (menu_key) - { - case K_ESCAPE: - M_PopMenu(); - break; - - case K_DOWNARROW: - if (++m_main_cursor >= MAIN_ITEMS) - { - m_main_cursor = 0; - } - return sound; - - case K_UPARROW: - if (--m_main_cursor < 0) - { - m_main_cursor = MAIN_ITEMS - 1; - } - return sound; - - case K_ENTER: - m_entersound = true; - - switch (m_main_cursor) - { - case 0: - M_Menu_Game_f(); - break; - - case 1: - M_Menu_Multiplayer_f(); - break; - - case 2: - M_Menu_Options_f(); - break; - - case 3: - M_Menu_Video_f(); - break; - - case 4: - M_Menu_Quit_f(); - break; - } - } - - return NULL; + return Default_MenuKey(&s_main, key); } void M_Menu_Main_f(void) { + menucommon_s * item = 0; + + InitMainMenu(); + + // force first available item to have focus + while (s_main.cursor >= 0 && s_main.cursor < s_main.nitems) { + + item = ( menucommon_s * )s_main.items[s_main.cursor]; + + if ((item->flags & (QMF_GRAYED))) { + s_main.cursor++; + } else { + break; + } + } + M_PushMenu(M_Main_Draw, M_Main_Key); } diff --git a/src/client/menu/qmenu.c b/src/client/menu/qmenu.c index 29d0fc63..1b955491 100644 --- a/src/client/menu/qmenu.c +++ b/src/client/menu/qmenu.c @@ -44,12 +44,25 @@ extern viddef_t viddef; #define VID_WIDTH viddef.width #define VID_HEIGHT viddef.height -void -Action_DoEnter(menuaction_s *a) +/* +================= +Bitmap_Draw +================= +*/ +void Bitmap_Draw(menubitmap_s * item) { - if (a->generic.callback) - { - a->generic.callback(a); + float scale = SCR_GetMenuScale(); + float x = 0.0f; + float y = 0.0f; + + x = item->generic.x; + y = item->generic.y; + + if (((item->generic.flags & QMF_HIGHLIGHT_IF_FOCUS) && + (Menu_ItemAtCursor(item->generic.parent) == item))) { + Draw_PicScaled(x * scale, y * scale, item->focuspic, scale); + } else if (item->generic.name) { + Draw_PicScaled(x * scale, y * scale, ( char * )item->generic.name, scale); } } @@ -321,7 +334,8 @@ Menu_AdjustCursor(menuframework_s *m, int dir) { if ((citem = Menu_ItemAtCursor(m)) != 0) { - if (citem->type != MTYPE_SEPARATOR) + if (citem->type != MTYPE_SEPARATOR && + (citem->flags & QMF_GRAYED) != QMF_GRAYED) { return; } @@ -338,7 +352,8 @@ Menu_AdjustCursor(menuframework_s *m, int dir) if (citem) { - if (citem->type != MTYPE_SEPARATOR) + if (citem->type != MTYPE_SEPARATOR && + (citem->flags & QMF_GRAYED) != QMF_GRAYED) { break; } @@ -360,7 +375,8 @@ Menu_AdjustCursor(menuframework_s *m, int dir) if (citem) { - if (citem->type != MTYPE_SEPARATOR) + if (citem->type != MTYPE_SEPARATOR && + (citem->flags & QMF_GRAYED) != QMF_GRAYED) { break; } @@ -412,6 +428,10 @@ Menu_Draw(menuframework_s *menu) case MTYPE_SPINCONTROL: SpinControl_Draw((menulist_s *)menu->items[i]); break; + case MTYPE_BITMAP: + { + Bitmap_Draw(( menubitmap_s * )menu->items[i]); + } break; case MTYPE_ACTION: Action_Draw((menuaction_s *)menu->items[i]); break; @@ -431,7 +451,7 @@ Menu_Draw(menuframework_s *menu) { menu->cursordraw(menu); } - else if (item && (item->type != MTYPE_FIELD)) + else if (item && (item->type != MTYPE_FIELD) && item->type != MTYPE_BITMAP) { if (item->flags & QMF_LEFT_JUSTIFY) { @@ -551,22 +571,13 @@ Menu_ItemAtCursor(menuframework_s *m) qboolean Menu_SelectItem(menuframework_s *s) { - menucommon_s *item = (menucommon_s *)Menu_ItemAtCursor(s); + menucommon_s * item = ( menucommon_s * )Menu_ItemAtCursor(s); - if (item) - { - switch (item->type) - { - case MTYPE_FIELD: - return Field_DoEnter((menufield_s *)item); - case MTYPE_ACTION: - Action_DoEnter((menuaction_s *)item); - return true; - case MTYPE_LIST: - return false; - case MTYPE_SPINCONTROL: - return false; - } + if (item->callback) { + + item->callback(item); + + return true; } return false;