// Copyright (C) 1999-2000 Id Software, Inc. // /* ======================================================================= DEMOS MENU ======================================================================= */ #include "ui_local.h" #include "ui_logger.h" enum ui_Demo2Limits_e { MAX_DEMODISP = 12, MAX_DEMOS = 128, NAMEBUFSIZE = (MAX_DEMOS * 16) }; enum ui_Demo2IDs_e { ID_MAINMENU = 10, ID_ENGAGE, ID_LIST, ID_UP, ID_DOWN, ID_DEMOCOMMENT1 = 110, ID_DEMOCOMMENT2, ID_DEMOCOMMENT3, ID_DEMOCOMMENT4, ID_DEMOCOMMENT5, ID_DEMOCOMMENT6, ID_DEMOCOMMENT7, ID_DEMOCOMMENT8, ID_DEMOCOMMENT9, ID_DEMOCOMMENT10, ID_DEMOCOMMENT11, ID_DEMOCOMMENT12 }; static const char PIC_UNDERLINE[] = "menu/common/underline.tga"; typedef struct { menuframework_s menu; menubitmap_s main; menubitmap_s engage; menulist_s list; menubitmap_s upArrow; menubitmap_s downArrow; qhandle_t currentGameTopLeft; // Upper left corner of current game box qhandle_t currentGameBotLeft; // Bottom left corner of current game box qhandle_t currentGameTopRight; // Upper right corner of current game box qhandle_t directoryUpperCorner1; // Left Upper corner of directory box qhandle_t directoryLowerCorner1; // Left Lower corner of directory box qhandle_t directoryUpperCorner2; // Right Upper corner of directory box menubitmap_s currentFile; int32_t numDemos; char names[NAMEBUFSIZE]; char *demolist[MAX_DEMOS]; int32_t currentDemoIndex; //TiM - Increments whenevever they scroll. used to increment/decrement the list order } demos_t; static demos_t s_demos; menufield_s s_demoline1; menufield_s s_demoline2; menufield_s s_demoline3; menufield_s s_demoline4; menufield_s s_demoline5; menufield_s s_demoline6; menufield_s s_demoline7; menufield_s s_demoline8; menufield_s s_demoline9; menufield_s s_demoline10; menufield_s s_demoline11; menufield_s s_demoline12; static void* g_demoline[] = { &s_demoline1, &s_demoline2, &s_demoline3, &s_demoline4, &s_demoline5, &s_demoline6, &s_demoline7, &s_demoline8, &s_demoline9, &s_demoline10, &s_demoline11, &s_demoline12, NULL, }; /* ================= DemoMenu_PopulateList TiM: Used to fill the controls array with the current list of demos we have ================= */ void DemoMenu_PopulateList(int32_t startingIndex) { UI_LogFuncBegin(); int32_t i = 0, len; char* demoName; while (g_demoline[i]) { if (i >= s_demos.list.numitems) { break; } demoName = s_demos.demolist[startingIndex + i]; //TiM - Error trapping. Altho this should never happen if (!demoName) { ((menubitmap_s *)g_demoline[i])->generic.flags = QMF_INACTIVE | QMF_HIDDEN; continue; } // No demos??? if (s_demos.list.numitems == 1) { if (!strcmp(demoName, menu_normal_text[MNT_NO_DEMOS_FOUND])) { ((menubitmap_s *)g_demoline[i])->generic.flags = QMF_INACTIVE; } } // strip extension len = strlen(demoName); if (len > 7 && !Q_stricmp(demoName + len - 7, ".efdemo")) { demoName[len - 7] = '\0'; } Q_strupr(demoName); ((menubitmap_s *)g_demoline[i])->textPtr = demoName; ((menubitmap_s *)g_demoline[i])->generic.flags = QMF_HIGHLIGHT_IF_FOCUS; i++; } UI_LogFuncEnd(); } /* ================= DemoMenu_Graphics ================= */ static void DemoMenu_Graphics(void) { UI_LogFuncBegin(); // Draw the basic screen layout UI_MenuFrame(&s_demos.menu); UI_DrawProportionalString(74, 66, "88134-7", UI_RIGHT | UI_TINYFONT, colorTable[CT_BLACK]); UI_DrawProportionalString(74, 84, "56-0990", UI_RIGHT | UI_TINYFONT, colorTable[CT_BLACK]); UI_DrawProportionalString(74, 188, "3456", UI_RIGHT | UI_TINYFONT, colorTable[CT_BLACK]); UI_DrawProportionalString(74, 206, "7618", UI_RIGHT | UI_TINYFONT, colorTable[CT_BLACK]); UI_DrawProportionalString(74, 395, "692", UI_RIGHT | UI_TINYFONT, colorTable[CT_BLACK]); trap_R_SetColor(colorTable[CT_DKBLUE2]); UI_DrawHandlePic(30, 203, 47, 130, uis.whiteShader); // Top left column square on bottom 2 3rds UI_DrawHandlePic(30, 336, 47, 16, uis.whiteShader); // Middle left column square on bottom 2 3rds UI_DrawHandlePic(30, 355, 47, 34, uis.whiteShader); // Bottom left column square on bottom 2 3rds // Numbers for left hand side UI_DrawProportionalString(74, 206, "52662", UI_RIGHT | UI_TINYFONT, colorTable[CT_BLACK]); UI_DrawProportionalString(74, 339, "662", UI_RIGHT | UI_TINYFONT, colorTable[CT_BLACK]); UI_DrawProportionalString(74, 358, "101235", UI_RIGHT | UI_TINYFONT, colorTable[CT_BLACK]); // Current game box trap_R_SetColor(colorTable[CT_DKPURPLE2]); UI_DrawHandlePic(130, 64, 88, 24, uis.whiteShader); // Left Side of current game line box 3 UI_DrawHandlePic(218, 64, 320, 3, uis.whiteShader); // Top of current game line UI_DrawHandlePic(218, 85, 320, 3, uis.whiteShader); // Bottom of current game line UI_DrawHandlePic(516, 64, 44, 24, uis.whiteShader); // Right side of current game line UI_DrawHandlePic(113, 64, 32, 32, s_demos.currentGameTopLeft); // Upper left corner of current game box UI_DrawHandlePic(113, 97, 32, 32, s_demos.currentGameBotLeft); // Bottom left corner of current game box UI_DrawHandlePic(559, 64, 32, 32, s_demos.currentGameTopRight); // Upper right corner of current game box UI_DrawHandlePic(552, 97, -32, 32, s_demos.currentGameBotLeft); // Bottom right corner of current game box UI_DrawHandlePic(113, 91, 18, 6, uis.whiteShader); // Left side of current game line UI_DrawHandlePic(566, 91, 18, 6, uis.whiteShader); // Right side of current game line UI_DrawHandlePic(138, 101, 142, 18, uis.whiteShader); // Lower bar to left side of 'engage' UI_DrawHandlePic(416, 101, 143, 18, uis.whiteShader); // Lower bar to right side of 'engage' // Available Demos trap_R_SetColor(colorTable[CT_DKPURPLE2]); UI_DrawHandlePic(189, 168, 32, 32, s_demos.directoryUpperCorner1); // Left Upper corner of directory box UI_DrawHandlePic(189, 421, 32, 32, s_demos.directoryLowerCorner1); // Left Lower corner of directory box UI_DrawHandlePic(481, 168, 32, 32, s_demos.directoryUpperCorner2); // Right Upper corner of directory box UI_DrawHandlePic(470, 421, -32, 32, s_demos.directoryLowerCorner1); // Right Lower corner of directory box UI_DrawHandlePic(205, 168, 277, 18, uis.whiteShader); // Top bar UI_DrawHandlePic(189, 193, 16, 224, uis.whiteShader); // Left column {//TiM - Arrow Boxes UI_DrawHandlePic(485, 193, 16, 16, uis.whiteShader); // Up Arrow UI_DrawHandlePic(485, 212, 16, 187, uis.whiteShader); // Right column UI_DrawHandlePic(485, 402, 16, 16, uis.whiteShader); // Down Arrow } UI_DrawHandlePic(205, 424, 277, 8, uis.whiteShader); // Bottom bar UI_DrawProportionalString(124, 67, "67B", UI_TINYFONT, colorTable[CT_BLACK]); UI_DrawProportionalString(220, 169, menu_normal_text[MNT_CURRENTDEMOSAVAILABLE], UI_SMALLFONT, colorTable[CT_BLACK]); UI_LogFuncEnd(); } /* ================= Demos_MenuDraw ================= */ static void Demos_MenuDraw(void) { UI_LogFuncBegin(); // Draw graphics particular to Demo Menu DemoMenu_Graphics(); Menu_Draw(&s_demos.menu); UI_LogFuncEnd(); } /* =============== Demos_MenuEvent =============== */ static void Demos_MenuEvent(void *ptr, int32_t event) { UI_LogFuncBegin(); int32_t index; if (event != QM_ACTIVATED) { UI_LogFuncEnd(); return; } switch (((menucommon_s*)ptr)->id) { case ID_UP: s_demos.currentDemoIndex--; if (s_demos.currentDemoIndex < 0) s_demos.currentDemoIndex = 0; DemoMenu_PopulateList(s_demos.currentDemoIndex); break; case ID_DOWN: s_demos.currentDemoIndex++; //TiM - cap it when the final entry is in view if (s_demos.list.numitems > MAX_DEMODISP && (s_demos.currentDemoIndex + MAX_DEMODISP) > s_demos.list.numitems) s_demos.currentDemoIndex = s_demos.list.numitems - MAX_DEMODISP; DemoMenu_PopulateList(s_demos.currentDemoIndex); break; case ID_DEMOCOMMENT1: case ID_DEMOCOMMENT2: case ID_DEMOCOMMENT3: case ID_DEMOCOMMENT4: case ID_DEMOCOMMENT5: case ID_DEMOCOMMENT6: case ID_DEMOCOMMENT7: case ID_DEMOCOMMENT8: case ID_DEMOCOMMENT9: case ID_DEMOCOMMENT10: case ID_DEMOCOMMENT11: case ID_DEMOCOMMENT12: index = ((menucommon_s*)ptr)->id - ID_DEMOCOMMENT1; if (((menubitmap_s *)g_demoline[index])->textPtr) { //s_demos.currentDemoIndex = index; s_demos.currentFile.textPtr = (((menubitmap_s *)g_demoline[index])->textPtr); //make it so s_demos.engage.generic.flags = QMF_HIGHLIGHT_IF_FOCUS; } break; case ID_ENGAGE: UI_ForceMenuOff(); trap_Cmd_ExecuteText(EXEC_APPEND, va("demo %s.efdemo\n", s_demos.currentFile.textPtr)); break; case ID_MAINMENU: UI_PopMenu(); break; } UI_LogFuncEnd(); } /* ================= UI_DemosMenu_Key ================= */ static sfxHandle_t UI_DemosMenu_Key(int32_t key) { UI_LogFuncBegin(); UI_LogFuncEnd(); return Menu_DefaultKey(&s_demos.menu, key); } /* =============== UI_DemosMenu_Cache =============== */ void UI_DemosMenu_Cache(void) { UI_LogFuncBegin(); s_demos.currentGameTopLeft = trap_R_RegisterShaderNoMip("menu/common/corner_ul_18_24.tga"); s_demos.currentGameBotLeft = trap_R_RegisterShaderNoMip("menu/common/corner_ll_18_18.tga"); s_demos.currentGameTopRight = trap_R_RegisterShaderNoMip("menu/common/corner_ur_18_24.tga"); s_demos.directoryUpperCorner1 = trap_R_RegisterShaderNoMip("menu/common/corner_ul_16_18.tga"); s_demos.directoryLowerCorner1 = trap_R_RegisterShaderNoMip("menu/common/corner_ll_8_16.tga"); s_demos.directoryUpperCorner2 = trap_R_RegisterShaderNoMip("menu/common/corner_ur_16_18.tga"); trap_R_RegisterShaderNoMip("menu/common/arrow_up_16.tga"); trap_R_RegisterShaderNoMip("menu/common/arrow_dn_16.tga"); trap_R_RegisterShaderNoMip(PIC_UNDERLINE); UI_LogFuncEnd(); } /* =============== Demos_MenuInit =============== */ static void Demos_MenuInit(void) { UI_LogFuncBegin(); int32_t i, x, y; int32_t len; char *demoname; memset(&s_demos, 0, sizeof(demos_t)); s_demos.menu.key = UI_DemosMenu_Key; UI_DemosMenu_Cache(); s_demos.menu.fullscreen = qtrue; s_demos.menu.wrapAround = qtrue; s_demos.menu.draw = Demos_MenuDraw; s_demos.menu.descX = MENU_DESC_X; s_demos.menu.descY = MENU_DESC_Y; s_demos.menu.titleX = MENU_TITLE_X; s_demos.menu.titleY = MENU_TITLE_Y; s_demos.menu.titleI = MNT_DEMOS_TITLE; s_demos.menu.footNoteEnum = MNT_DEMOS; s_demos.main.generic.type = MTYPE_BITMAP; s_demos.main.generic.flags = QMF_HIGHLIGHT_IF_FOCUS; s_demos.main.generic.x = 482; s_demos.main.generic.y = 136; s_demos.main.generic.name = BUTTON_GRAPHIC_LONGRIGHT; s_demos.main.generic.id = ID_MAINMENU; s_demos.main.generic.callback = Demos_MenuEvent; s_demos.main.width = MENU_BUTTON_MED_WIDTH; s_demos.main.height = MENU_BUTTON_MED_HEIGHT; s_demos.main.color = CT_DKPURPLE1; s_demos.main.color2 = CT_LTPURPLE1; s_demos.main.textX = MENU_BUTTON_TEXT_X; s_demos.main.textY = MENU_BUTTON_TEXT_Y; s_demos.main.textEnum = MBT_MAINMENU; s_demos.main.textcolor = CT_BLACK; s_demos.main.textcolor2 = CT_WHITE; s_demos.engage.generic.type = MTYPE_BITMAP; s_demos.engage.generic.flags = (QMF_INACTIVE | QMF_GRAYED); s_demos.engage.generic.x = 283; s_demos.engage.generic.y = 101; s_demos.engage.generic.name = GRAPHIC_SQUARE; s_demos.engage.generic.id = ID_ENGAGE; s_demos.engage.generic.callback = Demos_MenuEvent; s_demos.engage.width = MENU_BUTTON_MED_WIDTH; s_demos.engage.height = MENU_BUTTON_MED_HEIGHT; s_demos.engage.color = CT_DKPURPLE1; s_demos.engage.color2 = CT_LTPURPLE1; s_demos.engage.textX = MENU_BUTTON_TEXT_X; s_demos.engage.textY = MENU_BUTTON_TEXT_Y; s_demos.engage.textEnum = MBT_ENGAGEDEMO; s_demos.engage.textcolor = CT_BLACK; s_demos.engage.textcolor2 = CT_WHITE; s_demos.upArrow.generic.type = MTYPE_BITMAP; s_demos.upArrow.generic.flags = (QMF_INACTIVE | QMF_GRAYED); s_demos.upArrow.generic.x = 486; s_demos.upArrow.generic.y = 195; s_demos.upArrow.generic.name = "menu/common/arrow_up_16.tga"; s_demos.upArrow.generic.id = ID_UP; s_demos.upArrow.generic.callback = Demos_MenuEvent; s_demos.upArrow.width = 14; s_demos.upArrow.height = 14; s_demos.upArrow.color = CT_DKGOLD1;; s_demos.upArrow.color2 = CT_LTGOLD1;; s_demos.upArrow.textcolor = CT_BLACK; s_demos.upArrow.textcolor2 = CT_WHITE; s_demos.downArrow.generic.type = MTYPE_BITMAP; s_demos.downArrow.generic.flags = (QMF_INACTIVE | QMF_GRAYED); s_demos.downArrow.generic.x = 486; s_demos.downArrow.generic.y = 404; s_demos.downArrow.generic.name = "menu/common/arrow_dn_16.tga"; s_demos.downArrow.generic.id = ID_DOWN; s_demos.downArrow.generic.callback = Demos_MenuEvent; s_demos.downArrow.width = 14; s_demos.downArrow.height = 14; s_demos.downArrow.color = CT_DKGOLD1; s_demos.downArrow.color2 = CT_LTGOLD1; s_demos.downArrow.textcolor = CT_BLACK; s_demos.downArrow.textcolor2 = CT_WHITE; s_demos.currentFile.generic.type = MTYPE_BITMAP; s_demos.currentFile.generic.flags = QMF_INACTIVE; s_demos.currentFile.generic.x = 218; s_demos.currentFile.generic.y = 68; s_demos.currentFile.generic.name = BUTTON_GRAPHIC_LONGRIGHT; s_demos.currentFile.generic.id = ID_MAINMENU; s_demos.currentFile.generic.callback = Demos_MenuEvent; s_demos.currentFile.width = MENU_BUTTON_MED_WIDTH; s_demos.currentFile.height = MENU_BUTTON_MED_HEIGHT; s_demos.currentFile.color = CT_BLACK; s_demos.currentFile.color2 = CT_BLACK; s_demos.currentFile.textX = MENU_BUTTON_TEXT_X; s_demos.currentFile.textY = MENU_BUTTON_TEXT_Y; s_demos.currentFile.textEnum = MNT_NONE; s_demos.currentFile.textPtr = NULL; s_demos.currentFile.textcolor = CT_YELLOW; s_demos.list.generic.type = MTYPE_SCROLLLIST; s_demos.list.generic.flags = QMF_PULSEIFFOCUS; s_demos.list.generic.callback = Demos_MenuEvent; s_demos.list.generic.id = ID_LIST; s_demos.list.generic.x = 118; s_demos.list.generic.y = 170; s_demos.list.width = 16; s_demos.list.height = 14; s_demos.list.numitems = trap_FS_GetFileList("demos", ".efdemo", s_demos.names, NAMEBUFSIZE); s_demos.list.itemnames = (const char **)s_demos.demolist; s_demos.list.columns = 3; x = 225; y = 200; i = 0; while (g_demoline[i]) { ((menubitmap_s *)g_demoline[i])->generic.type = MTYPE_BITMAP; ((menubitmap_s *)g_demoline[i])->generic.flags = QMF_INACTIVE | QMF_HIDDEN; ((menubitmap_s *)g_demoline[i])->generic.x = x; ((menubitmap_s *)g_demoline[i])->generic.y = y; ((menubitmap_s *)g_demoline[i])->generic.name = PIC_UNDERLINE; ((menubitmap_s *)g_demoline[i])->generic.callback = Demos_MenuEvent; ((menubitmap_s *)g_demoline[i])->generic.id = ID_DEMOCOMMENT1 + i; ((menubitmap_s *)g_demoline[i])->width = 240; ((menubitmap_s *)g_demoline[i])->height = 16; ((menubitmap_s *)g_demoline[i])->color = CT_DKPURPLE1; ((menubitmap_s *)g_demoline[i])->color2 = CT_LTPURPLE1; ((menubitmap_s *)g_demoline[i])->textPtr = NULL; ((menubitmap_s *)g_demoline[i])->textX = 4; ((menubitmap_s *)g_demoline[i])->textY = 1; ((menubitmap_s *)g_demoline[i])->textcolor = CT_DKGOLD1; ((menubitmap_s *)g_demoline[i])->textcolor2 = CT_LTGOLD1; ((menubitmap_s *)g_demoline[i])->textStyle = UI_TINYFONT; // ((menubitmap_s *)g_demoline[i])->textEnum = MBT_DEMOLINE; Menu_AddItem(&s_demos.menu, (void *)g_demoline[i]); y += 18; ++i; } // No demos?? if (!s_demos.list.numitems) { strcpy(s_demos.names, menu_normal_text[MNT_NO_DEMOS_FOUND]); s_demos.list.numitems = 1; } else if (s_demos.list.numitems > MAX_DEMOS) {// Too many demos??? s_demos.list.numitems = MAX_DEMOS; } //TiM - If the list is longer than we can fit, enable the scroll buttons if (s_demos.list.numitems > MAX_DEMODISP) { s_demos.upArrow.generic.flags = QMF_HIGHLIGHT_IF_FOCUS; s_demos.downArrow.generic.flags = QMF_HIGHLIGHT_IF_FOCUS; } // Point fields to demo names i = 0; demoname = s_demos.names; //TiM - instead of sending the list names directly to the controls, we'll populate an array //with them and then selectively add the ones we want at the time to the controls. :) while (i < s_demos.list.numitems) { if (!demoname) break; // strip extension len = strlen(demoname); if (len>7 && !Q_stricmp(demoname + len - 7, ".efdemo")) { demoname[len - 7] = '\0'; } //Q_strupr(demoname); //insert into the array s_demos.demolist[i] = demoname; //increment demoname += len + 1; i++; } //Populate the controls with the values from the array DemoMenu_PopulateList(s_demos.currentDemoIndex); Menu_AddItem(&s_demos.menu, &s_demos.main); // Menu_AddItem( &s_demos.menu, &s_demos.list ); Menu_AddItem(&s_demos.menu, &s_demos.engage); Menu_AddItem(&s_demos.menu, &s_demos.currentFile); Menu_AddItem(&s_demos.menu, &s_demos.upArrow); Menu_AddItem(&s_demos.menu, &s_demos.downArrow); UI_LogFuncEnd(); } /* =============== UI_DemosMenu =============== */ void UI_DemosMenu(void) { UI_LogFuncBegin(); Demos_MenuInit(); UI_PushMenu(&s_demos.menu); UI_LogFuncEnd(); }