Forge: More stuff gets the axe.

This commit is contained in:
Jeff Teunissen 2001-11-05 19:45:09 +00:00
parent 02dd74b2f7
commit 2ab7a09812
21 changed files with 0 additions and 12263 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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])];
}

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}