diff options
author | Andrey Nazarov <skuller@skuller.net> | 2007-08-14 20:18:08 +0000 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2007-08-14 20:18:08 +0000 |
commit | f294db4ccf45f6274e65260dd6f9a2c5faa94313 (patch) | |
tree | e8cf1ba2bfe9c8417eec17faf912442f52fc4ef2 /source/ui_demos.c |
Initial import of the new Q2PRO tree.
Diffstat (limited to 'source/ui_demos.c')
-rw-r--r-- | source/ui_demos.c | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/source/ui_demos.c b/source/ui_demos.c new file mode 100644 index 0000000..c2519fa --- /dev/null +++ b/source/ui_demos.c @@ -0,0 +1,431 @@ +/* +Copyright (C) 2003-2006 Andrey Nazarov + +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 "ui_local.h" + +/* +======================================================================= + +DEMOS MENU + +======================================================================= +*/ + +#define MAX_MENU_DEMOS 1024 + +#define DEMO_EXTENSIONS \ + ".dm2;.dm2.gz;" \ + ".dm_35;.dm_35.gz;" \ + ".dm_36;.dm_36.gz;" \ + ".mvd2;.mvd2.gz" + +#define FFILE_UP 1 +#define FFILE_FOLDER 2 +#define FFILE_DEMO 3 + +#define ID_LIST 105 + +typedef struct m_demos_s { + menuFrameWork_t menu; + menuList_t list; + menuList_t playerList; + menuStatic_t banner; + + int count; + char *names[MAX_MENU_DEMOS+1]; + int types[MAX_MENU_DEMOS]; + char *playerNames[MAX_DEMOINFO_CLIENTS+1]; + + // Demo file info + demoInfo_t demo; +} m_demos_t; + +static m_demos_t m_demos; +static char m_demos_browse[MAX_QPATH]; +static int m_demos_selection; + +static void Demos_FreeInfo( void ) { + memset( &m_demos.demo, 0, sizeof( m_demos.demo ) ); + + m_demos.playerList.generic.flags |= QMF_HIDDEN; +} + +static void Demos_LoadInfo( int index ) { + char buffer[MAX_QPATH]; + int i, numNames, localPlayerNum; + + if( m_demos.types[index] != FFILE_DEMO ) { + m_demos.playerList.generic.flags |= QMF_HIDDEN; + m_demos.menu.statusbar = NULL; + return; + } + + Com_sprintf( buffer, sizeof( buffer ), "%s/%s", + m_demos_browse + 1, m_demos.names[index] ); + + client.GetDemoInfo( buffer, &m_demos.demo ); + + if( !m_demos.demo.mapname[0] ) { + m_demos.menu.statusbar = "Couldn't read demo info"; + m_demos.playerList.generic.flags |= QMF_HIDDEN; + return; + } + + + localPlayerNum = 0; + + numNames = 0; + for( i = 0; i < MAX_DEMOINFO_CLIENTS; i++ ) { + if( !m_demos.demo.clients[i][0] ) { + continue; + } + + if( i == m_demos.demo.clientNum ) { + localPlayerNum = numNames; + } + + // ( m_demos.demo.mvd || i == m_demos.demo.clientNum ) ? colorYellow : NULL + + m_demos.playerNames[numNames++] = m_demos.demo.clients[i]; + } + + if( numNames ) { + m_demos.playerList.generic.flags &= ~QMF_HIDDEN; + } else { + m_demos.playerList.generic.flags |= QMF_HIDDEN; + } + + m_demos.playerNames[numNames] = NULL; + + if( m_demos.demo.mvd ) { + m_demos.menu.statusbar = "Press Enter to play"; + } else { + m_demos.menu.statusbar = "Press Enter to play, " + "hold Shift to play on server"; + } + + MenuList_Init( &m_demos.playerList ); + MenuList_SetValue( &m_demos.playerList, localPlayerNum ); +} + +static char *Demos_BuildName( const char *path, const char *name, + fsFileInfo_t *info ) +{ + char buffer[MAX_QPATH]; + demoInfo_t demo; + char *s; + + Com_sprintf( buffer, sizeof( buffer ), "%s/%s", path, name ); + + client.GetDemoInfo( buffer, &demo ); + if( !demo.mapname[0] ) { + return NULL; + } + + Com_sprintf( buffer, sizeof( buffer ), "%4d", info->fileSize >> 10 ); + + if( demo.clientNum >= 0 && demo.clientNum < MAX_DEMOINFO_CLIENTS ) { + s = UI_FormatColumns( 4, name, buffer, demo.mapname, + demo.clients[demo.clientNum] ); + } else { + s = UI_FormatColumns( 3, name, buffer, demo.mapname ); + } + + return s; +} + +static void Demos_BuildList( const char *path ) { + fsFileInfo_t *info; + int numFiles; + char **list, *s; + int pos; + int i; + + if( *path == '/' ) { + path++; + } + + if( *path ) { + m_demos.names[m_demos.count] = UI_FormatColumns( 1, ".." ); + m_demos.types[m_demos.count] = FFILE_UP; + m_demos.count++; + } + + // list directories first + list = fs.ListFiles( path, NULL, FS_PATH_GAME | + FS_SEARCHDIRS_ONLY, &numFiles ); + if( list ) { + if( m_demos.count + numFiles > MAX_MENU_DEMOS ) { + numFiles = MAX_MENU_DEMOS - m_demos.count; + } + for( i = 0; i < numFiles; i++ ) { + m_demos.names[m_demos.count] = UI_FormatColumns( 1, list[i] ); + m_demos.types[m_demos.count] = FFILE_FOLDER; + m_demos.count++; + } + + fs.FreeFileList( list ); + } + + pos = m_demos.count; + + // list demos + list = fs.ListFiles( path, DEMO_EXTENSIONS, FS_PATH_GAME | + FS_SEARCH_EXTRAINFO, &numFiles ); + if( list ) { + if( m_demos.count + numFiles > MAX_MENU_DEMOS ) { + numFiles = MAX_MENU_DEMOS - m_demos.count; + } + for( i = 0; i < numFiles; i++ ) { + info = ( fsFileInfo_t * )( list[i] + strlen( list[i] ) + 1 ); + s = Demos_BuildName( path, list[i], info ); + if( s ) { + m_demos.names[m_demos.count] = s; + m_demos.types[m_demos.count] = FFILE_DEMO; + m_demos.count++; + } + } + + // sort them + qsort( m_demos.names + pos, m_demos.count - pos, + sizeof( m_demos.names[0] ), SortStrcmp ); + + fs.FreeFileList( list ); + } + + // terminate the list + m_demos.names[m_demos.count] = NULL; +} + +static void Demos_Free( void ) { + int i; + + Demos_FreeInfo(); + + for( i = 0; i < m_demos.count; i++ ) { + com.Free( m_demos.names[i] ); + m_demos.names[i] = NULL; + m_demos.types[i] = 0; + } + + m_demos.count = 0; + m_demos.list.curvalue = 0; +} + +static void Demos_LeaveDirectory( void ) { + char buffer[MAX_QPATH]; + char *s; + int i; + + s = strrchr( m_demos_browse, '/' ); + if( s ) { + *s = 0; + strcpy( buffer, s + 1 ); + } else { + buffer[0] = 0; + } + + // rebuild list + Demos_Free(); + Demos_BuildList( m_demos_browse ); + MenuList_Init( &m_demos.list ); + + if( s == m_demos_browse ) { + m_demos_browse[0] = '/'; + m_demos_browse[1] = 0; + } + + // move cursor to the previous directory + if( buffer[0] ) { + for( i = 0; i < m_demos.count; i++ ) { + if( !strcmp( m_demos.names[i], buffer ) ) { + MenuList_SetValue( &m_demos.list, i ); + return; + } + } + } + + MenuList_SetValue( &m_demos.list, 0 ); + +} + +static int Demos_Action( void ) { + char buffer[MAX_QPATH]; + int length, baseLength; + char *c; + + switch( m_demos.types[m_demos.list.curvalue] ) { + case FFILE_UP: + Demos_LeaveDirectory(); + return QMS_OUT; + + case FFILE_FOLDER: + baseLength = strlen( m_demos_browse ); + length = strlen( m_demos.names[m_demos.list.curvalue] ); + if( baseLength + length > sizeof( m_demos_browse ) - 2 ) { + return QMS_BEEP; + } + if( m_demos_browse[ baseLength - 1 ] != '/' ) { + m_demos_browse[ baseLength++ ] = '/'; + } + + strcpy( m_demos_browse + baseLength, + m_demos.names[m_demos.list.curvalue] ); + + // rebuild list + Demos_Free(); + Demos_BuildList( m_demos_browse ); + MenuList_Init( &m_demos.list ); + return QMS_IN; + + case FFILE_DEMO: + if( !m_demos.demo.mapname[0] ) { + return QMS_BEEP; + } + c = m_demos.demo.mvd || keys.IsDown( K_SHIFT ) ? "mvdplay" : "demo"; + Com_sprintf( buffer, sizeof( buffer ), "%s \"%s/%s\"\n", c, + m_demos_browse, m_demos.names[m_demos.list.curvalue] ); + cmd.ExecuteText( EXEC_APPEND, buffer ); + //UI_ForceMenuOff(); + return QMS_SILENT; + } + + return QMS_NOTHANDLED; +} + +static int Demos_MenuCallback( int id, int msg, int param ) { + switch( msg ) { + case QM_ACTIVATE: + switch( id ) { + case ID_LIST: + return Demos_Action(); + } + return QMS_IN; + + case QM_CHANGE: + switch( id ) { + case ID_LIST: + Demos_LoadInfo( m_demos.list.curvalue ); + break; + default: + break; + } + return QMS_MOVE; + + case QM_KEY: + switch( id ) { + case ID_LIST: + switch( param ) { + case K_BACKSPACE: + Demos_LeaveDirectory(); + return QMS_OUT; + default: + break; + } + default: + break; + } + break; + + case QM_DESTROY: + m_demos_selection = m_demos.list.curvalue; // save previous position + Demos_Free(); + break; + + default: + break; + } + + return QMS_NOTHANDLED; +} + +static void Demos_MenuInit( void ) { + int w1, w2; + + memset( &m_demos, 0, sizeof( m_demos ) ); + + m_demos.menu.callback = Demos_MenuCallback; + + // Point to a nice location at startup + if( !m_demos_browse[0] ) { + strcpy( m_demos_browse, "/demos" ); + } + + Demos_BuildList( m_demos_browse ); + + w1 = ( uis.glconfig.vidWidth - 30 ) * 0.8f; + w2 = ( uis.glconfig.vidWidth - 30 ) * 0.2f; + + m_demos.list.generic.type = MTYPE_LIST; + m_demos.list.generic.id = ID_LIST; + m_demos.list.generic.flags = QMF_HASFOCUS; + m_demos.list.generic.x = 10; + m_demos.list.generic.y = 32; + m_demos.list.generic.width = 0; + m_demos.list.generic.height = uis.glconfig.vidHeight - 64; + m_demos.list.generic.name = NULL; + m_demos.list.itemnames = ( const char ** )m_demos.names; + m_demos.list.drawNames = qtrue; + m_demos.list.numcolumns = 4; + + m_demos.list.columns[0].width = w1 - 180; + m_demos.list.columns[0].name = m_demos_browse; + m_demos.list.columns[0].uiFlags = UI_LEFT; + + m_demos.list.columns[1].width = 40; + m_demos.list.columns[1].name = "KiB"; + m_demos.list.columns[1].uiFlags = UI_CENTER; + + m_demos.list.columns[2].width = 60; + m_demos.list.columns[2].name = "Map"; + m_demos.list.columns[2].uiFlags = UI_CENTER; + + m_demos.list.columns[3].width = 80; + m_demos.list.columns[3].name = "POV"; + m_demos.list.columns[3].uiFlags = UI_CENTER; + + m_demos.playerList.generic.type = MTYPE_LIST; + m_demos.playerList.generic.flags = QMF_HIDDEN|QMF_DISABLED; + m_demos.playerList.generic.x = w1 + 20; + m_demos.playerList.generic.y = 32; + m_demos.playerList.generic.height = uis.glconfig.vidHeight - 64; + m_demos.playerList.itemnames = ( const char ** )m_demos.playerNames; + m_demos.playerList.mlFlags = MLF_HIDE_SCROLLBAR_EMPTY; + m_demos.playerList.numcolumns = 1; + m_demos.playerList.drawNames = qtrue; + + m_demos.playerList.columns[0].width = w2; + m_demos.playerList.columns[0].name = "Players"; + m_demos.playerList.columns[0].uiFlags = UI_CENTER; + + UI_SetupDefaultBanner( &m_demos.banner, "Demos" ); + + Menu_AddItem( &m_demos.menu, (void *)&m_demos.list ); + Menu_AddItem( &m_demos.menu, (void *)&m_demos.playerList ); + Menu_AddItem( &m_demos.menu, (void *)&m_demos.banner ); + + // move cursor to previous position + MenuList_SetValue( &m_demos.list, m_demos_selection ); +} + +void M_Menu_Demos_f( void ) { + Demos_MenuInit(); + UI_PushMenu( &m_demos.menu ); +} |