/* GenSurf plugin for GtkRadiant Copyright (C) 2001 David Hyde, Loki software and qeradiant.com This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include /* #include #include #include */ #include "gensurf.h" char gszAppDir[NAME_MAX]; char gszCaption[64]; char gszIni[NAME_MAX]; char gszHelpFile[NAME_MAX]; char gszMapFile[NAME_MAX]; char gszVersion[64]; double Amplitude; double Roughness; double TexOffset[2]; double TexScale[2]; double WaveLength; double Hll, Hur, Vll, Vur; double Z00, Z01, Z10, Z11; ELEMENT Vertex[( MAX_ROWS + 1 ) * ( MAX_ROWS + 1 )]; int AddHints; int ArghRad2; int AutoOverwrite; int Decimate = 0; int SnapToGrid = 0; // 0, or the grid size to snap to. // Hydra : snap to grid int FileAppend = 0; int FixBorders; int HideBackFaces = 0; int NH, NV; int NumVerticesSelected; int Plane; int Preview; int RandomSeed = 1; int Skybox; int UseDetail; int UseLadder; int VertexMode = 0; int WaveType; int gNumNodes = 0; int gNumTris = 0; int vid_x, vid_y; int view_x, view_y; int view_cx, view_cy; int UsePatches; int SlantAngle; int GimpHints; int Antialiasing; // ^Fishman - Antializing for the preview window. int AddTerrainKey; // ^Fishman - Add terrain key to func_group. int SP; // ^Fishman - Snap to grid. ui::Window g_pWnd{ui::null}; // ghwnd; GtkWidget *g_pRadiantWnd; // ghwnd_main; /*HWND ghwndAngles; */GtkWidget *g_pWndPreview; GtkWidget *g_pPreviewWidget; MYBITMAP gbmp; NODE *gNode = (NODE *)NULL; TRI *gTri = (TRI *)NULL; int Game; bounding_box PlayerBox[NUMGAMES] = { {{-16., 16.}, {-16., 16.}, {-24., 32.}}, // Quake2 {{-16., 16.}, {-16., 16.}, {-36., 36.}}, // Half-Life {{-16., 16.}, {-16., 16.}, {-32., 32.}}, // SiN {{-16., 16.}, {-16., 16.}, {-24., 32.}}, // Heretic2 (guess) {{-16., 16.}, {-16., 16.}, {-24., 32.}}, // KingPin (guess) {{-30., 30.}, {-30., 30.}, {-10.,160.}}, // Genesis3D (no idea) {{-16., 16.}, {-16., 16.}, {-24., 32.}}}; // Quake3 (not sure) //char gszOutputDir[NUMGAMES][NAME_MAX]; //char gszTextureDir[NUMGAMES][NAME_MAX]; char Texture[NUMGAMES][3][64]; //char pakfile[NUMGAMES][NAME_MAX]; //char lastpakfile[NUMGAMES][NAME_MAX]; //int UsePak[NUMGAMES]; //char GameDir[NUMGAMES][NAME_MAX]; char GameName[NUMGAMES][16] = {"Quake2", "Half-Life", "SiN", "Heretic2", "Kingpin", "Genesis3D", "Quake3" }; bool GenSurfInit(){ strcpy( gszVersion, "1.05" ); strcpy( gszCaption, "GtkGenSurf" ); if ( strlen( gszVersion ) ) { strcat( gszCaption, " v" ); strcat( gszCaption, gszVersion ); } strcpy( gszIni, g_FuncTable.m_pfnProfileGetDirectory() ); strcat( gszIni, "gensurf.ini" ); /*if (g_FuncTable.m_pfnReadProjectKey != NULL) { char *basepath; basepath = g_FuncTable.m_pfnReadProjectKey("basepath"); if (basepath) { g_strdown (basepath); if (strstr(basepath,"baseq3")) Game = QUAKE3; else if (strstr (basepath,"baseq2")) Game = QUAKE2; else // Gotta have a game, might as well be Quake3 Game = QUAKE3; } else Game = QUAKE3; } else */ Game = QUAKE3; if ( g_pWnd == NULL ) { g_pWnd = create_main_dialog(); } ReadIniFile( gszIni ); return true; } // Reads default values #define OPTS_SECTION "Options" void ReadIniFile( const char *file ){ char *Text; float x1,x2,x3,x4; int i; Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "Amplitude", "" ); if ( strlen( Text ) ) { Amplitude = atof( Text ); } else{ Amplitude = 128; } Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "Roughness", "" ); if ( strlen( Text ) ) { Roughness = atof( Text ); } else{ Roughness = 16; } Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "WaveLength", "" ); if ( strlen( Text ) ) { WaveLength = atof( Text ); } else{ WaveLength = 1024; } Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "Extents", "" ); if ( strlen( Text ) ) { sscanf( Text,"%f,%f,%f,%f",&x1,&x2,&x3,&x4 ); Hll = x1; Vll = x2; Hur = x3; Vur = x4; } else { Hll = -512; Vll = -512; Hur = 512; Vur = 512; } Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "CornerValues", "" ); if ( strlen( Text ) ) { sscanf( Text,"%f,%f,%f,%f",&x1,&x2,&x3,&x4 ); Z00 = x1; Z01 = x2; Z10 = x3; Z11 = x4; } else { Z00 = 0.; Z01 = 0.; Z10 = 0.; Z11 = 0.; } Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION, "TextureOffset", "" ); if ( strlen( Text ) ) { sscanf( Text,"%f,%f",&x1,&x2 ); TexOffset[0] = x1; TexOffset[1] = x2; } else { TexOffset[0] = 0.; TexOffset[1] = 0.; } Text = g_FuncTable.m_pfnProfileLoadString( file, OPTS_SECTION,"TextureScale","" ); if ( strlen( Text ) ) { sscanf( Text,"%f,%f",&x1,&x2 ); TexScale[0] = x1; TexScale[1] = x2; if ( TexScale[0] == 0. ) { TexScale[0] = 1.0; } if ( TexScale[1] == 0. ) { TexScale[1] = 1.0; } } else { TexScale[0] = 1.; TexScale[1] = 1.; } NH = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"NH",8 ); NH = max( 1,min( NH,MAX_ROWS ) ); NV = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"NV",8 ); NV = max( 1,min( NV,MAX_ROWS ) ); // Decimate = GetPrivateProfileInt(OPTS_SECTION,"Decimate",0,file); // Decimate = max(0,min(Decimate,100)); AddHints = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"AddHints",0 ); ArghRad2 = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"ArghRad2",0 ); AutoOverwrite = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"AutoOverwrite",0 ); FixBorders = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"FixBorders",1 ); HideBackFaces = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"HideBackFaces",0 ); Plane = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Plane",0 ); Preview = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Preview", 0 ); Antialiasing = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Antialiasing",0 ); // ^Fishman - Antializing for the preview window. RandomSeed = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"RandomSeed",1 ); Skybox = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"Skybox",0 ); UseDetail = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"UseDetail",0 ); AddTerrainKey = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"AddTerrainKey",0 ); // ^Fishman - Add terrain key to func_group. UseLadder = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"UseLadder",0 ); WaveType = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"WaveType",0 ); vid_x = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"vid_x", 0 ); vid_y = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"vid_y", 0 ); view_x = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_x",0 ); view_y = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_y",0 ); view_cx = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_cx",0 ); view_cy = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"view_cy",0 ); UsePatches = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"UsePatches",0 ); SlantAngle = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"SlantAngle",60 ); GimpHints = g_FuncTable.m_pfnProfileLoadInt( file, OPTS_SECTION,"GimpHints",0 ); for ( i = 0; i < NUMGAMES; i++ ) { // strcpy (gszOutputDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"OutputDir","")); strcpy( Texture[i][0], g_FuncTable.m_pfnProfileLoadString( file, GameName[i], "Texture", "" ) ); strcpy( Texture[i][1], g_FuncTable.m_pfnProfileLoadString( file, GameName[i], "Texture2", "" ) ); strcpy( Texture[i][2], g_FuncTable.m_pfnProfileLoadString( file, GameName[i], "Texture3", "" ) ); // strcpy (gszTextureDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"TextureDir","")); // UsePak[i] = GetPrivateProfileInt(GameName[i],"UsePak",0); // strcpy (pakfile[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"PakFile","")); // strcpy (lastpakfile[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"LastPakFile","")); // strcpy (GameDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"GameDir","\0")); } /* if(!strlen(gszTextureDir[QUAKE2])) strcpy(gszTextureDir[QUAKE2],"c:\\quake2\\baseq2\\textures\\"); if(!strlen(gszTextureDir[KINGPIN])) strcpy(gszTextureDir[KINGPIN],"c:\\kingpin\\main\\textures\\"); */ if ( !strlen( Texture[QUAKE2][0] ) ) { strcpy( Texture[QUAKE2][0], "textures/e1u1/grass1_4" ); } if ( !strlen( Texture[HALFLIFE][0] ) ) { strcpy( Texture[HALFLIFE][0], "textures/OUT_GRND1" ); } if ( !strlen( Texture[SIN][0] ) ) { strcpy( Texture[SIN][0], "textures/generic/floor_organic/fl_grass" ); } if ( !strlen( Texture[HERETIC2][0] ) ) { strcpy( Texture[HERETIC2][0], "textures/canyon/canyon05" ); } if ( !strlen( Texture[KINGPIN][0] ) ) { strcpy( Texture[KINGPIN][0], "textures/bricks/s_sr_m3" ); } if ( !strlen( Texture[GENESIS3D][0] ) ) { strcpy( Texture[GENESIS3D][0],"textures/rock13" ); } if ( !strlen( Texture[QUAKE3][0] ) ) { strcpy( Texture[QUAKE3][0], "textures/organics/grass3" ); } if ( !strlen( Texture[QUAKE3][1] ) ) { strcpy( Texture[QUAKE3][1], "textures/common/caulk" ); } strcpy( gbmp.name, g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","Filename","" ) ); gbmp.colors = NULL; if ( strlen( gbmp.name ) ) { OpenBitmap(); } strcpy( gbmp.defpath, g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","DefaultPath","" ) ); Text = g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","BlackValue","" ); if ( strlen( Text ) ) { gbmp.black_value = atof( Text ); } else{ gbmp.black_value = 0; } Text = g_FuncTable.m_pfnProfileLoadString( file, "Bitmap","WhiteValue","" ); if ( strlen( Text ) ) { gbmp.white_value = atof( Text ); } else{ gbmp.white_value = 256.; } } /* ============ va does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functions. FIXME: make this buffer size safe someday ============ */ char *va( const char *format, ... ){ va_list argptr; static char string[1024]; va_start( argptr, format ); vsprintf( string, format,argptr ); va_end( argptr ); return string; } // Writes current values to INI file void WriteIniFile( const char *file ){ int i; g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "Amplitude", va( "%g",Amplitude ) ); g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "Roughness", va( "%g",Roughness ) ); g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "WaveLength", va( "%g",WaveLength ) ); g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "Extents", va( "%g,%g,%g,%g",Hll,Vll,Hur,Vur ) ); g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "CornerValues", va( "%g,%g,%g,%g",Z00,Z01,Z10,Z11 ) ); g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "TextureOffset",va( "%g,%g",TexOffset[0],TexOffset[1] ) ); g_FuncTable.m_pfnProfileSaveString( file, OPTS_SECTION, "TextureScale", va( "%g,%g",TexScale[0],TexScale[1] ) ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "NH", NH ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "NV", NV ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "AddHints", AddHints ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "ArghRad2", ArghRad2 ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "AutoOverwrite", AutoOverwrite ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "FixBorders", FixBorders ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Plane", Plane ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Preview", Preview ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Antialiasing", Antialiasing ); // ^Fishman - Antializing for the preview window. g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "RandomSeed", RandomSeed ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "Skybox", Skybox ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "UseDetail", UseDetail ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "AddTerrainKey", AddTerrainKey ); // ^Fishman - Add terrain key to func_group. g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "UseLadder", UseLadder ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "WaveType", WaveType ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "vid_x", vid_x ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "vid_y", vid_y ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_x", view_x ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_y", view_y ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_cx", view_cx ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "view_cy", view_cy ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "UsePatches", UsePatches ); g_FuncTable.m_pfnProfileSaveInt( file, OPTS_SECTION, "SlantAngle", SlantAngle ); for ( i = 0; i < NUMGAMES; i++ ) { g_FuncTable.m_pfnProfileSaveString( file, GameName[i], "Texture", Texture[i][0] ); g_FuncTable.m_pfnProfileSaveString( file, GameName[i], "Texture2", Texture[i][1] ); g_FuncTable.m_pfnProfileSaveString( file, GameName[i], "Texture3", Texture[i][2] ); } g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "Filename", gbmp.name ); g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "DefaultPath", gbmp.defpath ); g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "BlackValue", va( "%g",gbmp.black_value ) ); g_FuncTable.m_pfnProfileSaveString( file, "Bitmap", "WhiteValue", va( "%g",gbmp.white_value ) ); //g_FuncTable.m_pfnProfileSaveString (file, "Formula", "Formula", ExcelFunc ); } void UpdatePreview( bool DataChange ){ if ( g_pWndPreview && gtk_widget_get_visible( g_pWndPreview ) ) { if ( DataChange ) { GenerateXYZ(); } gtk_widget_draw( g_pPreviewWidget, NULL ); } } void SaveSetup( GtkWidget *parent ){ const char *name = g_FuncTable.m_pfnFileDialog( parent, false, "Save GenSurf Settings", g_FuncTable.m_pfnProfileGetDirectory() ); if ( name != NULL ) { char key[32], text[32]; int i, j; WriteIniFile( name ); g_FuncTable.m_pfnProfileSaveString( name, OPTS_SECTION,"MapFile",gszMapFile ); sprintf( text,"0x%04x",FileAppend ); g_FuncTable.m_pfnProfileSaveString( name, OPTS_SECTION,"Append",text ); sprintf( text,"0x%04x",Decimate ); g_FuncTable.m_pfnProfileSaveString( name, OPTS_SECTION,"Decimate",text ); for ( i = 0; i <= NH; i++ ) { for ( j = 0; j <= NV; j++ ) { if ( xyz[i][j].fixed ) { sprintf( key,"I%dJ%d",i,j ); sprintf( text,"%g %g %g", xyz[i][j].fixed_value, xyz[i][j].range, xyz[i][j].rate ); g_FuncTable.m_pfnProfileSaveString( name, "FixedPoints",key,text ); } } } } } void OpenSetup( GtkWidget *parent, int UseDefaults ){ const char *name; char key[32], *text; float value,range,rate; int i, j; if ( UseDefaults ) { name = g_strdup( "plugins/defaults.srf" ); // dummy string } else{ name = g_FuncTable.m_pfnFileDialog( parent, true, "Open GenSurf Settings", g_FuncTable.m_pfnProfileGetDirectory() ); } if ( name != NULL ) { ReadIniFile( name ); Decimate = g_FuncTable.m_pfnProfileLoadInt( name, OPTS_SECTION,"Decimate",0 ); Decimate = max( 0,min( Decimate,100 ) ); for ( i = 0; i <= NH; i++ ) { for ( j = 0; j <= NV; j++ ) { sprintf( key,"I%dJ%d",i,j ); text = g_FuncTable.m_pfnProfileLoadString( name, "FixedPoints", key, "" ); if ( strlen( text ) ) { xyz[i][j].fixed = 1; xyz[i][j].rate = 0.; sscanf( text,"%g %g %g",&value,&range,&rate ); xyz[i][j].fixed_value = value; xyz[i][j].range = range; xyz[i][j].rate = rate; } else{ xyz[i][j].fixed = 0; } } } } }