ui_mods.c (7299B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 // 23 #include "ui_local.h" 24 25 #define ART_BACK0 "menu/art/back_0" 26 #define ART_BACK1 "menu/art/back_1" 27 #define ART_FIGHT0 "menu/art/load_0" 28 #define ART_FIGHT1 "menu/art/load_1" 29 #define ART_FRAMEL "menu/art/frame2_l" 30 #define ART_FRAMER "menu/art/frame1_r" 31 32 #define MAX_MODS 64 33 #define NAMEBUFSIZE ( MAX_MODS * 48 ) 34 #define GAMEBUFSIZE ( MAX_MODS * 16 ) 35 36 #define ID_BACK 10 37 #define ID_GO 11 38 #define ID_LIST 12 39 40 41 typedef struct { 42 menuframework_s menu; 43 44 menutext_s banner; 45 menubitmap_s framel; 46 menubitmap_s framer; 47 48 menulist_s list; 49 50 menubitmap_s back; 51 menubitmap_s go; 52 53 char description[NAMEBUFSIZE]; 54 char fs_game[GAMEBUFSIZE]; 55 56 char *descriptionPtr; 57 char *fs_gamePtr; 58 59 char *descriptionList[MAX_MODS]; 60 char *fs_gameList[MAX_MODS]; 61 } mods_t; 62 63 static mods_t s_mods; 64 65 66 /* 67 =============== 68 UI_Mods_MenuEvent 69 =============== 70 */ 71 static void UI_Mods_MenuEvent( void *ptr, int event ) { 72 if( event != QM_ACTIVATED ) { 73 return; 74 } 75 76 switch ( ((menucommon_s*)ptr)->id ) { 77 case ID_GO: 78 trap_Cvar_Set( "fs_game", s_mods.fs_gameList[s_mods.list.curvalue] ); 79 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart;" ); 80 UI_PopMenu(); 81 break; 82 83 case ID_BACK: 84 UI_PopMenu(); 85 break; 86 } 87 } 88 89 90 /* 91 =============== 92 UI_Mods_ParseInfos 93 =============== 94 */ 95 static void UI_Mods_ParseInfos( char *modDir, char *modDesc ) { 96 s_mods.fs_gameList[s_mods.list.numitems] = s_mods.fs_gamePtr; 97 Q_strncpyz( s_mods.fs_gamePtr, modDir, 16 ); 98 99 s_mods.descriptionList[s_mods.list.numitems] = s_mods.descriptionPtr; 100 Q_strncpyz( s_mods.descriptionPtr, modDesc, 48 ); 101 102 s_mods.list.itemnames[s_mods.list.numitems] = s_mods.descriptionPtr; 103 s_mods.descriptionPtr += strlen( s_mods.descriptionPtr ) + 1; 104 s_mods.fs_gamePtr += strlen( s_mods.fs_gamePtr ) + 1; 105 s_mods.list.numitems++; 106 } 107 108 109 #if 0 // bk001204 - unused 110 /* 111 =============== 112 UI_Mods_LoadModsFromFile 113 =============== 114 */ 115 static void UI_Mods_LoadModsFromFile( char *filename ) { 116 int len; 117 fileHandle_t f; 118 char buf[1024]; 119 120 len = trap_FS_FOpenFile( filename, &f, FS_READ ); 121 if ( !f ) { 122 trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) ); 123 return; 124 } 125 if ( len >= sizeof(buf) ) { 126 trap_Print( va( S_COLOR_RED "file too large: %s is %i, max allowed is %i", filename, len, sizeof(buf) ) ); 127 trap_FS_FCloseFile( f ); 128 return; 129 } 130 131 trap_FS_Read( buf, len, f ); 132 buf[len] = 0; 133 trap_FS_FCloseFile( f ); 134 135 len = strlen( filename ); 136 if( !Q_stricmp(filename + len - 4,".mod") ) { 137 filename[len-4] = '\0'; 138 } 139 140 UI_Mods_ParseInfos( filename, buf ); 141 } 142 #endif 143 144 145 /* 146 =============== 147 UI_Mods_LoadMods 148 =============== 149 */ 150 static void UI_Mods_LoadMods( void ) { 151 int numdirs; 152 char dirlist[2048]; 153 char *dirptr; 154 char *descptr; 155 int i; 156 int dirlen; 157 158 s_mods.list.itemnames = (const char **)s_mods.descriptionList; 159 s_mods.descriptionPtr = s_mods.description; 160 s_mods.fs_gamePtr = s_mods.fs_game; 161 162 // always start off with baseq3 163 s_mods.list.numitems = 1; 164 s_mods.list.itemnames[0] = s_mods.descriptionList[0] = "Quake III Arena"; 165 s_mods.fs_gameList[0] = ""; 166 167 numdirs = trap_FS_GetFileList( "$modlist", "", dirlist, sizeof(dirlist) ); 168 dirptr = dirlist; 169 for( i = 0; i < numdirs; i++ ) { 170 dirlen = strlen( dirptr ) + 1; 171 descptr = dirptr + dirlen; 172 UI_Mods_ParseInfos( dirptr, descptr); 173 dirptr += dirlen + strlen(descptr) + 1; 174 } 175 176 trap_Print( va( "%i mods parsed\n", s_mods.list.numitems ) ); 177 if (s_mods.list.numitems > MAX_MODS) { 178 s_mods.list.numitems = MAX_MODS; 179 } 180 } 181 182 183 /* 184 =============== 185 UI_Mods_MenuInit 186 =============== 187 */ 188 static void UI_Mods_MenuInit( void ) { 189 UI_ModsMenu_Cache(); 190 191 memset( &s_mods, 0 ,sizeof(mods_t) ); 192 s_mods.menu.wrapAround = qtrue; 193 s_mods.menu.fullscreen = qtrue; 194 195 s_mods.banner.generic.type = MTYPE_BTEXT; 196 s_mods.banner.generic.x = 320; 197 s_mods.banner.generic.y = 16; 198 s_mods.banner.string = "MODS"; 199 s_mods.banner.color = color_white; 200 s_mods.banner.style = UI_CENTER; 201 202 s_mods.framel.generic.type = MTYPE_BITMAP; 203 s_mods.framel.generic.name = ART_FRAMEL; 204 s_mods.framel.generic.flags = QMF_INACTIVE; 205 s_mods.framel.generic.x = 0; 206 s_mods.framel.generic.y = 78; 207 s_mods.framel.width = 256; 208 s_mods.framel.height = 329; 209 210 s_mods.framer.generic.type = MTYPE_BITMAP; 211 s_mods.framer.generic.name = ART_FRAMER; 212 s_mods.framer.generic.flags = QMF_INACTIVE; 213 s_mods.framer.generic.x = 376; 214 s_mods.framer.generic.y = 76; 215 s_mods.framer.width = 256; 216 s_mods.framer.height = 334; 217 218 s_mods.back.generic.type = MTYPE_BITMAP; 219 s_mods.back.generic.name = ART_BACK0; 220 s_mods.back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; 221 s_mods.back.generic.id = ID_BACK; 222 s_mods.back.generic.callback = UI_Mods_MenuEvent; 223 s_mods.back.generic.x = 0; 224 s_mods.back.generic.y = 480-64; 225 s_mods.back.width = 128; 226 s_mods.back.height = 64; 227 s_mods.back.focuspic = ART_BACK1; 228 229 s_mods.go.generic.type = MTYPE_BITMAP; 230 s_mods.go.generic.name = ART_FIGHT0; 231 s_mods.go.generic.flags = QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS; 232 s_mods.go.generic.id = ID_GO; 233 s_mods.go.generic.callback = UI_Mods_MenuEvent; 234 s_mods.go.generic.x = 640; 235 s_mods.go.generic.y = 480-64; 236 s_mods.go.width = 128; 237 s_mods.go.height = 64; 238 s_mods.go.focuspic = ART_FIGHT1; 239 240 // scan for mods 241 s_mods.list.generic.type = MTYPE_SCROLLLIST; 242 s_mods.list.generic.flags = QMF_PULSEIFFOCUS|QMF_CENTER_JUSTIFY; 243 s_mods.list.generic.callback = UI_Mods_MenuEvent; 244 s_mods.list.generic.id = ID_LIST; 245 s_mods.list.generic.x = 320; 246 s_mods.list.generic.y = 130; 247 s_mods.list.width = 48; 248 s_mods.list.height = 14; 249 250 UI_Mods_LoadMods(); 251 252 Menu_AddItem( &s_mods.menu, &s_mods.banner ); 253 Menu_AddItem( &s_mods.menu, &s_mods.framel ); 254 Menu_AddItem( &s_mods.menu, &s_mods.framer ); 255 Menu_AddItem( &s_mods.menu, &s_mods.list ); 256 Menu_AddItem( &s_mods.menu, &s_mods.back ); 257 Menu_AddItem( &s_mods.menu, &s_mods.go ); 258 } 259 260 /* 261 ================= 262 UI_Mods_Cache 263 ================= 264 */ 265 void UI_ModsMenu_Cache( void ) { 266 trap_R_RegisterShaderNoMip( ART_BACK0 ); 267 trap_R_RegisterShaderNoMip( ART_BACK1 ); 268 trap_R_RegisterShaderNoMip( ART_FIGHT0 ); 269 trap_R_RegisterShaderNoMip( ART_FIGHT1 ); 270 trap_R_RegisterShaderNoMip( ART_FRAMEL ); 271 trap_R_RegisterShaderNoMip( ART_FRAMER ); 272 } 273 274 275 /* 276 =============== 277 UI_ModsMenu 278 =============== 279 */ 280 void UI_ModsMenu( void ) { 281 UI_Mods_MenuInit(); 282 UI_PushMenu( &s_mods.menu ); 283 }