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