2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
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.
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.
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
23 #include "globaldefs.h"
27 #endif // GDEF_OS_WINDOWS
33 #define MAX_POLYSETS 64
36 #define filelength(f) filelength(fileno(f))
37 #else // !GDEF_OS_WINDOWS
39 #define _strcmpi Q_stricmp
40 #define strlwr strlower
41 #define filelength(f) Q_filelength(f)
42 #endif // !GDEF_OS_WINDOWS
49 char polysetNames[MAX_POLYSETS][256];
50 char shaders[MAX_POLYSETS][256];
52 char *buffer, *curpos;
57 static int P3DProcess();
58 static int P3DGetToken( int restOfLine );
60 static char s_token[1024];
67 int P3DLoad( const char *filename ){
68 FILE *fp = fopen( filename, "rb" );
74 memset( &p3d, 0, sizeof( p3d ) );
76 p3d.len = filelength( fp );
78 p3d.curpos = p3d.buffer = malloc( p3d.len );
80 if ( fread( p3d.buffer, p3d.len, 1, fp ) != 1 ) {
101 int CharIsTokenDelimiter( int ch ){
108 int P3DSkipToToken( const char *name ){
109 while ( P3DGetToken( 0 ) )
111 if ( !_strcmpi( s_token, name ) ) {
123 int P3DGetToken( int restOfLine ){
126 if ( p3d.buffer == 0 ) {
130 if ( ( p3d.curpos - p3d.buffer ) == p3d.len ) {
135 while ( ( ( p3d.curpos - p3d.buffer ) < p3d.len ) &&
136 ( *p3d.curpos <= 32 ) )
141 while ( ( p3d.curpos - p3d.buffer ) < p3d.len )
143 s_token[i] = *p3d.curpos;
148 if ( ( CharIsTokenDelimiter( s_token[i - 1] ) && !restOfLine ) ||
149 ( ( s_token[i - 1] == '\n' ) ) ) {
160 int P3DGetNextPair( char **psetName, char **associatedShader ){
161 if ( s_curpair < p3d.numPairs ) {
162 *psetName = p3d.polysetNames[s_curpair];
163 *associatedShader = p3d.shaders[s_curpair];
171 int P3DSkipToTokenInBlock( const char *name ){
174 while ( P3DGetToken( 0 ) )
176 if ( !_strcmpi( s_token, "}" ) ) {
179 else if ( !_strcmpi( s_token, "{" ) ) {
183 if ( !_strcmpi( s_token, name ) ) {
198 ** Nothing fancy here.
204 // first token should be a string
205 P3DGetToken( 1 ); // Voodoo Ascii File
207 // skip to the first Obj declaration
208 while ( P3DGetToken( 0 ) )
210 if ( !_strcmpi( s_token, "Obj" ) ) {
213 if ( P3DSkipToToken( "Text" ) ) {
214 if ( P3DSkipToTokenInBlock( "TMap" ) ) {
217 if ( !P3DSkipToToken( "Path" ) ) {
221 if ( !P3DGetToken( 1 ) ) {
225 while ( s_token[j] != 0 )
227 if ( s_token[j] == '\\' ) {
229 p3d.shaders[p3d.numPairs][k] = '/';
233 p3d.shaders[p3d.numPairs][k] = s_token[j];
238 p3d.shaders[p3d.numPairs][k] = 0;
241 // strip off any explicit extensions
243 if ( ( p = strrchr( p3d.shaders[p3d.numPairs], '/' ) ) != 0 ) {
255 // skip to the end of the Object and grab its name
257 if ( !P3DSkipToToken( "Name" ) ) {
261 if ( P3DGetToken( 0 ) ) {
262 // strip off leading 'Obj_' if it exists
263 if ( strstr( s_token, "Obj_" ) == s_token ) {
264 strcpy( p3d.polysetNames[p3d.numPairs], s_token + strlen( "Obj_" ) );
267 strcpy( p3d.polysetNames[p3d.numPairs], s_token );
270 // strip off trailing unused color information
271 // if ( strrchr( p3d.polysetNames[p3d.numPairs], '_' ) != 0 )
272 // *strrchr( p3d.polysetNames[p3d.numPairs], '_' ) = 0;
291 void SkinFromP3D( const char *file ){
293 char *psetName, *associatedShader;
296 ** a P3D file contains a list of polysets, each with a list of associated
297 ** texture names that constitute it's
302 ** polyset -> polyset
303 ** texture -> texture.SHADER becomes polyset's shader
305 sprintf( filename, "%s/%s", g_cddir, file );
307 if ( !P3DLoad( filename ) ) {
308 Error( "unable to load '%s'", filename );
311 while ( P3DGetNextPair( &psetName, &associatedShader ) )
315 // find the polyset in the object that this particular pset/shader pair
316 // corresponds to and append the shader to it
317 for ( i = 0; i < g_data.model.numSurfaces; i++ )
319 if ( !_strcmpi( g_data.surfData[i].header.name, psetName ) ) {
322 if ( strstr( associatedShader, gamedir + 1 ) ) {
323 p = strstr( associatedShader, gamedir + 1 ) + strlen( gamedir ) - 1;
327 p = associatedShader;
330 strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, p );
332 g_data.surfData[i].header.numShaders++;