Quake II RTX doxygen  1.0 dev
playermodels.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 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 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "ui.h"
20 #include "common/files.h"
21 
22 /*
23 =============================================================================
24 
25 PLAYER MODELS
26 
27 =============================================================================
28 */
29 
30 static qboolean IconOfSkinExists(char *skin, char **pcxfiles, int npcxfiles)
31 {
32  int i;
33  char scratch[MAX_OSPATH];
34 
35  COM_StripExtension(skin, scratch, sizeof(scratch));
36  Q_strlcat(scratch, "_i.pcx", sizeof(scratch));
37 
38  for (i = 0; i < npcxfiles; i++) {
39  if (strcmp(pcxfiles[i], scratch) == 0)
40  return qtrue;
41  }
42 
43  return qfalse;
44 }
45 
46 static int pmicmpfnc(const void *_a, const void *_b)
47 {
48  const playerModelInfo_t *a = (const playerModelInfo_t *)_a;
49  const playerModelInfo_t *b = (const playerModelInfo_t *)_b;
50 
51  /*
52  ** sort by male, female, then alphabetical
53  */
54  if (strcmp(a->directory, "male") == 0)
55  return -1;
56  else if (strcmp(b->directory, "male") == 0)
57  return 1;
58 
59  if (strcmp(a->directory, "female") == 0)
60  return -1;
61  else if (strcmp(b->directory, "female") == 0)
62  return 1;
63 
64  return strcmp(a->directory, b->directory);
65 }
66 
67 void PlayerModel_Load(void)
68 {
69  char scratch[MAX_QPATH];
70  size_t len;
71  int ndirs = 0;
72  char *dirnames[MAX_PLAYERMODELS];
73  int i, j;
74  char **list;
75  char *s, *p;
76  int numFiles;
77  playerModelInfo_t *pmi;
78 
79  uis.numPlayerModels = 0;
80 
81  // get a list of directories
82  if (!(list = (char **)FS_ListFiles(NULL, "players/*/tris.md2", FS_SEARCH_BYFILTER | FS_SEARCH_SAVEPATH, &numFiles))) {
83  return;
84  }
85 
86  for (i = 0; i < numFiles; i++) {
87  len = Q_strlcpy(scratch, list[i], sizeof(scratch));
88  if (len >= sizeof(scratch))
89  continue;
90 
91  // make short name for the model
92  if (!(s = strchr(scratch, '/')))
93  continue;
94  s++;
95 
96  if (!(p = strchr(s, '/')))
97  continue;
98  *p = 0;
99 
100  for (j = 0; j < ndirs; j++) {
101  if (!strcmp(dirnames[j], s)) {
102  break;
103  }
104  }
105 
106  if (j != ndirs) {
107  continue;
108  }
109 
110  dirnames[ndirs++] = UI_CopyString(s);
111  if (ndirs == MAX_PLAYERMODELS) {
112  break;
113  }
114  }
115 
116  FS_FreeList((void **)list);
117 
118  if (!ndirs) {
119  return;
120  }
121 
122  // go through the subdirectories
123  for (i = 0; i < ndirs; i++) {
124  int k, s;
125  char **pcxnames;
126  char **skinnames;
127  int npcxfiles;
128  int nskins = 0;
129 
130  // verify the existence of tris.md2
131  Q_concat(scratch, sizeof(scratch), "players/", dirnames[i], "/tris.md2", NULL);
132  if (!FS_FileExists(scratch)) {
133  goto skip;
134  }
135 
136  // verify the existence of at least one pcx skin
137  Q_concat(scratch, sizeof(scratch), "players/", dirnames[i], NULL);
138  pcxnames = (char **)FS_ListFiles(scratch, ".pcx", 0, &npcxfiles);
139  if (!pcxnames) {
140  goto skip;
141  }
142 
143  // count valid skins, which consist of a skin with a matching "_i" icon
144  for (k = 0; k < npcxfiles; k++) {
145  if (!strstr(pcxnames[k], "_i.pcx")) {
146  if (IconOfSkinExists(pcxnames[k], pcxnames, npcxfiles)) {
147  nskins++;
148  }
149  }
150  }
151 
152  if (!nskins) {
153  FS_FreeList((void **)pcxnames);
154  goto skip;
155  }
156 
157  skinnames = UI_Malloc(sizeof(char *) * (nskins + 1));
158  skinnames[nskins] = NULL;
159 
160  // copy the valid skins
161  for (s = 0, k = 0; k < npcxfiles; k++) {
162  if (!strstr(pcxnames[k], "_i.pcx")) {
163  if (IconOfSkinExists(pcxnames[k], pcxnames, npcxfiles)) {
164  COM_StripExtension(pcxnames[k], scratch, sizeof(scratch));
165  skinnames[s++] = UI_CopyString(scratch);
166  }
167  }
168  }
169 
170  FS_FreeList((void **)pcxnames);
171 
172  // at this point we have a valid player model
173  pmi = &uis.pmi[uis.numPlayerModels++];
174  pmi->nskins = nskins;
175  pmi->skindisplaynames = skinnames;
176  pmi->directory = dirnames[i];
177  continue;
178 
179 skip:
180  Z_Free(dirnames[i]);
181  }
182 
183  qsort(uis.pmi, uis.numPlayerModels, sizeof(uis.pmi[0]), pmicmpfnc);
184 }
185 
187 {
188  playerModelInfo_t *pmi;
189  int i, j;
190 
191  for (i = 0, pmi = uis.pmi; i < uis.numPlayerModels; i++, pmi++) {
192  if (pmi->skindisplaynames) {
193  for (j = 0; j < pmi->nskins; j++) {
194  Z_Free(pmi->skindisplaynames[j]);
195  }
196  Z_Free(pmi->skindisplaynames);
197  }
198  Z_Free(pmi->directory);
199  memset(pmi, 0, sizeof(*pmi));
200  }
201 
202  uis.numPlayerModels = 0;
203 }
204 
Q_strlcat
size_t Q_strlcat(char *dst, const char *src, size_t size)
Definition: shared.c:735
ui.h
pmicmpfnc
static int pmicmpfnc(const void *_a, const void *_b)
Definition: playermodels.c:46
FS_FreeList
void FS_FreeList(void **list)
Definition: files.c:2939
playerModelInfo_s
Definition: ui.h:272
IconOfSkinExists
static qboolean IconOfSkinExists(char *skin, char **pcxfiles, int npcxfiles)
Definition: playermodels.c:30
UI_Malloc
#define UI_Malloc(s)
Definition: ui.h:33
uis
uiStatic_t uis
Definition: ui.c:24
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
playerModelInfo_s::directory
char * directory
Definition: ui.h:275
UI_CopyString
#define UI_CopyString(s)
Definition: ui.h:35
FS_ListFiles
void ** FS_ListFiles(const char *path, const char *filter, unsigned flags, int *count_p)
Definition: files.c:2716
Q_strlcpy
size_t Q_strlcpy(char *dst, const char *src, size_t size)
Definition: shared.c:715
playerModelInfo_s::skindisplaynames
char ** skindisplaynames
Definition: ui.h:274
uiStatic_s::pmi
playerModelInfo_t pmi[MAX_PLAYERMODELS]
Definition: ui.h:303
COM_StripExtension
void COM_StripExtension(const char *in, char *out, size_t size)
Definition: shared.c:174
PlayerModel_Free
void PlayerModel_Free(void)
Definition: playermodels.c:186
Q_concat
size_t Q_concat(char *dest, size_t size,...)
Definition: shared.c:758
playerModelInfo_s::nskins
int nskins
Definition: ui.h:273
PlayerModel_Load
void PlayerModel_Load(void)
Definition: playermodels.c:67
uiStatic_s::numPlayerModels
int numPlayerModels
Definition: ui.h:302
MAX_PLAYERMODELS
#define MAX_PLAYERMODELS
Definition: ui.h:270