1024 lines
22 KiB
C
1024 lines
22 KiB
C
|
|
#include "qe3.h"
|
|
#include "clip.h"
|
|
#include "undo.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;
|
|
static vec3_t cliplinestart;
|
|
static vec3_t cliplineend;
|
|
|
|
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 Drag_Reset (void);
|
|
void XY_MouseDown (int x, int y, int buttons)
|
|
{
|
|
vec3_t point;
|
|
vec3_t origin, dir, right, up;
|
|
|
|
Drag_Reset();
|
|
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))
|
|
|| (buttons == (MK_LBUTTON | MK_RBUTTON)))
|
|
{
|
|
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;
|
|
}
|
|
// control rbutton = clip brush
|
|
if (buttonstate == (MK_CONTROL|MK_RBUTTON))
|
|
{
|
|
if (!QE_SingleBrush())
|
|
{
|
|
Sys_Status ("Must have exactly one brush selected.", 0);
|
|
Sys_Beep ();
|
|
return;
|
|
}
|
|
XY_ToGridPoint(x, y, cliplinestart);
|
|
XY_ToGridPoint(x, y, cliplineend);
|
|
Begin_Clip(x, y);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
==============
|
|
XY_MouseUp
|
|
==============
|
|
*/
|
|
void XY_MouseUp (int x, int y, int buttons)
|
|
{
|
|
Drag_MouseUp ();
|
|
|
|
if (!press_selection)
|
|
Sys_UpdateWindows (W_ALL);
|
|
|
|
if (buttonstate == (MK_CONTROL|MK_RBUTTON))
|
|
{
|
|
if (!QE_SingleBrush())
|
|
{
|
|
Sys_Status ("Must have exactly one brush selected.", 0);
|
|
Sys_Beep ();
|
|
}
|
|
else
|
|
{
|
|
Finish_Clip( x, y);
|
|
}
|
|
}
|
|
|
|
|
|
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 );
|
|
UNDO_FinishBrushAdd ("&Undo New Brush");
|
|
|
|
// 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;
|
|
}
|
|
// control + rbutton, draw line for clipping plane
|
|
if (buttonstate == (MK_CONTROL|MK_RBUTTON))
|
|
{
|
|
XY_ToGridPoint(x, y, cliplineend);
|
|
Sys_UpdateWindows (W_XY|W_XY_OVERLAY);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
============================================================================
|
|
|
|
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.flags == 40)
|
|
{
|
|
// 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)
|
|
{
|
|
if (g_qeglobals.d_savedinfo.exclude & BUOY_ONLY)
|
|
{
|
|
if (!strcmp(ValueForKey (pb->owner , "classname"), "info_buoy"))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
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");
|
|
ent_target[num_entities + 1] = ValueForKey (te, "target2");
|
|
if (ent_target[num_entities][0])
|
|
{
|
|
ent_entity[num_entities] = te;
|
|
num_entities++;
|
|
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, 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)));
|
|
}
|
|
// finally, draw a clipping line if needed
|
|
if ( buttonstate == (MK_RBUTTON|MK_CONTROL))
|
|
{
|
|
if (!QE_SingleBrush())
|
|
{
|
|
Sys_Status ("Must have exactly one brush selected.", 0);
|
|
Sys_Beep ();
|
|
return;
|
|
}
|
|
Draw_Clip(cliplinestart, cliplineend);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
==============
|
|
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();
|
|
}
|
|
|