/* Copyright (C) 1997-2001 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "ui_local.h" /* ============================================================================= DEMOS MENU ============================================================================= */ void Demos_MenuInit( void ); static menuframework_s s_demos_menu; //===================================================================== // PATH //===================================================================== // the current working directory // init with demos // each time we go in a new folder we append /name to cwd // when user press backspace we go back one folder: // ie: we reverse search for a / and replace by a \0 char cwd[MAX_QPATH]; //===================================================================== // Items list //===================================================================== //#define MAX_MENU_LIST_ITEMS 15 static int MAX_MENU_LIST_ITEMS = 15; m_itemslisthead_t demosItemsList; void M_Demos_PreviousFolder(void) { // go back to previous folder char *slash; slash=strrchr(cwd, '/'); if(slash!=NULL) { // erase prev folder *slash='\0'; // rebuild list Demos_MenuInit(); } } //================== //M_Demos_CreateFolderList //================== void M_Demos_CreateFolderList( void ) { char *s; char buffer[8*1024]; int numfolders; int length; int i; char foldername[MAX_QPATH]; if( (numfolders = trap_FS_GetFileList( cwd, "/", buffer, sizeof(buffer) )) == 0 ) return; s = buffer; length = 0; for ( i = 0; i < numfolders; i++, s += length+1 ) { length = strlen( s ); Q_strncpyz( foldername, s, sizeof(foldername) ); foldername[length-1]='\0'; // to remove the ending slash UI_AddItemToScrollList( &demosItemsList, foldername, NULL ); } } //================== //M_Demos_CreateDemosList //================== void M_Demos_CreateDemosList( void ) { char *s; char buffer[8*1024]; int numdemos; int length; int i; char demoname[MAX_QPATH]; if( (numdemos = trap_FS_GetFileList( cwd, va(".wd%d",PROTOCOL_VERSION), buffer, sizeof(buffer) )) == 0 ) return; s = buffer; length = 0; for ( i = 0; i < numdemos; i++, s += length+1 ) { length = strlen( s ); Q_strncpyz( demoname, s, sizeof(demoname) ); demoname[length]='\0'; UI_AddItemToScrollList( &demosItemsList, demoname, NULL ); } } //================== //M_Demos_CreateItemList //================== void M_Demos_CreateItemList( void ) { // first free the current list UI_FreeScrollItemList( &demosItemsList ); // get all the folders M_Demos_CreateFolderList(); // get all the demos M_Demos_CreateDemosList(); } //===================================================================== // Buttons & actions //===================================================================== #define NO_ITEM_STRING "" static int scrollbar_curvalue = 0; //================== //M_Connect_UpdateScrollbar //================== void M_Demos_UpdateScrollbar( menucommon_t *menuitem ) { scrollbar_curvalue = menuitem->curvalue; menuitem->maxvalue = max( 0, demosItemsList.numItems - MAX_MENU_LIST_ITEMS ); } //================== //M_Demo_Playdemo //================== void M_Demo_Playdemo( menucommon_t *menuitem ) { char buffer[MAX_STRING_CHARS]; m_listitem_t *item; menuitem->localdata[1] = menuitem->localdata[0] + scrollbar_curvalue; item = UI_FindItemInScrollListWithId( &demosItemsList, menuitem->localdata[1] ); if( item ) { if( item->name) { // can be a demos or a folder if(strstr(item->name,va(".wd%d",PROTOCOL_VERSION))!=NULL) { // it is a demos //cwd is "demos/path" // we need to remove demos char *slash=strchr(cwd,'/'); if(slash==NULL) Q_snprintfz( buffer, sizeof(buffer), "demo \"%s\"\n", item->name ); else { slash++; // skip the slash trap_Print(va("demo %s/%s\n", slash, item->name)); Q_snprintfz( buffer, sizeof(buffer), va("demo \"%s/%s\"\n", slash,item->name) ); } trap_Cmd_ExecuteText( EXEC_APPEND, buffer ); } else { // it is a folder int len=strlen(item->name)+1; // sanity if(strlen(cwd)+len>MAX_QPATH) { UI_Printf("Max sub folder limit reached\n"); return; } // add /name to cwd strcat(cwd, va("/%s", item->name)); // rebuild the lists Demos_MenuInit(); } } } } //================== //M_Demo_DemoButton //================== void M_Demo_UpdateButton( menucommon_t *menuitem ) { m_listitem_t *item; menuitem->localdata[1] = menuitem->localdata[0] + scrollbar_curvalue; item = UI_FindItemInScrollListWithId( &demosItemsList, menuitem->localdata[1] ); if( item ) { Q_snprintfz(menuitem->title, MAX_STRING_CHARS, item->name); } else Q_snprintfz(menuitem->title, MAX_STRING_CHARS, NO_ITEM_STRING); } //================== //Demos_MenuInit //================== void Demos_MenuInit( void ) { char path[MAX_QPATH]; menucommon_t *menuitem; int i; int y = 0; int yoffset; int scrollwindow_width, scrollwindow_height; yoffset = UI_SCALED_HEIGHT(56); // left space for the logo // scroll window width if( uis.vidWidth < 800 ) scrollwindow_width = uis.vidWidth * 0.85; else if( uis.vidWidth < 1024 ) scrollwindow_width = uis.vidWidth * 0.75; else scrollwindow_width = uis.vidWidth * 0.65; s_demos_menu.x = uis.vidWidth / 2; s_demos_menu.nitems = 0; // build the list folder and demos M_Demos_CreateItemList(); // title menuitem = UI_InitMenuItem( "m_demos_title1", "DEMOS", 0, y+yoffset, MTYPE_SEPARATOR, ALIGN_CENTER_TOP, uis.fontSystemBig, NULL ); Menu_AddItem( &s_demos_menu, menuitem ); yoffset += trap_SCR_strHeight( menuitem->font ); // current folder Q_snprintfz( path, sizeof(path), "%sCurrent folder: %s%s", S_COLOR_YELLOW, S_COLOR_WHITE, cwd ); menuitem = UI_InitMenuItem("m_demos_folder", path, -(scrollwindow_width/2), y+yoffset, MTYPE_SEPARATOR, ALIGN_LEFT_TOP, uis.fontSystemSmall, NULL ); Menu_AddItem( &s_demos_menu, menuitem ); yoffset += trap_SCR_strHeight( menuitem->font ); // Back button (back in demo browser) menuitem = UI_InitMenuItem( "m_demo_button_back", "Directory up", -(scrollwindow_width/2), y+yoffset, MTYPE_ACTION, ALIGN_LEFT_TOP, uis.fontSystemSmall, M_Demos_PreviousFolder ); menuitem->statusbar = "press for previous folder"; Menu_AddItem( &s_demos_menu, menuitem ); yoffset += trap_SCR_strHeight( menuitem->font ); yoffset += trap_SCR_strHeight( menuitem->font ); // scrollbar scrollwindow_height = uis.vidHeight - ( yoffset + ( 2 * trap_SCR_strHeight( uis.fontSystemBig ) ) ); MAX_MENU_LIST_ITEMS = ( scrollwindow_height / trap_SCR_strHeight( uis.fontSystemSmall ) ) - 6; // 6 lines left for back button if( MAX_MENU_LIST_ITEMS < 5 ) MAX_MENU_LIST_ITEMS = 5; menuitem = UI_InitMenuItem( "m_demos_scrollbar", NULL, -((scrollwindow_width*0.5)+16), y+yoffset, MTYPE_SCROLLBAR, ALIGN_CENTER_TOP, uis.fontSystemSmall, M_Demos_UpdateScrollbar ); UI_SetupScrollbar( menuitem, MAX_MENU_LIST_ITEMS-1, 0, 0, 0 ); Menu_AddItem( &s_demos_menu, menuitem ); // demos/folder buttons for( i = 0; i < MAX_MENU_LIST_ITEMS; i++ ) { menuitem = UI_InitMenuItem( va("m_demos_button_%i", i), NO_ITEM_STRING, -(scrollwindow_width*0.5), y+yoffset, MTYPE_ACTION, ALIGN_LEFT_TOP, uis.fontSystemSmall, M_Demo_Playdemo ); menuitem->statusbar = "press ENTER to play demos/enter folder, BACKSPACE for previous folder"; menuitem->ownerdraw = M_Demo_UpdateButton; menuitem->localdata[0] = i; // line in the window menuitem->localdata[1] = i; // line in list menuitem->width = scrollwindow_width; // adjust strings to this width Menu_AddItem( &s_demos_menu, menuitem ); // create an associated picture to the items to act as window background menuitem->pict.shader = uis.whiteShader; menuitem->pict.shaderHigh = uis.whiteShader; Vector4Copy( colorWhite, menuitem->pict.colorHigh ); Vector4Copy( ( i & 1 )?colorDkGrey:colorMdGrey, menuitem->pict.color ); menuitem->pict.color[3] = menuitem->pict.colorHigh[3] = 0.65f; menuitem->pict.yoffset = 0; menuitem->pict.xoffset = 0; menuitem->pict.width = scrollwindow_width; menuitem->pict.height = trap_SCR_strHeight( menuitem->font ); yoffset += trap_SCR_strHeight( menuitem->font ); } yoffset += trap_SCR_strHeight( menuitem->font ); // back (to previous menu) menuitem = UI_InitMenuItem( "m_demos_back", "back", 0, y+yoffset, MTYPE_ACTION, ALIGN_CENTER_TOP, uis.fontSystemBig, M_genericBackFunc ); Menu_AddItem( &s_demos_menu, menuitem ); yoffset += trap_SCR_strHeight( menuitem->font ); Menu_Center( &s_demos_menu ); Menu_Init( &s_demos_menu ); } void Demos_MenuDraw(void) { Menu_Draw( &s_demos_menu ); } const char *Demos_MenuKey( int key ) { menucommon_t *item; item = Menu_ItemAtCursor( &s_demos_menu ); if ( key == K_ESCAPE || ( (key == K_MOUSE2) && (item->type != MTYPE_SPINCONTROL) && (item->type != MTYPE_SLIDER)) ) { UI_FreeScrollItemList( &demosItemsList ); } else if( key == K_BACKSPACE ) { M_Demos_PreviousFolder(); } return Default_MenuKey( &s_demos_menu, key ); } const char *Demos_MenuCharEvent( int key ) { return Default_MenuCharEvent( &s_demos_menu, key ); } void M_Menu_Demos_f( void ) { // init current working directory memset(cwd, '\0', sizeof(cwd)); Q_snprintfz(cwd, sizeof(cwd), "demos"); // lets go Demos_MenuInit(); M_PushMenu( &s_demos_menu, Demos_MenuDraw, Demos_MenuKey, Demos_MenuCharEvent ); }