This is PreferencesBrain.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import <daymisckit/daymisckit.h> #import <gamekit/gamekit.h> #import <stdio.h> #import <stdlib.h> /* malloc */ BOOL getBOOLPreference(const char *name, BOOL def) { const char *tmpstr = NXGetDefaultValue ([NXApp appName], name); int temp = def; if (tmpstr) sscanf(tmpstr, "%d", &temp); if (temp) return YES; return NO; } int getIntPreference(const char *name, int min, int max, int def) { int tempInt; const char *tmpstr = NXGetDefaultValue ([NXApp appName], name); if (!tmpstr) return def; else { sscanf(tmpstr, "%d", &tempInt); if (tempInt < min) return min; if (tempInt > max) return max; } return tempInt; } const char *getStringPreference(const char *name, const char *def) { const char *tmpstr = NXGetDefaultValue ([NXApp appName], name); if (tmpstr == NULL) return def; return tmpstr; } void putIntPreference(const char *name, int value) { char str[16]; sprintf(str, "%d", value); NXWriteDefault ([NXApp appName], name, str); } void putBOOLPreference(const char *name, BOOL value) { char str[16]; int tempInt = 0; if (value) tempInt = 1; sprintf(str, "%d", tempInt); NXWriteDefault ([NXApp appName], name, str); } void putStringPreference(const char *name, const char *value) { NXWriteDefault ([NXApp appName], name, value); } @implementation PreferencesBrain static char *defaultServer = "*"; // very slow -- subclass should override! - init // designated initializer sets up game variables { // to sensible values. int i; [super init]; for (i=0; i<MAXKEYS; i++) { // get space to store default keypresses in keys[i] = malloc(8); defkey[i] = malloc(8); } numKeys = 5; strcpy(defkey[0], "a"); strcpy(defkey[1], "z"); strcpy(defkey[2], "l"); strcpy(defkey[3], ";"); strcpy(defkey[4], " "); defaultPlayerName = [[DAYString alloc] init]; version = malloc(8); serverName = NXCopyStringBufferFromZone(defaultServer, [self zone]); firstLoad = YES; return self; } - appDidInit:sender // forwarded by GameBrain { // Do all our basic init here if (!gameBrain) gameBrain = [NXApp delegate]; if (!info) info = [gameBrain infoController]; if (!scorePlayer) scorePlayer = [gameBrain scorePlayer]; if (!soundPlayer) soundPlayer = [gameBrain soundPlayer]; if (!highScoreTable) highScoreTable = [gameBrain highScoreController]; if (!strings) strings = [gameBrain mainStrings]; if (!gameScreen) gameScreen = [gameBrain gameScreen]; [self readDefaults:self]; [gameScreen getPreferences]; return self; } // methods to get at instance variables - (int)startLevel { return level; } // returns starting level - (int)speed { return speed; } - (BOOL)border { return border; } // return YES if gray border is on - (BOOL)effects { return effects; } - (BOOL)music { return music; } - (BOOL)alert { return alert; } - (BOOL)autoUnPause { return autoUnPause; } - (BOOL)autoStart { return autoStart; } - (BOOL)demoSound { return demoSound; } - (BOOL)useServer { return useServer; } - setAlert:(BOOL)al { alert = al; return self; } - setAutoUnPause:(BOOL)al { autoUnPause = al; return self; } - setAutoStart:(BOOL)al { autoStart = al; return self; } - (const char *)serverName { return serverName; } - setNumKeys:(int)num { numKeys = num; return self; } - readDefaults:sender // get preferences from defaults database { char *tmpstr = malloc(16); int i; if (serverName) free(serverName); useServer = getBOOLPreference("UseServer", NO); effects = getBOOLPreference("SoundOn", YES); alert = getBOOLPreference("Alerts", YES); autoUnPause = getBOOLPreference("AutoUnPause", YES); autoStart = getBOOLPreference("AutoStart", YES); border = getBOOLPreference("Border", YES); demoSound = getBOOLPreference("DemoSound", YES); music = getBOOLPreference("MusicOn", YES); level = getIntPreference("StartLevel", 1, 20, 1); speed = getIntPreference("GameSpeed", 0, 2, 1); serverName = NXCopyStringBufferFromZone( getStringPreference("ServerName", defaultServer), [self zone]); strcpy(version, getStringPreference("Version", "0.0")); [self setDefaultPlayerName:getStringPreference( "PlayerName", [NXApp userRealName])]; for (i=0; i < numKeys; i++) { sprintf(tmpstr, "Key%d", i); strcpy(keys[i], getStringPreference(tmpstr, defkey[i])); [gameScreen setKey:i val:keys[i][0]]; } [gameScreen getPreferences]; [highScoreTable setServerHost:serverName]; if (useServer) [highScoreTable setLocalScores:NO]; else [highScoreTable setLocalScores:YES]; // if couldn't locate the server, go local. if (useServer && [highScoreTable localScores]) useServer = NO; free(tmpstr); [soundPlayer turnOn:effects]; return self; } - writeDefaults:sender // save preferences in defaults database { char str[32]; int i; putBOOLPreference ("Border", border); putBOOLPreference ("Alerts", alert); putBOOLPreference ("AutoStart", autoStart); putBOOLPreference ("AutoUnPause", autoUnPause); putBOOLPreference ("DemoSound", demoSound); putBOOLPreference ("MusicOn", music); putBOOLPreference ("SoundOn", effects); putBOOLPreference ("UseServer", useServer); putIntPreference ("GameSpeed", speed); putIntPreference ("StartLevel", level); putStringPreference ("Version", version); putStringPreference ("ServerName", serverName); putStringPreference ("PlayerName", [defaultPlayerName stringValue]); for (i=0; i<numKeys; i++) { // ***** it would be better to make a single // string for all the keys; in the future I might make this adjustment. // This method leaves quite a few defaults... sprintf(str, "Key%d", i); putStringPreference(str, keys[i]); } return self; } - (BOOL)firstTimeCheck // first time running this version? { if (!version || ![info versionString]) return NO; // if NULL, then this // mechanism is disabled, so it's NEVER the first time running... if (strcmp(version, [info versionString])) { // first time if != strcpy(version, [info versionString]); return YES; // when the Prefs are saved (exit, etc.) the version // # will be stored in defaults and then next time we'll return a NO } return NO; } - revert:sender // return to default values { int tempInt; speed = 1; effects = YES; alert = YES; autoUnPause = YES; autoStart = YES; border = YES; demoSound = YES; music = YES; useServer = NO; if (serverName) free(serverName); serverName = NXCopyStringBufferFromZone(defaultServer, [self zone]); if (![highScoreTable localScores]) [highScoreTable closeServers]; [highScoreTable setServerHost:serverName]; [gameScreen revertBackground:sender]; for (tempInt=0; tempInt<numKeys; tempInt++) { strcpy(keys[tempInt], defkey[tempInt]); } // I'm not reverting defaultPlayerName; doesn't seem necessary for (tempInt=0; tempInt<4; tempInt++) [gameScreen setKey:tempInt val:keys[tempInt][0]]; [gameScreen getPreferences]; // make sure that the gameScreen is aware return [self preferences:self]; // update the panel } - takeKey:sender // used by below (keyChange) to get new keys { // This is klunky; there's a better way to fill up the matrix; I'll // fix it eventually ***** (See how the GKHighScorePanel does it; it's // much cleaner than this.) strcpy(keys[[sender tag]],[sender stringValue]); // store internally [gameScreen setKey:[sender tag] val:keys[[sender tag]][0]]; // send to view return self; } - (char)keyVal:(int)keyIndex // returns default key for action (0-4) { return keys[keyIndex][0]; } - keyChange:sender // accept changes in keys { [keyMatrix sendAction:@selector(takeKey:) to:self forAllCells:YES]; // ***** I should check here to be sure that the new keys don't // conflict with each other or with the 'p' and 'n' keys... return self; } - changeLevel:sender { level = [sender intValue]; if (sender != levelSlider) [levelSlider setIntValue:level]; else [levelText setIntValue:level]; return self; } - speedChange:sender // accept changes in speed { speed = [sender selectedTag]; return self; } - findKeyFor:sender // used by below to set keys in pref. matrix { [sender setStringValue:keys[[sender tag]]]; return self; } - setUpViews { // here is where we hook up the views to be switched around in the panel // you should override this to add extra panes besides the three basic // ones expected here; you can use Columns as an example of how you // would go about doing this. [inspectorBox getFrame:&inspectFrame]; [viewPlayer getFrame:&view[0]]; [viewScreen getFrame:&view[1]]; [viewSound getFrame:&view[2]]; ViewsList = [[List alloc] init]; thePopUpList = [thePopUpListButton target]; [thePopUpList setTarget:self]; [thePopUpList setAction:@selector(toggleInspectorPanels:)]; [thePopUpList removeItemAt:0]; [thePopUpList removeItemAt:0]; [thePopUpList removeItemAt:0]; [[[[self addView:viewPlayer withName:[strings valueForStringKey:"Player"]] addView:viewScreen withName:[strings valueForStringKey:"Screen"]] addView:viewSound withName:[strings valueForStringKey:"Sound" ]] show:[strings valueForStringKey:"Player"]]; [preferencesPanel orderFront:self]; [inspectorBox display]; return self; } - preferences:sender // sets controls on pref panel & brings it up { [self preferencesPanel]; // be sure panel is loaded; throw away return val. if (firstLoad) { [self setUpViews]; [preferencesPanel orderFront:self]; [inspectorBox display]; firstLoad = NO; } [self refresh]; [[self preferencesPanel] orderFront:self]; return self; } - refresh // refresh all controls -- set them to display the current state { [speedButtons selectCellWithTag:speed]; [musicButtons selectCellWithTag:music]; [effectButtons selectCellWithTag:effects]; [levelText setIntValue:level]; [levelSlider setIntValue:level]; [alertSwitch setState:alert]; [borderSwitch setState:border]; [serverButton setState:useServer]; [serverText setStringValue:serverName]; [autoStartSwitch setState:autoStart]; [autoUnPauseSwitch setState:autoUnPause]; [demoSwitch setState:demoSound]; [keyMatrix sendAction:@selector(findKeyFor:) to:self forAllCells:YES]; return self; } // // Methods to handle inspectors and swapping views around... // (Very much adapted from NewInspector.m) // - free { [ViewsList free]; [preferencesPanel orderOut:self]; return [super free]; } - addView:(id)aView withName:(const char *)name { [ViewsList addObject:aView]; [thePopUpList addItem:name]; return self; } - show:(const char *)name { [self turnOnView:[thePopUpList indexOfItem:name]]; [thePopUpListButton setTitle:name]; return self; } - toggleInspectorPanels:sender { // from pop-up list; we display the appropriate view. return [self turnOnView:[sender selectedRow]]; } - turnOnView:(int)i { NXRect newFrame; [preferencesPanel disableFlushWindow]; // get the right view [inspectorBox setContentView:[ViewsList objectAt:i]]; // resize and move to the right place newFrame.size.width = view[i].size.width; newFrame.size.height = view[i].size.height; newFrame.origin.x = inspectFrame.origin.x + (inspectFrame.size.width - view[i].size.width)/2; newFrame.origin.y = inspectFrame.origin.y + (inspectFrame.size.height - view[i].size.height)/2; [inspectorBox setFrameFromContentFrame:&newFrame]; // erase junk around it -- this wouldn't be necessary if I // properly added/removed the Views from the respective hierarchies. // sometime I'll get around to fixing this. newFrame.size.width = view[i].size.width; newFrame.size.height = view[i].size.height; newFrame.origin.x = inspectFrame.origin.x + (inspectFrame.size.width - view[i].size.width)/2; newFrame.origin.y = inspectFrame.origin.y + (inspectFrame.size.height - view[i].size.height)/2; [grayView aroundFrame:&newFrame :inspectFrame.origin.y]; // finally, display the new view [inspectorBox display]; [self refresh]; [preferencesPanel reenableFlushWindow]; [preferencesPanel flushWindowIfNeeded]; return self; } - preferencesPanel // return the preferencesPanel, load it if needed. { if( !preferencesPanel) { [NXApp loadNibSection:"PreferencesPanel.nib" owner:self withNames:NO]; [preferencesPanel setFrameUsingName:"Prefs"]; [preferencesPanel setFrameAutosaveName:"Prefs"]; } return preferencesPanel; } - musicChange:sender // turn music on/off { music = [[sender selectedCell] tag]; // music runs independently, so we just turn it on or off at the // appropriate times. *****Maybe I should have the score playback // pause when you pause a game; right now it doesn't. #ifdef GK_USE_MUSICKIT if ((music) && ([gameScreen gameState] != GAMEOVER)) [scorePlayer play:self]; else [scorePlayer stop:self]; #endif return self; } - setScore:sender { // sent by "Set Score File..." button; we forward to the ScorePlayer #ifdef GK_USE_MUSICKIT [scorePlayer selectFile:sender]; #endif return self; } - effectsChange:sender // turn sound effects on/off { effects = [[sender selectedCell] tag]; [soundPlayer turnOn:effects]; return self; } - setDefaultPlayerName:(const char *)aString // change default player name { if (aString) [defaultPlayerName setStringValue:aString]; else [defaultPlayerName setStringValue:"Mystery Player"]; return self; } - (const char *)defaultPlayerName // return ptr to defaultPlayerName string { return [defaultPlayerName stringValue]; } - alertChange:sender { alert = NO; if ([sender state]) alert = YES; return self; } - unPauseChange:sender { autoUnPause = NO; if ([sender state]) autoUnPause = YES; return self; } - autoStartChange:sender { autoStart = NO; if ([sender state]) autoStart = YES; return self; } - demoSoundChange:sender // New turn off sound only in demo { demoSound = NO; if ([sender state]) demoSound = YES; return self; } - setBack:sender // set the background image { // forward the message to the game screen return [gameScreen changeBackground:sender]; } - revertBack:sender // revert to default background image { // forward the message to the game screen return [gameScreen revertBackground:sender]; } - (BOOL)borderOn { return border; } - setBorder:(BOOL)newBord { // turn gray border on/off if (border == newBord) return self; border = newBord; [gameScreen changeBorder:border]; // inform the GameView to adjust things. return self; } - borderChange:sender { // turn gray border on/off -- sent by control on the panel // this is a cover for the above method return [self setBorder:[sender state]]; } - setUseServer:(BOOL)useIt { // This allows the high score controlling object to turn things off // if it can't connect or it loses the connection to the server useServer = useIt; [serverButton setState:useIt]; return [self refresh]; } - changeServer:sender { // The main if block handles the button/check box, while the else // block handles changing the server name (and also automatically // checks the server box) if (sender != serverText) { // user changed the button state BOOL newUse = NO; // get the state of the check box if ([serverButton state]) newUse = YES; if (useServer != newUse) { // turn local on/off // attempt to connect to the servers if we aren't already // note that this call only will happen if we're going local // to network; if going the other way, we're already connected // so we pass through... if (![highScoreTable connected]) [highScoreTable connectToServers]; // before finishing, make sure there were no problems connecting; // we can't assume all is OK. (The -connected handles that; the // 0 is in the case of going to a local table...) useServer = (newUse ? [highScoreTable connected] : 0); [highScoreTable setLocalScores:!useServer]; } } else { // check to see if the name is changing if (strcmp(serverName, [serverText stringValue])) { // make note of the new name (it has changed) if (serverName) free(serverName); serverName = NXCopyStringBufferFromZone([serverText stringValue], [self zone]); [highScoreTable setServerHost:serverName]; // close current servers if already connected // because we need to switch to a different server if ([highScoreTable connected]) [highScoreTable closeServers]; } // force us to use the server (i.e. return in server field will cause // the check box to be checked automatically, enabling the server.) useServer = YES; [serverButton setState:useServer]; if (![highScoreTable connected]) [highScoreTable connectToServers]; // refresh the high score panel amongst other things. [highScoreTable setLocalScores:![highScoreTable connected]]; } // Note that if we couldn't locate the server, we go local. // (The HighScoreController did that automatically for us above.) // Finally, refresh the prefs panel to reflect any changes of internal // state, in particular the state of the check box, which may have // changed due to what happened above. (No connection, etc.) [self refresh]; return self; } // if the Prefs are "unfair" then a game cannot be saved on a network server. // it is up to you to add methods that set unfair when the prefs become // unfair. Also, in -startingGame, you should set unfair if any prefs are // unfair to begin with. As it stands here, any game is fair... Note that // the only way to clear the unfair variable is by starting a new game with // fair prefs; once a pref is made unfair, the game is unfair even if you // change it back. - (BOOL)unfair { return unfair; } - setUnfair { unfair = YES; return self; } - startingGame // reset the unfair variable { unfair = NO; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.