project_files/HedgewarsMobile/Classes/OverlayViewController.m
changeset 5166 d1eb1560b4d5
parent 5156 641abe679bf0
child 5174 f5294509783e
equal deleted inserted replaced
5165:91fb710a6668 5166:d1eb1560b4d5
    37 
    37 
    38 #define removeInputWidget() [[self.view viewWithTag:CONFIRMATION_TAG] removeFromSuperview]; \
    38 #define removeInputWidget() [[self.view viewWithTag:CONFIRMATION_TAG] removeFromSuperview]; \
    39                             [[self.view viewWithTag:GRENADE_TAG] removeFromSuperview];
    39                             [[self.view viewWithTag:GRENADE_TAG] removeFromSuperview];
    40 
    40 
    41 @implementation OverlayViewController
    41 @implementation OverlayViewController
    42 @synthesize popoverController, popupMenu, helpPage, amvc, useClassicMenu, initialOrientation;
    42 @synthesize popoverController, popupMenu, helpPage, amvc, useClassicMenu, initialScreenCount, initialOrientation;
    43 
    43 
    44 #pragma mark -
    44 #pragma mark -
    45 #pragma mark rotation
    45 #pragma mark rotation
    46 
    46 
    47 -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation {
    47 -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation {
    49     if (isGameRunning() == NO)
    49     if (isGameRunning() == NO)
    50         return (interfaceOrientation == (UIInterfaceOrientation) self.initialOrientation);
    50         return (interfaceOrientation == (UIInterfaceOrientation) self.initialOrientation);
    51     return rotationManager(interfaceOrientation);
    51     return rotationManager(interfaceOrientation);
    52 }
    52 }
    53 
    53 
    54 // pause the game and remove objc menus so that animation is smoother
    54 // while in dual head the above rotation functions are not called
    55 -(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation) toInterfaceOrientation duration:(NSTimeInterval) duration{
    55 -(void) handleRotationEvent:(NSNotification *)notification {
    56     if (isGameRunning() == NO)
    56     if (isGameRunning() == NO)
    57         return;
    57         return;
    58 
    58 
    59     HW_pause();
       
    60     [self dismissPopover];
       
    61 
       
    62     if (self.amvc.isVisible && IS_DUALHEAD() == NO) {
       
    63         [self.amvc disappear];
       
    64         wasVisible = YES;
       
    65     } else
       
    66         wasVisible = NO;
       
    67 
       
    68     [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
       
    69 
       
    70     UIView *sdlView = [[[UIApplication sharedApplication] keyWindow] viewWithTag:SDL_VIEW_TAG];
       
    71     switch (toInterfaceOrientation) {
       
    72         case UIDeviceOrientationLandscapeLeft:
       
    73             sdlView.transform = CGAffineTransformMakeRotation(degreesToRadians(a));
       
    74             break;
       
    75         case UIDeviceOrientationLandscapeRight:
       
    76             sdlView.transform = CGAffineTransformMakeRotation(degreesToRadians(b));
       
    77             break;
       
    78         default:
       
    79             // a debug log would spam too much
       
    80             break;
       
    81     }
       
    82 }
       
    83 
       
    84 // now restore previous state
       
    85 -(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation) fromInterfaceOrientation {
       
    86     if (isGameRunning() == NO)
       
    87         return;
       
    88 
       
    89     if (wasVisible || IS_DUALHEAD())
       
    90         [self.amvc appearInView:self.view];
       
    91     HW_pauseToggle();
       
    92 
       
    93     [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
       
    94 }
       
    95 
       
    96 // while in dual head the above rotation functions are not called
       
    97 -(void) dualHeadRotation:(NSNotification *)notification {
       
    98     if (isGameRunning() == NO)
       
    99         return;
       
   100 
       
   101     UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
    59     UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
   102     UIView *sdlView = [[[UIApplication sharedApplication] keyWindow] viewWithTag:SDL_VIEW_TAG];
    60     UIView *sdlView = [[[UIApplication sharedApplication] keyWindow] viewWithTag:SDL_VIEW_TAG];
   103 
    61     NSInteger angle_left = (self.initialOrientation == UIInterfaceOrientationLandscapeLeft) ? 180 : 0;
   104     [UIView beginAnimations:@"rotation" context:NULL];
    62     NSInteger angle_right = (self.initialOrientation == UIInterfaceOrientationLandscapeLeft) ? 0 : 180;
   105     [UIView setAnimationDuration:0.7];
    63 
       
    64     if (IS_VERY_POWERFUL()) {
       
    65         [UIView beginAnimations:@"overlay rotation" context:NULL];
       
    66         [UIView setAnimationDuration:0.7];
       
    67     }
   106     switch (orientation) {
    68     switch (orientation) {
   107         case UIDeviceOrientationLandscapeLeft:
    69         case UIDeviceOrientationLandscapeLeft:
   108             self.view.frame = [[UIScreen mainScreen] bounds];
    70             self.view.frame = [[UIScreen mainScreen] bounds];
   109             self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(90));
    71             self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(90));
   110             sdlView.transform = CGAffineTransformMakeRotation(degreesToRadians(a));
    72             if (IS_DUALHEAD() == NO)
       
    73                 sdlView.transform = CGAffineTransformMakeRotation(degreesToRadians(angle_left));
   111             break;
    74             break;
   112         case UIDeviceOrientationLandscapeRight:
    75         case UIDeviceOrientationLandscapeRight:
   113             self.view.frame = [[UIScreen mainScreen] bounds];
    76             self.view.frame = [[UIScreen mainScreen] bounds];
   114             self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(-90));
    77             self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(-90));
   115             sdlView.transform = CGAffineTransformMakeRotation(degreesToRadians(b));
    78             if (IS_DUALHEAD() == NO)
       
    79                 sdlView.transform = CGAffineTransformMakeRotation(degreesToRadians(angle_right));
   116             break;
    80             break;
   117         default:
    81         default:
   118             // a debug log would spam too much
    82             // a debug log would spam too much
   119             break;
    83             break;
   120     }
    84     }
   121     [UIView commitAnimations];
    85     if (IS_VERY_POWERFUL())
       
    86         [UIView commitAnimations];
   122 }
    87 }
   123 
    88 
   124 #pragma mark -
    89 #pragma mark -
   125 #pragma mark View Management
    90 #pragma mark View Management
   126 -(id) initWithCoder:(NSCoder *)aDecoder {
    91 -(id) initWithCoder:(NSCoder *)aDecoder {
   127     if ((self = [super initWithCoder:aDecoder])) {
    92     if ((self = [super initWithCoder:aDecoder])) {
   128         objcExportsInit();
    93         objcExportsInit();
   129         isAttacking = NO;
    94         isAttacking = NO;
   130         wasVisible = NO;
    95         isPopoverVisible = NO;
   131         isPopoverVisible = NO;    // it is called "popover" even on the iphone
    96         initialScreenCount = (IS_DUALHEAD() ? 2 : 1);
       
    97         initialOrientation = 0;
   132     }
    98     }
   133     return self;
    99     return self;
   134 }
   100 }
   135 
   101 
   136 -(void) viewDidLoad {
   102 -(void) viewDidLoad {
   137     CGRect screenRect = [[UIScreen mainScreen] bounds];
   103     CGRect screenRect = [[UIScreen mainScreen] bounds];
   138     self.view.frame = CGRectMake(0, 0, screenRect.size.height, screenRect.size.width);
   104     self.view.frame = CGRectMake(0, 0, screenRect.size.height, screenRect.size.width);
   139     self.view.center = CGPointMake(self.view.frame.size.height/2, self.view.frame.size.width/2);
   105     self.view.center = CGPointMake(self.view.frame.size.height/2, self.view.frame.size.width/2);
   140     self.view.alpha = 0;
       
   141 
       
   142     // detrmine the quanitiy and direction of the rotation
       
   143     if (self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
       
   144         a = 180;
       
   145         b = 0;
       
   146     } else {
       
   147         a = 0;
       
   148         b = 180;
       
   149     }
       
   150 
       
   151     // get the number of screens to know the previous state whan a display is connected or detached
       
   152     if ([UIScreen respondsToSelector:@selector(screens)])
       
   153         initialScreenCount = [[UIScreen screens] count];
       
   154     else
       
   155         initialScreenCount = 1;
       
   156 
   106 
   157     // set initial orientation of the controller orientation
   107     // set initial orientation of the controller orientation
   158         switch (self.interfaceOrientation) {
   108     switch (self.interfaceOrientation) {
   159             case UIDeviceOrientationLandscapeLeft:
   109         case UIDeviceOrientationLandscapeLeft:
   160                 self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(90));
   110             self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(90));
   161                 break;
   111             break;
   162             case UIDeviceOrientationLandscapeRight:
   112         case UIDeviceOrientationLandscapeRight:
   163                 self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(-90));
   113             self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(-90));
   164                 break;
   114             break;
   165             default:
   115         default:
   166                 DLog(@"Nope");
   116             DLog(@"Nope");
   167                 break;
   117             break;
   168         }
   118     }
   169         [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
   119     [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
   170         [[NSNotificationCenter defaultCenter] addObserver:self
   120     [[NSNotificationCenter defaultCenter] addObserver:self
   171                                                  selector:@selector(dualHeadRotation:)
   121                                              selector:@selector(handleRotationEvent:)
   172                                                      name:UIDeviceOrientationDidChangeNotification
   122                                                  name:UIDeviceOrientationDidChangeNotification
   173                                                    object:nil];
   123                                                object:nil];
   174 
   124     
   175     // the timer used to dim the overlay
   125     // the timer used to dim the overlay
   176     dimTimer = [[NSTimer alloc] initWithFireDate:(IS_DUALHEAD()) ? HIDING_TIME_NEVER : [NSDate dateWithTimeIntervalSinceNow:6]
   126     dimTimer = [[NSTimer alloc] initWithFireDate:(IS_DUALHEAD()) ? HIDING_TIME_NEVER : [NSDate dateWithTimeIntervalSinceNow:6]
   177                                         interval:1000
   127                                         interval:1000
   178                                           target:self
   128                                           target:self
   179                                         selector:@selector(dimOverlay)
   129                                         selector:@selector(dimOverlay)
   200                                                      name:UIScreenDidDisconnectNotification
   150                                                      name:UIScreenDidDisconnectNotification
   201                                                    object:nil];
   151                                                    object:nil];
   202     }
   152     }
   203     
   153     
   204     // present the overlay
   154     // present the overlay
       
   155     self.view.alpha = 0;
   205     [UIView beginAnimations:@"showing overlay" context:NULL];
   156     [UIView beginAnimations:@"showing overlay" context:NULL];
   206     [UIView setAnimationDuration:2];
   157     [UIView setAnimationDuration:2];
   207     self.view.alpha = 1;
   158     self.view.alpha = 1;
   208     [UIView commitAnimations];
   159     [UIView commitAnimations];
   209 }
   160 }
   210 
   161 
   211 -(void) numberOfScreensIncreased {
   162 -(void) viewDidUnload {
   212     if (initialScreenCount == 1) {
   163     [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
   213         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"New display detected"
   164     [[NSNotificationCenter defaultCenter] removeObserver:self];
   214                                                         message:NSLocalizedString(@"Hedgewars supports multi-monitor configurations, but the screen has to be connected before launching the game.",@"")
   165 
   215                                                        delegate:nil
   166     [NSObject cancelPreviousPerformRequestsWithTarget:self
   216                                               cancelButtonTitle:@"Ok"
   167                                              selector:@selector(unsetPreciseStatus)
   217                                               otherButtonTitles:nil];
   168                                                object:nil];
   218         [alert show];
   169 
   219         [alert release];
   170     // only objects initialized in viewDidLoad should be here
   220         HW_pause();
   171     dimTimer = nil;
   221     }
   172     self.helpPage = nil;
   222 }
   173     [self dismissPopover];
   223 
   174     self.popoverController = nil;
   224 -(void) numberOfScreensDecreased {
   175     self.amvc = nil;
   225     if (initialScreenCount == 2) {
   176     MSG_DIDUNLOAD();
   226         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Oh noes! Display disconnected"
   177     [super viewDidUnload];
   227                                                         message:NSLocalizedString(@"A monitor has been disconnected while playing and this has ended the match! You need to restart the game if you wish to use the second display again.",@"")
       
   228                                                        delegate:nil
       
   229                                               cancelButtonTitle:@"Ok"
       
   230                                               otherButtonTitles:nil];
       
   231         [alert show];
       
   232         [alert release];
       
   233         HW_terminate(NO);
       
   234     }
       
   235 }
       
   236 
       
   237 
       
   238 -(void) showHelp:(id) sender {
       
   239     if (self.helpPage == nil) {
       
   240         NSString *xibName = (IS_IPAD() ? @"HelpPageInGameViewController-iPad" : @"HelpPageInGameViewController-iPhone");
       
   241         self.helpPage = [[HelpPageViewController alloc] initWithNibName:xibName bundle:nil];
       
   242     }
       
   243     self.helpPage.view.alpha = 0;
       
   244     [self.view addSubview:helpPage.view];
       
   245     [UIView beginAnimations:@"helpingame" context:NULL];
       
   246     self.helpPage.view.alpha = 1;
       
   247     [UIView commitAnimations];
       
   248     doNotDim();
       
   249 }
       
   250 
       
   251 -(void) removeOverlay {
       
   252     [self.popupMenu performSelectorOnMainThread:@selector(dismiss) withObject:nil waitUntilDone:YES];
       
   253     [self.popoverController performSelectorOnMainThread:@selector(dismissPopoverAnimated:) withObject:nil waitUntilDone:YES];
       
   254     [self.view performSelectorOnMainThread:@selector(removeFromSuperview) withObject:nil waitUntilDone:YES];
       
   255 }
   178 }
   256 
   179 
   257 -(void) didReceiveMemoryWarning {
   180 -(void) didReceiveMemoryWarning {
   258     if (self.popupMenu.view.superview == nil)
   181     if (self.popupMenu.view.superview == nil)
   259         self.popupMenu = nil;
   182         self.popupMenu = nil;
   267 
   190 
   268     MSG_MEMCLEAN();
   191     MSG_MEMCLEAN();
   269     [super didReceiveMemoryWarning];
   192     [super didReceiveMemoryWarning];
   270 }
   193 }
   271 
   194 
   272 -(void) viewDidUnload {
       
   273     // only objects initialized in viewDidLoad should be here
       
   274     if (IS_DUALHEAD())
       
   275         [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
       
   276     [[NSNotificationCenter defaultCenter] removeObserver:self];
       
   277     [NSObject cancelPreviousPerformRequestsWithTarget:self
       
   278                                              selector:@selector(unsetPreciseStatus)
       
   279                                                object:nil];
       
   280     dimTimer = nil;
       
   281     self.helpPage = nil;
       
   282     [self dismissPopover];
       
   283     self.popoverController = nil;
       
   284     self.amvc = nil;
       
   285     MSG_DIDUNLOAD();
       
   286     [super viewDidUnload];
       
   287 }
       
   288 
       
   289 -(void) dealloc {
   195 -(void) dealloc {
   290     [popupMenu release];
   196     [popupMenu release];
   291     [helpPage release];
   197     [helpPage release];
   292     [popoverController release];
   198     [popoverController release];
   293     [amvc release];
   199     [amvc release];
   294     // dimTimer is autoreleased
   200     // dimTimer is autoreleased
   295     [super dealloc];
   201     [super dealloc];
   296 }
   202 }
   297 
   203 
       
   204 -(void) numberOfScreensIncreased {
       
   205     if (self.initialScreenCount == 1) {
       
   206         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"New display detected"
       
   207                                                         message:NSLocalizedString(@"Hedgewars supports multi-monitor configurations, but the screen has to be connected before launching the game.",@"")
       
   208                                                        delegate:nil
       
   209                                               cancelButtonTitle:@"Ok"
       
   210                                               otherButtonTitles:nil];
       
   211         [alert show];
       
   212         [alert release];
       
   213         HW_pause();
       
   214     }
       
   215 }
       
   216 
       
   217 -(void) numberOfScreensDecreased {
       
   218     if (self.initialScreenCount == 2) {
       
   219         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Oh noes! Display disconnected"
       
   220                                                         message:NSLocalizedString(@"A monitor has been disconnected while playing and this has ended the match! You need to restart the game if you wish to use the second display again.",@"")
       
   221                                                        delegate:nil
       
   222                                               cancelButtonTitle:@"Ok"
       
   223                                               otherButtonTitles:nil];
       
   224         [alert show];
       
   225         [alert release];
       
   226         HW_terminate(NO);
       
   227     }
       
   228 }
       
   229 
   298 #pragma mark -
   230 #pragma mark -
   299 #pragma mark overlay user interaction
   231 #pragma mark overlay appearance
   300 // nice transition for dimming, should be called only by the timer himself
   232 // nice transition for dimming, should be called only by the timer himself
   301 -(void) dimOverlay {
   233 -(void) dimOverlay {
   302     if (isGameRunning()) {
   234     if (isGameRunning()) {
   303         [UIView beginAnimations:@"overlay dim" context:NULL];
   235         [UIView beginAnimations:@"overlay dim" context:NULL];
   304         [UIView setAnimationDuration:0.6];
   236         [UIView setAnimationDuration:0.6];
   311 -(void) activateOverlay {
   243 -(void) activateOverlay {
   312     self.view.alpha = 1;
   244     self.view.alpha = 1;
   313     doNotDim();
   245     doNotDim();
   314 }
   246 }
   315 
   247 
       
   248 -(void) removeOverlay {
       
   249     [self.popupMenu performSelectorOnMainThread:@selector(dismiss) withObject:nil waitUntilDone:YES];
       
   250     [self.popoverController performSelectorOnMainThread:@selector(dismissPopoverAnimated:) withObject:nil waitUntilDone:YES];
       
   251     [self.view performSelectorOnMainThread:@selector(removeFromSuperview) withObject:nil waitUntilDone:YES];
       
   252 }
       
   253 
       
   254 #pragma mark -
       
   255 #pragma mark overlay user interaction
   316 // dim the overlay when there's no more input for a certain amount of time
   256 // dim the overlay when there's no more input for a certain amount of time
   317 -(IBAction) buttonReleased:(id) sender {
   257 -(IBAction) buttonReleased:(id) sender {
   318     if (isGameRunning() == NO)
   258     if (isGameRunning() == NO)
   319         return;
   259         return;
   320 
   260 
   441         setGrenadeTime(theSegment.selectedSegmentIndex);
   381         setGrenadeTime(theSegment.selectedSegmentIndex);
   442     }
   382     }
   443 }
   383 }
   444 
   384 
   445 #pragma mark -
   385 #pragma mark -
   446 #pragma mark other menu
   386 #pragma mark in-game menu and help page
       
   387 -(void) showHelp:(id) sender {
       
   388     if (self.helpPage == nil) {
       
   389         NSString *xibName = (IS_IPAD() ? @"HelpPageInGameViewController-iPad" : @"HelpPageInGameViewController-iPhone");
       
   390         self.helpPage = [[HelpPageViewController alloc] initWithNibName:xibName bundle:nil];
       
   391     }
       
   392     self.helpPage.view.alpha = 0;
       
   393     [self.view addSubview:helpPage.view];
       
   394     [UIView beginAnimations:@"helpingame" context:NULL];
       
   395     self.helpPage.view.alpha = 1;
       
   396     [UIView commitAnimations];
       
   397     doNotDim();
       
   398 }
       
   399 
   447 // present a further check before closing game
   400 // present a further check before closing game
   448 -(void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger) buttonIndex {
   401 -(void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger) buttonIndex {
   449     if ([actionSheet cancelButtonIndex] != buttonIndex)
   402     if ([actionSheet cancelButtonIndex] != buttonIndex)
   450         HW_terminate(NO);
   403         HW_terminate(NO);
   451     else
   404     else