PlatformiOS.mm 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983
  1. #ifdef __APPLE__
  2. #include "Base.h"
  3. #include "Platform.h"
  4. #include "FileSystem.h"
  5. #include "Game.h"
  6. #include "Form.h"
  7. #include <unistd.h>
  8. #import <UIKit/UIKit.h>
  9. #import <QuartzCore/QuartzCore.h>
  10. #import <CoreMotion/CoreMotion.h>
  11. #import <OpenGLES/EAGL.h>
  12. #import <OpenGLES/EAGLDrawable.h>
  13. #import <OpenGLES/ES2/gl.h>
  14. #import <OpenGLES/ES2/glext.h>
  15. #import <mach/mach_time.h>
  16. #define UIInterfaceOrientationEnum(x) ([x isEqualToString:@"UIInterfaceOrientationPortrait"]?UIInterfaceOrientationPortrait: \
  17. ([x isEqualToString:@"UIInterfaceOrientationPortraitUpsideDown"]?UIInterfaceOrientationPortraitUpsideDown: \
  18. ([x isEqualToString:@"UIInterfaceOrientationLandscapeLeft"]?UIInterfaceOrientationLandscapeLeft: \
  19. UIInterfaceOrientationLandscapeRight)))
  20. #define DeviceOrientedSize(o) ((o == UIInterfaceOrientationPortrait || o == UIInterfaceOrientationPortraitUpsideDown)? \
  21. CGSizeMake([[UIScreen mainScreen] bounds].size.width * [[UIScreen mainScreen] scale], [[UIScreen mainScreen] bounds].size.height * [[UIScreen mainScreen] scale]): \
  22. CGSizeMake([[UIScreen mainScreen] bounds].size.height * [[UIScreen mainScreen] scale], [[UIScreen mainScreen] bounds].size.width * [[UIScreen mainScreen] scale]))
  23. using namespace std;
  24. using namespace gameplay;
  25. // UIScreen bounds are provided as if device was in portrait mode Gameplay defaults to landscape
  26. extern const int WINDOW_WIDTH = [[UIScreen mainScreen] bounds].size.height * [[UIScreen mainScreen] scale];
  27. extern const int WINDOW_HEIGHT = [[UIScreen mainScreen] bounds].size.width * [[UIScreen mainScreen] scale];
  28. extern const int WINDOW_SCALE = [[UIScreen mainScreen] scale];
  29. @class AppDelegate;
  30. @class View;
  31. static AppDelegate *__appDelegate = NULL;
  32. static View* __view = NULL;
  33. static double __timeStart;
  34. static double __timeAbsolute;
  35. static bool __vsync = WINDOW_VSYNC;
  36. static float __pitch;
  37. static float __roll;
  38. double getMachTimeInMilliseconds();
  39. int getKey(unichar keyCode);
  40. @interface View : UIView <UIKeyInput>
  41. {
  42. EAGLContext* context;
  43. CADisplayLink* displayLink;
  44. GLuint defaultFramebuffer;
  45. GLuint colorRenderbuffer;
  46. GLuint depthRenderbuffer;
  47. GLint framebufferWidth;
  48. GLint framebufferHeight;
  49. NSInteger swapInterval;
  50. BOOL updating;
  51. Game* _game;
  52. }
  53. @property (readonly, nonatomic, getter=isUpdating) BOOL updating;
  54. @property (readonly, nonatomic, getter=getContext) EAGLContext* context;
  55. - (void)startGame;
  56. - (void)startUpdating;
  57. - (void)stopUpdating;
  58. - (void)update:(id)sender;
  59. - (void)setSwapInterval:(NSInteger)interval;
  60. - (int)swapInterval;
  61. - (void)swapBuffers;
  62. - (BOOL)showKeyboard;
  63. - (BOOL)dismissKeyboard;
  64. @end
  65. @interface View (Private)
  66. - (void)createFramebuffer;
  67. - (void)deleteFramebuffer;
  68. @end
  69. @implementation View
  70. @synthesize updating;
  71. @synthesize context;
  72. + (Class) layerClass
  73. {
  74. return [CAEAGLLayer class];
  75. }
  76. - (id) initWithFrame:(CGRect)frame
  77. {
  78. if ((self = [super initWithFrame:frame]))
  79. {
  80. // A system version of 3.1 or greater is required to use CADisplayLink.
  81. NSString *reqSysVer = @"3.1";
  82. NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
  83. if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
  84. {
  85. // Log the system version
  86. NSLog(@"System Version: %@", currSysVer);
  87. }
  88. else
  89. {
  90. printError("Invalid OS Version: %s\n", (currSysVer == NULL?"NULL":[currSysVer cStringUsingEncoding:NSASCIIStringEncoding]));
  91. [self release];
  92. return nil;
  93. }
  94. // Configure the CAEAGLLayer and setup out the rendering context
  95. CGFloat scale = [[UIScreen mainScreen] scale];
  96. CAEAGLLayer* layer = (CAEAGLLayer *)self.layer;
  97. layer.opaque = TRUE;
  98. layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
  99. [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
  100. kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
  101. self.contentScaleFactor = scale;
  102. layer.contentsScale = scale;
  103. context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
  104. if (!context || ![EAGLContext setCurrentContext:context])
  105. {
  106. [self release];
  107. return nil;
  108. }
  109. if (!defaultFramebuffer)
  110. {
  111. [self createFramebuffer];
  112. }
  113. glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
  114. glViewport(0, 0, framebufferWidth, framebufferHeight);
  115. // Initialize Internal Defaults
  116. displayLink = nil;
  117. defaultFramebuffer = 0;
  118. colorRenderbuffer = 0;
  119. depthRenderbuffer = 0;
  120. framebufferWidth = 0;
  121. framebufferHeight = 0;
  122. swapInterval = 1;
  123. updating = FALSE;
  124. [self createFramebuffer];
  125. // Set the resource path and initalize the game
  126. NSString* bundlePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/"];
  127. FileSystem::setResourcePath([bundlePath fileSystemRepresentation]);
  128. }
  129. return self;
  130. }
  131. - (void) dealloc
  132. {
  133. _game->exit();
  134. [self deleteFramebuffer];
  135. if ([EAGLContext currentContext] == context)
  136. {
  137. [EAGLContext setCurrentContext:nil];
  138. }
  139. [context release];
  140. [super dealloc];
  141. }
  142. - (BOOL)canBecomeFirstResponder
  143. {
  144. // Override so we can control the keyboard
  145. return YES;
  146. }
  147. - (void) layoutSubviews
  148. {
  149. // Called on 'resize'
  150. [self deleteFramebuffer];
  151. }
  152. - (void)createFramebuffer
  153. {
  154. // iOS Requires all content go to a rendering buffer then it is swapped into the windows rendering surface
  155. assert(defaultFramebuffer == 0);
  156. // Create the default frame buffer, and render buffer
  157. glGenFramebuffers(1, &defaultFramebuffer);
  158. glGenRenderbuffers(1, &colorRenderbuffer);
  159. glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
  160. glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
  161. // request storage, width, and height of the view that we will render in
  162. [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
  163. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
  164. glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferWidth);
  165. glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferHeight);
  166. glGenRenderbuffers(1, &depthRenderbuffer);
  167. glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
  168. glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, framebufferWidth, framebufferHeight);
  169. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
  170. // Sanity check, ensure that the framebuffer is valid
  171. if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
  172. NSLog(@"ERROR: Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
  173. }
  174. - (void)deleteFramebuffer
  175. {
  176. if (context)
  177. {
  178. [EAGLContext setCurrentContext:context];
  179. if (defaultFramebuffer)
  180. {
  181. glDeleteFramebuffers(1, &defaultFramebuffer);
  182. defaultFramebuffer = 0;
  183. }
  184. if (colorRenderbuffer)
  185. {
  186. glDeleteRenderbuffers(1, &colorRenderbuffer);
  187. colorRenderbuffer = 0;
  188. }
  189. if (depthRenderbuffer)
  190. {
  191. glDeleteRenderbuffers(1, &depthRenderbuffer);
  192. depthRenderbuffer = 0;
  193. }
  194. }
  195. }
  196. - (void)setSwapInterval:(NSInteger)interval
  197. {
  198. if (interval >= 1)
  199. {
  200. swapInterval = interval;
  201. if (updating)
  202. {
  203. [self stopUpdating];
  204. [self startUpdating];
  205. }
  206. }
  207. }
  208. - (int)swapInterval
  209. {
  210. return swapInterval;
  211. }
  212. - (void)swapBuffers
  213. {
  214. if (context != nil)
  215. {
  216. glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
  217. [context presentRenderbuffer:GL_RENDERBUFFER];
  218. }
  219. }
  220. - (void)startGame
  221. {
  222. _game = Game::getInstance();
  223. __timeStart = getMachTimeInMilliseconds();
  224. _game->run();
  225. }
  226. - (void)startUpdating
  227. {
  228. if (!updating)
  229. {
  230. displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update:)];
  231. [displayLink setFrameInterval:swapInterval];
  232. [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  233. _game->resume();
  234. updating = TRUE;
  235. }
  236. }
  237. - (void)stopUpdating
  238. {
  239. if (updating)
  240. {
  241. _game->pause();
  242. [displayLink invalidate];
  243. displayLink = nil;
  244. updating = FALSE;
  245. }
  246. }
  247. - (void)update:(id)sender
  248. {
  249. if (context != nil)
  250. {
  251. [EAGLContext setCurrentContext:context];
  252. if (!defaultFramebuffer)
  253. [self createFramebuffer];
  254. glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
  255. glViewport(0, 0, framebufferWidth, framebufferHeight);
  256. if (_game && _game->getState() == Game::RUNNING)
  257. _game->frame();
  258. glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
  259. [context presentRenderbuffer:GL_RENDERBUFFER];
  260. }
  261. }
  262. - (BOOL)showKeyboard
  263. {
  264. return [self becomeFirstResponder];
  265. }
  266. - (BOOL)dismissKeyboard
  267. {
  268. return [self resignFirstResponder];
  269. }
  270. - (void)insertText:(NSString*)text
  271. {
  272. if([text length] == 0) return;
  273. assert([text length] == 1);
  274. unichar c = [text characterAtIndex:0];
  275. int key = getKey(c);
  276. Platform::keyEventInternal(Keyboard::KEY_PRESS, key);
  277. Platform::keyEventInternal(Keyboard::KEY_RELEASE, key);
  278. }
  279. - (void)deleteBackward
  280. {
  281. Platform::keyEventInternal(Keyboard::KEY_PRESS, Keyboard::KEY_BACKSPACE);
  282. Platform::keyEventInternal(Keyboard::KEY_RELEASE, Keyboard::KEY_BACKSPACE);
  283. }
  284. - (BOOL)hasText
  285. {
  286. return YES;
  287. }
  288. - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
  289. {
  290. unsigned int touchID = 0;
  291. for(UITouch* touch in touches)
  292. {
  293. CGPoint touchPoint = [touch locationInView:self];
  294. if(self.multipleTouchEnabled == YES)
  295. {
  296. touchID = [touch hash];
  297. }
  298. Platform::touchEventInternal(Touch::TOUCH_PRESS, touchPoint.x * WINDOW_SCALE, touchPoint.y * WINDOW_SCALE, touchID);
  299. }
  300. }
  301. - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
  302. {
  303. unsigned int touchID = 0;
  304. for(UITouch* touch in touches)
  305. {
  306. CGPoint touchPoint = [touch locationInView:self];
  307. if(self.multipleTouchEnabled == YES)
  308. touchID = [touch hash];
  309. Platform::touchEventInternal(Touch::TOUCH_RELEASE, touchPoint.x * WINDOW_SCALE, touchPoint.y * WINDOW_SCALE, touchID);
  310. }
  311. }
  312. - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
  313. {
  314. // No equivalent for this in GamePlay -- treat as touch end
  315. [self touchesEnded:touches withEvent:event];
  316. }
  317. - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
  318. {
  319. unsigned int touchID = 0;
  320. for(UITouch* touch in touches)
  321. {
  322. CGPoint touchPoint = [touch locationInView:self];
  323. if(self.multipleTouchEnabled == YES)
  324. touchID = [touch hash];
  325. Platform::touchEventInternal(Touch::TOUCH_MOVE, touchPoint.x * WINDOW_SCALE, touchPoint.y * WINDOW_SCALE, touchID);
  326. }
  327. }
  328. @end
  329. @interface ViewController : UIViewController
  330. - (void)startUpdating;
  331. - (void)stopUpdating;
  332. @end
  333. @implementation ViewController
  334. - (id)init
  335. {
  336. if((self = [super init]))
  337. {
  338. }
  339. return self;
  340. }
  341. - (void)dealloc
  342. {
  343. __view = nil;
  344. [super dealloc];
  345. }
  346. - (void)didReceiveMemoryWarning
  347. {
  348. [super didReceiveMemoryWarning];
  349. }
  350. #pragma mark - View lifecycle
  351. - (void)loadView
  352. {
  353. self.view = [[[View alloc] init] autorelease];
  354. if(__view == nil)
  355. {
  356. __view = (View*)self.view;
  357. }
  358. // Start the game after assigning __view so Platform object knows about it on game start
  359. [(View*)self.view startGame];
  360. }
  361. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  362. {
  363. // Fetch the supported orientations array
  364. NSArray *supportedOrientations = NULL;
  365. if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
  366. {
  367. supportedOrientations = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UISupportedInterfaceOrientations~ipad"];
  368. }
  369. else if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
  370. {
  371. supportedOrientations = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UISupportedInterfaceOrientations~iphone"];
  372. }
  373. if(supportedOrientations == NULL)
  374. {
  375. supportedOrientations = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UISupportedInterfaceOrientations"];
  376. }
  377. // If no supported orientations default to v1.0 handling (landscape only)
  378. if(supportedOrientations == nil) {
  379. return UIInterfaceOrientationIsLandscape(interfaceOrientation);
  380. }
  381. for(NSString *s in supportedOrientations) {
  382. if(interfaceOrientation == UIInterfaceOrientationEnum(s)) return YES;
  383. }
  384. return NO;
  385. }
  386. - (void)startUpdating
  387. {
  388. [(View*)self.view startUpdating];
  389. }
  390. - (void)stopUpdating
  391. {
  392. [(View*)self.view stopUpdating];
  393. }
  394. @end
  395. @interface AppDelegate : UIApplication <UIApplicationDelegate>
  396. {
  397. UIWindow* window;
  398. ViewController* viewController;
  399. CMMotionManager *motionManager;
  400. }
  401. @property (nonatomic, retain) ViewController *viewController;
  402. @end
  403. @implementation AppDelegate
  404. @synthesize viewController;
  405. - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
  406. {
  407. __appDelegate = self;
  408. [UIApplication sharedApplication].statusBarHidden = YES;
  409. [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
  410. motionManager = [[CMMotionManager alloc] init];
  411. if([motionManager isAccelerometerAvailable] == YES)
  412. {
  413. motionManager.accelerometerUpdateInterval = 1 / 40.0; // 40Hz
  414. [motionManager startAccelerometerUpdates];
  415. }
  416. window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  417. viewController = [[ViewController alloc] init];
  418. [window setRootViewController:viewController];
  419. [window makeKeyAndVisible];
  420. return YES;
  421. }
  422. - (void)getAccelerometerPitch:(float*)pitch roll:(float*)roll
  423. {
  424. float p = 0.0f;
  425. float r = 0.0f;
  426. CMAccelerometerData* accelerometerData = motionManager.accelerometerData;
  427. if(accelerometerData != nil)
  428. {
  429. float tx, ty, tz;
  430. switch ([[UIApplication sharedApplication] statusBarOrientation])
  431. {
  432. case UIInterfaceOrientationLandscapeRight:
  433. tx = -accelerometerData.acceleration.y;
  434. ty = accelerometerData.acceleration.x;
  435. break;
  436. case UIInterfaceOrientationLandscapeLeft:
  437. tx = accelerometerData.acceleration.y;
  438. ty = -accelerometerData.acceleration.x;
  439. break;
  440. case UIInterfaceOrientationPortraitUpsideDown:
  441. tx = -accelerometerData.acceleration.y;
  442. ty = -accelerometerData.acceleration.x;
  443. break;
  444. case UIInterfaceOrientationPortrait:
  445. tx = accelerometerData.acceleration.x;
  446. ty = accelerometerData.acceleration.y;
  447. break;
  448. }
  449. tz = accelerometerData.acceleration.z;
  450. p = atan(ty / sqrt(tx * tx + tz * tz)) * 180.0f * M_1_PI;
  451. r = atan(tx / sqrt(ty * ty + tz * tz)) * 180.0f * M_1_PI;
  452. }
  453. if(pitch != NULL)
  454. *pitch = p;
  455. if(roll != NULL)
  456. *roll = r;
  457. }
  458. - (void)applicationWillResignActive:(UIApplication*)application
  459. {
  460. [viewController stopUpdating];
  461. }
  462. - (void)applicationDidEnterBackground:(UIApplication*)application
  463. {
  464. [viewController stopUpdating];
  465. }
  466. - (void)applicationWillEnterForeground:(UIApplication*)application
  467. {
  468. [viewController startUpdating];
  469. }
  470. - (void)applicationDidBecomeActive:(UIApplication*)application
  471. {
  472. [viewController startUpdating];
  473. }
  474. - (void)applicationWillTerminate:(UIApplication*)application
  475. {
  476. [viewController stopUpdating];
  477. }
  478. - (void)dealloc
  479. {
  480. [window setRootViewController:nil];
  481. [viewController release];
  482. [window release];
  483. [motionManager release];
  484. [super dealloc];
  485. }
  486. @end
  487. double getMachTimeInMilliseconds()
  488. {
  489. static const double kOneMillion = 1000 * 1000;
  490. static mach_timebase_info_data_t s_timebase_info;
  491. if (s_timebase_info.denom == 0)
  492. (void) mach_timebase_info(&s_timebase_info);
  493. // mach_absolute_time() returns billionth of seconds, so divide by one million to get milliseconds
  494. GP_ASSERT(s_timebase_info.denom);
  495. return ((double)mach_absolute_time() * (double)s_timebase_info.numer) / (kOneMillion * (double)s_timebase_info.denom);
  496. }
  497. int getKey(unichar keyCode)
  498. {
  499. switch(keyCode)
  500. {
  501. case 0x30:
  502. return Keyboard::KEY_ZERO;
  503. case 0x31:
  504. return Keyboard::KEY_ONE;
  505. case 0x32:
  506. return Keyboard::KEY_TWO;
  507. case 0x33:
  508. return Keyboard::KEY_THREE;
  509. case 0x34:
  510. return Keyboard::KEY_FOUR;
  511. case 0x35:
  512. return Keyboard::KEY_FIVE;
  513. case 0x36:
  514. return Keyboard::KEY_SIX;
  515. case 0x37:
  516. return Keyboard::KEY_SEVEN;
  517. case 0x38:
  518. return Keyboard::KEY_EIGHT;
  519. case 0x39:
  520. return Keyboard::KEY_NINE;
  521. case 0x41:
  522. return Keyboard::KEY_CAPITAL_A;
  523. case 0x42:
  524. return Keyboard::KEY_CAPITAL_B;
  525. case 0x43:
  526. return Keyboard::KEY_CAPITAL_C;
  527. case 0x44:
  528. return Keyboard::KEY_CAPITAL_D;
  529. case 0x45:
  530. return Keyboard::KEY_CAPITAL_E;
  531. case 0x46:
  532. return Keyboard::KEY_CAPITAL_F;
  533. case 0x47:
  534. return Keyboard::KEY_CAPITAL_G;
  535. case 0x48:
  536. return Keyboard::KEY_CAPITAL_H;
  537. case 0x49:
  538. return Keyboard::KEY_CAPITAL_I;
  539. case 0x4A:
  540. return Keyboard::KEY_CAPITAL_J;
  541. case 0x4B:
  542. return Keyboard::KEY_CAPITAL_K;
  543. case 0x4C:
  544. return Keyboard::KEY_CAPITAL_L;
  545. case 0x4D:
  546. return Keyboard::KEY_CAPITAL_M;
  547. case 0x4E:
  548. return Keyboard::KEY_CAPITAL_N;
  549. case 0x4F:
  550. return Keyboard::KEY_CAPITAL_O;
  551. case 0x50:
  552. return Keyboard::KEY_CAPITAL_P;
  553. case 0x51:
  554. return Keyboard::KEY_CAPITAL_Q;
  555. case 0x52:
  556. return Keyboard::KEY_CAPITAL_R;
  557. case 0x53:
  558. return Keyboard::KEY_CAPITAL_S;
  559. case 0x54:
  560. return Keyboard::KEY_CAPITAL_T;
  561. case 0x55:
  562. return Keyboard::KEY_CAPITAL_U;
  563. case 0x56:
  564. return Keyboard::KEY_CAPITAL_V;
  565. case 0x57:
  566. return Keyboard::KEY_CAPITAL_W;
  567. case 0x58:
  568. return Keyboard::KEY_CAPITAL_X;
  569. case 0x59:
  570. return Keyboard::KEY_CAPITAL_Y;
  571. case 0x5A:
  572. return Keyboard::KEY_CAPITAL_Z;
  573. case 0x61:
  574. return Keyboard::KEY_A;
  575. case 0x62:
  576. return Keyboard::KEY_B;
  577. case 0x63:
  578. return Keyboard::KEY_C;
  579. case 0x64:
  580. return Keyboard::KEY_D;
  581. case 0x65:
  582. return Keyboard::KEY_E;
  583. case 0x66:
  584. return Keyboard::KEY_F;
  585. case 0x67:
  586. return Keyboard::KEY_G;
  587. case 0x68:
  588. return Keyboard::KEY_H;
  589. case 0x69:
  590. return Keyboard::KEY_I;
  591. case 0x6A:
  592. return Keyboard::KEY_J;
  593. case 0x6B:
  594. return Keyboard::KEY_K;
  595. case 0x6C:
  596. return Keyboard::KEY_L;
  597. case 0x6D:
  598. return Keyboard::KEY_M;
  599. case 0x6E:
  600. return Keyboard::KEY_N;
  601. case 0x6F:
  602. return Keyboard::KEY_O;
  603. case 0x70:
  604. return Keyboard::KEY_P;
  605. case 0x71:
  606. return Keyboard::KEY_Q;
  607. case 0x72:
  608. return Keyboard::KEY_R;
  609. case 0x73:
  610. return Keyboard::KEY_S;
  611. case 0x74:
  612. return Keyboard::KEY_T;
  613. case 0x75:
  614. return Keyboard::KEY_U;
  615. case 0x76:
  616. return Keyboard::KEY_V;
  617. case 0x77:
  618. return Keyboard::KEY_W;
  619. case 0x78:
  620. return Keyboard::KEY_X;
  621. case 0x79:
  622. return Keyboard::KEY_Y;
  623. case 0x7A:
  624. return Keyboard::KEY_Z;
  625. default:
  626. break;
  627. // Symbol Row 3
  628. case 0x2E:
  629. return Keyboard::KEY_PERIOD;
  630. case 0x2C:
  631. return Keyboard::KEY_COMMA;
  632. case 0x3F:
  633. return Keyboard::KEY_QUESTION;
  634. case 0x21:
  635. return Keyboard::KEY_EXCLAM;
  636. case 0x27:
  637. return Keyboard::KEY_APOSTROPHE;
  638. // Symbols Row 2
  639. case 0x2D:
  640. return Keyboard::KEY_MINUS;
  641. case 0x2F:
  642. return Keyboard::KEY_SLASH;
  643. case 0x3A:
  644. return Keyboard::KEY_COLON;
  645. case 0x3B:
  646. return Keyboard::KEY_SEMICOLON;
  647. case 0x28:
  648. return Keyboard::KEY_LEFT_PARENTHESIS;
  649. case 0x29:
  650. return Keyboard::KEY_RIGHT_PARENTHESIS;
  651. case 0x24:
  652. return Keyboard::KEY_DOLLAR;
  653. case 0x26:
  654. return Keyboard::KEY_AMPERSAND;
  655. case 0x40:
  656. return Keyboard::KEY_AT;
  657. case 0x22:
  658. return Keyboard::KEY_QUOTE;
  659. // Numeric Symbols Row 1
  660. case 0x5B:
  661. return Keyboard::KEY_LEFT_BRACKET;
  662. case 0x5D:
  663. return Keyboard::KEY_RIGHT_BRACKET;
  664. case 0x7B:
  665. return Keyboard::KEY_LEFT_BRACE;
  666. case 0x7D:
  667. return Keyboard::KEY_RIGHT_BRACE;
  668. case 0x23:
  669. return Keyboard::KEY_NUMBER;
  670. case 0x25:
  671. return Keyboard::KEY_PERCENT;
  672. case 0x5E:
  673. return Keyboard::KEY_CIRCUMFLEX;
  674. case 0x2A:
  675. return Keyboard::KEY_ASTERISK;
  676. case 0x2B:
  677. return Keyboard::KEY_PLUS;
  678. case 0x3D:
  679. return Keyboard::KEY_EQUAL;
  680. // Numeric Symbols Row 2
  681. case 0x5F:
  682. return Keyboard::KEY_UNDERSCORE;
  683. case 0x5C:
  684. return Keyboard::KEY_BACK_SLASH;
  685. case 0x7C:
  686. return Keyboard::KEY_BAR;
  687. case 0x7E:
  688. return Keyboard::KEY_TILDE;
  689. case 0x3C:
  690. return Keyboard::KEY_LESS_THAN;
  691. case 0x3E:
  692. return Keyboard::KEY_GREATER_THAN;
  693. case 0x80:
  694. return Keyboard::KEY_EURO;
  695. case 0xA3:
  696. return Keyboard::KEY_POUND;
  697. case 0xA5:
  698. return Keyboard::KEY_YEN;
  699. case 0xB7:
  700. return Keyboard::KEY_MIDDLE_DOT;
  701. }
  702. return Keyboard::KEY_NONE;
  703. }
  704. namespace gameplay
  705. {
  706. extern void printError(const char* format, ...)
  707. {
  708. GP_ASSERT(format);
  709. va_list argptr;
  710. va_start(argptr, format);
  711. vfprintf(stderr, format, argptr);
  712. va_end(argptr);
  713. }
  714. Platform::Platform(Game* game) : _game(game)
  715. {
  716. }
  717. Platform::~Platform()
  718. {
  719. }
  720. Platform* Platform::create(Game* game, void* attachToWindow)
  721. {
  722. Platform* platform = new Platform(game);
  723. return platform;
  724. }
  725. int Platform::enterMessagePump()
  726. {
  727. NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  728. [AppDelegate load];
  729. UIApplicationMain(0, nil, NSStringFromClass([AppDelegate class]), NSStringFromClass([AppDelegate class]));
  730. [pool release];
  731. return EXIT_SUCCESS;
  732. }
  733. void Platform::signalShutdown()
  734. {
  735. // Cannot 'exit' an iOS Application
  736. assert(false);
  737. [__view stopUpdating];
  738. exit(0);
  739. }
  740. unsigned int Platform::getDisplayWidth()
  741. {
  742. CGSize size = DeviceOrientedSize([__appDelegate.viewController interfaceOrientation]);
  743. return size.width;
  744. }
  745. unsigned int Platform::getDisplayHeight()
  746. {
  747. CGSize size = DeviceOrientedSize([__appDelegate.viewController interfaceOrientation]);
  748. return size.height;
  749. }
  750. double Platform::getAbsoluteTime()
  751. {
  752. __timeAbsolute = getMachTimeInMilliseconds();
  753. return __timeAbsolute;
  754. }
  755. void Platform::setAbsoluteTime(double time)
  756. {
  757. __timeAbsolute = time;
  758. }
  759. bool Platform::isVsync()
  760. {
  761. return __vsync;
  762. }
  763. void Platform::setVsync(bool enable)
  764. {
  765. __vsync = enable;
  766. }
  767. void Platform::getAccelerometerValues(float* pitch, float* roll)
  768. {
  769. [__appDelegate getAccelerometerPitch:pitch roll:roll];
  770. }
  771. bool Platform::hasMouse()
  772. {
  773. // not supported
  774. return false;
  775. }
  776. void Platform::setMouseCaptured(bool captured)
  777. {
  778. // not supported
  779. }
  780. bool Platform::isMouseCaptured()
  781. {
  782. // not supported
  783. return false;
  784. }
  785. void Platform::setCursorVisible(bool visible)
  786. {
  787. // not supported
  788. }
  789. bool Platform::isCursorVisible()
  790. {
  791. // not supported
  792. return false;
  793. }
  794. void Platform::setMultiTouch(bool enabled)
  795. {
  796. __view.multipleTouchEnabled = enabled;
  797. }
  798. bool Platform::isMultiTouch()
  799. {
  800. return __view.multipleTouchEnabled;
  801. }
  802. void Platform::swapBuffers()
  803. {
  804. if (__view)
  805. [__view swapBuffers];
  806. }
  807. void Platform::displayKeyboard(bool display)
  808. {
  809. if(__view)
  810. {
  811. if(display)
  812. {
  813. [__view showKeyboard];
  814. }
  815. else
  816. {
  817. [__view dismissKeyboard];
  818. }
  819. }
  820. }
  821. void Platform::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
  822. {
  823. if (!Form::touchEventInternal(evt, x, y, contactIndex))
  824. Game::getInstance()->touchEvent(evt, x, y, contactIndex);
  825. }
  826. void Platform::keyEventInternal(Keyboard::KeyEvent evt, int key)
  827. {
  828. if (!Form::keyEventInternal(evt, key))
  829. Game::getInstance()->keyEvent(evt, key);
  830. }
  831. bool Platform::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
  832. {
  833. if (Form::mouseEventInternal(evt, x, y, wheelDelta))
  834. {
  835. return true;
  836. }
  837. else
  838. {
  839. return Game::getInstance()->mouseEvent(evt, x, y, wheelDelta);
  840. }
  841. }
  842. void Platform::sleep(long ms)
  843. {
  844. usleep(ms * 1000);
  845. }
  846. }
  847. #endif