]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/qe4/xy.c
Merge branch 'NateEag-master-patch-12920' into 'master'
[xonotic/netradiant.git] / tools / quake2 / extra / qe4 / xy.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 #define PAGEFLIPS       2
26
27 /*
28 ============
29 XY_Init
30 ============
31 */
32 void XY_Init (void)
33 {
34         g_qeglobals.d_xy.origin[0] = 0;
35         g_qeglobals.d_xy.origin[1] = 20;
36         g_qeglobals.d_xy.origin[2] = 46;
37
38         g_qeglobals.d_xy.scale = 1;
39 }
40
41
42 /*
43 ============================================================================
44
45   MOUSE ACTIONS
46
47 ============================================================================
48 */
49
50 static  int     cursorx, cursory;
51 static  int     buttonstate;
52 static  int     pressx, pressy;
53 static  vec3_t  pressdelta;
54 static  qboolean        press_selection;
55
56 void XY_ToPoint (int x, int y, vec3_t point)
57 {
58         point[0] = g_qeglobals.d_xy.origin[0] + (x - g_qeglobals.d_xy.width/2)/g_qeglobals.d_xy.scale;
59         point[1] = g_qeglobals.d_xy.origin[1] + (y - g_qeglobals.d_xy.height/2)/g_qeglobals.d_xy.scale;
60         point[2] = 0;
61 }
62
63 void XY_ToGridPoint (int x, int y, vec3_t point)
64 {
65         point[0] = g_qeglobals.d_xy.origin[0] + (x - g_qeglobals.d_xy.width/2)/g_qeglobals.d_xy.scale;
66         point[1] = g_qeglobals.d_xy.origin[1] + (y - g_qeglobals.d_xy.height/2)/g_qeglobals.d_xy.scale;
67         point[2] = 0;
68         point[0] = floor(point[0]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
69         point[1] = floor(point[1]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
70 }
71
72 /*
73 ==============
74 XY_MouseDown
75 ==============
76 */
77 void XY_MouseDown (int x, int y, int buttons)
78 {
79         vec3_t  point;
80         vec3_t  origin, dir, right, up;
81
82         buttonstate = buttons;
83         pressx = x;
84         pressy = y;
85         VectorCopy (vec3_origin, pressdelta);
86
87         XY_ToPoint (x, y, point);
88
89         VectorCopy (point, origin);
90         origin[2] = 8192;
91
92         dir[0] = 0; dir[1] = 0; dir[2] = -1;
93         right[0] = 1/g_qeglobals.d_xy.scale; right[1] = 0; right[2] = 0;
94         up[0] = 0; up[1] = 1/g_qeglobals.d_xy.scale; up[2] = 0;
95
96         press_selection = (selected_brushes.next != &selected_brushes);
97
98         Sys_GetCursorPos (&cursorx, &cursory);
99
100         // lbutton = manipulate selection
101         // shift-LBUTTON = select
102         if ( (buttons == MK_LBUTTON)
103                 || (buttons == (MK_LBUTTON | MK_SHIFT))
104                 || (buttons == (MK_LBUTTON | MK_CONTROL))
105                 || (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) )
106         {
107                 Drag_Begin (x, y, buttons,
108                         right, up,
109                         origin, dir);
110                 return;
111         }
112
113         // control mbutton = move camera
114         if (buttonstate == (MK_CONTROL|MK_MBUTTON) )
115         {
116                 camera.origin[0] = point[0];
117                 camera.origin[1] = point[1];
118                 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
119         }
120
121         // mbutton = angle camera
122         if (buttonstate == MK_MBUTTON)
123         {
124                 VectorSubtract (point, camera.origin, point);
125                 if (point[1] || point[0])
126                 {
127                         camera.angles[YAW] = 180/Q_PI*atan2 (point[1], point[0]);
128                         Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
129                 }
130         }
131
132         // shift mbutton = move z checker
133         if (buttonstate == (MK_SHIFT|MK_MBUTTON) )
134         {
135                 XY_ToPoint (x, y, point);
136                 z.origin[0] = point[0];
137                 z.origin[1] = point[1];
138                 Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
139                 return;
140         }
141
142 }
143
144 /*
145 ==============
146 XY_MouseUp
147 ==============
148 */
149 void XY_MouseUp (int x, int y, int buttons)
150 {
151         Drag_MouseUp ();
152
153         if (!press_selection)
154                 Sys_UpdateWindows (W_ALL);
155
156         buttonstate = 0;
157 }
158
159 qboolean DragDelta (int x, int y, vec3_t move)
160 {
161         vec3_t  xvec, yvec, delta;
162         int             i;
163
164         xvec[0] = 1/g_qeglobals.d_xy.scale;
165         xvec[1] = xvec[2] = 0;
166         yvec[1] = 1/g_qeglobals.d_xy.scale;
167         yvec[0] = yvec[2] = 0;
168
169         for (i=0 ; i<3 ; i++)
170         {
171                 delta[i] = xvec[i]*(x - pressx) + yvec[i]*(y - pressy);
172                 delta[i] = floor(delta[i]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
173         }
174         VectorSubtract (delta, pressdelta, move);
175         VectorCopy (delta, pressdelta);
176
177         if (move[0] || move[1] || move[2])
178                 return true;
179         return false;
180 }
181
182 /*
183 ==============
184 NewBrushDrag
185 ==============
186 */
187 void NewBrushDrag (int x, int y)
188 {
189         vec3_t  mins, maxs, junk;
190         int             i;
191         float   temp;
192         brush_t *n;
193
194         if (!DragDelta (x,y, junk))
195                 return;
196         // delete the current selection
197         if (selected_brushes.next != &selected_brushes)
198                 Brush_Free (selected_brushes.next);
199         XY_ToGridPoint (pressx, pressy, mins);
200         mins[2] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z/g_qeglobals.d_gridsize));
201         XY_ToGridPoint (x, y, maxs);
202         maxs[2] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z/g_qeglobals.d_gridsize));
203         if (maxs[2] <= mins[2])
204                 maxs[2] = mins[2] + g_qeglobals.d_gridsize;
205
206         for (i=0 ; i<3 ; i++)
207         {
208                 if (mins[i] == maxs[i])
209                         return; // don't create a degenerate brush
210                 if (mins[i] > maxs[i])
211                 {
212                         temp = mins[i];
213                         mins[i] = maxs[i];
214                         maxs[i] = temp;
215                 }
216         }
217
218         n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
219         if (!n)
220                 return;
221
222         Brush_AddToList (n, &selected_brushes);
223
224         Entity_LinkBrush (world_entity, n);
225
226         Brush_Build( n );
227
228 //      Sys_UpdateWindows (W_ALL);
229         Sys_UpdateWindows (W_XY| W_CAMERA);
230 }
231
232 /*
233 ==============
234 XY_MouseMoved
235 ==============
236 */
237 void XY_MouseMoved (int x, int y, int buttons)
238 {
239         vec3_t  point;
240
241         if (!buttonstate)
242                 return;
243
244         // lbutton without selection = drag new brush
245         if (buttonstate == MK_LBUTTON && !press_selection)
246         {
247                 NewBrushDrag (x, y);
248                 return;
249         }
250
251         // lbutton (possibly with control and or shift)
252         // with selection = drag selection
253         if (buttonstate & MK_LBUTTON)
254         {
255                 Drag_MouseMoved (x, y, buttons);
256                 Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA);
257                 return;
258         }
259
260         // control mbutton = move camera
261         if (buttonstate == (MK_CONTROL|MK_MBUTTON) )
262         {
263                 XY_ToPoint (x, y, point);
264                 camera.origin[0] = point[0];
265                 camera.origin[1] = point[1];
266                 Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA);
267                 return;
268         }
269
270         // shift mbutton = move z checker
271         if (buttonstate == (MK_SHIFT|MK_MBUTTON) )
272         {
273                 XY_ToPoint (x, y, point);
274                 z.origin[0] = point[0];
275                 z.origin[1] = point[1];
276                 Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
277                 return;
278         }
279
280         // mbutton = angle camera
281         if (buttonstate == MK_MBUTTON )
282         {
283                 XY_ToPoint (x, y, point);
284                 VectorSubtract (point, camera.origin, point);
285                 if (point[1] || point[0])
286                 {
287                         camera.angles[YAW] = 180/Q_PI*atan2 (point[1], point[0]);
288                         Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA);
289                 }
290                 return;
291         }
292
293         // rbutton = drag xy origin
294         if (buttonstate == MK_RBUTTON)
295         {
296                 Sys_GetCursorPos (&x, &y);
297                 if (x != cursorx || y != cursory)
298                 {
299                         g_qeglobals.d_xy.origin[0] -= (x-cursorx)/g_qeglobals.d_xy.scale;
300                         g_qeglobals.d_xy.origin[1] += (y-cursory)/g_qeglobals.d_xy.scale;
301                         Sys_SetCursorPos (cursorx, cursory);
302                         Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
303                 }
304                 return;
305         }
306 }
307
308
309 /*
310 ============================================================================
311
312 DRAWING
313
314 ============================================================================
315 */
316
317
318 /*
319 ==============
320 XY_DrawGrid
321 ==============
322 */
323 void XY_DrawGrid (void)
324 {
325         float   x, y, xb, xe, yb, ye;
326         int             w, h;
327         char    text[32];
328
329         glDisable(GL_TEXTURE_2D);
330         glDisable(GL_TEXTURE_1D);
331         glDisable(GL_DEPTH_TEST);
332         glDisable(GL_BLEND);
333
334         w = g_qeglobals.d_xy.width/2 / g_qeglobals.d_xy.scale;
335         h = g_qeglobals.d_xy.height/2 / g_qeglobals.d_xy.scale;
336
337         xb = g_qeglobals.d_xy.origin[0] - w;
338         if (xb < region_mins[0])
339                 xb = region_mins[0];
340         xb = 64 * floor (xb/64);
341
342         xe = g_qeglobals.d_xy.origin[0] + w;
343         if (xe > region_maxs[0])
344                 xe = region_maxs[0];
345         xe = 64 * ceil (xe/64);
346
347         yb = g_qeglobals.d_xy.origin[1] - h;
348         if (yb < region_mins[1])
349                 yb = region_mins[1];
350         yb = 64 * floor (yb/64);
351
352         ye = g_qeglobals.d_xy.origin[1] + h;
353         if (ye > region_maxs[1])
354                 ye = region_maxs[1];
355         ye = 64 * ceil (ye/64);
356
357         // draw major blocks
358
359         glColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR]);
360
361         if ( g_qeglobals.d_showgrid )
362         {
363
364                 glBegin (GL_LINES);
365
366                 for (x=xb ; x<=xe ; x+=64)
367                 {
368                         glVertex2f (x, yb);
369                         glVertex2f (x, ye);
370                 }
371                 for (y=yb ; y<=ye ; y+=64)
372                 {
373                         glVertex2f (xb, y);
374                         glVertex2f (xe, y);
375                 }
376
377                 glEnd ();
378
379         }
380
381         // draw minor blocks
382         if ( g_qeglobals.d_showgrid && g_qeglobals.d_gridsize*g_qeglobals.d_xy.scale >= 4)
383         {
384                 glColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]);
385
386                 glBegin (GL_LINES);
387                 for (x=xb ; x<xe ; x += g_qeglobals.d_gridsize)
388                 {
389                         if ( ! ((int)x & 63) )
390                                 continue;
391                         glVertex2f (x, yb);
392                         glVertex2f (x, ye);
393                 }
394                 for (y=yb ; y<ye ; y+=g_qeglobals.d_gridsize)
395                 {
396                         if ( ! ((int)y & 63) )
397                                 continue;
398                         glVertex2f (xb, y);
399                         glVertex2f (xe, y);
400                 }
401                 glEnd ();
402         }
403
404         // draw coordinate text if needed
405
406         if ( g_qeglobals.d_savedinfo.show_coordinates)
407         {
408                 glColor4f(0, 0, 0, 0);
409
410                 for (x=xb ; x<xe ; x+=64)
411                 {
412                         glRasterPos2f (x, g_qeglobals.d_xy.origin[1] + h - 6/g_qeglobals.d_xy.scale);
413                         sprintf (text, "%i",(int)x);
414                         glCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
415                 }
416                 for (y=yb ; y<ye ; y+=64)
417                 {
418                         glRasterPos2f (g_qeglobals.d_xy.origin[0] - w + 1, y);
419                         sprintf (text, "%i",(int)y);
420                         glCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
421                 }
422         }
423 }
424
425 /*
426 ==============
427 XY_DrawBlockGrid
428 ==============
429 */
430 void XY_DrawBlockGrid (void)
431 {
432         float   x, y, xb, xe, yb, ye;
433         int             w, h;
434         char    text[32];
435
436         glDisable(GL_TEXTURE_2D);
437         glDisable(GL_TEXTURE_1D);
438         glDisable(GL_DEPTH_TEST);
439         glDisable(GL_BLEND);
440
441         w = g_qeglobals.d_xy.width/2 / g_qeglobals.d_xy.scale;
442         h = g_qeglobals.d_xy.height/2 / g_qeglobals.d_xy.scale;
443
444         xb = g_qeglobals.d_xy.origin[0] - w;
445         if (xb < region_mins[0])
446                 xb = region_mins[0];
447         xb = 1024 * floor (xb/1024);
448
449         xe = g_qeglobals.d_xy.origin[0] + w;
450         if (xe > region_maxs[0])
451                 xe = region_maxs[0];
452         xe = 1024 * ceil (xe/1024);
453
454         yb = g_qeglobals.d_xy.origin[1] - h;
455         if (yb < region_mins[1])
456                 yb = region_mins[1];
457         yb = 1024 * floor (yb/1024);
458
459         ye = g_qeglobals.d_xy.origin[1] + h;
460         if (ye > region_maxs[1])
461                 ye = region_maxs[1];
462         ye = 1024 * ceil (ye/1024);
463
464         // draw major blocks
465
466         glColor3f(0,0,1);
467         glLineWidth (2);
468
469         glBegin (GL_LINES);
470
471         for (x=xb ; x<=xe ; x+=1024)
472         {
473                 glVertex2f (x, yb);
474                 glVertex2f (x, ye);
475         }
476         for (y=yb ; y<=ye ; y+=1024)
477         {
478                 glVertex2f (xb, y);
479                 glVertex2f (xe, y);
480         }
481
482         glEnd ();
483         glLineWidth (1);
484
485         // draw coordinate text if needed
486
487         for (x=xb ; x<xe ; x+=1024)
488                 for (y=yb ; y<ye ; y+=1024)
489                 {
490                         glRasterPos2f (x+512, y+512);
491                         sprintf (text, "%i,%i",(int)floor(x/1024), (int)floor(y/1024) );
492                         glCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
493                 }
494
495         glColor4f(0, 0, 0, 0);
496 }
497
498
499 void DrawCameraIcon (void)
500 {
501         float   x, y, a;
502
503         x = camera.origin[0];
504         y = camera.origin[1];
505         a = camera.angles[YAW]/180*Q_PI;
506
507         glColor3f (0.0, 0.0, 1.0);
508         glBegin(GL_LINE_STRIP);
509         glVertex3f (x-16,y,0);
510         glVertex3f (x,y+8,0);
511         glVertex3f (x+16,y,0);
512         glVertex3f (x,y-8,0);
513         glVertex3f (x-16,y,0);
514         glVertex3f (x+16,y,0);
515         glEnd ();
516
517         glBegin(GL_LINE_STRIP);
518         glVertex3f (x+48*cos(a+Q_PI/4), y+48*sin(a+Q_PI/4), 0);
519         glVertex3f (x, y, 0);
520         glVertex3f (x+48*cos(a-Q_PI/4), y+48*sin(a-Q_PI/4), 0);
521         glEnd ();
522
523 }
524
525 void DrawZIcon (void)
526 {
527         float   x, y;
528
529         x = z.origin[0];
530         y = z.origin[1];
531
532         glEnable (GL_BLEND);
533         glDisable (GL_TEXTURE_2D);
534         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
535         glDisable (GL_CULL_FACE);
536         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
537         glColor4f (0.0, 0.0, 1.0, 0.25);
538         glBegin(GL_QUADS);
539         glVertex3f (x-8,y-8,0);
540         glVertex3f (x+8,y-8,0);
541         glVertex3f (x+8,y+8,0);
542         glVertex3f (x-8,y+8,0);
543         glEnd ();
544         glDisable (GL_BLEND);
545
546         glColor4f (0.0, 0.0, 1.0, 1);
547
548         glBegin(GL_LINE_LOOP);
549         glVertex3f (x-8,y-8,0);
550         glVertex3f (x+8,y-8,0);
551         glVertex3f (x+8,y+8,0);
552         glVertex3f (x-8,y+8,0);
553         glEnd ();
554
555         glBegin(GL_LINE_STRIP);
556         glVertex3f (x-4,y+4,0);
557         glVertex3f (x+4,y+4,0);
558         glVertex3f (x-4,y-4,0);
559         glVertex3f (x+4,y-4,0);
560         glEnd ();
561 }
562
563
564 /*
565 ==================
566 FilterBrush
567 ==================
568 */
569 BOOL FilterBrush(brush_t *pb)
570 {
571         if (!pb->owner)
572                 return FALSE;           // during construction
573
574         if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP)
575         {
576                 if (!strncmp(pb->brush_faces->texdef.name, "clip", 4))
577                         return TRUE;
578         }
579
580         if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER)
581         {
582                 if (pb->brush_faces->texdef.name[0] == '*')
583                         return TRUE;
584         }
585
586         if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_DETAIL)
587         {
588                 if (pb->brush_faces->texdef.contents & CONTENTS_DETAIL)
589                         return TRUE;
590         }
591
592         if (pb->owner == world_entity)
593         {
594                 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD)
595                         return TRUE;
596                 return FALSE;
597         }
598         else if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT)
599                 return TRUE;
600
601         if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS)
602         {
603                 if (!strncmp(pb->owner->eclass->name, "light", 5))
604                         return TRUE;
605         }
606
607         if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
608         {
609                 if (!strncmp(pb->owner->eclass->name, "path", 4))
610                         return TRUE;
611         }
612
613         return FALSE;
614 }
615
616 /*
617 =============================================================
618
619   PATH LINES
620
621 =============================================================
622 */
623
624 /*
625 ==================
626 DrawPathLines
627
628 Draws connections between entities.
629 Needs to consider all entities, not just ones on screen,
630 because the lines can be visible when neither end is.
631 Called for both camera view and xy view.
632 ==================
633 */
634 void DrawPathLines (void)
635 {
636         int             i, j, k;
637         vec3_t  mid, mid1;
638         entity_t *se, *te;
639         brush_t *sb, *tb;
640         char    *psz;
641         vec3_t  dir, s1, s2;
642         vec_t   len, f;
643         int             arrows;
644         int                     num_entities;
645         char            *ent_target[MAX_MAP_ENTITIES];
646         entity_t        *ent_entity[MAX_MAP_ENTITIES];
647
648
649         num_entities = 0;
650         for (te = entities.next ; te != &entities && num_entities != MAX_MAP_ENTITIES ; te = te->next)
651         {
652                 ent_target[num_entities] = ValueForKey (te, "target");
653                 if (ent_target[num_entities][0])
654                 {
655                         ent_entity[num_entities] = te;
656                         num_entities++;
657                 }
658         }
659
660         for (se = entities.next ; se != &entities ; se = se->next)
661         {
662                 psz = ValueForKey(se, "targetname");
663
664                 if (psz == NULL || psz[0] == '\0')
665                         continue;
666
667                 sb = se->brushes.onext;
668                 if (sb == &se->brushes)
669                         continue;
670
671                 for (k=0 ; k<num_entities ; k++)
672                 {
673                         if (strcmp (ent_target[k], psz))
674                                 continue;
675
676                         te = ent_entity[k];
677                         tb = te->brushes.onext;
678                         if (tb == &te->brushes)
679                                 continue;
680
681                         for (i=0 ; i<3 ; i++)
682                                 mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
683
684                         for (i=0 ; i<3 ; i++)
685                                 mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5;
686
687                         VectorSubtract (mid1, mid, dir);
688                         len = VectorNormalize (dir);
689                         s1[0] = -dir[1]*8 + dir[0]*8;
690                         s2[0] = dir[1]*8 + dir[0]*8;
691                         s1[1] = dir[0]*8 + dir[1]*8;
692                         s2[1] = -dir[0]*8 + dir[1]*8;
693
694                         glColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
695
696                         glBegin(GL_LINES);
697                         glVertex3fv(mid);
698                         glVertex3fv(mid1);
699
700                         arrows = (int)(len / 256) + 1;
701
702                         for (i=0 ; i<arrows ; i++)
703                         {
704                                 f = len * (i + 0.5) / arrows;
705
706                                 for (j=0 ; j<3 ; j++)
707                                         mid1[j] = mid[j] + f*dir[j];
708                                 glVertex3fv (mid1);
709                                 glVertex3f (mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]);
710                                 glVertex3fv (mid1);
711                                 glVertex3f (mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]);
712                         }
713
714                         glEnd();
715                 }
716         }
717
718         return;
719 }
720
721 //=============================================================
722
723
724 /*
725 ==============
726 XY_Draw
727 ==============
728 */
729 void XY_Draw (void)
730 {
731     brush_t     *brush;
732         float   w, h;
733         entity_t        *e;
734         double  start, end;
735         vec3_t  mins, maxs;
736         int             drawn, culled;
737         int             i;
738
739         if (!active_brushes.next)
740                 return; // not valid yet
741
742         if (g_qeglobals.d_xy.timing)
743                 start = Sys_DoubleTime ();
744
745         //
746         // clear
747         //
748         g_qeglobals.d_xy.d_dirty = false;
749
750         glViewport(0, 0, g_qeglobals.d_xy.width, g_qeglobals.d_xy.height);
751         glClearColor (
752                 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0],
753                 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1],
754                 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],
755                 0);
756
757     glClear(GL_COLOR_BUFFER_BIT);
758
759         //
760         // set up viewpoint
761         //
762         glMatrixMode(GL_PROJECTION);
763     glLoadIdentity ();
764
765         w = g_qeglobals.d_xy.width/2 / g_qeglobals.d_xy.scale;
766         h = g_qeglobals.d_xy.height/2 / g_qeglobals.d_xy.scale;
767         mins[0] = g_qeglobals.d_xy.origin[0] - w;
768         maxs[0] = g_qeglobals.d_xy.origin[0] + w;
769         mins[1] = g_qeglobals.d_xy.origin[1] - h;
770         maxs[1] = g_qeglobals.d_xy.origin[1] + h;
771
772         glOrtho (mins[0], maxs[0], mins[1], maxs[1], -8000, 8000);
773
774         //
775         // now draw the grid
776         //
777         XY_DrawGrid ();
778
779         //
780         // draw stuff
781         //
782     glShadeModel (GL_FLAT);
783         glDisable(GL_TEXTURE_2D);
784         glDisable(GL_TEXTURE_1D);
785         glDisable(GL_DEPTH_TEST);
786         glDisable(GL_BLEND);
787         glColor3f(0, 0, 0);
788 //              glEnable (GL_LINE_SMOOTH);
789
790         drawn = culled = 0;
791
792         e = NULL;
793         for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
794         {
795                 if (brush->mins[0] > maxs[0]
796                         || brush->mins[1] > maxs[1]
797                         || brush->maxs[0] < mins[0]
798                         || brush->maxs[1] < mins[1]     )
799                 {
800                         culled++;
801                         continue;               // off screen
802                 }
803
804                 if (FilterBrush (brush))
805                         continue;
806                 drawn++;
807                 if (brush->owner != e)
808                 {
809                         e = brush->owner;
810                         glColor3fv(e->eclass->color);
811                 }
812                 Brush_DrawXY( brush );
813         }
814
815         DrawPathLines ();
816
817         //
818         // draw pointfile
819         //
820         if ( g_qeglobals.d_pointfile_display_list)
821                 glCallList (g_qeglobals.d_pointfile_display_list);
822
823         //
824         // draw block grid
825         //
826         if ( g_qeglobals.show_blocks)
827                 XY_DrawBlockGrid ();
828
829         //
830         // now draw selected brushes
831         //
832         glTranslatef( g_qeglobals.d_select_translate[0], g_qeglobals.d_select_translate[1], g_qeglobals.d_select_translate[2]);
833
834         glColor3f(1.0, 0.0, 0.0);
835         glEnable (GL_LINE_STIPPLE);
836         glLineStipple (3, 0xaaaa);
837         glLineWidth (2);
838
839         for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next)
840         {
841                 drawn++;
842                 Brush_DrawXY( brush );
843         }
844
845         glDisable (GL_LINE_STIPPLE);
846         glLineWidth (1);
847
848         // edge / vertex flags
849
850         if (g_qeglobals.d_select_mode == sel_vertex)
851         {
852                 glPointSize (4);
853                 glColor3f (0,1,0);
854                 glBegin (GL_POINTS);
855                 for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
856                         glVertex3fv (g_qeglobals.d_points[i]);
857                 glEnd ();
858                 glPointSize (1);
859         }
860         else if (g_qeglobals.d_select_mode == sel_edge)
861         {
862                 float   *v1, *v2;
863
864                 glPointSize (4);
865                 glColor3f (0,0,1);
866                 glBegin (GL_POINTS);
867                 for (i=0 ; i<g_qeglobals.d_numedges ; i++)
868                 {
869                         v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
870                         v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
871                         glVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
872                 }
873                 glEnd ();
874                 glPointSize (1);
875         }
876         glTranslatef (-g_qeglobals.d_select_translate[0], -g_qeglobals.d_select_translate[1], -g_qeglobals.d_select_translate[2]);
877
878         //
879         // now draw camera point
880         //
881         DrawCameraIcon ();
882         DrawZIcon ();
883
884     glFinish();
885         QE_CheckOpenGLForErrors();
886
887         if (g_qeglobals.d_xy.timing)
888         {
889                 end = Sys_DoubleTime ();
890                 Sys_Printf ("xy: %i ms\n", (int)(1000*(end-start)));
891         }
892 }
893
894 /*
895 ==============
896 XY_Overlay
897 ==============
898 */
899 void XY_Overlay (void)
900 {
901         int     w, h;
902         int     r[4];
903         static  vec3_t  lastz;
904         static  vec3_t  lastcamera;
905
906
907         glViewport(0, 0, g_qeglobals.d_xy.width, g_qeglobals.d_xy.height);
908
909         //
910         // set up viewpoint
911         //
912         glMatrixMode(GL_PROJECTION);
913     glLoadIdentity ();
914
915         w = g_qeglobals.d_xy.width/2 / g_qeglobals.d_xy.scale;
916         h = g_qeglobals.d_xy.height/2 / g_qeglobals.d_xy.scale;
917         glOrtho (g_qeglobals.d_xy.origin[0] - w, g_qeglobals.d_xy.origin[0] + w
918                 , g_qeglobals.d_xy.origin[1] - h, g_qeglobals.d_xy.origin[1] + h, -8000, 8000);
919         //
920         // erase the old camera and z checker positions
921         // if the entire xy hasn't been redrawn
922         //
923         if (g_qeglobals.d_xy.d_dirty)
924         {
925                 glReadBuffer (GL_BACK);
926                 glDrawBuffer (GL_FRONT);
927
928                 glRasterPos2f (lastz[0]-9, lastz[1]-9);
929                 glGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
930                 glCopyPixels(r[0], r[1], 18,18, GL_COLOR);
931
932                 glRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
933                 glGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
934                 glCopyPixels(r[0], r[1], 100,100, GL_COLOR);
935         }
936         g_qeglobals.d_xy.d_dirty = true;
937
938         //
939         // save off underneath where we are about to draw
940         //
941         VectorCopy (z.origin, lastz);
942         VectorCopy (camera.origin, lastcamera);
943
944         glReadBuffer (GL_FRONT);
945         glDrawBuffer (GL_BACK);
946
947         glRasterPos2f (lastz[0]-9, lastz[1]-9);
948         glGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
949         glCopyPixels(r[0], r[1], 18,18, GL_COLOR);
950
951         glRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
952         glGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
953         glCopyPixels(r[0], r[1], 100,100, GL_COLOR);
954
955         //
956         // draw the new icons
957         //
958         glDrawBuffer (GL_FRONT);
959
960     glShadeModel (GL_FLAT);
961         glDisable(GL_TEXTURE_2D);
962         glDisable(GL_TEXTURE_1D);
963         glDisable(GL_DEPTH_TEST);
964         glDisable(GL_BLEND);
965         glColor3f(0, 0, 0);
966
967         DrawCameraIcon ();
968         DrawZIcon ();
969
970         glDrawBuffer (GL_BACK);
971     glFinish();
972 }
973