This is Think2.m in view mode; [Download] [Up]
#import <appkit/appkit.h> #import "Thinker.h" #import "xoxDefs.h" #import "BackView.h" #import "Scenario.h" #import "ActorMgr.h" #import "GameInfo.h" #import "BackWindow.h" #import "CacheManager.h" #import "EKProgressView.h" #import "SoundMgr.h" #include <sys/types.h> #include <sys/dir.h> extern id sceneOneStepper; extern BOOL pauseState; extern BOOL obscureMouse; @implementation Thinker(thinker2) - setupGameBrowser { id theMatrix; char buf[MAXPATHLEN]; const char *ptr; strcpy( buf, NXHomeDirectory()); strcat( buf, "/Library/XoxGames"); gameList = [[GameList alloc] init]; [self loadGamesFrom:buf]; ptr = NXGetDefaultValue([NXApp appName], "altGamePath"); if (ptr) [self loadGamesFrom:ptr]; [self loadGamesFrom: [[NXBundle mainBundle] directory]]; [self loadGamesFrom: "/LocalLibrary/XoxGames"]; [gameList sort]; [scenarioBrowser loadColumnZero]; theMatrix = [scenarioBrowser matrixInColumn:0]; [theMatrix selectCellAt:gameIndex :0]; [theMatrix scrollCellToVisible:gameIndex :0]; return self; } - getSoundSetting { NXZone *soundZone; const char *ptr; soundZone = NXCreateZone(vm_page_size, vm_page_size, YES); soundMgr = [[SoundMgr allocFromZone:soundZone] init]; ptr = NXGetDefaultValue([NXApp appName], "Sound"); if (!ptr || !strcmp(ptr,"On")) { [soundMgr turnSoundOn:nil]; } [soundButton setState:[soundMgr isSoundEnabled]]; return self; } - setSound:sender { if ([soundButton state]) { if (![soundMgr turnSoundOn:sender]) [soundButton setState:0]; } else { [soundMgr turnSoundOff]; } if ([soundMgr isSoundEnabled]) NXRemoveDefault([NXApp appName], "Sound"); else NXWriteDefault([NXApp appName], "Sound", "Off"); return self; } - selectGame:sender { // sender is the game browser, or nil if sent from within the app int i; int index = [[scenarioBrowser matrixInColumn:0] selectedRow]; NXRect f1; id inspector; GAME_STATUS gs; if (sender && (index == gameIndex)) return self; [scenario scenarioDeselected]; [cacheMgr setBackground:NO]; gameIndex = index; scenario = [self getScenario]; if (sender) NXWriteDefault([NXApp appName], "whichGame", [gameList nameAt: index]); gx = gy = 0; maxTimeScale = 1.5; collisionDistance = 1.25; if ([scenario respondsTo:@selector(oneStep)]) sceneOneStepper = scenario; else sceneOneStepper = nil; if ([scenario respondsTo:@selector(shouldObscureCursor)] && ![scenario shouldObscureCursor]) obscureMouse = NO; else obscureMouse = YES; [keyTimerList empty]; inspector = [scenario infoView]; [inspector getFrame:&f1]; [invisibleInfoBox setContentView: nullInfoBox]; [nullInfoBox sizeTo:f1.size.width :f1.size.height byWindowCorner:3]; [inspector setFrame:&f1]; [invisibleInfoBox setContentView: inspector]; [[invisibleInfoBox window] display]; [self installGameViewsIntoWindow:littleWindow]; if (i = [[gameList objectAt: gameIndex] level]) [actorMgr requestLevel:i]; else [actorMgr requestLevel:0]; [self adjustLittleWindowSize]; [scenario scenarioSelected]; [self setPauseState: (pauseState & ~1)]; gs = [(GameInfo *)[gameList objectAt: gameIndex] status]; if (gs == GAME_DYING || gs == GAME_DEAD) [self newGame:self]; else [actorMgr setGameStatus:gs]; [littleWindow display]; [littleWindow makeKeyAndOrderFront:self]; if (sender) [self justOneStep]; // yech! I should have a better way to get // everything set up... return self; } - installGameViewsIntoWindow:w { int i; for (i=([[gcontentView subviews] count]-1); i>=0; i--) { [[[gcontentView subviews] objectAt:i] removeFromSuperview]; } gameWindow = w; gcontentView = [w contentView]; if ([scenario respondsTo:@selector(tile)]) mainView = [scenario tile]; else { NXRect r; [gcontentView getBounds:&r]; [abackView setFrame:&r]; [gcontentView addSubview:abackView]; mainView = abackView; } [gameWindow makeFirstResponder:mainView]; return self; } - (BOOL)browser:sender columnIsValid:(int)column { return browserValid; } - addCellWithString:(const char *)str at:(int)row toMatrix:matrix { id theCell; [matrix insertRowAt:row]; theCell = [matrix cellAt:row :0]; [theCell setStringValue:str]; [theCell setLoaded:YES]; [theCell setLeaf:YES]; return self; } - (int)browser:sender fillMatrix:matrix inColumn:(int)column { const char *ptr; int i; // this shouldn't happen... if (browserValid) return [matrix cellCount]; for (i = 0; i < [gameList count]; i++) [self addCellWithString:NXLocalString([gameList nameAt: i], 0, 0) at:(i) toMatrix:matrix]; ptr = NXGetDefaultValue([NXApp appName], "whichGame"); if (ptr) { for (i = 0; i < [gameList count]; i++) if (strcmp(ptr, [gameList nameAt: i]) == 0) { gameIndex = i; break; } } browserValid = YES; return [matrix cellCount]; } // Dynamically load all object files found in the specified directory // if we find a module in several places, we save the additional paths // in case they point to modules for different architectures - loadGamesFrom: (const char *) dirname { DIR *dir; struct direct *de; char path[MAXPATHLEN]; char name[60]; char *iptr; GameInfo *m; BOOL validName; dir = opendir(dirname); if (dir == NULL) { return self; } while ((de = readdir(dir)) != NULL) { int i, numstrings; // Ignore '.'-files (not really necessary, I guess) if (de->d_name[0] == '.') continue; validName = NO; if (de->d_namlen > 4 && !strcmp(&de->d_name[de->d_namlen-4], ".XoX")) { validName = YES; } if (!validName) continue; // check if the name matches a module already loaded numstrings = [gameList count]; strcpy(name, de->d_name); // Smash out the '.' in "Foo.XoX" if (iptr = rindex(name, '.')) *iptr = '\0'; for (i=0; i< numstrings; i++) { if (!strcmp(name, [gameList nameAt:i])) { // we already have a module with this name, but will save the path anyway validName = NO; sprintf(path,"%s/%s.XoX",dirname,name); [[gameList objectAt:i] appendPath:path]; break; } } if (!validName) continue; sprintf(path,"%s/%s.XoX",dirname,name); m = [[GameInfo alloc] initWithScenario:NULL name:name path:path]; [gameList addObject: m]; } closedir(dir); return self; } extern NXZone *scenarioZone, *bundleZone; - getScenario { id progressWin = [progressView window]; if (![gameList scenarioAt:gameIndex]) { id theClass = nil; GameInfo *gi; id theScenario = nil; gi = [gameList objectAt: gameIndex]; if ([gi path]) // we have path but no instance, must load class { char str[80]; [progressView setProgress:0]; // fixme - these strings should be localizable... sprintf(str,"Loading %s",[gi scenarioName]); [[progressView window] setTitle:str]; [[statusText setStringValue:"loading code"] display]; [progressWin makeKeyAndOrderFront:self]; NXPing(); do { NXBundle *myBundle = [[NXBundle allocFromZone:bundleZone] initForDirectory:[gi path]]; theClass = [myBundle classNamed:[gi scenarioName]]; if (theClass) { theScenario = [[theClass allocFromZone:scenarioZone] init]; } else { [myBundle free]; } } while ((!theClass) && [gi useNextPath]); [gi discardAltPaths]; [[progressView setMin:0] setMax:[imageNames count] + [soundsToCache count]]; [progressView setProgress:0]; [self loadResources]; [progressWin close]; if (!theClass) { NXRunAlertPanel([NXApp appName], NXLocalString( "Could not load class: %s",0,0), NULL, NULL, NULL, [gi scenarioName]); } } [gi setScenario:theScenario]; } return [gameList scenarioAt:gameIndex]; } - createBigWindowIfNecessary { if (!bigWindow) { NXRect r={{0, 0}}; [NXApp getScreenSize:&(r.size)]; bigWindow = [[BackWindow allocFromZone:[self zone]] initContent:&r style:NX_PLAINSTYLE backing:NX_NONRETAINED buttonMask:0 defer:NO]; [bigWindow setBackgroundGray:NX_BLACK]; [bigWindow setDelegate:self]; } return self; } // delegate method invoked by window - windowWillResize:sender toSize:(NXSize *)frameSize { NXRect frm = {0,0,0,0}; NXRect cnt = {0,0,0,0}; if (![scenario respondsTo:@selector(newWindowContentSize:)]) return self; frm.size = *frameSize; [Window getContentRect:&cnt forFrameRect:&frm style:[sender style]]; if ([scenario newWindowContentSize:&(cnt.size)]) { [Window getFrameRect:&frm forContentRect:&cnt style:[sender style]]; *frameSize = frm.size; } return self; } - adjustLittleWindowSize { NXRect contRect; if (![scenario respondsTo:@selector(newWindowContentSize:)]) return self; [[littleWindow contentView] getBounds:&contRect]; if ([scenario newWindowContentSize:&contRect.size]) { [[littleWindow contentView] sizeTo:contRect.size.width :contRect.size.height byWindowCorner:3]; } return self; } - (BOOL)bigWindowOK { NXSize screenSize; if (![scenario respondsTo:@selector(newWindowContentSize:)]) return YES; [NXApp getScreenSize:&screenSize]; return (![scenario newWindowContentSize:&screenSize]); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.