project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m
changeset 5010 af4e205e4b5a
parent 5009 12135f659bf1
parent 5004 2efa6a414518
child 5011 73c5839d4447
equal deleted inserted replaced
5009:12135f659bf1 5010:af4e205e4b5a
     1 /*
       
     2  SDL - Simple DirectMedia Layer
       
     3  Copyright (C) 1997-2011 Sam Lantinga
       
     4 
       
     5  This library is free software; you can redistribute it and/or
       
     6  modify it under the terms of the GNU Lesser General Public
       
     7  License as published by the Free Software Foundation; either
       
     8  version 2.1 of the License, or (at your option) any later version.
       
     9 
       
    10  This library is distributed in the hope that it will be useful,
       
    11  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  Lesser General Public License for more details.
       
    14 
       
    15  You should have received a copy of the GNU Lesser General Public
       
    16  License along with this library; if not, write to the Free Software
       
    17  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    18 
       
    19  Sam Lantinga, mods for Hedgewars by Vittorio Giovara
       
    20  slouken@libsdl.org, vittorio.giovara@gmail.com
       
    21 */
       
    22 
       
    23 #import "SDL_uikitappdelegate.h"
       
    24 #import "SDL_uikitopenglview.h"
       
    25 #import "SDL_uikitwindow.h"
       
    26 #import "SDL_events_c.h"
       
    27 #import "jumphack.h"
       
    28 #import "SDL_video.h"
       
    29 #import "SDL_mixer.h"
       
    30 #import "PascalImports.h"
       
    31 #import "ObjcExports.h"
       
    32 #import "CommodityFunctions.h"
       
    33 #import "GameSetup.h"
       
    34 #import "MainMenuViewController.h"
       
    35 #import "OverlayViewController.h"
       
    36 #import "Appirater.h"
       
    37 #include <unistd.h>
       
    38 
       
    39 #ifdef main
       
    40 #undef main
       
    41 #endif
       
    42 
       
    43 #define BLACKVIEW_TAG 17935
       
    44 #define SECONDBLACKVIEW_TAG 48620
       
    45 #define VALGRIND "/opt/fink/bin/valgrind"
       
    46 
       
    47 int main (int argc, char *argv[]) {
       
    48 #ifdef VALGRIND_REXEC
       
    49     // Using the valgrind build config, rexec ourself in valgrind
       
    50     // from http://landonf.bikemonkey.org/code/iphone/iPhone_Simulator_Valgrind.20081224.html
       
    51     if (argc < 2 || (argc >= 2 && strcmp(argv[1], "-valgrind") != 0))
       
    52         execl(VALGRIND, VALGRIND, "--leak-check=full", "--dsymutil=yes", argv[0], "-valgrind", NULL);
       
    53 #endif
       
    54     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       
    55     int retVal = UIApplicationMain(argc, argv, nil, @"SDLUIKitDelegate");
       
    56     [pool release];
       
    57     return retVal;
       
    58 }
       
    59 
       
    60 @implementation SDLUIKitDelegate
       
    61 @synthesize mainViewController, overlayController, uiwindow, secondWindow, isInGame;
       
    62 
       
    63 // convenience method
       
    64 +(SDLUIKitDelegate *)sharedAppDelegate {
       
    65     // the delegate is set in UIApplicationMain(), which is guaranteed to be called before this method
       
    66     return (SDLUIKitDelegate *)[[UIApplication sharedApplication] delegate];
       
    67 }
       
    68 
       
    69 -(id) init {
       
    70     if (self = [super init]){
       
    71         mainViewController = nil;
       
    72         uiwindow = nil;
       
    73         secondWindow = nil;
       
    74         isInGame = NO;
       
    75     }
       
    76     return self;
       
    77 }
       
    78 
       
    79 -(void) dealloc {
       
    80     [mainViewController release];
       
    81     [overlayController release];
       
    82     [uiwindow release];
       
    83     [secondWindow release];
       
    84     [super dealloc];
       
    85 }
       
    86 
       
    87 // main routine for calling the actual game engine
       
    88 -(NSArray *)startSDLgame:(NSDictionary *)gameDictionary {
       
    89     UIWindow *gameWindow;
       
    90     if (IS_DUALHEAD())
       
    91         gameWindow = self.secondWindow;
       
    92     else
       
    93         gameWindow = self.uiwindow;
       
    94 
       
    95     UIView *blackView = [[UIView alloc] initWithFrame:gameWindow.frame];
       
    96     blackView.backgroundColor = [UIColor blackColor];
       
    97     blackView.opaque = YES;
       
    98     blackView.tag = BLACKVIEW_TAG;
       
    99     [gameWindow addSubview:blackView];    
       
   100     if (IS_DUALHEAD()) {
       
   101         blackView.alpha = 0;
       
   102         [UIView beginAnimations:@"fading to game first" context:NULL];
       
   103         [UIView setAnimationDuration:1];
       
   104         blackView.alpha = 1;
       
   105         [UIView commitAnimations];
       
   106         
       
   107         UIView *secondBlackView = [[UIView alloc] initWithFrame:self.uiwindow.frame];
       
   108         secondBlackView.backgroundColor = [UIColor blackColor];
       
   109         secondBlackView.opaque = YES;
       
   110         secondBlackView.tag = SECONDBLACKVIEW_TAG;
       
   111         secondBlackView.alpha = 0;
       
   112         [self.uiwindow addSubview:secondBlackView];
       
   113         [UIView beginAnimations:@"fading to game second" context:NULL];
       
   114         [UIView setAnimationDuration:1];
       
   115         secondBlackView.alpha = 1;
       
   116         [UIView commitAnimations];
       
   117         [secondBlackView release];
       
   118     }
       
   119     [blackView release];
       
   120 
       
   121 
       
   122     // pull out useful configuration info from various files
       
   123     GameSetup *setup = [[GameSetup alloc] initWithDictionary:gameDictionary];
       
   124     NSNumber *isNetGameNum = [gameDictionary objectForKey:@"netgame"];
       
   125 
       
   126     [NSThread detachNewThreadSelector:@selector(engineProtocol)
       
   127                              toTarget:setup
       
   128                            withObject:nil];
       
   129 
       
   130     NSNumber *menuStyle = [NSNumber numberWithBool:setup.menuStyle];
       
   131     NSNumber *orientation = [[gameDictionary objectForKey:@"game_dictionary"] objectForKey:@"orientation"];
       
   132     NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
       
   133                           isNetGameNum,@"net",
       
   134                           menuStyle,@"menu",
       
   135                           orientation,@"orientation",
       
   136                           nil];
       
   137     [self performSelector:@selector(displayOverlayLater:) withObject:dict afterDelay:1];
       
   138 
       
   139     // need to set again [gameDictionary objectForKey:@"savefile"] because if it's empty it means it's a normal game
       
   140     const char **gameArgs = [setup getGameSettings:[gameDictionary objectForKey:@"savefile"]];
       
   141     self.isInGame = YES;
       
   142     // this is the pascal fuction that starts the game
       
   143     Game(gameArgs);
       
   144     self.isInGame = NO;
       
   145     free(gameArgs);
       
   146     
       
   147     NSArray *stats = setup.statsArray;
       
   148     [setup release];
       
   149 
       
   150 
       
   151     [self.uiwindow makeKeyAndVisible];
       
   152     [self.uiwindow bringSubviewToFront:self.mainViewController.view];
       
   153     
       
   154     UIView *refBlackView = [gameWindow viewWithTag:BLACKVIEW_TAG];
       
   155     UIView *refSecondBlackView = [self.uiwindow viewWithTag:SECONDBLACKVIEW_TAG];
       
   156     [UIView beginAnimations:@"fading in from ingame" context:NULL];
       
   157     [UIView setAnimationDuration:1];
       
   158     refBlackView.alpha = 0;
       
   159     refSecondBlackView.alpha = 0;
       
   160     [UIView commitAnimations];
       
   161     [refBlackView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1];
       
   162     [refSecondBlackView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:2];
       
   163 
       
   164     return stats;
       
   165 }
       
   166 
       
   167 // overlay with controls, become visible later, with a transparency effect since the sdlwindow is not yet created
       
   168 -(void) displayOverlayLater:(id) object {
       
   169     NSDictionary *dict = (NSDictionary *)object;
       
   170     self.overlayController = [[OverlayViewController alloc] initWithNibName:@"OverlayViewController" bundle:nil];
       
   171     self.overlayController.isNetGame = [[dict objectForKey:@"net"] boolValue];
       
   172     self.overlayController.useClassicMenu = [[dict objectForKey:@"menu"] boolValue];
       
   173     self.overlayController.initialOrientation = [[dict objectForKey:@"orientation"] intValue];
       
   174     
       
   175     UIWindow *gameWindow;
       
   176     if (IS_DUALHEAD())
       
   177         gameWindow = self.uiwindow;
       
   178     else
       
   179         gameWindow = [[UIApplication sharedApplication] keyWindow];
       
   180     [gameWindow addSubview:self.overlayController.view];
       
   181 }
       
   182 
       
   183 // override the direct execution of SDL_main to allow us to implement the frontend (or even using a nib)
       
   184 -(BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
       
   185     [application setStatusBarHidden:YES];
       
   186 
       
   187     self.uiwindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
       
   188 
       
   189     if (IS_IPAD())
       
   190         self.mainViewController = [[MainMenuViewController alloc] initWithNibName:@"MainMenuViewController-iPad" bundle:nil];
       
   191     else
       
   192         self.mainViewController = [[MainMenuViewController alloc] initWithNibName:@"MainMenuViewController-iPhone" bundle:nil];
       
   193 
       
   194     [self.uiwindow addSubview:self.mainViewController.view];
       
   195     [self.mainViewController release];
       
   196     self.uiwindow.backgroundColor = [UIColor blackColor];
       
   197     [self.uiwindow makeKeyAndVisible];
       
   198 
       
   199     // set working directory to resource path
       
   200     [[NSFileManager defaultManager] changeCurrentDirectoryPath:[[NSBundle mainBundle] resourcePath]];
       
   201 
       
   202     // check for dual monitor support
       
   203     if (IS_DUALHEAD()) {
       
   204         DLog(@"dual head mode ftw");
       
   205         self.secondWindow = [[UIWindow alloc] initWithFrame:[[[UIScreen screens] objectAtIndex:1] bounds]];
       
   206         self.secondWindow.backgroundColor = [UIColor blackColor];
       
   207         self.secondWindow.screen = [[UIScreen screens] objectAtIndex:1];
       
   208         UIImage *titleImage = [UIImage imageWithContentsOfFile:@"title.png"];
       
   209         UIImageView *titleView = [[UIImageView alloc] initWithImage:titleImage];
       
   210         titleView.center = self.secondWindow.center;
       
   211         [self.secondWindow addSubview:titleView];
       
   212         [titleView release];
       
   213         [self.secondWindow makeKeyAndVisible];
       
   214     }
       
   215 
       
   216     [Appirater appLaunched];
       
   217     return YES;
       
   218 }
       
   219 
       
   220 -(void) applicationWillTerminate:(UIApplication *)application {
       
   221     SDL_SendQuit();
       
   222 
       
   223     if (self.isInGame) {
       
   224         HW_terminate(YES);
       
   225         // hack to prevent automatic termination. See SDL_uikitevents.m for details
       
   226         longjmp(*(jump_env()), 1);
       
   227     }
       
   228 }
       
   229 
       
   230 -(void) applicationDidReceiveMemoryWarning:(UIApplication *)application {
       
   231     // don't clean mainMenuViewController here!!!
       
   232     MSG_MEMCLEAN();
       
   233     print_free_memory();
       
   234 }
       
   235 
       
   236 -(void) applicationWillResignActive:(UIApplication *)application {
       
   237     UIDevice* device = [UIDevice currentDevice];
       
   238     if ([device respondsToSelector:@selector(isMultitaskingSupported)] &&
       
   239          device.multitaskingSupported &&
       
   240          self.isInGame) {
       
   241         // let's try to be permissive with multitasking here...
       
   242         NSDictionary *settings = [[NSDictionary alloc] initWithContentsOfFile:SETTINGS_FILE()];
       
   243         if ([[settings objectForKey:@"multitasking"] boolValue])
       
   244             HW_suspend();
       
   245         else {
       
   246             // so the game returns to the configuration view
       
   247             if (isGameRunning())
       
   248                 HW_terminate(NO);
       
   249             else {
       
   250                 // while screen is loading you can't call HW_terminate() so we close the app
       
   251                 SDL_SendQuit();
       
   252                 HW_terminate(YES);
       
   253                 longjmp(*(jump_env()), 1);
       
   254             }
       
   255         }
       
   256         [settings release];
       
   257     }
       
   258 }
       
   259 
       
   260 -(void) applicationDidBecomeActive:(UIApplication *)application {
       
   261     UIDevice* device = [UIDevice currentDevice];
       
   262     if ([device respondsToSelector:@selector(isMultitaskingSupported)] &&
       
   263          device.multitaskingSupported &&
       
   264          self.isInGame) {
       
   265         HW_resume();
       
   266     }
       
   267 }
       
   268 
       
   269 @end