project_files/HedgewarsMobile/Classes/OverlayViewController.m
changeset 7110 c91d33837b0d
parent 7020 846cea23aea2
parent 7107 1982e702ed2f
child 7123 9fe1c4091dd1
equal deleted inserted replaced
7020:846cea23aea2 7110:c91d33837b0d
     1 /*
       
     2  * Hedgewars-iOS, a Hedgewars port for iOS devices
       
     3  * Copyright (c) 2009-2012 Vittorio Giovara <vittorio.giovara@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
       
    17  */
       
    18 
       
    19 
       
    20 #import "OverlayViewController.h"
       
    21 #import "InGameMenuViewController.h"
       
    22 #import "HelpPageInGameViewController.h"
       
    23 #import "CGPointUtils.h"
       
    24 
       
    25 
       
    26 #define HIDING_TIME_DEFAULT [NSDate dateWithTimeIntervalSinceNow:2.7]
       
    27 #define HIDING_TIME_NEVER   [NSDate dateWithTimeIntervalSinceNow:10000]
       
    28 #define doDim()             [dimTimer setFireDate:HIDING_TIME_DEFAULT]
       
    29 #define doNotDim()          [dimTimer setFireDate:HIDING_TIME_NEVER]
       
    30 
       
    31 @implementation OverlayViewController
       
    32 @synthesize popoverController, popupMenu, helpPage, loadingIndicator, confirmButton, grenadeTimeSegment;
       
    33 
       
    34 #pragma mark -
       
    35 #pragma mark rotation
       
    36 -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation {
       
    37     return rotationManager(interfaceOrientation);
       
    38 }
       
    39 
       
    40 #pragma mark -
       
    41 #pragma mark View Management
       
    42 -(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
       
    43     if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
       
    44         isAttacking = NO;
       
    45         isPopoverVisible = NO;
       
    46         loadingIndicator = nil;
       
    47     }
       
    48     return self;
       
    49 }
       
    50 
       
    51 -(void) viewDidLoad {
       
    52     // fill all the screen available as sdlview disables autoresizing
       
    53     self.view.frame = [[UIScreen mainScreen] safeBounds];
       
    54     // the timer used to dim the overlay
       
    55     dimTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:6]
       
    56                                         interval:1000
       
    57                                           target:self
       
    58                                         selector:@selector(dimOverlay)
       
    59                                         userInfo:nil
       
    60                                          repeats:YES];
       
    61     // add timer to runloop, otherwise it doesn't work
       
    62     [[NSRunLoop currentRunLoop] addTimer:dimTimer forMode:NSDefaultRunLoopMode];
       
    63 
       
    64     // display the help page, required by the popover on ipad
       
    65     [[NSNotificationCenter defaultCenter] addObserver:self
       
    66                                              selector:@selector(showHelp:)
       
    67                                                  name:@"show help ingame"
       
    68                                                object:nil];
       
    69     
       
    70     // present the overlay
       
    71     self.view.alpha = 0;
       
    72     [UIView beginAnimations:@"showing overlay" context:NULL];
       
    73     [UIView setAnimationDuration:2];
       
    74     self.view.alpha = 1;
       
    75     [UIView commitAnimations];
       
    76 }
       
    77 
       
    78 -(void) viewDidUnload {
       
    79     [[NSNotificationCenter defaultCenter] removeObserver:self];
       
    80 
       
    81     [NSObject cancelPreviousPerformRequestsWithTarget:self
       
    82                                              selector:@selector(unsetPreciseStatus)
       
    83                                                object:nil];
       
    84 
       
    85     // only objects initialized in viewDidLoad should be here
       
    86     dimTimer = nil;
       
    87     self.helpPage = nil;
       
    88     [self dismissPopover];
       
    89     self.popoverController = nil;
       
    90     self.loadingIndicator = nil;
       
    91     MSG_DIDUNLOAD();
       
    92     [super viewDidUnload];
       
    93 }
       
    94 
       
    95 -(void) didReceiveMemoryWarning {
       
    96     if (self.popupMenu.view.superview == nil)
       
    97         self.popupMenu = nil;
       
    98     if (self.helpPage.view.superview == nil)
       
    99         self.helpPage = nil;
       
   100     if (self.loadingIndicator.superview == nil)
       
   101         self.loadingIndicator = nil;
       
   102     if (self.confirmButton.superview == nil)
       
   103         self.confirmButton = nil;
       
   104     if (self.grenadeTimeSegment.superview == nil)
       
   105         self.grenadeTimeSegment = nil;
       
   106     if (IS_IPAD())
       
   107         if (((UIPopoverController *)self.popoverController).contentViewController.view.superview == nil)
       
   108             self.popoverController = nil;
       
   109 
       
   110     MSG_MEMCLEAN();
       
   111     [super didReceiveMemoryWarning];
       
   112 }
       
   113 
       
   114 -(void) dealloc {
       
   115     releaseAndNil(popupMenu);
       
   116     releaseAndNil(helpPage);
       
   117     releaseAndNil(popoverController);
       
   118     releaseAndNil(loadingIndicator);
       
   119     releaseAndNil(confirmButton);
       
   120     releaseAndNil(grenadeTimeSegment);
       
   121     // dimTimer is autoreleased
       
   122     [super dealloc];
       
   123 }
       
   124 
       
   125 #pragma mark -
       
   126 #pragma mark overlay appearance
       
   127 // nice transition for dimming, should be called only by the timer himself
       
   128 -(void) dimOverlay {
       
   129     if ([HWUtils isGameRunning]) {
       
   130         [UIView beginAnimations:@"overlay dim" context:NULL];
       
   131         [UIView setAnimationDuration:0.6];
       
   132         self.view.alpha = 0.2;
       
   133         [UIView commitAnimations];
       
   134     }
       
   135 }
       
   136 
       
   137 // set the overlay visible and put off the timer for enough time
       
   138 -(void) activateOverlay {
       
   139     self.view.alpha = 1;
       
   140     doNotDim();
       
   141 }
       
   142 
       
   143 -(void) clearOverlay {
       
   144     [UIView beginAnimations:@"remove button" context:NULL];
       
   145     [UIView setAnimationDuration:ANIMATION_DURATION];
       
   146     self.confirmButton.alpha = 0;
       
   147     self.grenadeTimeSegment.alpha = 0;
       
   148     [UIView commitAnimations];
       
   149 
       
   150     if (self.confirmButton)
       
   151         [self.confirmButton performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:ANIMATION_DURATION];
       
   152     if (self.grenadeTimeSegment)
       
   153         [self.grenadeTimeSegment performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:ANIMATION_DURATION];
       
   154 }
       
   155 
       
   156 #pragma mark -
       
   157 #pragma mark overlay user interaction
       
   158 // dim the overlay when there's no more input for a certain amount of time
       
   159 -(IBAction) buttonReleased:(id) sender {
       
   160     if ([HWUtils isGameRunning] == NO)
       
   161         return;
       
   162 
       
   163     UIButton *theButton = (UIButton *)sender;
       
   164 
       
   165     switch (theButton.tag) {
       
   166         case 0:
       
   167         case 1:
       
   168         case 2:
       
   169         case 3:
       
   170             [NSObject cancelPreviousPerformRequestsWithTarget:self
       
   171                                                      selector:@selector(unsetPreciseStatus)
       
   172                                                        object:nil];
       
   173             HW_walkingKeysUp();
       
   174             break;
       
   175         case 4:
       
   176         case 5:
       
   177         case 6:
       
   178             HW_otherKeysUp();
       
   179             break;
       
   180         default:
       
   181             DLog(@"Nope");
       
   182             break;
       
   183     }
       
   184 
       
   185     isAttacking = NO;
       
   186     doDim();
       
   187 }
       
   188 
       
   189 // issue certain action based on the tag of the button
       
   190 -(IBAction) buttonPressed:(id) sender {
       
   191     [self activateOverlay];
       
   192     
       
   193     if ([HWUtils isGameRunning] == NO)
       
   194         return;
       
   195     
       
   196     if (isPopoverVisible)
       
   197         [self dismissPopover];
       
   198     
       
   199     UIButton *theButton = (UIButton *)sender;
       
   200     switch (theButton.tag) {
       
   201         case 0:
       
   202             if (isAttacking == NO)
       
   203                 HW_walkLeft();
       
   204             break;
       
   205         case 1:
       
   206             if (isAttacking == NO)
       
   207                 HW_walkRight();
       
   208             break;
       
   209         case 2:
       
   210             [self performSelector:@selector(unsetPreciseStatus) withObject:nil afterDelay:0.8];
       
   211             HW_preciseSet(!HW_isWeaponRope());
       
   212             HW_aimUp();
       
   213             break;
       
   214         case 3:
       
   215             [self performSelector:@selector(unsetPreciseStatus) withObject:nil afterDelay:0.8];
       
   216             HW_preciseSet(!HW_isWeaponRope());
       
   217             HW_aimDown();
       
   218             break;
       
   219         case 4:
       
   220             HW_shoot();
       
   221             isAttacking = YES;
       
   222             break;
       
   223         case 5:
       
   224             HW_jump();
       
   225             break;
       
   226         case 6:
       
   227             HW_backjump();
       
   228             break;
       
   229         case 10:
       
   230             [[AudioManagerController mainManager] playClickSound];
       
   231             HW_pause();
       
   232             [self clearOverlay];
       
   233             [self showPopover];
       
   234             break;
       
   235         case 11:
       
   236             [[AudioManagerController mainManager] playClickSound];
       
   237             [self clearOverlay];
       
   238             HW_ammoMenu();
       
   239             break;
       
   240         default:
       
   241             DLog(@"Nope");
       
   242             break;
       
   243     }
       
   244 }
       
   245 
       
   246 -(void) unsetPreciseStatus {
       
   247     HW_preciseSet(NO);
       
   248 }
       
   249 
       
   250 -(void) sendHWClick {
       
   251     [self clearOverlay];
       
   252     HW_click();
       
   253     doDim();
       
   254 }
       
   255 
       
   256 -(void) setGrenadeTime:(id) sender {
       
   257     UISegmentedControl *theSegment = (UISegmentedControl *)sender;
       
   258     NSInteger timeIndex = theSegment.selectedSegmentIndex + 1;
       
   259     if (HW_getGrenadeTime() != timeIndex)
       
   260         HW_setGrenadeTime(timeIndex);
       
   261 }
       
   262 
       
   263 #pragma mark -
       
   264 #pragma mark in-game menu and help page
       
   265 -(void) showHelp:(id) sender {
       
   266     if (self.helpPage == nil) {
       
   267         NSString *xibName = (IS_IPAD() ? @"HelpPageInGameViewController-iPad" : @"HelpPageInGameViewController-iPhone");
       
   268         self.helpPage = [[HelpPageInGameViewController alloc] initWithNibName:xibName bundle:nil];
       
   269     }
       
   270     self.helpPage.view.alpha = 0;
       
   271     [self.view addSubview:helpPage.view];
       
   272     [UIView beginAnimations:@"helpingame" context:NULL];
       
   273     self.helpPage.view.alpha = 1;
       
   274     [UIView commitAnimations];
       
   275     doNotDim();
       
   276 }
       
   277 
       
   278 // show up a popover containing a popupMenuViewController; we hook it with setPopoverContentSize
       
   279 // on iphone instead just use the tableViewController directly (and implement manually all animations)
       
   280 -(IBAction) showPopover{
       
   281     CGRect screen = [[UIScreen mainScreen] safeBounds];
       
   282     isPopoverVisible = YES;
       
   283 
       
   284     if (IS_IPAD()) {
       
   285         if (self.popupMenu == nil)
       
   286             self.popupMenu = [[InGameMenuViewController alloc] initWithStyle:UITableViewStylePlain];
       
   287         if (self.popoverController == nil) {
       
   288             self.popoverController = [[UIPopoverController alloc] initWithContentViewController:self.popupMenu];
       
   289             [self.popoverController setPopoverContentSize:CGSizeMake(220, 200) animated:YES];
       
   290             [self.popoverController setPassthroughViews:[NSArray arrayWithObject:self.view]];
       
   291         }
       
   292 
       
   293         [self.popoverController presentPopoverFromRect:CGRectMake(screen.size.width / 2, screen.size.height / 2, 1, 1)
       
   294                                            inView:self.view
       
   295                          permittedArrowDirections:UIPopoverArrowDirectionAny
       
   296                                          animated:YES];
       
   297     } else {
       
   298         if (self.popupMenu == nil)
       
   299             self.popupMenu = [[InGameMenuViewController alloc] initWithStyle:UITableViewStyleGrouped];
       
   300 
       
   301         [self.view addSubview:popupMenu.view];
       
   302         [self.popupMenu present];
       
   303     }
       
   304     self.popupMenu.tableView.scrollEnabled = NO;
       
   305 }
       
   306 
       
   307 // on ipad just dismiss it, on iphone transtion to the right
       
   308 -(void) dismissPopover {
       
   309     if (YES == isPopoverVisible) {
       
   310         isPopoverVisible = NO;
       
   311         if (HW_isPaused())
       
   312             HW_pauseToggle();
       
   313 
       
   314         [self.popupMenu dismiss];
       
   315         if (IS_IPAD())
       
   316             [self.popoverController dismissPopoverAnimated:YES];
       
   317 
       
   318         [self buttonReleased:nil];
       
   319     }
       
   320 }
       
   321 
       
   322 #pragma mark -
       
   323 #pragma mark Custom touch event handling
       
   324 -(BOOL) shouldIgnoreTouch:(NSSet *)allTouches {
       
   325     if ([HWUtils isGameRunning] == NO)
       
   326         return YES;
       
   327 
       
   328     // ignore activity near the dpad and buttons
       
   329     CGPoint touchPoint = [[[allTouches allObjects] objectAtIndex:0] locationInView:self.view];
       
   330     CGSize screen = [[UIScreen mainScreen] safeBounds].size;
       
   331 
       
   332     if ((touchPoint.x < 160 && touchPoint.y > screen.height - 155 ) ||
       
   333         (touchPoint.x > screen.width - 135 && touchPoint.y > screen.height - 140))
       
   334         return YES;
       
   335     return NO;
       
   336 }
       
   337 
       
   338 -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
       
   339     NSSet *allTouches = [event allTouches];
       
   340     UITouch *first, *second;
       
   341 
       
   342     if ([self shouldIgnoreTouch:allTouches] == YES)
       
   343         return;
       
   344 
       
   345     // hide in-game menu
       
   346     if (isPopoverVisible)
       
   347         [self dismissPopover];
       
   348 
       
   349     // reset default dimming
       
   350     doDim();
       
   351 
       
   352     HW_setPianoSound([allTouches count]);
       
   353 
       
   354     switch ([allTouches count]) {
       
   355         case 1:
       
   356             startingPoint = [[[allTouches allObjects] objectAtIndex:0] locationInView:self.view];
       
   357             if (2 == [[[allTouches allObjects] objectAtIndex:0] tapCount])
       
   358                 HW_zoomReset();
       
   359             break;
       
   360         case 2:
       
   361             if (2 == [[[allTouches allObjects] objectAtIndex:0] tapCount])
       
   362                 HW_screenshot();
       
   363             else {
       
   364                 // pinching
       
   365                 first = [[allTouches allObjects] objectAtIndex:0];
       
   366                 second = [[allTouches allObjects] objectAtIndex:1];
       
   367                 initialDistanceForPinching = distanceBetweenPoints([first locationInView:self.view], [second locationInView:self.view]);
       
   368             }
       
   369             break;
       
   370         default:
       
   371             break;
       
   372     }
       
   373 }
       
   374 
       
   375 -(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
       
   376     NSSet *allTouches = [event allTouches];
       
   377     if ([self shouldIgnoreTouch:allTouches] == YES)
       
   378         return;
       
   379 
       
   380     CGRect screen = [[UIScreen mainScreen] safeBounds];
       
   381     CGPoint currentPosition = [[[allTouches allObjects] objectAtIndex:0] locationInView:self.view];
       
   382 
       
   383     switch ([allTouches count]) {
       
   384         case 1:
       
   385             // if we're in the menu we just click in the point
       
   386             if (HW_isAmmoMenuOpen()) {
       
   387                 HW_setCursor(HWXZ(currentPosition.x),HWYZ(currentPosition.y));
       
   388                 // this click doesn't need any wrapping because the ammoMenu already limits the cursor
       
   389                 HW_click();
       
   390             } else
       
   391                 // if weapon requires a further click, ask for tapping again
       
   392                 if (HW_isWeaponRequiringClick()) {
       
   393                     // here don't have to wrap thanks to isCursorVisible magic
       
   394                     HW_setCursor(HWX(currentPosition.x), HWY(currentPosition.y));
       
   395 
       
   396                     // draw the button at the last touched point (which is the current position)
       
   397                     if (self.confirmButton == nil) {
       
   398                         UIButton *tapAgain = [UIButton buttonWithType:UIButtonTypeRoundedRect];
       
   399                         [tapAgain addTarget:self action:@selector(sendHWClick) forControlEvents:UIControlEventTouchUpInside];
       
   400                         [tapAgain setTitle:NSLocalizedString(@"Set!",@"on the overlay") forState:UIControlStateNormal];
       
   401                         self.confirmButton = tapAgain;
       
   402                     }
       
   403                     self.confirmButton.alpha = 0;
       
   404                     self.confirmButton.frame = CGRectMake(currentPosition.x - 75, currentPosition.y + 25, 150, 40);
       
   405                     [self.view addSubview:self.confirmButton];
       
   406 
       
   407                     // animation ftw!
       
   408                     [UIView beginAnimations:@"inserting button" context:NULL];
       
   409                     [UIView setAnimationDuration:ANIMATION_DURATION];
       
   410                     self.confirmButton.alpha = 1;
       
   411                     [UIView commitAnimations];
       
   412 
       
   413                     // keep the overlay active, or the button will fade
       
   414                     [self activateOverlay];
       
   415                     doNotDim();
       
   416                 } else
       
   417                     if (HW_isWeaponTimerable()) {
       
   418                         if (self.grenadeTimeSegment.superview != nil) {
       
   419                             [UIView beginAnimations:@"removing segmented control" context:NULL];
       
   420                             [UIView setAnimationDuration:ANIMATION_DURATION];
       
   421                             self.grenadeTimeSegment.alpha = 0;
       
   422                             [UIView commitAnimations];
       
   423 
       
   424                             [self.grenadeTimeSegment performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:ANIMATION_DURATION];
       
   425                         } else {
       
   426                             if (self.grenadeTimeSegment == nil) {
       
   427                                 NSArray *items = [[NSArray alloc] initWithObjects:@"1",@"2",@"3",@"4",@"5",nil];
       
   428                                 UISegmentedControl *grenadeSegment = [[UISegmentedControl alloc] initWithItems:items];
       
   429                                 [items release];
       
   430                                 [grenadeSegment addTarget:self action:@selector(setGrenadeTime:) forControlEvents:UIControlEventValueChanged];
       
   431                                 self.grenadeTimeSegment = grenadeSegment;
       
   432                                 [grenadeSegment release];
       
   433                             }
       
   434                             self.grenadeTimeSegment.frame = CGRectMake(screen.size.width / 2 - 125, screen.size.height, 250, 50);
       
   435                             self.grenadeTimeSegment.selectedSegmentIndex = HW_getGrenadeTime() - 1;
       
   436                             self.grenadeTimeSegment.alpha = 1;
       
   437                             self.grenadeTimeSegment.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |
       
   438                                                                        UIViewAutoresizingFlexibleRightMargin |
       
   439                                                                        UIViewAutoresizingFlexibleTopMargin;
       
   440                             [self.view addSubview:self.grenadeTimeSegment];
       
   441 
       
   442                             [UIView beginAnimations:@"inserting segmented control" context:NULL];
       
   443                             [UIView setAnimationDuration:ANIMATION_DURATION];
       
   444                             [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
       
   445                             self.grenadeTimeSegment.frame = CGRectMake(screen.size.width / 2 - 125, screen.size.height - 100, 250, 50);
       
   446                             [UIView commitAnimations];
       
   447 
       
   448                             [self activateOverlay];
       
   449                             doNotDim();
       
   450                         }
       
   451                     } else
       
   452                         if (HW_isWeaponSwitch())
       
   453                             HW_tab();
       
   454             break;
       
   455         case 2:
       
   456             HW_allKeysUp();
       
   457             break;
       
   458         default:
       
   459             break;
       
   460     }
       
   461 
       
   462     initialDistanceForPinching = 0;
       
   463 }
       
   464 
       
   465 -(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
       
   466     [self touchesEnded:touches withEvent:event];
       
   467 }
       
   468 
       
   469 -(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
       
   470     NSSet *allTouches = [event allTouches];
       
   471     if ([self shouldIgnoreTouch:allTouches] == YES)
       
   472         return;
       
   473 
       
   474     CGRect screen = [[UIScreen mainScreen] safeBounds];
       
   475     int x, y, dx, dy;
       
   476     UITouch *touch, *first, *second;
       
   477 
       
   478     switch ([allTouches count]) {
       
   479         case 1:
       
   480             touch = [[allTouches allObjects] objectAtIndex:0];
       
   481             CGPoint currentPosition = [touch locationInView:self.view];
       
   482 
       
   483             if (HW_isAmmoMenuOpen()) {
       
   484                 // no zoom consideration for this
       
   485                 HW_setCursor(HWXZ(currentPosition.x), HWYZ(currentPosition.y));
       
   486             } else
       
   487                 if (HW_isWeaponRequiringClick()) {
       
   488                     // moves the cursor around wrt zoom
       
   489                     HW_setCursor(HWX(currentPosition.x), HWY(currentPosition.y));
       
   490                 } else {
       
   491                     // panning \o/
       
   492                     dx = startingPoint.x - currentPosition.x;
       
   493                     dy = currentPosition.y - startingPoint.y;
       
   494                     HW_getCursor(&x, &y);
       
   495                     // momentum (or something like that)
       
   496                     /*if (abs(dx) > 40)
       
   497                         dx *= log(abs(dx)/4);
       
   498                     if (abs(dy) > 40)
       
   499                         dy *= log(abs(dy)/4);*/
       
   500                     HW_setCursor(x + dx/HW_zoomFactor(), y + dy/HW_zoomFactor());
       
   501                     startingPoint = currentPosition;
       
   502                 }
       
   503             break;
       
   504         case 2:
       
   505             first = [[allTouches allObjects] objectAtIndex:0];
       
   506             second = [[allTouches allObjects] objectAtIndex:1];
       
   507             CGFloat currentDistanceOfPinching = distanceBetweenPoints([first locationInView:self.view], [second locationInView:self.view]);
       
   508             const int pinchDelta = 40;
       
   509 
       
   510             if (0 != initialDistanceForPinching) {
       
   511                 if (currentDistanceOfPinching - initialDistanceForPinching > pinchDelta) {
       
   512                     HW_zoomIn();
       
   513                     initialDistanceForPinching = currentDistanceOfPinching;
       
   514                 }
       
   515                 else if (initialDistanceForPinching - currentDistanceOfPinching > pinchDelta) {
       
   516                     HW_zoomOut();
       
   517                     initialDistanceForPinching = currentDistanceOfPinching;
       
   518                 }
       
   519             } else
       
   520                 initialDistanceForPinching = currentDistanceOfPinching;
       
   521             break;
       
   522         default:
       
   523             break;
       
   524     }
       
   525 }
       
   526 
       
   527 @end