]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/qe4/qe3.c
Merge branch 'master' into divVerent/farplanedist-sky-fix
[xonotic/netradiant.git] / tools / quake2 / extra / qe4 / qe3.c
1 /*
2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
4
5 This file is part of Quake 2 Tools source code.
6
7 Quake 2 Tools source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake 2 Tools source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22
23 #include "qe3.h"
24
25 QEGlobals_t  g_qeglobals;
26
27 void QE_CheckOpenGLForErrors(void)
28 {
29     int     i;
30
31     while ( ( i = glGetError() ) != GL_NO_ERROR )
32     {
33                 char buffer[100];
34
35                 sprintf( buffer, "OpenGL Error: %s", gluErrorString( i ) );
36
37                 MessageBox( g_qeglobals.d_hwndMain, buffer , "QuakeEd Error", MB_OK | MB_ICONEXCLAMATION );
38                 exit( 1 );
39     }
40 }
41
42
43 char *ExpandReletivePath (char *p)
44 {
45         static char     temp[1024];
46         char    *base;
47
48         if (!p || !p[0])
49                 return NULL;
50         if (p[0] == '/' || p[0] == '\\')
51                 return p;
52
53         base = ValueForKey(g_qeglobals.d_project_entity, "basepath");
54         sprintf (temp, "%s/%s", base, p);
55         return temp;
56 }
57
58
59
60 void *qmalloc (int size)
61 {
62         void *b;
63         b = malloc(size);
64         memset (b, 0, size);
65         return b;
66 }
67
68 char *copystring (char *s)
69 {
70         char    *b;
71         b = malloc(strlen(s)+1);
72         strcpy (b,s);
73         return b;
74 }
75
76 /*
77 ===============
78 QE_CheckAutoSave
79
80 If five minutes have passed since making a change
81 and the map hasn't been saved, save it out.
82 ===============
83 */
84 void QE_CheckAutoSave( void )
85 {
86         static clock_t s_start;
87         clock_t        now;
88
89         now = clock();
90
91         if ( modified != 1 || !s_start)
92         {
93                 s_start = now;
94                 return;
95         }
96
97         if ( now - s_start > ( CLOCKS_PER_SEC * 60 * QE_AUTOSAVE_INTERVAL ) )
98         {
99                 Sys_Printf ("Autosaving...\n");
100                 Sys_Status ("Autosaving...", 0 );
101
102                 Map_SaveFile (ValueForKey(g_qeglobals.d_project_entity, "autosave"), false);
103
104                 Sys_Status ("Autosaving...Saved.", 0 );
105                 modified = 2;
106                 s_start = now;
107         }
108 }
109
110
111
112 /*
113 ===========
114 QE_LoadProject
115 ===========
116 */
117 qboolean QE_LoadProject (char *projectfile)
118 {
119         char    *data;
120
121         Sys_Printf ("QE_LoadProject (%s)\n", projectfile);
122
123         if ( LoadFileNoCrash (projectfile, (void *)&data) == -1)
124                 return false;
125         StartTokenParsing (data);
126         g_qeglobals.d_project_entity = Entity_Parse (true);
127         if (!g_qeglobals.d_project_entity)
128                 Error ("Couldn't parse %s", projectfile);
129         free (data);
130
131         Eclass_InitForSourceDirectory (ValueForKey (g_qeglobals.d_project_entity, "entitypath"));
132
133         FillClassList ();               // list in entity window
134
135         Map_New ();
136
137         FillTextureMenu ();
138         FillBSPMenu ();
139
140         return true;
141 }
142
143 /*
144 ===========
145 QE_KeyDown
146 ===========
147 */
148 #define SPEED_MOVE      32
149 #define SPEED_TURN      22.5
150
151 qboolean QE_KeyDown (int key)
152 {
153         switch (key)
154         {
155         case 'K':
156                 PostMessage( g_qeglobals.d_hwndMain, WM_COMMAND, ID_MISC_SELECTENTITYCOLOR, 0 );
157                 break;
158
159         case VK_UP:
160                 VectorMA (camera.origin, SPEED_MOVE, camera.forward, camera.origin);
161                 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
162                 break;
163         case VK_DOWN:
164                 VectorMA (camera.origin, -SPEED_MOVE, camera.forward, camera.origin);
165                 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
166                 break;
167         case VK_LEFT:
168                 camera.angles[1] += SPEED_TURN;
169                 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
170                 break;
171         case VK_RIGHT:
172                 camera.angles[1] -= SPEED_TURN;
173                 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
174                 break;
175         case 'D':
176                 camera.origin[2] += SPEED_MOVE;
177                 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY|W_Z_OVERLAY);
178                 break;
179         case 'C':
180                 camera.origin[2] -= SPEED_MOVE;
181                 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY|W_Z_OVERLAY);
182                 break;
183         case 'A':
184                 camera.angles[0] += SPEED_TURN;
185                 if (camera.angles[0] > 85)
186                         camera.angles[0] = 85;
187                 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
188                 break;
189         case 'Z':
190                 camera.angles[0] -= SPEED_TURN;
191                 if (camera.angles[0] < -85)
192                         camera.angles[0] = -85;
193                 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
194                 break;
195         case VK_COMMA:
196                 VectorMA (camera.origin, -SPEED_MOVE, camera.right, camera.origin);
197                 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
198                 break;
199         case VK_PERIOD:
200                 VectorMA (camera.origin, SPEED_MOVE, camera.right, camera.origin);
201                 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
202                 break;
203
204         case '0':
205                 g_qeglobals.d_showgrid = !g_qeglobals.d_showgrid;
206                 PostMessage( g_qeglobals.d_hwndXY, WM_PAINT, 0, 0 );
207                 break;
208         case '1':
209                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_1, 0);
210                 break;
211         case '2':
212                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_2, 0);
213                 break;
214         case '3':
215                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_4, 0);
216                 break;
217         case '4':
218                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_8, 0);
219                 break;
220         case '5':
221                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_16, 0);
222                 break;
223         case '6':
224                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_32, 0);
225                 break;
226         case '7':
227                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_GRID_64, 0);
228                 break;
229
230         case 'E':
231                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_SELECTION_DRAGEDGES, 0);
232                 break;
233         case 'V':
234                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_SELECTION_DRAGVERTECIES, 0);
235                 break;
236
237         case 'N':
238                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_ENTITY, 0);
239                 break;
240         case 'O':
241                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_CONSOLE, 0);
242                 break;
243         case 'T':
244                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_TEXTURE, 0);
245                 break;
246         case 'S':
247                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_TEXTURES_INSPECTOR, 0);
248                 break;
249
250         case ' ':
251                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_SELECTION_CLONE, 0);
252                 break;
253
254         case VK_BACK:
255                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_SELECTION_DELETE, 0);
256                 break;
257         case VK_ESCAPE:
258                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_SELECTION_DESELECT, 0);
259                 break;
260         case VK_END:
261                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_CENTER, 0);
262                 break;
263
264         case VK_DELETE:
265                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_ZOOMIN, 0);
266                 break;
267         case VK_INSERT:
268                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_ZOOMOUT, 0);
269                 break;
270
271         case VK_NEXT:
272                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_DOWNFLOOR, 0);
273                 break;
274         case VK_PRIOR:
275                 PostMessage (g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_UPFLOOR, 0);
276                 break;
277
278         default:
279                 return false;
280
281         }
282
283         return true;
284 }
285
286 /*
287 ===============
288 ConnectEntities
289
290 Sets target / targetname on the two entities selected
291 from the first selected to the secon
292 ===============
293 */
294 void ConnectEntities (void)
295 {
296         entity_t        *e1, *e2, *e;
297         char            *target, *tn;
298         int                     maxtarg, targetnum;
299         char            newtarg[32];
300
301         if (g_qeglobals.d_select_count != 2)
302         {
303                 Sys_Status ("Must have two brushes selected.", 0);
304                 Sys_Beep ();
305                 return;
306         }
307
308         e1 = g_qeglobals.d_select_order[0]->owner;
309         e2 = g_qeglobals.d_select_order[1]->owner;
310
311         if (e1 == world_entity || e2 == world_entity)
312         {
313                 Sys_Status ("Can't connect to the world.", 0);
314                 Sys_Beep ();
315                 return;
316         }
317
318         if (e1 == e2)
319         {
320                 Sys_Status ("Brushes are from same entity.", 0);
321                 Sys_Beep ();
322                 return;
323         }
324
325         target = ValueForKey (e1, "target");
326         if (target && target[0])
327                 strcpy (newtarg, target);
328         else
329         {
330                 target = ValueForKey (e2, "targetname");
331                 if (target && target[0])
332                         strcpy (newtarg, target);
333                 else
334                 {
335                         // make a unique target value
336                         maxtarg = 0;
337                         for (e=entities.next ; e != &entities ; e=e->next)
338                         {
339                                 tn = ValueForKey (e, "targetname");
340                                 if (tn && tn[0])
341                                 {
342                                         targetnum = atoi(tn+1);
343                                         if (targetnum > maxtarg)
344                                                 maxtarg = targetnum;
345                                 }
346                         }
347                         sprintf (newtarg, "t%i", maxtarg+1);
348                 }
349         }
350
351         SetKeyValue (e1, "target", newtarg);
352         SetKeyValue (e2, "targetname", newtarg);
353         Sys_UpdateWindows (W_XY | W_CAMERA);
354
355         Select_Deselect();
356         Select_Brush (g_qeglobals.d_select_order[1]);
357 }
358
359 qboolean QE_SingleBrush (void)
360 {
361         if ( (selected_brushes.next == &selected_brushes)
362                 || (selected_brushes.next->next != &selected_brushes) )
363         {
364                 Sys_Printf ("Error: you must have a single brush selected\n");
365                 return false;
366         }
367         if (selected_brushes.next->owner->eclass->fixedsize)
368         {
369                 Sys_Printf ("Error: you cannot manipulate fixed size entities\n");
370                 return false;
371         }
372
373         return true;
374 }
375
376 void QE_Init (void)
377 {
378         /*
379         ** initialize variables
380         */
381         g_qeglobals.d_gridsize = 8;
382         g_qeglobals.d_showgrid = true;
383
384         /*
385         ** other stuff
386         */
387         Texture_Init ();
388         Cam_Init ();
389         XY_Init ();
390         Z_Init ();
391 }
392
393 void QE_ConvertDOSToUnixName( char *dst, const char *src )
394 {
395         while ( *src )
396         {
397                 if ( *src == '\\' )
398                         *dst = '/';
399                 else
400                         *dst = *src;
401                 dst++; src++;
402         }
403         *dst = 0;
404 }
405
406 int g_numbrushes, g_numentities;
407
408 void QE_CountBrushesAndUpdateStatusBar( void )
409 {
410         static int      s_lastbrushcount, s_lastentitycount;
411         static qboolean s_didonce;
412
413         entity_t   *e;
414         brush_t    *b, *next;
415
416         g_numbrushes = 0;
417         g_numentities = 0;
418
419         if ( active_brushes.next != NULL )
420         {
421                 for ( b = active_brushes.next ; b != NULL && b != &active_brushes ; b=next)
422                 {
423                         next = b->next;
424                         if (b->brush_faces )
425                         {
426                                 if ( !b->owner->eclass->fixedsize)
427                                         g_numbrushes++;
428                                 else
429                                         g_numentities++;
430                         }
431                 }
432         }
433
434         if ( entities.next != NULL )
435         {
436                 for ( e = entities.next ; e != &entities && g_numentities != MAX_MAP_ENTITIES ; e = e->next)
437                 {
438                         g_numentities++;
439                 }
440         }
441
442         if ( ( ( g_numbrushes != s_lastbrushcount ) || ( g_numentities != s_lastentitycount ) ) || ( !s_didonce ) )
443         {
444                 Sys_UpdateStatusBar();
445
446                 s_lastbrushcount = g_numbrushes;
447                 s_lastentitycount = g_numentities;
448                 s_didonce = true;
449         }
450 }
451