project_files/HedgewarsMobile/Classes/OverlayViewController.m
changeset 3546 ccf4854df294
parent 3535 9e78c1f3d8d8
child 3547 02875b1145b7
equal deleted inserted replaced
3545:b07ee704f35d 3546:ccf4854df294
     1 //
       
     2 //  overlayViewController.m
       
     3 //  HedgewarsMobile
       
     4 //
       
     5 //  Created by Vittorio on 16/03/10.
       
     6 //  Copyright 2010 __MyCompanyName__. All rights reserved.
       
     7 //
       
     8 
       
     9 #import "OverlayViewController.h"
       
    10 #import "SDL_uikitappdelegate.h"
       
    11 #import "PascalImports.h"
       
    12 #import "CGPointUtils.h"
       
    13 #import "SDL_mouse.h"
       
    14 #import "SDL_config_iphoneos.h"
       
    15 #import "PopoverMenuViewController.h"
       
    16 #import "CommodityFunctions.h"
       
    17 
       
    18 #define HIDING_TIME_DEFAULT [NSDate dateWithTimeIntervalSinceNow:2.7]
       
    19 #define HIDING_TIME_NEVER   [NSDate dateWithTimeIntervalSinceNow:10000]
       
    20 
       
    21 
       
    22 @implementation OverlayViewController
       
    23 @synthesize popoverController, popupMenu, writeChatTextField, spinningWheel;
       
    24 
       
    25 -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation {
       
    26 	return rotationManager(interfaceOrientation);
       
    27 }
       
    28 
       
    29 
       
    30 -(void) didReceiveMemoryWarning {
       
    31 	// Releases the view if it doesn't have a superview.
       
    32     [super didReceiveMemoryWarning];
       
    33 	// Release any cached data, images, etc that aren't in use.
       
    34     if (popupMenu.view.superview == nil) 
       
    35         popupMenu = nil;
       
    36 }
       
    37 
       
    38 -(void) didRotate:(NSNotification *)notification {	
       
    39     UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
       
    40     CGRect rect = [[UIScreen mainScreen] bounds];
       
    41     CGRect usefulRect = CGRectMake(0, 0, rect.size.width, rect.size.height);
       
    42     UIView *sdlView = [[[UIApplication sharedApplication] keyWindow] viewWithTag:12345];
       
    43     
       
    44     [UIView beginAnimations:@"rotation" context:NULL];
       
    45     [UIView setAnimationDuration:0.8f];
       
    46     [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
       
    47 	switch (orientation) {
       
    48         case UIDeviceOrientationLandscapeLeft:
       
    49             sdlView.transform = CGAffineTransformMakeRotation(degreesToRadian(0));
       
    50             self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
       
    51             [self chatDisappear];
       
    52             HW_setLandscape(YES);
       
    53             break;
       
    54         case UIDeviceOrientationLandscapeRight:
       
    55             sdlView.transform = CGAffineTransformMakeRotation(degreesToRadian(180));
       
    56             self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(-90));
       
    57             [self chatDisappear];
       
    58             HW_setLandscape(YES);
       
    59             break;
       
    60         case UIDeviceOrientationPortrait:
       
    61             if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
       
    62                 sdlView.transform = CGAffineTransformMakeRotation(degreesToRadian(270));
       
    63                 self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(0));
       
    64                 [self chatAppear];
       
    65                 HW_setLandscape(NO);
       
    66             }
       
    67             break;
       
    68         case UIDeviceOrientationPortraitUpsideDown:
       
    69             if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
       
    70                 sdlView.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
       
    71                 self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(180));
       
    72                 [self chatAppear];
       
    73                 HW_setLandscape(NO);
       
    74             }
       
    75             break;
       
    76         default:
       
    77             break;
       
    78     }
       
    79     self.view.frame = usefulRect;
       
    80     //sdlView.frame = usefulRect;
       
    81     [UIView commitAnimations];
       
    82 }
       
    83 
       
    84 -(void) chatAppear {
       
    85     if (writeChatTextField == nil) {
       
    86         writeChatTextField = [[UITextField alloc] initWithFrame:CGRectMake(0, 100, 768, [UIFont systemFontSize]+8)];
       
    87         writeChatTextField.textColor = [UIColor whiteColor];
       
    88         writeChatTextField.backgroundColor = [UIColor blueColor];
       
    89         writeChatTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
       
    90         writeChatTextField.autocorrectionType = UITextAutocorrectionTypeNo;
       
    91         writeChatTextField.enablesReturnKeyAutomatically = NO;
       
    92         writeChatTextField.keyboardAppearance = UIKeyboardAppearanceDefault;
       
    93         writeChatTextField.keyboardType = UIKeyboardTypeDefault;
       
    94         writeChatTextField.returnKeyType = UIReturnKeyDefault;
       
    95         writeChatTextField.secureTextEntry = NO;	
       
    96         [self.view addSubview:writeChatTextField];
       
    97     }
       
    98     writeChatTextField.alpha = 1;
       
    99     [self activateOverlay];
       
   100     [dimTimer setFireDate:HIDING_TIME_NEVER];
       
   101 }
       
   102 
       
   103 -(void) chatDisappear {
       
   104     writeChatTextField.alpha = 0;
       
   105     [writeChatTextField resignFirstResponder];
       
   106     [dimTimer setFireDate:HIDING_TIME_DEFAULT];
       
   107 }
       
   108 
       
   109 #pragma mark -
       
   110 #pragma mark View Management
       
   111 -(void) viewDidLoad {
       
   112     isPopoverVisible = NO;
       
   113     singleton = self.spinningWheel;
       
   114     canDim = NO;
       
   115     self.view.alpha = 0;
       
   116     self.view.center = CGPointMake(self.view.frame.size.height/2.0, self.view.frame.size.width/2.0);
       
   117     
       
   118     
       
   119     dimTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:6]
       
   120                                         interval:1000
       
   121                                           target:self
       
   122                                         selector:@selector(dimOverlay)
       
   123                                         userInfo:nil
       
   124                                          repeats:YES];
       
   125     
       
   126     // add timer too runloop, otherwise it doesn't work
       
   127     [[NSRunLoop currentRunLoop] addTimer:dimTimer forMode:NSDefaultRunLoopMode];
       
   128     
       
   129     // listen for dismissal of the popover (see below)
       
   130     [[NSNotificationCenter defaultCenter] addObserver:self
       
   131                                              selector:@selector(dismissPopover)
       
   132                                                  name:@"dismissPopover"
       
   133                                                object:nil];
       
   134     
       
   135     [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];	
       
   136     [[NSNotificationCenter defaultCenter] addObserver:self
       
   137                                              selector:@selector(didRotate:)
       
   138                                                  name:@"UIDeviceOrientationDidChangeNotification"
       
   139                                                object:nil];
       
   140 
       
   141     //self.view.transform = CGAffineTransformRotate(self.view.transform, (M_PI/2.0)); 
       
   142 	[UIView beginAnimations:@"showing overlay" context:NULL];
       
   143 	[UIView setAnimationDuration:1];
       
   144 	self.view.alpha = 1;
       
   145 	[UIView commitAnimations];
       
   146 }
       
   147 
       
   148 -(void) viewDidUnload {
       
   149     self.writeChatTextField = nil;
       
   150     self.popoverController = nil;
       
   151     self.popupMenu = nil;
       
   152     self.spinningWheel = nil;
       
   153     [super viewDidUnload];
       
   154     MSG_DIDUNLOAD();
       
   155 }
       
   156 
       
   157 -(void) dealloc {
       
   158 	[dimTimer invalidate];
       
   159     [writeChatTextField release];
       
   160     [popupMenu release];
       
   161     [popoverController release];
       
   162     // dimTimer is autoreleased
       
   163     [spinningWheel release];
       
   164     [super dealloc];
       
   165 }
       
   166 
       
   167 #pragma mark -
       
   168 #pragma mark Overlay actions and members
       
   169 // dim the overlay when there's no more input for a certain amount of time
       
   170 -(IBAction) buttonReleased:(id) sender {
       
   171 	HW_allKeysUp();
       
   172     [dimTimer setFireDate:HIDING_TIME_DEFAULT];
       
   173 }
       
   174 
       
   175 // nice transition for dimming, should be called only by the timer himself
       
   176 -(void) dimOverlay {
       
   177     if (canDim) {
       
   178         [UIView beginAnimations:@"overlay dim" context:NULL];
       
   179         [UIView setAnimationDuration:0.6];
       
   180         self.view.alpha = 0.2;
       
   181         [UIView commitAnimations];
       
   182     }
       
   183 }
       
   184 
       
   185 // set the overlay visible and put off the timer for enough time
       
   186 -(void) activateOverlay {
       
   187     self.view.alpha = 1;
       
   188     [dimTimer setFireDate:HIDING_TIME_NEVER];
       
   189 }
       
   190 
       
   191 // issue certain action based on the tag of the button 
       
   192 -(IBAction) buttonPressed:(id) sender {
       
   193     [self activateOverlay];
       
   194     if (isPopoverVisible) {
       
   195         [self dismissPopover];
       
   196     }
       
   197     UIButton *theButton = (UIButton *)sender;
       
   198     
       
   199     switch (theButton.tag) {
       
   200         case 0:
       
   201             HW_walkLeft();
       
   202             break;
       
   203         case 1:
       
   204             HW_walkRight();
       
   205             break;
       
   206         case 2:
       
   207             HW_aimUp();
       
   208             break;
       
   209         case 3:
       
   210             HW_aimDown();
       
   211             break;
       
   212         case 4:
       
   213             HW_shoot();
       
   214             break;
       
   215         case 5:
       
   216             HW_jump();
       
   217             break;
       
   218         case 6:
       
   219             HW_backjump();
       
   220             break;
       
   221         case 7:
       
   222             HW_tab();
       
   223             break;
       
   224         case 10:
       
   225             [self showPopover];
       
   226             break;
       
   227         default:
       
   228             NSLog(@"Nope");
       
   229             break;
       
   230     }
       
   231 }
       
   232 
       
   233 // present a further check before closing game
       
   234 -(void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger) buttonIndex {
       
   235 	if ([actionSheet cancelButtonIndex] != buttonIndex)
       
   236 	    HW_terminate(NO);
       
   237 	else
       
   238         HW_pause();		
       
   239 }
       
   240 
       
   241 // show up a popover containing a popupMenuViewController; we hook it with setPopoverContentSize
       
   242 // on iphone instead just use the tableViewController directly (and implement manually all animations)
       
   243 -(IBAction) showPopover{
       
   244     isPopoverVisible = YES;
       
   245     CGRect anchorForPopover;
       
   246 
       
   247     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
       
   248         if (popupMenu == nil) 
       
   249             popupMenu = [[PopoverMenuViewController alloc] initWithStyle:UITableViewStylePlain];
       
   250         if (popoverController == nil) {
       
   251             popoverController = [[UIPopoverController alloc] initWithContentViewController:popupMenu];
       
   252             [popoverController setPopoverContentSize:CGSizeMake(220, 170) animated:YES];
       
   253             [popoverController setPassthroughViews:[NSArray arrayWithObject:self.view]];
       
   254         }
       
   255         
       
   256         if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]))
       
   257             anchorForPopover = CGRectMake(960, 0, 220, 32);
       
   258         else
       
   259             anchorForPopover = CGRectMake(736, 0, 220, 32);
       
   260         
       
   261         [popoverController presentPopoverFromRect:anchorForPopover
       
   262                                            inView:self.view
       
   263                          permittedArrowDirections:UIPopoverArrowDirectionUp
       
   264                                          animated:YES];
       
   265     } else {
       
   266         if (popupMenu == nil) {
       
   267             popupMenu = [[PopoverMenuViewController alloc] initWithStyle:UITableViewStyleGrouped];
       
   268             popupMenu.view.backgroundColor = [UIColor clearColor];
       
   269             popupMenu.view.frame = CGRectMake(480, 0, 200, 170);
       
   270         }
       
   271         [self.view addSubview:popupMenu.view];
       
   272         
       
   273         [UIView beginAnimations:@"showing popover" context:NULL];
       
   274         [UIView setAnimationDuration:0.35];
       
   275         popupMenu.view.frame = CGRectMake(280, 0, 200, 170);
       
   276         [UIView commitAnimations];
       
   277     }
       
   278     popupMenu.tableView.scrollEnabled = NO;
       
   279 }
       
   280 
       
   281 // on ipad just dismiss it, on iphone transtion to the right
       
   282 -(void) dismissPopover {
       
   283     if (YES == isPopoverVisible) {
       
   284         isPopoverVisible = NO;
       
   285         
       
   286         if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
       
   287             [popoverController dismissPopoverAnimated:YES];
       
   288         } else {
       
   289             [UIView beginAnimations:@"hiding popover" context:NULL];
       
   290             [UIView setAnimationDuration:0.35];
       
   291             popupMenu.view.frame = CGRectMake(480, 0, 200, 170);
       
   292             [UIView commitAnimations];
       
   293         
       
   294             [popupMenu.view performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:0.35];
       
   295         }
       
   296         [self buttonReleased:nil];
       
   297     }
       
   298 }
       
   299 
       
   300 -(void) textFieldDoneEditing:(id) sender{
       
   301     [sender resignFirstResponder];
       
   302 }
       
   303 
       
   304 // this function is called by pascal FinishProgress and removes the spinning wheel when loading is done
       
   305 void spinningWheelDone (void) {
       
   306     [UIView beginAnimations:@"hiding spinning wheel" context:NULL];
       
   307     [UIView setAnimationDuration:0.7];
       
   308     singleton.alpha = 0;
       
   309     [UIView commitAnimations];
       
   310     [singleton performSelector:@selector(stopAnimating) withObject:nil afterDelay:0.7];
       
   311     canDim = YES;
       
   312 }
       
   313 
       
   314 #pragma mark -
       
   315 #pragma mark Custom touch event handling
       
   316 -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
       
   317 	NSArray *twoTouches;
       
   318 	UITouch *touch = [touches anyObject];
       
   319     
       
   320     if (isPopoverVisible) {
       
   321         [self dismissPopover];
       
   322     }
       
   323     if (writeChatTextField) {
       
   324         [self.writeChatTextField resignFirstResponder];
       
   325         [dimTimer setFireDate:HIDING_TIME_DEFAULT];
       
   326     }
       
   327     
       
   328     gestureStartPoint = [touch locationInView:self.view];
       
   329         
       
   330 	switch ([touches count]) {
       
   331 		/*case 1:
       
   332 			initialDistanceForPinching = 0;
       
   333 			switch ([touch tapCount]) {
       
   334 				case 1:
       
   335 					NSLog(@"X:%d Y:%d", (int)gestureStartPoint.x, (int)gestureStartPoint.y );
       
   336 					//SDL_WarpMouseInWindow([SDLUIKitDelegate sharedAppDelegate].window, 
       
   337 					//		      (int)gestureStartPoint.y, width - (int)gestureStartPoint.x);
       
   338 					//HW_click();
       
   339 					break;
       
   340 				case 2:
       
   341 					HW_ammoMenu();
       
   342 					break;
       
   343 				default:
       
   344 					break;
       
   345 			}
       
   346 			break;*/
       
   347 		case 2:
       
   348 			if (2 == [touch tapCount]) {
       
   349 				HW_zoomReset();
       
   350 			}
       
   351 			
       
   352 			// pinching
       
   353             gestureStartPoint = CGPointMake(0, 0);
       
   354 			twoTouches = [touches allObjects];
       
   355 			UITouch *first = [twoTouches objectAtIndex:0];
       
   356 			UITouch *second = [twoTouches objectAtIndex:1];
       
   357 			initialDistanceForPinching = distanceBetweenPoints([first locationInView:self.view], [second locationInView:self.view]);
       
   358 			break;
       
   359 		default:
       
   360 			break;
       
   361 	}
       
   362 
       
   363 }
       
   364 
       
   365 -(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
       
   366     gestureStartPoint = CGPointMake(0, 0);
       
   367 	initialDistanceForPinching = 0;
       
   368 	//HW_allKeysUp();
       
   369 }
       
   370 
       
   371 -(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
       
   372 	// this can happen if the user puts more than 5 touches on the screen at once, or perhaps in other circumstances
       
   373 	[self touchesEnded:touches withEvent:event];
       
   374 }
       
   375 
       
   376 -(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
       
   377     CGFloat minimumGestureLength;
       
   378     int logCoeff;
       
   379     
       
   380     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
       
   381         minimumGestureLength = 5.0f;
       
   382         logCoeff = 19;
       
   383     } else {
       
   384         minimumGestureLength = 3.0f;
       
   385         logCoeff = 3;
       
   386     }
       
   387     
       
   388 	NSArray *twoTouches;
       
   389 	CGPoint currentPosition;
       
   390 	UITouch *touch = [touches anyObject];
       
   391 
       
   392 	switch ([touches count]) {
       
   393 		/*case 1:
       
   394 			currentPosition = [touch locationInView:self.view];
       
   395 			// panning
       
   396 			CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x);
       
   397 			CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y);
       
   398 			
       
   399             // the two ifs are not mutually exclusive
       
   400             if (deltaX >= minimumGestureLength) {
       
   401                 DLog(@"deltaX: %f deltaY: %f", deltaX, deltaY);
       
   402                 if (currentPosition.x > gestureStartPoint.x) {
       
   403                     HW_cursorLeft(logCoeff*log(deltaX));
       
   404                 } else {
       
   405                     HW_cursorRight(logCoeff*log(deltaX));
       
   406                 }
       
   407 
       
   408             } 
       
   409             if (deltaY >= minimumGestureLength) {
       
   410                 DLog(@"deltaX: %f deltaY: %f", deltaX, deltaY);
       
   411                 if (currentPosition.y < gestureStartPoint.y) {
       
   412                     HW_cursorDown(logCoeff*log(deltaY));
       
   413                 } else {
       
   414                     HW_cursorUp(logCoeff*log(deltaY));
       
   415                 }            
       
   416             }
       
   417 
       
   418 			break;*/
       
   419 		case 2:
       
   420 			twoTouches = [touches allObjects];
       
   421 			UITouch *first = [twoTouches objectAtIndex:0];
       
   422 			UITouch *second = [twoTouches objectAtIndex:1];
       
   423 			CGFloat currentDistanceOfPinching = distanceBetweenPoints([first locationInView:self.view], [second locationInView:self.view]);
       
   424 			const int pinchDelta = 40;
       
   425             
       
   426 			if (0 != initialDistanceForPinching) {
       
   427                 if (currentDistanceOfPinching - initialDistanceForPinching > pinchDelta) {
       
   428                     HW_zoomIn();
       
   429                     initialDistanceForPinching = currentDistanceOfPinching;
       
   430                 }
       
   431                 else if (initialDistanceForPinching - currentDistanceOfPinching > pinchDelta) {
       
   432                     HW_zoomOut();
       
   433                     initialDistanceForPinching = currentDistanceOfPinching;
       
   434                 }
       
   435             } else 
       
   436                 initialDistanceForPinching = currentDistanceOfPinching;
       
   437             
       
   438 			break;
       
   439 		default:
       
   440 			break;
       
   441 	}
       
   442 }
       
   443 
       
   444 
       
   445 @end