cocoaTouch/SDL_uikitview.m
changeset 2678 334016e8d895
child 2682 d4c395f25db2
equal deleted inserted replaced
2677:83ad68ceef72 2678:334016e8d895
       
     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 
       
    26 #if SDL_IPHONE_KEYBOARD
       
    27 #import "SDL_keyboard_c.h"
       
    28 #import "keyinfotable.h"
       
    29 #import "SDL_uikitwindow.h"
       
    30 #import "SDL_uikitappdelegate.h"
       
    31 #endif
       
    32 
       
    33 @implementation SDL_uikitview
       
    34 
       
    35 @synthesize initialDistance;
       
    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 	self.multipleTouchEnabled = YES;
       
    60 			
       
    61 	return self;
       
    62 
       
    63 }
       
    64 
       
    65 #pragma mark -
       
    66 #pragma mark Custom SDL_UIView input handling
       
    67 
       
    68 // we override default touch input to implement our own gestures
       
    69 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
       
    70 
       
    71 	/*NSEnumerator *enumerator = [touches objectEnumerator];
       
    72 	UITouch *touch =(UITouch*)[enumerator nextObject];
       
    73 	
       
    74 	/* associate touches with mice, so long as we have slots 
       
    75 	int i;
       
    76 	int found = 0;
       
    77 	for(i=0; touch && i < MAX_SIMULTANEOUS_TOUCHES; i++) {
       
    78 	
       
    79 		/* check if this mouse is already tracking a touch 
       
    80 		if (mice[i].driverdata != NULL) {
       
    81 			continue;
       
    82 		}
       
    83 		/*	
       
    84 			mouse not associated with anything right now,
       
    85 			associate the touch with this mouse
       
    86 		
       
    87 		found = 1;
       
    88 		
       
    89 		/* save old mouse so we can switch back 
       
    90 		int oldMouse = SDL_SelectMouse(-1);
       
    91 		
       
    92 		/* select this slot's mouse 
       
    93 		SDL_SelectMouse(i);
       
    94 		CGPoint locationInView = [touch locationInView: self];
       
    95 		
       
    96 		/* set driver data to touch object, we'll use touch object later 
       
    97 		mice[i].driverdata = [touch retain];
       
    98 		
       
    99 		/* send moved event 
       
   100 		SDL_SendMouseMotion(i, 0, locationInView.x, locationInView.y, 0);
       
   101 		
       
   102 		/* send mouse down event 
       
   103 		SDL_SendMouseButton(i, SDL_PRESSED, SDL_BUTTON_LEFT);
       
   104 		
       
   105 		/* re-calibrate relative mouse motion 
       
   106 		SDL_GetRelativeMouseState(i, NULL, NULL);
       
   107 		
       
   108 		/* grab next touch 
       
   109 		touch = (UITouch*)[enumerator nextObject]; 
       
   110 		
       
   111 		/* switch back to our old mouse 
       
   112 		SDL_SelectMouse(oldMouse);
       
   113 		
       
   114 	}	*/
       
   115 	UITouch *touch = [touches anyObject];
       
   116 	if (2 == [touch tapCount] ) {
       
   117 		HW_ammoMenu();
       
   118 	}
       
   119 	
       
   120 	if (2 == [touches count]) {
       
   121 		NSArray *twoTouches = [touches allObjects];
       
   122 		UITouch *first = [twoTouches objectAtIndex:0];
       
   123 		UITouch *second = [twoTouches objectAtIndex:1];
       
   124 		initialDistance = distanceBetweenPoints([first locationInView:self], [second locationInView:self]);
       
   125 	}
       
   126 }
       
   127 
       
   128 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
       
   129 	initialDistance = 0;
       
   130 	/*NSEnumerator *enumerator = [touches objectEnumerator];
       
   131 	UITouch *touch=nil;
       
   132 	
       
   133 	while(touch = (UITouch *)[enumerator nextObject]) {
       
   134 		/* search for the mouse slot associated with this touch 
       
   135 		int i, found = NO;
       
   136 		for (i=0; i<MAX_SIMULTANEOUS_TOUCHES && !found; i++) {
       
   137 			if (mice[i].driverdata == touch) {
       
   138 				/* found the mouse associate with the touch 
       
   139 				[(UITouch*)(mice[i].driverdata) release];
       
   140 				mice[i].driverdata = NULL;
       
   141 				/* send mouse up 
       
   142 				SDL_SendMouseButton(i, SDL_RELEASED, SDL_BUTTON_LEFT);
       
   143 				/* discontinue search for this touch 
       
   144 				found = YES;
       
   145 			}
       
   146 		}
       
   147 	}*/
       
   148 }
       
   149 
       
   150 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
       
   151 	/*
       
   152 		this can happen if the user puts more than 5 touches on the screen
       
   153 		at once, or perhaps in other circumstances.  Usually (it seems)
       
   154 		all active touches are canceled.
       
   155 	*/
       
   156 	[self touchesEnded: touches withEvent: event];
       
   157 }
       
   158 
       
   159 
       
   160 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
       
   161 	
       
   162 //	NSEnumerator *enumerator = [touches objectEnumerator];
       
   163 //	UITouch *touch=nil;
       
   164 
       
   165 	if (2 == [touches count]) {
       
   166 		NSArray *twoTouches = [touches allObjects];
       
   167 		UITouch *first = [twoTouches objectAtIndex:0];
       
   168 		UITouch *second = [twoTouches objectAtIndex:1];
       
   169 		CGFloat currentDistance = distanceBetweenPoints([first locationInView:self], [second locationInView:self]);
       
   170 	
       
   171 		if (0 == initialDistance) 
       
   172 			initialDistance = currentDistance;
       
   173 		else if (currentDistance - initialDistance > kMinimumPinchDelta) {
       
   174 			NSLog(@"Outward pinch detected");
       
   175 			HW_zoomOut();
       
   176 		}
       
   177 		else if (initialDistance - currentDistance > kMinimumPinchDelta) {
       
   178 			NSLog(@"Inward pinch detected");
       
   179 			HW_zoomIn();
       
   180 		}
       
   181 	}
       
   182 	
       
   183 	/*while(touch = (UITouch *)[enumerator nextObject]) {
       
   184 		// try to find the mouse associated with this touch 
       
   185 		int i, found = NO;
       
   186 		for (i=0; i<MAX_SIMULTANEOUS_TOUCHES && !found; i++) {
       
   187 			if (mice[i].driverdata == touch) {
       
   188 				// found proper mouse 
       
   189 				CGPoint locationInView = [touch locationInView: self];
       
   190 				// send moved event 
       
   191 				SDL_SendMouseMotion(i, 0, locationInView.x, locationInView.y, 0);
       
   192 				// discontinue search 
       
   193 				found = YES;
       
   194 			}
       
   195 		}
       
   196 	}*/
       
   197 }
       
   198 
       
   199 #pragma mark -
       
   200 #pragma mark default routines
       
   201 /*
       
   202 	---- Keyboard related functionality below this line ----
       
   203 */
       
   204 #if SDL_IPHONE_KEYBOARD
       
   205 
       
   206 /* Is the iPhone virtual keyboard visible onscreen? */
       
   207 - (BOOL)keyboardVisible {
       
   208 	return keyboardVisible;
       
   209 }
       
   210 
       
   211 /* Set ourselves up as a UITextFieldDelegate */
       
   212 - (void)initializeKeyboard {
       
   213 		
       
   214 	textField = [[[UITextField alloc] initWithFrame: CGRectZero] autorelease];
       
   215 	textField.delegate = self;
       
   216 	/* placeholder so there is something to delete! */
       
   217 	textField.text = @" ";	
       
   218 	
       
   219 	/* set UITextInputTrait properties, mostly to defaults */
       
   220 	textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
       
   221 	textField.autocorrectionType = UITextAutocorrectionTypeNo;
       
   222 	textField.enablesReturnKeyAutomatically = NO;
       
   223 	textField.keyboardAppearance = UIKeyboardAppearanceDefault;
       
   224 	textField.keyboardType = UIKeyboardTypeDefault;
       
   225 	textField.returnKeyType = UIReturnKeyDefault;
       
   226 	textField.secureTextEntry = NO;	
       
   227 	
       
   228 	textField.hidden = YES;
       
   229 	keyboardVisible = NO;
       
   230 	/* add the UITextField (hidden) to our view */
       
   231 	[self addSubview: textField];
       
   232 	
       
   233 	/* create our SDL_Keyboard */
       
   234 	SDL_Keyboard keyboard;
       
   235 	SDL_zero(keyboard);
       
   236 	SDL_AddKeyboard(&keyboard, 0);
       
   237 	SDLKey keymap[SDL_NUM_SCANCODES];
       
   238 	SDL_GetDefaultKeymap(keymap);
       
   239 	SDL_SetKeymap(0, 0, keymap, SDL_NUM_SCANCODES);
       
   240 	
       
   241 }
       
   242 
       
   243 /* reveal onscreen virtual keyboard */
       
   244 - (void)showKeyboard {
       
   245 	keyboardVisible = YES;
       
   246 	[textField becomeFirstResponder];
       
   247 }
       
   248 
       
   249 /* hide onscreen virtual keyboard */
       
   250 - (void)hideKeyboard {
       
   251 	keyboardVisible = NO;
       
   252 	[textField resignFirstResponder];
       
   253 }
       
   254 
       
   255 /* UITextFieldDelegate method.  Invoked when user types something. */
       
   256 - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
       
   257 	
       
   258 	if ([string length] == 0) {
       
   259 		/* it wants to replace text with nothing, ie a delete */
       
   260 		SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_DELETE);
       
   261 		SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_DELETE);
       
   262 	}
       
   263 	else {
       
   264 		/* go through all the characters in the string we've been sent
       
   265 		   and convert them to key presses */
       
   266 		int i;
       
   267 		for (i=0; i<[string length]; i++) {
       
   268 			
       
   269 			unichar c = [string characterAtIndex: i];
       
   270 			
       
   271 			Uint16 mod = 0;
       
   272 			SDL_scancode code;
       
   273 			
       
   274 			if (c < 127) {
       
   275 				/* figure out the SDL_scancode and SDL_keymod for this unichar */
       
   276 				code = unicharToUIKeyInfoTable[c].code;
       
   277 				mod  = unicharToUIKeyInfoTable[c].mod;
       
   278 			}
       
   279 			else {
       
   280 				/* we only deal with ASCII right now */
       
   281 				code = SDL_SCANCODE_UNKNOWN;
       
   282 				mod = 0;
       
   283 			}
       
   284 			
       
   285 			if (mod & KMOD_SHIFT) {
       
   286 				/* If character uses shift, press shift down */
       
   287 				SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_LSHIFT);
       
   288 			}
       
   289 			/* send a keydown and keyup even for the character */
       
   290 			SDL_SendKeyboardKey( 0, SDL_PRESSED, code);
       
   291 			SDL_SendKeyboardKey( 0, SDL_RELEASED, code);
       
   292 			if (mod & KMOD_SHIFT) {
       
   293 				/* If character uses shift, press shift back up */
       
   294 				SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_LSHIFT);
       
   295 			}			
       
   296 		}
       
   297 	}
       
   298 	return NO; /* don't allow the edit! (keep placeholder text there) */
       
   299 }
       
   300 
       
   301 /* Terminates the editing session */
       
   302 - (BOOL)textFieldShouldReturn:(UITextField*)_textField {
       
   303 	[self hideKeyboard];
       
   304 	return YES;
       
   305 }
       
   306 
       
   307 #endif
       
   308 
       
   309 @end
       
   310 
       
   311 /* iPhone keyboard addition functions */
       
   312 #if SDL_IPHONE_KEYBOARD
       
   313 
       
   314 int SDL_iPhoneKeyboardShow(SDL_WindowID windowID) {
       
   315 	
       
   316 	SDL_Window *window = SDL_GetWindowFromID(windowID);
       
   317 	SDL_WindowData *data;
       
   318 	SDL_uikitview *view;
       
   319 	
       
   320 	if (NULL == window) {
       
   321 		SDL_SetError("Window does not exist");
       
   322 		return -1;
       
   323 	}
       
   324 	
       
   325 	data = (SDL_WindowData *)window->driverdata;
       
   326 	view = data->view;
       
   327 	
       
   328 	if (nil == view) {
       
   329 		SDL_SetError("Window has no view");
       
   330 		return -1;
       
   331 	}
       
   332 	else {
       
   333 		[view showKeyboard];
       
   334 		return 0;
       
   335 	}
       
   336 }
       
   337 
       
   338 int SDL_iPhoneKeyboardHide(SDL_WindowID windowID) {
       
   339 	
       
   340 	SDL_Window *window = SDL_GetWindowFromID(windowID);
       
   341 	SDL_WindowData *data;
       
   342 	SDL_uikitview *view;
       
   343 	
       
   344 	if (NULL == window) {
       
   345 		SDL_SetError("Window does not exist");
       
   346 		return -1;
       
   347 	}	
       
   348 	
       
   349 	data = (SDL_WindowData *)window->driverdata;
       
   350 	view = data->view;
       
   351 	
       
   352 	if (NULL == view) {
       
   353 		SDL_SetError("Window has no view");
       
   354 		return -1;
       
   355 	}
       
   356 	else {
       
   357 		[view hideKeyboard];
       
   358 		return 0;
       
   359 	}
       
   360 }
       
   361 
       
   362 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_WindowID windowID) {
       
   363 	
       
   364 	SDL_Window *window = SDL_GetWindowFromID(windowID);
       
   365 	SDL_WindowData *data;
       
   366 	SDL_uikitview *view;
       
   367 	
       
   368 	if (NULL == window) {
       
   369 		SDL_SetError("Window does not exist");
       
   370 		return -1;
       
   371 	}	
       
   372 	
       
   373 	data = (SDL_WindowData *)window->driverdata;
       
   374 	view = data->view;
       
   375 	
       
   376 	if (NULL == view) {
       
   377 		SDL_SetError("Window has no view");
       
   378 		return 0;
       
   379 	}
       
   380 	else {
       
   381 		return view.keyboardVisible;
       
   382 	}
       
   383 }
       
   384 
       
   385 int SDL_iPhoneKeyboardToggle(SDL_WindowID windowID) {
       
   386 	
       
   387 	SDL_Window *window = SDL_GetWindowFromID(windowID);
       
   388 	SDL_WindowData *data;
       
   389 	SDL_uikitview *view;
       
   390 	
       
   391 	if (NULL == window) {
       
   392 		SDL_SetError("Window does not exist");
       
   393 		return -1;
       
   394 	}	
       
   395 	
       
   396 	data = (SDL_WindowData *)window->driverdata;
       
   397 	view = data->view;
       
   398 	
       
   399 	if (NULL == view) {
       
   400 		SDL_SetError("Window has no view");
       
   401 		return -1;
       
   402 	}
       
   403 	else {
       
   404 		if (SDL_iPhoneKeyboardIsShown(windowID)) {
       
   405 			SDL_iPhoneKeyboardHide(windowID);
       
   406 		}
       
   407 		else {
       
   408 			SDL_iPhoneKeyboardShow(windowID);
       
   409 		}
       
   410 		return 0;
       
   411 	}
       
   412 }
       
   413 
       
   414 #else
       
   415 
       
   416 /* stubs, used if compiled without keyboard support */
       
   417 
       
   418 int SDL_iPhoneKeyboardShow(SDL_WindowID windowID) {
       
   419 	SDL_SetError("Not compiled with keyboard support");
       
   420 	return -1;
       
   421 }
       
   422 
       
   423 int SDL_iPhoneKeyboardHide(SDL_WindowID windowID) {
       
   424 	SDL_SetError("Not compiled with keyboard support");
       
   425 	return -1;
       
   426 }
       
   427 
       
   428 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_WindowID windowID) {
       
   429 	return 0;
       
   430 }
       
   431 
       
   432 int SDL_iPhoneKeyboardToggle(SDL_WindowID windowID) {
       
   433 	SDL_SetError("Not compiled with keyboard support");
       
   434 	return -1;
       
   435 }
       
   436 
       
   437 
       
   438 #endif /* SDL_IPHONE_KEYBOARD */