This is StarShipView.m in view mode; [Download] [Up]
#import "StarShipView.h"
#import "NewSpaceView.h"
#import "Thinker.h"
#import <stdio.h>
#import "StarShipProtocol.h"
#import <dpsclient/wraps.h>
#define sliderDelay 2000
@implementation StarShipView
static char **bundleFilenameList;
+ initialize
{
if ( self == [StarShipView class] )
{
static NXDefaultsVector starShipDefs = {
{"StarShipObjectSpeed", "180"},
{"StarShipIntervalTime", "5"},
{"StarShipAnimationSpeed", "500"},
{"StarShipCycleCount", "250"},
{"StarShipSound", "1"},
{"StarShipStarSpeed", "1"},
{NULL}
};
NXRegisterDefaults([NXApp appName], starShipDefs);
}
return self;
}
- oneStep
{
if (viewScreenResized){ //tell everybody about it
if(controllerTypeCount > 0){
[spaceTypeController setBoundsRect: &newViewScreenSize];
//set new clip area
NXSetRect(&clipRect,newViewScreenSize.origin.x,
newViewScreenSize.origin.y,newViewScreenSize.size.width,
newViewScreenSize.size.height);
// numbers have to do with size of the viewscreen border
clipRect.origin.x += 3.0;
clipRect.origin.y += 3.0;;
clipRect.size.width -= 6.0;
clipRect.size.height -= 6.0;
rectPtr = &clipRect;
}
viewScreenResized = NO;
}
if (controllerTypeCount > 0){ // they exist
NXRectClip(rectPtr); //clip to screen border
if ([spaceTypeController doUntilDone]){
[spaceTypeController freeResources];
controllerIndex++;
if (controllerIndex >= controllerTypeCount)
controllerIndex = 0;
spaceTypeController = [controllerList
objectAt:controllerIndex];
if(soundGood){
[spaceTypeController setPwrDownSnd:pwrDownSnd];
[spaceTypeController setPwrUpSnd:pwrUpSnd];
}
[self setModuleBox]; //update module info in inspector window
[viewScreen setBodyControllerOutlet:spaceTypeController];
[spaceTypeController setStarsOutlet:viewScreen];
//send module all slider values
firstTimeSound = 1; //don't want to play sound at startup
[self setSound:soundMatrix];
[self setStarSpeed:starSpeedSlider];
[self setAnimationSpeed:animationSlider];
[self setObjectInterval:objectIntervalSlider];
[self setObjectSpeed:objectSpeedSlider];
[self setCycleCount:cycleCountSlider];
[spaceTypeController setBoundsRect: &newViewScreenSize];
[spaceTypeController setFirstState];
}
PSinitclip(); //turn off clipping
}
[viewScreen oneStep];
if(frameRate > 1)
xmach_sleep(port, frameRate);
return self;
}
- (BOOL)makeSndObjects: (char *)directory
{
char buf[MAXPATHLEN + 1];
soundGood = YES;
sprintf(buf,"%s/pwrDown.snd",directory);
pwrDownSnd = [[Sound alloc] initFromSoundfile:buf];
if(pwrDownSnd == nil){
soundGood = NO;
printf("unable to create sound object %s\n",buf);
}
sprintf(buf,"%s/pwrUp.snd",directory);
pwrUpSnd = [[Sound alloc] initFromSoundfile:buf];
if(pwrUpSnd == nil){
soundGood = NO;
printf("unable to create sound object %s\n",buf);
}
sprintf(buf,"%s/sound.snd",directory);
sound = [[Sound alloc] initFromSoundfile:buf];
if(sound == nil){
soundGood = NO;
printf("unable to create sound object %s\n",buf);
}
return soundGood;
}
//*********************************
// this builds a list of bundles in the StarShipView.BackModule bundle
// and instantiates first bundle object
// there must be a class object that is same as bundle name
// The idea here is build a list of space object controllers
// like celestial body controllers, ship controllers, etc
- buildControllerList: (char *)directory
{
NXBundle * tmpBundle;
char buf[MAXPATHLEN + 1];
short ii,successCount;
controllerTypeCount = [self searchDirectory: directory];
controllerList = [[List alloc] initCount:controllerTypeCount];
successCount = 0;
if(controllerTypeCount > 0){//there are some
successCount = 0;
for(ii = 0; ii < controllerTypeCount; ii++){
sprintf(buf,"%s/%s.bundle",directory,bundleFilenameList[ii]);
if((tmpBundle = [[NXBundle alloc] initForDirectory:buf]) == nil)
printf("could not create bundle object for %s\n",buf);
else {
if((spaceTypeController = [[[tmpBundle
classNamed:bundleFilenameList[ii]]alloc]init])){
successCount++;
[controllerList addObject:spaceTypeController];
}
}
}
controllerTypeCount = successCount;
}
return self;
}
static BOOL isOk(const char *filename)
/* checks to make sure the filename is .bundle
*/
{
char *suffix;
suffix = rindex(filename,'.');
if (suffix == 0)
return NO;
else if(strlen(suffix) != 7)
return NO;
else
return(strncmp(suffix,".bundle",7)) ? NO : YES;
}
#define CHUNK 127
static char **addFile(const char *file, int length, char **list, int count)
/* Adds the specified filename to the list of filenames. It allocates
* more memory in chunks as needed.
*/
{
char *suffix;
if (!list) list = (char **)malloc(CHUNK*sizeof(char *));
if (suffix = rindex(file,'.'))
*suffix = '\0'; /* strip .bundle suffix */
list[count] = (char *)malloc((length+1)*sizeof(char));
strcpy(list[count], file);
count++;
if (!(count% CHUNK)) {
list = (char **)realloc(list,(((count/CHUNK)+1)*CHUNK)*sizeof(char *));
}
list[count] = NULL;
return list;
}
static void freeList(char **list)
/* Frees the array of filenames
*/
{
char **strings;
if (list) {
strings = list;
while (*strings) free(*strings++);
free(list);
}
}
// look in the right bundle directory for all the space object bundles
// create a list called bundleFilenameList
- (int)searchDirectory: (char *)directory
{
long basep;
char *buf;
struct direct *dp;
char **list = NULL;
int cc, fd, fileCount = 0;
char dirbuf[8192];
if ((fd = open(directory, O_RDONLY, 0644)) > 0) {
cc = getdirentries(fd, (buf = dirbuf), 8192, &basep);
while (cc) {
dp = (struct direct *)buf;
if (isOk(dp->d_name)) {
list = addFile(dp->d_name, dp->d_namlen, list, fileCount++);
}
buf += dp->d_reclen;
if (buf >= dirbuf + cc) {
cc = getdirentries(fd, (buf = dirbuf), 8192, &basep);
}
}
close(fd);
}
freeList(bundleFilenameList);
bundleFilenameList = list;
return fileCount;
}
- sizeTo:(NXCoord)width :(NXCoord)height
{
[super sizeTo:width :height];
[viewScreen sizeTo:width :height];//send original size to space
if(controllerTypeCount > 0){
[spaceTypeController setBoundsRect:&newViewScreenSize];
NXSetRect(&clipRect,newViewScreenSize.origin.x,
newViewScreenSize.origin.y,
newViewScreenSize.size.width,newViewScreenSize.size.height);
clipRect.origin.x += 3.0;
clipRect.origin.y += 3.0;;
clipRect.size.width -= 6.0;
clipRect.size.height -= 6.0;
rectPtr = &clipRect;
[spaceTypeController windowSizeChanged];
}
return self;
}
- initFrame:(const NXRect *)frameRect
{
char buf[MAXPATHLEN + 1];
[super initFrame:frameRect];
[self allocateGState]; // For faster lock/unlockFocus
[self inspector:self]; //this guarantees that sliders exist when I
//set them
moduleDir = [[NXApp delegate] moduleDirectory:"StarShip"];
strcpy(buf, moduleDir);
viewScreen = [[NewSpaceView alloc] initFrame:frameRect];
[viewScreen setStarShipOutlet:self];
NXSetRect(&clipRect,newViewScreenSize.origin.x,
newViewScreenSize.origin.y,
newViewScreenSize.size.width,newViewScreenSize.size.height);
clipRect.origin.x += 3.0;
clipRect.origin.y += 3.0;;
clipRect.size.width -= 6.0;
clipRect.size.height -= 6.0;
rectPtr = &clipRect;
// builds list of bundle objects
[self buildControllerList:buf];
controllerIndex = 0;
spaceTypeController = [controllerList objectAt:controllerIndex];
if([self makeSndObjects:buf]){
[spaceTypeController setPwrDownSnd:pwrDownSnd];
[spaceTypeController setPwrUpSnd:pwrUpSnd];
}
[self setModuleBox]; //update module info in inspector window
[spaceTypeController setBoundsRect: (NXRect *)frameRect];
[spaceTypeController setStarsOutlet:viewScreen];
[viewScreen setBodyControllerOutlet:spaceTypeController];
[self getDefaults:self];
firstTimeSound = 1; //don't want to play sound at startup
[self setSound:soundMatrix];
[self setStarSpeed:starSpeedSlider];
[self setAnimationSpeed:animationSlider];
[self setObjectInterval:objectIntervalSlider];
[self setObjectSpeed:objectSpeedSlider];
[self setCycleCount:cycleCountSlider];
[spaceTypeController setFirstState];
port = xmach_sleep_install();
viewScreenResized = NO;
return self;
}
- setCycleCount:(Slider *)sender
{
int multiplier,value;;
// real slider value min is 0
//I show a min of 1 cycle in the cycleCountBox
value = [sender intValue];
multiplier = (int)[spaceTypeController setCycleValue:value];
if (value == 0)
value = 1;
else
value *= multiplier;
[cycleCountBox setIntValue:value];
[self delayedDefaults:self];
return self;
}
- setStarSpeed:(Slider *)sender
{
[viewScreen setStarSpeed:sender];
[spaceTypeController setStarSpeed:sender];
[self delayedDefaults:self];
return self;
}
- setAnimationSpeed:(Slider *)sender
{
frameRate = ([sender maxValue] + [sender minValue]) - [sender intValue];
[self delayedDefaults:self];
return self;
}
- setObjectSpeed:(Slider *)sender
{
[spaceTypeController setObjectSpeed:sender];
[self delayedDefaults:self];
return self;
}
- setObjectInterval:(Slider *)sender
{
[spaceTypeController setStartInterval: sender];//send slider to current
[self delayedDefaults:self]; //space object
return self;
}
- setSound:sender
{
if(soundGood){ //there are valid sound files
if(!firstTimeSound)
[sound play];
firstTimeSound = 0;
soundEnabled = (BOOL)[[sender selectedCell] tag];
[spaceTypeController setSoundEnabled:soundEnabled];
}
else{ //set all sound off permanently
soundEnabled = NO;
[spaceTypeController setSoundEnabled:soundEnabled];
}
[self delayedDefaults:self];
return self;
}
- setModuleBox
{
[moduleBox setStringValue:bundleFilenameList[controllerIndex]];
return self;
}
- didLockFocus
{
[viewScreen didLockFocus];
return self;
}
- (const char *) windowTitle
{
return("StarShip!");
}
- inspector:sender
{
char buf[MAXPATHLEN];
if (!inspectorPanel)
{
sprintf(buf,"%s/English.lproj/StarShip.nib",[[NXApp delegate]
moduleDirectory:"StarShip"]);
if([NXApp loadNibFile:buf owner:self withNames:NO] == nil)
printf ("inspector not loaded %s\n",buf);
}
return inspectorPanel;
}
- inspectorWillBeRemoved
{
[[infoText window] orderOut:self];
return self;
}
// The module is never freed
// but it's here in case backSpace ever wants to ;-)
- free
{
//This is untested!!!!
[controllerList freeObjects];
[controllerList free];
[pwrDownSnd free];
[pwrUpSnd free];
[sound free];
freeList(bundleFilenameList);
xmach_sleep_remove(port);
return [super free];
}
// I left this in in case some of the modules wanted to do
//something cool with mouse
//down events - it is not functional right now
/*- mouseDown:(NXEvent *)theEvent;
{
NXRect r;
NXPoint p;
unsigned int i;
p = theEvent->location;
[self convertPoint:&p fromView:nil];
[self lockFocus];
[spaceTypeController doSomethingNow];
[self unlockFocus];
return self;
}*/
//needed for mouse down events
/*- newWindow
{
shipWindow = [self window];
[shipWindow addToEventMask:NX_LMOUSEDOWNMASK];
return self;
}*/
- delayedDefaults:sender
{
[self perform:@selector(writeDefaults:) with:self afterDelay:sliderDelay
cancelPrevious:YES];
return self;
}
- getDefaults:sender
{
int cell;
[animationSlider setIntValue:atoi(NXGetDefaultValue([NXApp appName],
"StarShipAnimationSpeed"))];
[objectSpeedSlider setIntValue:atoi(NXGetDefaultValue([NXApp appName],
"StarShipObjectSpeed"))];
[starSpeedSlider setFloatValue:atof(NXGetDefaultValue([NXApp appName],
"StarShipStarSpeed"))];
[objectIntervalSlider setIntValue:atoi(NXGetDefaultValue([NXApp appName],
"StarShipIntervalTime"))];
[cycleCountSlider setIntValue:atoi(NXGetDefaultValue([NXApp appName],
"StarShipCycleCount"))];
[cycleCountBox setIntValue:atoi(NXGetDefaultValue([NXApp appName],
"StarShipCycleCount"))];
cell = atoi(NXGetDefaultValue([NXApp appName], "StarShipSound"));
if(cell)
[soundMatrix selectCellAt:0:0];
else
[soundMatrix selectCellAt:1:0];
return self;
}
- writeDefaults:sender
{
int tag;
char ctag[2];
NXWriteDefault([NXApp appName], "StarShipAnimationSpeed",
[animationSlider stringValue]);
NXWriteDefault([NXApp appName], "StarShipObjectSpeed",
[objectSpeedSlider stringValue]);
NXWriteDefault([NXApp appName], "StarShipStarSpeed",
[starSpeedSlider stringValue]);
NXWriteDefault([NXApp appName], "StarShipIntervalTime",
[objectIntervalSlider stringValue]);
NXWriteDefault([NXApp appName], "StarShipCycleCount",
[cycleCountSlider stringValue]);
tag = [[soundMatrix selectedCell] tag];
sprintf(ctag,"%d",tag);
NXWriteDefault([NXApp appName], "StarShipSound",ctag);
return self;
}
port_t *xmach_sleep_install(void)
{
port_t *port;
NX_MALLOC(port, port_t, sizeof(port_t));
port_allocate(task_self(), port);
return(port);
}
void xmach_sleep_remove(port_t *port)
{
port_deallocate(task_self(), *port);
NX_FREE(port);
}
void xmach_sleep(port_t *port, msg_timeout_t msecs)
{
msg_header_t h;
h.msg_size = sizeof(h);
h.msg_local_port = *port;
msg_receive(&h, RCV_TIMEOUT, msecs);
}
- viewScreenResized:(NXRect *)screenRect
{
viewScreenResized = YES;
NXSetRect(&newViewScreenSize,screenRect->origin.x,
screenRect->origin.y,screenRect->size.width,
screenRect->size.height);
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.