-/*\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.
+
+GtkWidget *g_pWnd; // 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;
+
+ ReadIniFile (gszIni);
+
+ if (g_pWnd == NULL)
+ g_pWnd = create_main_dialog ();
+
+ 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",""));
+
+ 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 (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_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;
+ }
+ }
+ }
+}