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 #import "PascalImports.h" |
|
24 #import "CGPointUtils.h" |
|
25 #import "SDL_uikitview.h" |
|
26 #import "SDL_uikitappdelegate.h" |
|
27 |
|
28 #if SDL_IPHONE_KEYBOARD |
|
29 #import "SDL_keyboard_c.h" |
|
30 #import "keyinfotable.h" |
|
31 #import "SDL_uikitwindow.h" |
|
32 #endif |
|
33 |
|
34 @implementation SDL_uikitview |
|
35 |
|
36 // they have to be global variables to allow showControls() to use them |
|
37 //UIButton *attackButton, *menuButton; |
|
38 UIView *menuView; |
|
39 -(void) dealloc { |
|
40 #if SDL_IPHONE_KEYBOARD |
|
41 SDL_DelKeyboard(0); |
|
42 [textField release]; |
|
43 #endif |
|
44 [super dealloc]; |
|
45 } |
|
46 |
|
47 -(id) initWithFrame:(CGRect)frame { |
|
48 self = [super initWithFrame:frame]; |
|
49 |
|
50 #if SDL_IPHONE_KEYBOARD |
|
51 [self initializeKeyboard]; |
|
52 #endif |
|
53 |
|
54 int i; |
|
55 for (i=0; i<MAX_SIMULTANEOUS_TOUCHES; i++) { |
|
56 mice[i].id = i; |
|
57 mice[i].driverdata = NULL; |
|
58 SDL_AddMouse(&mice[i], "Mouse", 0, 0, 1); |
|
59 } |
|
60 |
|
61 self.multipleTouchEnabled = YES; |
|
62 self.exclusiveTouch = YES; |
|
63 |
|
64 //(0,0) is the lower left corner |
|
65 //x:[0-320] |
|
66 //y:[0-480] |
|
67 |
|
68 // TO BE MOVED somewhere |
|
69 /* |
|
70 UIButton *menuCorner = [[UIButton alloc] initWithFrame:CGRectMake(256, 416, 64, 64)]; |
|
71 [menuCorner addTarget:[self superclass] action:@selector(showMenu) forControlEvents:UIControlEventTouchDown]; |
|
72 [menuCorner setBackgroundImage:[UIImage imageNamed:@"menuCorner.png"] forState:UIControlStateNormal]; |
|
73 [self insertSubview:menuCorner atIndex:0]; |
|
74 [menuCorner release]; |
|
75 |
|
76 menuView = [[UIView alloc] initWithFrame:CGRectMake(320, 480, 150, 100)]; |
|
77 menuView.backgroundColor = [UIColor lightGrayColor]; |
|
78 [self insertSubview:menuView atIndex:1]; |
|
79 */ |
|
80 return self; |
|
81 } |
|
82 |
|
83 /* |
|
84 TO BE MOVED IN overlayViewController ASAP |
|
85 +(void) showMenu { |
|
86 HW_pause(); |
|
87 |
|
88 [UIView beginAnimations:@"show menu" context:NULL]; |
|
89 [UIView setAnimationDuration:1]; |
|
90 |
|
91 menuView.frame = CGRectMake(170, 380, 150, 100); |
|
92 |
|
93 [UIView commitAnimations]; |
|
94 } |
|
95 |
|
96 +(void) hideMenu { |
|
97 [UIView beginAnimations:@"hide menu" context:NULL]; |
|
98 [UIView setAnimationDuration:1]; |
|
99 |
|
100 menuView.frame = CGRectMake(480, -70, 150, 100); |
|
101 |
|
102 [UIView commitAnimations]; |
|
103 |
|
104 HW_pause(); |
|
105 } |
|
106 |
|
107 */ |
|
108 |
|
109 #pragma mark - |
|
110 #pragma mark Exported functions for FreePascal |
|
111 const char* IPH_getDocumentsPath() { |
|
112 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); |
|
113 NSString *documentsDirectory = [paths objectAtIndex: 0]; |
|
114 return [documentsDirectory UTF8String]; |
|
115 } |
|
116 |
|
117 void IPH_showControls (void) { |
|
118 NSLog(@"Showing controls"); |
|
119 } |
|
120 |
|
121 #pragma mark - |
|
122 #pragma mark Custom SDL_UIView input handling |
|
123 #define kMinimumPinchDelta 50 |
|
124 #define kMinimumGestureLength 10 |
|
125 #define kMaximumVariance 3 |
|
126 |
|
127 // we override default touch input to implement our own gestures |
|
128 -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { |
|
129 NSArray *twoTouches; |
|
130 UITouch *touch = [touches anyObject]; |
|
131 |
|
132 switch ([touches count]) { |
|
133 case 1: |
|
134 gestureStartPoint = [touch locationInView:self]; |
|
135 initialDistanceForPinching = 0; |
|
136 switch ([touch tapCount]) { |
|
137 case 1: |
|
138 NSLog(@"X:%d Y:%d", (int)gestureStartPoint.x, (int)gestureStartPoint.y ); |
|
139 SDL_WarpMouseInWindow([SDLUIKitDelegate sharedAppDelegate].window, |
|
140 (int)gestureStartPoint.y, 320 - (int)gestureStartPoint.x); |
|
141 HW_click(); |
|
142 break; |
|
143 case 2: |
|
144 HW_ammoMenu(); |
|
145 break; |
|
146 default: |
|
147 break; |
|
148 } |
|
149 break; |
|
150 case 2: |
|
151 if (2 == [touch tapCount]) { |
|
152 HW_zoomReset(); |
|
153 } |
|
154 |
|
155 // pinching |
|
156 twoTouches = [touches allObjects]; |
|
157 UITouch *first = [twoTouches objectAtIndex:0]; |
|
158 UITouch *second = [twoTouches objectAtIndex:1]; |
|
159 initialDistanceForPinching = distanceBetweenPoints([first locationInView:self], [second locationInView:self]); |
|
160 break; |
|
161 default: |
|
162 break; |
|
163 } |
|
164 |
|
165 } |
|
166 |
|
167 -(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { |
|
168 initialDistanceForPinching = 0; |
|
169 gestureStartPoint.x = 0; |
|
170 gestureStartPoint.y = 0; |
|
171 HW_allKeysUp(); |
|
172 } |
|
173 |
|
174 -(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { |
|
175 // this can happen if the user puts more than 5 touches on the screen at once, or perhaps in other circumstances. |
|
176 // Usually (it seems) all active touches are canceled. |
|
177 [self touchesEnded:touches withEvent:event]; |
|
178 } |
|
179 |
|
180 -(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { |
|
181 NSArray *twoTouches; |
|
182 CGPoint currentPosition; |
|
183 UITouch *touch = [touches anyObject]; |
|
184 |
|
185 switch ([touches count]) { |
|
186 case 1: |
|
187 currentPosition = [touch locationInView:self]; |
|
188 // panning |
|
189 SDL_WarpMouseInWindow([SDLUIKitDelegate sharedAppDelegate].window, |
|
190 (int)gestureStartPoint.y, 320 - (int)gestureStartPoint.x); |
|
191 // remember that we have x and y inverted |
|
192 /* temporarily disabling hog movements for camera panning testing |
|
193 CGFloat vertDiff = gestureStartPoint.x - currentPosition.x; |
|
194 CGFloat horizDiff = gestureStartPoint.y - currentPosition.y; |
|
195 CGFloat deltaX = fabsf(vertDiff); |
|
196 CGFloat deltaY = fabsf(horizDiff); |
|
197 |
|
198 if (deltaY >= kMinimumGestureLength && deltaX <= kMaximumVariance) { |
|
199 NSLog(@"Horizontal swipe detected, begX:%f curX:%f", gestureStartPoint.x, currentPosition.x); |
|
200 if (horizDiff > 0) HW_walkLeft(); |
|
201 else HW_walkRight(); |
|
202 } else if (deltaX >= kMinimumGestureLength && deltaY <= kMaximumVariance){ |
|
203 NSLog(@"Vertical swipe detected, begY:%f curY:%f", gestureStartPoint.y, currentPosition.y); |
|
204 if (vertDiff < 0) HW_aimUp(); |
|
205 else HW_aimDown(); |
|
206 } |
|
207 */ |
|
208 break; |
|
209 case 2: |
|
210 twoTouches = [touches allObjects]; |
|
211 UITouch *first = [twoTouches objectAtIndex:0]; |
|
212 UITouch *second = [twoTouches objectAtIndex:1]; |
|
213 CGFloat currentDistanceOfPinching = distanceBetweenPoints([first locationInView:self], [second locationInView:self]); |
|
214 |
|
215 if (0 == initialDistanceForPinching) |
|
216 initialDistanceForPinching = currentDistanceOfPinching; |
|
217 |
|
218 if (currentDistanceOfPinching < initialDistanceForPinching + kMinimumPinchDelta) |
|
219 HW_zoomOut(); |
|
220 else if (currentDistanceOfPinching > initialDistanceForPinching + kMinimumPinchDelta) |
|
221 HW_zoomIn(); |
|
222 |
|
223 currentDistanceOfPinching = initialDistanceForPinching; |
|
224 break; |
|
225 default: |
|
226 break; |
|
227 } |
|
228 } |
|
229 |
|
230 /* |
|
231 #pragma mark - |
|
232 #pragma mark Keyboard related functionality |
|
233 #if SDL_IPHONE_KEYBOARD |
|
234 // Is the iPhone virtual keyboard visible onscreen? |
|
235 - (BOOL)keyboardVisible { |
|
236 return keyboardVisible; |
|
237 } |
|
238 |
|
239 // Set ourselves up as a UITextFieldDelegate |
|
240 - (void)initializeKeyboard { |
|
241 |
|
242 textField = [[[UITextField alloc] initWithFrame: CGRectZero] autorelease]; |
|
243 textField.delegate = self; |
|
244 // placeholder so there is something to delete! |
|
245 textField.text = @" "; |
|
246 |
|
247 // set UITextInputTrait properties, mostly to defaults |
|
248 textField.autocapitalizationType = UITextAutocapitalizationTypeNone; |
|
249 textField.autocorrectionType = UITextAutocorrectionTypeNo; |
|
250 textField.enablesReturnKeyAutomatically = NO; |
|
251 textField.keyboardAppearance = UIKeyboardAppearanceDefault; |
|
252 textField.keyboardType = UIKeyboardTypeDefault; |
|
253 textField.returnKeyType = UIReturnKeyDefault; |
|
254 textField.secureTextEntry = NO; |
|
255 |
|
256 textField.hidden = YES; |
|
257 keyboardVisible = NO; |
|
258 // add the UITextField (hidden) to our view |
|
259 [self addSubview: textField]; |
|
260 |
|
261 // create our SDL_Keyboard |
|
262 SDL_Keyboard keyboard; |
|
263 SDL_zero(keyboard); |
|
264 SDL_AddKeyboard(&keyboard, 0); |
|
265 SDLKey keymap[SDL_NUM_SCANCODES]; |
|
266 SDL_GetDefaultKeymap(keymap); |
|
267 SDL_SetKeymap(0, 0, keymap, SDL_NUM_SCANCODES); |
|
268 |
|
269 } |
|
270 |
|
271 // reveal onscreen virtual keyboard |
|
272 - (void)showKeyboard { |
|
273 keyboardVisible = YES; |
|
274 [textField becomeFirstResponder]; |
|
275 } |
|
276 |
|
277 // hide onscreen virtual keyboard |
|
278 - (void)hideKeyboard { |
|
279 keyboardVisible = NO; |
|
280 [textField resignFirstResponder]; |
|
281 } |
|
282 |
|
283 // UITextFieldDelegate method. Invoked when user types something. |
|
284 - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { |
|
285 |
|
286 if ([string length] == 0) { |
|
287 // it wants to replace text with nothing, ie a delete |
|
288 SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_DELETE); |
|
289 SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_DELETE); |
|
290 } |
|
291 else { |
|
292 // go through all the characters in the string we've been sent and convert them to key presses |
|
293 int i; |
|
294 for (i=0; i<[string length]; i++) { |
|
295 |
|
296 unichar c = [string characterAtIndex: i]; |
|
297 |
|
298 Uint16 mod = 0; |
|
299 SDL_scancode code; |
|
300 |
|
301 if (c < 127) { |
|
302 // figure out the SDL_scancode and SDL_keymod for this unichar |
|
303 code = unicharToUIKeyInfoTable[c].code; |
|
304 mod = unicharToUIKeyInfoTable[c].mod; |
|
305 } |
|
306 else { |
|
307 // we only deal with ASCII right now |
|
308 code = SDL_SCANCODE_UNKNOWN; |
|
309 mod = 0; |
|
310 } |
|
311 |
|
312 if (mod & KMOD_SHIFT) { |
|
313 // If character uses shift, press shift down |
|
314 SDL_SendKeyboardKey( 0, SDL_PRESSED, SDL_SCANCODE_LSHIFT); |
|
315 } |
|
316 // send a keydown and keyup even for the character |
|
317 SDL_SendKeyboardKey( 0, SDL_PRESSED, code); |
|
318 SDL_SendKeyboardKey( 0, SDL_RELEASED, code); |
|
319 if (mod & KMOD_SHIFT) { |
|
320 // If character uses shift, press shift back up |
|
321 SDL_SendKeyboardKey( 0, SDL_RELEASED, SDL_SCANCODE_LSHIFT); |
|
322 } |
|
323 } |
|
324 } |
|
325 return NO; // don't allow the edit! (keep placeholder text there) |
|
326 } |
|
327 |
|
328 // Terminates the editing session |
|
329 - (BOOL)textFieldShouldReturn:(UITextField*)_textField { |
|
330 [self hideKeyboard]; |
|
331 return YES; |
|
332 } |
|
333 |
|
334 #endif |
|
335 */ |
|
336 @end |
|
337 /* |
|
338 // iPhone keyboard addition functions |
|
339 #if SDL_IPHONE_KEYBOARD |
|
340 |
|
341 int SDL_iPhoneKeyboardShow(SDL_Window *window) { |
|
342 SDL_WindowData *data; |
|
343 SDL_uikitview *view; |
|
344 |
|
345 if (NULL == window) { |
|
346 SDL_SetError("Window does not exist"); |
|
347 return -1; |
|
348 } |
|
349 |
|
350 data = (SDL_WindowData *)window->driverdata; |
|
351 view = data->view; |
|
352 |
|
353 if (nil == view) { |
|
354 SDL_SetError("Window has no view"); |
|
355 return -1; |
|
356 } |
|
357 else { |
|
358 [view showKeyboard]; |
|
359 return 0; |
|
360 } |
|
361 } |
|
362 |
|
363 int SDL_iPhoneKeyboardHide(SDL_Window *window) { |
|
364 SDL_WindowData *data; |
|
365 SDL_uikitview *view; |
|
366 |
|
367 if (NULL == window) { |
|
368 SDL_SetError("Window does not exist"); |
|
369 return -1; |
|
370 } |
|
371 |
|
372 data = (SDL_WindowData *)window->driverdata; |
|
373 view = data->view; |
|
374 |
|
375 if (NULL == view) { |
|
376 SDL_SetError("Window has no view"); |
|
377 return -1; |
|
378 } |
|
379 else { |
|
380 [view hideKeyboard]; |
|
381 return 0; |
|
382 } |
|
383 } |
|
384 |
|
385 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window *window) { |
|
386 SDL_WindowData *data; |
|
387 SDL_uikitview *view; |
|
388 |
|
389 if (NULL == window) { |
|
390 SDL_SetError("Window does not exist"); |
|
391 return -1; |
|
392 } |
|
393 |
|
394 data = (SDL_WindowData *)window->driverdata; |
|
395 view = data->view; |
|
396 |
|
397 if (NULL == view) { |
|
398 SDL_SetError("Window has no view"); |
|
399 return 0; |
|
400 } |
|
401 else { |
|
402 return view.keyboardVisible; |
|
403 } |
|
404 } |
|
405 |
|
406 int SDL_iPhoneKeyboardToggle(SDL_Window *window) { |
|
407 SDL_WindowData *data; |
|
408 SDL_uikitview *view; |
|
409 |
|
410 if (NULL == window) { |
|
411 SDL_SetError("Window does not exist"); |
|
412 return -1; |
|
413 } |
|
414 |
|
415 data = (SDL_WindowData *)window->driverdata; |
|
416 view = data->view; |
|
417 |
|
418 if (NULL == view) { |
|
419 SDL_SetError("Window has no view"); |
|
420 return -1; |
|
421 } |
|
422 else { |
|
423 if (SDL_iPhoneKeyboardIsShown(window)) { |
|
424 SDL_iPhoneKeyboardHide(window); |
|
425 } |
|
426 else { |
|
427 SDL_iPhoneKeyboardShow(window); |
|
428 } |
|
429 return 0; |
|
430 } |
|
431 } |
|
432 |
|
433 #else |
|
434 |
|
435 // stubs, used if compiled without keyboard support |
|
436 |
|
437 int SDL_iPhoneKeyboardShow(SDL_Window *window) { |
|
438 SDL_SetError("Not compiled with keyboard support"); |
|
439 return -1; |
|
440 } |
|
441 |
|
442 int SDL_iPhoneKeyboardHide(SDL_Window *window) { |
|
443 SDL_SetError("Not compiled with keyboard support"); |
|
444 return -1; |
|
445 } |
|
446 |
|
447 SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window *window) { |
|
448 return 0; |
|
449 } |
|
450 |
|
451 int SDL_iPhoneKeyboardToggle(SDL_Window *window) { |
|
452 SDL_SetError("Not compiled with keyboard support"); |
|
453 return -1; |
|
454 } |
|
455 |
|
456 #endif /* SDL_IPHONE_KEYBOARD */ |
|