
#include "qe3.h"

#define	PAGEFLIPS	2

/*
============
XY_Init
============
*/
void XY_Init (void)
{
	g_qeglobals.d_xy.origin[0] = 0;
	g_qeglobals.d_xy.origin[1] = 20;
	g_qeglobals.d_xy.origin[2] = 46;

	g_qeglobals.d_xy.scale = 1;
}


/*
============================================================================

  MOUSE ACTIONS

============================================================================
*/

static	int	cursorx, cursory;
static	int	buttonstate;
static	int	pressx, pressy;
static	vec3_t	pressdelta;
static	qboolean	press_selection;

void XY_ToPoint (int x, int y, vec3_t point)
{
	point[0] = g_qeglobals.d_xy.origin[0] + (x - g_qeglobals.d_xy.width/2)/g_qeglobals.d_xy.scale;
	point[1] = g_qeglobals.d_xy.origin[1] + (y - g_qeglobals.d_xy.height/2)/g_qeglobals.d_xy.scale;
	point[2] = 0;
}

void XY_ToGridPoint (int x, int y, vec3_t point)
{
	point[0] = g_qeglobals.d_xy.origin[0] + (x - g_qeglobals.d_xy.width/2)/g_qeglobals.d_xy.scale;
	point[1] = g_qeglobals.d_xy.origin[1] + (y - g_qeglobals.d_xy.height/2)/g_qeglobals.d_xy.scale;
	point[2] = 0;
	point[0] = floor(point[0]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
	point[1] = floor(point[1]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
}

/*
==============
XY_MouseDown
==============
*/
void XY_MouseDown (int x, int y, int buttons)
{
	vec3_t	point;
	vec3_t	origin, dir, right, up;

	buttonstate = buttons;
	pressx = x;
	pressy = y;
	VectorCopy (vec3_origin, pressdelta);

	XY_ToPoint (x, y, point);

	VectorCopy (point, origin);
	origin[2] = 8192;

	dir[0] = 0; dir[1] = 0; dir[2] = -1;
	right[0] = 1/g_qeglobals.d_xy.scale; right[1] = 0; right[2] = 0;
	up[0] = 0; up[1] = 1/g_qeglobals.d_xy.scale; up[2] = 0;

	press_selection = (selected_brushes.next != &selected_brushes);

	Sys_GetCursorPos (&cursorx, &cursory);

	// lbutton = manipulate selection
	// shift-LBUTTON = select
	if ( (buttons == MK_LBUTTON)
		|| (buttons == (MK_LBUTTON | MK_SHIFT))
		|| (buttons == (MK_LBUTTON | MK_CONTROL))
		|| (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) )
	{	
		Drag_Begin (x, y, buttons, 
			right, up,
			origin, dir);
		return;
	}

	// control mbutton = move camera
	if (buttonstate == (MK_CONTROL|MK_MBUTTON) )
	{	
		camera.origin[0] = point[0];
		camera.origin[1] = point[1];
		Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
	}

	// mbutton = angle camera
	if (buttonstate == MK_MBUTTON)
	{	
		VectorSubtract (point, camera.origin, point);
		if (point[1] || point[0])
		{
			camera.angles[YAW] = 180/Q_PI*atan2 (point[1], point[0]);
			Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
		}
	}

	// shift mbutton = move z checker
	if (buttonstate == (MK_SHIFT|MK_MBUTTON) )
	{
		XY_ToPoint (x, y, point);
		z.origin[0] = point[0];
		z.origin[1] = point[1];
		Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
		return;
	}

}

/*
==============
XY_MouseUp
==============
*/
void XY_MouseUp (int x, int y, int buttons)
{
	Drag_MouseUp ();

	if (!press_selection)
		Sys_UpdateWindows (W_ALL);

	buttonstate = 0;
}

qboolean DragDelta (int x, int y, vec3_t move)
{
	vec3_t	xvec, yvec, delta;
	int		i;

	xvec[0] = 1/g_qeglobals.d_xy.scale;
	xvec[1] = xvec[2] = 0;
	yvec[1] = 1/g_qeglobals.d_xy.scale;
	yvec[0] = yvec[2] = 0;

	for (i=0 ; i<3 ; i++)
	{
		delta[i] = xvec[i]*(x - pressx) + yvec[i]*(y - pressy);
		delta[i] = floor(delta[i]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
	}
	VectorSubtract (delta, pressdelta, move);
	VectorCopy (delta, pressdelta);

	if (move[0] || move[1] || move[2])
		return true;
	return false;
}

/*
==============
NewBrushDrag
==============
*/
void NewBrushDrag (int x, int y)
{
	vec3_t	mins, maxs, junk;
	int		i;
	float	temp;
	brush_t	*n;

	if (!DragDelta (x,y, junk))
		return;
	// delete the current selection
	if (selected_brushes.next != &selected_brushes)
		Brush_Free (selected_brushes.next);
	XY_ToGridPoint (pressx, pressy, mins);
	mins[2] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z/g_qeglobals.d_gridsize));
	XY_ToGridPoint (x, y, maxs);
	maxs[2] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z/g_qeglobals.d_gridsize));
	if (maxs[2] <= mins[2])
		maxs[2] = mins[2] + g_qeglobals.d_gridsize;

	for (i=0 ; i<3 ; i++)
	{
		if (mins[i] == maxs[i])
			return;	// don't create a degenerate brush
		if (mins[i] > maxs[i])
		{
			temp = mins[i];
			mins[i] = maxs[i];
			maxs[i] = temp;
		}
	}

	n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
	if (!n)
		return;

	Brush_AddToList (n, &selected_brushes);

	Entity_LinkBrush (world_entity, n);

	Brush_Build( n );

//	Sys_UpdateWindows (W_ALL);
	Sys_UpdateWindows (W_XY| W_CAMERA);
}

/*
==============
XY_MouseMoved
==============
*/
void XY_MouseMoved (int x, int y, int buttons)
{
	vec3_t	point;

	if (!buttonstate)
		return;

	// lbutton without selection = drag new brush
	if (buttonstate == MK_LBUTTON && !press_selection)
	{
		NewBrushDrag (x, y);
		return;
	}

	// lbutton (possibly with control and or shift)
	// with selection = drag selection
	if (buttonstate & MK_LBUTTON)
	{
		Drag_MouseMoved (x, y, buttons);
		Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA);
		return;
	}

	// control mbutton = move camera
	if (buttonstate == (MK_CONTROL|MK_MBUTTON) )
	{
		XY_ToPoint (x, y, point);
		camera.origin[0] = point[0];
		camera.origin[1] = point[1];
		Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA);
		return;
	}

	// shift mbutton = move z checker
	if (buttonstate == (MK_SHIFT|MK_MBUTTON) )
	{
		XY_ToPoint (x, y, point);
		z.origin[0] = point[0];
		z.origin[1] = point[1];
		Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
		return;
	}

	// mbutton = angle camera
	if (buttonstate == MK_MBUTTON )
	{	
		XY_ToPoint (x, y, point);
		VectorSubtract (point, camera.origin, point);
		if (point[1] || point[0])
		{
			camera.angles[YAW] = 180/Q_PI*atan2 (point[1], point[0]);
			Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA);
		}
		return;
	}

	// rbutton = drag xy origin
	if (buttonstate == MK_RBUTTON)
	{
		Sys_GetCursorPos (&x, &y);
		if (x != cursorx || y != cursory)
		{
			g_qeglobals.d_xy.origin[0] -= (x-cursorx)/g_qeglobals.d_xy.scale;
			g_qeglobals.d_xy.origin[1] += (y-cursory)/g_qeglobals.d_xy.scale;
			Sys_SetCursorPos (cursorx, cursory);
			Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
		}
		return;
	}
}


/*
============================================================================

DRAWING

============================================================================
*/


/*
==============
XY_DrawGrid
==============
*/
void XY_DrawGrid (void)
{
	float	x, y, xb, xe, yb, ye;
	int		w, h;
	char	text[32];

	glDisable(GL_TEXTURE_2D);
	glDisable(GL_TEXTURE_1D);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_BLEND);

	w = g_qeglobals.d_xy.width/2 / g_qeglobals.d_xy.scale;
	h = g_qeglobals.d_xy.height/2 / g_qeglobals.d_xy.scale;

	xb = g_qeglobals.d_xy.origin[0] - w;
	if (xb < region_mins[0])
		xb = region_mins[0];
	xb = 64 * floor (xb/64);

	xe = g_qeglobals.d_xy.origin[0] + w;
	if (xe > region_maxs[0])
		xe = region_maxs[0];
	xe = 64 * ceil (xe/64);

	yb = g_qeglobals.d_xy.origin[1] - h;
	if (yb < region_mins[1])
		yb = region_mins[1];
	yb = 64 * floor (yb/64);

	ye = g_qeglobals.d_xy.origin[1] + h;
	if (ye > region_maxs[1])
		ye = region_maxs[1];
	ye = 64 * ceil (ye/64);

	// draw major blocks

	glColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR]);

	if ( g_qeglobals.d_showgrid )
	{
		
		glBegin (GL_LINES);
		
		for (x=xb ; x<=xe ; x+=64)
		{
			glVertex2f (x, yb);
			glVertex2f (x, ye);
		}
		for (y=yb ; y<=ye ; y+=64)
		{
			glVertex2f (xb, y);
			glVertex2f (xe, y);
		}
		
		glEnd ();
		
	}

	// draw minor blocks
	if ( g_qeglobals.d_showgrid && g_qeglobals.d_gridsize*g_qeglobals.d_xy.scale >= 4)
	{
		glColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]);

		glBegin (GL_LINES);
		for (x=xb ; x<xe ; x += g_qeglobals.d_gridsize)
		{
			if ( ! ((int)x & 63) )
				continue;
			glVertex2f (x, yb);
			glVertex2f (x, ye);
		}
		for (y=yb ; y<ye ; y+=g_qeglobals.d_gridsize)
		{
			if ( ! ((int)y & 63) )
				continue;
			glVertex2f (xb, y);
			glVertex2f (xe, y);
		}
		glEnd ();
	}

	// draw coordinate text if needed

	if ( g_qeglobals.d_savedinfo.show_coordinates)
	{
		glColor4f(0, 0, 0, 0);

		for (x=xb ; x<xe ; x+=64)
		{
			glRasterPos2f (x, g_qeglobals.d_xy.origin[1] + h - 6/g_qeglobals.d_xy.scale);
			sprintf (text, "%i",(int)x);
			glCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
		}
		for (y=yb ; y<ye ; y+=64)
		{
			glRasterPos2f (g_qeglobals.d_xy.origin[0] - w + 1, y);
			sprintf (text, "%i",(int)y);
			glCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
		}
	}
}

/*
==============
XY_DrawBlockGrid
==============
*/
void XY_DrawBlockGrid (void)
{
	float	x, y, xb, xe, yb, ye;
	int		w, h;
	char	text[32];

	glDisable(GL_TEXTURE_2D);
	glDisable(GL_TEXTURE_1D);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_BLEND);

	w = g_qeglobals.d_xy.width/2 / g_qeglobals.d_xy.scale;
	h = g_qeglobals.d_xy.height/2 / g_qeglobals.d_xy.scale;

	xb = g_qeglobals.d_xy.origin[0] - w;
	if (xb < region_mins[0])
		xb = region_mins[0];
	xb = 1024 * floor (xb/1024);

	xe = g_qeglobals.d_xy.origin[0] + w;
	if (xe > region_maxs[0])
		xe = region_maxs[0];
	xe = 1024 * ceil (xe/1024);

	yb = g_qeglobals.d_xy.origin[1] - h;
	if (yb < region_mins[1])
		yb = region_mins[1];
	yb = 1024 * floor (yb/1024);

	ye = g_qeglobals.d_xy.origin[1] + h;
	if (ye > region_maxs[1])
		ye = region_maxs[1];
	ye = 1024 * ceil (ye/1024);

	// draw major blocks

	glColor3f(0,0,1);
	glLineWidth (2);

	glBegin (GL_LINES);
	
	for (x=xb ; x<=xe ; x+=1024)
	{
		glVertex2f (x, yb);
		glVertex2f (x, ye);
	}
	for (y=yb ; y<=ye ; y+=1024)
	{
		glVertex2f (xb, y);
		glVertex2f (xe, y);
	}
	
	glEnd ();
	glLineWidth (1);

	// draw coordinate text if needed

	for (x=xb ; x<xe ; x+=1024)
		for (y=yb ; y<ye ; y+=1024)
		{
			glRasterPos2f (x+512, y+512);
			sprintf (text, "%i,%i",(int)floor(x/1024), (int)floor(y/1024) );
			glCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
		}

	glColor4f(0, 0, 0, 0);
}


void DrawCameraIcon (void)
{
	float	x, y, a;

	x = camera.origin[0];
	y = camera.origin[1];
	a = camera.angles[YAW]/180*Q_PI;

	glColor3f (0.0, 0.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex3f (x-16,y,0);
	glVertex3f (x,y+8,0);
	glVertex3f (x+16,y,0);
	glVertex3f (x,y-8,0);
	glVertex3f (x-16,y,0);
	glVertex3f (x+16,y,0);
	glEnd ();
	
	glBegin(GL_LINE_STRIP);
	glVertex3f (x+48*cos(a+Q_PI/4), y+48*sin(a+Q_PI/4), 0);
	glVertex3f (x, y, 0);
	glVertex3f (x+48*cos(a-Q_PI/4), y+48*sin(a-Q_PI/4), 0);
	glEnd ();

}

void DrawZIcon (void)
{
	float	x, y;

	x = z.origin[0];
	y = z.origin[1];

	glEnable (GL_BLEND);
	glDisable (GL_TEXTURE_2D);
	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
	glDisable (GL_CULL_FACE);
	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glColor4f (0.0, 0.0, 1.0, 0.25);
	glBegin(GL_QUADS);
	glVertex3f (x-8,y-8,0);
	glVertex3f (x+8,y-8,0);
	glVertex3f (x+8,y+8,0);
	glVertex3f (x-8,y+8,0);
	glEnd ();
	glDisable (GL_BLEND);

	glColor4f (0.0, 0.0, 1.0, 1);

	glBegin(GL_LINE_LOOP);
	glVertex3f (x-8,y-8,0);
	glVertex3f (x+8,y-8,0);
	glVertex3f (x+8,y+8,0);
	glVertex3f (x-8,y+8,0);
	glEnd ();

	glBegin(GL_LINE_STRIP);
	glVertex3f (x-4,y+4,0);
	glVertex3f (x+4,y+4,0);
	glVertex3f (x-4,y-4,0);
	glVertex3f (x+4,y-4,0);
	glEnd ();
}


/*
==================
FilterBrush
==================
*/
BOOL FilterBrush(brush_t *pb)
{
	if (!pb->owner)
		return FALSE;		// during construction

	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP)
	{
		if (!strncmp(pb->brush_faces->texdef.name, "clip", 4))
			return TRUE;
	}

	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER)
	{
		if (pb->brush_faces->texdef.name[0] == '*')
			return TRUE;
	}

	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_DETAIL)
	{
		if (pb->brush_faces->texdef.contents & CONTENTS_DETAIL)
			return TRUE;
	}

	if (pb->owner == world_entity)
	{
		if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD)
			return TRUE;
		return FALSE;
	}
	else if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT)
		return TRUE;
	
	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS)
	{
		if (!strncmp(pb->owner->eclass->name, "light", 5))
			return TRUE;
	}

	if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
	{
		if (!strncmp(pb->owner->eclass->name, "path", 4))
			return TRUE;
	}

	return FALSE;
}

/*
=============================================================

  PATH LINES

=============================================================
*/

/*
==================
DrawPathLines

Draws connections between entities.
Needs to consider all entities, not just ones on screen,
because the lines can be visible when neither end is.
Called for both camera view and xy view.
==================
*/
void DrawPathLines (void)
{
	int		i, j, k;
	vec3_t	mid, mid1;
	entity_t *se, *te;
	brush_t	*sb, *tb;
	char	*psz;
	vec3_t	dir, s1, s2;
	vec_t	len, f;
	int		arrows;
	int			num_entities;
	char		*ent_target[MAX_MAP_ENTITIES];
	entity_t	*ent_entity[MAX_MAP_ENTITIES];


	num_entities = 0;
	for (te = entities.next ; te != &entities && num_entities != MAX_MAP_ENTITIES ; te = te->next)
	{
		ent_target[num_entities] = ValueForKey (te, "target");
		if (ent_target[num_entities][0])
		{
			ent_entity[num_entities] = te;
			num_entities++;
		}
	}

	for (se = entities.next ; se != &entities ; se = se->next)
	{
		psz = ValueForKey(se, "targetname");
	
		if (psz == NULL || psz[0] == '\0')
			continue;
		
		sb = se->brushes.onext;
		if (sb == &se->brushes)
			continue;

		for (k=0 ; k<num_entities ; k++)
		{
			if (strcmp (ent_target[k], psz))
				continue;

			te = ent_entity[k];
			tb = te->brushes.onext;
			if (tb == &te->brushes)
				continue;

			for (i=0 ; i<3 ; i++)
				mid[i] = (sb->mins[i] + sb->maxs[i])*0.5; 

			for (i=0 ; i<3 ; i++)
				mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5; 

			VectorSubtract (mid1, mid, dir);
			len = VectorNormalize (dir);
			s1[0] = -dir[1]*8 + dir[0]*8;
			s2[0] = dir[1]*8 + dir[0]*8;
			s1[1] = dir[0]*8 + dir[1]*8;
			s2[1] = -dir[0]*8 + dir[1]*8;

			glColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);

			glBegin(GL_LINES);
			glVertex3fv(mid);
			glVertex3fv(mid1);

			arrows = (int)(len / 256) + 1;

			for (i=0 ; i<arrows ; i++)
			{
				f = len * (i + 0.5) / arrows;

				for (j=0 ; j<3 ; j++)
					mid1[j] = mid[j] + f*dir[j];
				glVertex3fv (mid1);
				glVertex3f (mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]);
				glVertex3fv (mid1);
				glVertex3f (mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]);
			}

			glEnd();
		}
	}

	return;
}

//=============================================================


/*
==============
XY_Draw
==============
*/
void XY_Draw (void)
{
    brush_t	*brush;
	float	w, h;
	entity_t	*e;
	double	start, end;
	vec3_t	mins, maxs;
	int		drawn, culled;
	int		i;

	if (!active_brushes.next)
		return;	// not valid yet

	if (g_qeglobals.d_xy.timing)
		start = Sys_DoubleTime ();

	//
	// clear
	//
	g_qeglobals.d_xy.d_dirty = false;

	glViewport(0, 0, g_qeglobals.d_xy.width, g_qeglobals.d_xy.height);
	glClearColor (
		g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0],
		g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1],
		g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],
		0);

    glClear(GL_COLOR_BUFFER_BIT);

	//
	// set up viewpoint
	//
	glMatrixMode(GL_PROJECTION);
    glLoadIdentity ();

	w = g_qeglobals.d_xy.width/2 / g_qeglobals.d_xy.scale;
	h = g_qeglobals.d_xy.height/2 / g_qeglobals.d_xy.scale;
	mins[0] = g_qeglobals.d_xy.origin[0] - w;
	maxs[0] = g_qeglobals.d_xy.origin[0] + w;
	mins[1] = g_qeglobals.d_xy.origin[1] - h;
	maxs[1] = g_qeglobals.d_xy.origin[1] + h;

	glOrtho (mins[0], maxs[0], mins[1], maxs[1], -8000, 8000);

	//
	// now draw the grid
	//
	XY_DrawGrid ();

	//
	// draw stuff
	//
    glShadeModel (GL_FLAT);
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_TEXTURE_1D);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_BLEND);
	glColor3f(0, 0, 0);
//		glEnable (GL_LINE_SMOOTH);

	drawn = culled = 0;

	e = NULL;
	for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
	{
		if (brush->mins[0] > maxs[0]
			|| brush->mins[1] > maxs[1]
			|| brush->maxs[0] < mins[0]
			|| brush->maxs[1] < mins[1]	)
		{
			culled++;
			continue;		// off screen
		}

		if (FilterBrush (brush))
			continue;
		drawn++;
		if (brush->owner != e)
		{
			e = brush->owner;
			glColor3fv(e->eclass->color);
		}
		Brush_DrawXY( brush );
	}

	DrawPathLines ();

	//
	// draw pointfile
	//
	if ( g_qeglobals.d_pointfile_display_list)
		glCallList (g_qeglobals.d_pointfile_display_list);

	//
	// draw block grid
	//
	if ( g_qeglobals.show_blocks)
		XY_DrawBlockGrid ();

	//
	// now draw selected brushes
	//
	glTranslatef( g_qeglobals.d_select_translate[0], g_qeglobals.d_select_translate[1], g_qeglobals.d_select_translate[2]);

	glColor3f(1.0, 0.0, 0.0);
	glEnable (GL_LINE_STIPPLE);
	glLineStipple (3, 0xaaaa);
	glLineWidth (2);

	for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next)
	{
		drawn++;
		Brush_DrawXY( brush );
	}

	glDisable (GL_LINE_STIPPLE);
	glLineWidth (1);

	// edge / vertex flags

	if (g_qeglobals.d_select_mode == sel_vertex)
	{
		glPointSize (4);
		glColor3f (0,1,0);
		glBegin (GL_POINTS);
		for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
			glVertex3fv (g_qeglobals.d_points[i]);
		glEnd ();
		glPointSize (1);
	}
	else if (g_qeglobals.d_select_mode == sel_edge)
	{
		float	*v1, *v2;

		glPointSize (4);
		glColor3f (0,0,1);
		glBegin (GL_POINTS);
		for (i=0 ; i<g_qeglobals.d_numedges ; i++)
		{
			v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
			v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
			glVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
		}
		glEnd ();
		glPointSize (1);
	}
	glTranslatef (-g_qeglobals.d_select_translate[0], -g_qeglobals.d_select_translate[1], -g_qeglobals.d_select_translate[2]);

	//
	// now draw camera point
	//
	DrawCameraIcon ();
	DrawZIcon ();

    glFinish();
	QE_CheckOpenGLForErrors();

	if (g_qeglobals.d_xy.timing)
	{
		end = Sys_DoubleTime ();
		Sys_Printf ("xy: %i ms\n", (int)(1000*(end-start)));
	}
}

/*
==============
XY_Overlay
==============
*/
void XY_Overlay (void)
{
	int	w, h;
	int	r[4];
	static	vec3_t	lastz;
	static	vec3_t	lastcamera;


	glViewport(0, 0, g_qeglobals.d_xy.width, g_qeglobals.d_xy.height);

	//
	// set up viewpoint
	//
	glMatrixMode(GL_PROJECTION);
    glLoadIdentity ();

	w = g_qeglobals.d_xy.width/2 / g_qeglobals.d_xy.scale;
	h = g_qeglobals.d_xy.height/2 / g_qeglobals.d_xy.scale;
	glOrtho (g_qeglobals.d_xy.origin[0] - w, g_qeglobals.d_xy.origin[0] + w
		, g_qeglobals.d_xy.origin[1] - h, g_qeglobals.d_xy.origin[1] + h, -8000, 8000);
	//
	// erase the old camera and z checker positions
	// if the entire xy hasn't been redrawn
	//
	if (g_qeglobals.d_xy.d_dirty)
	{
		glReadBuffer (GL_BACK);
		glDrawBuffer (GL_FRONT);

		glRasterPos2f (lastz[0]-9, lastz[1]-9);
		glGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
		glCopyPixels(r[0], r[1], 18,18, GL_COLOR);

		glRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
		glGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
		glCopyPixels(r[0], r[1], 100,100, GL_COLOR);
	}
	g_qeglobals.d_xy.d_dirty = true;

	//
	// save off underneath where we are about to draw
	//
	VectorCopy (z.origin, lastz);
	VectorCopy (camera.origin, lastcamera);

	glReadBuffer (GL_FRONT);
	glDrawBuffer (GL_BACK);

	glRasterPos2f (lastz[0]-9, lastz[1]-9);
	glGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
	glCopyPixels(r[0], r[1], 18,18, GL_COLOR);

	glRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
	glGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
	glCopyPixels(r[0], r[1], 100,100, GL_COLOR);

	//
	// draw the new icons
	//
	glDrawBuffer (GL_FRONT);

    glShadeModel (GL_FLAT);
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_TEXTURE_1D);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_BLEND);
	glColor3f(0, 0, 0);

	DrawCameraIcon ();
	DrawZIcon ();

	glDrawBuffer (GL_BACK);
    glFinish();
}

