]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/tools/radiant/QE3.CPP
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / tools / radiant / QE3.CPP
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "qe3.h"
33 #include <direct.h>
34 #include <sys/stat.h>
35 #include "WaitDlg.h"
36
37 QEGlobals_t g_qeglobals;
38
39 /*
40  =======================================================================================================================
41  =======================================================================================================================
42  */
43 void WINAPI QE_CheckOpenGLForErrors(void) {
44         CString strMsg;
45         int             i = qglGetError();
46         if (i != GL_NO_ERROR) {
47                 if (i == GL_OUT_OF_MEMORY) {
48                         //
49                         // strMsg.Format("OpenGL out of memory error %s\nDo you wish to save before
50                         // exiting?", gluErrorString((GLenum)i));
51                         //
52                         if (g_pParentWnd->MessageBox(strMsg, EDITOR_WINDOWTEXT " Error", MB_YESNO) == IDYES) {
53                                 Map_SaveFile(NULL, false);
54                         }
55
56                         exit(1);
57                 }
58                 else {
59                         // strMsg.Format("Warning: OpenGL Error %s\n ", gluErrorString((GLenum)i));
60                         common->Printf(strMsg.GetBuffer(0));
61                 }
62         }
63 }
64
65 /*
66  =======================================================================================================================
67  =======================================================================================================================
68  */
69 bool DoesFileExist(const char *pBuff, long &lSize) {
70         CFile   file;
71         if (file.Open(pBuff, CFile::modeRead | CFile::shareDenyNone)) {
72                 lSize += file.GetLength();
73                 file.Close();
74                 return true;
75         }
76
77         return false;
78 }
79
80 /*
81  =======================================================================================================================
82  =======================================================================================================================
83  */
84 bool ExtractPath_and_Filename(const char *pPath, CString &strPath, CString &strFilename) {
85         CString strPathName = pPath;
86         int             nSlash = strPathName.ReverseFind('\\');
87         if (nSlash >= 0) {
88                 strPath = strPathName.Left(nSlash + 1);
89                 strFilename = strPathName.Right(strPathName.GetLength() - nSlash - 1);
90         }
91         else {
92                 strFilename = pPath;
93         }
94
95         return true;
96 }
97
98 /*
99  =======================================================================================================================
100  =======================================================================================================================
101  */
102 void Map_Snapshot() {
103         CString strMsg;
104
105         //
106         // we need to do the following 1. make sure the snapshot directory exists (create
107         // it if it doesn't) 2. find out what the lastest save is based on number 3. inc
108         // that and save the map
109         //
110         CString strOrgPath, strOrgFile;
111         ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
112         AddSlash(strOrgPath);
113         strOrgPath += "snapshots";
114
115         bool                    bGo = true;
116         struct _stat    Stat;
117         if (_stat(strOrgPath, &Stat) == -1) {
118                 bGo = (_mkdir(strOrgPath) != -1);
119         }
120
121         AddSlash(strOrgPath);
122         if (bGo) {
123                 int             nCount = 0;
124                 long    lSize = 0;
125                 CString strNewPath = strOrgPath;
126                 strNewPath += strOrgFile;
127
128                 CString strFile;
129                 while (bGo) {
130                         strFile.Format("%s.%i", strNewPath, nCount);
131                         bGo = DoesFileExist(strFile, lSize);
132                         nCount++;
133                 }
134
135                 // strFile has the next available slot
136                 Map_SaveFile(strFile.GetBuffer(0), false);
137                 Sys_SetTitle(currentmap);
138                 if (lSize > 12 * 1024 * 1024) { // total size of saves > 4 mb
139                         common->Printf
140                         (
141                                 "The snapshot files in the [%s] directory total more than 4 megabytes. You might consider cleaning the directory up.",
142                                 strOrgPath
143                         );
144                 }
145         }
146         else {
147                 strMsg.Format("Snapshot save failed.. unabled to create directory\n%s", strOrgPath);
148                 g_pParentWnd->MessageBox(strMsg);
149         }
150 }
151
152 /*
153  =======================================================================================================================
154     QE_CheckAutoSave If five minutes have passed since making a change and the map hasn't been saved, save it out.
155  =======================================================================================================================
156  */
157 void QE_CheckAutoSave(void) {
158         static bool inAutoSave = false;
159         static bool autoToggle = false;
160         if (inAutoSave) {
161                 Sys_Status("Did not autosave due recursive entry into autosave routine\n");
162                 return;
163         }
164
165         if ( !mapModified ) {
166                 return;
167         }
168
169         inAutoSave = true;
170
171         if ( g_PrefsDlg.m_bAutoSave ) {
172                 CString strMsg = g_PrefsDlg.m_bSnapShots ? "Autosaving snapshot..." : "Autosaving...";
173                 Sys_Status(strMsg.GetBuffer(0), 0);
174
175                 if (g_PrefsDlg.m_bSnapShots && stricmp(currentmap, "unnamed.map") != 0) {
176                         Map_Snapshot();
177                 } else {
178                         Map_SaveFile(ValueForKey(g_qeglobals.d_project_entity, (autoToggle == 0) ? "autosave1" : "autosave2" ), false, true);
179                         autoToggle ^= 1;
180                 }
181                 Sys_Status("Autosaving...Saved.", 0);
182                 mapModified = 0;                // DHM - _D3XP
183         } else {
184                 common->Printf("Autosave skipped...\n");
185                 Sys_Status("Autosave skipped...", 0);
186         }
187
188         inAutoSave = false;
189 }
190
191 /*
192  =======================================================================================================================
193  =======================================================================================================================
194  */
195
196 const char      *g_pPathFixups[] = {
197         "basepath",
198
199         // "remotebasepath",
200         "entitypath",
201
202         // "texturepath",
203         "autosave",
204
205         // "mapspath"
206 };
207
208 const int       g_nPathFixupCount = sizeof(g_pPathFixups) / sizeof (const char *);
209
210 /*
211  =======================================================================================================================
212     QE_LoadProject
213  =======================================================================================================================
214  */
215 bool QE_LoadProject(char *projectfile) {
216         char            *data;
217         ID_TIME_T               time;
218
219         common->Printf("QE_LoadProject (%s)\n", projectfile);
220
221         if ( fileSystem->ReadFile( projectfile, reinterpret_cast < void ** > (&data), &time) <= 0 ) {
222                 return false;
223         }
224
225         g_strProject = projectfile;
226         g_PrefsDlg.m_strLastProject = projectfile;
227         g_PrefsDlg.SavePrefs();
228
229         CString strData = data;
230
231         fileSystem->FreeFile( data );
232
233         StartTokenParsing(strData.GetBuffer(0));
234         g_qeglobals.d_project_entity = Entity_Parse(true);
235         if (!g_qeglobals.d_project_entity) {
236                 Error("Couldn't parse %s", projectfile);
237         }
238
239         // set here some default project settings you need
240         if (strlen(ValueForKey(g_qeglobals.d_project_entity, "brush_primit")) == 0) {
241                 SetKeyValue(g_qeglobals.d_project_entity, "brush_primit", "0");
242         }
243
244         g_qeglobals.m_bBrushPrimitMode = IntForKey(g_qeglobals.d_project_entity, "brush_primit");
245
246         Eclass_InitForSourceDirectory(ValueForKey(g_qeglobals.d_project_entity, "entitypath"));
247         g_Inspectors->FillClassList();  // list in entity window
248
249         Map_New();
250
251         // FillTextureMenu();
252         FillBSPMenu();
253
254         return true;
255 }
256
257 /*
258  =======================================================================================================================
259     QE_SaveProject £
260  =======================================================================================================================
261  */
262 bool QE_SaveProject(const char *pProjectFile) {
263
264         idFile *file = fileSystem->OpenFileWrite(pProjectFile);
265         if ( !file ) {
266                 return false;
267         }
268
269         file->Write("{\n", 2);
270
271         int count = g_qeglobals.d_project_entity->epairs.GetNumKeyVals();
272         for (int i = 0; i < count; i++) {
273                 file->WriteFloatString( "\"%s\" \"%s\"\n", g_qeglobals.d_project_entity->epairs.GetKeyVal(i)->GetKey().c_str(), g_qeglobals.d_project_entity->epairs.GetKeyVal(i)->GetValue().c_str());
274         }
275
276         file->Write("}\n", 2);
277
278         fileSystem->CloseFile( file );
279
280         return true;
281 }
282
283 /* QE_KeyDown */
284 #define SPEED_MOVE      32
285 #define SPEED_TURN      22.5
286
287 /*
288  =======================================================================================================================
289     ConnectEntities Sets target / name on the two entities selected from the first selected to the secon
290  =======================================================================================================================
291  */
292 void ConnectEntities(void) {
293         entity_t        *e1;
294         const char              *target;
295         idStr strTarget;
296         int i, t;
297
298         if (g_qeglobals.d_select_count < 2) {
299                 Sys_Status("Must have at least two brushes selected.", 0);
300                 Sys_Beep();
301                 return;
302         }
303
304         e1 = g_qeglobals.d_select_order[0]->owner;
305
306         for (i = 0; i < g_qeglobals.d_select_count; i++) {
307                 if (g_qeglobals.d_select_order[i]->owner == world_entity) {
308                         Sys_Status("Can't connect to the world.", 0);
309                         Sys_Beep();
310                         return;
311                 }
312         }
313
314         for (i = 1; i < g_qeglobals.d_select_count; i++) {
315                 if (e1 == g_qeglobals.d_select_order[i]->owner) {
316                         Sys_Status("Brushes are from same entity.", 0);
317                         Sys_Beep();
318                         return;
319                 }
320         }
321
322         target = ValueForKey(e1, "target");
323         if ( target && *target) {
324                 for (t = 1; t < 2048; t++) {
325                         target = ValueForKey(e1, va("target%i", t));
326                         if (target && *target) {
327                                 continue;
328                         } else {
329                                 break;
330                         }
331                 }
332         } else {
333                 t = 0;
334         }
335
336         for (i = 1; i < g_qeglobals.d_select_count; i++) {
337                 target = ValueForKey(g_qeglobals.d_select_order[i]->owner, "name");
338                 if (target && *target) {
339                         strTarget = target;
340                 } else {
341                         UniqueTargetName(strTarget);
342                 }
343                 if (t == 0) {
344                         SetKeyValue(e1, "target", strTarget);
345                 } else {
346                         SetKeyValue(e1, va("target%i", t), strTarget);
347                 }
348                 t++;
349         }
350
351         Sys_UpdateWindows(W_XY | W_CAMERA);
352
353         Select_Deselect();
354         Select_Brush(g_qeglobals.d_select_order[1]);
355 }
356
357 /*
358  =======================================================================================================================
359  =======================================================================================================================
360  */
361 bool QE_SingleBrush(bool bQuiet, bool entityOK) {
362         if ((selected_brushes.next == &selected_brushes) || (selected_brushes.next->next != &selected_brushes)) {
363                 if (!bQuiet) {
364                         Sys_Status("Error: you must have a single brush selected\n");
365                 }
366
367                 return false;
368         }
369
370         if (!entityOK && selected_brushes.next->owner->eclass->fixedsize) {
371                 if (!bQuiet) {
372                         Sys_Status("Error: you cannot manipulate fixed size entities\n");
373                 }
374
375                 return false;
376         }
377
378         return true;
379 }
380
381 /*
382  =======================================================================================================================
383  =======================================================================================================================
384  */
385 void QE_Init(void) {
386         /* initialize variables */
387         g_qeglobals.d_gridsize = 8;
388         g_qeglobals.d_showgrid = true;
389
390         /*
391          * other stuff £
392          * FIXME: idMaterial Texture_Init (true); Cam_Init (); XY_Init ();
393          */
394         Z_Init();
395 }
396
397
398 int g_numbrushes, g_numentities;
399
400 /*
401  =======================================================================================================================
402  =======================================================================================================================
403  */
404 void QE_CountBrushesAndUpdateStatusBar(void) {
405         static int      s_lastbrushcount, s_lastentitycount;
406         static bool s_didonce;
407
408         // entity_t *e;
409         brush_t         *b, *next;
410
411         g_numbrushes = 0;
412         g_numentities = 0;
413
414         if (active_brushes.next != NULL) {
415                 for (b = active_brushes.next; b != NULL && b != &active_brushes; b = next) {
416                         next = b->next;
417                         if (b->brush_faces) {
418                                 if (!b->owner->eclass->fixedsize) {
419                                         g_numbrushes++;
420                                 }
421                                 else {
422                                         g_numentities++;
423                                 }
424                         }
425                 }
426         }
427
428         /*
429          * if ( entities.next != NULL ) { for ( e = entities.next ; e != &entities &&
430          * g_numentities != MAX_MAP_ENTITIES ; e = e->next) { g_numentities++; } }
431          */
432         if (((g_numbrushes != s_lastbrushcount) || (g_numentities != s_lastentitycount)) || (!s_didonce)) {
433                 Sys_UpdateStatusBar();
434
435                 s_lastbrushcount = g_numbrushes;
436                 s_lastentitycount = g_numentities;
437                 s_didonce = true;
438         }
439 }
440