ui_playermodel.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. //
  19. #include "ui_local.h"
  20. #define MODEL_BACK0 "menu/art/back_0"
  21. #define MODEL_BACK1 "menu/art/back_1"
  22. #define MODEL_SELECT "menu/art/opponents_select"
  23. #define MODEL_SELECTED "menu/art/opponents_selected"
  24. #define MODEL_FRAMEL "menu/art/frame1_l"
  25. #define MODEL_FRAMER "menu/art/frame1_r"
  26. #define MODEL_PORTS "menu/art/player_models_ports"
  27. #define MODEL_ARROWS "menu/art/gs_arrows_0"
  28. #define MODEL_ARROWSL "menu/art/gs_arrows_l"
  29. #define MODEL_ARROWSR "menu/art/gs_arrows_r"
  30. #define LOW_MEMORY (5 * 1024 * 1024)
  31. static char* playermodel_artlist[] =
  32. {
  33. MODEL_BACK0,
  34. MODEL_BACK1,
  35. MODEL_SELECT,
  36. MODEL_SELECTED,
  37. MODEL_FRAMEL,
  38. MODEL_FRAMER,
  39. MODEL_PORTS,
  40. MODEL_ARROWS,
  41. MODEL_ARROWSL,
  42. MODEL_ARROWSR,
  43. NULL
  44. };
  45. #define PLAYERGRID_COLS 4
  46. #define PLAYERGRID_ROWS 4
  47. #define MAX_MODELSPERPAGE (PLAYERGRID_ROWS*PLAYERGRID_COLS)
  48. #define MAX_PLAYERMODELS 256
  49. #define ID_PLAYERPIC0 0
  50. #define ID_PLAYERPIC1 1
  51. #define ID_PLAYERPIC2 2
  52. #define ID_PLAYERPIC3 3
  53. #define ID_PLAYERPIC4 4
  54. #define ID_PLAYERPIC5 5
  55. #define ID_PLAYERPIC6 6
  56. #define ID_PLAYERPIC7 7
  57. #define ID_PLAYERPIC8 8
  58. #define ID_PLAYERPIC9 9
  59. #define ID_PLAYERPIC10 10
  60. #define ID_PLAYERPIC11 11
  61. #define ID_PLAYERPIC12 12
  62. #define ID_PLAYERPIC13 13
  63. #define ID_PLAYERPIC14 14
  64. #define ID_PLAYERPIC15 15
  65. #define ID_PREVPAGE 100
  66. #define ID_NEXTPAGE 101
  67. #define ID_BACK 102
  68. typedef struct
  69. {
  70. menuframework_s menu;
  71. menubitmap_s pics[MAX_MODELSPERPAGE];
  72. menubitmap_s picbuttons[MAX_MODELSPERPAGE];
  73. menubitmap_s framel;
  74. menubitmap_s framer;
  75. menubitmap_s ports;
  76. menutext_s banner;
  77. menubitmap_s back;
  78. menubitmap_s player;
  79. menubitmap_s arrows;
  80. menubitmap_s left;
  81. menubitmap_s right;
  82. menutext_s modelname;
  83. menutext_s skinname;
  84. menutext_s playername;
  85. playerInfo_t playerinfo;
  86. int nummodels;
  87. char modelnames[MAX_PLAYERMODELS][128];
  88. int modelpage;
  89. int numpages;
  90. char modelskin[64];
  91. int selectedmodel;
  92. } playermodel_t;
  93. static playermodel_t s_playermodel;
  94. /*
  95. =================
  96. PlayerModel_UpdateGrid
  97. =================
  98. */
  99. static void PlayerModel_UpdateGrid( void )
  100. {
  101. int i;
  102. int j;
  103. j = s_playermodel.modelpage * MAX_MODELSPERPAGE;
  104. for (i=0; i<PLAYERGRID_ROWS*PLAYERGRID_COLS; i++,j++)
  105. {
  106. if (j < s_playermodel.nummodels)
  107. {
  108. // model/skin portrait
  109. s_playermodel.pics[i].generic.name = s_playermodel.modelnames[j];
  110. s_playermodel.picbuttons[i].generic.flags &= ~QMF_INACTIVE;
  111. }
  112. else
  113. {
  114. // dead slot
  115. s_playermodel.pics[i].generic.name = NULL;
  116. s_playermodel.picbuttons[i].generic.flags |= QMF_INACTIVE;
  117. }
  118. s_playermodel.pics[i].generic.flags &= ~QMF_HIGHLIGHT;
  119. s_playermodel.pics[i].shader = 0;
  120. s_playermodel.picbuttons[i].generic.flags |= QMF_PULSEIFFOCUS;
  121. }
  122. if (s_playermodel.selectedmodel/MAX_MODELSPERPAGE == s_playermodel.modelpage)
  123. {
  124. // set selected model
  125. i = s_playermodel.selectedmodel % MAX_MODELSPERPAGE;
  126. s_playermodel.pics[i].generic.flags |= QMF_HIGHLIGHT;
  127. s_playermodel.picbuttons[i].generic.flags &= ~QMF_PULSEIFFOCUS;
  128. }
  129. if (s_playermodel.numpages > 1)
  130. {
  131. if (s_playermodel.modelpage > 0)
  132. s_playermodel.left.generic.flags &= ~QMF_INACTIVE;
  133. else
  134. s_playermodel.left.generic.flags |= QMF_INACTIVE;
  135. if (s_playermodel.modelpage < s_playermodel.numpages-1)
  136. s_playermodel.right.generic.flags &= ~QMF_INACTIVE;
  137. else
  138. s_playermodel.right.generic.flags |= QMF_INACTIVE;
  139. }
  140. else
  141. {
  142. // hide left/right markers
  143. s_playermodel.left.generic.flags |= QMF_INACTIVE;
  144. s_playermodel.right.generic.flags |= QMF_INACTIVE;
  145. }
  146. }
  147. /*
  148. =================
  149. PlayerModel_UpdateModel
  150. =================
  151. */
  152. static void PlayerModel_UpdateModel( void )
  153. {
  154. vec3_t viewangles;
  155. vec3_t moveangles;
  156. memset( &s_playermodel.playerinfo, 0, sizeof(playerInfo_t) );
  157. viewangles[YAW] = 180 - 30;
  158. viewangles[PITCH] = 0;
  159. viewangles[ROLL] = 0;
  160. VectorClear( moveangles );
  161. UI_PlayerInfo_SetModel( &s_playermodel.playerinfo, s_playermodel.modelskin );
  162. UI_PlayerInfo_SetInfo( &s_playermodel.playerinfo, LEGS_IDLE, TORSO_STAND, viewangles, moveangles, WP_MACHINEGUN, qfalse );
  163. }
  164. /*
  165. =================
  166. PlayerModel_SaveChanges
  167. =================
  168. */
  169. static void PlayerModel_SaveChanges( void )
  170. {
  171. trap_Cvar_Set( "model", s_playermodel.modelskin );
  172. trap_Cvar_Set( "headmodel", s_playermodel.modelskin );
  173. trap_Cvar_Set( "team_model", s_playermodel.modelskin );
  174. trap_Cvar_Set( "team_headmodel", s_playermodel.modelskin );
  175. }
  176. /*
  177. =================
  178. PlayerModel_MenuEvent
  179. =================
  180. */
  181. static void PlayerModel_MenuEvent( void* ptr, int event )
  182. {
  183. if (event != QM_ACTIVATED)
  184. return;
  185. switch (((menucommon_s*)ptr)->id)
  186. {
  187. case ID_PREVPAGE:
  188. if (s_playermodel.modelpage > 0)
  189. {
  190. s_playermodel.modelpage--;
  191. PlayerModel_UpdateGrid();
  192. }
  193. break;
  194. case ID_NEXTPAGE:
  195. if (s_playermodel.modelpage < s_playermodel.numpages-1)
  196. {
  197. s_playermodel.modelpage++;
  198. PlayerModel_UpdateGrid();
  199. }
  200. break;
  201. case ID_BACK:
  202. PlayerModel_SaveChanges();
  203. UI_PopMenu();
  204. break;
  205. }
  206. }
  207. /*
  208. =================
  209. PlayerModel_MenuKey
  210. =================
  211. */
  212. static sfxHandle_t PlayerModel_MenuKey( int key )
  213. {
  214. menucommon_s* m;
  215. int picnum;
  216. switch (key)
  217. {
  218. case K_KP_LEFTARROW:
  219. case K_LEFTARROW:
  220. m = Menu_ItemAtCursor(&s_playermodel.menu);
  221. picnum = m->id - ID_PLAYERPIC0;
  222. if (picnum >= 0 && picnum <= 15)
  223. {
  224. if (picnum > 0)
  225. {
  226. Menu_SetCursor(&s_playermodel.menu,s_playermodel.menu.cursor-1);
  227. return (menu_move_sound);
  228. }
  229. else if (s_playermodel.modelpage > 0)
  230. {
  231. s_playermodel.modelpage--;
  232. Menu_SetCursor(&s_playermodel.menu,s_playermodel.menu.cursor+15);
  233. PlayerModel_UpdateGrid();
  234. return (menu_move_sound);
  235. }
  236. else
  237. return (menu_buzz_sound);
  238. }
  239. break;
  240. case K_KP_RIGHTARROW:
  241. case K_RIGHTARROW:
  242. m = Menu_ItemAtCursor(&s_playermodel.menu);
  243. picnum = m->id - ID_PLAYERPIC0;
  244. if (picnum >= 0 && picnum <= 15)
  245. {
  246. if ((picnum < 15) && (s_playermodel.modelpage*MAX_MODELSPERPAGE + picnum+1 < s_playermodel.nummodels))
  247. {
  248. Menu_SetCursor(&s_playermodel.menu,s_playermodel.menu.cursor+1);
  249. return (menu_move_sound);
  250. }
  251. else if ((picnum == 15) && (s_playermodel.modelpage < s_playermodel.numpages-1))
  252. {
  253. s_playermodel.modelpage++;
  254. Menu_SetCursor(&s_playermodel.menu,s_playermodel.menu.cursor-15);
  255. PlayerModel_UpdateGrid();
  256. return (menu_move_sound);
  257. }
  258. else
  259. return (menu_buzz_sound);
  260. }
  261. break;
  262. case K_MOUSE2:
  263. case K_ESCAPE:
  264. PlayerModel_SaveChanges();
  265. break;
  266. }
  267. return ( Menu_DefaultKey( &s_playermodel.menu, key ) );
  268. }
  269. /*
  270. =================
  271. PlayerModel_PicEvent
  272. =================
  273. */
  274. static void PlayerModel_PicEvent( void* ptr, int event )
  275. {
  276. int modelnum;
  277. int maxlen;
  278. char* buffptr;
  279. char* pdest;
  280. int i;
  281. if (event != QM_ACTIVATED)
  282. return;
  283. for (i=0; i<PLAYERGRID_ROWS*PLAYERGRID_COLS; i++)
  284. {
  285. // reset
  286. s_playermodel.pics[i].generic.flags &= ~QMF_HIGHLIGHT;
  287. s_playermodel.picbuttons[i].generic.flags |= QMF_PULSEIFFOCUS;
  288. }
  289. // set selected
  290. i = ((menucommon_s*)ptr)->id - ID_PLAYERPIC0;
  291. s_playermodel.pics[i].generic.flags |= QMF_HIGHLIGHT;
  292. s_playermodel.picbuttons[i].generic.flags &= ~QMF_PULSEIFFOCUS;
  293. // get model and strip icon_
  294. modelnum = s_playermodel.modelpage*MAX_MODELSPERPAGE + i;
  295. buffptr = s_playermodel.modelnames[modelnum] + strlen("models/players/");
  296. pdest = strstr(buffptr,"icon_");
  297. if (pdest)
  298. {
  299. // track the whole model/skin name
  300. Q_strncpyz(s_playermodel.modelskin,buffptr,pdest-buffptr+1);
  301. strcat(s_playermodel.modelskin,pdest + 5);
  302. // seperate the model name
  303. maxlen = pdest-buffptr;
  304. if (maxlen > 16)
  305. maxlen = 16;
  306. Q_strncpyz( s_playermodel.modelname.string, buffptr, maxlen );
  307. Q_strupr( s_playermodel.modelname.string );
  308. // seperate the skin name
  309. maxlen = strlen(pdest+5)+1;
  310. if (maxlen > 16)
  311. maxlen = 16;
  312. Q_strncpyz( s_playermodel.skinname.string, pdest+5, maxlen );
  313. Q_strupr( s_playermodel.skinname.string );
  314. s_playermodel.selectedmodel = modelnum;
  315. if( trap_MemoryRemaining() > LOW_MEMORY ) {
  316. PlayerModel_UpdateModel();
  317. }
  318. }
  319. }
  320. /*
  321. =================
  322. PlayerModel_DrawPlayer
  323. =================
  324. */
  325. static void PlayerModel_DrawPlayer( void *self )
  326. {
  327. menubitmap_s* b;
  328. b = (menubitmap_s*) self;
  329. if( trap_MemoryRemaining() <= LOW_MEMORY ) {
  330. UI_DrawProportionalString( b->generic.x, b->generic.y + b->height / 2, "LOW MEMORY", UI_LEFT, color_red );
  331. return;
  332. }
  333. UI_DrawPlayer( b->generic.x, b->generic.y, b->width, b->height, &s_playermodel.playerinfo, uis.realtime/2 );
  334. }
  335. /*
  336. =================
  337. PlayerModel_BuildList
  338. =================
  339. */
  340. static void PlayerModel_BuildList( void )
  341. {
  342. int numdirs;
  343. int numfiles;
  344. char dirlist[2048];
  345. char filelist[2048];
  346. char skinname[64];
  347. char* dirptr;
  348. char* fileptr;
  349. int i;
  350. int j;
  351. int dirlen;
  352. int filelen;
  353. qboolean precache;
  354. precache = trap_Cvar_VariableValue("com_buildscript");
  355. s_playermodel.modelpage = 0;
  356. s_playermodel.nummodels = 0;
  357. // iterate directory of all player models
  358. numdirs = trap_FS_GetFileList("models/players", "/", dirlist, 2048 );
  359. dirptr = dirlist;
  360. for (i=0; i<numdirs && s_playermodel.nummodels < MAX_PLAYERMODELS; i++,dirptr+=dirlen+1)
  361. {
  362. dirlen = strlen(dirptr);
  363. if (dirlen && dirptr[dirlen-1]=='/') dirptr[dirlen-1]='\0';
  364. if (!strcmp(dirptr,".") || !strcmp(dirptr,".."))
  365. continue;
  366. // iterate all skin files in directory
  367. numfiles = trap_FS_GetFileList( va("models/players/%s",dirptr), "tga", filelist, 2048 );
  368. fileptr = filelist;
  369. for (j=0; j<numfiles && s_playermodel.nummodels < MAX_PLAYERMODELS;j++,fileptr+=filelen+1)
  370. {
  371. filelen = strlen(fileptr);
  372. COM_StripExtension(fileptr,skinname);
  373. // look for icon_????
  374. if (!Q_stricmpn(skinname,"icon_",5))
  375. {
  376. Com_sprintf( s_playermodel.modelnames[s_playermodel.nummodels++],
  377. sizeof( s_playermodel.modelnames[s_playermodel.nummodels] ),
  378. "models/players/%s/%s", dirptr, skinname );
  379. //if (s_playermodel.nummodels >= MAX_PLAYERMODELS)
  380. // return;
  381. }
  382. if( precache ) {
  383. trap_S_RegisterSound( va( "sound/player/announce/%s_wins.wav", skinname), qfalse );
  384. }
  385. }
  386. }
  387. //APSFIXME - Degenerate no models case
  388. s_playermodel.numpages = s_playermodel.nummodels/MAX_MODELSPERPAGE;
  389. if (s_playermodel.nummodels % MAX_MODELSPERPAGE)
  390. s_playermodel.numpages++;
  391. }
  392. /*
  393. =================
  394. PlayerModel_SetMenuItems
  395. =================
  396. */
  397. static void PlayerModel_SetMenuItems( void )
  398. {
  399. int i;
  400. int maxlen;
  401. char modelskin[64];
  402. char* buffptr;
  403. char* pdest;
  404. // name
  405. trap_Cvar_VariableStringBuffer( "name", s_playermodel.playername.string, 16 );
  406. Q_CleanStr( s_playermodel.playername.string );
  407. // model
  408. trap_Cvar_VariableStringBuffer( "model", s_playermodel.modelskin, 64 );
  409. // find model in our list
  410. for (i=0; i<s_playermodel.nummodels; i++)
  411. {
  412. // strip icon_
  413. buffptr = s_playermodel.modelnames[i] + strlen("models/players/");
  414. pdest = strstr(buffptr,"icon_");
  415. if (pdest)
  416. {
  417. Q_strncpyz(modelskin,buffptr,pdest-buffptr+1);
  418. strcat(modelskin,pdest + 5);
  419. }
  420. else
  421. continue;
  422. if (!Q_stricmp( s_playermodel.modelskin, modelskin ))
  423. {
  424. // found pic, set selection here
  425. s_playermodel.selectedmodel = i;
  426. s_playermodel.modelpage = i/MAX_MODELSPERPAGE;
  427. // seperate the model name
  428. maxlen = pdest-buffptr;
  429. if (maxlen > 16)
  430. maxlen = 16;
  431. Q_strncpyz( s_playermodel.modelname.string, buffptr, maxlen );
  432. Q_strupr( s_playermodel.modelname.string );
  433. // seperate the skin name
  434. maxlen = strlen(pdest+5)+1;
  435. if (maxlen > 16)
  436. maxlen = 16;
  437. Q_strncpyz( s_playermodel.skinname.string, pdest+5, maxlen );
  438. Q_strupr( s_playermodel.skinname.string );
  439. break;
  440. }
  441. }
  442. }
  443. /*
  444. =================
  445. PlayerModel_MenuInit
  446. =================
  447. */
  448. static void PlayerModel_MenuInit( void )
  449. {
  450. int i;
  451. int j;
  452. int k;
  453. int x;
  454. int y;
  455. static char playername[32];
  456. static char modelname[32];
  457. static char skinname[32];
  458. // zero set all our globals
  459. memset( &s_playermodel, 0 ,sizeof(playermodel_t) );
  460. PlayerModel_Cache();
  461. s_playermodel.menu.key = PlayerModel_MenuKey;
  462. s_playermodel.menu.wrapAround = qtrue;
  463. s_playermodel.menu.fullscreen = qtrue;
  464. s_playermodel.banner.generic.type = MTYPE_BTEXT;
  465. s_playermodel.banner.generic.x = 320;
  466. s_playermodel.banner.generic.y = 16;
  467. s_playermodel.banner.string = "PLAYER MODEL";
  468. s_playermodel.banner.color = color_white;
  469. s_playermodel.banner.style = UI_CENTER;
  470. s_playermodel.framel.generic.type = MTYPE_BITMAP;
  471. s_playermodel.framel.generic.name = MODEL_FRAMEL;
  472. s_playermodel.framel.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE;
  473. s_playermodel.framel.generic.x = 0;
  474. s_playermodel.framel.generic.y = 78;
  475. s_playermodel.framel.width = 256;
  476. s_playermodel.framel.height = 329;
  477. s_playermodel.framer.generic.type = MTYPE_BITMAP;
  478. s_playermodel.framer.generic.name = MODEL_FRAMER;
  479. s_playermodel.framer.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE;
  480. s_playermodel.framer.generic.x = 376;
  481. s_playermodel.framer.generic.y = 76;
  482. s_playermodel.framer.width = 256;
  483. s_playermodel.framer.height = 334;
  484. s_playermodel.ports.generic.type = MTYPE_BITMAP;
  485. s_playermodel.ports.generic.name = MODEL_PORTS;
  486. s_playermodel.ports.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE;
  487. s_playermodel.ports.generic.x = 50;
  488. s_playermodel.ports.generic.y = 59;
  489. s_playermodel.ports.width = 274;
  490. s_playermodel.ports.height = 274;
  491. y = 59;
  492. for (i=0,k=0; i<PLAYERGRID_ROWS; i++)
  493. {
  494. x = 50;
  495. for (j=0; j<PLAYERGRID_COLS; j++,k++)
  496. {
  497. s_playermodel.pics[k].generic.type = MTYPE_BITMAP;
  498. s_playermodel.pics[k].generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE;
  499. s_playermodel.pics[k].generic.x = x;
  500. s_playermodel.pics[k].generic.y = y;
  501. s_playermodel.pics[k].width = 64;
  502. s_playermodel.pics[k].height = 64;
  503. s_playermodel.pics[k].focuspic = MODEL_SELECTED;
  504. s_playermodel.pics[k].focuscolor = colorRed;
  505. s_playermodel.picbuttons[k].generic.type = MTYPE_BITMAP;
  506. s_playermodel.picbuttons[k].generic.flags = QMF_LEFT_JUSTIFY|QMF_NODEFAULTINIT|QMF_PULSEIFFOCUS;
  507. s_playermodel.picbuttons[k].generic.id = ID_PLAYERPIC0+k;
  508. s_playermodel.picbuttons[k].generic.callback = PlayerModel_PicEvent;
  509. s_playermodel.picbuttons[k].generic.x = x - 16;
  510. s_playermodel.picbuttons[k].generic.y = y - 16;
  511. s_playermodel.picbuttons[k].generic.left = x;
  512. s_playermodel.picbuttons[k].generic.top = y;
  513. s_playermodel.picbuttons[k].generic.right = x + 64;
  514. s_playermodel.picbuttons[k].generic.bottom = y + 64;
  515. s_playermodel.picbuttons[k].width = 128;
  516. s_playermodel.picbuttons[k].height = 128;
  517. s_playermodel.picbuttons[k].focuspic = MODEL_SELECT;
  518. s_playermodel.picbuttons[k].focuscolor = colorRed;
  519. x += 64+6;
  520. }
  521. y += 64+6;
  522. }
  523. s_playermodel.playername.generic.type = MTYPE_PTEXT;
  524. s_playermodel.playername.generic.flags = QMF_CENTER_JUSTIFY|QMF_INACTIVE;
  525. s_playermodel.playername.generic.x = 320;
  526. s_playermodel.playername.generic.y = 440;
  527. s_playermodel.playername.string = playername;
  528. s_playermodel.playername.style = UI_CENTER;
  529. s_playermodel.playername.color = text_color_normal;
  530. s_playermodel.modelname.generic.type = MTYPE_PTEXT;
  531. s_playermodel.modelname.generic.flags = QMF_CENTER_JUSTIFY|QMF_INACTIVE;
  532. s_playermodel.modelname.generic.x = 497;
  533. s_playermodel.modelname.generic.y = 54;
  534. s_playermodel.modelname.string = modelname;
  535. s_playermodel.modelname.style = UI_CENTER;
  536. s_playermodel.modelname.color = text_color_normal;
  537. s_playermodel.skinname.generic.type = MTYPE_PTEXT;
  538. s_playermodel.skinname.generic.flags = QMF_CENTER_JUSTIFY|QMF_INACTIVE;
  539. s_playermodel.skinname.generic.x = 497;
  540. s_playermodel.skinname.generic.y = 394;
  541. s_playermodel.skinname.string = skinname;
  542. s_playermodel.skinname.style = UI_CENTER;
  543. s_playermodel.skinname.color = text_color_normal;
  544. s_playermodel.player.generic.type = MTYPE_BITMAP;
  545. s_playermodel.player.generic.flags = QMF_INACTIVE;
  546. s_playermodel.player.generic.ownerdraw = PlayerModel_DrawPlayer;
  547. s_playermodel.player.generic.x = 400;
  548. s_playermodel.player.generic.y = -40;
  549. s_playermodel.player.width = 32*10;
  550. s_playermodel.player.height = 56*10;
  551. s_playermodel.arrows.generic.type = MTYPE_BITMAP;
  552. s_playermodel.arrows.generic.name = MODEL_ARROWS;
  553. s_playermodel.arrows.generic.flags = QMF_INACTIVE;
  554. s_playermodel.arrows.generic.x = 125;
  555. s_playermodel.arrows.generic.y = 340;
  556. s_playermodel.arrows.width = 128;
  557. s_playermodel.arrows.height = 32;
  558. s_playermodel.left.generic.type = MTYPE_BITMAP;
  559. s_playermodel.left.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
  560. s_playermodel.left.generic.callback = PlayerModel_MenuEvent;
  561. s_playermodel.left.generic.id = ID_PREVPAGE;
  562. s_playermodel.left.generic.x = 125;
  563. s_playermodel.left.generic.y = 340;
  564. s_playermodel.left.width = 64;
  565. s_playermodel.left.height = 32;
  566. s_playermodel.left.focuspic = MODEL_ARROWSL;
  567. s_playermodel.right.generic.type = MTYPE_BITMAP;
  568. s_playermodel.right.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
  569. s_playermodel.right.generic.callback = PlayerModel_MenuEvent;
  570. s_playermodel.right.generic.id = ID_NEXTPAGE;
  571. s_playermodel.right.generic.x = 125+61;
  572. s_playermodel.right.generic.y = 340;
  573. s_playermodel.right.width = 64;
  574. s_playermodel.right.height = 32;
  575. s_playermodel.right.focuspic = MODEL_ARROWSR;
  576. s_playermodel.back.generic.type = MTYPE_BITMAP;
  577. s_playermodel.back.generic.name = MODEL_BACK0;
  578. s_playermodel.back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
  579. s_playermodel.back.generic.callback = PlayerModel_MenuEvent;
  580. s_playermodel.back.generic.id = ID_BACK;
  581. s_playermodel.back.generic.x = 0;
  582. s_playermodel.back.generic.y = 480-64;
  583. s_playermodel.back.width = 128;
  584. s_playermodel.back.height = 64;
  585. s_playermodel.back.focuspic = MODEL_BACK1;
  586. Menu_AddItem( &s_playermodel.menu, &s_playermodel.banner );
  587. Menu_AddItem( &s_playermodel.menu, &s_playermodel.framel );
  588. Menu_AddItem( &s_playermodel.menu, &s_playermodel.framer );
  589. Menu_AddItem( &s_playermodel.menu, &s_playermodel.ports );
  590. Menu_AddItem( &s_playermodel.menu, &s_playermodel.playername );
  591. Menu_AddItem( &s_playermodel.menu, &s_playermodel.modelname );
  592. Menu_AddItem( &s_playermodel.menu, &s_playermodel.skinname );
  593. for (i=0; i<MAX_MODELSPERPAGE; i++)
  594. {
  595. Menu_AddItem( &s_playermodel.menu, &s_playermodel.pics[i] );
  596. Menu_AddItem( &s_playermodel.menu, &s_playermodel.picbuttons[i] );
  597. }
  598. Menu_AddItem( &s_playermodel.menu, &s_playermodel.player );
  599. Menu_AddItem( &s_playermodel.menu, &s_playermodel.arrows );
  600. Menu_AddItem( &s_playermodel.menu, &s_playermodel.left );
  601. Menu_AddItem( &s_playermodel.menu, &s_playermodel.right );
  602. Menu_AddItem( &s_playermodel.menu, &s_playermodel.back );
  603. // find all available models
  604. // PlayerModel_BuildList();
  605. // set initial states
  606. PlayerModel_SetMenuItems();
  607. // update user interface
  608. PlayerModel_UpdateGrid();
  609. PlayerModel_UpdateModel();
  610. }
  611. /*
  612. =================
  613. PlayerModel_Cache
  614. =================
  615. */
  616. void PlayerModel_Cache( void )
  617. {
  618. int i;
  619. for( i = 0; playermodel_artlist[i]; i++ ) {
  620. trap_R_RegisterShaderNoMip( playermodel_artlist[i] );
  621. }
  622. PlayerModel_BuildList();
  623. for( i = 0; i < s_playermodel.nummodels; i++ ) {
  624. trap_R_RegisterShaderNoMip( s_playermodel.modelnames[i] );
  625. }
  626. }
  627. void UI_PlayerModelMenu(void)
  628. {
  629. PlayerModel_MenuInit();
  630. UI_PushMenu( &s_playermodel.menu );
  631. Menu_SetCursorToItem( &s_playermodel.menu, &s_playermodel.pics[s_playermodel.selectedmodel % MAX_MODELSPERPAGE] );
  632. }