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