]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake3/q3map2/writebsp.c
q3map2: make Smokin'Guns code not requiring a rebuild
[xonotic/netradiant.git] / tools / quake3 / q3map2 / writebsp.c
index 8fd073cdfdfe90e40220e6637830c2417ab9966e..3fbed1cc64dfb25a1f4a705baf50e9e22aa1d53c 100644 (file)
 
 
 
+//prefixInfo-stats
+typedef struct {
+       char    *name;
+       int             surfaceFlags;
+} prefixInfo_t;
+
+static prefixInfo_t prefixInfo[] = {
+       { "metal",      TEX_SURF_METAL},
+       { "wood",       TEX_SURF_WOOD},
+       { "cloth",      TEX_SURF_CLOTH},
+       { "dirt",       TEX_SURF_DIRT},
+       { "glass",      TEX_SURF_GLASS},
+       { "plant",      TEX_SURF_PLANT},
+       { "sand",       TEX_SURF_SAND},
+       { "snow",       TEX_SURF_SNOW},
+       { "stone",      TEX_SURF_STONE},
+       { "water",      TEX_SURF_WATER},
+       { "grass",      TEX_SURF_GRASS},
+};
+
+#define NUM_PREFIXINFO 11 /* very important */
+
+//Added by Spoon to recognize surfaceparms by shadernames
+int GetSurfaceParm(const char *tex){
+       char surf[MAX_QPATH], tex2[MAX_QPATH];
+       int     i, j = 0;
+
+       strcpy(tex2, tex);
+
+       /* find last dir */
+       for(i = 0; i < 64 && tex2[i] != '\0'; i++){
+               if(tex2[i] == '\\' || tex2[i] == '/')
+                       j=i+1;
+       }
+
+       strcpy(surf, tex2+j);
+
+       for(i=0; i<10; i++){
+               if(surf[i] == '_')
+                       break;
+       }
+       surf[i] = '\0';
+
+       /* Sys_Printf("%s\n", surf); */
+
+       for(i=0; i < NUM_PREFIXINFO; i++){
+               if(!Q_stricmp(surf, prefixInfo[i].name)){
+                       return prefixInfo[i].surfaceFlags;
+               }
+       }
+       return 0;
+}
+
+
+
 /*
    EmitShader()
    emits a bsp shader entry
@@ -56,12 +111,16 @@ int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags ){
        /* try to find an existing shader */
        for ( i = 0; i < numBSPShaders; i++ )
        {
-               /* ydnar: handle custom surface/content flags */
-               if ( surfaceFlags != NULL && bspShaders[ i ].surfaceFlags != *surfaceFlags ) {
-                       continue;
-               }
-               if ( contentFlags != NULL && bspShaders[ i ].contentFlags != *contentFlags ) {
-                       continue;
+               /* if not Smokin'Guns like tex file */
+               if ( !game->texFile )
+               {
+                       /* ydnar: handle custom surface/content flags */
+                       if ( surfaceFlags != NULL && bspShaders[ i ].surfaceFlags != *surfaceFlags ) {
+                               continue;
+                       }
+                       if ( contentFlags != NULL && bspShaders[ i ].contentFlags != *contentFlags ) {
+                               continue;
+                       }
                }
 
                /* compare name */
@@ -74,20 +133,30 @@ int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags ){
        si = ShaderInfoForShader( shader );
 
        /* emit a new shader */
-       if ( i == MAX_MAP_SHADERS ) {
-               Error( "MAX_MAP_SHADERS" );
-       }
+       AUTOEXPAND_BY_REALLOC_BSP( Shaders, 1024 );
+
        numBSPShaders++;
        strcpy( bspShaders[ i ].shader, shader );
        bspShaders[ i ].surfaceFlags = si->surfaceFlags;
-       bspShaders[ i ].contentFlags = si->contentFlags;
 
-       /* handle custom content/surface flags */
-       if ( surfaceFlags != NULL ) {
-               bspShaders[ i ].surfaceFlags = *surfaceFlags;
+       if ( game->texFile )
+       {
+               /* Smokin'Guns like tex file */
+               bspShaders[ i ].surfaceFlags |= GetSurfaceParm(si->shader);
        }
-       if ( contentFlags != NULL ) {
-               bspShaders[ i ].contentFlags = *contentFlags;
+
+       bspShaders[ i ].contentFlags = si->contentFlags;
+
+       /* if not Smokin'Guns like tex file */
+       if ( !game->texFile )
+       {
+               /* handle custom content/surface flags */
+               if ( surfaceFlags != NULL ) {
+                       bspShaders[ i ].surfaceFlags = *surfaceFlags;
+               }
+               if ( contentFlags != NULL ) {
+                       bspShaders[ i ].contentFlags = *contentFlags;
+               }
        }
 
        /* recursively emit any damage shaders */
@@ -118,6 +187,7 @@ void EmitPlanes( void ){
        mp = mapplanes;
        for ( i = 0; i < nummapplanes; i++, mp++ )
        {
+               AUTOEXPAND_BY_REALLOC_BSP( Planes, 1024 );
                bp = &bspPlanes[ numBSPPlanes ];
                VectorCopy( mp->normal, bp->normal );
                bp->dist = mp->dist;
@@ -162,15 +232,13 @@ void EmitLeaf( node_t *node ){
        {
                /* something is corrupting brushes */
                if ( (size_t) b < 256 ) {
-                       Sys_Printf( "WARNING: Node brush list corrupted (0x%08X)\n", b );
+                       Sys_FPrintf( SYS_WRN, "WARNING: Node brush list corrupted (0x%08X)\n", b );
                        break;
                }
                //%     if( b->guard != 0xDEADBEEF )
                //%             Sys_Printf( "Brush %6d: 0x%08X Guard: 0x%08X Next: 0x%08X Original: 0x%08X Sides: %d\n", b->brushNum, b, b, b->next, b->original, b->numsides );
 
-               if ( numBSPLeafBrushes >= MAX_MAP_LEAFBRUSHES ) {
-                       Error( "MAX_MAP_LEAFBRUSHES" );
-               }
+               AUTOEXPAND_BY_REALLOC_BSP( LeafBrushes, 1024 );
                bspLeafBrushes[ numBSPLeafBrushes ] = b->original->outputNum;
                numBSPLeafBrushes++;
        }
@@ -186,9 +254,7 @@ void EmitLeaf( node_t *node ){
        leaf_p->firstBSPLeafSurface = numBSPLeafSurfaces;
        for ( dsr = node->drawSurfReferences; dsr; dsr = dsr->nextRef )
        {
-               if ( numBSPLeafSurfaces >= MAX_MAP_LEAFFACES ) {
-                       Error( "MAX_MAP_LEAFFACES" );
-               }
+               AUTOEXPAND_BY_REALLOC_BSP( LeafSurfaces, 1024 );
                bspLeafSurfaces[ numBSPLeafSurfaces ] = dsr->outputNum;
                numBSPLeafSurfaces++;
        }
@@ -204,7 +270,7 @@ void EmitLeaf( node_t *node ){
 
 int EmitDrawNode_r( node_t *node ){
        bspNode_t   *n;
-       int i;
+       int i, n0;
 
 
        /* check for leafnode */
@@ -214,10 +280,9 @@ int EmitDrawNode_r( node_t *node ){
        }
 
        /* emit a node */
-       if ( numBSPNodes == MAX_MAP_NODES ) {
-               Error( "MAX_MAP_NODES" );
-       }
-       n = &bspNodes[ numBSPNodes ];
+       AUTOEXPAND_BY_REALLOC_BSP( Nodes, 1024 );
+       n0 = numBSPNodes;
+       n = &bspNodes[ n0 ];
        numBSPNodes++;
 
        VectorCopy( node->mins, n->mins );
@@ -241,6 +306,8 @@ int EmitDrawNode_r( node_t *node ){
                {
                        n->children[i] = numBSPNodes;
                        EmitDrawNode_r( node->children[i] );
+                       // n may have become invalid here, so...
+                       n = &bspNodes[ n0 ];
                }
        }
 
@@ -280,7 +347,6 @@ void SetModelNumbers( void ){
 
 void SetLightStyles( void ){
        int i, j, style, numStyles;
-       qboolean keepLights;
        const char  *t;
        entity_t    *e;
        epair_t     *ep, *next;
@@ -288,10 +354,16 @@ void SetLightStyles( void ){
        char lightTargets[ MAX_SWITCHED_LIGHTS ][ 64 ];
        int lightStyles[ MAX_SWITCHED_LIGHTS ];
 
+       /* -keeplights option: force lights to be kept and ignore what the map file says */
+       if ( keepLights ) {
+               SetKeyValue( &entities[0], "_keepLights", "1" );
+       }
 
        /* ydnar: determine if we keep lights in the bsp */
-       t = ValueForKey( &entities[ 0 ], "_keepLights" );
-       keepLights = ( t[ 0 ] == '1' ) ? qtrue : qfalse;
+       if ( KeyExists( &entities[ 0 ], "_keepLights" ) == qtrue ) {
+               t = ValueForKey( &entities[ 0 ], "_keepLights" );
+               keepLights = ( t[ 0 ] == '1' ) ? qtrue : qfalse;
+       }
 
        /* any light that is controlled (has a targetname) must have a unique style number generated for it */
        numStyles = 0;
@@ -382,6 +454,7 @@ void BeginBSPFile( void ){
 
        /* ydnar: gs mods: set the first 6 drawindexes to 0 1 2 2 1 3 for triangles and quads */
        numBSPDrawIndexes = 6;
+       AUTOEXPAND_BY_REALLOC_BSP( DrawIndexes, 1024 );
        bspDrawIndexes[ 0 ] = 0;
        bspDrawIndexes[ 1 ] = 1;
        bspDrawIndexes[ 2 ] = 2;
@@ -392,14 +465,85 @@ void BeginBSPFile( void ){
 
 
 
+/*
+   RestoreSurfaceFlags()
+   read Smokin'Guns like tex file
+   added by spoon to get back the changed surfaceflags
+ */
+
+void RestoreSurfaceFlags( char *filename ) {
+       int i;
+       FILE *texfile;
+       int surfaceFlags[ MAX_MAP_DRAW_SURFS ];
+       int numTexInfos;
+
+       /* first parse the tex file */
+       texfile = fopen( filename, "r" );
+
+       if ( texfile ) {
+               fscanf( texfile, "TEXFILE\n%i\n", &numTexInfos );
+
+               /* Sys_Printf( "%i\n", numTexInfos ); */
+
+               for ( i = 0; i < numTexInfos; i++ ) {
+                       vec3_t color;
+
+                       fscanf( texfile, "%i %f %f %f\n", &surfaceFlags[ i ],
+                               &color[ 0 ], &color[ 1 ], &color[ 2 ]);
+
+                       bspShaders[ i ].surfaceFlags = surfaceFlags[ i ];
+
+                       /* Sys_Printf( "%i\n", surfaceFlags[ i ] ); */
+               }
+       } else {
+               Sys_Printf("couldn't find %s not tex-file is now writed without surfaceFlags!\n", filename);
+       }
+}
+
+
+
+/*
+   WriteTexFile()
+   write Smokin'Guns like tex file
+   added by spoon
+ */
+
+void WriteTexFile( char* filename ) {
+       FILE *texfile;
+       int i;
+
+       if ( !compile_map ) {
+               RestoreSurfaceFlags( filename );
+       }
+
+       Sys_Printf( "Writing %s ...\n", filename );
+
+       texfile = fopen ( filename, "w" );
+
+       fprintf( texfile, "TEXFILE\n" );
+
+       fprintf( texfile, "%i\n", numBSPShaders );
+
+       for ( i = 0 ; i < numBSPShaders ; i++ ) {
+               shaderInfo_t *se = ShaderInfoForShader( bspShaders[ i ].shader );
+
+               fprintf( texfile, "\n%i %f %f %f", bspShaders[ i ].surfaceFlags,
+                       se->color[ 0 ], se->color[ 1 ], se->color[ 2 ] );
+
+               bspShaders[ i ].surfaceFlags = i;
+       }
+
+       fclose( texfile );
+}
+
+
+
 /*
    EndBSPFile()
    finishes a new bsp and writes to disk
  */
 
-void EndBSPFile( void ){
-       char path[ 1024 ];
-
+void EndBSPFile( qboolean do_write, const char *BSPFilePath, const char *surfaceFilePath ){
 
        Sys_FPrintf( SYS_VRB, "--- EndBSPFile ---\n" );
 
@@ -408,13 +552,25 @@ void EndBSPFile( void ){
        numBSPEntities = numEntities;
        UnparseEntities();
 
-       /* write the surface extra file */
-       WriteSurfaceExtraFile( source );
+       if ( do_write ) {
+               /* write the surface extra file */
+               WriteSurfaceExtraFile( surfaceFilePath );
+
+               if ( game->texFile )
+               {
+                       char basename[ 1024 ];  
+                       char filename[ 1024 ];
+                       strncpy( basename, BSPFilePath, sizeof(basename) );
+                       sprintf( filename, "%s.tex", basename );
+
+                       /* only create tex file if it is the first compile */
+                       WriteTexFile( filename );
+               }
 
-       /* write the bsp */
-       sprintf( path, "%s.bsp", source );
-       Sys_Printf( "Writing %s\n", path );
-       WriteBSPFile( path );
+               /* write the bsp */
+               Sys_Printf( "Writing %s\n", BSPFilePath );
+               WriteBSPFile( BSPFilePath );
+       }
 }
 
 
@@ -443,9 +599,7 @@ void EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes ){
        for ( b = brushes; b != NULL; b = b->next )
        {
                /* check limits */
-               if ( numBSPBrushes == MAX_MAP_BRUSHES ) {
-                       Error( "MAX_MAP_BRUSHES (%d)", numBSPBrushes );
-               }
+               AUTOEXPAND_BY_REALLOC_BSP( Brushes, 1024 );
 
                /* get bsp brush */
                b->outputNum = numBSPBrushes;
@@ -466,9 +620,7 @@ void EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes ){
                        b->sides[ j ].outputNum = -1;
 
                        /* check count */
-                       if ( numBSPBrushSides == MAX_MAP_BRUSHSIDES ) {
-                               Error( "MAX_MAP_BRUSHSIDES " );
-                       }
+                       AUTOEXPAND_BY_REALLOC_BSP( BrushSides, 1024 );
 
                        /* emit side */
                        b->sides[ j ].outputNum = numBSPBrushSides;
@@ -555,9 +707,7 @@ void BeginModel( void ){
 
 
        /* test limits */
-       if ( numBSPModels == MAX_MAP_MODELS ) {
-               Error( "MAX_MAP_MODELS" );
-       }
+       AUTOEXPAND_BY_REALLOC_BSP( Models, 256 );
 
        /* get model and entity */
        mod = &bspModels[ numBSPModels ];