p3dlib.c: include “cmdlib.h” on non Windows platform
[xonotic/netradiant.git] / tools / quake3 / q3data / p3dlib.c
1 /*
2    Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    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 GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "p3dlib.h"
23
24 #ifdef WIN32
25 #include <io.h>
26 #endif
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #define MAX_POLYSETS 64
32
33 #if defined ( __linux__ ) || defined ( __APPLE__ )
34         #include "cmdlib.h"
35         #define _strcmpi Q_stricmp
36         #define filelength Q_filelength
37         #define strlwr strlower
38 #endif
39 typedef struct
40 {
41         long len;
42
43         int numPairs;
44         char polysetNames[MAX_POLYSETS][256];
45         char shaders[MAX_POLYSETS][256];
46
47         char *buffer, *curpos;
48 } p3d_t;
49
50 static p3d_t p3d;
51
52 static int P3DProcess();
53 static int P3DGetToken( int restOfLine );
54
55 static char s_token[1024];
56 static int s_curpair;
57
58 /*
59 ** P3DLoad
60 **
61 */
62 int P3DLoad( const char *filename ){
63         FILE *fp = fopen( filename, "rb" );
64
65         if ( !fp ) {
66                 return 0;
67         }
68
69         memset( &p3d, 0, sizeof( p3d ) );
70
71         p3d.len = filelength( fileno( fp ) );
72
73         p3d.curpos = p3d.buffer = malloc( p3d.len );
74
75         if ( fread( p3d.buffer, p3d.len, 1, fp ) != 1 ) {
76                 fclose( fp );
77                 return 0;
78         }
79
80         fclose( fp );
81
82         return P3DProcess();
83 }
84
85 /*
86 ** P3DClose
87 **
88 */
89 void P3DClose(){
90         if ( p3d.buffer ) {
91                 free( p3d.buffer );
92                 p3d.buffer = 0;
93         }
94 }
95
96 int CharIsTokenDelimiter( int ch ){
97         if ( ch <= 32 ) {
98                 return 1;
99         }
100         return 0;
101 }
102
103 int P3DSkipToToken( const char *name ){
104         while ( P3DGetToken( 0 ) )
105         {
106                 if ( !_strcmpi( s_token, name ) ) {
107                         return 1;
108                 }
109         }
110
111         return 0;
112 }
113
114 /*
115 ** P3DGetToken
116 **
117 */
118 int P3DGetToken( int restOfLine ){
119         int i = 0;
120
121         if ( p3d.buffer == 0 ) {
122                 return 0;
123         }
124
125         if ( ( p3d.curpos - p3d.buffer ) == p3d.len ) {
126                 return 0;
127         }
128
129         // skip over crap
130         while ( ( ( p3d.curpos - p3d.buffer ) < p3d.len ) &&
131                         ( *p3d.curpos <= 32 ) )
132         {
133                 p3d.curpos++;
134         }
135
136         while ( ( p3d.curpos - p3d.buffer ) < p3d.len )
137         {
138                 s_token[i] = *p3d.curpos;
139
140                 p3d.curpos++;
141                 i++;
142
143                 if ( ( CharIsTokenDelimiter( s_token[i - 1] ) && !restOfLine ) ||
144                          ( ( s_token[i - 1] == '\n' ) ) ) {
145                         s_token[i - 1] = 0;
146                         break;
147                 }
148         }
149
150         s_token[i] = 0;
151
152         return 1;
153 }
154
155 int P3DGetNextPair( char **psetName, char **associatedShader ){
156         if ( s_curpair < p3d.numPairs ) {
157                 *psetName = p3d.polysetNames[s_curpair];
158                 *associatedShader = p3d.shaders[s_curpair];
159                 s_curpair++;
160                 return 1;
161         }
162
163         return 0;
164 }
165
166 int P3DSkipToTokenInBlock( const char *name ){
167         int iLevel = 0;
168
169         while ( P3DGetToken( 0 ) )
170         {
171                 if ( !_strcmpi( s_token, "}" ) ) {
172                         iLevel--;
173                 }
174                 else if ( !_strcmpi( s_token, "{" ) ) {
175                         iLevel++;
176                 }
177
178                 if ( !_strcmpi( s_token, name ) ) {
179                         return 1;
180                 }
181
182                 if ( iLevel == 0 ) {
183                         return 0;
184                 }
185         }
186
187         return 0;
188 }
189
190 /*
191 ** P3DProcess
192 **
193 ** Nothing fancy here.
194 */
195 int P3DProcess(){
196
197         s_curpair = 0;
198
199         // first token should be a string
200         P3DGetToken( 1 );       // Voodoo Ascii File
201
202         // skip to the first Obj declaration
203         while ( P3DGetToken( 0 ) )
204         {
205                 if ( !_strcmpi( s_token, "Obj" ) ) {
206                         int j = 0, k = 0;
207
208                         if ( P3DSkipToToken( "Text" ) ) {
209                                 if ( P3DSkipToTokenInBlock( "TMap" ) ) {
210                                         char *p;
211
212                                         if ( !P3DSkipToToken( "Path" ) ) {
213                                                 return 0;
214                                         }
215
216                                         if ( !P3DGetToken( 1 ) ) {
217                                                 return 0;
218                                         }
219
220                                         while ( s_token[j] != 0 )
221                                         {
222                                                 if ( s_token[j] == '\\' ) {
223                                                         j++;
224                                                         p3d.shaders[p3d.numPairs][k] = '/';
225                                                 }
226                                                 else
227                                                 {
228                                                         p3d.shaders[p3d.numPairs][k] = s_token[j];
229                                                 }
230                                                 j++;
231                                                 k++;
232                                         }
233                                         p3d.shaders[p3d.numPairs][k] = 0;
234
235                                         //
236                                         // strip off any explicit extensions
237                                         //
238                                         if ( ( p = strrchr( p3d.shaders[p3d.numPairs], '/' ) ) != 0 ) {
239                                                 while ( *p )
240                                                 {
241                                                         if ( *p == '.' ) {
242                                                                 *p = 0;
243                                                                 break;
244                                                         }
245                                                         p++;
246                                                 }
247                                         }
248
249                                         //
250                                         // skip to the end of the Object and grab its name
251                                         //
252                                         if ( !P3DSkipToToken( "Name" ) ) {
253                                                 return 0;
254                                         }
255
256                                         if ( P3DGetToken( 0 ) ) {
257                                                 // strip off leading 'Obj_' if it exists
258                                                 if ( strstr( s_token, "Obj_" ) == s_token ) {
259                                                         strcpy( p3d.polysetNames[p3d.numPairs], s_token + strlen( "Obj_" ) );
260                                                 }
261                                                 else{
262                                                         strcpy( p3d.polysetNames[p3d.numPairs], s_token );
263                                                 }
264
265                                                 // strip off trailing unused color information
266 //                                              if ( strrchr( p3d.polysetNames[p3d.numPairs], '_' ) != 0 )
267 //                                                      *strrchr( p3d.polysetNames[p3d.numPairs], '_' ) = 0;
268
269                                                 p3d.numPairs++;
270                                         }
271                                         else
272                                         {
273                                                 return 0;
274                                         }
275                                 }
276                         }
277                 }
278         }
279
280         s_curpair = 0;
281
282         return 1;
283 }
284
285 #if 0
286 void SkinFromP3D( const char *file ){
287         char filename[1024];
288         char *psetName, *associatedShader;
289
290         /*
291         ** a P3D file contains a list of polysets, each with a list of associated
292         ** texture names that constitute it's
293         **
294         ** Thus:
295         **
296         ** P3D file -> skin
297         ** polyset  -> polyset
298         **   texture -> texture.SHADER becomes polyset's shader
299         */
300         sprintf( filename, "%s/%s", g_cddir, file );
301
302         if ( !P3DLoad( filename ) ) {
303                 Error( "unable to load '%s'", filename );
304         }
305
306         while ( P3DGetNextPair( &psetName, &associatedShader ) )
307         {
308                 int i;
309
310                 // find the polyset in the object that this particular pset/shader pair
311                 // corresponds to and append the shader to it
312                 for ( i = 0; i < g_data.model.numSurfaces; i++ )
313                 {
314                         if ( !_strcmpi( g_data.surfData[i].header.name, psetName ) ) {
315                                 char *p;
316
317                                 if ( strstr( associatedShader, gamedir + 1 ) ) {
318                                         p = strstr( associatedShader, gamedir + 1 ) + strlen( gamedir ) - 1;
319                                 }
320                                 else
321                                 {
322                                         p = associatedShader;
323                                 }
324
325                                 strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, p );
326
327                                 g_data.surfData[i].header.numShaders++;
328                         }
329                 }
330
331         }
332
333         P3DClose();
334 }
335 #endif