]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake2/extra/qe4/xy.c
Merge remote-tracking branch 'ttimo/master'
[xonotic/netradiant.git] / tools / quake2 / extra / qe4 / xy.c
diff --git a/tools/quake2/extra/qe4/xy.c b/tools/quake2/extra/qe4/xy.c
new file mode 100644 (file)
index 0000000..5c8303e
--- /dev/null
@@ -0,0 +1,973 @@
+/*
+===========================================================================
+Copyright (C) 1997-2006 Id Software, Inc.
+
+This file is part of Quake 2 Tools source code.
+
+Quake 2 Tools source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake 2 Tools source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Quake 2 Tools source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+===========================================================================
+*/
+
+#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();
+}
+