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