cocoaTouch/SDL_uikitview.m
changeset 2688 174c94b8ea72
parent 2687 28b8330b8af1
child 2689 dfda97c153a4
equal deleted inserted replaced
2687:28b8330b8af1 2688:174c94b8ea72
     1 /*
       
     2  SDL - Simple DirectMedia Layer
       
     3  Copyright (C) 1997-2009 Sam Lantinga
       
     4  
       
     5  This library is free software; you can redistribute it and/or
       
     6  modify it under the terms of the GNU Lesser General Public
       
     7  License as published by the Free Software Foundation; either
       
     8  version 2.1 of the License, or (at your option) any later version.
       
     9  
       
    10  This library is distributed in the hope that it will be useful,
       
    11  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  Lesser General Public License for more details.
       
    14  
       
    15  You should have received a copy of the GNU Lesser General Public
       
    16  License along with this library; if not, write to the Free Software
       
    17  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    18  
       
    19  Sam Lantinga, mods for Hedgewars by Vittorio Giovara
       
    20  slouken@libsdl.org, vittorio.giovara@gmail.com
       
    21  */
       
    22 
       
    23 #include "PascalImports.h"
       
    24 #import "SDL_uikitview.h"
       
    25 #import "SDL_uikitappdelegate.h"
       
    26 
       
    27 #if SDL_IPHONE_KEYBOARD
       
    28 #import "SDL_keyboard_c.h"
       
    29 #import "keyinfotable.h"
       
    30 #import "SDL_uikitwindow.h"
       
    31 #endif
       
    32 
       
    33 @implementation SDL_uikitview
       
    34 
       
    35 @synthesize initialDistance, gestureStartPoint;
       
    36 
       
    37 - (void)dealloc {
       
    38 #if SDL_IPHONE_KEYBOARD
       
    39 	SDL_DelKeyboard(0);
       
    40 	[textField release];
       
    41 #endif
       
    42 	[super dealloc];
       
    43 }
       
    44 
       
    45 - (id)initWithFrame:(CGRect)frame {
       
    46 
       
    47 	self = [super initWithFrame: frame];
       
    48 	
       
    49 #if SDL_IPHONE_KEYBOARD
       
    50 	[self initializeKeyboard];
       
    51 #endif	
       
    52 
       
    53 	int i;
       
    54 	for (i=0; i<MAX_SIMULTANEOUS_TOUCHES; i++) {
       
    55         mice[i].id = i;
       
    56 		mice[i].driverdata = NULL;
       
    57 		SDL_AddMouse(&mice[i], "Mouse", 0, 0, 1);
       
    58 	}
       
    59 	
       
    60 	UIButton *attackButton;
       
    61 
       
    62 	attackButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 90,60)];
       
    63 	[attackButton setBackgroundImage:[UIImage imageNamed:@"Default.png"] forState:UIControlStateNormal];
       
    64 	// this object is inherited by SDL_openglesview.m which is the one allocated by SDL.
       
    65 	// We select this class with [self superclass] and call the selectors with "+" because
       
    66 	// they are superclass methods 
       
    67 	[attackButton addTarget:[self superclass] action:@selector(attackButtonPressed) forControlEvents:UIControlEventTouchDown];
       
    68 	[attackButton addTarget:[self superclass] action:@selector(attackButtonReleased) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside];
       
    69 	[self insertSubview:attackButton atIndex:10];
       
    70 	[attackButton release];
       
    71 
       
    72 	self.multipleTouchEnabled = YES;
       
    73 			
       
    74 	return self;
       
    75 }
       
    76 
       
    77 #pragma mark -
       
    78 #pragma mark Superclass methods
       
    79 +(void) attackButtonPressed {
       
    80 	HW_shoot();
       
    81 }
       
    82 
       
    83 +(void) attackButtonReleased {
       
    84 	HW_allKeysUp();
       
    85 }
       
    86 
       
    87 #pragma mark -
       
    88 #pragma mark Custom SDL_UIView input handling
       
    89 
       
    90 // we override default touch input to implement our own gestures
       
    91 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
       
    92 	/*NSEnumerator *enumerator = [touches objectEnumerator];
       
    93 	UITouch *touch =(UITouch*)[enumerator nextObject];
       
    94 	
       
    95 	/* associate touches with mice, so long as we have slots 
       
    96 	int i;
       
    97 	int found = 0;
       
    98 	for(i=0; touch && i < MAX_SIMULTANEOUS_TOUCHES; i++) {
       
    99 	
       
   100 		/* check if this mouse is already tracking a touch 
       
   101 		if (mice[i].driverdata != NULL) {
       
   102 			continue;
       
   103 		}
       
   104 		/*	
       
   105 			mouse not associated with anything right now,
       
   106 			associate the touch with this mouse
       
   107 		
       
   108 		found = 1;
       
   109 		
       
   110 		/* save old mouse so we can switch back 
       
   111 		int oldMouse = SDL_SelectMouse(-1);
       
   112 		
       
   113 		/* select this slot's mouse 
       
   114 		SDL_SelectMouse(i);
       
   115 		CGPoint locationInView = [touch locationInView: self];
       
   116 		
       
   117 		/* set driver data to touch object, we'll use touch object later 
       
   118 		mice[i].driverdata = [touch retain];
       
   119 		
       
   120 		/* send moved event 
       
   121 		SDL_SendMouseMotion(i, 0, locationInView.x, locationInView.y, 0);
       
   122 		
       
   123 		/* send mouse down event 
       
   124 		SDL_SendMouseButton(i, SDL_PRESSED, SDL_BUTTON_LEFT);
       
   125 		
       
   126 		/* re-calibrate relative mouse motion 
       
   127 		SDL_GetRelativeMouseState(i, NULL, NULL);
       
   128 		
       
   129 		/* grab next touch 
       
   130 		touch = (UITouch*)[enumerator nextObject]; 
       
   131 		
       
   132 		/* switch back to our old mouse 
       
   133 		SDL_SelectMouse(oldMouse);
       
   134 		
       
   135 	}	*/
       
   136 	
       
   137 	UITouch *touch = [touches anyObject];
       
   138 	gestureStartPoint = [touch locationInView:self];
       
   139 
       
   140 	// one tap - single click
       
   141 	if (1 == [touch tapCount] ) {
       
   142 		//SDL_WarpMouseInWindow([SDLUIKitDelegate sharedAppDelegate].windowID, gestureStartPoint.x, gestureStartPoint.y);
       
   143 		HW_click();
       
   144 	}
       
   145 	
       
   146 	// two taps - right click
       
   147 	if (2 == [touch tapCount] ) {
       
   148 		HW_ammoMenu();
       
   149 	}
       
   150 	
       
   151 	// two taps with two fingers - middle click
       
   152 	if (2 == [touch tapCount] && 2 == [touches count]) {
       
   153 		HW_zoomReset();
       
   154 	}
       
   155 	
       
   156 	// two fingers - begin pinching
       
   157 	if (2 == [touches count]) {
       
   158 		NSArray *twoTouches = [touches allObjects];
       
   159 		UITouch *first = [twoTouches objectAtIndex:0];
       
   160 		UITouch *second = [twoTouches objectAtIndex:1];
       
   161 		initialDistance = distanceBetweenPoints([first locationInView:self], [second locationInView:self]);
       
   162 	}
       
   163 }
       
   164 
       
   165 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
       
   166 	initialDistance = 0;
       
   167 //	NSLog(@"touches ended, sigh");
       
   168 	
       
   169 	HW_allKeysUp();
       
   170 	/*NSEnumerator *enumerator = [touches objectEnumerator];
       
   171 	UITouch *touch=nil;
       
   172 	
       
   173 	while(touch = (UITouch *)[enumerator nextObject]) {
       
   174 		/* search for the mouse slot associated with this touch 
       
   175 		int i, found = NO;
       
   176 		for (i=0; i<MAX_SIMULTANEOUS_TOUCHES && !found; i++) {
       
   177 			if (mice[i].driverdata == touch) {
       
   178 				/* found the mouse associate with the touch 
       
   179 				[(UITouch*)(mice[i].driverdata) release];
       
   180 				mice[i].driverdata = NULL;
       
   181 				/* send mouse up 
       
   182 				SDL_SendMouseButton(i, SDL_RELEASED, SDL_BUTTON_LEFT);
       
   183 				/* discontinue search for this touch 
       
   184 				found = YES;
       
   185 			}
       
   186 		}
       
   187 	}*/
       
   188 }
       
   189 
       
   190 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
       
   191 	/*
       
   192 		this can happen if the user puts more than 5 touches on the screen
       
   193 		at once, or perhaps in other circumstances.  Usually (it seems)
       
   194 		all active touches are canceled.
       
   195 	*/
       
   196 	[self touchesEnded: touches withEvent: event];
       
   197 }
       
   198 
       
   199 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
       
   200 	UITouch *touch = [touches anyObject];
       
   201 	CGPoint currentPosition = [touch locationInView:self];
       
   202 	
       
   203 	CGFloat Xdiff = gestureStartPoint.x - currentPosition.x;
       
   204 	CGFloat Ydiff = gestureStartPoint.y - currentPosition.y;
       
   205 	CGFloat deltaX = fabsf(Xdiff);
       
   206     CGFloat deltaY = fabsf(Ydiff);
       
   207     
       
   208 	if (deltaX >= kMinimumGestureLength && deltaY <= kMaximumVariance) {
       
   209 		NSLog(@"Horizontal swipe detected, begX:%f curX:%f", gestureStartPoint.x, currentPosition.x);
       
   210 		if (Xdiff > 0) HW_walkLeft();
       
   211 		else HW_walkRight();
       
   212     }
       
   213     else if (deltaY >= kMinimumGestureLength && deltaX <= kMaximumVariance){
       
   214 		NSLog(@"Vertical swipe detected, begY:%f curY:%f", gestureStartPoint.y, currentPosition.y);
       
   215 		if (Ydiff > 0) HW_aimUp();
       
   216 		else HW_aimDown();
       
   217 	}
       
   218 	
       
   219 	// end pinch detection
       
   220 	if (2 == [touches count]) {
       
   221 		NSArray *twoTouches = [touches allObjects];
       
   222 		UITouch *first = [twoTouches objectAtIndex:0];
       
   223 		UITouch *second = [twoTouches objectAtIndex:1];
       
   224 		CGFloat currentDistance = distanceBetweenPoints([first locationInView:self], [second locationInView:self]);
       
   225 	
       
   226 		if (0 == initialDistance) 
       
   227 			initialDistance = currentDistance;
       
   228 		else if (currentDistance - initialDistance > kMinimumPinchDelta) {
       
   229 			NSLog(@"Outward pinch detected");
       
   230 			HW_zoomOut();
       
   231 		}
       
   232 		else if (initialDistance - currentDistance > kMinimumPinchDelta) {
       
   233 			NSLog(@"Inward pinch detected");
       
   234 			HW_zoomIn();
       
   235 		}
       
   236 	}
       
   237 	
       
   238 	/*NSEnumerator *enumerator = [touches objectEnumerator];
       
   239 	 UITouch *touch=nil;while(touch = (UITouch *)[enumerator nextObject]) {
       
   240 		// try to find the mouse associated with this touch 
       
   241 		int i, found = NO;
       
   242 		for (i=0; i<MAX_SIMULTANEOUS_TOUCHES && !found; i++) {
       
   243 			if (mice[i].driverdata == touch) {
       
   244 				// found proper mouse 
       
   245 				CGPoint locationInView = [touch locationInView: self];
       
   246 				// send moved event 
       
   247 				SDL_SendMouseMotion(i, 0, locationInView.x, locationInView.y, 0);
       
   248 				// discontinue search 
       
   249 				found = YES;
       
   250 			}
       
   251 		}
       
   252 	}*/
       
   253 }
       
   254 
       
   255 #pragma mark -
       
   256 #pragma mark default routines
       
   257 /*
       
   258 	---- Keyboard related functionality below this line ----
       
   259 */
       
   260 #if SDL_IPHONE_KEYBOARD
       
   261 
       
   262 /* Is the iPhone virtual keyboard visible onscreen? */
       
   263 - (BOOL)keyboardVisible {
       
   264 	return keyboardVisible;
       
   265 }
       
   266 
       
   267 /* Set ourselves up as a UITextFieldDelegate */
       
   268 - (void)initializeKeyboard {
       
   269 		
       
   270 	textField = [[[UITextField alloc] initWithFrame: CGRectZero] autorelease];
       
   271 	textField.delegate = self;
       
   272 	/* placeholder so there is something to delete! */
       
   273 	textField.text = @" ";	
       
   274 	
       
   275 	/* set UITextInputTrait properties, mostly to defaults */
       
   276 	textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
       
   277 	textField.autocorrectionType = UITextAutocorrectionTypeNo;
       
   278 	textField.enablesReturnKeyAutomatically = NO;
       
   279 	textField.keyboardAppearance = UIKeyboardAppearanceDefault;
       
   280 	textField.keyboardType = UIKeyboardTypeDefault;
       
   281 	textField.returnKeyType = UIReturnKeyDefault;
       
   282 	textField.secureTextEntry = NO;	
       
   283 	
       
   284 	textField.hidden = YES;
       
   285 	keyboardVisible = NO;
       
   286 	/* add the UITextField (hidden) to our view */
       
   287 	[self addSubview: textField];
       
   288 	
       
   289 	/* create our SDL_Keyboard */
       
   290 	SDL_Keyboard keyboard;
       
   291 	SDL_zero(keyboard);
       
   292 	SDL_AddKeyboard(&keyboard, 0);
       
   293 	SDLKey keymap[SDL_NUM_SCANCODES];
       
   294 	SDL_GetDefaultKeymap(keymap);
       
   295 	SDL_SetKeymap(0, 0, keymap, SDL_NUM_SCANCODES);
       
   296 	
       
   297 }
       
   298 
       
   299 /* reveal onscreen virtual keyboard */
       
   300 - (void)showKeyboard {
       
   301 	keyboardVisible = YES;
       
   302 	[textField becomeFirstResponder];
       
   303 }
       
   304 
       
   305 /* hide onscreen virtual keyboard */
       
   306 - (void)hideKeyboard {
       
   307 	keyboardVisible = NO;
       
   308 	[textField resignFirstResponder];
       
   309 }
       
   310 
       
   311 /* UITextFieldDelegate method.  Invoked when user types something. */
       
   312 - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
       
   313 	
       
   314 	if ([string length] == 0) {
       
   315 		/* it wants to replace text with nothing, ie a delete */
       
   316 		SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_DELETE);
       
   317 		SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_DELETE);
       
   318 	}
       
   319 	else {
       
   320 		/* go through all the characters in the string we've been sent
       
   321 		   and convert them to key presses */
       
   322 		int i;
       
   323 		for (i=0; i<[string length]; i++) {
       
   324 			
       
   325 			unichar c = [string characterAtIndex: i];
       
   326 			
       
   327 			Uint16 mod = 0;
       
   328 			SDL_scancode code;
       
   329 			
       
   330 			if (c < 127) {
       
   331 				/* figure out the SDL_scancode and SDL_keymod for this unichar */
       
   332 				code = unicharToUIKeyInfoTable[c].code;
       
   333 				mod  = unicharToUIKeyInfoTable[c].mod;
       
   334 			}
       
   335 			else {
       
   336 				/* we only deal with ASCII right now */
       
   337 				code = SDL_SCANCODE_UNKNOWN;
       
   338 				mod = 0;
       
   339 			}
       
   340 			
       
   341 			if (mod & KMOD_SHIFT) {
       
   342 				/* If character uses shift, press shift down */
       
   343 				SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_LSHIFT);
       
   344 			}
       
   345 			/* send a keydown and keyup even for the character */
       
   346 			SDL_SendKeyboardKey( 0, SDL_PRESSED, code);
       
   347 			SDL_SendKeyboardKey( 0, SDL_RELEASED, code);
       
   348 			if (mod & KMOD_SHIFT) {
       
   349 				/* If character uses shift, press shift back up */
       
   350 				SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_LSHIFT);
       
   351 			}			
       
   352 		}
       
   353 	}
       
   354 	return NO; /* don't allow the edit! (keep placeholder text there) */
       
   355 }
       
   356 
       
   357 /* Terminates the editing session */
       
   358 - (BOOL)textFieldShouldReturn:(UITextField*)_textField {
       
   359 	[self hideKeyboard];
       
   360 	return YES;
       
   361 }
       
   362 
       
   363 #endif
       
   364 
       
   365 @end
       
   366 
       
   367 /* iPhone keyboard addition functions */
       
   368 #if SDL_IPHONE_KEYBOARD
       
   369 
       
   370 int SDL_iPhoneKeyboardShow(SDL_WindowID windowID) {
       
   371 	
       
   372 	SDL_Window *window = SDL_GetWindowFromID(windowID);
       
   373 	SDL_WindowData *data;
       
   374 	SDL_uikitview *view;
       
   375 	
       
   376 	if (NULL == window) {
       
   377 		SDL_SetError("Window does not exist");
       
   378 		return -1;
       
   379 	}
       
   380 	
       
   381 	data = (SDL_WindowData *)window->driverdata;
       
   382 	view = data->view;
       
   383 	
       
   384 	if (nil == view) {
       
   385 		SDL_SetError("Window has no view");
       
   386 		return -1;
       
   387 	}
       
   388 	else {
       
   389 		[view showKeyboard];
       
   390 		return 0;
       
   391 	}
       
   392 }
       
   393 
       
   394 int SDL_iPhoneKeyboardHide(SDL_WindowID windowID) {
       
   395 	
       
   396 	SDL_Window *window = SDL_GetWindowFromID(windowID);
       
   397 	SDL_WindowData *data;
       
   398 	SDL_uikitview *view;
       
   399 	
       
   400 	if (NULL == window) {
       
   401 		SDL_SetError("Window does not exist");
       
   402 		return -1;
       
   403 	}	
       
   404 	
       
   405 	data = (SDL_WindowData *)window->driverdata;
       
   406 	view = data->view;
       
   407 	
       
   408 	if (NULL == view) {
       
   409 		SDL_SetError("Window has no view");
       
   410 		return -1;
       
   411 	}
       
   412 	else {
       
   413 		[view hideKeyboard];
       
   414 		return 0;
       
   415 	}
       
   416 }
       
   417 
       
   418 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_WindowID windowID) {
       
   419 	
       
   420 	SDL_Window *window = SDL_GetWindowFromID(windowID);
       
   421 	SDL_WindowData *data;
       
   422 	SDL_uikitview *view;
       
   423 	
       
   424 	if (NULL == window) {
       
   425 		SDL_SetError("Window does not exist");
       
   426 		return -1;
       
   427 	}	
       
   428 	
       
   429 	data = (SDL_WindowData *)window->driverdata;
       
   430 	view = data->view;
       
   431 	
       
   432 	if (NULL == view) {
       
   433 		SDL_SetError("Window has no view");
       
   434 		return 0;
       
   435 	}
       
   436 	else {
       
   437 		return view.keyboardVisible;
       
   438 	}
       
   439 }
       
   440 
       
   441 int SDL_iPhoneKeyboardToggle(SDL_WindowID windowID) {
       
   442 	
       
   443 	SDL_Window *window = SDL_GetWindowFromID(windowID);
       
   444 	SDL_WindowData *data;
       
   445 	SDL_uikitview *view;
       
   446 	
       
   447 	if (NULL == window) {
       
   448 		SDL_SetError("Window does not exist");
       
   449 		return -1;
       
   450 	}	
       
   451 	
       
   452 	data = (SDL_WindowData *)window->driverdata;
       
   453 	view = data->view;
       
   454 	
       
   455 	if (NULL == view) {
       
   456 		SDL_SetError("Window has no view");
       
   457 		return -1;
       
   458 	}
       
   459 	else {
       
   460 		if (SDL_iPhoneKeyboardIsShown(windowID)) {
       
   461 			SDL_iPhoneKeyboardHide(windowID);
       
   462 		}
       
   463 		else {
       
   464 			SDL_iPhoneKeyboardShow(windowID);
       
   465 		}
       
   466 		return 0;
       
   467 	}
       
   468 }
       
   469 
       
   470 #else
       
   471 
       
   472 /* stubs, used if compiled without keyboard support */
       
   473 
       
   474 int SDL_iPhoneKeyboardShow(SDL_WindowID windowID) {
       
   475 	SDL_SetError("Not compiled with keyboard support");
       
   476 	return -1;
       
   477 }
       
   478 
       
   479 int SDL_iPhoneKeyboardHide(SDL_WindowID windowID) {
       
   480 	SDL_SetError("Not compiled with keyboard support");
       
   481 	return -1;
       
   482 }
       
   483 
       
   484 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_WindowID windowID) {
       
   485 	return 0;
       
   486 }
       
   487 
       
   488 int SDL_iPhoneKeyboardToggle(SDL_WindowID windowID) {
       
   489 	SDL_SetError("Not compiled with keyboard support");
       
   490 	return -1;
       
   491 }
       
   492 
       
   493 
       
   494 #endif /* SDL_IPHONE_KEYBOARD */