mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
Forge: More stuff gets the axe.
This commit is contained in:
parent
02dd74b2f7
commit
2ab7a09812
21 changed files with 0 additions and 12263 deletions
|
@ -1,980 +0,0 @@
|
||||||
/*
|
|
||||||
CameraView.m
|
|
||||||
|
|
||||||
Camera view object
|
|
||||||
|
|
||||||
Copyright (C) 2001 Jeff Teunissen <deek@d2dc.net>
|
|
||||||
|
|
||||||
This program 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.
|
|
||||||
|
|
||||||
This program 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 this program; if not, write to:
|
|
||||||
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#import <Foundation/NSGeometry.h>
|
|
||||||
#import <Foundation/NSObject.h>
|
|
||||||
|
|
||||||
#import <AppKit/DPSOperators.h>
|
|
||||||
#import <AppKit/NSGraphicsContext.h>
|
|
||||||
|
|
||||||
#import "CameraView.h"
|
|
||||||
#import "Forge.h"
|
|
||||||
#import "Map.h"
|
|
||||||
//#import "UserPath.h"
|
|
||||||
#import "ZView.h"
|
|
||||||
|
|
||||||
#import "render.h"
|
|
||||||
|
|
||||||
CameraView *cameraView;
|
|
||||||
BOOL timeDrawing = 0;
|
|
||||||
|
|
||||||
@implementation CameraView
|
|
||||||
|
|
||||||
/*
|
|
||||||
(id) initWithFrame: (NSRect)
|
|
||||||
|
|
||||||
Given a frame, set up our view.
|
|
||||||
*/
|
|
||||||
- (id) initWithFrame: (NSRect) frameRect
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
|
|
||||||
[super initWithFrame: frameRect];
|
|
||||||
|
|
||||||
cameraView = self;
|
|
||||||
|
|
||||||
angles[0] = angles[1] = angles[2] = 0.0;
|
|
||||||
|
|
||||||
[self matrixFromAngles];
|
|
||||||
|
|
||||||
origin[0] = 64;
|
|
||||||
origin[1] = 64;
|
|
||||||
origin[2] = 48;
|
|
||||||
|
|
||||||
move = 16;
|
|
||||||
|
|
||||||
bounds = frameRect;
|
|
||||||
size = bounds.size.width * bounds.size.height;
|
|
||||||
zbuffer = malloc (size*4);
|
|
||||||
imagebuffer = malloc (size*4);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- setXYOrigin: (NSPoint) point
|
|
||||||
{
|
|
||||||
origin[0] = point.x;
|
|
||||||
origin[1] = point.y;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- setZOrigin: (float) point
|
|
||||||
{
|
|
||||||
origin[2] = point;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- setOrigin: (vec3_t) org angle: (float) angle
|
|
||||||
{
|
|
||||||
VectorCopy (org, origin);
|
|
||||||
angles[1] = angle;
|
|
||||||
[self matrixFromAngles];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- getOrigin: (vec3_t) org
|
|
||||||
{
|
|
||||||
VectorCopy (origin, org);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (float)yawAngle
|
|
||||||
{
|
|
||||||
return angles[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
- upFloor: sender
|
|
||||||
{
|
|
||||||
sb_floor_dir = 1;
|
|
||||||
sb_floor_dist = 99999;
|
|
||||||
[map makeObjectsPerformSelector: @selector(feetToFloor)];
|
|
||||||
if (sb_floor_dist == 99999)
|
|
||||||
{
|
|
||||||
qprintf ("already on top floor");
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
qprintf ("up floor");
|
|
||||||
origin[2] += sb_floor_dist;
|
|
||||||
[forge updateCamera];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- downFloor: sender
|
|
||||||
{
|
|
||||||
sb_floor_dir = -1;
|
|
||||||
sb_floor_dist = -99999;
|
|
||||||
[map makeAllPerform: @selector(feetToFloor)];
|
|
||||||
if (sb_floor_dist == -99999)
|
|
||||||
{
|
|
||||||
qprintf ("already on bottom floor");
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
qprintf ("down floor");
|
|
||||||
origin[2] += sb_floor_dist;
|
|
||||||
[forge updateCamera];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============================================================================
|
|
||||||
|
|
||||||
UI TARGETS
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
============
|
|
||||||
homeView
|
|
||||||
============
|
|
||||||
*/
|
|
||||||
- homeView: sender
|
|
||||||
{
|
|
||||||
angles[0] = angles[2] = 0;
|
|
||||||
|
|
||||||
[self matrixFromAngles];
|
|
||||||
|
|
||||||
[forge updateAll];
|
|
||||||
|
|
||||||
qprintf ("homed view angle");
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- drawMode: (NSMatrix) sender
|
|
||||||
{
|
|
||||||
drawmode = [sender selectedColumn];
|
|
||||||
[forge updateCamera];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- setDrawMode: (drawmode_t)mode
|
|
||||||
{
|
|
||||||
drawmode = mode;
|
|
||||||
[mode_radio_i selectCellAtRow: 0 column: mode];
|
|
||||||
[forge updateCamera];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============================================================================
|
|
||||||
|
|
||||||
TRANSFORMATION METHODS
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
- matrixFromAngles
|
|
||||||
{
|
|
||||||
if (angles[0] > M_PI*0.4)
|
|
||||||
angles[0] = M_PI*0.4;
|
|
||||||
if (angles[0] < -M_PI*0.4)
|
|
||||||
angles[0] = -M_PI*0.4;
|
|
||||||
|
|
||||||
// vpn
|
|
||||||
matrix[2][0] = cos(angles[0])*cos(angles[1]);
|
|
||||||
matrix[2][1] = cos(angles[0])*sin(angles[1]);
|
|
||||||
matrix[2][2] = sin(angles[0]);
|
|
||||||
|
|
||||||
// vup
|
|
||||||
matrix[1][0] = cos(angles[0]+M_PI/2)*cos(angles[1]);
|
|
||||||
matrix[1][1] = cos(angles[0]+M_PI/2)*sin(angles[1]);
|
|
||||||
matrix[1][2] = sin(angles[0]+M_PI/2);
|
|
||||||
|
|
||||||
// vright
|
|
||||||
CrossProduct (matrix[2], matrix[1], matrix[0]);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- inverseTransform: (vec_t *)invec to:(vec_t *)outvec
|
|
||||||
{
|
|
||||||
vec3_t inverse[3];
|
|
||||||
vec3_t temp;
|
|
||||||
int i,j;
|
|
||||||
|
|
||||||
for (i=0 ; i<3 ; i++)
|
|
||||||
for (j=0 ; j<3 ; j++)
|
|
||||||
inverse[i][j] = matrix[j][i];
|
|
||||||
|
|
||||||
temp[0] = DotProduct(invec, inverse[0]);
|
|
||||||
temp[1] = DotProduct(invec, inverse[1]);
|
|
||||||
temp[2] = DotProduct(invec, inverse[2]);
|
|
||||||
|
|
||||||
VectorAdd (temp, origin, outvec);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============================================================================
|
|
||||||
|
|
||||||
DRAWING METHODS
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
vec3_t trans;
|
|
||||||
int clipflags;
|
|
||||||
vec3_t screen; // only valid if clipflags == 0
|
|
||||||
} campt_t;
|
|
||||||
#define CLIP_RIGHT 1
|
|
||||||
#define CLIP_LEFT 2
|
|
||||||
#define CLIP_TOP 4
|
|
||||||
#define CLIP_BOTTOM 8
|
|
||||||
#define CLIP_FRONT 16
|
|
||||||
|
|
||||||
int cam_cur;
|
|
||||||
campt_t campts[2];
|
|
||||||
|
|
||||||
vec3_t r_matrix[3];
|
|
||||||
vec3_t r_origin;
|
|
||||||
float mid_x, mid_y;
|
|
||||||
float topscale = (240.0/3)/160;
|
|
||||||
float bottomscale = (240.0*2/3)/160;
|
|
||||||
|
|
||||||
//extern plane_t frustum[5];
|
|
||||||
|
|
||||||
void MakeCampt (vec3_t in, campt_t *pt)
|
|
||||||
{
|
|
||||||
vec3_t temp;
|
|
||||||
float scale;
|
|
||||||
|
|
||||||
// transform the points
|
|
||||||
VectorSubtract (in, r_origin, temp);
|
|
||||||
|
|
||||||
pt->trans[0] = DotProduct(temp, r_matrix[0]);
|
|
||||||
pt->trans[1] = DotProduct(temp, r_matrix[1]);
|
|
||||||
pt->trans[2] = DotProduct(temp, r_matrix[2]);
|
|
||||||
|
|
||||||
// check clip flags
|
|
||||||
if (pt->trans[2] < 1)
|
|
||||||
pt->clipflags = CLIP_FRONT;
|
|
||||||
else
|
|
||||||
pt->clipflags = 0;
|
|
||||||
|
|
||||||
if (pt->trans[0] > pt->trans[2])
|
|
||||||
pt->clipflags |= CLIP_RIGHT;
|
|
||||||
else if (-pt->trans[0] > pt->trans[2])
|
|
||||||
pt->clipflags |= CLIP_LEFT;
|
|
||||||
|
|
||||||
if (pt->trans[1] > pt->trans[2]*topscale )
|
|
||||||
pt->clipflags |= CLIP_TOP;
|
|
||||||
else if (-pt->trans[1] > pt->trans[2]*bottomscale )
|
|
||||||
pt->clipflags |= CLIP_BOTTOM;
|
|
||||||
|
|
||||||
if (pt->clipflags)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// project
|
|
||||||
scale = mid_x/pt->trans[2];
|
|
||||||
pt->screen[0] = mid_x + pt->trans[0]*scale;
|
|
||||||
pt->screen[1] = mid_y + pt->trans[1]*scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CameraMoveto(vec3_t p)
|
|
||||||
{
|
|
||||||
campt_t *pt;
|
|
||||||
|
|
||||||
if (userPath->numberOfPoints > 2048)
|
|
||||||
lineflush ();
|
|
||||||
|
|
||||||
pt = &campts[cam_cur];
|
|
||||||
cam_cur ^= 1;
|
|
||||||
MakeCampt (p,pt);
|
|
||||||
if (!pt->clipflags)
|
|
||||||
{ // onscreen, so move there immediately
|
|
||||||
UPmoveto (userPath, pt->screen[0], pt->screen[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClipLine (vec3_t p1, vec3_t p2, int planenum)
|
|
||||||
{
|
|
||||||
float d, d2, frac;
|
|
||||||
vec3_t new;
|
|
||||||
mplane_t *pl;
|
|
||||||
float scale;
|
|
||||||
|
|
||||||
if (planenum == 5)
|
|
||||||
{ // draw it!
|
|
||||||
scale = mid_x/p1[2];
|
|
||||||
new[0] = mid_x + p1[0]*scale;
|
|
||||||
new[1] = mid_y + p1[1]*scale;
|
|
||||||
UPmoveto (userPath, new[0], new[1]);
|
|
||||||
|
|
||||||
scale = mid_x/p2[2];
|
|
||||||
new[0] = mid_x + p2[0]*scale;
|
|
||||||
new[1] = mid_y + p2[1]*scale;
|
|
||||||
UPlineto (userPath, new[0], new[1]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pl = &frustum[planenum];
|
|
||||||
|
|
||||||
d = DotProduct (p1, pl->normal) - pl->dist;
|
|
||||||
d2 = DotProduct (p2, pl->normal) - pl->dist;
|
|
||||||
if (d <= ON_EPSILON && d2 <= ON_EPSILON)
|
|
||||||
{ // off screen
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d >= 0 && d2 >= 0)
|
|
||||||
{ // on front
|
|
||||||
ClipLine (p1, p2, planenum+1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
frac = d/(d-d2);
|
|
||||||
new[0] = p1[0] + frac*(p2[0]-p1[0]);
|
|
||||||
new[1] = p1[1] + frac*(p2[1]-p1[1]);
|
|
||||||
new[2] = p1[2] + frac*(p2[2]-p1[2]);
|
|
||||||
|
|
||||||
if (d > 0)
|
|
||||||
ClipLine (p1, new, planenum+1);
|
|
||||||
else
|
|
||||||
ClipLine (new, p2, planenum+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int c_off, c_on, c_clip;
|
|
||||||
|
|
||||||
void CameraLineto(vec3_t p)
|
|
||||||
{
|
|
||||||
campt_t *p1, *p2;
|
|
||||||
int bits;
|
|
||||||
|
|
||||||
p2 = &campts[cam_cur];
|
|
||||||
cam_cur ^= 1;
|
|
||||||
p1 = &campts[cam_cur];
|
|
||||||
MakeCampt (p, p2);
|
|
||||||
|
|
||||||
if (p1->clipflags & p2->clipflags)
|
|
||||||
{
|
|
||||||
c_off++;
|
|
||||||
return; // entirely off screen
|
|
||||||
}
|
|
||||||
|
|
||||||
bits = p1->clipflags | p2->clipflags;
|
|
||||||
|
|
||||||
if (! bits )
|
|
||||||
{
|
|
||||||
c_on++;
|
|
||||||
UPmoveto (userPath, p1->screen[0], p1->screen[1]);
|
|
||||||
UPlineto (userPath, p2->screen[0], p2->screen[1]);
|
|
||||||
return; // entirely on screen
|
|
||||||
}
|
|
||||||
|
|
||||||
// needs to be clipped
|
|
||||||
c_clip++;
|
|
||||||
|
|
||||||
ClipLine (p1->trans, p2->trans, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
drawSolid
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
- drawSolid
|
|
||||||
{
|
|
||||||
const unsigned char *planes[5];
|
|
||||||
|
|
||||||
//
|
|
||||||
// draw it
|
|
||||||
//
|
|
||||||
VectorCopy (origin, r_origin);
|
|
||||||
VectorCopy (matrix[0], r_matrix[0]);
|
|
||||||
VectorCopy (matrix[1], r_matrix[1]);
|
|
||||||
VectorCopy (matrix[2], r_matrix[2]);
|
|
||||||
|
|
||||||
r_width = [self bounds].size.width;
|
|
||||||
r_height = [self bounds].size.height;
|
|
||||||
r_picbuffer = imagebuffer;
|
|
||||||
r_zbuffer = zbuffer;
|
|
||||||
|
|
||||||
r_drawflat = (drawmode == dr_flat);
|
|
||||||
|
|
||||||
REN_BeginCamera ();
|
|
||||||
REN_ClearBuffers ();
|
|
||||||
|
|
||||||
//
|
|
||||||
// render the setbrushes
|
|
||||||
//
|
|
||||||
[map makeAllPerform: @selector(CameraRenderSelf)];
|
|
||||||
|
|
||||||
//
|
|
||||||
// display the output
|
|
||||||
//
|
|
||||||
[[self window] setBackingType:NSBackingStoreRetained];
|
|
||||||
|
|
||||||
planes[0] = (unsigned char *)imagebuffer;
|
|
||||||
NSDrawBitmap(
|
|
||||||
bounds, r_width, r_height,
|
|
||||||
8, 3, 32, r_width*4,
|
|
||||||
NO, // not planar
|
|
||||||
NO, // no alpha
|
|
||||||
NSCalibratedRGBColorSpace,
|
|
||||||
planes
|
|
||||||
);
|
|
||||||
|
|
||||||
// NSPing ();
|
|
||||||
[[self window] setBackingType:NSBackingStoreBuffered];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
drawWire
|
|
||||||
===================
|
|
||||||
*/
|
|
||||||
- drawWire: (NSRect) rect
|
|
||||||
{
|
|
||||||
// copy current info to globals for the C callbacks
|
|
||||||
mid_x = bounds.size.width / 2;
|
|
||||||
mid_y = 2 * bounds.size.height / 3;
|
|
||||||
|
|
||||||
VectorCopy (origin, r_origin);
|
|
||||||
VectorCopy (matrix[0], r_matrix[0]);
|
|
||||||
VectorCopy (matrix[1], r_matrix[1]);
|
|
||||||
VectorCopy (matrix[2], r_matrix[2]);
|
|
||||||
|
|
||||||
r_width = bounds.size.width;
|
|
||||||
r_height = bounds.size.height;
|
|
||||||
r_picbuffer = imagebuffer;
|
|
||||||
r_zbuffer = zbuffer;
|
|
||||||
|
|
||||||
REN_BeginCamera ();
|
|
||||||
|
|
||||||
// erase window
|
|
||||||
NSEraseRect (rect);
|
|
||||||
|
|
||||||
// draw all entities
|
|
||||||
linestart (0,0,0);
|
|
||||||
[map makeUnselectedPerform: @selector(CameraDrawSelf)];
|
|
||||||
lineflush ();
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
drawSelf
|
|
||||||
===================
|
|
||||||
*/
|
|
||||||
- drawSelf: (NSRect) rects :(int)rectCount
|
|
||||||
{
|
|
||||||
static float drawtime; // static to shut up compiler warning
|
|
||||||
|
|
||||||
if (timeDrawing)
|
|
||||||
drawtime = I_FloatTime ();
|
|
||||||
|
|
||||||
if (drawmode == dr_texture || drawmode == dr_flat)
|
|
||||||
[self drawSolid];
|
|
||||||
else
|
|
||||||
[self drawWire: rects];
|
|
||||||
|
|
||||||
if (timeDrawing) {
|
|
||||||
// NSPing ();
|
|
||||||
drawtime = I_FloatTime() - drawtime;
|
|
||||||
printf ("CameraView drawtime: %5.3f\n", drawtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
XYDrawSelf
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
- XYDrawSelf
|
|
||||||
{
|
|
||||||
|
|
||||||
PSsetrgbcolor (0,0,1.0);
|
|
||||||
PSsetlinewidth (0.15);
|
|
||||||
PSmoveto (origin[0]-16,origin[1]);
|
|
||||||
PSrlineto (16,8);
|
|
||||||
PSrlineto (16,-8);
|
|
||||||
PSrlineto (-16,-8);
|
|
||||||
PSrlineto (-16,8);
|
|
||||||
PSrlineto (32,0);
|
|
||||||
|
|
||||||
PSmoveto (origin[0],origin[1]);
|
|
||||||
PSrlineto (64*cos(angles[1]+M_PI/4), 64*sin(angles[1]+M_PI/4));
|
|
||||||
PSmoveto (origin[0],origin[1]);
|
|
||||||
PSrlineto (64*cos(angles[1]-M_PI/4), 64*sin(angles[1]-M_PI/4));
|
|
||||||
|
|
||||||
PSstroke ();
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
ZDrawSelf
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
- ZDrawSelf
|
|
||||||
{
|
|
||||||
PSsetrgbcolor (0,0,1.0);
|
|
||||||
PSsetlinewidth (0.15);
|
|
||||||
|
|
||||||
PSmoveto (-16,origin[2]);
|
|
||||||
PSrlineto (16,8);
|
|
||||||
PSrlineto (16,-8);
|
|
||||||
PSrlineto (-16,-8);
|
|
||||||
PSrlineto (-16,8);
|
|
||||||
PSrlineto (32,0);
|
|
||||||
|
|
||||||
PSmoveto (-15,origin[2]-47);
|
|
||||||
PSrlineto (29,0);
|
|
||||||
PSrlineto (0,54);
|
|
||||||
PSrlineto (-29,0);
|
|
||||||
PSrlineto (0,-54);
|
|
||||||
|
|
||||||
PSstroke ();
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============================================================================
|
|
||||||
|
|
||||||
XYZ mouse view methods
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
modalMoveLoop
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
- modalMoveLoop: (NSPoint) basept : (vec3_t) movemod : converter
|
|
||||||
{
|
|
||||||
vec3_t originbase;
|
|
||||||
NSEvent *event;
|
|
||||||
NSPoint newpt;
|
|
||||||
// NSPoint brushpt;
|
|
||||||
vec3_t delta;
|
|
||||||
// id ent;
|
|
||||||
int i;
|
|
||||||
// vec3_t temp;
|
|
||||||
unsigned int eventMask = NSLeftMouseUpMask | NSRightMouseUpMask |
|
|
||||||
NSLeftMouseDraggedMask | NSRightMouseDraggedMask |
|
|
||||||
NSApplicationDefinedMask | NSKeyDownMask;
|
|
||||||
|
|
||||||
qprintf ("moving camera position");
|
|
||||||
|
|
||||||
VectorCopy (origin, originbase);
|
|
||||||
|
|
||||||
//
|
|
||||||
// modal event loop using instance drawing
|
|
||||||
//
|
|
||||||
goto drawentry;
|
|
||||||
|
|
||||||
while ([event type] != NSLeftMouseUp && [event type] != NSRightMouseUp)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// calculate new point
|
|
||||||
//
|
|
||||||
newpt = [event locationInWindow];
|
|
||||||
[converter convertPoint: newpt fromView: nil];
|
|
||||||
|
|
||||||
delta[0] = newpt.x - basept.x;
|
|
||||||
delta[1] = newpt.y - basept.y;
|
|
||||||
delta[2] = delta[1]; // height change
|
|
||||||
|
|
||||||
for (i=0 ; i<3 ; i++)
|
|
||||||
origin[i] = originbase[i]+movemod[i]*delta[i];
|
|
||||||
|
|
||||||
#if 0 // FIXME
|
|
||||||
//
|
|
||||||
// if command is down, look towards brush or entity
|
|
||||||
//
|
|
||||||
if ([event modifierFlags] & NSShiftKeyMask)
|
|
||||||
{
|
|
||||||
ent = [quakemap selectedEntity];
|
|
||||||
if (ent)
|
|
||||||
{
|
|
||||||
[ent origin: temp];
|
|
||||||
brushpt.x = temp[0];
|
|
||||||
brushpt.y = temp[1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
brushpt = [brush_i centerPoint];
|
|
||||||
angles[1] = atan2 (brushpt.y - newpt.y, brushpt.x - newpt.x);
|
|
||||||
[self matrixFromAngles];
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
drawentry:
|
|
||||||
// instance draw new frame
|
|
||||||
[forge newinstance];
|
|
||||||
[self display];
|
|
||||||
|
|
||||||
event = [NSApp nextEventMatchingMask: eventMask
|
|
||||||
untilDate: [NSDate distantFuture]
|
|
||||||
inMode: NSEventTrackingRunLoopMode
|
|
||||||
dequeue: YES];
|
|
||||||
|
|
||||||
if ([event type] == NSKeyDown) {
|
|
||||||
[self _keyDown: event];
|
|
||||||
[self display];
|
|
||||||
goto drawentry;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
XYmouseDown
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
- (BOOL) XYmouseDown: (NSPoint) pt flags: (unsigned int) flags // return YES if brush handled
|
|
||||||
{
|
|
||||||
vec3_t movemod;
|
|
||||||
|
|
||||||
if (fabs(pt.x - origin[0]) > 16
|
|
||||||
|| fabs(pt.y - origin[1]) > 16 )
|
|
||||||
return NO;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (flags & NS_ALTERNATEMASK)
|
|
||||||
{ // up / down drag
|
|
||||||
movemod[0] = 0;
|
|
||||||
movemod[1] = 0;
|
|
||||||
movemod[2] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
movemod[0] = 1;
|
|
||||||
movemod[1] = 1;
|
|
||||||
movemod[2] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[self modalMoveLoop: pt : movemod : xyView];
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
ZmouseDown
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
- (BOOL) ZmouseDown: (NSPoint) pt flags: (unsigned int) flags // return YES if brush handled
|
|
||||||
{
|
|
||||||
vec3_t movemod;
|
|
||||||
|
|
||||||
if (fabs(pt.y - origin[2]) > 16
|
|
||||||
|| pt.x < -8 || pt.x > 8 )
|
|
||||||
return NO;
|
|
||||||
|
|
||||||
movemod[0] = 0;
|
|
||||||
movemod[1] = 0;
|
|
||||||
movemod[2] = 1;
|
|
||||||
|
|
||||||
[self modalMoveLoop: pt : movemod : zView];
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
viewDrag:
|
|
||||||
===================
|
|
||||||
*/
|
|
||||||
- viewDrag: (NSPoint) pt
|
|
||||||
{
|
|
||||||
float dx,dy;
|
|
||||||
NSEvent *event;
|
|
||||||
NSPoint newpt;
|
|
||||||
unsigned int eventMask = NSKeyDownMask | NSRightMouseUpMask |
|
|
||||||
NSRightMouseDraggedMask;
|
|
||||||
|
|
||||||
// modal event loop using instance drawing
|
|
||||||
goto drawentry;
|
|
||||||
|
|
||||||
while ([event type] != NSRightMouseUp) {
|
|
||||||
|
|
||||||
// calculate new point
|
|
||||||
newpt = [event locationInWindow];
|
|
||||||
[self convertPoint: newpt fromView: nil];
|
|
||||||
|
|
||||||
dx = newpt.x - pt.x;
|
|
||||||
dy = newpt.y - pt.y;
|
|
||||||
pt = newpt;
|
|
||||||
|
|
||||||
angles[1] -= dx/bounds.size.width*M_PI/2 * 4;
|
|
||||||
angles[0] += dy/bounds.size.width*M_PI/2 * 4;
|
|
||||||
|
|
||||||
[self matrixFromAngles];
|
|
||||||
|
|
||||||
drawentry:
|
|
||||||
[forge newinstance];
|
|
||||||
[self display];
|
|
||||||
|
|
||||||
event = [NSApp nextEventMatchingMask: eventMask
|
|
||||||
untilDate: [NSDate distantFuture]
|
|
||||||
inMode: NSEventTrackingRunLoopMode
|
|
||||||
dequeue: YES];
|
|
||||||
|
|
||||||
if ([event type] == NSKeyDown) {
|
|
||||||
[self _keyDown: event];
|
|
||||||
[self display];
|
|
||||||
goto drawentry;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
mouseDown
|
|
||||||
===================
|
|
||||||
*/
|
|
||||||
- (void) mouseDown: (NSEvent *) theEvent
|
|
||||||
{
|
|
||||||
NSPoint pt;
|
|
||||||
int i;
|
|
||||||
vec3_t p1, p2;
|
|
||||||
float forward, right, up;
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
pt = [theEvent locationInWindow];
|
|
||||||
|
|
||||||
[self convertPoint: pt fromView: nil];
|
|
||||||
|
|
||||||
VectorCopy (origin, p1);
|
|
||||||
forward = 160;
|
|
||||||
right = pt.x - 160;
|
|
||||||
up = pt.y - 240*2/3;
|
|
||||||
for (i=0 ; i<3 ; i++)
|
|
||||||
p2[i] = forward*matrix[2][i] + up*matrix[1][i] + right*matrix[0][i];
|
|
||||||
for (i=0 ; i<3 ; i++)
|
|
||||||
p2[i] = p1[i] + 100*p2[i];
|
|
||||||
|
|
||||||
flags = [theEvent modifierFlags] & (NSShiftKeyMask | NSControlKeyMask |
|
|
||||||
NSAlternateKeyMask | NSCommandKeyMask);
|
|
||||||
|
|
||||||
// bare click to select a texture
|
|
||||||
if (!flags) {
|
|
||||||
[map getTextureRay: p1 : p2];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// shift click to select / deselect a brush from the world
|
|
||||||
if (flags == NSShiftKeyMask) {
|
|
||||||
[map selectRay: p1 : p2 : NO];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// cmd-shift click to set a target/targetname entity connection
|
|
||||||
if (flags == (NSShiftKeyMask | NSCommandKeyMask)) {
|
|
||||||
[map entityConnect: p1 : p2];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// alt click = set entire brush texture
|
|
||||||
if (flags == NSAlternateKeyMask) {
|
|
||||||
if (drawmode != dr_texture) {
|
|
||||||
qprintf ("No texture setting except in texture mode!\n");
|
|
||||||
NopSound ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
[map setTextureRay: p1 : p2 : YES];
|
|
||||||
[forge updateAll];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ctrl-alt click = set single face texture
|
|
||||||
if (flags == (NSControlKeyMask | NSAlternateKeyMask) ) {
|
|
||||||
if (drawmode != dr_texture) {
|
|
||||||
qprintf ("No texture setting except in texture mode!\n");
|
|
||||||
NopSound ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
[map setTextureRay: p1 : p2 : NO];
|
|
||||||
[forge updateAll];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qprintf ("bad modifier flags for click");
|
|
||||||
NopSound ();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
rightMouseDown
|
|
||||||
===================
|
|
||||||
*/
|
|
||||||
- (void) rightMouseDown: (NSEvent *) theEvent
|
|
||||||
{
|
|
||||||
NSPoint pt;
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
pt = [theEvent locationInWindow];
|
|
||||||
|
|
||||||
[self convertPoint: pt fromView: nil];
|
|
||||||
|
|
||||||
flags = [theEvent modifierFlags] & (NSShiftKeyMask | NSControlKeyMask |
|
|
||||||
NSAlternateKeyMask | NSCommandKeyMask);
|
|
||||||
|
|
||||||
// click = drag camera
|
|
||||||
if (!flags) {
|
|
||||||
qprintf ("looking");
|
|
||||||
[self viewDrag: pt];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qprintf ("bad modifier flags for click");
|
|
||||||
NopSound ();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
keyDown
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
- (void) _keyDown: (NSEvent *) theEvent
|
|
||||||
{
|
|
||||||
NSString *chars = [theEvent characters];
|
|
||||||
unichar ch;
|
|
||||||
|
|
||||||
if ([chars length] != 1) {
|
|
||||||
qprintf ("Incorrect number of characters in keyDown event.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ch = [chars characterAtIndex: 1];
|
|
||||||
|
|
||||||
switch (ch) {
|
|
||||||
case 13:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 'a':
|
|
||||||
case 'A':
|
|
||||||
angles[0] += M_PI/8;
|
|
||||||
[self matrixFromAngles];
|
|
||||||
[forge updateCamera];
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 'z':
|
|
||||||
case 'Z':
|
|
||||||
angles[0] -= M_PI/8;
|
|
||||||
[self matrixFromAngles];
|
|
||||||
[forge updateCamera];
|
|
||||||
return;
|
|
||||||
|
|
||||||
case NSRightArrowFunctionKey:
|
|
||||||
angles[1] -= M_PI*move/(64*2);
|
|
||||||
[self matrixFromAngles];
|
|
||||||
[forge updateCamera];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSLeftArrowFunctionKey:
|
|
||||||
angles[1] += M_PI*move/(64*2);
|
|
||||||
[self matrixFromAngles];
|
|
||||||
[forge updateCamera];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSUpArrowFunctionKey:
|
|
||||||
origin[0] += move*cos(angles[1]);
|
|
||||||
origin[1] += move*sin(angles[1]);
|
|
||||||
[forge updateCamera];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSDownArrowFunctionKey:
|
|
||||||
origin[0] -= move*cos(angles[1]);
|
|
||||||
origin[1] -= move*sin(angles[1]);
|
|
||||||
[forge updateCamera];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '.':
|
|
||||||
origin[0] += move*cos(angles[1]-M_PI_2);
|
|
||||||
origin[1] += move*sin(angles[1]-M_PI_2);
|
|
||||||
[forge updateCamera];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ',':
|
|
||||||
origin[0] -= move*cos(angles[1]-M_PI_2);
|
|
||||||
origin[1] -= move*sin(angles[1]-M_PI_2);
|
|
||||||
[forge updateCamera];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'd':
|
|
||||||
case 'D':
|
|
||||||
origin[2] += move;
|
|
||||||
[forge updateCamera];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'c':
|
|
||||||
case 'C':
|
|
||||||
origin[2] -= move;
|
|
||||||
[forge updateCamera];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,257 +0,0 @@
|
||||||
/*
|
|
||||||
Clipper.h
|
|
||||||
|
|
||||||
Clipping plane class
|
|
||||||
|
|
||||||
Copyright (C) 2001 Jeff Teunissen <deek@d2dc.net>
|
|
||||||
|
|
||||||
This program 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.
|
|
||||||
|
|
||||||
This program 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 this program; if not, write to:
|
|
||||||
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "Config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <QF/mathlib.h>
|
|
||||||
#include <QF/bspfile.h>
|
|
||||||
|
|
||||||
#import <AppKit/NSGraphics.h>
|
|
||||||
#import <AppKit/DPSOperators.h>
|
|
||||||
|
|
||||||
#import "CameraView.h"
|
|
||||||
#import "Clipper.h"
|
|
||||||
#import "Forge.h"
|
|
||||||
#import "Map.h"
|
|
||||||
#import "SetBrush.h"
|
|
||||||
#import "XYView.h"
|
|
||||||
#import "ZView.h"
|
|
||||||
|
|
||||||
Clipper *clipper;
|
|
||||||
|
|
||||||
@implementation Clipper
|
|
||||||
|
|
||||||
- init
|
|
||||||
{
|
|
||||||
[super init];
|
|
||||||
clipper = self;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) hide
|
|
||||||
{
|
|
||||||
int oldnum;
|
|
||||||
|
|
||||||
oldnum = num;
|
|
||||||
num = 0;
|
|
||||||
return (oldnum > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
- flipNormal
|
|
||||||
{
|
|
||||||
vec3_t temp;
|
|
||||||
|
|
||||||
switch (num) {
|
|
||||||
case 2:
|
|
||||||
VectorCopy (pos[0], temp);
|
|
||||||
VectorCopy (pos[1], pos[0]);
|
|
||||||
VectorCopy (temp, pos[1]);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
VectorCopy (pos[0], temp);
|
|
||||||
VectorCopy (pos[2], pos[0]);
|
|
||||||
VectorCopy (temp, pos[2]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NSLog (@"No clipping plane");
|
|
||||||
NSBeep ();
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) getFace: (face_t *) f
|
|
||||||
{
|
|
||||||
vec3_t v1, v2, norm;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
VectorCopy (vec3_origin, plane.normal);
|
|
||||||
plane.dist = 0;
|
|
||||||
if (num < 2)
|
|
||||||
return NO;
|
|
||||||
if (num == 2)
|
|
||||||
{
|
|
||||||
VectorCopy (pos[0], pos[2]);
|
|
||||||
pos[2][2] += 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0 ; i<3 ; i++)
|
|
||||||
VectorCopy (pos[i], f->planepts[i]);
|
|
||||||
|
|
||||||
VectorSubtract (pos[2], pos[0], v1);
|
|
||||||
VectorSubtract (pos[1], pos[0], v2);
|
|
||||||
|
|
||||||
CrossProduct (v1, v2, norm);
|
|
||||||
VectorNormalize (norm);
|
|
||||||
|
|
||||||
if ( !norm[0] && !norm[1] && !norm[2] )
|
|
||||||
return NO;
|
|
||||||
|
|
||||||
[texturepalette_i setTextureDef: &f->texture];
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
XYClick
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
- XYClick: (NSPoint) pt
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
vec3_t new;
|
|
||||||
|
|
||||||
new[0] = [xyView snapToGrid: pt.x];
|
|
||||||
new[1] = [xyView snapToGrid: pt.y];
|
|
||||||
new[2] = [map currentMinZ];
|
|
||||||
|
|
||||||
// see if a point is already there
|
|
||||||
for (i=0 ; i<num ; i++) {
|
|
||||||
if (new[0] == pos[i][0] && new[1] == pos[i][1]) {
|
|
||||||
if (pos[i][2] == [map currentMinZ])
|
|
||||||
pos[i][2] = [map currentMaxZ];
|
|
||||||
else
|
|
||||||
pos[i][2] = [map currentMinZ];
|
|
||||||
[forge updateAll];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (num == 3)
|
|
||||||
num = 0;
|
|
||||||
|
|
||||||
VectorCopy (new, pos[num]);
|
|
||||||
num++;
|
|
||||||
|
|
||||||
[forge updateAll];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
XYDrag
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
- (BOOL) XYDrag: (NSPoint *) pt
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0 ; i<3 ; i++) {
|
|
||||||
if (fabs(pt->x - pos[i][0] > 10) || fabs(pt->y - pos[i][1] > 10))
|
|
||||||
continue; // drag this point
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ZClick: (NSPoint) pt
|
|
||||||
{
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
- carve
|
|
||||||
{
|
|
||||||
[map makeSelectedPerform: @selector(carveByClipper)];
|
|
||||||
num = 0;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (void) cameraDrawSelf
|
|
||||||
{
|
|
||||||
vec3_t mid;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
linecolor (1, 0.5, 0);
|
|
||||||
|
|
||||||
for (i = 0; i < num; i++) {
|
|
||||||
VectorCopy (pos[i], mid);
|
|
||||||
mid[0] -= 8;
|
|
||||||
mid[1] -= 8;
|
|
||||||
CameraMoveto (mid);
|
|
||||||
mid[0] += 16;
|
|
||||||
mid[1] += 16;
|
|
||||||
CameraLineto (mid);
|
|
||||||
|
|
||||||
VectorCopy (pos[i], mid);
|
|
||||||
mid[0] -= 8;
|
|
||||||
mid[1] += 8;
|
|
||||||
CameraMoveto (mid);
|
|
||||||
mid[0] += 16;
|
|
||||||
mid[1] -= 16;
|
|
||||||
CameraLineto (mid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) xyDrawSelf
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char text[8];
|
|
||||||
|
|
||||||
PSsetrgbcolor (1, 0.5, 0);
|
|
||||||
PSselectfont ("Helvetica-Medium", 10 / [xyView currentScale]);
|
|
||||||
PSrotate (0);
|
|
||||||
|
|
||||||
for (i = 0; i < num; i++) {
|
|
||||||
PSmoveto (pos[i][0] - 4, pos[i][1] - 4);
|
|
||||||
sprintf (text, "%i", i);
|
|
||||||
PSshow (text);
|
|
||||||
PSstroke ();
|
|
||||||
PSarc (pos[i][0], pos[i][1], 10, 0, 360);
|
|
||||||
PSstroke ();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) zDrawSelf
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char text[8];
|
|
||||||
|
|
||||||
PSsetrgbcolor (1, 0.5, 0);
|
|
||||||
PSselectfont ("Helvetica-Medium", 10 / [zView currentScale]);
|
|
||||||
PSrotate (0);
|
|
||||||
|
|
||||||
for (i = 0; i < num; i++) {
|
|
||||||
PSmoveto ((-28 + (i * 8)) - 4, pos[i][2] - 4);
|
|
||||||
sprintf (text, "%i", i);
|
|
||||||
PSshow (text);
|
|
||||||
PSstroke ();
|
|
||||||
PSarc ((-28 + (i * 8)), pos[i][2], 10, 0, 360);
|
|
||||||
PSstroke ();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,579 +0,0 @@
|
||||||
|
|
||||||
#import "qedefs.h"
|
|
||||||
|
|
||||||
@implementation Dict
|
|
||||||
|
|
||||||
- init
|
|
||||||
{
|
|
||||||
[super initCount: 0
|
|
||||||
elementSize: sizeof (dict_t)
|
|
||||||
description: NULL];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- print
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
dict_t *d;
|
|
||||||
|
|
||||||
for (i=0 ; i<numElements ; i++)
|
|
||||||
{
|
|
||||||
d = [self elementAt: i];
|
|
||||||
printf ("%s : %s\n",d->key, d->value);
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===========
|
|
||||||
copyFromZone
|
|
||||||
|
|
||||||
JDC
|
|
||||||
===========
|
|
||||||
*/
|
|
||||||
- copyFromZone:(NXZone *)zone
|
|
||||||
{
|
|
||||||
id new;
|
|
||||||
int i;
|
|
||||||
dict_t *d;
|
|
||||||
char *old;
|
|
||||||
|
|
||||||
new = [super copyFromZone: zone];
|
|
||||||
for (i=0 ; i<numElements ; i++)
|
|
||||||
{
|
|
||||||
d = [self elementAt: i];
|
|
||||||
old = d->key;
|
|
||||||
d->key = malloc(strlen(old)+1);
|
|
||||||
strcpy (d->key, old);
|
|
||||||
|
|
||||||
old = d->value;
|
|
||||||
d->value = malloc(strlen(old)+1);
|
|
||||||
strcpy (d->value, old);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
- initFromFile:(FILE *)fp
|
|
||||||
{
|
|
||||||
[self init];
|
|
||||||
return [self parseBraceBlock:fp];
|
|
||||||
}
|
|
||||||
|
|
||||||
//===============================================
|
|
||||||
//
|
|
||||||
// Dictionary pair functions
|
|
||||||
//
|
|
||||||
//===============================================
|
|
||||||
|
|
||||||
//
|
|
||||||
// Write a { } block out to a FILE*
|
|
||||||
//
|
|
||||||
- writeBlockTo:(FILE *)fp
|
|
||||||
{
|
|
||||||
int max;
|
|
||||||
int i;
|
|
||||||
dict_t *d;
|
|
||||||
|
|
||||||
fprintf (fp, "{\n");
|
|
||||||
max = [super count];
|
|
||||||
for (i = 0; i < max; i++) {
|
|
||||||
d = [super elementAt: i];
|
|
||||||
fprintf (fp, "\t{\"%s\"\t\"%s\"}\n", d->key, d->value);
|
|
||||||
}
|
|
||||||
fprintf(fp,"}\n");
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Write a single { } block out
|
|
||||||
//
|
|
||||||
- writeFile: (char *) path
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
if (!(fp = fopen(path,"w+t"))) {
|
|
||||||
printf ("Error writing %s!\n", path);
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf ("Writing dictionary file %s.\n", path);
|
|
||||||
fprintf (fp, "// QE_Project file %s\n", path);
|
|
||||||
|
|
||||||
[self writeBlockTo: fp];
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===============================================
|
|
||||||
//
|
|
||||||
// Utility methods
|
|
||||||
//
|
|
||||||
//===============================================
|
|
||||||
|
|
||||||
//
|
|
||||||
// Find a keyword in storage
|
|
||||||
// Returns * to dict_t, otherwise NULL
|
|
||||||
//
|
|
||||||
- (dict_t *) findKeyword:(char *)key
|
|
||||||
{
|
|
||||||
int max;
|
|
||||||
int i;
|
|
||||||
dict_t *d;
|
|
||||||
|
|
||||||
max = [super count];
|
|
||||||
for (i = 0;i < max;i++)
|
|
||||||
{
|
|
||||||
d = [super elementAt:i];
|
|
||||||
if (!strcmp(d->key,key))
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Change a keyword's string
|
|
||||||
//
|
|
||||||
- changeStringFor:(char *)key to:(char *)value
|
|
||||||
{
|
|
||||||
dict_t *d;
|
|
||||||
dict_t newd;
|
|
||||||
|
|
||||||
d = [self findKeyword:key];
|
|
||||||
if (d != NULL)
|
|
||||||
{
|
|
||||||
free(d->value);
|
|
||||||
d->value = malloc(strlen(value)+1);
|
|
||||||
strcpy(d->value,value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newd.key = malloc(strlen(key)+1);
|
|
||||||
strcpy(newd.key,key);
|
|
||||||
newd.value = malloc(strlen(value)+1);
|
|
||||||
strcpy(newd.value,value);
|
|
||||||
[self addElement:&newd];
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Search for keyword, return the string *
|
|
||||||
//
|
|
||||||
- (char *)getStringFor:(char *)name
|
|
||||||
{
|
|
||||||
dict_t *d;
|
|
||||||
|
|
||||||
d = [self findKeyword:name];
|
|
||||||
if (d != NULL)
|
|
||||||
return d->value;
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Search for keyword, return the value
|
|
||||||
//
|
|
||||||
- (unsigned int)getValueFor:(char *)name
|
|
||||||
{
|
|
||||||
dict_t *d;
|
|
||||||
|
|
||||||
d = [self findKeyword:name];
|
|
||||||
if (d != NULL)
|
|
||||||
return atol(d->value);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Return # of units in keyword's value
|
|
||||||
//
|
|
||||||
- (int) getValueUnits:(char *)key
|
|
||||||
{
|
|
||||||
id temp;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
temp = [self parseMultipleFrom:key];
|
|
||||||
count = [temp count];
|
|
||||||
[temp free];
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Convert List to string
|
|
||||||
//
|
|
||||||
- (char *)convertListToString:(id)list
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int max;
|
|
||||||
char tempstr[4096];
|
|
||||||
char *s;
|
|
||||||
char *newstr;
|
|
||||||
|
|
||||||
max = [list count];
|
|
||||||
tempstr[0] = 0;
|
|
||||||
for (i = 0;i < max;i++)
|
|
||||||
{
|
|
||||||
s = [list elementAt:i];
|
|
||||||
strcat(tempstr,s);
|
|
||||||
strcat(tempstr," ");
|
|
||||||
}
|
|
||||||
newstr = malloc(strlen(tempstr)+1);
|
|
||||||
strcpy(newstr,tempstr);
|
|
||||||
|
|
||||||
return newstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// JDC: I wrote this to simplify removing vectors
|
|
||||||
//
|
|
||||||
- removeKeyword:(char *)key
|
|
||||||
{
|
|
||||||
dict_t *d;
|
|
||||||
|
|
||||||
d = [self findKeyword:key];
|
|
||||||
if (d == NULL)
|
|
||||||
return self;
|
|
||||||
[self removeElementAt:d - (dict_t*)dataPtr];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Delete string from keyword's value
|
|
||||||
//
|
|
||||||
- delString:(char *)string fromValue:(char *)key
|
|
||||||
{
|
|
||||||
id temp;
|
|
||||||
int count;
|
|
||||||
int i;
|
|
||||||
char *s;
|
|
||||||
dict_t *d;
|
|
||||||
|
|
||||||
d = [self findKeyword:key];
|
|
||||||
if (d == NULL)
|
|
||||||
return NULL;
|
|
||||||
temp = [self parseMultipleFrom:key];
|
|
||||||
count = [temp count];
|
|
||||||
for (i = 0;i < count;i++)
|
|
||||||
{
|
|
||||||
s = [temp elementAt:i];
|
|
||||||
if (!strcmp(s,string))
|
|
||||||
{
|
|
||||||
[temp removeElementAt:i];
|
|
||||||
free(d->value);
|
|
||||||
d->value = [self convertListToString:temp];
|
|
||||||
[temp free];
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Add string to keyword's value
|
|
||||||
//
|
|
||||||
- addString:(char *)string toValue:(char *)key
|
|
||||||
{
|
|
||||||
char *newstr;
|
|
||||||
char spacing[] = "\t";
|
|
||||||
dict_t *d;
|
|
||||||
|
|
||||||
d = [self findKeyword:key];
|
|
||||||
if (d == NULL)
|
|
||||||
return NULL;
|
|
||||||
newstr = malloc(strlen(string) + strlen(d->value) + strlen(spacing) + 1);
|
|
||||||
strcpy(newstr,d->value);
|
|
||||||
strcat(newstr,spacing);
|
|
||||||
strcat(newstr,string);
|
|
||||||
free(d->value);
|
|
||||||
d->value = newstr;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===============================================
|
|
||||||
//
|
|
||||||
// Use these for multiple parameters in a keyword value
|
|
||||||
//
|
|
||||||
//===============================================
|
|
||||||
char *searchStr;
|
|
||||||
char item[4096];
|
|
||||||
|
|
||||||
- setupMultiple:(char *)value
|
|
||||||
{
|
|
||||||
searchStr = value;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (char *)getNextParameter
|
|
||||||
{
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
if (!searchStr)
|
|
||||||
return NULL;
|
|
||||||
strcpy(item,searchStr);
|
|
||||||
s = FindWhitespcInBuffer(item);
|
|
||||||
if (!*s)
|
|
||||||
searchStr = NULL;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*s = 0;
|
|
||||||
searchStr = FindNonwhitespcInBuffer(s+1);
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Parses a keyvalue string & returns a Storage full of those items
|
|
||||||
//
|
|
||||||
- (id) parseMultipleFrom:(char *)key
|
|
||||||
{
|
|
||||||
#define ITEMSIZE 128
|
|
||||||
id stuff;
|
|
||||||
char string[ITEMSIZE];
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
s = [self getStringFor:key];
|
|
||||||
if (s == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
stuff = [[Storage alloc]
|
|
||||||
initCount:0
|
|
||||||
elementSize:ITEMSIZE
|
|
||||||
description:NULL];
|
|
||||||
|
|
||||||
[self setupMultiple:s];
|
|
||||||
while((s = [self getNextParameter]))
|
|
||||||
{
|
|
||||||
bzero(string,ITEMSIZE);
|
|
||||||
strcpy(string,s);
|
|
||||||
[stuff addElement:string];
|
|
||||||
}
|
|
||||||
|
|
||||||
return stuff;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===============================================
|
|
||||||
//
|
|
||||||
// Dictionary pair parsing
|
|
||||||
//
|
|
||||||
//===============================================
|
|
||||||
|
|
||||||
//
|
|
||||||
// parse all keyword/value pairs within { } 's
|
|
||||||
//
|
|
||||||
- (id) parseBraceBlock:(FILE *)fp
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
dict_t pair;
|
|
||||||
char string[1024];
|
|
||||||
|
|
||||||
c = FindBrace(fp);
|
|
||||||
if (c == -1)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
while((c = FindBrace(fp)) != '}')
|
|
||||||
{
|
|
||||||
if (c == -1)
|
|
||||||
return NULL;
|
|
||||||
// c = FindNonwhitespc(fp);
|
|
||||||
// if (c == -1)
|
|
||||||
// return NULL;
|
|
||||||
// CopyUntilWhitespc(fp,string);
|
|
||||||
|
|
||||||
// JDC: fixed to allow quoted keys
|
|
||||||
c = FindNonwhitespc(fp);
|
|
||||||
if (c == -1)
|
|
||||||
return NULL;
|
|
||||||
c = fgetc(fp);
|
|
||||||
if ( c == '\"')
|
|
||||||
CopyUntilQuote(fp,string);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ungetc (c,fp);
|
|
||||||
CopyUntilWhitespc(fp,string);
|
|
||||||
}
|
|
||||||
|
|
||||||
pair.key = malloc(strlen(string)+1);
|
|
||||||
strcpy(pair.key,string);
|
|
||||||
|
|
||||||
c = FindQuote(fp);
|
|
||||||
CopyUntilQuote(fp,string);
|
|
||||||
pair.value = malloc(strlen(string)+1);
|
|
||||||
strcpy(pair.value,string);
|
|
||||||
|
|
||||||
[super addElement:&pair];
|
|
||||||
c = FindBrace(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
//===============================================
|
|
||||||
//
|
|
||||||
// C routines for string parsing
|
|
||||||
//
|
|
||||||
//===============================================
|
|
||||||
int GetNextChar(FILE *fp)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
int c2;
|
|
||||||
|
|
||||||
c = getc(fp);
|
|
||||||
if (c == EOF)
|
|
||||||
return -1;
|
|
||||||
if (c == '/') // parse comments
|
|
||||||
{
|
|
||||||
c2 = getc(fp);
|
|
||||||
if (c2 == '/')
|
|
||||||
{
|
|
||||||
while((c2 = getc(fp)) != '\n');
|
|
||||||
c = getc(fp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ungetc(c2,fp);
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CopyUntilWhitespc(FILE *fp,char *buffer)
|
|
||||||
{
|
|
||||||
int count = 800;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
while(count--)
|
|
||||||
{
|
|
||||||
c = GetNextChar(fp);
|
|
||||||
if (c == EOF)
|
|
||||||
return;
|
|
||||||
if (c <= ' ')
|
|
||||||
{
|
|
||||||
*buffer = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*buffer++ = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CopyUntilQuote(FILE *fp,char *buffer)
|
|
||||||
{
|
|
||||||
int count = 800;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
while(count--)
|
|
||||||
{
|
|
||||||
c = GetNextChar(fp);
|
|
||||||
if (c == EOF)
|
|
||||||
return;
|
|
||||||
if (c == '\"')
|
|
||||||
{
|
|
||||||
*buffer = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*buffer++ = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int FindBrace(FILE *fp)
|
|
||||||
{
|
|
||||||
int count = 800;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
while(count--)
|
|
||||||
{
|
|
||||||
c = GetNextChar(fp);
|
|
||||||
if (c == EOF)
|
|
||||||
return -1;
|
|
||||||
if (c == '{' ||
|
|
||||||
c == '}')
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FindQuote(FILE *fp)
|
|
||||||
{
|
|
||||||
int count = 800;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
while(count--)
|
|
||||||
{
|
|
||||||
c = GetNextChar(fp);
|
|
||||||
if (c == EOF)
|
|
||||||
return -1;
|
|
||||||
if (c == '\"')
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FindWhitespc(FILE *fp)
|
|
||||||
{
|
|
||||||
int count = 800;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
while(count--)
|
|
||||||
{
|
|
||||||
c = GetNextChar(fp);
|
|
||||||
if (c == EOF)
|
|
||||||
return -1;
|
|
||||||
if (c <= ' ')
|
|
||||||
{
|
|
||||||
ungetc(c,fp);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FindNonwhitespc(FILE *fp)
|
|
||||||
{
|
|
||||||
int count = 800;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
while(count--)
|
|
||||||
{
|
|
||||||
c = GetNextChar(fp);
|
|
||||||
if (c == EOF)
|
|
||||||
return -1;
|
|
||||||
if (c > ' ')
|
|
||||||
{
|
|
||||||
ungetc(c,fp);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *FindWhitespcInBuffer(char *buffer)
|
|
||||||
{
|
|
||||||
int count = 1000;
|
|
||||||
char *b = buffer;
|
|
||||||
|
|
||||||
while(count--)
|
|
||||||
if (*b <= ' ')
|
|
||||||
return b;
|
|
||||||
else
|
|
||||||
b++;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *FindNonwhitespcInBuffer(char *buffer)
|
|
||||||
{
|
|
||||||
int count = 1000;
|
|
||||||
char *b = buffer;
|
|
||||||
|
|
||||||
while(count--)
|
|
||||||
if (*b > ' ')
|
|
||||||
return b;
|
|
||||||
else
|
|
||||||
b++;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
|
@ -1,485 +0,0 @@
|
||||||
|
|
||||||
#import "Entity.h"
|
|
||||||
|
|
||||||
@implementation Entity
|
|
||||||
|
|
||||||
vec3_t bad_mins = {-8, -8, -8};
|
|
||||||
vec3_t bad_maxs = {8, 8, 8};
|
|
||||||
|
|
||||||
- createFixedBrush: (vec3_t)org
|
|
||||||
{
|
|
||||||
vec3_t emins, emaxs;
|
|
||||||
float *v, *v2, *color;
|
|
||||||
id new;
|
|
||||||
texturedef_t td;
|
|
||||||
|
|
||||||
// get class
|
|
||||||
new = [entity_classes_i classForName: [self valueForQKey: "classname"]];
|
|
||||||
if (new)
|
|
||||||
{
|
|
||||||
v = [new mins];
|
|
||||||
v2 = [new maxs];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v = bad_mins;
|
|
||||||
v2 = bad_maxs;
|
|
||||||
}
|
|
||||||
|
|
||||||
color = [new drawColor];
|
|
||||||
|
|
||||||
modifiable = NO;
|
|
||||||
memset(&td,0,sizeof(td));
|
|
||||||
strcpy (td.texture,"entity");
|
|
||||||
|
|
||||||
VectorAdd (org, v, emins);
|
|
||||||
VectorAdd (org, v2, emaxs);
|
|
||||||
new = [[SetBrush alloc] initOwner: self mins:emins maxs:emaxs
|
|
||||||
texture: &td];
|
|
||||||
[new setEntityColor: color];
|
|
||||||
|
|
||||||
[self addObject: new];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- copyFromZone:(NSZone *)zone
|
|
||||||
{
|
|
||||||
id new, nb;
|
|
||||||
epair_t *e;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
new = [[Entity alloc] init];
|
|
||||||
[new setModifiable: modifiable];
|
|
||||||
|
|
||||||
for (e = epairs; e; e = e->next) {
|
|
||||||
if (strncmp (e->key, "target", 6)) // don't copy target and targetname fields
|
|
||||||
[new setKey: e->key toValue: e->value];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < [self count]; i++) {
|
|
||||||
nb = [[self objectAtIndex: i] copy];
|
|
||||||
[nb setParent: new];
|
|
||||||
[new addObject: nb];
|
|
||||||
}
|
|
||||||
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
- initClass: (char *)classname
|
|
||||||
{
|
|
||||||
id new;
|
|
||||||
esize_t esize;
|
|
||||||
char value[80];
|
|
||||||
vec3_t min, max;
|
|
||||||
float *v;
|
|
||||||
|
|
||||||
[super init];
|
|
||||||
|
|
||||||
modifiable = YES;
|
|
||||||
|
|
||||||
[self setKey: "classname" toValue:classname];
|
|
||||||
|
|
||||||
// get class
|
|
||||||
new = [entity_classes_i classForName: [self valueForQKey: "classname"]];
|
|
||||||
if (!new)
|
|
||||||
esize = esize_model;
|
|
||||||
else
|
|
||||||
esize = [new esize];
|
|
||||||
|
|
||||||
// create a brush if needed
|
|
||||||
if (esize == esize_fixed)
|
|
||||||
{
|
|
||||||
v = [new mins];
|
|
||||||
[[map_i selectedBrush] getMins: min maxs: max];
|
|
||||||
VectorSubtract (min, v, min);
|
|
||||||
|
|
||||||
sprintf (value, "%i %i %i",(int)min[0], (int)min[1], (int)min[2]);
|
|
||||||
[self setKey:"origin" toValue: value];
|
|
||||||
|
|
||||||
[self createFixedBrush: min];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
modifiable = YES;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (oneway void) release
|
|
||||||
{
|
|
||||||
epair_t *e, *n;
|
|
||||||
|
|
||||||
for (e = epairs; e; e = n) {
|
|
||||||
n = e->next;
|
|
||||||
free (e);
|
|
||||||
}
|
|
||||||
[super release];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) modifiable
|
|
||||||
{
|
|
||||||
return modifiable;
|
|
||||||
}
|
|
||||||
|
|
||||||
- setModifiable: (BOOL) m
|
|
||||||
{
|
|
||||||
modifiable = m;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) removeObject: (id) anObject
|
|
||||||
{
|
|
||||||
[super removeObject: anObject];
|
|
||||||
|
|
||||||
if ([self count])
|
|
||||||
return;
|
|
||||||
|
|
||||||
// the entity is empty, so remove the entire thing
|
|
||||||
|
|
||||||
if (self == [map_i objectAtIndex: 0]) // never remove the world
|
|
||||||
return;
|
|
||||||
|
|
||||||
[map_i removeObject: self];
|
|
||||||
[self release];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (char *)valueForQKey: (char *)k
|
|
||||||
{
|
|
||||||
epair_t *e;
|
|
||||||
static char ret[64];
|
|
||||||
|
|
||||||
for (e=epairs ; e ; e=e->next)
|
|
||||||
if (!strcmp(k,e->key))
|
|
||||||
{
|
|
||||||
strcpy (ret, e->value);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
- getVector: (vec3_t)v forKey: (char *)k
|
|
||||||
{
|
|
||||||
char *c;
|
|
||||||
|
|
||||||
c = [self valueForQKey: k];
|
|
||||||
|
|
||||||
v[0] = v[1] = v[2] = 0;
|
|
||||||
|
|
||||||
sscanf (c, "%f %f %f", &v[0], &v[1], &v[2]);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- print
|
|
||||||
{
|
|
||||||
epair_t *e;
|
|
||||||
|
|
||||||
for (e=epairs ; e ; e=e->next)
|
|
||||||
printf ("%20s : %20s\n",e->key, e->value);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- setKey:(char *)k toValue:(char *)v
|
|
||||||
{
|
|
||||||
epair_t *e;
|
|
||||||
|
|
||||||
if (strlen(k) > MAX_KEY)
|
|
||||||
Error ("setKey: %s > MAX_KEY", k);
|
|
||||||
if (strlen(v) > MAX_VALUE)
|
|
||||||
Error ("setKey: %s > MAX_VALUE", v);
|
|
||||||
|
|
||||||
while (*k && *k <= ' ')
|
|
||||||
k++;
|
|
||||||
if (!*k)
|
|
||||||
return self; // don't set NULL values
|
|
||||||
|
|
||||||
for (e=epairs ; e ; e=e->next)
|
|
||||||
if (!strcmp(k,e->key))
|
|
||||||
{
|
|
||||||
memset (e->value, 0, sizeof(e->value));
|
|
||||||
strcpy (e->value, v);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = malloc (sizeof(epair_t));
|
|
||||||
memset (e, 0, sizeof(epair_t));
|
|
||||||
|
|
||||||
strcpy (e->key, k);
|
|
||||||
strcpy (e->value, v);
|
|
||||||
e->next = epairs;
|
|
||||||
epairs = e;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int)numPairs
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
epair_t *e;
|
|
||||||
|
|
||||||
i=0;
|
|
||||||
for (e=epairs ; e ; e=e->next)
|
|
||||||
i++;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (epair_t *)epairs
|
|
||||||
{
|
|
||||||
return epairs;
|
|
||||||
}
|
|
||||||
|
|
||||||
- removeKeyPair: (char *)key
|
|
||||||
{
|
|
||||||
epair_t *e, *e2;
|
|
||||||
|
|
||||||
if (!epairs)
|
|
||||||
return self;
|
|
||||||
e = epairs;
|
|
||||||
if (!strcmp(e->key, key))
|
|
||||||
{
|
|
||||||
epairs = e->next;
|
|
||||||
free (e);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; e ; e=e->next)
|
|
||||||
{
|
|
||||||
if (e->next && !strcmp(e->next->key, key))
|
|
||||||
{
|
|
||||||
e2 = e->next;
|
|
||||||
e->next = e2->next;
|
|
||||||
free (e2);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf ("WARNING: removeKeyPair: %s not found\n", key);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
targetname
|
|
||||||
|
|
||||||
If the entity does not have a "targetname" key, a unique one is generated
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
- (char *)targetname
|
|
||||||
{
|
|
||||||
char *t;
|
|
||||||
int i, count;
|
|
||||||
id ent;
|
|
||||||
int tval, maxt;
|
|
||||||
char name[20];
|
|
||||||
|
|
||||||
t = [self valueForQKey: "targetname"];
|
|
||||||
if (t && t[0])
|
|
||||||
return t;
|
|
||||||
|
|
||||||
// make a unique name of the form t<number>
|
|
||||||
count = [map_i count];
|
|
||||||
maxt = 0;
|
|
||||||
for (i=1 ; i<count ; i++)
|
|
||||||
{
|
|
||||||
ent = [map_i objectAtIndex: i];
|
|
||||||
t = [ent valueForQKey: "targetname"];
|
|
||||||
if (!t || t[0] != 't')
|
|
||||||
continue;
|
|
||||||
tval = atoi (t+1);
|
|
||||||
if (tval > maxt)
|
|
||||||
maxt = tval;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf (name,"t%i",maxt+1);
|
|
||||||
|
|
||||||
[self setKey: "targetname" toValue: name];
|
|
||||||
|
|
||||||
return [self valueForQKey: "targetname"]; // so it's not on the stack
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
FILE METHODS
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
int nument;
|
|
||||||
|
|
||||||
- initFromTokens
|
|
||||||
{
|
|
||||||
char key[MAXTOKEN];
|
|
||||||
id eclass, brush;
|
|
||||||
char *spawn;
|
|
||||||
vec3_t emins, emaxs;
|
|
||||||
vec3_t org;
|
|
||||||
texturedef_t td;
|
|
||||||
esize_t esize;
|
|
||||||
int i, c;
|
|
||||||
float *color;
|
|
||||||
|
|
||||||
[self init];
|
|
||||||
|
|
||||||
if (!GetToken (true))
|
|
||||||
{
|
|
||||||
[self release];
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (token, "{") )
|
|
||||||
Error ("initFromFileP: { not found");
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (!GetToken (true))
|
|
||||||
break;
|
|
||||||
if (!strcmp (token, "}") )
|
|
||||||
break;
|
|
||||||
if (!strcmp (token, "{") )
|
|
||||||
{ // read a brush
|
|
||||||
brush = [[SetBrush alloc] initFromTokens: self];
|
|
||||||
[self addObject: brush];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // read a key / value pair
|
|
||||||
strcpy (key, token);
|
|
||||||
GetToken (false);
|
|
||||||
[self setKey: key toValue:token];
|
|
||||||
}
|
|
||||||
} while (1);
|
|
||||||
|
|
||||||
nument++;
|
|
||||||
|
|
||||||
// get class
|
|
||||||
spawn = [self valueForQKey: "classname"];
|
|
||||||
eclass = [entity_classes_i classForName: spawn];
|
|
||||||
|
|
||||||
esize = [eclass esize];
|
|
||||||
|
|
||||||
[self getVector: org forKey: "origin"];
|
|
||||||
|
|
||||||
if ([self count] && esize != esize_model)
|
|
||||||
{
|
|
||||||
printf ("WARNING:Entity with brushes and wrong model type\n");
|
|
||||||
[self removeAllObjects];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (![self count] && esize == esize_model)
|
|
||||||
{
|
|
||||||
printf ("WARNING:Entity with no brushes and esize_model\n");
|
|
||||||
[texturepalette_i setTextureDef: &td];
|
|
||||||
for (i=0 ; i<3 ; i++)
|
|
||||||
{
|
|
||||||
emins[i] = org[i] - 8;
|
|
||||||
emaxs[i] = org[i] + 8;
|
|
||||||
}
|
|
||||||
brush = [[SetBrush alloc] initOwner: self mins:emins maxs:emaxs
|
|
||||||
texture: &td];
|
|
||||||
[self addObject: brush];
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a brush if needed
|
|
||||||
if (esize == esize_fixed)
|
|
||||||
[self createFixedBrush: org];
|
|
||||||
else
|
|
||||||
modifiable = YES;
|
|
||||||
|
|
||||||
// set all the brush colors
|
|
||||||
color = [eclass drawColor];
|
|
||||||
|
|
||||||
c = [self count];
|
|
||||||
for (i=0 ; i<c ; i++)
|
|
||||||
{
|
|
||||||
brush = [self objectAtIndex: i];
|
|
||||||
[brush setEntityColor: color];
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- writeToFILE: (FILE *)f region:(BOOL)reg;
|
|
||||||
{
|
|
||||||
epair_t *e;
|
|
||||||
int i;
|
|
||||||
id new;
|
|
||||||
char value[80];
|
|
||||||
vec3_t mins, maxs, org;
|
|
||||||
float *v;
|
|
||||||
BOOL temporg;
|
|
||||||
char oldang[80];
|
|
||||||
|
|
||||||
temporg = NO;
|
|
||||||
if (reg)
|
|
||||||
{
|
|
||||||
if ( !strcmp ([self valueForQKey: "classname"], "info_player_start") )
|
|
||||||
{ // move the playerstart temporarily to the camera position
|
|
||||||
temporg = YES;
|
|
||||||
strcpy (oldang, [self valueForQKey: "angle"]);
|
|
||||||
sprintf (value, "%i", (int)([cameraview_i yawAngle]*180/M_PI));
|
|
||||||
[self setKey: "angle" toValue: value];
|
|
||||||
}
|
|
||||||
else if ( self != [map_i objectAtIndex: 0]
|
|
||||||
&& [[self objectAtIndex: 0] regioned] )
|
|
||||||
return self; // skip the entire entity definition
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf (f,"{\n");
|
|
||||||
|
|
||||||
// set an origin epair
|
|
||||||
if (!modifiable)
|
|
||||||
{
|
|
||||||
[[self objectAtIndex: 0] getMins: mins maxs: maxs];
|
|
||||||
if (temporg)
|
|
||||||
{
|
|
||||||
[cameraview_i getOrigin: mins];
|
|
||||||
mins[0] -= 16;
|
|
||||||
mins[1] -= 16;
|
|
||||||
mins[2] -= 48;
|
|
||||||
}
|
|
||||||
new = [entity_classes_i classForName:
|
|
||||||
[self valueForQKey: "classname"]];
|
|
||||||
if (new)
|
|
||||||
v = [new mins];
|
|
||||||
else
|
|
||||||
v = vec3_origin;
|
|
||||||
|
|
||||||
VectorSubtract (mins, v, org);
|
|
||||||
sprintf (value, "%i %i %i",(int)org[0], (int)org[1], (int)org[2]);
|
|
||||||
[self setKey:"origin" toValue: value];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (e=epairs ; e ; e=e->next)
|
|
||||||
fprintf (f,"\"%s\"\t\"%s\"\n", e->key, e->value);
|
|
||||||
|
|
||||||
// fixed size entities don't save out brushes
|
|
||||||
if ( modifiable )
|
|
||||||
{
|
|
||||||
for (i=0 ; i < [self count]; i++)
|
|
||||||
[[self objectAtIndex: i] writeToFILE: f region: reg];
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf (f,"}\n");
|
|
||||||
|
|
||||||
if (temporg)
|
|
||||||
[self setKey: "angle" toValue: oldang];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
INTERACTION
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,119 +0,0 @@
|
||||||
#import "qedefs.h"
|
|
||||||
|
|
||||||
@implementation EntityArray
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
insertEC:
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
- (void)insertEC: ec
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
name = [ec classname];
|
|
||||||
for (i=0 ; i<[self count] ; i++)
|
|
||||||
{
|
|
||||||
if (strcasecmp (name, [[self objectAtIndex: i] classname]) < 0)
|
|
||||||
{
|
|
||||||
[self insertObject: ec atIndex:i];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[self addObject: ec];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
scanFile
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
- (void)scanFile: (char *)filename
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
char *data;
|
|
||||||
id cl;
|
|
||||||
int i;
|
|
||||||
char path[1024];
|
|
||||||
|
|
||||||
sprintf (path,"%s/%s", source_path, filename);
|
|
||||||
|
|
||||||
size = LoadFile (path, (void *)&data);
|
|
||||||
|
|
||||||
for (i=0 ; i<size ; i++)
|
|
||||||
if (!strncmp(data+i, "/*QUAKED",8))
|
|
||||||
{
|
|
||||||
cl = [[EntityClass alloc] initFromText: data+i];
|
|
||||||
if (cl)
|
|
||||||
[self insertEC: cl];
|
|
||||||
else
|
|
||||||
printf ("Error parsing: %s in %s\n",debugname, filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
free (data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
scanDirectory
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
- (void)scanDirectory
|
|
||||||
{
|
|
||||||
int count, i;
|
|
||||||
struct dirent **namelist, *ent;
|
|
||||||
|
|
||||||
[self removeAllObjects];
|
|
||||||
|
|
||||||
count = scandir(source_path, &namelist, NULL, NULL);
|
|
||||||
|
|
||||||
for (i=0 ; i<count ; i++)
|
|
||||||
{
|
|
||||||
ent = namelist[i];
|
|
||||||
if (strlen(ent->d_name) <= 3)
|
|
||||||
continue;
|
|
||||||
if (!strcmp (ent->d_name+strlen(ent->d_name)-3,".qc"))
|
|
||||||
[self scanFile: ent->d_name];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
id entity_classes_i;
|
|
||||||
|
|
||||||
|
|
||||||
- initForSourceDirectory: (char *)path
|
|
||||||
{
|
|
||||||
[super init];
|
|
||||||
|
|
||||||
source_path = path;
|
|
||||||
[self scanDirectory];
|
|
||||||
|
|
||||||
entity_classes_i = self;
|
|
||||||
|
|
||||||
nullclass = [[EntityClass alloc] initFromText:
|
|
||||||
"/*QUAKED UNKNOWN_CLASS (0 0.5 0) ?"];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id)classForName: (char *)name
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
id o;
|
|
||||||
|
|
||||||
for (i=0 ; i<[self count] ; i++)
|
|
||||||
{
|
|
||||||
o = [self objectAtIndex: i];
|
|
||||||
if (!strcmp (name,[o classname]) )
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullclass;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
|
@ -1,148 +0,0 @@
|
||||||
|
|
||||||
#import "qedefs.h"
|
|
||||||
|
|
||||||
@implementation EntityClass
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
the classname, color triple, and bounding box are parsed out of comments
|
|
||||||
A ? size means take the exact brush size.
|
|
||||||
|
|
||||||
(these are really comments, but a space has been added to shut the compiler up.)
|
|
||||||
|
|
||||||
/*QUAKED <classname> (0 0 0) ?
|
|
||||||
/*QUAKED <classname> (0 0 0) (-8 -8 -8) (8 8 8)
|
|
||||||
|
|
||||||
Flag names can follow the size description:
|
|
||||||
|
|
||||||
/*QUAKED func_door (0 .5 .8) ? START_OPEN STONE_SOUND DOOR_DONT_LINK GOLD_KEY SILVER_KEY
|
|
||||||
|
|
||||||
*/
|
|
||||||
char *debugname;
|
|
||||||
- initFromText: (char *)text
|
|
||||||
{
|
|
||||||
char *t;
|
|
||||||
int len;
|
|
||||||
int r, i;
|
|
||||||
char parms[256], *p;
|
|
||||||
|
|
||||||
[super init];
|
|
||||||
|
|
||||||
text += strlen("/*QUAKED ");
|
|
||||||
|
|
||||||
// grab the name
|
|
||||||
text = COM_Parse (text);
|
|
||||||
name = malloc (strlen(com_token)+1);
|
|
||||||
strcpy (name, com_token);
|
|
||||||
debugname = name;
|
|
||||||
|
|
||||||
// grab the color
|
|
||||||
r = sscanf (text," (%f %f %f)", &color[0], &color[1], &color[2]);
|
|
||||||
if (r != 3)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
while (*text != ')')
|
|
||||||
{
|
|
||||||
if (!*text)
|
|
||||||
return NULL;
|
|
||||||
text++;
|
|
||||||
}
|
|
||||||
text++;
|
|
||||||
|
|
||||||
// get the size
|
|
||||||
text = COM_Parse (text);
|
|
||||||
if (com_token[0] == '(')
|
|
||||||
{ // parse the size as two vectors
|
|
||||||
esize = esize_fixed;
|
|
||||||
r = sscanf (text,"%f %f %f) (%f %f %f)", &mins[0], &mins[1], &mins[2], &maxs[0], &maxs[1], &maxs[2]);
|
|
||||||
if (r != 6)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i=0 ; i<2 ; i++)
|
|
||||||
{
|
|
||||||
while (*text != ')')
|
|
||||||
{
|
|
||||||
if (!*text)
|
|
||||||
return NULL;
|
|
||||||
text++;
|
|
||||||
}
|
|
||||||
text++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // use the brushes
|
|
||||||
esize = esize_model;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the flags
|
|
||||||
|
|
||||||
|
|
||||||
// copy to the first /n
|
|
||||||
p = parms;
|
|
||||||
while (*text && *text != '\n')
|
|
||||||
*p++ = *text++;
|
|
||||||
*p = 0;
|
|
||||||
text++;
|
|
||||||
|
|
||||||
// any remaining words are parm flags
|
|
||||||
p = parms;
|
|
||||||
for (i=0 ; i<8 ; i++)
|
|
||||||
{
|
|
||||||
p = COM_Parse (p);
|
|
||||||
if (!p)
|
|
||||||
break;
|
|
||||||
strcpy (flagnames[i], com_token);
|
|
||||||
}
|
|
||||||
|
|
||||||
// find the length until close comment
|
|
||||||
for (t=text ; t[0] && !(t[0]=='*' && t[1]=='/') ; t++)
|
|
||||||
;
|
|
||||||
|
|
||||||
// copy the comment block out
|
|
||||||
len = t-text;
|
|
||||||
comments = malloc (len+1);
|
|
||||||
memcpy (comments, text, len);
|
|
||||||
comments[len] = 0;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (esize_t)esize
|
|
||||||
{
|
|
||||||
return esize;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (char *)classname
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (float *)mins
|
|
||||||
{
|
|
||||||
return mins;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (float *)maxs
|
|
||||||
{
|
|
||||||
return maxs;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (float *)drawColor
|
|
||||||
{
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (char *)comments
|
|
||||||
{
|
|
||||||
return comments;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (char *)flagName: (unsigned)flagnum
|
|
||||||
{
|
|
||||||
if (flagnum >= MAX_FLAGS)
|
|
||||||
Error ("EntityClass flagName: bad number");
|
|
||||||
return flagnames[flagnum];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
1029
tools/Forge/Forge.m
1029
tools/Forge/Forge.m
File diff suppressed because it is too large
Load diff
|
@ -1,18 +0,0 @@
|
||||||
#import <AppKit/AppKit.h>
|
|
||||||
|
|
||||||
NSString *commandOutput = @"/tmp/Forge/command.txt";
|
|
||||||
NSString *developerLogFile = @"/tmp/Forge/developer.log";
|
|
||||||
NSString *tempSaveFile = @"/tmp/Forge/temp.map";
|
|
||||||
NSString *autoSaveFile = @"/tmp/Forge/autoSave.map";
|
|
||||||
NSString *errorSaveFile = @"/tmp/Forge/errorSave.map";
|
|
||||||
|
|
||||||
int
|
|
||||||
main (int argc, char *argv[]) {
|
|
||||||
|
|
||||||
[NSApplication new];
|
|
||||||
if ([NSBundle loadNibNamed: @"Forge" owner: NSApp])
|
|
||||||
[NSApp run];
|
|
||||||
|
|
||||||
[NSApp release];
|
|
||||||
return 0;
|
|
||||||
}
|
|
1096
tools/Forge/Map.m
1096
tools/Forge/Map.m
File diff suppressed because it is too large
Load diff
|
@ -1,85 +0,0 @@
|
||||||
|
|
||||||
#import "qedefs.h"
|
|
||||||
|
|
||||||
@implementation PopScrollView
|
|
||||||
|
|
||||||
/*
|
|
||||||
====================
|
|
||||||
initFrame: button:
|
|
||||||
|
|
||||||
Initizes a scroll view with a button at it's lower right corner
|
|
||||||
====================
|
|
||||||
*/
|
|
||||||
|
|
||||||
- (id) initWithFrame: (NSRect) frameRect button1: (NSButton *) b1 button2: (NSButton *) b2
|
|
||||||
{
|
|
||||||
[super initWithFrame: frameRect];
|
|
||||||
|
|
||||||
[self addSubview: b1];
|
|
||||||
[self addSubview: b2];
|
|
||||||
|
|
||||||
button1 = b1;
|
|
||||||
button2 = b2;
|
|
||||||
|
|
||||||
[self setHasHorizontalScroller: YES];
|
|
||||||
[self setHasVerticalScroller: YES];
|
|
||||||
|
|
||||||
[self setBorderType: NSBezelBorder];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
tile
|
|
||||||
|
|
||||||
Adjust the size for the pop up scale menu
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
|
|
||||||
- (void) tile
|
|
||||||
{
|
|
||||||
NSRect scrollerframe;
|
|
||||||
NSRect buttonframe, buttonframe2;
|
|
||||||
NSRect newframe;
|
|
||||||
|
|
||||||
[super tile];
|
|
||||||
[button1 setFrame: buttonframe];
|
|
||||||
[button2 setFrame: buttonframe2];
|
|
||||||
[[self horizontalScroller] setFrame: scrollerframe];
|
|
||||||
|
|
||||||
newframe.origin.y = scrollerframe.origin.y;
|
|
||||||
newframe.origin.x = [self frame].size.width - buttonframe.size.width;
|
|
||||||
newframe.size.width = buttonframe.size.width;
|
|
||||||
newframe.size.height = scrollerframe.size.height;
|
|
||||||
scrollerframe.size.width -= newframe.size.width;
|
|
||||||
[button1 setFrame: newframe];
|
|
||||||
newframe.size.width = buttonframe2.size.width;
|
|
||||||
newframe.origin.x -= newframe.size.width;
|
|
||||||
[button2 setFrame: newframe];
|
|
||||||
scrollerframe.size.width -= newframe.size.width;
|
|
||||||
|
|
||||||
[[self horizontalScroller] setFrame: scrollerframe];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (void) resizeWithOldSuperviewSize: (NSSize) oldFrameSize
|
|
||||||
{
|
|
||||||
[super resizeWithOldSuperviewSize: oldFrameSize];
|
|
||||||
|
|
||||||
[[self documentView] newSuperBounds];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (BOOL) acceptsFirstResponder
|
|
||||||
{
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
|
@ -1,328 +0,0 @@
|
||||||
/*
|
|
||||||
Preferences.m
|
|
||||||
|
|
||||||
Preferences class for Forge
|
|
||||||
|
|
||||||
Copyright (C) 2001 Jeff Teunissen <deek@quakeforge.net>
|
|
||||||
|
|
||||||
This program 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.
|
|
||||||
|
|
||||||
This program 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 this program; if not, write to:
|
|
||||||
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import <Foundation/NSNotification.h>
|
|
||||||
#import <Foundation/NSString.h>
|
|
||||||
#import <Foundation/NSUserDefaults.h>
|
|
||||||
#import <Foundation/NSValue.h>
|
|
||||||
|
|
||||||
#import <AppKit/NSButton.h>
|
|
||||||
#import <AppKit/NSControl.h>
|
|
||||||
|
|
||||||
#import "Preferences.h"
|
|
||||||
|
|
||||||
id prefs;
|
|
||||||
|
|
||||||
static NSDictionary *defaultValues (void) {
|
|
||||||
static NSDictionary *dict = nil;
|
|
||||||
if (!dict) {
|
|
||||||
dict = [[NSDictionary alloc] initWithObjectsAndKeys:
|
|
||||||
@"/Local/Forge/Projects", ProjectPath,
|
|
||||||
@"/Local/Forge/Sounds", BspSoundPath,
|
|
||||||
[NSNumber numberWithInt: 0], StartWad,
|
|
||||||
[NSNumber numberWithFloat: 1.0], XLight,
|
|
||||||
[NSNumber numberWithFloat: 0.6], YLight,
|
|
||||||
[NSNumber numberWithFloat: 0.75], ZLight,
|
|
||||||
[NSNumber numberWithBool: NO], ShowBSPOutput,
|
|
||||||
[NSNumber numberWithBool: NO], OffsetBrushCopy,
|
|
||||||
nil];
|
|
||||||
}
|
|
||||||
return dict;
|
|
||||||
}
|
|
||||||
|
|
||||||
@implementation Preferences
|
|
||||||
|
|
||||||
static Preferences *sharedInstance = nil;
|
|
||||||
|
|
||||||
- (id) objectForKey: (id) key
|
|
||||||
{
|
|
||||||
return [[[[self class] sharedInstance] preferences] objectForKey: key];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void) saveDefaults
|
|
||||||
{
|
|
||||||
if (sharedInstance) {
|
|
||||||
[self savePreferencesToDefaults: [sharedInstance preferences]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) saveDefaults: (id) sender
|
|
||||||
{
|
|
||||||
[[self class] saveDefaults];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) loadDefaults
|
|
||||||
{
|
|
||||||
if (currentValues)
|
|
||||||
[currentValues release];
|
|
||||||
|
|
||||||
currentValues = [[[self class] preferencesFromDefaults] copyWithZone: [self zone]];
|
|
||||||
[self discardDisplayedValues];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (Preferences *) sharedInstance
|
|
||||||
{
|
|
||||||
return (sharedInstance ? sharedInstance : [[self alloc] init]);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) init
|
|
||||||
{
|
|
||||||
if (sharedInstance) {
|
|
||||||
[self dealloc];
|
|
||||||
} else {
|
|
||||||
[super init];
|
|
||||||
currentValues = [[[self class] preferencesFromDefaults] copyWithZone:[self zone]];
|
|
||||||
[self discardDisplayedValues];
|
|
||||||
sharedInstance = self;
|
|
||||||
prefs = sharedInstance;
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
|
||||||
addObserver: self
|
|
||||||
selector: @selector(saveDefaults:)
|
|
||||||
name: @"NSApplicationWillTerminateNotification"
|
|
||||||
object: nil];
|
|
||||||
}
|
|
||||||
return sharedInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSDictionary *) preferences
|
|
||||||
{
|
|
||||||
return currentValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) dealloc
|
|
||||||
{
|
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver: self];
|
|
||||||
[currentValues release];
|
|
||||||
[displayedValues release];
|
|
||||||
currentValues = displayedValues = nil;
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
updateUI
|
|
||||||
|
|
||||||
Update the user interface with new preferences
|
|
||||||
*/
|
|
||||||
- (void) updateUI
|
|
||||||
{
|
|
||||||
id theCenter = [NSNotificationCenter defaultCenter];
|
|
||||||
|
|
||||||
NSLog (@"Defaults updated, UI should update.");
|
|
||||||
|
|
||||||
[theCenter postNotificationName: @"ForgeTextureCacheShouldFlush" object: self userInfo: nil];
|
|
||||||
[theCenter postNotificationName: @"ForgeUIShouldUpdate" object: self userInfo: nil];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) prefsChanged: (id) sender {
|
|
||||||
static NSNumber *yes = nil;
|
|
||||||
static NSNumber *no = nil;
|
|
||||||
int anInt;
|
|
||||||
float aFloat;
|
|
||||||
|
|
||||||
if (!yes) {
|
|
||||||
yes = [[NSNumber alloc] initWithBool: YES];
|
|
||||||
no = [[NSNumber alloc] initWithBool: NO];
|
|
||||||
}
|
|
||||||
|
|
||||||
[displayedValues setObject: [projectPathField stringValue] forKey: ProjectPath];
|
|
||||||
[displayedValues setObject: [bspSoundPathField stringValue] forKey: BspSoundPath];
|
|
||||||
|
|
||||||
if ((anInt = [startWadField intValue]) < 0 || anInt > 2) {
|
|
||||||
if ((anInt = [[displayedValues objectForKey: StartWad] intValue]) < 0 || anInt > 2) {
|
|
||||||
anInt = [[defaultValues () objectForKey: StartWad] intValue];
|
|
||||||
}
|
|
||||||
[startWadField setIntValue: anInt];
|
|
||||||
} else {
|
|
||||||
[displayedValues setObject: [NSNumber numberWithInt: anInt] forKey: StartWad];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((aFloat = [xLightField floatValue]) < 0.0 || aFloat > 1.0) {
|
|
||||||
if ((aFloat = [[displayedValues objectForKey: XLight] floatValue]) < 0.0 || aFloat > 1.0) {
|
|
||||||
aFloat = [[defaultValues () objectForKey: XLight] floatValue];
|
|
||||||
}
|
|
||||||
[xLightField setFloatValue: aFloat];
|
|
||||||
} else {
|
|
||||||
[displayedValues setObject: [NSNumber numberWithFloat: aFloat] forKey: XLight];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((aFloat = [yLightField floatValue]) < 0.0 || aFloat > 1.0) {
|
|
||||||
if ((aFloat = [[displayedValues objectForKey: YLight] floatValue]) < 0.0 || aFloat > 1.0) {
|
|
||||||
aFloat = [[defaultValues () objectForKey: YLight] floatValue];
|
|
||||||
}
|
|
||||||
[yLightField setFloatValue: aFloat];
|
|
||||||
} else {
|
|
||||||
[displayedValues setObject: [NSNumber numberWithFloat: aFloat] forKey: YLight];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((aFloat = [zLightField floatValue]) < 0.0 || aFloat > 1.0) {
|
|
||||||
if ((aFloat = [[displayedValues objectForKey: YLight] floatValue]) < 0.0 || aFloat > 1.0) {
|
|
||||||
aFloat = [[defaultValues () objectForKey: YLight] floatValue];
|
|
||||||
}
|
|
||||||
[zLightField setFloatValue: aFloat];
|
|
||||||
} else {
|
|
||||||
[displayedValues setObject: [NSNumber numberWithFloat: aFloat] forKey: ZLight];
|
|
||||||
}
|
|
||||||
|
|
||||||
[displayedValues setObject: ([showBSPOutputButton state] ? yes : no) forKey: ShowBSPOutput];
|
|
||||||
[displayedValues setObject: ([offsetBrushCopyButton state] ? yes : no) forKey: OffsetBrushCopy];
|
|
||||||
|
|
||||||
[self commitDisplayedValues];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) commitDisplayedValues
|
|
||||||
{
|
|
||||||
if (currentValues != displayedValues) {
|
|
||||||
[currentValues release];
|
|
||||||
currentValues = [displayedValues copyWithZone: [self zone]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) discardDisplayedValues
|
|
||||||
{
|
|
||||||
if (currentValues != displayedValues) {
|
|
||||||
[displayedValues release];
|
|
||||||
displayedValues = [currentValues mutableCopyWithZone: [self zone]];
|
|
||||||
[self updateUI];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) ok: (id) sender
|
|
||||||
{
|
|
||||||
[self commitDisplayedValues];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) revert: (id) sender
|
|
||||||
{
|
|
||||||
[self discardDisplayedValues];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) revertToDefault: (id) sender
|
|
||||||
{
|
|
||||||
if (currentValues)
|
|
||||||
[currentValues release];
|
|
||||||
|
|
||||||
currentValues = [defaultValues () copyWithZone: [self zone]];
|
|
||||||
[currentValues retain];
|
|
||||||
|
|
||||||
[self discardDisplayedValues];
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
Code to deal with defaults
|
|
||||||
***/
|
|
||||||
|
|
||||||
#define getBoolDefault(name) \
|
|
||||||
{ \
|
|
||||||
NSString *str = [defaults stringForKey: name]; \
|
|
||||||
[dict setObject: (str ? [NSNumber numberWithBool: [str hasPrefix: @"Y"]] : [defaultValues() objectForKey: name]) forKey: name]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define getFloatDefault(name) \
|
|
||||||
{ \
|
|
||||||
NSString *str = [defaults stringForKey: name]; \
|
|
||||||
[dict setObject: (str ? [NSNumber numberWithFloat: [str floatValue]] : [defaultValues() objectForKey: name]) forKey: name]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define getIntDefault(name) \
|
|
||||||
{ \
|
|
||||||
NSString *str = [defaults stringForKey: name]; \
|
|
||||||
[dict setObject: (str ? [NSNumber numberWithInt: [str intValue]] : [defaultValues() objectForKey: name]) forKey: name]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define getStringDefault(name) \
|
|
||||||
{ \
|
|
||||||
NSString *str = [defaults stringForKey: name]; \
|
|
||||||
[dict setObject: (str ? str : [defaultValues() objectForKey: name]) forKey: name]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSDictionary *) preferencesFromDefaults
|
|
||||||
{
|
|
||||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
||||||
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity: 10];
|
|
||||||
|
|
||||||
getStringDefault(ProjectPath);
|
|
||||||
getStringDefault(BspSoundPath);
|
|
||||||
getIntDefault(StartWad);
|
|
||||||
getFloatDefault(XLight);
|
|
||||||
getFloatDefault(YLight);
|
|
||||||
getFloatDefault(ZLight);
|
|
||||||
getBoolDefault(ShowBSPOutput);
|
|
||||||
getBoolDefault(OffsetBrushCopy);
|
|
||||||
|
|
||||||
return dict;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define setBoolDefault(name) \
|
|
||||||
{ \
|
|
||||||
if ([[defaultValues() objectForKey: name] isEqual: [dict objectForKey: name]]) \
|
|
||||||
[defaults removeObjectForKey: name]; \
|
|
||||||
else \
|
|
||||||
[defaults setBool:[[dict objectForKey:name] boolValue] forKey: name]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define setFloatDefault(name) \
|
|
||||||
{ \
|
|
||||||
if ([[defaultValues() objectForKey: name] isEqual: [dict objectForKey: name]]) \
|
|
||||||
[defaults removeObjectForKey: name]; \
|
|
||||||
else \
|
|
||||||
[defaults setFloat:[[dict objectForKey:name] floatValue] forKey: name]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define setIntDefault(name) \
|
|
||||||
{ \
|
|
||||||
if ([[defaultValues() objectForKey:name] isEqual:[dict objectForKey:name]]) \
|
|
||||||
[defaults removeObjectForKey:name]; \
|
|
||||||
else \
|
|
||||||
[defaults setInteger:[[dict objectForKey:name] intValue] forKey:name]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define setStringDefault(name) \
|
|
||||||
{ \
|
|
||||||
if ([[defaultValues() objectForKey:name] isEqual: [dict objectForKey: name]]) \
|
|
||||||
[defaults removeObjectForKey: name]; \
|
|
||||||
else \
|
|
||||||
[defaults setObject: [[dict objectForKey: name] stringValue] forKey: name]; \
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void) savePreferencesToDefaults: (NSDictionary *) dict
|
|
||||||
{
|
|
||||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
||||||
|
|
||||||
setStringDefault(ProjectPath);
|
|
||||||
setStringDefault(BspSoundPath);
|
|
||||||
setIntDefault(StartWad);
|
|
||||||
setFloatDefault(XLight);
|
|
||||||
setFloatDefault(YLight);
|
|
||||||
setFloatDefault(ZLight);
|
|
||||||
setBoolDefault(ShowBSPOutput);
|
|
||||||
setBoolDefault(OffsetBrushCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,429 +0,0 @@
|
||||||
//======================================
|
|
||||||
//
|
|
||||||
// QuakeEd Project Management
|
|
||||||
//
|
|
||||||
//======================================
|
|
||||||
|
|
||||||
#import <AppKit/NSApplication.h>
|
|
||||||
|
|
||||||
#import "Preferences.h"
|
|
||||||
#import "Project.h"
|
|
||||||
|
|
||||||
Project *project;
|
|
||||||
|
|
||||||
@implementation Project
|
|
||||||
|
|
||||||
- init
|
|
||||||
{
|
|
||||||
project = self;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================
|
|
||||||
//
|
|
||||||
// Project code
|
|
||||||
//
|
|
||||||
//===========================================================
|
|
||||||
- initVars
|
|
||||||
{
|
|
||||||
NSString *s = [[Preferences sharedInstance] objectForKey: ProjectPath];
|
|
||||||
|
|
||||||
_basePath = [s stringByDeletingLastPathComponent];
|
|
||||||
|
|
||||||
_progsPath = [_basePath stringByAppendingPathComponent: EntSubdir];
|
|
||||||
_mapPath = [_basePath stringByAppendingPathComponent: MapSubdir];
|
|
||||||
_finalMapPath = [_basePath stringByAppendingPathComponent: MapSubdir];
|
|
||||||
|
|
||||||
[pBasePathField setStringValue: s]; // in Project Inspector
|
|
||||||
|
|
||||||
if ((s = [projectInfo objectForKey: BSPFullVis])) {
|
|
||||||
_fullVisCommand = [[[s componentsSeparatedByString: @"@"]
|
|
||||||
componentsJoinedByString: @"\""] retain];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((s = [projectInfo objectForKey: BSPFastVis])) {
|
|
||||||
_fastVisCommand = [[[s componentsSeparatedByString: @"@"]
|
|
||||||
componentsJoinedByString: @"\""] retain];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((s = [projectInfo objectForKey: BSPNoVis])) {
|
|
||||||
_noVisCommand = [[[s componentsSeparatedByString: @"@"]
|
|
||||||
componentsJoinedByString: @"\""] retain];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((s = [projectInfo objectForKey: BSPRelight])) {
|
|
||||||
_relightCommand = [[[s componentsSeparatedByString: @"@"]
|
|
||||||
componentsJoinedByString: @"\""] retain];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((s = [projectInfo objectForKey: BSPLeakTest])) {
|
|
||||||
_leakTestCommand = [[[s componentsSeparatedByString: @"@"]
|
|
||||||
componentsJoinedByString: @"\""] retain];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((s = [projectInfo objectForKey: BSPEntities])) {
|
|
||||||
_entitiesCommand = [[[s componentsSeparatedByString: @"@"]
|
|
||||||
componentsJoinedByString: @"\""] retain];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build list of wads
|
|
||||||
wadNames = [projectInfo objectForKey: WadFiles];
|
|
||||||
|
|
||||||
// Build list of maps & descriptions
|
|
||||||
mapNames = [projectInfo objectForKey: MapNames];
|
|
||||||
descriptions = [projectInfo objectForKey: Descriptions];
|
|
||||||
[self changeString: @"_" to: @" " in: descriptions];
|
|
||||||
|
|
||||||
[self initProjectSettings];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) initProjectSettings
|
|
||||||
{
|
|
||||||
[ppBasePath setStringValue: _basePath];
|
|
||||||
[ppFullVisField setStringValue: _fullVisCommand];
|
|
||||||
[ppFullVisField setStringValue: _fastVisCommand];
|
|
||||||
[ppNoVisField setStringValue: _noVisCommand];
|
|
||||||
[ppRelightField setStringValue: _relightCommand];
|
|
||||||
[ppLeakTestField setStringValue: _leakTestCommand];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Add text to the BSP Output window
|
|
||||||
//
|
|
||||||
- (void) addToOutput: (NSString *) string
|
|
||||||
{
|
|
||||||
NSRange range = NSMakeRange([pBSPOutputView textLength], 0);
|
|
||||||
|
|
||||||
[pBSPOutputView replaceCharactersInRange: range withString: string];
|
|
||||||
|
|
||||||
range = NSMakeRange([pBSPOutputView textLength], 0);
|
|
||||||
[pBSPOutputView scrollRangeToVisible: range];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) clearBspOutput: (id) sender
|
|
||||||
{
|
|
||||||
[pBSPOutputView selectAll: self];
|
|
||||||
[pBSPOutputView delete: self];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- (void) print
|
|
||||||
//{
|
|
||||||
// [pBSPOutputView printPSCode: self];
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
- initProject
|
|
||||||
{
|
|
||||||
[self parseProjectFile];
|
|
||||||
if (!projectInfo)
|
|
||||||
return self;
|
|
||||||
|
|
||||||
[self initVars];
|
|
||||||
// [pMapBrowser reuseColumns: YES];
|
|
||||||
[pMapBrowser loadColumnZero];
|
|
||||||
// [ppWadBrowser reuseColumns: YES];
|
|
||||||
[ppWadBrowser loadColumnZero];
|
|
||||||
|
|
||||||
// [things_i initEntities]; // FIXME
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Change a character to another in a Storage list of strings
|
|
||||||
//
|
|
||||||
- (void) changeString: (NSString *) f to: (NSString *) t in: (id) obj
|
|
||||||
{
|
|
||||||
NSMutableArray *newObj = [[NSMutableArray alloc] initWithCapacity: 10];
|
|
||||||
NSEnumerator *enumerator = [obj objectEnumerator];
|
|
||||||
id currentString;
|
|
||||||
|
|
||||||
while ((currentString = [enumerator nextObject])) {
|
|
||||||
[newObj addObject: [[currentString componentsSeparatedByString: f]
|
|
||||||
componentsJoinedByString: t]];
|
|
||||||
[currentString release];
|
|
||||||
}
|
|
||||||
|
|
||||||
[obj release];
|
|
||||||
obj = newObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill the Maps or Wads browser
|
|
||||||
// (Delegate method - delegated in Interface Builder)
|
|
||||||
- (int) browser: (id) sender fillMatrix: (id) matrix inColumn: (int) column
|
|
||||||
{
|
|
||||||
NSString *name;
|
|
||||||
NSArray *list;
|
|
||||||
NSCell *cell;
|
|
||||||
int max;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (sender == pMapBrowser) {
|
|
||||||
list = mapNames;
|
|
||||||
} else {
|
|
||||||
if (sender == ppWadBrowser) {
|
|
||||||
list = wadNames;
|
|
||||||
} else {
|
|
||||||
list = nil;
|
|
||||||
NSLog (@"Project: Unknown browser to fill");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
max = [list count];
|
|
||||||
for (i = 0; i < max; i++) {
|
|
||||||
name = [[list objectAtIndex: i] stringValue];
|
|
||||||
[matrix addRow];
|
|
||||||
cell = [matrix cellAtRow: i column: 0];
|
|
||||||
[cell setStringValue: name];
|
|
||||||
// [cell setLeaf: YES];
|
|
||||||
// [cell setLoaded: YES];
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clicked on a map name or description!
|
|
||||||
- (void) mapWasClicked: (id) sender
|
|
||||||
{
|
|
||||||
NSString *fname;
|
|
||||||
id matrix;
|
|
||||||
int row;
|
|
||||||
id panel;
|
|
||||||
|
|
||||||
matrix = [sender matrixInColumn: 0];
|
|
||||||
row = [matrix selectedRow];
|
|
||||||
|
|
||||||
fname = [_mapPath stringByAppendingPathComponent:
|
|
||||||
[[mapNames objectAtIndex: row]
|
|
||||||
stringByAppendingPathExtension: @"map"
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
panel = NSGetInformationalAlertPanel (@"Loading...",
|
|
||||||
@"Loading map. Please wait...", nil, nil, nil);
|
|
||||||
[panel orderFront: self];
|
|
||||||
[NSApp tryToPerform: @selector(openFile:) with: fname];
|
|
||||||
[panel performClose: self];
|
|
||||||
NSReleaseAlertPanel (panel);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
- (void) setTextureWad: (NSString *) wadFile
|
|
||||||
{
|
|
||||||
int i, c;
|
|
||||||
NSString *name;
|
|
||||||
|
|
||||||
NSLog (@"loading %s", wadFile);
|
|
||||||
|
|
||||||
// set the row in the settings inspector wad browser
|
|
||||||
c = [wadNames count];
|
|
||||||
for (i = 0; i < c; i++) {
|
|
||||||
name = [[wadNames objectAtIndex: i] stringValue];
|
|
||||||
if ([name isEqualToString: wadFile]) {
|
|
||||||
[ppWadBrowser selectCellAtRow: i column: 0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the texture inspector
|
|
||||||
[texturepalette_i initPaletteFromWadfile: wadFile];
|
|
||||||
[[map_i objectAtIndex: 0] setObject: wadFile forKey: @"wad"];
|
|
||||||
// [inspcontrol_i changeInspectorTo:i_textures];
|
|
||||||
|
|
||||||
[quakeed_i updateAll];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Clicked on a wad name
|
|
||||||
//
|
|
||||||
- (void) wadWasClicked: (id) sender
|
|
||||||
{
|
|
||||||
id matrix;
|
|
||||||
int row;
|
|
||||||
NSString *name;
|
|
||||||
|
|
||||||
matrix = [sender matrixInColumn: 0];
|
|
||||||
row = [matrix selectedRow];
|
|
||||||
|
|
||||||
name = [wadNames objectAtIndex: row];
|
|
||||||
[self setTextureWad: name];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Read in the <name>.QE_Project file
|
|
||||||
//
|
|
||||||
- (void) parseProjectFile
|
|
||||||
{
|
|
||||||
NSString *path;
|
|
||||||
int rtn;
|
|
||||||
|
|
||||||
if (!(path = [[Preferences sharedInstance] objectForKey: ProjectPath])) {
|
|
||||||
rtn = NSRunAlertPanel (@"Project Error",
|
|
||||||
@"A default project has not been found.\n"
|
|
||||||
, @"Open Project", nil, nil);
|
|
||||||
if ([self openProject] == nil)
|
|
||||||
while (1) // can't run without a project
|
|
||||||
[NSApp terminate: self];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
[self openProjectWithFile: path];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Loads and parses a project file
|
|
||||||
//
|
|
||||||
- (void) openProjectWithFile: (NSString *) path
|
|
||||||
{
|
|
||||||
[_projectPath release];
|
|
||||||
_projectPath = path;
|
|
||||||
|
|
||||||
[projectInfo release];
|
|
||||||
|
|
||||||
projectInfo = [NSMutableDictionary dictionaryWithContentsOfFile: path];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open a project file
|
|
||||||
- (id) openProject
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
NSArray *fileTypes = [NSArray arrayWithObject: @"forge"];
|
|
||||||
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
|
|
||||||
|
|
||||||
[openPanel setAllowsMultipleSelection: NO];
|
|
||||||
[openPanel setCanChooseDirectories: NO];
|
|
||||||
|
|
||||||
result = [openPanel runModalForTypes: fileTypes];
|
|
||||||
if (result == NSOKButton) {
|
|
||||||
NSArray *filenames = [[openPanel filenames] autorelease];
|
|
||||||
NSString *directory = [[openPanel directory] autorelease];
|
|
||||||
NSString *path = [directory stringByAppendingPathComponent: [filenames objectAtIndex: 0]];
|
|
||||||
|
|
||||||
[self openProjectWithFile: path];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Search for a string in an array
|
|
||||||
//
|
|
||||||
- (BOOL) searchForString: (NSString *) str in: (NSArray *) obj
|
|
||||||
{
|
|
||||||
NSEnumerator *enumerator = [obj objectEnumerator];
|
|
||||||
id name;
|
|
||||||
|
|
||||||
while ((name = [enumerator nextObject])) {
|
|
||||||
if ([[name stringValue] isEqualToString: str])
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) currentProject
|
|
||||||
{
|
|
||||||
return _projectPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) mapDirectory
|
|
||||||
{
|
|
||||||
return _mapPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) finalMapDirectory
|
|
||||||
{
|
|
||||||
return _finalMapPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) progDirectory
|
|
||||||
{
|
|
||||||
return _progsPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) wad8
|
|
||||||
{
|
|
||||||
return _wad8 ? _wad8 : nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) wad9
|
|
||||||
{
|
|
||||||
return _wad9 ? _wad9 : nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) wad0
|
|
||||||
{
|
|
||||||
return _wad0 ? _wad0 : nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) fullVisCommand
|
|
||||||
{
|
|
||||||
return _fullVisCommand ? _fullVisCommand : nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) fastVisCommand
|
|
||||||
{
|
|
||||||
return _fastVisCommand ? _fastVisCommand : nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) noVisCommand
|
|
||||||
{
|
|
||||||
return _noVisCommand ? _noVisCommand : nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) relightCommand
|
|
||||||
{
|
|
||||||
return _relightCommand ? _relightCommand : nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) leakTestCommand
|
|
||||||
{
|
|
||||||
return _leakTestCommand ? _leakTestCommand : nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) entitiesCommand
|
|
||||||
{
|
|
||||||
return _entitiesCommand ? _entitiesCommand : nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
//====================================================
|
|
||||||
// C Functions
|
|
||||||
//====================================================
|
|
||||||
|
|
||||||
//
|
|
||||||
// Change a character to a different char in a string
|
|
||||||
//
|
|
||||||
void changeString(char cf,char ct,char *string)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
|
|
||||||
for (j = 0;j < strlen(string);j++)
|
|
||||||
if (string[j] == cf)
|
|
||||||
string[j] = ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,800 +0,0 @@
|
||||||
|
|
||||||
#import "Preferences.h"
|
|
||||||
|
|
||||||
#import "qedefs.h"
|
|
||||||
|
|
||||||
id texturepalette_i;
|
|
||||||
|
|
||||||
#define TYP_MIPTEX 67
|
|
||||||
|
|
||||||
int tex_count;
|
|
||||||
qtexture_t qtextures[MAX_TEXTURES];
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char name[16];
|
|
||||||
unsigned width, height;
|
|
||||||
unsigned offsets[4]; // four mip maps stored
|
|
||||||
} miptex_t;
|
|
||||||
|
|
||||||
unsigned tex_palette[256];
|
|
||||||
|
|
||||||
unsigned int badtex_d[] = {
|
|
||||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
|
|
||||||
};
|
|
||||||
|
|
||||||
qtexture_t badtex = {
|
|
||||||
@"notexture",
|
|
||||||
{16.0, 16.0},
|
|
||||||
nil,
|
|
||||||
badtex_d,
|
|
||||||
{{0, 0, 255, 255}}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
==============
|
|
||||||
TEX_InitPalette
|
|
||||||
==============
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
TEX_InitPalette (byte *pal)
|
|
||||||
{
|
|
||||||
int r,g,b,v;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < 256; i++) {
|
|
||||||
r = pal[0];
|
|
||||||
g = pal[1];
|
|
||||||
b = pal[2];
|
|
||||||
pal += 3;
|
|
||||||
|
|
||||||
v = (r << 24) + (g << 16) + (b << 8) + 255;
|
|
||||||
v = BigLong (v);
|
|
||||||
|
|
||||||
tex_palette[i] = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
TEX_ImageFromMiptex
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
TEX_ImageFromMiptex (miptex_t *qtex)
|
|
||||||
{
|
|
||||||
NSBitmapImageRep *bm;
|
|
||||||
byte *source;
|
|
||||||
unsigned *dest;
|
|
||||||
int width, height, i, count;
|
|
||||||
qtexture_t *q;
|
|
||||||
int tr, tg, tb;
|
|
||||||
|
|
||||||
width = LittleLong(qtex->width);
|
|
||||||
height = LittleLong(qtex->height);
|
|
||||||
|
|
||||||
bm = [[NSBitmapImageRep alloc]
|
|
||||||
initWithBitmapDataPlanes: NULL
|
|
||||||
pixelsWide: width
|
|
||||||
pixelsHigh: height
|
|
||||||
bitsPerSample: 8
|
|
||||||
samplesPerPixel:3
|
|
||||||
hasAlpha: NO
|
|
||||||
isPlanar: NO
|
|
||||||
colorSpaceName: NSCalibratedRGBColorSpace
|
|
||||||
bytesPerRow: width * 4
|
|
||||||
bitsPerPixel: 32];
|
|
||||||
|
|
||||||
dest = (unsigned *) [bm bitmapData];
|
|
||||||
count = width * height;
|
|
||||||
source = (byte *)qtex + LittleLong(qtex->offsets[0]);
|
|
||||||
|
|
||||||
q = &qtextures[tex_count];
|
|
||||||
tex_count++;
|
|
||||||
|
|
||||||
q->size.width = width;
|
|
||||||
q->size.height = height;
|
|
||||||
q->rep = bm;
|
|
||||||
q->data = dest;
|
|
||||||
|
|
||||||
tr = tg = tb = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
dest[i] = tex_palette[source[i]];
|
|
||||||
tr += ((pixel32_t *) &dest[i])->chan[0];
|
|
||||||
tg += ((pixel32_t *) &dest[i])->chan[1];
|
|
||||||
tb += ((pixel32_t *) &dest[i])->chan[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
q->flatcolor.chan[0] = tr / count;
|
|
||||||
q->flatcolor.chan[1] = tg / count;
|
|
||||||
q->flatcolor.chan[2] = tb / count;
|
|
||||||
q->flatcolor.chan[3] = 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char identification[4]; // should be WAD2 or 2DAW
|
|
||||||
int numlumps;
|
|
||||||
int infotableofs;
|
|
||||||
} wadinfo_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int filepos;
|
|
||||||
int disksize;
|
|
||||||
int size; // uncompressed
|
|
||||||
char type;
|
|
||||||
char compression;
|
|
||||||
char pad1, pad2;
|
|
||||||
char name[16]; // must be null terminated
|
|
||||||
} lumpinfo_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
TEX_InitFromWad
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
TEX_InitFromWad (NSString *path)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
NSString *local;
|
|
||||||
NSString *newpath;
|
|
||||||
byte *wadfile;
|
|
||||||
wadinfo_t *wadinfo;
|
|
||||||
lumpinfo_t *lumpinfo;
|
|
||||||
int numlumps;
|
|
||||||
float start, stop;
|
|
||||||
|
|
||||||
start = I_FloatTime ();
|
|
||||||
|
|
||||||
newpath = [[prefs objectForKey: ProjectPath] stringByAppendingPathComponent: path];
|
|
||||||
|
|
||||||
// free any textures
|
|
||||||
for (i = 0; i < tex_count; i++)
|
|
||||||
[qtextures[i].rep release];
|
|
||||||
tex_count = 0;
|
|
||||||
|
|
||||||
// try and use the cached wadfile
|
|
||||||
local = [NSString initWithFormat: @"/qcache%@", newpath];
|
|
||||||
|
|
||||||
Sys_UpdateFile (local, newpath);
|
|
||||||
|
|
||||||
LoadFile (local, (void **)&wadfile);
|
|
||||||
wadinfo = (wadinfo_t *)wadfile;
|
|
||||||
|
|
||||||
if (strncmp (wadfile, "WAD2", 4))
|
|
||||||
{
|
|
||||||
unlink (local);
|
|
||||||
Error ("TEX_InitFromWad: %s isn't a wadfile", newpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
numlumps = LittleLong (wadinfo->numlumps);
|
|
||||||
lumpinfo = (lumpinfo_t *)(wadfile + LittleLong (wadinfo->infotableofs));
|
|
||||||
|
|
||||||
if (strcmp (lumpinfo->name, "PALETTE")) {
|
|
||||||
unlink (local);
|
|
||||||
Error ("TEX_InitFromWad: %s doesn't have palette as 0",path);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEX_InitPalette (wadfile + LittleLong(lumpinfo->filepos));
|
|
||||||
|
|
||||||
lumpinfo++;
|
|
||||||
for (i=1 ; i<numlumps ; i++, lumpinfo++) {
|
|
||||||
if (lumpinfo->type != TYP_MIPTEX)
|
|
||||||
Error ("TEX_InitFromWad: %s is not a miptex!",lumpinfo->name);
|
|
||||||
CleanupName (lumpinfo->name,qtextures[tex_count].name);
|
|
||||||
TEX_ImageFromMiptex ( (miptex_t *)(wadfile +
|
|
||||||
LittleLong(lumpinfo->filepos) ));
|
|
||||||
}
|
|
||||||
|
|
||||||
free (wadfile);
|
|
||||||
|
|
||||||
stop = I_FloatTime ();
|
|
||||||
|
|
||||||
qprintf ("loaded %s (%5.1f)", local, stop - start);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
TEX_NumForName
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
qtexture_t *TEX_ForName (char *name)
|
|
||||||
{
|
|
||||||
char newname[16];
|
|
||||||
int i;
|
|
||||||
qtexture_t *q;
|
|
||||||
|
|
||||||
CleanupName (name, newname);
|
|
||||||
|
|
||||||
for (i=0,q = qtextures ; i< tex_count ; i++, q++)
|
|
||||||
{
|
|
||||||
if (!strcmp(name, q->name))
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &badtex;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
@implementation TexturePalette
|
|
||||||
|
|
||||||
- init
|
|
||||||
{
|
|
||||||
[super init];
|
|
||||||
texturepalette_i = self;
|
|
||||||
selectedTexture = -1;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- display
|
|
||||||
{
|
|
||||||
[[textureView_i superview] display];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (char *)currentWad
|
|
||||||
{
|
|
||||||
return currentwad;
|
|
||||||
}
|
|
||||||
|
|
||||||
- initPaletteFromWadfile:(char *)wf
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
texpal_t t;
|
|
||||||
qtexture_t *q;
|
|
||||||
|
|
||||||
strcpy (currentwad, wf);
|
|
||||||
[map_i makeGlobalPerform: @selector(flushTextures)];
|
|
||||||
selectedTexture = -1;
|
|
||||||
|
|
||||||
// Init textures WAD
|
|
||||||
TEX_InitFromWad(wf);
|
|
||||||
|
|
||||||
// Create STORAGE
|
|
||||||
if (textureList_i)
|
|
||||||
[textureList_i removeAllObjects];
|
|
||||||
else
|
|
||||||
textureList_i = [[Storage alloc]
|
|
||||||
initCount:0
|
|
||||||
elementSize:sizeof(texpal_t)
|
|
||||||
description:NULL];
|
|
||||||
|
|
||||||
// Init STORAGE
|
|
||||||
|
|
||||||
for (i = 0,q=qtextures;i < tex_count; i++,q++)
|
|
||||||
{
|
|
||||||
t.image = q->rep;
|
|
||||||
t.r.size.width = [t.image pixelsWide];
|
|
||||||
if (t.r.size.width < 64)
|
|
||||||
t.r.size.width = 64;
|
|
||||||
t.r.size.height = [t.image pixelsHigh] + TEX_SPACING;
|
|
||||||
t.name = q->name;
|
|
||||||
t.index = i;
|
|
||||||
t.display = 1;
|
|
||||||
[textureList_i addElement:&t];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate size of TextureView
|
|
||||||
[self alphabetize];
|
|
||||||
[self computeTextureViewSize];
|
|
||||||
[textureView_i setParent:self];
|
|
||||||
[self setSelectedTexture:0];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Return texture STORAGE list
|
|
||||||
- getList
|
|
||||||
{
|
|
||||||
return textureList_i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alphabetize texture list - reverse order!
|
|
||||||
- alphabetize
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int max;
|
|
||||||
texpal_t *t1p;
|
|
||||||
texpal_t *t2p;
|
|
||||||
texpal_t t1;
|
|
||||||
texpal_t t2;
|
|
||||||
int found;
|
|
||||||
|
|
||||||
max = [textureList_i count];
|
|
||||||
found = 1;
|
|
||||||
while(found)
|
|
||||||
{
|
|
||||||
found = 0;
|
|
||||||
for (i = 0;i < max-1;i++)
|
|
||||||
{
|
|
||||||
t1p = [textureList_i elementAtIndex:i];
|
|
||||||
t2p = [textureList_i elementAtIndex:i+1];
|
|
||||||
if (strcmp(t1p->name,t2p->name) < 0)
|
|
||||||
{
|
|
||||||
t1 = *t1p;
|
|
||||||
t2 = *t2p;
|
|
||||||
[textureList_i replaceElementAt:i with:&t2];
|
|
||||||
[textureList_i replaceElementAt:i+1 with:&t1];
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- computeTextureViewSize
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int max;
|
|
||||||
int x;
|
|
||||||
texpal_t *t;
|
|
||||||
int y;
|
|
||||||
id view;
|
|
||||||
NSRect b;
|
|
||||||
int maxwidth;
|
|
||||||
int maxheight;
|
|
||||||
NXPoint pt;
|
|
||||||
|
|
||||||
max = [textureList_i count];
|
|
||||||
y = 0;
|
|
||||||
maxheight = 0;
|
|
||||||
x = TEX_INDENT;
|
|
||||||
|
|
||||||
view = [textureView_i superview];
|
|
||||||
[view getBounds:&b];
|
|
||||||
maxwidth = b.size.width;
|
|
||||||
|
|
||||||
for (i = 0;i < max; i++)
|
|
||||||
{
|
|
||||||
t = [textureList_i elementAtIndex:i];
|
|
||||||
if (x + t->r.size.width + TEX_INDENT > maxwidth)
|
|
||||||
{
|
|
||||||
x = TEX_INDENT;
|
|
||||||
y += maxheight;
|
|
||||||
maxheight = 0;
|
|
||||||
}
|
|
||||||
if (t->r.size.height > maxheight)
|
|
||||||
maxheight = t->r.size.height;
|
|
||||||
t->r.origin.x = x;
|
|
||||||
t->r.origin.y = y;
|
|
||||||
x += t->r.size.width + TEX_INDENT;
|
|
||||||
if (i == max - 1)
|
|
||||||
y += t->r.size.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
viewWidth = maxwidth;
|
|
||||||
viewHeight = y + TEX_SPACING;
|
|
||||||
[textureView_i sizeTo:viewWidth :viewHeight];
|
|
||||||
pt.x = pt.y = 0;
|
|
||||||
[textureView_i scrollPoint:&pt];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- windowResized
|
|
||||||
{
|
|
||||||
[self computeTextureViewSize];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- texturedefChanged: sender
|
|
||||||
{
|
|
||||||
if ([map_i numSelected])
|
|
||||||
{
|
|
||||||
if ( [[map_i currentEntity] modifiable] )
|
|
||||||
{
|
|
||||||
[map_i makeSelectedPerform: @selector(takeCurrentTexture)];
|
|
||||||
[quakeed_i updateAll];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
qprintf ("can't modify spawned entities");
|
|
||||||
}
|
|
||||||
[quakeed_i makeFirstResponder: quakeed_i];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- clearTexinfo: sender
|
|
||||||
{
|
|
||||||
[field_Xshift_i setFloatValue:0];
|
|
||||||
[field_Yshift_i setFloatValue:0];
|
|
||||||
[field_Xscale_i setFloatValue:1];
|
|
||||||
[field_Yscale_i setFloatValue:1];
|
|
||||||
[field_Rotate_i setFloatValue:0];
|
|
||||||
|
|
||||||
[self texturedefChanged: self];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set the selected texture
|
|
||||||
//
|
|
||||||
- setSelectedTexture:(int)which
|
|
||||||
{
|
|
||||||
texpal_t *t;
|
|
||||||
NSRect r;
|
|
||||||
char string[16];
|
|
||||||
|
|
||||||
// wipe the fields
|
|
||||||
[self clearTexinfo: self];
|
|
||||||
|
|
||||||
if (which != selectedTexture)
|
|
||||||
{
|
|
||||||
[textureView_i deselect];
|
|
||||||
selectedTexture = which;
|
|
||||||
t = [textureList_i elementAtIndex:which];
|
|
||||||
r = t->r;
|
|
||||||
r.size.width += TEX_INDENT*2;
|
|
||||||
r.size.height += TEX_INDENT*2;
|
|
||||||
r.origin.x -= TEX_INDENT;
|
|
||||||
r.origin.y -= TEX_INDENT;
|
|
||||||
[textureView_i scrollRectToVisible:&r];
|
|
||||||
[textureView_i display];
|
|
||||||
sprintf(string,"%d x %d",(int)t->r.size.width,
|
|
||||||
(int)t->r.size.height - TEX_SPACING);
|
|
||||||
[sizeField_i setStringValue:string];
|
|
||||||
}
|
|
||||||
|
|
||||||
[self texturedefChanged:self];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Return the selected texture index
|
|
||||||
//
|
|
||||||
- (int)getSelectedTexture
|
|
||||||
{
|
|
||||||
return selectedTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Return the original tex_ index of the selected texture
|
|
||||||
// so the texture info can be indexed from tex_images, etc.
|
|
||||||
//
|
|
||||||
- (int)getSelectedTexIndex
|
|
||||||
{
|
|
||||||
texpal_t *t;
|
|
||||||
|
|
||||||
if (selectedTexture == -1)
|
|
||||||
return -1;
|
|
||||||
t = [textureList_i elementAtIndex:selectedTexture];
|
|
||||||
return t->index;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Return the name of the selected texture
|
|
||||||
//
|
|
||||||
- (char *)getSelTextureName
|
|
||||||
{
|
|
||||||
texpal_t *t;
|
|
||||||
|
|
||||||
if (selectedTexture == -1)
|
|
||||||
return NULL;
|
|
||||||
t = [textureList_i elementAtIndex:selectedTexture];
|
|
||||||
return t->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set selected texture by texture name
|
|
||||||
//
|
|
||||||
- setTextureByName:(char *)name
|
|
||||||
{
|
|
||||||
texpal_t *t;
|
|
||||||
int i;
|
|
||||||
int max;
|
|
||||||
|
|
||||||
max = [textureList_i count];
|
|
||||||
CleanupName(name,name);
|
|
||||||
for (i = 0;i < max;i++)
|
|
||||||
{
|
|
||||||
t = [textureList_i elementAtIndex:i];
|
|
||||||
if (!strcmp(t->name,name))
|
|
||||||
{
|
|
||||||
[self setSelectedTexture: i];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===================================================
|
|
||||||
//
|
|
||||||
// Action methods
|
|
||||||
//
|
|
||||||
//===================================================
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Search for texture named in searchField
|
|
||||||
//
|
|
||||||
- searchForTexture:sender
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int max;
|
|
||||||
int len;
|
|
||||||
char name[32];
|
|
||||||
texpal_t *t;
|
|
||||||
|
|
||||||
if (selectedTexture == -1)
|
|
||||||
return self;
|
|
||||||
|
|
||||||
max = [textureList_i count];
|
|
||||||
strcpy(name,(const char *)[sender stringValue]);
|
|
||||||
[sender setStringValue:strupr(name)];
|
|
||||||
len = strlen(name);
|
|
||||||
|
|
||||||
for (i = selectedTexture-1;i >= 0; i--)
|
|
||||||
{
|
|
||||||
t = [textureList_i elementAtIndex:i];
|
|
||||||
if (!strncmp(t->name,name,len))
|
|
||||||
{
|
|
||||||
[self setTextureByName:t->name];
|
|
||||||
[sender selectText:sender];
|
|
||||||
[self texturedefChanged:self];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = max-1;i >= selectedTexture; i--)
|
|
||||||
{
|
|
||||||
t = [textureList_i elementAtIndex:i];
|
|
||||||
if (!strncmp(t->name,name,len))
|
|
||||||
{
|
|
||||||
[self setTextureByName:t->name];
|
|
||||||
[sender selectText:sender];
|
|
||||||
[self texturedefChanged:self];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[self texturedefChanged:self];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set texture def from outside TexturePalette
|
|
||||||
//
|
|
||||||
- setTextureDef:(texturedef_t *)td
|
|
||||||
{
|
|
||||||
[self setTextureByName:td->texture];
|
|
||||||
|
|
||||||
[field_Xshift_i setFloatValue:td->shift[0]];
|
|
||||||
[field_Yshift_i setFloatValue:td->shift[1]];
|
|
||||||
[field_Xscale_i setFloatValue:td->scale[0]];
|
|
||||||
[field_Yscale_i setFloatValue:td->scale[1]];
|
|
||||||
[field_Rotate_i setFloatValue:td->rotate];
|
|
||||||
|
|
||||||
[self texturedefChanged:self];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Return the current texture def to passed *
|
|
||||||
//
|
|
||||||
- getTextureDef:(texturedef_t *)td
|
|
||||||
{
|
|
||||||
if (selectedTexture == -1)
|
|
||||||
{
|
|
||||||
memset (td, 0, sizeof(*td));
|
|
||||||
strcpy (td->texture, "notexture");
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(td->texture,[self getSelTextureName],16);
|
|
||||||
|
|
||||||
td->shift[0] = [field_Xshift_i floatValue];
|
|
||||||
td->shift[1] = [field_Yshift_i floatValue];
|
|
||||||
td->scale[0] = [field_Xscale_i floatValue];
|
|
||||||
td->scale[1] = [field_Yscale_i floatValue];
|
|
||||||
td->rotate = [field_Rotate_i floatValue];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
//
|
|
||||||
// Change value in a field
|
|
||||||
//
|
|
||||||
- changeField:(id)field by:(int)amount
|
|
||||||
{
|
|
||||||
int val;
|
|
||||||
|
|
||||||
val = [field intValue];
|
|
||||||
val += amount;
|
|
||||||
[field setIntValue:val];
|
|
||||||
|
|
||||||
[self texturedefChanged:self];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Inc/Dec the XShift field
|
|
||||||
//
|
|
||||||
- incXShift:sender
|
|
||||||
{
|
|
||||||
[self changeField:field_Xshift_i by:8];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
- decXShift:sender
|
|
||||||
{
|
|
||||||
[self changeField:field_Xshift_i by:-8];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Inc/Dec the YShift field
|
|
||||||
//
|
|
||||||
- incYShift:sender
|
|
||||||
{
|
|
||||||
[self changeField:field_Yshift_i by:8];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
- decYShift:sender
|
|
||||||
{
|
|
||||||
[self changeField:field_Yshift_i by:-8];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Inc/Dec the Rotate field
|
|
||||||
//
|
|
||||||
- incRotate:sender
|
|
||||||
{
|
|
||||||
[self changeField:field_Rotate_i by:90];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
- decRotate:sender
|
|
||||||
{
|
|
||||||
[self changeField:field_Rotate_i by:-90];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Inc/Dec the Xscale field
|
|
||||||
//
|
|
||||||
- incXScale:sender
|
|
||||||
{
|
|
||||||
[field_Xscale_i setIntValue: 1];
|
|
||||||
[self texturedefChanged:self];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
- decXScale:sender
|
|
||||||
{
|
|
||||||
[field_Xscale_i setIntValue: -1];
|
|
||||||
[self texturedefChanged:self];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Inc/Dec the Yscale field
|
|
||||||
//
|
|
||||||
- incYScale:sender
|
|
||||||
{
|
|
||||||
[field_Yscale_i setIntValue: 1];
|
|
||||||
[self texturedefChanged:self];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
- decYScale:sender
|
|
||||||
{
|
|
||||||
[field_Yscale_i setIntValue: -1];
|
|
||||||
[self texturedefChanged:self];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Search for texture in entire palette
|
|
||||||
// Return index of texturedef, or -1 if unsuccessful
|
|
||||||
//
|
|
||||||
- (int) searchForTextureInPalette:(char *)texture
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int max;
|
|
||||||
char name[32];
|
|
||||||
texpal_t *t;
|
|
||||||
|
|
||||||
if (selectedTexture == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
max = [textureList_i count];
|
|
||||||
strcpy(name,texture);
|
|
||||||
|
|
||||||
for (i = 0; i < max; i++)
|
|
||||||
{
|
|
||||||
t = [textureList_i elementAtIndex:i];
|
|
||||||
if (!strcmp(t->name,name))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Scan thru map & only display textures that are in map
|
|
||||||
//
|
|
||||||
- onlyShowMapTextures:sender
|
|
||||||
{
|
|
||||||
int max;
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
id brushes;
|
|
||||||
SetBrush *b;
|
|
||||||
int numfaces;
|
|
||||||
face_t *f;
|
|
||||||
int index;
|
|
||||||
|
|
||||||
// Turn 'em off
|
|
||||||
if ([sender intValue])
|
|
||||||
{
|
|
||||||
max = [textureList_i count];
|
|
||||||
for (i = 0;i < max; i++)
|
|
||||||
[self setDisplayFlag:i to:0];
|
|
||||||
|
|
||||||
brushes = [map_i objectAtIndex:0];
|
|
||||||
max = [brushes count];
|
|
||||||
for (i = 0;i < max; i++)
|
|
||||||
{
|
|
||||||
b = (SetBrush *)[brushes objectAtIndex:i];
|
|
||||||
numfaces = [b getNumBrushFaces];
|
|
||||||
for (j = 0; j < numfaces; j++)
|
|
||||||
{
|
|
||||||
f = [b getBrushFace:j];
|
|
||||||
index = [self searchForTextureInPalette:f->texture.texture];
|
|
||||||
if (index >= 0)
|
|
||||||
[self setDisplayFlag:index to:1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Turn 'em on
|
|
||||||
else
|
|
||||||
{
|
|
||||||
max = [textureList_i count];
|
|
||||||
for (i = 0;i < max; i++)
|
|
||||||
[self setDisplayFlag:i to:1];
|
|
||||||
}
|
|
||||||
|
|
||||||
[textureView_i display];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- setDisplayFlag:(int)index to:(int)value
|
|
||||||
{
|
|
||||||
texpal_t *tp;
|
|
||||||
|
|
||||||
tp = [textureList_i elementAtIndex:index];
|
|
||||||
tp->display = value;
|
|
||||||
return self;
|
|
||||||
};
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,317 +0,0 @@
|
||||||
|
|
||||||
#import "qedefs.h"
|
|
||||||
|
|
||||||
id things_i;
|
|
||||||
|
|
||||||
@implementation Things
|
|
||||||
|
|
||||||
- init
|
|
||||||
{
|
|
||||||
[super init];
|
|
||||||
|
|
||||||
things_i = self;
|
|
||||||
lastSelected = 0;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Load the TEXT object with the entity comment
|
|
||||||
//
|
|
||||||
- loadEntityComment:(id)obj
|
|
||||||
{
|
|
||||||
[entity_comment_i selectAll:self];
|
|
||||||
[entity_comment_i replaceSel:[obj comments]];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- initEntities
|
|
||||||
{
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
path = [project_i getProgDirectory];
|
|
||||||
|
|
||||||
[prog_path_i setStringValue: [NSString stringWithCString:path]];
|
|
||||||
|
|
||||||
[[EntityClassList alloc] initForSourceDirectory: path];
|
|
||||||
|
|
||||||
[self loadEntityComment:[entity_classes_i objectAtIndex:lastSelected]];
|
|
||||||
[entity_browser_i loadColumnZero];
|
|
||||||
[[entity_browser_i matrixInColumn:0] selectCellAtRow:lastSelected column:0];
|
|
||||||
|
|
||||||
[entity_browser_i setDoubleAction: @selector(doubleClickEntity:)];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- selectEntity: sender
|
|
||||||
{
|
|
||||||
id matr;
|
|
||||||
|
|
||||||
matr = [sender matrixInColumn: 0];
|
|
||||||
lastSelected = [matr selectedRow];
|
|
||||||
[self loadEntityComment:[entity_classes_i objectAtIndex:lastSelected]];
|
|
||||||
[quakeed_i makeFirstResponder: quakeed_i];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- doubleClickEntity: sender
|
|
||||||
{
|
|
||||||
[map_i makeEntity: sender];
|
|
||||||
[quakeed_i makeFirstResponder: quakeed_i];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (char *)spawnName
|
|
||||||
{
|
|
||||||
return [[entity_classes_i objectAtIndex:lastSelected] classname];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Flush entity classes & reload them!
|
|
||||||
//
|
|
||||||
- reloadEntityClasses: sender
|
|
||||||
{
|
|
||||||
EntityClass *ent;
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
path = (char *)[prog_path_i stringValue];
|
|
||||||
if (!path || !path[0])
|
|
||||||
{
|
|
||||||
path = [project_i getProgDirectory];
|
|
||||||
[prog_path_i setStringValue: [NSString stringWithCString:path]];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free all entity info in memory...
|
|
||||||
[entity_classes_i freeObjects];
|
|
||||||
[entity_classes_i free];
|
|
||||||
|
|
||||||
// Now, RELOAD!
|
|
||||||
[[EntityClassList alloc] initForSourceDirectory: path];
|
|
||||||
|
|
||||||
lastSelected = 0;
|
|
||||||
ent = [entity_classes_i objectAtIndex:lastSelected];
|
|
||||||
[self loadEntityComment:[entity_classes_i objectAtIndex:lastSelected]];
|
|
||||||
|
|
||||||
[entity_browser_i loadColumnZero];
|
|
||||||
[[entity_browser_i matrixInColumn:0] selectCellAtRow:lastSelected column:0];
|
|
||||||
|
|
||||||
[self newCurrentEntity]; // in case flags changed
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- selectClass: (char *)class
|
|
||||||
{
|
|
||||||
id classent;
|
|
||||||
|
|
||||||
classent = [entity_classes_i classForName:class];
|
|
||||||
if (!classent)
|
|
||||||
return self;
|
|
||||||
lastSelected = [entity_classes_i indexOfObject: classent];
|
|
||||||
|
|
||||||
if (lastSelected < 0)
|
|
||||||
lastSelected = 0;
|
|
||||||
|
|
||||||
[self loadEntityComment:classent];
|
|
||||||
[[entity_browser_i matrixInColumn:0] selectCellAtRow:lastSelected column:0];
|
|
||||||
[[entity_browser_i matrixInColumn:0] scrollCellToVisibleAtRow:lastSelected column:0];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- newCurrentEntity
|
|
||||||
{
|
|
||||||
id ent, classent, cell;
|
|
||||||
char *classname;
|
|
||||||
int r, c;
|
|
||||||
char *flagname;
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
ent = [map_i currentEntity];
|
|
||||||
classname = [ent valueForQKey: "classname"];
|
|
||||||
if (ent != [map_i objectAtIndex: 0])
|
|
||||||
[self selectClass: classname]; // don't reset for world
|
|
||||||
classent = [entity_classes_i classForName:classname];
|
|
||||||
flagname = [ent valueForQKey: "spawnflags"];
|
|
||||||
if (!flagname)
|
|
||||||
flags = 0;
|
|
||||||
else
|
|
||||||
flags = atoi(flagname);
|
|
||||||
|
|
||||||
[flags_i setAutodisplay: NO];
|
|
||||||
for (r=0 ; r<4 ; r++)
|
|
||||||
for (c=0 ; c<3 ; c++)
|
|
||||||
{
|
|
||||||
cell = [flags_i cellAtRow: r column: c];
|
|
||||||
if (c < 2)
|
|
||||||
{
|
|
||||||
flagname = [classent flagName: c*4 + r];
|
|
||||||
[cell setTitle: [NSString stringWithCString:flagname]];
|
|
||||||
}
|
|
||||||
[cell setIntValue: (flags & (1<< ((c*4)+r)) ) > 0];
|
|
||||||
}
|
|
||||||
[flags_i setAutodisplay: YES];
|
|
||||||
[flags_i display];
|
|
||||||
|
|
||||||
// [keyInput_i setStringValue: ""];
|
|
||||||
// [valueInput_i setStringValue: ""];
|
|
||||||
|
|
||||||
[keypairview_i calcViewSize];
|
|
||||||
[keypairview_i display];
|
|
||||||
|
|
||||||
[quakeed_i makeFirstResponder: quakeed_i];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Clicked in the Keypair view - set as selected
|
|
||||||
//
|
|
||||||
- setSelectedKey:(epair_t *)ep;
|
|
||||||
{
|
|
||||||
[keyInput_i setStringValue:[NSString stringWithCString:ep->key]];
|
|
||||||
[valueInput_i setStringValue:[NSString stringWithCString:ep->value]];
|
|
||||||
[valueInput_i selectText:self];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- clearInputs
|
|
||||||
{
|
|
||||||
// [keyInput_i setStringValue: ""];
|
|
||||||
// [valueInput_i setStringValue: ""];
|
|
||||||
|
|
||||||
[quakeed_i makeFirstResponder: quakeed_i];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Action methods
|
|
||||||
//
|
|
||||||
|
|
||||||
-addPair:sender
|
|
||||||
{
|
|
||||||
char *key, *value;
|
|
||||||
|
|
||||||
key = (char *)[keyInput_i stringValue];
|
|
||||||
value = (char *)[valueInput_i stringValue];
|
|
||||||
|
|
||||||
[ [map_i currentEntity] setKey: key toValue: value ];
|
|
||||||
|
|
||||||
[keypairview_i calcViewSize];
|
|
||||||
[keypairview_i display];
|
|
||||||
|
|
||||||
[self clearInputs];
|
|
||||||
[quakeed_i updateXY];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
-delPair:sender
|
|
||||||
{
|
|
||||||
[quakeed_i makeFirstResponder: quakeed_i];
|
|
||||||
|
|
||||||
[ [map_i currentEntity] removeKeyPair: (char *)[keyInput_i stringValue] ];
|
|
||||||
|
|
||||||
[keypairview_i calcViewSize];
|
|
||||||
[keypairview_i display];
|
|
||||||
|
|
||||||
[self clearInputs];
|
|
||||||
|
|
||||||
[quakeed_i updateXY];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set the key/value fields to "angle <button value>"
|
|
||||||
//
|
|
||||||
- setAngle:sender
|
|
||||||
{
|
|
||||||
const char *title;
|
|
||||||
char value[10];
|
|
||||||
|
|
||||||
title = [[sender selectedCell] title];
|
|
||||||
if (!strcmp(title,"Up"))
|
|
||||||
strcpy (value, "-1");
|
|
||||||
else if (!strcmp(title,"Dn"))
|
|
||||||
strcpy (value, "-2");
|
|
||||||
else
|
|
||||||
strcpy (value, title);
|
|
||||||
|
|
||||||
[keyInput_i setStringValue:"angle"];
|
|
||||||
[valueInput_i setStringValue:value];
|
|
||||||
[self addPair:NULL];
|
|
||||||
|
|
||||||
[self clearInputs];
|
|
||||||
|
|
||||||
[quakeed_i updateXY];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- setFlags:sender
|
|
||||||
{
|
|
||||||
int flags;
|
|
||||||
int r, c, i;
|
|
||||||
id cell;
|
|
||||||
char str[20];
|
|
||||||
|
|
||||||
[self clearInputs];
|
|
||||||
flags = 0;
|
|
||||||
|
|
||||||
for (r=0 ; r<4 ; r++)
|
|
||||||
for (c=0 ; c<3 ; c++)
|
|
||||||
{
|
|
||||||
cell = [flags_i cellAtRow: r column: c];
|
|
||||||
i = ([cell intValue] > 0);
|
|
||||||
flags |= (i<< ((c*4)+r));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!flags)
|
|
||||||
[[map_i currentEntity] removeKeyPair: "spawnflags"];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf (str, "%i", flags);
|
|
||||||
[[map_i currentEntity] setKey: "spawnflags" toValue: str];
|
|
||||||
}
|
|
||||||
|
|
||||||
[keypairview_i calcViewSize];
|
|
||||||
[keypairview_i display];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Fill the Entity browser
|
|
||||||
// (Delegate method - delegated in Interface Builder)
|
|
||||||
//
|
|
||||||
- (int)browser:sender fillMatrix:matrix inColumn:(int)column
|
|
||||||
{
|
|
||||||
id cell;
|
|
||||||
int max;
|
|
||||||
int i;
|
|
||||||
id object;
|
|
||||||
|
|
||||||
max = [entity_classes_i count];
|
|
||||||
i = 0;
|
|
||||||
while(max--)
|
|
||||||
{
|
|
||||||
object = [entity_classes_i objectAtIndex:i];
|
|
||||||
[matrix addRow];
|
|
||||||
cell = [matrix cellAtRow:i++ column:0];
|
|
||||||
[cell setStringValue:[NSString stringWithCString:[object classname]]];
|
|
||||||
[cell setLeaf:YES];
|
|
||||||
[cell setLoaded:YES];
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,215 +0,0 @@
|
||||||
/*
|
|
||||||
Vector.h
|
|
||||||
|
|
||||||
Vector class definition
|
|
||||||
|
|
||||||
Copyright (C) 2001 Jeff Teunissen <deek@d2dc.net>
|
|
||||||
|
|
||||||
This program 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.
|
|
||||||
|
|
||||||
This program 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 this program; if not, write to:
|
|
||||||
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
For more information on vectors, see:
|
|
||||||
http://chortle.ccsu.ctstateu.edu/vectorLessons/vectorIndex.html
|
|
||||||
|
|
||||||
Vector formulae: (notation: vN = vector N)
|
|
||||||
|
|
||||||
Addition: vx + vy == (x1+y1, x2+y2, ...)
|
|
||||||
Subtraction: vx - vy == (x1-y1, x2-y2, ...) OR vx + (-vy)
|
|
||||||
(3, 3) - (2, 1) = (3, 3) + (-2, -1) = (1, 2)
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include <Config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#import <Vector.h>
|
|
||||||
|
|
||||||
@implementation Vector
|
|
||||||
|
|
||||||
- (id) initWithString: (NSString *) str
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) zero dimensions: (unsigned char) d
|
|
||||||
{
|
|
||||||
_numDimensions = d;
|
|
||||||
for (i = 0; i < d; i++)
|
|
||||||
_values[i] = 0.0;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) one dimensions: (unsigned char) d
|
|
||||||
{
|
|
||||||
_numDimensions = d;
|
|
||||||
for (i = 0; i < d; i++)
|
|
||||||
_values[i] = 1.0;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (double) x
|
|
||||||
{
|
|
||||||
if ([self dimensions] < 1) { // Makes no sense, but catch it
|
|
||||||
NSLog (@"Not enough dimensions for operation");
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
return _values[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (double) y
|
|
||||||
{
|
|
||||||
if ([self dimensions] < 2) { // Makes no sense, but catch it
|
|
||||||
NSLog (@"Not enough dimensions for operation");
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
return _values[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (double) z
|
|
||||||
{
|
|
||||||
if ([self dimensions] < 3) { // This one could happen
|
|
||||||
NSLog (@"Not enough dimensions for operation");
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
return _values[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (double) dimension: (unsigned char) d
|
|
||||||
{
|
|
||||||
if (d <= 0) { // deal with calls that don't make any sense
|
|
||||||
NSLog (@"Vectors cannot have zero dimensions");
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([self dimensions] < d) { // This one's easy to make happen
|
|
||||||
NSLog (@"Not enough dimensions for operation");
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
return _values[d - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (double) length;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
double temp;
|
|
||||||
|
|
||||||
for (i = 1; i <= [self dimensions]; i++)
|
|
||||||
temp += sqrt ([self dimension: i] ** 2);
|
|
||||||
|
|
||||||
return sqrt (temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) add: (Vector *) vec
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if ([vec dimensions] != [self dimensions])
|
|
||||||
NSLog (@"Tried to add unlike vectors");
|
|
||||||
|
|
||||||
for (i = 1; i <= [self dimensions]; i++)
|
|
||||||
[self setDimension: i to: [self dimension: i] + [vec dimension: i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
subtract:
|
|
||||||
|
|
||||||
Subtract a vector by adding its inverse
|
|
||||||
The temporary object is autoreleased so it will be deallocated when the
|
|
||||||
application loop completes
|
|
||||||
*/
|
|
||||||
- (void) subtract: (Vector *) vec
|
|
||||||
{
|
|
||||||
[self add: [[[vec copy] autorelease] invert]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) scale: (double) scalar
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < [self dimensions]; i++)
|
|
||||||
_values[i - 1] *= scalar;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
invert
|
|
||||||
|
|
||||||
Turn a vector around. Since vectors have no position, this is OK
|
|
||||||
*/
|
|
||||||
- (void) invert
|
|
||||||
{
|
|
||||||
[self scale: -1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Convert to a unit vector (make our length 1.0)
|
|
||||||
*/
|
|
||||||
- (void) normalize
|
|
||||||
{
|
|
||||||
[self scale: 1.0 / [self length]];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
/*
|
|
||||||
Get the dot product
|
|
||||||
*/
|
|
||||||
double
|
|
||||||
DotProduct (Vector *x, Vector *y)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
unsigned int d;
|
|
||||||
double product = 0.0;
|
|
||||||
|
|
||||||
if ([x dimensions] != [y dimensions]) {
|
|
||||||
NSLog (@"Tried to get the dot product of unlike vectors");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 1, d = [x dimensions]; i <= d; i++) {
|
|
||||||
product += [x dimension: i] * [y dimension: i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return product;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
CrossProduct ()
|
|
||||||
|
|
||||||
Get the cross product
|
|
||||||
*/
|
|
||||||
Vector *
|
|
||||||
CrossProduct (Vector *a, Vector *b)
|
|
||||||
{
|
|
||||||
Vector *newVec = [[[Vector alloc] zero dimensions: 3] autorelease];
|
|
||||||
|
|
||||||
if (([a dimensions] != 3) || ([b dimensions] != 3)) {
|
|
||||||
NSLog (@"Tried to get the cross product of non-3D vectors");
|
|
||||||
return (Vector *) nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
[newVec setX: ([a y] * [b z]) - ([a z] * [b y])];
|
|
||||||
[newVec setY: ([a z] * [b x]) - ([a x] * [b z])];
|
|
||||||
[newVec setZ: ([a x] * [b y]) - ([a y] * [b x])];
|
|
||||||
}
|
|
1386
tools/Forge/XYView.m
1386
tools/Forge/XYView.m
File diff suppressed because it is too large
Load diff
|
@ -1,71 +0,0 @@
|
||||||
#import "qedefs.h"
|
|
||||||
|
|
||||||
@implementation ZScrollView
|
|
||||||
|
|
||||||
/*
|
|
||||||
====================
|
|
||||||
initFrame: button:
|
|
||||||
|
|
||||||
Initizes a scroll view with a button at it's lower right corner
|
|
||||||
====================
|
|
||||||
*/
|
|
||||||
|
|
||||||
- initFrame:(const NSRect *)frameRect button1:b1
|
|
||||||
{
|
|
||||||
[super initFrame: frameRect];
|
|
||||||
|
|
||||||
[self addSubview: b1];
|
|
||||||
|
|
||||||
button1 = b1;
|
|
||||||
|
|
||||||
[self setHorizScrollerRequired: YES];
|
|
||||||
[self setVertScrollerRequired: YES];
|
|
||||||
|
|
||||||
[self setBorderType: NX_BEZEL];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
tile
|
|
||||||
|
|
||||||
Adjust the size for the pop up scale menu
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
|
|
||||||
- tile
|
|
||||||
{
|
|
||||||
NSRect scrollerframe;
|
|
||||||
|
|
||||||
[super tile];
|
|
||||||
[hScroller getFrame: &scrollerframe];
|
|
||||||
[button1 setFrame: &scrollerframe];
|
|
||||||
|
|
||||||
scrollerframe.size.width = 0;
|
|
||||||
[hScroller setFrame: &scrollerframe];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-(BOOL) acceptsFirstResponder
|
|
||||||
{
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- superviewSizeChanged:(const NSSize *)oldSize
|
|
||||||
{
|
|
||||||
[super superviewSizeChanged: oldSize];
|
|
||||||
|
|
||||||
[[self docView] newSuperBounds];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
|
@ -1,872 +0,0 @@
|
||||||
|
|
||||||
#import "qedefs.h"
|
|
||||||
|
|
||||||
id zview_i;
|
|
||||||
|
|
||||||
id zscrollview_i, zscalemenu_i, zscalebutton_i;
|
|
||||||
|
|
||||||
float zplane;
|
|
||||||
float zplanedir;
|
|
||||||
|
|
||||||
@implementation ZView
|
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
initFrame:
|
|
||||||
==================
|
|
||||||
*/
|
|
||||||
- initFrame:(const NSRect *)frameRect
|
|
||||||
{
|
|
||||||
NSPoint pt;
|
|
||||||
|
|
||||||
origin[0] = 0.333;
|
|
||||||
origin[1] = 0.333;
|
|
||||||
|
|
||||||
[super initFrame:frameRect];
|
|
||||||
[self allocateGState];
|
|
||||||
[self clearBounds];
|
|
||||||
|
|
||||||
zview_i = self;
|
|
||||||
scale = 1;
|
|
||||||
|
|
||||||
//
|
|
||||||
// initialize the pop up menus
|
|
||||||
//
|
|
||||||
zscalemenu_i = [[PopUpList alloc] init];
|
|
||||||
[zscalemenu_i setTarget: self];
|
|
||||||
[zscalemenu_i setAction: @selector(scaleMenuTarget:)];
|
|
||||||
|
|
||||||
[zscalemenu_i addItem: "12.5%"];
|
|
||||||
[zscalemenu_i addItem: "25%"];
|
|
||||||
[zscalemenu_i addItem: "50%"];
|
|
||||||
[zscalemenu_i addItem: "75%"];
|
|
||||||
[zscalemenu_i addItem: "100%"];
|
|
||||||
[zscalemenu_i addItem: "200%"];
|
|
||||||
[zscalemenu_i addItem: "300%"];
|
|
||||||
[[zscalemenu_i itemList] selectCellAt: 4 : 0];
|
|
||||||
|
|
||||||
zscalebutton_i = NXCreatePopUpListButton(zscalemenu_i);
|
|
||||||
|
|
||||||
|
|
||||||
// initialize the scroll view
|
|
||||||
zscrollview_i = [[ZScrollView alloc]
|
|
||||||
initFrame: frameRect
|
|
||||||
button1: zscalebutton_i
|
|
||||||
];
|
|
||||||
[zscrollview_i setAutosizing: NX_WIDTHSIZABLE | NX_HEIGHTSIZABLE];
|
|
||||||
|
|
||||||
[[zscrollview_i setDocView: self] free];
|
|
||||||
|
|
||||||
// [superview setDrawOrigin: 0 : 0];
|
|
||||||
|
|
||||||
minheight = 0;
|
|
||||||
maxheight = 64;
|
|
||||||
|
|
||||||
pt.x = -bounds.size.width;
|
|
||||||
pt.y = -128;
|
|
||||||
|
|
||||||
[self newRealBounds];
|
|
||||||
|
|
||||||
[self setOrigin: &pt scale: 1];
|
|
||||||
|
|
||||||
return zscrollview_i;
|
|
||||||
}
|
|
||||||
|
|
||||||
- setXYOrigin: (NSPoint *)pt
|
|
||||||
{
|
|
||||||
origin[0] = pt->x + 0.333;
|
|
||||||
origin[1] = pt->y + 0.333;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (float)currentScale
|
|
||||||
{
|
|
||||||
return scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
setOrigin:scale:
|
|
||||||
===================
|
|
||||||
*/
|
|
||||||
- setOrigin: (NSPoint *)pt scale: (float)sc
|
|
||||||
{
|
|
||||||
NSRect sframe;
|
|
||||||
NSRect newbounds;
|
|
||||||
|
|
||||||
//
|
|
||||||
// calculate the area visible in the cliprect
|
|
||||||
//
|
|
||||||
scale = sc;
|
|
||||||
|
|
||||||
[superview getFrame: &sframe];
|
|
||||||
[superview getFrame: &newbounds];
|
|
||||||
newbounds.origin = *pt;
|
|
||||||
newbounds.size.width /= scale;
|
|
||||||
newbounds.size.height /= scale;
|
|
||||||
|
|
||||||
//
|
|
||||||
// union with the realbounds
|
|
||||||
//
|
|
||||||
if (newbounds.origin.y > oldminheight)
|
|
||||||
{
|
|
||||||
newbounds.size.height += newbounds.origin.y - oldminheight;
|
|
||||||
newbounds.origin.y = oldminheight;
|
|
||||||
}
|
|
||||||
if (newbounds.origin.y+newbounds.size.height < oldmaxheight)
|
|
||||||
{
|
|
||||||
newbounds.size.height += oldmaxheight
|
|
||||||
- (newbounds.origin.y + newbounds.size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// redisplay everything
|
|
||||||
//
|
|
||||||
[quakeed_i disableDisplay];
|
|
||||||
|
|
||||||
//
|
|
||||||
// size this view
|
|
||||||
//
|
|
||||||
[self sizeTo: newbounds.size.width : newbounds.size.height];
|
|
||||||
[self setDrawOrigin: -newbounds.size.width/2 : newbounds.origin.y];
|
|
||||||
[self moveTo: -newbounds.size.width/2 : newbounds.origin.y];
|
|
||||||
|
|
||||||
//
|
|
||||||
// scroll and scale the clip view
|
|
||||||
//
|
|
||||||
[superview setDrawSize
|
|
||||||
: sframe.size.width/scale
|
|
||||||
: sframe.size.height/scale];
|
|
||||||
[superview setDrawOrigin: pt->x : pt->y];
|
|
||||||
|
|
||||||
[quakeed_i reenableDisplay];
|
|
||||||
[zscrollview_i display];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
====================
|
|
||||||
scaleMenuTarget:
|
|
||||||
|
|
||||||
Called when the scaler popup on the window is used
|
|
||||||
====================
|
|
||||||
*/
|
|
||||||
- scaleMenuTarget: sender
|
|
||||||
{
|
|
||||||
char const *item;
|
|
||||||
NSRect visrect, sframe;
|
|
||||||
float nscale;
|
|
||||||
|
|
||||||
item = [[sender selectedCell] title];
|
|
||||||
sscanf (item,"%f",&nscale);
|
|
||||||
nscale /= 100;
|
|
||||||
|
|
||||||
if (nscale == scale)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// keep the center of the view constant
|
|
||||||
[superview getBounds: &visrect];
|
|
||||||
[superview getFrame: &sframe];
|
|
||||||
visrect.origin.x += visrect.size.width/2;
|
|
||||||
visrect.origin.y += visrect.size.height/2;
|
|
||||||
|
|
||||||
visrect.origin.x -= sframe.size.width/2/nscale;
|
|
||||||
visrect.origin.y -= sframe.size.height/2/nscale;
|
|
||||||
|
|
||||||
[self setOrigin: &visrect.origin scale: nscale];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- clearBounds
|
|
||||||
{
|
|
||||||
topbound = 999999;
|
|
||||||
bottombound = -999999;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- getBounds: (float *)top :(float *)bottom;
|
|
||||||
{
|
|
||||||
*top = topbound;
|
|
||||||
*bottom = bottombound;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
addToHeightRange:
|
|
||||||
==================
|
|
||||||
*/
|
|
||||||
- addToHeightRange: (float)height
|
|
||||||
{
|
|
||||||
if (height < minheight)
|
|
||||||
minheight = height;
|
|
||||||
if (height > maxheight)
|
|
||||||
maxheight = height;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
newSuperBounds
|
|
||||||
|
|
||||||
When superview is resized
|
|
||||||
==================
|
|
||||||
*/
|
|
||||||
- newSuperBounds
|
|
||||||
{
|
|
||||||
oldminheight++;
|
|
||||||
[self newRealBounds];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
newRealBounds
|
|
||||||
|
|
||||||
Should only change the scroll bars, not cause any redraws.
|
|
||||||
If realbounds has shrunk, nothing will change.
|
|
||||||
===================
|
|
||||||
*/
|
|
||||||
- newRealBounds
|
|
||||||
{
|
|
||||||
NSRect sbounds;
|
|
||||||
float vistop, visbottom;
|
|
||||||
|
|
||||||
if (minheight == oldminheight && maxheight == oldmaxheight)
|
|
||||||
return self;
|
|
||||||
|
|
||||||
oldminheight = minheight;
|
|
||||||
oldmaxheight = maxheight;
|
|
||||||
|
|
||||||
minheight -= 16;
|
|
||||||
maxheight += 16;
|
|
||||||
|
|
||||||
//
|
|
||||||
// calculate the area visible in the cliprect
|
|
||||||
//
|
|
||||||
[superview getBounds: &sbounds];
|
|
||||||
visbottom = sbounds.origin.y;
|
|
||||||
vistop = visbottom + sbounds.size.height;
|
|
||||||
|
|
||||||
if (vistop > maxheight)
|
|
||||||
maxheight = vistop;
|
|
||||||
if (visbottom < minheight)
|
|
||||||
minheight = visbottom;
|
|
||||||
if (minheight == bounds.origin.y && maxheight-minheight == bounds.size.height)
|
|
||||||
return self;
|
|
||||||
|
|
||||||
sbounds.origin.y = minheight;
|
|
||||||
sbounds.size.height = maxheight - minheight;
|
|
||||||
|
|
||||||
//
|
|
||||||
// size this view
|
|
||||||
//
|
|
||||||
[quakeed_i disableDisplay];
|
|
||||||
|
|
||||||
[self suspendNotifyAncestorWhenFrameChanged:YES];
|
|
||||||
[self sizeTo: sbounds.size.width : sbounds.size.height];
|
|
||||||
[self setDrawOrigin: -sbounds.size.width/2 : sbounds.origin.y];
|
|
||||||
[self moveTo: -sbounds.size.width/2 : sbounds.origin.y];
|
|
||||||
[self suspendNotifyAncestorWhenFrameChanged:NO];
|
|
||||||
[[superview superview] reflectScroll: superview];
|
|
||||||
|
|
||||||
[quakeed_i reenableDisplay];
|
|
||||||
|
|
||||||
[[[[self superview] superview] vertScroller] display];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
============
|
|
||||||
drawGrid
|
|
||||||
|
|
||||||
Draws tile markings every 64 units, and grid markings at the grid scale if
|
|
||||||
the grid lines are >= 4 pixels apart
|
|
||||||
|
|
||||||
Rect is in global world (unscaled) coordinates
|
|
||||||
============
|
|
||||||
*/
|
|
||||||
|
|
||||||
- drawGrid: (const NSRect *)rect
|
|
||||||
{
|
|
||||||
int y, stopy;
|
|
||||||
float top,bottom;
|
|
||||||
int left, right;
|
|
||||||
int gridsize;
|
|
||||||
char text[10];
|
|
||||||
BOOL showcoords;
|
|
||||||
|
|
||||||
showcoords = [quakeed_i showCoordinates];
|
|
||||||
|
|
||||||
PSsetlinewidth (0);
|
|
||||||
|
|
||||||
gridsize = [xyview_i gridsize];
|
|
||||||
|
|
||||||
left = bounds.origin.x;
|
|
||||||
right = 24;
|
|
||||||
|
|
||||||
bottom = rect->origin.y-1;
|
|
||||||
top = rect->origin.y+rect->size.height+2;
|
|
||||||
|
|
||||||
//
|
|
||||||
// grid
|
|
||||||
//
|
|
||||||
// can't just divide by grid size because of negetive coordinate
|
|
||||||
// truncating direction
|
|
||||||
//
|
|
||||||
if (gridsize>= 4/scale)
|
|
||||||
{
|
|
||||||
y = floor(bottom/gridsize);
|
|
||||||
stopy = floor(top/gridsize);
|
|
||||||
|
|
||||||
y *= gridsize;
|
|
||||||
stopy *= gridsize;
|
|
||||||
if (y<bottom)
|
|
||||||
y+= gridsize;
|
|
||||||
|
|
||||||
beginUserPath (upath,NO);
|
|
||||||
|
|
||||||
for ( ; y<=stopy ; y+= gridsize)
|
|
||||||
if (y&31)
|
|
||||||
{
|
|
||||||
UPmoveto (upath, left, y);
|
|
||||||
UPlineto (upath, right, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
endUserPath (upath, dps_ustroke);
|
|
||||||
PSsetrgbcolor (0.8,0.8,1.0); // thin grid color
|
|
||||||
sendUserPath (upath);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// half tiles
|
|
||||||
//
|
|
||||||
y = floor(bottom/32);
|
|
||||||
stopy = floor(top/32);
|
|
||||||
|
|
||||||
if ( ! (((int)y + 4096) & 1) )
|
|
||||||
y++;
|
|
||||||
y *= 32;
|
|
||||||
stopy *= 32;
|
|
||||||
if (stopy >= top)
|
|
||||||
stopy -= 32;
|
|
||||||
|
|
||||||
beginUserPath (upath,NO);
|
|
||||||
|
|
||||||
for ( ; y<=stopy ; y+= 64)
|
|
||||||
{
|
|
||||||
UPmoveto (upath, left, y);
|
|
||||||
UPlineto (upath, right, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
endUserPath (upath, dps_ustroke);
|
|
||||||
PSsetgray (12.0/16.0);
|
|
||||||
sendUserPath (upath);
|
|
||||||
|
|
||||||
//
|
|
||||||
// tiles
|
|
||||||
//
|
|
||||||
y = floor(bottom/64);
|
|
||||||
stopy = floor(top/64);
|
|
||||||
|
|
||||||
y *= 64;
|
|
||||||
stopy *= 64;
|
|
||||||
if (y<bottom)
|
|
||||||
y+= 64;
|
|
||||||
if (stopy >= top)
|
|
||||||
stopy -= 64;
|
|
||||||
|
|
||||||
beginUserPath (upath,NO);
|
|
||||||
PSsetgray (0); // for text
|
|
||||||
PSselectfont("Helvetica-Medium",10/scale);
|
|
||||||
PSrotate(0);
|
|
||||||
|
|
||||||
for ( ; y<=stopy ; y+= 64)
|
|
||||||
{
|
|
||||||
if (showcoords)
|
|
||||||
{
|
|
||||||
sprintf (text, "%i",y);
|
|
||||||
PSmoveto(left,y);
|
|
||||||
PSshow(text);
|
|
||||||
}
|
|
||||||
UPmoveto (upath, left+24, y);
|
|
||||||
UPlineto (upath, right, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// divider
|
|
||||||
UPmoveto (upath, 0, bounds.origin.y);
|
|
||||||
UPlineto (upath, 0, bounds.origin.y + bounds.size.height);
|
|
||||||
|
|
||||||
endUserPath (upath, dps_ustroke);
|
|
||||||
PSsetgray (10.0/16.0);
|
|
||||||
sendUserPath (upath);
|
|
||||||
|
|
||||||
//
|
|
||||||
// origin
|
|
||||||
//
|
|
||||||
PSsetlinewidth (5);
|
|
||||||
PSsetgray (4.0/16.0);
|
|
||||||
PSmoveto (right,0);
|
|
||||||
PSlineto (left,0);
|
|
||||||
PSstroke ();
|
|
||||||
PSsetlinewidth (0.15);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- drawZplane
|
|
||||||
{
|
|
||||||
PSsetrgbcolor (0.2, 0.2, 0);
|
|
||||||
PSarc (0, zplane, 4, 0, M_PI*2);
|
|
||||||
PSfill ();
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============================================================================
|
|
||||||
drawSelf
|
|
||||||
===============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
- drawSelf:(const NSRect *)rects :(int)rectCount
|
|
||||||
{
|
|
||||||
NSRect visRect;
|
|
||||||
|
|
||||||
minheight = 999999;
|
|
||||||
maxheight = -999999;
|
|
||||||
|
|
||||||
// always draw the entire bar
|
|
||||||
[self getVisibleRect:&visRect];
|
|
||||||
rects = &visRect;
|
|
||||||
|
|
||||||
// erase window
|
|
||||||
NSEraseRect (&rects[0]);
|
|
||||||
|
|
||||||
// draw grid
|
|
||||||
[self drawGrid: &rects[0]];
|
|
||||||
|
|
||||||
// draw zplane
|
|
||||||
// [self drawZplane];
|
|
||||||
|
|
||||||
// draw all entities
|
|
||||||
[map_i makeUnselectedPerform: @selector(ZDrawSelf)];
|
|
||||||
|
|
||||||
// possibly resize the view
|
|
||||||
[self newRealBounds];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
==============
|
|
||||||
XYDrawSelf
|
|
||||||
==============
|
|
||||||
*/
|
|
||||||
- XYDrawSelf
|
|
||||||
{
|
|
||||||
PSsetrgbcolor (0,0.5,1.0);
|
|
||||||
PSsetlinewidth (0.15);
|
|
||||||
PSmoveto (origin[0]-16, origin[1]-16);
|
|
||||||
PSrlineto (32,32);
|
|
||||||
PSmoveto (origin[0]-16, origin[1]+16);
|
|
||||||
PSrlineto (32,-32);
|
|
||||||
PSstroke ();
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
==============
|
|
||||||
getPoint: (NSPoint *)pt
|
|
||||||
==============
|
|
||||||
*/
|
|
||||||
- getPoint: (NSPoint *)pt
|
|
||||||
{
|
|
||||||
pt->x = origin[0] + 0.333; // offset a bit to avoid edge cases
|
|
||||||
pt->y = origin[1] + 0.333;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- setPoint: (NSPoint *)pt
|
|
||||||
{
|
|
||||||
origin[0] = pt->x;
|
|
||||||
origin[1] = pt->y;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
MOUSE CLICKING
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
dragLoop:
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
static NSPoint oldreletive;
|
|
||||||
- dragFrom: (NSEvent *)startevent
|
|
||||||
useGrid: (BOOL)ug
|
|
||||||
callback: (void (*) (float dy)) callback
|
|
||||||
{
|
|
||||||
NSEvent *event;
|
|
||||||
NSPoint startpt, newpt;
|
|
||||||
NSPoint reletive, delta;
|
|
||||||
int gridsize;
|
|
||||||
|
|
||||||
gridsize = [xyview_i gridsize];
|
|
||||||
|
|
||||||
startpt = startevent->location;
|
|
||||||
[self convertPoint:&startpt fromView:NULL];
|
|
||||||
|
|
||||||
oldreletive.x = oldreletive.y = 0;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
event = [NSApp getNextEvent:
|
|
||||||
NSLeftMouseUpMask | NSLeftMouseDraggedMask
|
|
||||||
| NSRightMouseUpMask | NSRightMouseDraggedMask];
|
|
||||||
if (event->type == NSLeftMouseUp || event->type == NSRightMouseUp)
|
|
||||||
break;
|
|
||||||
|
|
||||||
newpt = event->location;
|
|
||||||
[self convertPoint:&newpt fromView:NULL];
|
|
||||||
|
|
||||||
reletive.y = newpt.y - startpt.y;
|
|
||||||
|
|
||||||
if (ug)
|
|
||||||
{ // we want truncate towards 0 behavior here
|
|
||||||
reletive.y = gridsize * (int)(reletive.y / gridsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reletive.y == oldreletive.y)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
delta.y = reletive.y - oldreletive.y;
|
|
||||||
oldreletive = reletive;
|
|
||||||
callback (delta.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
void ZDragCallback (float dy)
|
|
||||||
{
|
|
||||||
sb_translate[0] = 0;
|
|
||||||
sb_translate[1] = 0;
|
|
||||||
sb_translate[2] = dy;
|
|
||||||
|
|
||||||
[map_i makeSelectedPerform: @selector(translate)];
|
|
||||||
|
|
||||||
[quakeed_i redrawInstance];
|
|
||||||
}
|
|
||||||
|
|
||||||
- selectionDragFrom: (NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
qprintf ("dragging selection");
|
|
||||||
[self dragFrom: theEvent
|
|
||||||
useGrid: YES
|
|
||||||
callback: ZDragCallback ];
|
|
||||||
[quakeed_i updateCamera];
|
|
||||||
qprintf ("");
|
|
||||||
return self;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
void ZScrollCallback (float dy)
|
|
||||||
{
|
|
||||||
NSRect basebounds;
|
|
||||||
NSPoint neworg;
|
|
||||||
float scale;
|
|
||||||
|
|
||||||
[ [zview_i superview] getBounds: &basebounds];
|
|
||||||
[zview_i convertRectFromSuperview: &basebounds];
|
|
||||||
|
|
||||||
neworg.y = basebounds.origin.y - dy;
|
|
||||||
|
|
||||||
scale = [zview_i currentScale];
|
|
||||||
|
|
||||||
oldreletive.y -= dy;
|
|
||||||
[zview_i setOrigin: &neworg scale: scale];
|
|
||||||
}
|
|
||||||
|
|
||||||
- scrollDragFrom: (NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
qprintf ("scrolling view");
|
|
||||||
[self dragFrom: theEvent
|
|
||||||
useGrid: YES
|
|
||||||
callback: ZScrollCallback ];
|
|
||||||
qprintf ("");
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
void ZControlCallback (float dy)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0 ; i<numcontrolpoints ; i++)
|
|
||||||
controlpoints[i][2] += dy;
|
|
||||||
|
|
||||||
[[map_i selectedBrush] calcWindings];
|
|
||||||
[quakeed_i redrawInstance];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)planeDragFrom: (NSEvent*)theEvent
|
|
||||||
{
|
|
||||||
NSPoint pt;
|
|
||||||
vec3_t dragpoint;
|
|
||||||
|
|
||||||
if ([map_i numSelected] != 1)
|
|
||||||
return NO;
|
|
||||||
|
|
||||||
pt= theEvent->location;
|
|
||||||
[self convertPoint:&pt fromView:NULL];
|
|
||||||
|
|
||||||
dragpoint[0] = origin[0];
|
|
||||||
dragpoint[1] = origin[1];
|
|
||||||
dragpoint[2] = pt.y;
|
|
||||||
|
|
||||||
[[map_i selectedBrush] getZdragface: dragpoint];
|
|
||||||
if (!numcontrolpoints)
|
|
||||||
return NO;
|
|
||||||
|
|
||||||
qprintf ("dragging brush plane");
|
|
||||||
|
|
||||||
pt= theEvent->location;
|
|
||||||
[self convertPoint:&pt fromView:NULL];
|
|
||||||
|
|
||||||
[self dragFrom: theEvent
|
|
||||||
useGrid: YES
|
|
||||||
callback: ZControlCallback ];
|
|
||||||
|
|
||||||
[[map_i selectedBrush] removeIfInvalid];
|
|
||||||
|
|
||||||
[quakeed_i updateCamera];
|
|
||||||
qprintf ("");
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
mouseDown
|
|
||||||
===================
|
|
||||||
*/
|
|
||||||
- mouseDown:(NSEvent *)theEvent
|
|
||||||
{
|
|
||||||
NSPoint pt;
|
|
||||||
int flags;
|
|
||||||
vec3_t p1;
|
|
||||||
|
|
||||||
pt= theEvent->location;
|
|
||||||
[self convertPoint:&pt fromView:NULL];
|
|
||||||
|
|
||||||
p1[0] = origin[0];
|
|
||||||
p1[1] = origin[1];
|
|
||||||
p1[2] = pt.y;
|
|
||||||
|
|
||||||
flags = theEvent->flags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask);
|
|
||||||
|
|
||||||
//
|
|
||||||
// shift click to select / deselect a brush from the world
|
|
||||||
//
|
|
||||||
if (flags == NSShiftKeyMask)
|
|
||||||
{
|
|
||||||
[map_i selectRay: p1 : p1 : NO];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// alt click = set entire brush texture
|
|
||||||
//
|
|
||||||
if (flags == NSAlternateKeyMask)
|
|
||||||
{
|
|
||||||
[map_i setTextureRay: p1 : p1 : YES];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// control click = position view
|
|
||||||
//
|
|
||||||
if (flags == NSControlKeyMask)
|
|
||||||
{
|
|
||||||
[cameraview_i setZOrigin: pt.y];
|
|
||||||
[quakeed_i updateAll];
|
|
||||||
[cameraview_i ZmouseDown: &pt flags:theEvent->flags];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// bare click to drag icons or new brush drag
|
|
||||||
//
|
|
||||||
if ( flags == 0 )
|
|
||||||
{
|
|
||||||
// check eye
|
|
||||||
if ( [cameraview_i ZmouseDown: &pt flags:theEvent->flags] )
|
|
||||||
return self;
|
|
||||||
|
|
||||||
if ([map_i numSelected])
|
|
||||||
{
|
|
||||||
if ( pt.x > 0)
|
|
||||||
{
|
|
||||||
if ([self planeDragFrom: theEvent])
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
[self selectionDragFrom: theEvent];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
qprintf ("bad flags for click");
|
|
||||||
NopSound ();
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===================
|
|
||||||
rightMouseDown
|
|
||||||
===================
|
|
||||||
*/
|
|
||||||
- rightMouseDown:(NSEvent *)theEvent
|
|
||||||
{
|
|
||||||
NSPoint pt;
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
pt= theEvent->location;
|
|
||||||
[self convertPoint:&pt fromView:NULL];
|
|
||||||
|
|
||||||
flags = theEvent->flags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// click = scroll view
|
|
||||||
//
|
|
||||||
if (flags == 0)
|
|
||||||
{
|
|
||||||
return [self scrollDragFrom: theEvent];
|
|
||||||
}
|
|
||||||
|
|
||||||
qprintf ("bad flags for click");
|
|
||||||
NopSound ();
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============================================================================
|
|
||||||
|
|
||||||
XY mouse view methods
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
modalMoveLoop
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
- modalMoveLoop: (NSPoint *)basept :(vec3_t)movemod : converter
|
|
||||||
{
|
|
||||||
vec3_t originbase;
|
|
||||||
NSEvent *event;
|
|
||||||
NSPoint newpt;
|
|
||||||
vec3_t delta;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
VectorCopy (origin, originbase);
|
|
||||||
|
|
||||||
//
|
|
||||||
// modal event loop using instance drawing
|
|
||||||
//
|
|
||||||
goto drawentry;
|
|
||||||
|
|
||||||
while (event->type != NSLeftMouseUp)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// calculate new point
|
|
||||||
//
|
|
||||||
newpt = event->location;
|
|
||||||
[converter convertPoint:&newpt fromView:NULL];
|
|
||||||
|
|
||||||
delta[0] = newpt.x-basept->x;
|
|
||||||
delta[1] = newpt.y-basept->y;
|
|
||||||
delta[2] = delta[1]; // height change
|
|
||||||
|
|
||||||
for (i=0 ; i<3 ; i++)
|
|
||||||
origin[i] = originbase[i]+movemod[i]*delta[i];
|
|
||||||
|
|
||||||
|
|
||||||
drawentry:
|
|
||||||
//
|
|
||||||
// instance draw new frame
|
|
||||||
//
|
|
||||||
[quakeed_i newinstance];
|
|
||||||
[self display];
|
|
||||||
NSPing ();
|
|
||||||
|
|
||||||
event = [NSApp getNextEvent:
|
|
||||||
NSLeftMouseUpMask | NSLeftMouseDraggedMask];
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// draw the brush back into the window buffer
|
|
||||||
//
|
|
||||||
// [xyview_i display];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
XYmouseDown
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
- (BOOL)XYmouseDown: (NSPoint *)pt
|
|
||||||
{
|
|
||||||
vec3_t movemod;
|
|
||||||
|
|
||||||
if (fabs(pt->x - origin[0]) > 16
|
|
||||||
|| fabs(pt->y - origin[1]) > 16)
|
|
||||||
return NO;
|
|
||||||
|
|
||||||
movemod[0] = 1;
|
|
||||||
movemod[1] = 1;
|
|
||||||
movemod[2] = 0;
|
|
||||||
|
|
||||||
[self modalMoveLoop: pt : movemod : xyview_i];
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,274 +0,0 @@
|
||||||
|
|
||||||
#include "qedefs.h"
|
|
||||||
|
|
||||||
|
|
||||||
char token[MAXTOKEN];
|
|
||||||
boolean unget;
|
|
||||||
char *script_p;
|
|
||||||
int scriptline;
|
|
||||||
|
|
||||||
void StartTokenParsing (char *data)
|
|
||||||
{
|
|
||||||
scriptline = 1;
|
|
||||||
script_p = data;
|
|
||||||
unget = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean GetToken (boolean crossline)
|
|
||||||
{
|
|
||||||
char *token_p;
|
|
||||||
|
|
||||||
if (unget) // is a token already waiting?
|
|
||||||
return true;
|
|
||||||
|
|
||||||
//
|
|
||||||
// skip space
|
|
||||||
//
|
|
||||||
skipspace:
|
|
||||||
while (*script_p <= 32)
|
|
||||||
{
|
|
||||||
if (!*script_p)
|
|
||||||
{
|
|
||||||
if (!crossline)
|
|
||||||
Error ("Line %i is incomplete",scriptline);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (*script_p++ == '\n')
|
|
||||||
{
|
|
||||||
if (!crossline)
|
|
||||||
Error ("Line %i is incomplete",scriptline);
|
|
||||||
scriptline++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (script_p[0] == '/' && script_p[1] == '/') // comment field
|
|
||||||
{
|
|
||||||
if (!crossline)
|
|
||||||
Error ("Line %i is incomplete\n",scriptline);
|
|
||||||
while (*script_p++ != '\n')
|
|
||||||
if (!*script_p)
|
|
||||||
{
|
|
||||||
if (!crossline)
|
|
||||||
Error ("Line %i is incomplete",scriptline);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
goto skipspace;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// copy token
|
|
||||||
//
|
|
||||||
token_p = token;
|
|
||||||
|
|
||||||
if (*script_p == '"')
|
|
||||||
{
|
|
||||||
script_p++;
|
|
||||||
while ( *script_p != '"' )
|
|
||||||
{
|
|
||||||
if (!*script_p)
|
|
||||||
Error ("EOF inside quoted token");
|
|
||||||
*token_p++ = *script_p++;
|
|
||||||
if (token_p == &token[MAXTOKEN])
|
|
||||||
Error ("Token too large on line %i",scriptline);
|
|
||||||
}
|
|
||||||
script_p++;
|
|
||||||
}
|
|
||||||
else while ( *script_p > 32 )
|
|
||||||
{
|
|
||||||
*token_p++ = *script_p++;
|
|
||||||
if (token_p == &token[MAXTOKEN])
|
|
||||||
Error ("Token too large on line %i",scriptline);
|
|
||||||
}
|
|
||||||
|
|
||||||
*token_p = 0;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UngetToken ()
|
|
||||||
{
|
|
||||||
unget = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void qprintf (char *fmt, ...) // prints text to cmd_out_i
|
|
||||||
{
|
|
||||||
va_list argptr;
|
|
||||||
static char string[1024];
|
|
||||||
|
|
||||||
va_start (argptr, fmt);
|
|
||||||
vsprintf (string, fmt,argptr);
|
|
||||||
va_end (argptr);
|
|
||||||
|
|
||||||
[g_cmd_out_i setStringValue: string];
|
|
||||||
NSPing ();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
Error
|
|
||||||
|
|
||||||
For abnormal program terminations
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
BOOL in_error;
|
|
||||||
void Error (char *error, ...)
|
|
||||||
{
|
|
||||||
va_list argptr;
|
|
||||||
static char string[1024];
|
|
||||||
|
|
||||||
if (in_error)
|
|
||||||
[NSApp terminate: NULL];
|
|
||||||
in_error = YES;
|
|
||||||
|
|
||||||
va_start (argptr,error);
|
|
||||||
vsprintf (string,error,argptr);
|
|
||||||
va_end (argptr);
|
|
||||||
|
|
||||||
strcat (string, "\nmap saved to "FN_CRASHSAVE);
|
|
||||||
|
|
||||||
[map_i writeMapFile: FN_CRASHSAVE useRegion: NO];
|
|
||||||
NSRunAlertPanel ("Error",string,NULL,NULL,NULL);
|
|
||||||
|
|
||||||
[NSApp terminate: NULL];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CleanupName (char *in, char *out)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0 ; i< 16 ; i++ )
|
|
||||||
{
|
|
||||||
if (!in[i])
|
|
||||||
break;
|
|
||||||
|
|
||||||
out[i] = toupper(in[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( ; i< 16 ; i++ )
|
|
||||||
out[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PrintRect (NSRect *r)
|
|
||||||
{
|
|
||||||
printf ("(%4.0f, %4.0f) + (%4.0f, %4.0f) = (%4.0f,%4.0f)\n"
|
|
||||||
,r->origin.x,r->origin.y,
|
|
||||||
r->size.width, r->size.height, r->origin.x+r->size.width,
|
|
||||||
r->origin.y+r->size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
============
|
|
||||||
FileTime
|
|
||||||
|
|
||||||
returns -1 if not present
|
|
||||||
============
|
|
||||||
*/
|
|
||||||
int FileTime (char *path)
|
|
||||||
{
|
|
||||||
struct stat buf;
|
|
||||||
|
|
||||||
if (stat (path,&buf) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return buf.st_mtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
============
|
|
||||||
CreatePath
|
|
||||||
============
|
|
||||||
*/
|
|
||||||
void CreatePath (char *path)
|
|
||||||
{
|
|
||||||
char *ofs;
|
|
||||||
|
|
||||||
for (ofs = path+1 ; *ofs ; ofs++)
|
|
||||||
{
|
|
||||||
if (*ofs == '/')
|
|
||||||
{ // create the directory
|
|
||||||
*ofs = 0;
|
|
||||||
mkdir (path,0777);
|
|
||||||
*ofs = '/';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int I_FileOpenRead (char *path, int *handle)
|
|
||||||
{
|
|
||||||
int h;
|
|
||||||
struct stat fileinfo;
|
|
||||||
|
|
||||||
|
|
||||||
h = open (path, O_RDONLY, 0666);
|
|
||||||
*handle = h;
|
|
||||||
if (h == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (fstat (h,&fileinfo) == -1)
|
|
||||||
Error ("Error fstating %s", path);
|
|
||||||
|
|
||||||
return fileinfo.st_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int I_FileOpenWrite (char *path)
|
|
||||||
{
|
|
||||||
int handle;
|
|
||||||
|
|
||||||
umask (0);
|
|
||||||
|
|
||||||
handle = open(path,O_RDWR | O_CREAT | O_TRUNC
|
|
||||||
, 0666);
|
|
||||||
|
|
||||||
if (handle == -1)
|
|
||||||
Error ("Error opening %s: %s", path,strerror(errno));
|
|
||||||
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
============
|
|
||||||
Sys_UpdateFile
|
|
||||||
|
|
||||||
Copies a more recent net file to the local drive
|
|
||||||
============
|
|
||||||
*/
|
|
||||||
void Sys_UpdateFile (char *path, char *netpath)
|
|
||||||
{
|
|
||||||
int ltime, ntime;
|
|
||||||
int in, out, size;
|
|
||||||
char *buf;
|
|
||||||
|
|
||||||
ltime = FileTime (path);
|
|
||||||
ntime = FileTime (netpath);
|
|
||||||
|
|
||||||
if (ntime <= ltime)
|
|
||||||
return; // up to date
|
|
||||||
|
|
||||||
// copy the file
|
|
||||||
printf ("UpdateFile: copying %s to %s...\n", netpath, path);
|
|
||||||
|
|
||||||
size = I_FileOpenRead (netpath, &in);
|
|
||||||
buf = malloc (size);
|
|
||||||
if (read (in, buf, size) != size)
|
|
||||||
Error ("UpdateFile: couldn't read all of %s", netpath);
|
|
||||||
close (in);
|
|
||||||
|
|
||||||
CreatePath (path);
|
|
||||||
out = I_FileOpenWrite (path);
|
|
||||||
write (out, buf, size);
|
|
||||||
close (out);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,748 +0,0 @@
|
||||||
|
|
||||||
#import "qedefs.h"
|
|
||||||
|
|
||||||
|
|
||||||
//define NOLIGHT
|
|
||||||
|
|
||||||
vec3_t r_origin, r_matrix[3];
|
|
||||||
|
|
||||||
int t_width, t_height;
|
|
||||||
unsigned *t_data;
|
|
||||||
int t_widthmask, t_heightmask, t_widthshift;
|
|
||||||
float t_widthadd, t_heightadd;
|
|
||||||
|
|
||||||
int r_width, r_height;
|
|
||||||
float *r_zbuffer;
|
|
||||||
unsigned *r_picbuffer;
|
|
||||||
|
|
||||||
vec5_t rightside, leftside, rightstep,leftstep;
|
|
||||||
|
|
||||||
face_t *r_face;
|
|
||||||
|
|
||||||
BOOL r_drawflat;
|
|
||||||
|
|
||||||
pixel32_t r_flatcolor;
|
|
||||||
|
|
||||||
int sy[20];
|
|
||||||
|
|
||||||
/*
|
|
||||||
====================
|
|
||||||
REN_ClearBuffers
|
|
||||||
====================
|
|
||||||
*/
|
|
||||||
void REN_ClearBuffers (void)
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
|
|
||||||
size = r_width * r_height*4;
|
|
||||||
|
|
||||||
memset (r_zbuffer, 0, size);
|
|
||||||
memset (r_picbuffer, 0, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
====================
|
|
||||||
REN_SetTexture
|
|
||||||
====================
|
|
||||||
*/
|
|
||||||
|
|
||||||
void REN_SetTexture (face_t *face)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int t_heightshift;
|
|
||||||
qtexture_t *q;
|
|
||||||
|
|
||||||
if (!face->qtexture)
|
|
||||||
face->qtexture = TEX_ForName (face->texture.texture); // try to load
|
|
||||||
q = face->qtexture;
|
|
||||||
|
|
||||||
t_width = q->width;
|
|
||||||
t_height = q->height;
|
|
||||||
t_data = q->data;
|
|
||||||
r_flatcolor = q->flatcolor;
|
|
||||||
|
|
||||||
r_flatcolor.chan[0] *= r_face->light;
|
|
||||||
r_flatcolor.chan[1] *= r_face->light;
|
|
||||||
r_flatcolor.chan[2] *= r_face->light;
|
|
||||||
|
|
||||||
t_widthadd = t_width*1024;
|
|
||||||
t_heightadd = t_height*1024;
|
|
||||||
|
|
||||||
t_widthmask = t_width-1;
|
|
||||||
t_heightmask = t_height-1;
|
|
||||||
|
|
||||||
t_widthshift = 0;
|
|
||||||
i = t_width;
|
|
||||||
while (i >= 2)
|
|
||||||
{
|
|
||||||
t_widthshift++;
|
|
||||||
i>>=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
t_heightshift = 0;
|
|
||||||
i = t_width;
|
|
||||||
while (i >= 2)
|
|
||||||
{
|
|
||||||
t_heightshift++;
|
|
||||||
i>>=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (1<<t_widthshift) != t_width || (1<<t_heightshift) != t_height)
|
|
||||||
t_widthshift = t_heightshift = 0; // non power of two
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
REN_DrawSpan
|
|
||||||
==================
|
|
||||||
*/
|
|
||||||
void REN_DrawSpan (int y)
|
|
||||||
{
|
|
||||||
int x, count;
|
|
||||||
int ofs;
|
|
||||||
int tx, ty;
|
|
||||||
int x1, x2;
|
|
||||||
float ufrac, vfrac, zfrac, lightfrac, ustep, vstep, zstep;
|
|
||||||
pixel32_t *in, *out;
|
|
||||||
float scale;
|
|
||||||
|
|
||||||
if (y<0 || y >= r_height)
|
|
||||||
return;
|
|
||||||
|
|
||||||
x1 = (leftside[0]);
|
|
||||||
x2 = (rightside[0]);
|
|
||||||
|
|
||||||
count = x2 - x1;
|
|
||||||
if (count < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
zfrac = leftside[2];
|
|
||||||
ufrac = leftside[3];
|
|
||||||
vfrac = leftside[4];
|
|
||||||
lightfrac = r_face->light;
|
|
||||||
|
|
||||||
if (!count)
|
|
||||||
scale = 1;
|
|
||||||
else
|
|
||||||
scale = 1.0/count;
|
|
||||||
|
|
||||||
zstep = (rightside[2] - zfrac)*scale;
|
|
||||||
ustep = (rightside[3] - ufrac)*scale;
|
|
||||||
vstep = (rightside[4] - vfrac)*scale;
|
|
||||||
|
|
||||||
if (x1 < 0)
|
|
||||||
{
|
|
||||||
ufrac -= x1*ustep;
|
|
||||||
vfrac -= x1*vstep;
|
|
||||||
zfrac -= x1*zstep;
|
|
||||||
x1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x2 > r_width)
|
|
||||||
x2 = r_width;
|
|
||||||
|
|
||||||
ofs = y*r_width+x1;
|
|
||||||
|
|
||||||
// this should be specialized for 1.0 / 0.5 / 0.75 light levels
|
|
||||||
for (x=x1 ; x < x2 ; x++)
|
|
||||||
{
|
|
||||||
if (r_zbuffer[ofs] <= zfrac)
|
|
||||||
{
|
|
||||||
scale = 1/zfrac;
|
|
||||||
|
|
||||||
r_zbuffer[ofs] = zfrac;
|
|
||||||
|
|
||||||
if (t_widthshift)
|
|
||||||
{
|
|
||||||
tx = (int)((ufrac*scale)) & t_widthmask;
|
|
||||||
ty = (int)((vfrac*scale)) & t_heightmask;
|
|
||||||
in = (pixel32_t *)&t_data [(ty<<t_widthshift)+tx];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tx = (int)((ufrac*scale)+t_widthadd) % t_width;
|
|
||||||
ty = (int)((vfrac*scale)+t_heightadd) % t_height;
|
|
||||||
in = (pixel32_t *)&t_data [ty*t_width+tx];
|
|
||||||
}
|
|
||||||
|
|
||||||
out = (pixel32_t *)&r_picbuffer[ofs];
|
|
||||||
#ifdef NOLIGHT
|
|
||||||
*out = *in;
|
|
||||||
#else
|
|
||||||
out->chan[0] = in->chan[0]*lightfrac;
|
|
||||||
out->chan[1] = in->chan[1]*lightfrac;
|
|
||||||
out->chan[2] = in->chan[2]*lightfrac;
|
|
||||||
out->chan[3] = 0xff;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
ufrac += ustep;
|
|
||||||
vfrac += vstep;
|
|
||||||
zfrac += zstep;
|
|
||||||
ofs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
REN_DrawFlatSpan
|
|
||||||
==================
|
|
||||||
*/
|
|
||||||
void REN_DrawFlatSpan (int y)
|
|
||||||
{
|
|
||||||
int x, count;
|
|
||||||
int ofs;
|
|
||||||
int x1, x2;
|
|
||||||
float zfrac, zstep;
|
|
||||||
pixel32_t *out;
|
|
||||||
|
|
||||||
if (y<0 || y >= r_height)
|
|
||||||
return;
|
|
||||||
|
|
||||||
x1 = (leftside[0]);
|
|
||||||
x2 = (rightside[0]);
|
|
||||||
|
|
||||||
count = x2 - x1;
|
|
||||||
if (count < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
zfrac = leftside[2];
|
|
||||||
|
|
||||||
zstep = (rightside[2] - zfrac)/count;
|
|
||||||
|
|
||||||
if (x1 < 0)
|
|
||||||
{
|
|
||||||
zfrac -= x1*zstep;
|
|
||||||
x1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x2 > r_width)
|
|
||||||
x2 = r_width;
|
|
||||||
|
|
||||||
ofs = y*r_width+x1;
|
|
||||||
|
|
||||||
// this should be specialized for 1.0 / 0.5 / 0.75 light levels
|
|
||||||
for (x=x1 ; x < x2 ; x++)
|
|
||||||
{
|
|
||||||
if (r_zbuffer[ofs] <= zfrac)
|
|
||||||
{
|
|
||||||
r_zbuffer[ofs] = zfrac;
|
|
||||||
out = (pixel32_t *)&r_picbuffer[ofs];
|
|
||||||
*out = r_flatcolor.p;
|
|
||||||
}
|
|
||||||
zfrac += zstep;
|
|
||||||
ofs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
REN_RasterizeFace
|
|
||||||
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void REN_RasterizeFace (winding_t *w)
|
|
||||||
{
|
|
||||||
int y;
|
|
||||||
int i;
|
|
||||||
int top, bot;
|
|
||||||
int leftv, rightv;
|
|
||||||
int count;
|
|
||||||
int numvertex;
|
|
||||||
|
|
||||||
//
|
|
||||||
// find top vertex
|
|
||||||
//
|
|
||||||
numvertex = w->numpoints;
|
|
||||||
top = 0x7fffffff;
|
|
||||||
bot = 0x80000000;
|
|
||||||
leftv = 0;
|
|
||||||
|
|
||||||
for (i=0 ; i<numvertex ; i++)
|
|
||||||
{
|
|
||||||
w->points[i][3] *= w->points[i][2];
|
|
||||||
w->points[i][4] *= w->points[i][2];
|
|
||||||
|
|
||||||
sy[i] = (int)w->points[i][1];
|
|
||||||
|
|
||||||
if (sy[i] < top)
|
|
||||||
{
|
|
||||||
top = sy[i];
|
|
||||||
leftv = i;
|
|
||||||
}
|
|
||||||
if (sy[i] > bot)
|
|
||||||
bot = sy[i];
|
|
||||||
}
|
|
||||||
rightv = leftv;
|
|
||||||
|
|
||||||
if (top < 0 || bot > r_height || top > bot)
|
|
||||||
return; // shouldn't have to have this...
|
|
||||||
|
|
||||||
//
|
|
||||||
// render a trapezoid
|
|
||||||
//
|
|
||||||
y = top;
|
|
||||||
|
|
||||||
while (y < bot)
|
|
||||||
{
|
|
||||||
if (y >= sy[leftv])
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
for (i=0 ; i<5 ; i++)
|
|
||||||
leftside[i] = w->points[leftv][i];
|
|
||||||
leftv--;
|
|
||||||
if (leftv == -1)
|
|
||||||
leftv = numvertex-1;
|
|
||||||
} while (sy[leftv] <= y);
|
|
||||||
count = sy[leftv]-y;
|
|
||||||
for (i=0 ; i<5 ; i++)
|
|
||||||
leftstep[i] = (w->points[leftv][i] - leftside[i])/count;
|
|
||||||
}
|
|
||||||
if (y >= sy[rightv])
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
for (i=0 ; i<5 ; i++)
|
|
||||||
rightside[i] = w->points[rightv][i];
|
|
||||||
rightv++;
|
|
||||||
if (rightv == numvertex)
|
|
||||||
rightv = 0;
|
|
||||||
} while (sy[rightv] <= y);
|
|
||||||
count = sy[rightv]-y;
|
|
||||||
for (i=0 ; i<5 ; i++)
|
|
||||||
rightstep[i] = (w->points[rightv][i] - rightside[i])/count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r_drawflat)
|
|
||||||
REN_DrawFlatSpan (y);
|
|
||||||
else
|
|
||||||
REN_DrawSpan (y);
|
|
||||||
|
|
||||||
for (i=0 ; i<5 ; i++)
|
|
||||||
{
|
|
||||||
leftside[i] += leftstep[i];
|
|
||||||
rightside[i] += rightstep[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
REN_DrawSpanLinear
|
|
||||||
==================
|
|
||||||
*/
|
|
||||||
void REN_DrawSpanLinear (int y)
|
|
||||||
{
|
|
||||||
int x, count;
|
|
||||||
int ofs;
|
|
||||||
int tx, ty;
|
|
||||||
int x1, x2;
|
|
||||||
float ufrac, vfrac, zfrac, ustep, vstep, zstep;
|
|
||||||
pixel32_t *in, *out;
|
|
||||||
float scale;
|
|
||||||
|
|
||||||
if (y<0 || y >= r_height)
|
|
||||||
return;
|
|
||||||
|
|
||||||
x1 = (leftside[0]);
|
|
||||||
x2 = (rightside[0]);
|
|
||||||
|
|
||||||
count = x2 - x1;
|
|
||||||
if (count < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
zfrac = leftside[2];
|
|
||||||
ufrac = leftside[3];
|
|
||||||
vfrac = leftside[4];
|
|
||||||
|
|
||||||
if (!count)
|
|
||||||
scale = 1;
|
|
||||||
else
|
|
||||||
scale = 1.0/count;
|
|
||||||
|
|
||||||
zstep = (rightside[2] - zfrac)*scale;
|
|
||||||
ustep = (rightside[3] - ufrac)*scale;
|
|
||||||
vstep = (rightside[4] - vfrac)*scale;
|
|
||||||
|
|
||||||
|
|
||||||
if (x1 < 0)
|
|
||||||
{
|
|
||||||
ufrac -= x1*ustep;
|
|
||||||
vfrac -= x1*vstep;
|
|
||||||
zfrac -= x1*zstep;
|
|
||||||
x1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x2 > r_width)
|
|
||||||
x2 = r_width;
|
|
||||||
|
|
||||||
ofs = y*r_width+x1;
|
|
||||||
|
|
||||||
for (x=x1 ; x < x2 ; x++)
|
|
||||||
{
|
|
||||||
if (r_zbuffer[ofs] <= zfrac)
|
|
||||||
{
|
|
||||||
r_zbuffer[ofs] = zfrac;
|
|
||||||
|
|
||||||
if (t_widthshift)
|
|
||||||
{
|
|
||||||
tx = (int)ufrac & t_widthmask;
|
|
||||||
ty = (int)vfrac & t_heightmask;
|
|
||||||
in = (pixel32_t *)&t_data [(ty<<t_widthshift)+tx];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tx = (int)(ufrac+t_widthadd) % t_width;
|
|
||||||
ty = (int)(vfrac+t_heightadd) % t_height;
|
|
||||||
in = (pixel32_t *)&t_data [ty*t_width+tx];
|
|
||||||
}
|
|
||||||
|
|
||||||
out = (pixel32_t *)&r_picbuffer[ofs];
|
|
||||||
*out = *in;
|
|
||||||
}
|
|
||||||
ufrac += ustep;
|
|
||||||
vfrac += vstep;
|
|
||||||
zfrac += zstep;
|
|
||||||
ofs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
REN_RasterizeFaceLinear
|
|
||||||
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void REN_RasterizeFaceLinear (winding_t *w)
|
|
||||||
{
|
|
||||||
int y;
|
|
||||||
int i;
|
|
||||||
int top, bot;
|
|
||||||
int leftv, rightv;
|
|
||||||
int count;
|
|
||||||
int numvertex;
|
|
||||||
|
|
||||||
//
|
|
||||||
// find top vertex
|
|
||||||
//
|
|
||||||
numvertex = w->numpoints;
|
|
||||||
top = 0x7fffffff;
|
|
||||||
bot = 0x80000000;
|
|
||||||
|
|
||||||
leftv = 0;
|
|
||||||
for (i=0 ; i<numvertex ; i++)
|
|
||||||
{
|
|
||||||
sy[i] = (int)w->points[i][1];
|
|
||||||
|
|
||||||
if (sy[i] < top)
|
|
||||||
{
|
|
||||||
top = sy[i];
|
|
||||||
leftv = i;
|
|
||||||
}
|
|
||||||
if (sy[i] > bot)
|
|
||||||
bot = sy[i];
|
|
||||||
}
|
|
||||||
rightv = leftv;
|
|
||||||
|
|
||||||
if (top < 0 || bot > r_height || top > bot)
|
|
||||||
return; // shouldn't have to have this...
|
|
||||||
|
|
||||||
//
|
|
||||||
// render a trapezoid
|
|
||||||
//
|
|
||||||
y = top;
|
|
||||||
|
|
||||||
while (y < bot)
|
|
||||||
{
|
|
||||||
if (y >= sy[leftv])
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
for (i=0 ; i<5 ; i++)
|
|
||||||
leftside[i] = w->points[leftv][i];
|
|
||||||
leftv--;
|
|
||||||
if (leftv == -1)
|
|
||||||
leftv = numvertex-1;
|
|
||||||
} while (sy[leftv] <= y);
|
|
||||||
count = sy[leftv]-y;
|
|
||||||
for (i=0 ; i<5 ; i++)
|
|
||||||
leftstep[i] = (w->points[leftv][i] - leftside[i])/count;
|
|
||||||
}
|
|
||||||
if (y >= sy[rightv])
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
for (i=0 ; i<5 ; i++)
|
|
||||||
rightside[i] = w->points[rightv][i];
|
|
||||||
rightv++;
|
|
||||||
if (rightv == numvertex)
|
|
||||||
rightv = 0;
|
|
||||||
} while (sy[rightv] <= y);
|
|
||||||
count = sy[rightv]-y;
|
|
||||||
for (i=0 ; i<5 ; i++)
|
|
||||||
rightstep[i] = (w->points[rightv][i] - rightside[i])/count;
|
|
||||||
}
|
|
||||||
|
|
||||||
REN_DrawSpanLinear (y);
|
|
||||||
|
|
||||||
for (i=0 ; i<5 ; i++)
|
|
||||||
{
|
|
||||||
leftside[i] += leftstep[i];
|
|
||||||
rightside[i] += rightstep[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
REN_BeginCamera
|
|
||||||
===================
|
|
||||||
*/
|
|
||||||
float r_width_2, r_height_3;
|
|
||||||
plane_t frustum[5];
|
|
||||||
|
|
||||||
void REN_BeginCamera (void)
|
|
||||||
{
|
|
||||||
r_width_2 = (float)r_width / 2;
|
|
||||||
r_height_3 = (float)r_height / 3;
|
|
||||||
|
|
||||||
|
|
||||||
// clip to right side
|
|
||||||
frustum[0].normal[0] = -1;
|
|
||||||
frustum[0].normal[1] = 0;
|
|
||||||
frustum[0].normal[2] = 1;
|
|
||||||
frustum[0].dist = 0;
|
|
||||||
|
|
||||||
// clip to left side
|
|
||||||
frustum[1].normal[0] = 1;
|
|
||||||
frustum[1].normal[1] = 0;
|
|
||||||
frustum[1].normal[2] = 1;
|
|
||||||
frustum[1].dist = 0;
|
|
||||||
|
|
||||||
// clip to top side
|
|
||||||
frustum[2].normal[0] = 0;
|
|
||||||
frustum[2].normal[1] = -1;
|
|
||||||
frustum[2].normal[2] = r_height_3 / r_width_2;
|
|
||||||
frustum[2].dist = 0;
|
|
||||||
|
|
||||||
// clip to bottom side
|
|
||||||
frustum[3].normal[0] = 0;
|
|
||||||
frustum[3].normal[1] = 1;
|
|
||||||
frustum[3].normal[2] = 2*r_height_3 / r_width_2;
|
|
||||||
frustum[3].dist = 0;
|
|
||||||
|
|
||||||
// near Z
|
|
||||||
frustum[4].normal[0] = 0;
|
|
||||||
frustum[4].normal[1] = 0;
|
|
||||||
frustum[4].normal[2] = 1;
|
|
||||||
frustum[4].dist = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void REN_BeginXY (void)
|
|
||||||
{
|
|
||||||
frustum[0].normal[0] = 1;
|
|
||||||
frustum[0].normal[1] = 0;
|
|
||||||
frustum[0].normal[2] = 0;
|
|
||||||
frustum[0].dist = 0;
|
|
||||||
|
|
||||||
frustum[1].normal[0] = -1;
|
|
||||||
frustum[1].normal[1] = 0;
|
|
||||||
frustum[1].normal[2] = 0;
|
|
||||||
frustum[1].dist = -r_width;
|
|
||||||
|
|
||||||
frustum[2].normal[0] = 0;
|
|
||||||
frustum[2].normal[1] = 1;
|
|
||||||
frustum[2].normal[2] = 0;
|
|
||||||
frustum[2].dist = 0;
|
|
||||||
|
|
||||||
frustum[3].normal[0] = 0;
|
|
||||||
frustum[3].normal[1] = -1;
|
|
||||||
frustum[3].normal[2] = 0;
|
|
||||||
frustum[3].dist = -r_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
REN_DrawCameraFace
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void REN_DrawCameraFace (face_t *idpol)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
float scale;
|
|
||||||
int numvertex;
|
|
||||||
winding_t *w, *in;
|
|
||||||
vec3_t temp;
|
|
||||||
|
|
||||||
if (!idpol->w)
|
|
||||||
return; // overconstrained plane
|
|
||||||
|
|
||||||
r_face = idpol;
|
|
||||||
|
|
||||||
//
|
|
||||||
// back face cull
|
|
||||||
//
|
|
||||||
if (DotProduct (r_origin, idpol->plane.normal) <= idpol->plane.dist)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//
|
|
||||||
// transform in 3D (FIXME: clip first, then transform)
|
|
||||||
//
|
|
||||||
in = idpol->w;
|
|
||||||
numvertex = in->numpoints;
|
|
||||||
|
|
||||||
w = NewWinding (numvertex);
|
|
||||||
w->numpoints = numvertex;
|
|
||||||
for (i=0 ; i<numvertex ; i++)
|
|
||||||
{
|
|
||||||
VectorSubtract (in->points[i], r_origin, temp);
|
|
||||||
|
|
||||||
w->points[i][0] = DotProduct(temp,r_matrix[0]);
|
|
||||||
w->points[i][1] = DotProduct(temp,r_matrix[1]);
|
|
||||||
w->points[i][2] = DotProduct(temp,r_matrix[2]);
|
|
||||||
|
|
||||||
w->points[i][3] = in->points[i][3];
|
|
||||||
w->points[i][4] = in->points[i][4];
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// 3D clip
|
|
||||||
//
|
|
||||||
for (i=0 ; i<4 ; i++)
|
|
||||||
{
|
|
||||||
w = ClipWinding (w, &frustum[i]);
|
|
||||||
if (!w)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// project to 2D
|
|
||||||
//
|
|
||||||
for (i=0 ; i<w->numpoints ; i++)
|
|
||||||
{
|
|
||||||
scale = r_width_2 / w->points[i][2];
|
|
||||||
w->points[i][0] = r_width_2 + scale*w->points[i][0];
|
|
||||||
w->points[i][1] = r_height_3 - scale*w->points[i][1];
|
|
||||||
w->points[i][2] = scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// draw it
|
|
||||||
//
|
|
||||||
REN_SetTexture (idpol);
|
|
||||||
|
|
||||||
REN_RasterizeFace (w);
|
|
||||||
free (w);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
REN_DrawXYFace
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void REN_DrawXYFace (face_t *idpol)
|
|
||||||
{
|
|
||||||
int i, j, numvertex;
|
|
||||||
winding_t *w, *in;
|
|
||||||
float *dest, *source;
|
|
||||||
float temp;
|
|
||||||
|
|
||||||
if (!idpol->w)
|
|
||||||
return; // overconstrained plane
|
|
||||||
w = idpol->w;
|
|
||||||
|
|
||||||
r_face = idpol;
|
|
||||||
|
|
||||||
//
|
|
||||||
// back (and side) face cull
|
|
||||||
//
|
|
||||||
if (DotProduct (idpol->plane.normal, xy_viewnormal) > -VECTOR_EPSILON)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//
|
|
||||||
// transform
|
|
||||||
//
|
|
||||||
in = idpol->w;
|
|
||||||
numvertex = in->numpoints;
|
|
||||||
|
|
||||||
w = NewWinding (numvertex);
|
|
||||||
w->numpoints = numvertex;
|
|
||||||
|
|
||||||
for (i=0 ; i<numvertex ; i++)
|
|
||||||
{
|
|
||||||
// using Z as a scale for the 2D projection
|
|
||||||
w->points[i][0] = (in->points[i][0] - r_origin[0])*r_origin[2];
|
|
||||||
w->points[i][1] = r_height - (in->points[i][1] - r_origin[1])*r_origin[2];
|
|
||||||
w->points[i][2] = in->points[i][2] + 3000;
|
|
||||||
w->points[i][3] = in->points[i][3];
|
|
||||||
w->points[i][4] = in->points[i][4];
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// clip
|
|
||||||
//
|
|
||||||
for (i=0 ; i<4 ; i++)
|
|
||||||
{
|
|
||||||
w = ClipWinding (w, &frustum[i]);
|
|
||||||
if (!w)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// project to 2D
|
|
||||||
//
|
|
||||||
for (i=0 ; i<w->numpoints ; i++)
|
|
||||||
{
|
|
||||||
dest = w->points[i];
|
|
||||||
if (dest[0] < 0)
|
|
||||||
dest[0] = 0;
|
|
||||||
if (dest[0] > r_width)
|
|
||||||
dest[0] = r_width;
|
|
||||||
if (dest[1] < 0)
|
|
||||||
dest[1] = 0;
|
|
||||||
if (dest[1] > r_height)
|
|
||||||
dest[1] = r_height;
|
|
||||||
if (xy_viewnormal[2] > 0)
|
|
||||||
dest[2] = 4096-dest[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xy_viewnormal[2] > 0)
|
|
||||||
{ // flip order when upside down
|
|
||||||
for (i=0 ; i<w->numpoints/2 ; i++)
|
|
||||||
{
|
|
||||||
dest = w->points[i];
|
|
||||||
source = w->points[w->numpoints-1-i];
|
|
||||||
for (j=0 ; j<5 ; j++)
|
|
||||||
{
|
|
||||||
temp = dest[j];
|
|
||||||
dest[j] = source[j];
|
|
||||||
source[j] = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
REN_SetTexture (idpol);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// draw it
|
|
||||||
//
|
|
||||||
REN_RasterizeFaceLinear (w);
|
|
||||||
free (w);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue