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 */
XY_Init(void)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
XY_ToPoint(int x,int y,vec3_t point)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
XY_ToGridPoint(int x,int y,vec3_t point)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 */
XY_MouseDown(int x,int y,int buttons)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 */
XY_MouseUp(int x,int y,int buttons)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
DragDelta(int x,int y,vec3_t move)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 */
NewBrushDrag(int x,int y)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 */
XY_MouseMoved(int x,int y,int buttons)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 */
XY_DrawGrid(void)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 */
XY_DrawBlockGrid(void)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
DrawCameraIcon(void)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
DrawZIcon(void)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 */
FilterBrush(brush_t * pb)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 */
DrawPathLines(void)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 */
XY_Draw(void)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 */
XY_Overlay(void)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
974