]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/gtkgensurf/gensurf.cpp
reformat code! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / contrib / gtkgensurf / gensurf.cpp
1 /*
2    GenSurf plugin for GtkRadiant
3    Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include <gtk/gtk.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 /*
24    #include <string.h>
25    #include <tchar.h>
26    #include <math.h>
27  */
28 #include "gensurf.h"
29
30 char gszAppDir[NAME_MAX];
31 char gszCaption[64];
32 char gszIni[NAME_MAX];
33 char gszHelpFile[NAME_MAX];
34 char gszMapFile[NAME_MAX];
35 char gszVersion[64];
36 double Amplitude;
37 double Roughness;
38 double TexOffset[2];
39 double TexScale[2];
40 double WaveLength;
41 double Hll, Hur, Vll, Vur;
42 double Z00, Z01, Z10, Z11;
43 ELEMENT Vertex[(MAX_ROWS + 1) * (MAX_ROWS + 1)];
44 int AddHints;
45 int ArghRad2;
46 int AutoOverwrite;
47 int Decimate = 0;
48 int SnapToGrid = 0;           // 0, or the grid size to snap to. // Hydra : snap to grid
49 int FileAppend = 0;
50 int FixBorders;
51 int HideBackFaces = 0;
52 int NH, NV;
53 int NumVerticesSelected;
54 int Plane;
55 int Preview;
56 int RandomSeed = 1;
57 int Skybox;
58 int UseDetail;
59 int UseLadder;
60 int VertexMode = 0;
61 int WaveType;
62 int gNumNodes = 0;
63 int gNumTris = 0;
64 int vid_x, vid_y;
65 int view_x, view_y;
66 int view_cx, view_cy;
67 int UsePatches;
68 int SlantAngle;
69 int GimpHints;
70 int Antialiasing;             // ^Fishman - Antializing for the preview window.
71 int AddTerrainKey;             // ^Fishman - Add terrain key to func_group.
72 int SP;             // ^Fishman - Snap to grid.
73
74 ui::Window g_pWnd{ui::null};        // ghwnd;
75 GtkWidget *g_pRadiantWnd; // ghwnd_main;
76 /*HWND      ghwndAngles;
77  */GtkWidget *g_pWndPreview;
78 GtkWidget *g_pPreviewWidget;
79 MYBITMAP gbmp;
80 NODE *gNode = (NODE *) NULL;
81 TRI *gTri = (TRI *) NULL;
82
83 int Game;
84 bounding_box PlayerBox[NUMGAMES] = {{{-16., 16.}, {-16., 16.}, {-24., 32.}},    // Quake2
85                                     {{-16., 16.}, {-16., 16.}, {-36., 36.}},    // Half-Life
86                                     {{-16., 16.}, {-16., 16.}, {-32., 32.}},    // SiN
87                                     {{-16., 16.}, {-16., 16.}, {-24., 32.}},    // Heretic2 (guess)
88                                     {{-16., 16.}, {-16., 16.}, {-24., 32.}},    // KingPin (guess)
89                                     {{-30., 30.}, {-30., 30.}, {-10., 160.}},    // Genesis3D (no idea)
90                                     {{-16., 16.}, {-16., 16.}, {-24., 32.}}};   // Quake3 (not sure)
91 //char      gszOutputDir[NUMGAMES][NAME_MAX];
92 //char      gszTextureDir[NUMGAMES][NAME_MAX];
93 char Texture[NUMGAMES][3][64];
94 //char      pakfile[NUMGAMES][NAME_MAX];
95 //char      lastpakfile[NUMGAMES][NAME_MAX];
96 //int       UsePak[NUMGAMES];
97 //char      GameDir[NUMGAMES][NAME_MAX];
98
99 char GameName[NUMGAMES][16] = {"Quake2", "Half-Life", "SiN", "Heretic2", "Kingpin", "Genesis3D", "Quake3"};
100
101
102 bool GenSurfInit()
103 {
104     strcpy(gszVersion, "1.05");
105     strcpy(gszCaption, "GtkGenSurf");
106     if (strlen(gszVersion)) {
107         strcat(gszCaption, " v");
108         strcat(gszCaption, gszVersion);
109     }
110
111     strcpy(gszIni, g_FuncTable.m_pfnProfileGetDirectory());
112     strcat(gszIni, "gensurf.ini");
113
114 /*if (g_FuncTable.m_pfnReadProjectKey != NULL)
115    {
116     char *basepath;
117
118     basepath = g_FuncTable.m_pfnReadProjectKey("basepath");
119     if (basepath)
120     {
121       g_strdown (basepath);
122       if (strstr(basepath,"baseq3"))
123         Game = QUAKE3;
124       else if (strstr (basepath,"baseq2"))
125         Game = QUAKE2;
126       else // Gotta have a game, might as well be Quake3
127         Game = QUAKE3;
128     }
129     else
130       Game = QUAKE3;
131    }
132    else */
133     Game = QUAKE3;
134
135
136     if (g_pWnd == NULL) {
137         g_pWnd = create_main_dialog();
138     }
139
140     ReadIniFile(gszIni);
141
142     return true;
143 }
144
145 // Reads default values
146
147 #define OPTS_SECTION "Options"
148
149 void ReadIniFile(const char *file)
150 {
151     char *Text;
152     float x1, x2, x3, x4;
153     int i;
154
155     Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "Amplitude", "");
156     if (strlen(Text)) {
157         Amplitude = atof(Text);
158     } else {
159         Amplitude = 128;
160     }
161
162     Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "Roughness", "");
163     if (strlen(Text)) {
164         Roughness = atof(Text);
165     } else {
166         Roughness = 16;
167     }
168
169     Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "WaveLength", "");
170     if (strlen(Text)) {
171         WaveLength = atof(Text);
172     } else {
173         WaveLength = 1024;
174     }
175
176     Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "Extents", "");
177     if (strlen(Text)) {
178         sscanf(Text, "%f,%f,%f,%f", &x1, &x2, &x3, &x4);
179         Hll = x1;
180         Vll = x2;
181         Hur = x3;
182         Vur = x4;
183     } else {
184         Hll = -512;
185         Vll = -512;
186         Hur = 512;
187         Vur = 512;
188     }
189
190     Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "CornerValues", "");
191     if (strlen(Text)) {
192         sscanf(Text, "%f,%f,%f,%f", &x1, &x2, &x3, &x4);
193         Z00 = x1;
194         Z01 = x2;
195         Z10 = x3;
196         Z11 = x4;
197     } else {
198         Z00 = 0.;
199         Z01 = 0.;
200         Z10 = 0.;
201         Z11 = 0.;
202     }
203
204     Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "TextureOffset", "");
205     if (strlen(Text)) {
206         sscanf(Text, "%f,%f", &x1, &x2);
207         TexOffset[0] = x1;
208         TexOffset[1] = x2;
209     } else {
210         TexOffset[0] = 0.;
211         TexOffset[1] = 0.;
212     }
213
214     Text = g_FuncTable.m_pfnProfileLoadString(file, OPTS_SECTION, "TextureScale", "");
215     if (strlen(Text)) {
216         sscanf(Text, "%f,%f", &x1, &x2);
217         TexScale[0] = x1;
218         TexScale[1] = x2;
219         if (TexScale[0] == 0.) {
220             TexScale[0] = 1.0;
221         }
222         if (TexScale[1] == 0.) {
223             TexScale[1] = 1.0;
224         }
225     } else {
226         TexScale[0] = 1.;
227         TexScale[1] = 1.;
228     }
229
230     NH = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "NH", 8);
231     NH = max(1, min(NH, MAX_ROWS));
232     NV = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "NV", 8);
233     NV = max(1, min(NV, MAX_ROWS));
234
235 //      Decimate   = GetPrivateProfileInt(OPTS_SECTION,"Decimate",0,file);
236 //      Decimate = max(0,min(Decimate,100));
237
238     AddHints = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "AddHints", 0);
239     ArghRad2 = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "ArghRad2", 0);
240     AutoOverwrite = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "AutoOverwrite", 0);
241     FixBorders = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "FixBorders", 1);
242     HideBackFaces = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "HideBackFaces", 0);
243     Plane = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "Plane", 0);
244     Preview = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "Preview", 0);
245     Antialiasing = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "Antialiasing",
246                                                    0); // ^Fishman - Antializing for the preview window.
247     RandomSeed = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "RandomSeed", 1);
248     Skybox = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "Skybox", 0);
249     UseDetail = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "UseDetail", 0);
250     AddTerrainKey = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "AddTerrainKey",
251                                                     0); // ^Fishman - Add terrain key to func_group.
252     UseLadder = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "UseLadder", 0);
253     WaveType = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "WaveType", 0);
254     vid_x = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "vid_x", 0);
255     vid_y = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "vid_y", 0);
256     view_x = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "view_x", 0);
257     view_y = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "view_y", 0);
258     view_cx = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "view_cx", 0);
259     view_cy = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "view_cy", 0);
260
261     UsePatches = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "UsePatches", 0);
262
263     SlantAngle = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "SlantAngle", 60);
264     GimpHints = g_FuncTable.m_pfnProfileLoadInt(file, OPTS_SECTION, "GimpHints", 0);
265
266     for (i = 0; i < NUMGAMES; i++) {
267         //    strcpy (gszOutputDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"OutputDir",""));
268         strcpy(Texture[i][0], g_FuncTable.m_pfnProfileLoadString(file, GameName[i], "Texture", ""));
269         strcpy(Texture[i][1], g_FuncTable.m_pfnProfileLoadString(file, GameName[i], "Texture2", ""));
270         strcpy(Texture[i][2], g_FuncTable.m_pfnProfileLoadString(file, GameName[i], "Texture3", ""));
271         //    strcpy (gszTextureDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"TextureDir",""));
272         //    UsePak[i] = GetPrivateProfileInt(GameName[i],"UsePak",0);
273         //    strcpy (pakfile[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"PakFile",""));
274         //    strcpy (lastpakfile[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"LastPakFile",""));
275         //    strcpy (GameDir[i], g_FuncTable.m_pfnProfileLoadString (file, GameName[i],"GameDir","\0"));
276     }
277     /*
278        if(!strlen(gszTextureDir[QUAKE2]))
279           strcpy(gszTextureDir[QUAKE2],"c:\\quake2\\baseq2\\textures\\");
280        if(!strlen(gszTextureDir[KINGPIN]))
281           strcpy(gszTextureDir[KINGPIN],"c:\\kingpin\\main\\textures\\");
282      */
283     if (!strlen(Texture[QUAKE2][0])) {
284         strcpy(Texture[QUAKE2][0], "textures/e1u1/grass1_4");
285     }
286     if (!strlen(Texture[HALFLIFE][0])) {
287         strcpy(Texture[HALFLIFE][0], "textures/OUT_GRND1");
288     }
289     if (!strlen(Texture[SIN][0])) {
290         strcpy(Texture[SIN][0], "textures/generic/floor_organic/fl_grass");
291     }
292     if (!strlen(Texture[HERETIC2][0])) {
293         strcpy(Texture[HERETIC2][0], "textures/canyon/canyon05");
294     }
295     if (!strlen(Texture[KINGPIN][0])) {
296         strcpy(Texture[KINGPIN][0], "textures/bricks/s_sr_m3");
297     }
298     if (!strlen(Texture[GENESIS3D][0])) {
299         strcpy(Texture[GENESIS3D][0], "textures/rock13");
300     }
301     if (!strlen(Texture[QUAKE3][0])) {
302         strcpy(Texture[QUAKE3][0], "textures/organics/grass3");
303     }
304     if (!strlen(Texture[QUAKE3][1])) {
305         strcpy(Texture[QUAKE3][1], "textures/common/caulk");
306     }
307     strcpy(gbmp.name, g_FuncTable.m_pfnProfileLoadString(file, "Bitmap", "Filename", ""));
308
309
310     gbmp.colors = NULL;
311     if (strlen(gbmp.name)) {
312         OpenBitmap();
313     }
314
315     strcpy(gbmp.defpath, g_FuncTable.m_pfnProfileLoadString(file, "Bitmap", "DefaultPath", ""));
316
317     Text = g_FuncTable.m_pfnProfileLoadString(file, "Bitmap", "BlackValue", "");
318     if (strlen(Text)) {
319         gbmp.black_value = atof(Text);
320     } else {
321         gbmp.black_value = 0;
322     }
323
324     Text = g_FuncTable.m_pfnProfileLoadString(file, "Bitmap", "WhiteValue", "");
325     if (strlen(Text)) {
326         gbmp.white_value = atof(Text);
327     } else {
328         gbmp.white_value = 256.;
329     }
330 }
331
332 /*
333    ============
334    va
335
336    does a varargs printf into a temp buffer, so I don't need to have
337    varargs versions of all text functions.
338    FIXME: make this buffer size safe someday
339    ============
340  */
341 char *va(const char *format, ...)
342 {
343     va_list argptr;
344     static char string[1024];
345
346     va_start(argptr, format);
347     vsprintf(string, format, argptr);
348     va_end(argptr);
349
350     return string;
351 }
352
353
354 // Writes current values to INI file
355 void WriteIniFile(const char *file)
356 {
357     int i;
358
359     g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "Amplitude", va("%g", Amplitude));
360     g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "Roughness", va("%g", Roughness));
361     g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "WaveLength", va("%g", WaveLength));
362     g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "Extents", va("%g,%g,%g,%g", Hll, Vll, Hur, Vur));
363     g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "CornerValues", va("%g,%g,%g,%g", Z00, Z01, Z10, Z11));
364     g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "TextureOffset", va("%g,%g", TexOffset[0], TexOffset[1]));
365     g_FuncTable.m_pfnProfileSaveString(file, OPTS_SECTION, "TextureScale", va("%g,%g", TexScale[0], TexScale[1]));
366     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "NH", NH);
367     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "NV", NV);
368     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "AddHints", AddHints);
369     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "ArghRad2", ArghRad2);
370     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "AutoOverwrite", AutoOverwrite);
371     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "FixBorders", FixBorders);
372     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "Plane", Plane);
373     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "Preview", Preview);
374     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "Antialiasing",
375                                     Antialiasing); // ^Fishman - Antializing for the preview window.
376     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "RandomSeed", RandomSeed);
377     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "Skybox", Skybox);
378     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "UseDetail", UseDetail);
379     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "AddTerrainKey",
380                                     AddTerrainKey); // ^Fishman - Add terrain key to func_group.
381     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "UseLadder", UseLadder);
382     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "WaveType", WaveType);
383     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "vid_x", vid_x);
384     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "vid_y", vid_y);
385     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "view_x", view_x);
386     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "view_y", view_y);
387     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "view_cx", view_cx);
388     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "view_cy", view_cy);
389     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "UsePatches", UsePatches);
390     g_FuncTable.m_pfnProfileSaveInt(file, OPTS_SECTION, "SlantAngle", SlantAngle);
391     for (i = 0; i < NUMGAMES; i++) {
392         g_FuncTable.m_pfnProfileSaveString(file, GameName[i], "Texture", Texture[i][0]);
393         g_FuncTable.m_pfnProfileSaveString(file, GameName[i], "Texture2", Texture[i][1]);
394         g_FuncTable.m_pfnProfileSaveString(file, GameName[i], "Texture3", Texture[i][2]);
395     }
396
397     g_FuncTable.m_pfnProfileSaveString(file, "Bitmap", "Filename", gbmp.name);
398     g_FuncTable.m_pfnProfileSaveString(file, "Bitmap", "DefaultPath", gbmp.defpath);
399     g_FuncTable.m_pfnProfileSaveString(file, "Bitmap", "BlackValue", va("%g", gbmp.black_value));
400     g_FuncTable.m_pfnProfileSaveString(file, "Bitmap", "WhiteValue", va("%g", gbmp.white_value));
401 //g_FuncTable.m_pfnProfileSaveString (file, "Formula", "Formula", ExcelFunc );
402 }
403
404 void UpdatePreview(bool DataChange)
405 {
406     if (g_pWndPreview && gtk_widget_get_visible(g_pWndPreview)) {
407         if (DataChange) {
408             GenerateXYZ();
409         }
410
411         gtk_widget_draw(g_pPreviewWidget, NULL);
412     }
413 }
414
415 void SaveSetup(GtkWidget *parent)
416 {
417     const char *name = g_FuncTable.m_pfnFileDialog(parent, false, "Save GenSurf Settings",
418                                                    g_FuncTable.m_pfnProfileGetDirectory());
419
420     if (name != NULL) {
421         char key[32], text[32];
422         int i, j;
423
424         WriteIniFile(name);
425         g_FuncTable.m_pfnProfileSaveString(name, OPTS_SECTION, "MapFile", gszMapFile);
426         sprintf(text, "0x%04x", FileAppend);
427         g_FuncTable.m_pfnProfileSaveString(name, OPTS_SECTION, "Append", text);
428         sprintf(text, "0x%04x", Decimate);
429         g_FuncTable.m_pfnProfileSaveString(name, OPTS_SECTION, "Decimate", text);
430         for (i = 0; i <= NH; i++) {
431             for (j = 0; j <= NV; j++) {
432                 if (xyz[i][j].fixed) {
433                     sprintf(key, "I%dJ%d", i, j);
434                     sprintf(text, "%g %g %g", xyz[i][j].fixed_value, xyz[i][j].range, xyz[i][j].rate);
435                     g_FuncTable.m_pfnProfileSaveString(name, "FixedPoints", key, text);
436                 }
437             }
438         }
439     }
440 }
441
442 void OpenSetup(GtkWidget *parent, int UseDefaults)
443 {
444     const char *name;
445     char key[32], *text;
446     float value, range, rate;
447     int i, j;
448
449     if (UseDefaults) {
450         name = g_strdup("plugins/defaults.srf"); // dummy string
451     } else {
452         name = g_FuncTable.m_pfnFileDialog(parent, true, "Open GenSurf Settings",
453                                            g_FuncTable.m_pfnProfileGetDirectory());
454     }
455
456     if (name != NULL) {
457         ReadIniFile(name);
458         Decimate = g_FuncTable.m_pfnProfileLoadInt(name, OPTS_SECTION, "Decimate", 0);
459         Decimate = max(0, min(Decimate, 100));
460
461         for (i = 0; i <= NH; i++) {
462             for (j = 0; j <= NV; j++) {
463                 sprintf(key, "I%dJ%d", i, j);
464                 text = g_FuncTable.m_pfnProfileLoadString(name, "FixedPoints", key, "");
465                 if (strlen(text)) {
466                     xyz[i][j].fixed = 1;
467                     xyz[i][j].rate = 0.;
468                     sscanf(text, "%g %g %g", &value, &range, &rate);
469                     xyz[i][j].fixed_value = value;
470                     xyz[i][j].range = range;
471                     xyz[i][j].rate = rate;
472                 } else {
473                     xyz[i][j].fixed = 0;
474                 }
475             }
476         }
477     }
478 }