This is NeXTView.m in view mode; [Download] [Up]
#import "NeXTView.h" #import <math.h> #import "WireFrame.h" #import <sys/dir.h> #import <sys/types.h> #import <objc/NXBundle.h> // this code is copyright Darcy Brockbank, 1993 // // You may freely reuse and distribute this code in any way shape or // form, provided that this notice stays intact. // // darcy@hasc.ca, samurai@cs.mcgill.ca // // StefView was implemented out of WorldSpaceView and retains some of the // movement properties... // // The code for WorldSpaceView was written by Sam Streeper at NeXT, I think, // and there were two other contributors, but I can't find their names in the // source for it. // // NeXTView shows a simple (ha!) spinning NeXTcube logo, in full 3D. The 3D code // came from an app I wrote a long time ago called "WireFrame", and so the code // is pretty scary. As well, this thing is only a quick hack, though a nice one. // // This thing has room for improvement, and if you do so, send me a copy! // // - darcy @implementation NeXTView #define X_PERIOD 15000.0 #define Y_PERIOD 12000.0 #define DEFAULT_FPS 10 #define PI 3.1415926535 #define MAX_IMAGE_WIDTH 256 #define MAX_IMAGE_HEIGHT 256 #define MAX_X_SPEED (26) #define MAX_Y_SPEED (26) #define BUFFER_WIDTH (MAX_IMAGE_WIDTH + MAX_X_SPEED + 1) #define BUFFER_HEIGHT (MAX_IMAGE_HEIGHT + MAX_Y_SPEED + 1) #define PRINT(a) printf(a) #define MINX 0.0 #define MINY 0.0 #define ZOOM 680.0 - takeSpot:(float)x:(float)y; { [self draw]; return self; } - takeSnapshot; { return self; } - oneStep { NXRect black = {0,0,0,0}; NXRect ballRect; BRECT new; static float xdelta = 2.0; static float ydelta = 2.0; int changed = 0; then = now; now = currentTimeInMs(); xpos += xdelta; if (xpos<MINX) { xpos = MINX; xdelta*=-1.0; changed=1; } else if (xpos>maxCoord.x){ xpos = maxCoord.x; xdelta*=-1.0; changed=1; } ypos += ydelta; if (ypos<MINY) { ypos = MINY; ydelta*=-1.0; changed=1; } else if (ypos>maxCoord.y){ ypos = maxCoord.y; ydelta*=-1.0; changed=1; } if (changed){ #if 0 Axis flip[3]={y,y,y}; Direction dir[2]={positive,positive}; #else Axis flip[3]={y,z,x}; Direction dir[2]={positive,negative}; #endif axis = flip[axis]; spin = dir[spin]; } new.l = floor(xpos); new.b = floor(ypos); new.r = new.l + imageSize.width; new.t = new.b + imageSize.height; ballRect.origin.x = 0; ballRect.origin.y = 0; ballRect.size.width = imageSize.width; ballRect.size.height = imageSize.height; redrawTo.x = MIN(new.l, old.l); redrawTo.y = MIN(new.b, old.b); redraw.origin.x = 0; redraw.origin.y = 0; redraw.size.width = (MAX(new.r, old.r)) - redrawTo.x + 1; redraw.size.height = (MAX(new.t, old.t)) - redrawTo.y + 1; black.size= redraw.size; [buffer lockFocus]; PSsetgray(0); NXRectFill(&black); [self draw]; ballTo.x = new.l - redrawTo.x; ballTo.y = new.b - redrawTo.y; [buffer unlockFocus]; [buffer composite:NX_COPY toPoint:&redrawTo]; old = new; return self; } #define SIZE 200.0 - initFrame:(const NXRect *)frameRect { const char *animSpeed; NXRect black = {0, 0, SIZE, SIZE }; imageSize = black.size; [super initFrame:frameRect]; [self allocateGState]; // For faster lock/unlockFocus [self setClipping:NO]; // even faster... PSsetlinewidth(0.15); backgroundColour=NX_COLORBLACK; worldOrigin.x=0.0; worldOrigin.y=0.0; worldOrigin.z=0.0; translationRate = 3.0; currentZoom=ZOOM; list = [[List alloc] init]; axis = y; spin = positive; buffer = [[NXImage alloc] initSize:&black.size]; if ([buffer lockFocus]) { PSsetgray(0); NXRectFill(&black); [buffer unlockFocus]; } animSpeed = NXGetDefaultValue([NXApp appName], "animSpeed"); if (animSpeed == NULL) framesPerSecond = DEFAULT_FPS; else framesPerSecond = atoi(animSpeed); nextRotationTime = 0; [self newViewSize]; return self; } - sizeTo:(NXCoord)width :(NXCoord)height { [super sizeTo:width :height]; [self newViewSize]; return self; } - newViewSize { //this is called every time View size changes NXRect black = {0, 0, BUFFER_WIDTH, BUFFER_HEIGHT }; then = now = currentTimeInMs(); if (oldSize.width == bounds.size.width && oldSize.height == bounds.size.height) return self; else { oldSize.width = bounds.size.width; oldSize.height = bounds.size.height; } maxCoord.x = bounds.size.width - imageSize.width - MINX; maxCoord.y = bounds.size.height - imageSize.height - MINY; if (maxCoord.x < 0) maxCoord.x = 0; if (maxCoord.y < 0) maxCoord.y = 0; old.l = old.r = maxCoord.x/2 + MINX; old.b = old.t = maxCoord.y/2 + MINY; ballTo.x = ballTo.y = 0; if ([buffer lockFocus]) { PSsetgray(0); NXRectFill(&black); [buffer unlockFocus]; } return self; } - (const char *)windowTitle { return "NeXTView"; } - inspector:sender { char buf[MAXPATHLEN]; if (!sharedInspectorPanel){ sprintf(buf,"%s/NeXTView.nib",[sender moduleDirectory:"NeXT"]); [NXApp loadNibFile:buf owner:self withNames:NO]; [self loadDir:[sender moduleDirectory:"NeXT"]]; } return sharedInspectorPanel; } - tryToChangeCentre { id object=[self firstObject]; if (object) { [object getCentre:&curOrigin.x:&curOrigin.y:&curOrigin.z]; } else { curOrigin.x = curOrigin.y = curOrigin.z = 0.0; } return self; } - firstObject { return [list objectAt:0]; } - free { [list free]; return [super free]; } - (const char *)world; { return "NeXTcube.world"; } - loadDir:(const char *)dir { char world[MAXPATHLEN+1]; sprintf(world,"%s/%s",dir,[self world]); [self loadWorld:world]; [self tryToChangeCentre]; [self display]; return self; } - loadWorld:(const char *)world { DIR *dirp; id newFrame; struct direct *dp; char *tail; char temp[1024]; dirp=opendir(world); if (!dirp) { NXRunAlertPanel("Directory Error", "Can't read directory: %s","OK",0,0,world); } else { for(dp=readdir(dirp);dp!=NULL;dp=readdir(dirp)){ if ((tail=(rindex(dp->d_name,'.')))!=NULL){ if (strcmp((tail+1),"wireframe")==0){ sprintf(temp,"%s/%s",world,dp->d_name); newFrame = [[WireFrame alloc] init]; [newFrame makeWireFrame:temp]; [self addThisObject:newFrame]; } if (strcmp((tail+1),"wireframeb")==0){ sprintf(temp,"%s/%s",world,dp->d_name); newFrame = [[WireFrame alloc] init]; [newFrame readBinaryCodeFrom:temp]; [self addThisObject:newFrame]; } } } } return self; } - setTranslationRate:sender; { translationRate=[sender floatValue]; return self; } - (int)numberOfObjects { return [list count]; } - addThisObject:anObject { [list addObject:anObject]; return self; } - setZoom: sender { currentZoom=[sender floatValue]; [self display]; return self; } - draw; { int i,count = [list count] ; NXPoint zero = {0.0,0.0}; for (i=0;i<count;i++){ id wireFrame = [list objectAt:i]; [wireFrame rotate:spin aroundAxis:axis atOrigin:curOrigin]; [wireFrame drawYourself:currentZoom centeredOn:imageSize.width/2.0 :imageSize.height/2.0]; } return self; } - translate:(Direction)dir alongAxis:(Axis)a atRate:(float)rate { int i,count = [list count]; for (i=0;i<count;i++){ [[list objectAt:i] translate:dir alongAxis:a atRate:rate]; } [self tryToChangeCentre]; return self; } - rotate:(Direction)dir aroundAxis:(Axis)a atOrigin:(Origin)orig { int i,count = [list count]; for (i=0;i<count;i++){ [[list objectAt:i] rotate:dir aroundAxis:a atOrigin:orig]; } return self; } - rotatey:sender; { [self rotate:negative aroundAxis:y atOrigin:curOrigin]; return self; } - rotateY:sender; { [self rotate:positive aroundAxis:y atOrigin:curOrigin]; return self; } - rotatez:sender; { [self rotate:negative aroundAxis:z atOrigin:curOrigin]; return self; } - rotateZ:sender; { [self rotate:positive aroundAxis:z atOrigin:curOrigin]; return self; } - rotatex:sender; { [self rotate:negative aroundAxis:x atOrigin:curOrigin]; return self; } - rotateX:sender; { [self rotate:positive aroundAxis:x atOrigin:curOrigin]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.