/* Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. This file is part of the WOLF3D iOS v2.1 GPL Source Code. 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 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import "wolf3dAppDelegate.h" #import "MainMenuViewController.h" #import "wolf3dViewController.h" #import "EAGLView.h" #import #include "../wolfiphone.h" #include //added for downloading SOD content from the internet... added by gsh extern void Com_Printf(const char* fmt, ... ); //extern void AppendData(NSData* data); extern void AppendDataToFile(NSData* data); extern void AppendUserDataToFile(NSData* data); //extern void SaveData(); //used for downloading custom made map extern void FinalizeUserDownload(); yesNoBoxType_t currentYesNoBox = YESNO_NONE; #if SPEARSTOREKIT //was used for storekit extern void FinalizeDownload(); extern int IsSpearPurchased(); extern int IsSpearInstalled(); extern void BeginStoreKit(); extern void GetSpear(); #endif extern void DownloadURLConnection(char *url); extern void iphoneSet2D(); //extern bool isAlive; @interface UIApplication (Private) - (void)setSystemVolumeHUDEnabled:(BOOL)enabled forAudioCategory:(NSString *)category; - (void)setSystemVolumeHUDEnabled:(BOOL)enabled; @end char iphoneDocDirectory[1024]; char iphoneAppDirectory[1024]; void SysIPhoneVibrate() { AudioServicesPlaySystemSound( kSystemSoundID_Vibrate ); } @implementation wolf3dAppDelegate @synthesize window; @synthesize viewController; @synthesize navigationController; @synthesize waitingView; @synthesize player; - (void)initMenuMusicPlayer { NSString *soundFilePath = [[NSBundle mainBundle] pathForResource: @"wondering" ofType: @"caf"]; NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath]; AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL error: nil]; [fileURL release]; if ( s_masterVolume != NULL ) { newPlayer.volume = s_masterVolume->value * 0.5f; } else { newPlayer.volume = 0.2f; } newPlayer.numberOfLoops = -1; self.player = newPlayer; [newPlayer release]; [player prepareToPlay]; } - (void)startMenuMusic { [player play]; } - (void)stopMenuMusic { [player stop]; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // get the documents directory, where we will write configs and save games NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; [documentsDirectory getCString: iphoneDocDirectory maxLength: sizeof( iphoneDocDirectory ) - 1 encoding: NSASCIIStringEncoding ]; // get the app directory, where our data files live paths = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES); NSString *appDirectory = documentsDirectory = [paths objectAtIndex:0]; [appDirectory getCString: iphoneAppDirectory maxLength: sizeof( iphoneAppDirectory ) - 1 encoding: NSASCIIStringEncoding ]; // start the flow of accelerometer events UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer]; accelerometer.delegate = self; accelerometer.updateInterval = 1.0 / 30.0; // do all the game startup work //iphoneStartup(); #if SPEARSTOREKIT //check if user downloaded spear but didn't purchase if (IsSpearInstalled() && !IsSpearPurchased()) { alertPurchaseSpear = [[UIAlertView alloc] initWithTitle:@""//Title" message:@"You have downloaded and installed Spear of Destiny. Would you like to unlock those levels by purchasing it for $1.99?" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes", nil]; [alertPurchaseSpear show]; } #endif // Sign up for rotation notifications [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil]; // Support rendering at native resolution on devices with Retina displays. if ( [[UIScreen mainScreen] respondsToSelector:@selector(scale)] ) { deviceScale = UIScreen.mainScreen.scale; touchCoordinateScale = UIScreen.mainScreen.scale; } // Screen is initially landscape-left. // BEWARE! For UI*Interface*Orientation, Left/Right refers to the location of the home button. // BUT, for UI*Device*Orientation, Left/Right refers to the location of the side OPPOSITE the home button!! [self setScreenForOrientation:UIDeviceOrientationLandscapeRight]; // Create the window programmatically instead of loading from a nib file. self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; // We will create the OpenGL view here so we can get a context and preload textures, but // don't actually add the view to the window until the player enters a level. wolf3dViewController *vc = [[wolf3dViewController alloc] initWithNibName:nil bundle:nil]; self.viewController = vc; [self.viewController setActive:NO]; [vc release]; MainMenuViewController *rootController = [[MainMenuViewController alloc] initWithNibName:@"MainMenuView" bundle:nil]; navigationController = [[UINavigationController alloc] initWithRootViewController:rootController]; [navigationController setNavigationBarHidden:YES]; [rootController release]; [window addSubview:navigationController.view]; [window makeKeyAndVisible]; return YES; } - (void)showOpenGL { // Maybe clearing the OpenGL view before displaying will fix the old frame flashing. // I don't mind if this blocks until a vsync, becasue it's just a menu. [self.viewController clearAndPresentRenderbuffer]; [[navigationController view] removeFromSuperview]; [self.viewController setActive:YES]; [window addSubview:[self.viewController view]]; [self.viewController startAnimation]; } - (void)didRotate:(NSNotification *)notification { UIDeviceOrientation orient = [[UIDevice currentDevice] orientation]; [self setScreenForOrientation:orient]; } - (void)setScreenForOrientation:(UIDeviceOrientation) orientation { // Note the the UIDeviceOrientations are REVERSED from the UIInterface orientations! switch (orientation) { case UIDeviceOrientationLandscapeLeft: deviceOrientation = ORIENTATION_LANDSCAPE_RIGHT; viddef.width = [UIScreen mainScreen].bounds.size.height * deviceScale; viddef.height = [UIScreen mainScreen].bounds.size.width * deviceScale; //[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeRight; break; case UIDeviceOrientationLandscapeRight: deviceOrientation = ORIENTATION_LANDSCAPE_LEFT; viddef.width = [UIScreen mainScreen].bounds.size.height * deviceScale; viddef.height = [UIScreen mainScreen].bounds.size.width * deviceScale; //[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeLeft; break; default: break; } float widthRatio = viddef.width / REFERENCE_WIDTH; float heightRatio = viddef.height / REFERENCE_HEIGHT; if ( widthRatio < heightRatio ) { screenScale = widthRatio; } else { screenScale = heightRatio; } } //this is so that we can respond to alertView events (messageboxes) //but this should only respond to the alertPurchaseSpear - (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex == 1) { switch ( currentYesNoBox ) { case YESNO_BUY_PLATINUM: { // They clicked yes to buy the platinum edition. // Set up a fullscreen view with the activity indicator in the middle while // we wait for the in-app purchase to complete. UIView* topView = [[self.navigationController topViewController] view]; CGRect waitFrame = topView.frame; [waitingView release]; waitingView = [[UIView alloc] initWithFrame:waitFrame]; waitingView.backgroundColor = [UIColor blackColor]; waitingView.opaque = NO; waitingView.alpha = 0.75; UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; [indicator startAnimating]; [waitingView addSubview:indicator]; // This mask centers the view in its superview indicator.center = indicator.superview.center; [indicator release]; [topView addSubview:waitingView]; // Start the request to the app store InAppPurchaseSetCallback( inAppPurchaseCallback ); InAppPurchaseStartPurchase( PLATINUM_UPGRADE_STRING ); break; } case YESNO_GO_TO_WEBSITE: //if they clicked yes to going to the idsoftware website SysIPhoneOpenURL( "http://www.idsoftware.com/wolfenstein-3d-classic-platinum/" ); break; case YESNO_DOWNLOAD_INSTRUCTIONS: //this is if they clicked yes to going to the map instructions website SysIPhoneOpenURL( "http://www.idsoftware.com/wolfenstein-3d-classic-platinum/mapinstructions/" ); break; default: break; } } /* if (alertPurchaseSpear && (alertPurchaseSpear == actionSheet)) { if (buttonIndex != actionSheet.cancelButtonIndex) BeginStoreKit(); }*/ } - (void)applicationWillResignActive:(UIApplication *)application { [self.viewController stopAnimation]; } - (void)applicationDidBecomeActive:(UIApplication *)application { [self.viewController startAnimation]; } - (void)applicationWillTerminate:(UIApplication *)application { [self.viewController stopAnimation]; // Save the game. iphoneShutdown(); } - (void)applicationDidEnterBackground:(UIApplication *)application { [self.viewController stopAnimation]; // Save the game. iphoneShutdown(); } - (void)dismissWaitingView { if ( waitingView != nil ) { [waitingView removeFromSuperview]; [waitingView release]; waitingView = nil; } } #if 1 extern char urlbuffer[1024]; - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { // wolf3d:foo should launch wolf3d now... next, add useful URL parameter encoding if ( SysIPhoneGetContentVersion() == CONTENT_LITE ) { iphoneMessageBox("Lite version", "This is a Lite version. You must purchase Wolfenstein3D to get this feature."); return NO; } if (!url) return NO; NSString *str = [url absoluteString]; //in the future we may wish to parse this string //for commands that wolf3d might follow //for now we'll just start the storekit char buffer[1024]; if(![str getCString:buffer maxLength:1024 encoding:NSUTF8StringEncoding]) { iphoneMessageBox("Not Valid", "There were encoding errors. Make sure the link is less than 1023 characters in length."); return NO; } //iphoneMessageBox("URL", buffer); /* if (strcmp(buffer, "wolf3d:foo") == 0) GetSpear(); */ char *pstr = buffer;//&buffer[strlen(buffer) - 5]; pstr += strlen(buffer) - 4; if (strcmp(pstr, ".map") != 0) { iphoneMessageBox("Not Valid", "URL is not a valid map. Maps must end in \".map\""); return NO; } if (strncmp(buffer, "wolf3dp:", 8) == 0) { char cURL[1024]; char *http = "http:"; strcpy(cURL, http); strcpy(cURL + 5, buffer + 8); //strcpy(cURL, "http://gregory.hodges.googlepages.com/SODmm.tgz"); //TODO: delete me Com_Printf("wolf3dp: installing map %s\n", cURL); strcpy(urlbuffer, cURL); //download and install this map //iphoneMessageBox("wolf3d:", "it's a map TODO install"); //InstallUserMap(); DownloadURLConnection(cURL); } else { iphoneMessageBox("Not Valid", "URL is not a valid map. Identifier must start with \"wolf3dp:\""); return NO; } return YES; } #endif - (void)dealloc { [viewController release]; [navigationController release]; [window release]; [super dealloc]; } - (void)restartAccelerometerIfNeeded { // I have no idea why this seems to happen sometimes... if ( Sys_Milliseconds() - lastAccelUpdateMsec > 1000 ) { static int count; if ( ++count < 5 ) { printf( "Restarting accelerometer updates.\n" ); } UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer]; accelerometer.delegate = self; accelerometer.updateInterval = 1.0 / 30.0; } } - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { float acc[4]; acc[0] = acceleration.x; acc[1] = acceleration.y; acc[2] = acceleration.z; acc[3] = acceleration.timestamp; iphoneTiltEvent( acc ); lastAccelUpdateMsec = Sys_Milliseconds(); } //------------------------------------------------------------ // connection // called by the app when data is received during download // gsh //------------------------------------------------------------- - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { // lock the game out temporarily pthread_mutex_t eventMutex; pthread_mutex_lock( &eventMutex ); /* //display the network activity indicator UIApplication* app = [UIApplication sharedApplication]; app.networkActivityIndicatorVisible = YES; // to stop it, set this to NO app.statusBarHidden = NO; */ // append the new data to file AppendUserDataToFile(data); // the game is free to copy the appendedData size now pthread_mutex_unlock( &eventMutex ); } //------------------------------------------------------------------------ // connectionDidFinishLoading // this is called when the app finishes downloading // the new Spear of Destiny Levels // gsh //------------------------------------------------------------------------ - (void) connectionDidFinishLoading:(NSURLConnection *)connection { Com_Printf("connectionDidFinishLoading called\n"); /* //no need to display network traffic anymore UIApplication* app = [UIApplication sharedApplication]; app.networkActivityIndicatorVisible = NO; // to stop it, set this to NO app.statusBarHidden = YES; */ //release the connection [connection release]; //uncompress/move files/delete unwanted FinalizeUserDownload(); } //------------------------------------------------------------------------ // connection didFailWithError // if the connection fails during the download then this is called // gsh //------------------------------------------------------------------------ - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { //let user know that the connection failed iphoneMessageBox("Connection Failed", "Please check your connection and try again later."); //return the user to the main menu menuState = IPM_MAIN; /* //no need to display network traffic anymore UIApplication* app = [UIApplication sharedApplication]; app.networkActivityIndicatorVisible = NO; // to stop it, set this to NO app.statusBarHidden = YES; */ } /* - (void)setDownloadResponse:(NSURLResponse *)aDownloadResponse { [aDownloadResponse retain]; [downloadResponse release]; downloadResponse = aDownloadResponse; } - (void)download:(NSURLDownload *)download didReceiveResponse:(NSURLResponse *)response { // reset the progress, this might be called multiple times bytesReceived=0; // retain the response to use later [self setDownloadResponse:response]; } - (void)download:(NSURLDownload *)download didReceiveDataOfLength:(unsigned)length { long long expectedLength=[[self downloadResponse] expectedContentLength]; bytesReceived=bytesReceived+length; if (expectedLength != NSURLResponseUnknownLength) { // if the expected content length is // available, display percent complete float percentComplete=(bytesReceived/(float)expectedLength)*100.0; NSLog(@"Percent complete - %f",percentComplete); } else { // if the expected content length is // unknown just log the progress NSLog(@"Bytes received - %d",bytesReceived); } } */ - (void)GLtoMainMenu { [self.navigationController popToRootViewControllerAnimated:NO]; [viewController setActive:NO]; [[viewController view] removeFromSuperview]; [window addSubview:navigationController.view]; } - (void)GLtoPreviousMenu { [viewController setActive:NO]; [[viewController view] removeFromSuperview]; [window addSubview:navigationController.view]; } @end void iphoneStartMainMenu() { Sound_StopBGTrack(); iphoneStartMenuMusic(); numTouches = 0; numPrevTouches = 0; wolf3dAppDelegate *app = (wolf3dAppDelegate*)[[UIApplication sharedApplication] delegate]; [app GLtoMainMenu]; } void iphoneStartPreviousMenu() { wolf3dAppDelegate *app = (wolf3dAppDelegate*)[[UIApplication sharedApplication] delegate]; [app GLtoPreviousMenu ]; } void inAppPurchaseCallback( InAppPurchaseResult result ) { wolf3dAppDelegate* app = (wolf3dAppDelegate*)[[UIApplication sharedApplication] delegate]; [app dismissWaitingView]; }