/* Copyright (C) 1999-2007 id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // // writes quake3 map format from internal objects // static int g_count_entities; static int g_count_brushes; #include "plugin.h" extern int g_MapVersion; void Float_Write( float data, IDataStream *out ){ if ( data == (int)data ) { out->printf( "%i ", (int)data ); } else{ out->printf( "%f ", data ); } } void Patch_Write( patchMesh_t *pPatch, IDataStream *out ){ int i, j; const char *str; // write shader name and matrix dimensions str = pPatch->pShader->getName(); if ( strchr( str, ' ' ) ) { Sys_FPrintf( SYS_WRN, "WARNING: Patch_Write: shader names with spaces are not allowed, ignoring '%s'\n", str ); str = SHADER_NOT_FOUND; } if ( !strncmp( str, "textures/", 9 ) ) { str += 9; } out->printf( "patchDef2\n{\n%s\n( %i %i 0 0 0 )\n", str, pPatch->width, pPatch->height ); // write matrix out->printf( "(\n" ); for ( i = 0; i < pPatch->width; i++ ) { out->printf( "( " ); for ( j = 0; j < pPatch->height; j++ ) { out->printf( "( " ); Float_Write( pPatch->ctrl[i][j].xyz[0], out ); Float_Write( pPatch->ctrl[i][j].xyz[1], out ); Float_Write( pPatch->ctrl[i][j].xyz[2], out ); Float_Write( pPatch->ctrl[i][j].st[0], out ); Float_Write( pPatch->ctrl[i][j].st[1], out ); out->printf( ") " ); } out->printf( ")\n" ); } out->printf( ")\n}\n" ); } void Face_Write( face_t *face, IDataStream *out, bool bAlternateTexdef = false ){ int i, j; const char *str; // write planepts for ( i = 0; i < 3; i++ ) { out->printf( "( " ); for ( j = 0; j < 3; j++ ) { Float_Write( face->planepts[i][j], out ); } out->printf( ") " ); } if ( bAlternateTexdef ) { // write alternate texdef out->printf( "( ( " ); for ( i = 0; i < 3; i++ ) Float_Write( face->brushprimit_texdef.coords[0][i], out ); out->printf( ") ( " ); for ( i = 0; i < 3; i++ ) Float_Write( face->brushprimit_texdef.coords[1][i], out ); out->printf( ") ) " ); } // write shader name str = face->texdef.GetName(); if ( strchr( str, ' ' ) ) { Sys_FPrintf( SYS_WRN, "WARNING: Face_Write: shader names with spaces are not allowed, ignoring '%s'\n", str ); str = SHADER_NOT_FOUND; } if ( !strncmp( str, "textures/", 9 ) ) { str += 9; } // Strip all remaining paths. // FIXME: Hydra - this is actually a HalfLife specific bit, not Q2 map format specific. if ( g_MapVersion == MAPVERSION_HL ) { char *pos; while ( ( pos = (char*)strchr( str, '/' ) ) != NULL ) { str = pos + 1; // to speed optimize, change the "while" to an "if" } } out->printf( "%s ", str ); if ( !bAlternateTexdef ) { // write texdef out->printf( "%i %i %i %f %f ", (int)face->texdef.shift[0], (int)face->texdef.shift[1], (int)face->texdef.rotate, face->texdef.scale[0], face->texdef.scale[1] ); } if ( g_MapVersion == MAPVERSION_Q3 ) { // write surface flags out->printf( "%i %i %i\n", face->texdef.contents, face->texdef.flags, face->texdef.value ); } if ( ( g_MapVersion == MAPVERSION_HL ) || ( g_MapVersion == MAPVERSION_Q2 ) ) { // write surface flags if non-zero values. if ( face->texdef.contents || face->texdef.flags || face->texdef.value ) { out->printf( "%i %i %i\n", face->texdef.contents, face->texdef.flags, face->texdef.value ); } else { out->printf( "\n" ); } } } void Primitive_Write( brush_t *pBrush, IDataStream *out ){ if ( ( g_MapVersion == MAPVERSION_Q2 ) && ( pBrush->patchBrush ) ) { Sys_FPrintf( SYS_WRN, "WARNING: Primitive_Write: Patches are not supported in Quake2, ignoring Brush %d\n", g_count_brushes++ ); } else { out->printf( "// brush %i\n", g_count_brushes++ ); out->printf( "{\n" ); if ( pBrush->patchBrush ) { Patch_Write( pBrush->pPatch, out ); } else if ( pBrush->bBrushDef ) { out->printf( "brushDef\n{\n" ); for ( face_t *face = pBrush->brush_faces; face != NULL; face = face->next ) Face_Write( face, out, true ); out->printf( "}\n" ); } else{ for ( face_t *face = pBrush->brush_faces; face != NULL; face = face->next ) Face_Write( face, out ); } out->printf( "}\n" ); } } void Entity_Write( entity_t *pEntity, IDataStream *out ){ epair_t *pEpair; CPtrArray *brushes = (CPtrArray*)pEntity->pData; out->printf( "// entity %i\n", g_count_entities++ ); out->printf( "{\n" ); for ( pEpair = pEntity->epairs; pEpair != NULL; pEpair = pEpair->next ) out->printf( "\"%s\" \"%s\"\n", pEpair->key, pEpair->value ); g_count_brushes = 0; for ( int i = 0; i < brushes->GetSize(); i++ ) Primitive_Write( (brush_t*)brushes->GetAt( i ), out ); out->printf( "}\n" ); } void Map_Write( CPtrArray *map, IDataStream *out ){ g_count_entities = 0; for ( int i = 0; i < map->GetSize(); i++ ) Entity_Write( (entity_t*)map->GetAt( i ), out ); } void Map_WriteQ3( CPtrArray *map, IDataStream *out ){ g_MapVersion = MAPVERSION_Q3; Map_Write( map,out ); } void Map_WriteHL( CPtrArray *map, IDataStream *out ){ g_MapVersion = MAPVERSION_HL; Map_Write( map,out ); } void Map_WriteQ2( CPtrArray *map, IDataStream *out ){ g_MapVersion = MAPVERSION_Q2; Map_Write( map,out ); }