From 638dc113f8c05f121d50e68f68c4e86c130756a4 Mon Sep 17 00:00:00 2001 From: Vincent Bénony Date: Fri, 4 Dec 2015 18:20:09 +0100 Subject: IOS: Create two targets for old iPhone (iOS <= 6) and new one (iOS >= 7) The "iphone" backend is the support for the old iPhones. The "ios7" backend is for the new iPhones. --- backends/platform/iphone/README.md | 66 ----- backends/platform/iphone/iphone_common.h | 8 +- backends/platform/iphone/iphone_keyboard.h | 5 +- backends/platform/iphone/iphone_keyboard.mm | 45 ++-- backends/platform/iphone/iphone_main.mm | 38 +-- backends/platform/iphone/iphone_video.h | 4 + backends/platform/iphone/iphone_video.mm | 362 +++++++++++++--------------- backends/platform/iphone/osys_events.cpp | 211 ++++++---------- backends/platform/iphone/osys_main.cpp | 27 +-- backends/platform/iphone/osys_main.h | 5 +- 10 files changed, 275 insertions(+), 496 deletions(-) delete mode 100644 backends/platform/iphone/README.md (limited to 'backends/platform/iphone') diff --git a/backends/platform/iphone/README.md b/backends/platform/iphone/README.md deleted file mode 100644 index 0e22e6d2bd..0000000000 --- a/backends/platform/iphone/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# ScummVM for iOS 7.1+ # - -This is a quick fix of the latest ScummVM (1.8.0) for iOS 7.1. It has been tested on real iPhone 6S+, and iPad Pro, and also on all the available Xcode simulators. - -I tried to use all the latest iOS features to replace the old code. For instance, it uses gesture recognizers most of the time, it supports the new iPhones 6 / 6+ / 6s / 6s+ resolution, and you can copy your game files using iTunes. - -## Compilation ## - -First, clone the repository: -``` -$ git clone -b ios-fix --recursive https://github.com/bSr43/scummvm.git -``` - -### Compilation from Xcode ### - -This is the recommended way to compile ScummVM, and the only one which makes it possible to run ScummVM on a non-jailbroken device! - -The next step is to compile the **create_project** tool. Open the Xcode project you'll found in the **devtools/create\_project/xcode/** directory. Once compiled, copy the binary somewhere in your *PATH*, and create a **build** directory somewhere on your harddisk. It is recommended to create this directory next to the cloned repository (they share the same parent). - -Execute the following commands in a terminal: -``` -$ cd path_to_the_build_directory -$ create_project path_to_scummvm_repository --xcode --disable-mad --disable-jpeg --disable-bink --disable-scalers --disable-hqscalers --disable-16bit --disable-mt32emu --disable-nasm --disable-opengl --disable-theora --disable-taskbar -``` - -This will create an Xcode project for ScummVM, for both the OS X, and the iOS target. - -Now, download the external libraries from http://bsr43.free.fr/scummvm/ScummVM-iOS-libraries.zip. Unzip the archive in your **build** directory. Please make sure that the **lib**, and **include** directories are at the root of the **build** directory, not in a subdirectory. - -Now, your **build** directory should contain: -* a generated **engines** directory, -* a generated **scummvm.xcodeproj** project, -* an **include** directory, -* a **lib** directory. - -You are ready to compile ScummVM: open the **scummvm.xcodeproj** project, and build it. - -### Compilation from command line ### - -For jailbroken devices, it is also possible to compile the project from command line. You'll need some tools, like **ldid**, to fake the code signature. - -Open a terminal, and execute the following commands: -``` -$ cd path_to_the_scummvm_sources -$ SDKROOT=$(xcrun --sdk iphoneos --show-sdk-path) CC=clang CXX=clang++ ./configure --host=iphone --disable-scalers --disable-mt32emu --enable-release -$ make iphone -$ make iphonebundle -``` - -At the end of the compilation, you'll find a **ScummVM.app** application: copy it over SSH, and reboot your device. - -## Usage ## - -The game data files can be copied on the iOS device using iTunes. Once done, add your games in ScummVM as usual. - -Here is a list of the in-game gestures: - -|Gesture|Description| -|-------|-----------| -|Two fingers swipe down|Display the ScummVM menu for loading, saving, etc.| -|Two fingers swipe right|Enable / disable the touchpad mode| -|Two fingers swipe up|Enable / disable the mouse-click-and-drag mode| -|Two fingers tap|Simulate a right click. You should tap with one finger, and then tap with another while keeping your first finger on the screen.| -|Two fingers double-tap|Skip the cinematic / video| - -The iOS keyboard is visible when the device is in portrait mode, and hidden in landscape mode. diff --git a/backends/platform/iphone/iphone_common.h b/backends/platform/iphone/iphone_common.h index 94836dabcd..59dca84b85 100644 --- a/backends/platform/iphone/iphone_common.h +++ b/backends/platform/iphone/iphone_common.h @@ -36,8 +36,7 @@ enum InputEvent { kInputKeyPressed, kInputApplicationSuspended, kInputApplicationResumed, - kInputSwipe, - kInputTap + kInputSwipe }; enum ScreenOrientation { @@ -53,11 +52,6 @@ enum UIViewSwipeDirection { kUIViewSwipeRight = 8 }; -enum UIViewTapDescription { - kUIViewTapSingle = 1, - kUIViewTapDouble = 2 -}; - enum GraphicsModes { kGraphicsModeLinear = 0, kGraphicsModeNone = 1 diff --git a/backends/platform/iphone/iphone_keyboard.h b/backends/platform/iphone/iphone_keyboard.h index ddd8f436e5..d54df9ac96 100644 --- a/backends/platform/iphone/iphone_keyboard.h +++ b/backends/platform/iphone/iphone_keyboard.h @@ -26,7 +26,7 @@ #include #include -@interface SoftKeyboard : UIView { +@interface SoftKeyboard : UIView { id inputDelegate; UITextView *inputView; } @@ -36,9 +36,6 @@ - (void)setInputDelegate:(id)delegate; - (void)handleKeyPress:(unichar)c; -- (void)showKeyboard; -- (void)hideKeyboard; - @end #endif diff --git a/backends/platform/iphone/iphone_keyboard.mm b/backends/platform/iphone/iphone_keyboard.mm index 0588aac8ab..39d68aff81 100644 --- a/backends/platform/iphone/iphone_keyboard.mm +++ b/backends/platform/iphone/iphone_keyboard.mm @@ -43,13 +43,31 @@ self = [super initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f)]; softKeyboard = keyboard; - [self setAutocorrectionType:UITextAutocorrectionTypeNo]; - [self setAutocapitalizationType:UITextAutocapitalizationTypeNone]; - [self setEnablesReturnKeyAutomatically:NO]; + [[self textInputTraits] setAutocorrectionType:(UITextAutocorrectionType)1]; + [[self textInputTraits] setAutocapitalizationType:(UITextAutocapitalizationType)0]; + [[self textInputTraits] setEnablesReturnKeyAutomatically:NO]; return self; } +- (void) keyboardInputShouldDelete:(id)input { + [softKeyboard handleKeyPress:0x08]; +} + +- (BOOL)webView:(id)fp8 shouldInsertText:(id)character + replacingDOMRange:(id)fp16 + givenAction:(int)fp20 { + + if ([character length] != 1) { + [NSException raise:@"Unsupported" format:@"Unhandled multi-char insert!"]; + return NO; + } + + [softKeyboard handleKeyPress:[character characterAtIndex:0]]; + + return NO; +} + @end @@ -59,22 +77,9 @@ self = [super initWithFrame:frame]; inputDelegate = nil; inputView = [[TextInputHandler alloc] initWithKeyboard:self]; - inputView.delegate = self; return self; } -- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { - unichar c; - if (text.length) { - c = [text characterAtIndex:0]; - } - else { - c = '\b'; - } - [inputDelegate handleKeyPress:c]; - return YES; -} - - (UITextView *)inputView { return inputView; } @@ -87,12 +92,4 @@ [inputDelegate handleKeyPress:c]; } -- (void)showKeyboard { - [inputView becomeFirstResponder]; -} - -- (void)hideKeyboard { - [inputView endEditing:YES]; -} - @end diff --git a/backends/platform/iphone/iphone_main.mm b/backends/platform/iphone/iphone_main.mm index 02d46c1995..3707f10a29 100644 --- a/backends/platform/iphone/iphone_main.mm +++ b/backends/platform/iphone/iphone_main.mm @@ -30,21 +30,8 @@ void iphone_main(int argc, char *argv[]); -@interface ScummVMViewController : UIViewController - -@end - -@implementation ScummVMViewController - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -@end - @interface iPhoneMain : UIApplication { UIWindow *_window; - ScummVMViewController *_controller; iPhoneView *_view; } @@ -93,26 +80,19 @@ int main(int argc, char **argv) { - (void)applicationDidFinishLaunching:(UIApplication *)application { CGRect rect = [[UIScreen mainScreen] bounds]; - // Create the directory for savegames -#ifdef IPHONE_OFFICIAL - NSFileManager *fm = [NSFileManager defaultManager]; - NSString *documentPath = [NSString stringWithUTF8String:iPhone_getDocumentsDir()]; - NSString *savePath = [documentPath stringByAppendingPathComponent:@"Savegames"]; - if (![fm fileExistsAtPath:savePath]) { - [fm createDirectoryAtPath:savePath withIntermediateDirectories:YES attributes:nil error:nil]; - } -#endif + // hide the status bar + [application setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:NO]; + [application setStatusBarHidden:YES animated:YES]; _window = [[UIWindow alloc] initWithFrame:rect]; [_window retain]; - _controller = [[ScummVMViewController alloc] init]; - _view = [[iPhoneView alloc] initWithFrame:rect]; _view.multipleTouchEnabled = YES; - _controller.view = _view; - [_window setRootViewController:_controller]; + [_window setContentView:_view]; + + [_window addSubview:_view]; [_window makeKeyAndVisible]; [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; @@ -140,6 +120,12 @@ int main(int argc, char **argv) { - (void)applicationResume:(struct __GSEvent *)event { [_view applicationResume]; + + // Workaround, need to "hide" and unhide the statusbar to properly remove it, + // since the Springboard has put it back without apparently flagging our application. + [self setStatusBarHidden:YES animated:YES]; + [self setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:NO]; + [self setStatusBarHidden:YES animated:YES]; } - (void)didRotate:(NSNotification *)notification { diff --git a/backends/platform/iphone/iphone_video.h b/backends/platform/iphone/iphone_video.h index 5c9766a116..7dbf3c57ab 100644 --- a/backends/platform/iphone/iphone_video.h +++ b/backends/platform/iphone/iphone_video.h @@ -50,6 +50,8 @@ GLuint _overlayTexture; GLuint _mouseCursorTexture; + UIDeviceOrientation _orientation; + GLint _renderBufferWidth; GLint _renderBufferHeight; @@ -78,6 +80,8 @@ - (VideoContext *)getVideoContext; +- (void)drawRect:(CGRect)frame; + - (void)createScreenTexture; - (void)initSurface; - (void)setViewTransformation; diff --git a/backends/platform/iphone/iphone_video.mm b/backends/platform/iphone/iphone_video.mm index efd8ea3acf..5048b57328 100644 --- a/backends/platform/iphone/iphone_video.mm +++ b/backends/platform/iphone/iphone_video.mm @@ -26,7 +26,6 @@ #include "iphone_video.h" #include "graphics/colormasks.h" -#include "common/system.h" iPhoneView *g_iPhoneViewInstance = nil; static int g_fullWidth; @@ -39,8 +38,6 @@ static long g_lastTick = 0; static int g_frames = 0; #endif -extern bool iphone_touchpadModeEnabled(); - #define printOpenGLError() printOglError(__FILE__, __LINE__) int printOglError(const char *file, int line) { @@ -105,10 +102,8 @@ const char *iPhone_getDocumentsDir() { CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; eaglLayer.opaque = YES; - eaglLayer.drawableProperties = @{ - kEAGLDrawablePropertyRetainedBacking: @NO, - kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGB565 - }; + eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGB565, kEAGLDrawablePropertyColorFormat, nil]; _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; @@ -137,14 +132,11 @@ const char *iPhone_getDocumentsDir() { NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); return; } - uint maxValue = MAX(_renderBufferWidth, _renderBufferHeight), maxValuePOT = getSizeNextPOT(maxValue); - uint minValue = MIN(_renderBufferWidth, _renderBufferHeight), minValuePOT = getSizeNextPOT(minValue); - - _videoContext.overlayWidth = maxValue; - _videoContext.overlayHeight = minValue; - uint overlayTextureWidth = maxValuePOT; - uint overlayTextureHeight = minValuePOT; + _videoContext.overlayHeight = _renderBufferWidth; + _videoContext.overlayWidth = _renderBufferHeight; + uint overlayTextureWidth = getSizeNextPOT(_videoContext.overlayHeight); + uint overlayTextureHeight = getSizeNextPOT(_videoContext.overlayWidth); // Since the overlay size won't change the whole run, we can // precalculate the texture coordinates for the overlay texture here @@ -166,74 +158,31 @@ const char *iPhone_getDocumentsDir() { } } -- (void)setupGestureRecognizers { - UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeRight:)]; - swipeRight.direction = UISwipeGestureRecognizerDirectionRight; - swipeRight.numberOfTouchesRequired = 2; - - UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeLeft:)]; - swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft; - swipeLeft.numberOfTouchesRequired = 2; - - UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeUp:)]; - swipeUp.direction = UISwipeGestureRecognizerDirectionUp; - swipeUp.numberOfTouchesRequired = 2; - - UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeDown:)]; - swipeDown.direction = UISwipeGestureRecognizerDirectionDown; - swipeDown.numberOfTouchesRequired = 2; - - UITapGestureRecognizer *doubleTapTwoFingers = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersDoubleTap:)]; - doubleTapTwoFingers.numberOfTapsRequired = 2; - doubleTapTwoFingers.numberOfTouchesRequired = 2; - - [self addGestureRecognizer:swipeRight]; - [self addGestureRecognizer:swipeLeft]; - [self addGestureRecognizer:swipeUp]; - [self addGestureRecognizer:swipeDown]; - [self addGestureRecognizer:doubleTapTwoFingers]; -} - -- (CGFloat)optimalScale { - CGFloat screenScale = [[UIScreen mainScreen] scale]; - if (screenScale < 2) return screenScale; - - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - return 1; - } - - CGSize screenSize; - UIScreen *mainScreen = [UIScreen mainScreen]; - if ([mainScreen respondsToSelector:@selector(nativeBounds)]) { - screenSize = [mainScreen nativeBounds].size; - } - else { - screenSize = [mainScreen bounds].size; - screenSize.width *= screenScale; - screenSize.height *= screenScale; - } - CGFloat mxSize = MAX(screenSize.width, screenSize.height); - - if (mxSize <= 1136) { - // iPhone 4S / 5 / 5S / 5C - return 1; - } - else { - // iPhone 6 / 6S / 6+ / 6S+ - return 2; - } -} - - (id)initWithFrame:(struct CGRect)frame { self = [super initWithFrame: frame]; - [self setupGestureRecognizers]; - - g_fullWidth = (int)MAX(frame.size.width, frame.size.height); - g_fullHeight = (int)MIN(frame.size.width, frame.size.height); + _contentScaleFactor = 1; + if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { + if ([self respondsToSelector:@selector(setContentScaleFactor:)]) { + // Horrible and crazy method to get the proper return value of + // scale when the SDK used for building does not know anything + // about the selector scale... + NSMethodSignature *scaleSignature = [UIScreen instanceMethodSignatureForSelector:@selector(scale)]; + NSInvocation *scaleInvocation = [NSInvocation invocationWithMethodSignature:scaleSignature]; + [scaleInvocation setTarget:[UIScreen mainScreen]]; + [scaleInvocation setSelector:@selector(scale)]; + [scaleInvocation invoke]; + + NSInteger returnLength = [[scaleInvocation methodSignature] methodReturnLength]; + if (returnLength == sizeof(CGFloat)) { + [scaleInvocation getReturnValue:&_contentScaleFactor]; + [self setContentScaleFactor:_contentScaleFactor]; + } + } + } - _contentScaleFactor = [self optimalScale]; - [self setContentScaleFactor:_contentScaleFactor]; + g_fullWidth = (int)frame.size.width; + g_fullHeight = (int)frame.size.height; g_iPhoneViewInstance = self; @@ -298,8 +247,8 @@ const char *iPhone_getDocumentsDir() { [super dealloc]; } -#if 0 - (void)drawRect:(CGRect)frame { +#if 0 if (g_lastTick == 0) { g_lastTick = time(0); } @@ -310,8 +259,8 @@ const char *iPhone_getDocumentsDir() { printf("FPS: %i\n", g_frames); g_frames = 0; } -} #endif +} - (void)setFilterModeForTexture:(GLuint)tex { if (!tex) @@ -463,72 +412,69 @@ const char *iPhone_getDocumentsDir() { glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError(); } -- (void)createScreenTexture { - const uint screenTexWidth = getSizeNextPOT(_videoContext.screenWidth); - const uint screenTexHeight = getSizeNextPOT(_videoContext.screenHeight); - - _gameScreenTexCoords[2] = _gameScreenTexCoords[6] = _videoContext.screenWidth / (GLfloat)screenTexWidth; - _gameScreenTexCoords[5] = _gameScreenTexCoords[7] = _videoContext.screenHeight / (GLfloat)screenTexHeight; - - _videoContext.screenTexture.create(screenTexWidth, screenTexHeight, Graphics::createPixelFormat<565>()); -} - -- (void)initSurface { - if (_context) { - glDeleteTextures(1, &_screenTexture); printOpenGLError(); - glDeleteTextures(1, &_overlayTexture); printOpenGLError(); +- (void)setUpOrientation:(UIDeviceOrientation)orientation width:(int *)width height:(int *)height { + _orientation = orientation; - glDeleteRenderbuffersOES(1, &_viewRenderbuffer); - glDeleteFramebuffersOES(1, &_viewFramebuffer); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); - glGenFramebuffersOES(1, &_viewFramebuffer); printOpenGLError(); - glGenRenderbuffersOES(1, &_viewRenderbuffer); printOpenGLError(); + // We always force the origin (0,0) to be in the upper left corner. + switch (_orientation) { + case UIDeviceOrientationLandscapeRight: + glRotatef( 90, 0, 0, 1); printOpenGLError(); + glOrthof(0, _renderBufferHeight, _renderBufferWidth, 0, 0, 1); printOpenGLError(); - glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); printOpenGLError(); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); - [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id)self.layer]; + *width = _renderBufferHeight; + *height = _renderBufferWidth; + break; - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); + case UIDeviceOrientationLandscapeLeft: + glRotatef(-90, 0, 0, 1); printOpenGLError(); + glOrthof(0, _renderBufferHeight, _renderBufferWidth, 0, 0, 1); printOpenGLError(); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_renderBufferWidth); printOpenGLError(); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_renderBufferHeight); printOpenGLError(); - - if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { - NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); - return; - } + *width = _renderBufferHeight; + *height = _renderBufferWidth; + break; - glViewport(0, 0, _renderBufferWidth, _renderBufferHeight); printOpenGLError(); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); printOpenGLError(); + case UIDeviceOrientationPortrait: + default: + // We must force the portrait orientation here, since we might not know + // the real orientation. + _orientation = UIDeviceOrientationPortrait; - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glOrthof(0, _renderBufferWidth, _renderBufferHeight, 0, 0, 1); printOpenGLError(); - glEnable(GL_TEXTURE_2D); printOpenGLError(); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); printOpenGLError(); - glEnableClientState(GL_VERTEX_ARRAY); printOpenGLError(); + *width = _renderBufferWidth; + *height = _renderBufferHeight; + break; } +} + +- (void)createScreenTexture { + const uint screenTexWidth = getSizeNextPOT(_videoContext.screenWidth); + const uint screenTexHeight = getSizeNextPOT(_videoContext.screenHeight); - BOOL isLandscape = (self.bounds.size.width > self.bounds.size.height); // UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]); + _gameScreenTexCoords[2] = _gameScreenTexCoords[6] = _videoContext.screenWidth / (GLfloat)screenTexWidth; + _gameScreenTexCoords[5] = _gameScreenTexCoords[7] = _videoContext.screenHeight / (GLfloat)screenTexHeight; -// glMatrixMode(GL_PROJECTION); -// glLoadIdentity(); + _videoContext.screenTexture.create(screenTexWidth, screenTexHeight, Graphics::createPixelFormat<565>()); +} +- (void)initSurface { int screenWidth, screenHeight; - if (isLandscape) { - screenWidth = MAX(_renderBufferWidth, _renderBufferHeight); - screenHeight = MIN(_renderBufferWidth, _renderBufferHeight); -// glOrthof(0, screenWidth, screenHeight, 0, 0, 1); printOpenGLError(); - } - else { - screenWidth = MIN(_renderBufferWidth, _renderBufferHeight); - screenHeight = MAX(_renderBufferWidth, _renderBufferHeight); -// glOrthof(0, screenHeight, screenWidth, 0, 0, 1); printOpenGLError(); + [self setUpOrientation:[[UIDevice currentDevice] orientation] width:&screenWidth height:&screenHeight]; + + if (_screenTexture > 0) { + glDeleteTextures(1, &_screenTexture); printOpenGLError(); } glGenTextures(1, &_screenTexture); printOpenGLError(); [self setFilterModeForTexture:_screenTexture]; + if (_overlayTexture > 0) { + glDeleteTextures(1, &_overlayTexture); printOpenGLError(); + } + glGenTextures(1, &_overlayTexture); printOpenGLError(); [self setFilterModeForTexture:_overlayTexture]; @@ -536,10 +482,10 @@ const char *iPhone_getDocumentsDir() { [self clearColorBuffer]; -// if (_keyboardView != nil) { -// [_keyboardView removeFromSuperview]; -// [[_keyboardView inputView] removeFromSuperview]; -// } + if (_keyboardView != nil) { + [_keyboardView removeFromSuperview]; + [[_keyboardView inputView] removeFromSuperview]; + } GLfloat adjustedWidth = _videoContext.screenWidth; GLfloat adjustedHeight = _videoContext.screenHeight; @@ -552,7 +498,7 @@ const char *iPhone_getDocumentsDir() { float overlayPortraitRatio; - if (isLandscape) { + if (_orientation == UIDeviceOrientationLandscapeLeft || _orientation == UIDeviceOrientationLandscapeRight) { GLfloat gameScreenRatio = adjustedWidth / adjustedHeight; GLfloat screenRatio = (GLfloat)screenWidth / (GLfloat)screenHeight; @@ -578,8 +524,6 @@ const char *iPhone_getDocumentsDir() { yOffset = (screenHeight - rectHeight) / 2; } - [_keyboardView hideKeyboard]; - //printf("Rect: %i, %i, %i, %i\n", xOffset, yOffset, rectWidth, rectHeight); _gameScreenRect = CGRectMake(xOffset, yOffset, rectWidth, rectHeight); overlayPortraitRatio = 1.0f; @@ -593,13 +537,14 @@ const char *iPhone_getDocumentsDir() { if (_keyboardView == nil) { _keyboardView = [[SoftKeyboard alloc] initWithFrame:keyFrame]; [_keyboardView setInputDelegate:self]; - [self addSubview:[_keyboardView inputView]]; - [self addSubview: _keyboardView]; } - [_keyboardView showKeyboard]; + [self addSubview:[_keyboardView inputView]]; + [self addSubview: _keyboardView]; + [[_keyboardView inputView] becomeFirstResponder]; overlayPortraitRatio = (_videoContext.overlayHeight * ratio) / _videoContext.overlayWidth; } + _overlayRect = CGRectMake(0, 0, screenWidth, screenHeight * overlayPortraitRatio); _gameScreenVertCoords[0] = _gameScreenVertCoords[4] = CGRectGetMinX(_gameScreenRect); @@ -610,10 +555,6 @@ const char *iPhone_getDocumentsDir() { _overlayVertCoords[2] = _overlayVertCoords[6] = CGRectGetMaxX(_overlayRect); _overlayVertCoords[5] = _overlayVertCoords[7] = CGRectGetMaxY(_overlayRect); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrthof(0, screenWidth, screenHeight, 0, 0, 1); - [self setViewTransformation]; [self updateMouseCursorScaling]; } @@ -660,12 +601,40 @@ const char *iPhone_getDocumentsDir() { return true; } +/** + * Converts portrait mode coordinates into rotated mode coordinates. + */ +- (bool)convertToRotatedCoords:(CGPoint)point result:(CGPoint *)result { + switch (_orientation) { + case UIDeviceOrientationLandscapeLeft: + result->x = point.y; + result->y = _renderBufferWidth - point.x; + return true; + + case UIDeviceOrientationLandscapeRight: + result->x = _renderBufferHeight - point.y; + result->y = point.x; + return true; + + case UIDeviceOrientationPortrait: + result->x = point.x; + result->y = point.y; + return true; + + default: + return false; + } +} + - (bool)getMouseCoords:(CGPoint)point eventX:(int *)x eventY:(int *)y { // We scale the input according to our scale factor to get actual screen // cooridnates. point.x *= _contentScaleFactor; point.y *= _contentScaleFactor; + if (![self convertToRotatedCoords:point result:&point]) + return false; + CGRect *area; int width, height, offsetY; if (_videoContext.overlayVisible) { @@ -688,58 +657,62 @@ const char *iPhone_getDocumentsDir() { // thus we need to add it here. *y = (int)(point.y * height + offsetY); - if (!iphone_touchpadModeEnabled()) { - // Clip coordinates - if (*x < 0 || *x > width || *y < 0 || *y > height) - return false; - } + // Clip coordinates + if (*x < 0 || *x > width || *y < 0 || *y > height) + return false; return true; } - (void)deviceOrientationChanged:(UIDeviceOrientation)orientation { - [self addEvent:InternalEvent(kInputOrientationChanged, orientation, 0)]; -} + switch (orientation) { + case UIDeviceOrientationLandscapeLeft: + case UIDeviceOrientationLandscapeRight: + case UIDeviceOrientationPortrait: + _orientation = orientation; + break; -- (UITouch *)secondTouchOtherTouchThan:(UITouch *)touch in:(NSSet *)set { - NSArray *all = [set allObjects]; - for (UITouch *t in all) { - if (t != touch) { - return t; - } + default: + return; } - return nil; + + [self addEvent:InternalEvent(kInputOrientationChanged, orientation, 0)]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + NSSet *allTouches = [event allTouches]; int x, y; - NSSet *allTouches = [event allTouches]; - if (allTouches.count == 1) { - _firstTouch = [allTouches anyObject]; - CGPoint point = [_firstTouch locationInView:self]; + switch ([allTouches count]) { + case 1: { + UITouch *touch = [touches anyObject]; + CGPoint point = [touch locationInView:self]; if (![self getMouseCoords:point eventX:&x eventY:&y]) return; + _firstTouch = touch; [self addEvent:InternalEvent(kInputMouseDown, x, y)]; - } - else if (allTouches.count == 2) { - _secondTouch = [self secondTouchOtherTouchThan:_firstTouch in:allTouches]; - if (_secondTouch) { - CGPoint point = [_secondTouch locationInView:self]; - if (![self getMouseCoords:point eventX:&x eventY:&y]) - return; + break; + } + + case 2: { + UITouch *touch = [touches anyObject]; + CGPoint point = [touch locationInView:self]; + if (![self getMouseCoords:point eventX:&x eventY:&y]) + return; - [self addEvent:InternalEvent(kInputMouseSecondDown, x, y)]; + _secondTouch = touch; + [self addEvent:InternalEvent(kInputMouseSecondDown, x, y)]; + break; } } } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + //NSSet *allTouches = [event allTouches]; int x, y; - NSSet *allTouches = [event allTouches]; - for (UITouch *touch in allTouches) { + for (UITouch *touch in touches) { if (touch == _firstTouch) { CGPoint point = [touch locationInView:self]; if (![self getMouseCoords:point eventX:&x eventY:&y]) @@ -750,64 +723,55 @@ const char *iPhone_getDocumentsDir() { CGPoint point = [touch locationInView:self]; if (![self getMouseCoords:point eventX:&x eventY:&y]) return; - + [self addEvent:InternalEvent(kInputMouseSecondDragged, x, y)]; } } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + NSSet *allTouches = [event allTouches]; int x, y; - NSSet *allTouches = [event allTouches]; - if (allTouches.count == 1) { - UITouch *touch = [allTouches anyObject]; + switch ([allTouches count]) { + case 1: { + UITouch *touch = [[allTouches allObjects] objectAtIndex:0]; CGPoint point = [touch locationInView:self]; - if (![self getMouseCoords:point eventX:&x eventY:&y]) { + if (![self getMouseCoords:point eventX:&x eventY:&y]) return; - } [self addEvent:InternalEvent(kInputMouseUp, x, y)]; - } - else if (allTouches.count == 2) { + break; + } + + case 2: { UITouch *touch = [[allTouches allObjects] objectAtIndex:1]; CGPoint point = [touch locationInView:self]; if (![self getMouseCoords:point eventX:&x eventY:&y]) return; [self addEvent:InternalEvent(kInputMouseSecondUp, x, y)]; + break; + } } - _firstTouch = nil; - _secondTouch = nil; } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - _firstTouch = nil; - _secondTouch = nil; -} - -- (void)twoFingersSwipeRight:(UISwipeGestureRecognizer *)recognizer { - [self addEvent:InternalEvent(kInputSwipe, kUIViewSwipeRight, 2)]; -} - -- (void)twoFingersSwipeLeft:(UISwipeGestureRecognizer *)recognizer { - [self addEvent:InternalEvent(kInputSwipe, kUIViewSwipeLeft, 2)]; } -- (void)twoFingersSwipeUp:(UISwipeGestureRecognizer *)recognizer { - [self addEvent:InternalEvent(kInputSwipe, kUIViewSwipeUp, 2)]; +- (void)handleKeyPress:(unichar)c { + [self addEvent:InternalEvent(kInputKeyPressed, c, 0)]; } -- (void)twoFingersSwipeDown:(UISwipeGestureRecognizer *)recognizer { - [self addEvent:InternalEvent(kInputSwipe, kUIViewSwipeDown, 2)]; +- (BOOL)canHandleSwipes { + return TRUE; } -- (void)twoFingersDoubleTap:(UITapGestureRecognizer *)recognizer { - [self addEvent:InternalEvent(kInputTap, kUIViewTapDouble, 2)]; -} +- (int)swipe:(int)num withEvent:(struct __GSEvent *)event { + //printf("swipe: %i\n", num); -- (void)handleKeyPress:(unichar)c { - [self addEvent:InternalEvent(kInputKeyPressed, c, 0)]; + [self addEvent:InternalEvent(kInputSwipe, num, 0)]; + return 0; } - (void)applicationSuspend { diff --git a/backends/platform/iphone/osys_events.cpp b/backends/platform/iphone/osys_events.cpp index 19da580c80..95ca25a2d2 100644 --- a/backends/platform/iphone/osys_events.cpp +++ b/backends/platform/iphone/osys_events.cpp @@ -64,17 +64,6 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) { if (!handleEvent_mouseDragged(event, internalEvent.value1, internalEvent.value2)) return false; break; - - case kInputOrientationChanged: - handleEvent_orientationChanged(internalEvent.value1); - return false; - break; - - case kInputApplicationSuspended: - suspendLoop(); - return false; - break; - case kInputMouseSecondDragged: if (!handleEvent_mouseSecondDragged(event, internalEvent.value1, internalEvent.value2)) return false; @@ -89,25 +78,29 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) { if (!handleEvent_secondMouseUp(event, internalEvent.value1, internalEvent.value2)) return false; break; - + case kInputOrientationChanged: + handleEvent_orientationChanged(internalEvent.value1); + return false; + break; + + case kInputApplicationSuspended: + suspendLoop(); + return false; + break; + case kInputKeyPressed: handleEvent_keyPressed(event, internalEvent.value1); break; - + case kInputSwipe: - if (!handleEvent_swipe(event, internalEvent.value1, internalEvent.value2)) - return false; - break; - - case kInputTap: - if (!handleEvent_tap(event, (UIViewTapDescription) internalEvent.value1, internalEvent.value2)) + if (!handleEvent_swipe(event, internalEvent.value1)) return false; break; default: break; } - + return true; } return false; @@ -426,137 +419,71 @@ void OSystem_IPHONE::handleEvent_keyPressed(Common::Event &event, int keyPresse _queuedEventTime = getMillis() + kQueuedInputEventDelay; } -bool OSystem_IPHONE::handleEvent_swipe(Common::Event &event, int direction, int touches) { - if (touches == 1) { - Common::KeyCode keycode = Common::KEYCODE_INVALID; - switch (_screenOrientation) { - case kScreenOrientationPortrait: - switch ((UIViewSwipeDirection)direction) { - case kUIViewSwipeUp: - keycode = Common::KEYCODE_UP; - break; - case kUIViewSwipeDown: - keycode = Common::KEYCODE_DOWN; - break; - case kUIViewSwipeLeft: - keycode = Common::KEYCODE_LEFT; - break; - case kUIViewSwipeRight: - keycode = Common::KEYCODE_RIGHT; - break; - default: - return false; - } +bool OSystem_IPHONE::handleEvent_swipe(Common::Event &event, int direction) { + Common::KeyCode keycode = Common::KEYCODE_INVALID; + switch (_screenOrientation) { + case kScreenOrientationPortrait: + switch ((UIViewSwipeDirection)direction) { + case kUIViewSwipeUp: + keycode = Common::KEYCODE_UP; break; - case kScreenOrientationLandscape: - switch ((UIViewSwipeDirection)direction) { - case kUIViewSwipeUp: - keycode = Common::KEYCODE_LEFT; - break; - case kUIViewSwipeDown: - keycode = Common::KEYCODE_RIGHT; - break; - case kUIViewSwipeLeft: - keycode = Common::KEYCODE_DOWN; - break; - case kUIViewSwipeRight: - keycode = Common::KEYCODE_UP; - break; - default: - return false; - } + case kUIViewSwipeDown: + keycode = Common::KEYCODE_DOWN; break; - case kScreenOrientationFlippedLandscape: - switch ((UIViewSwipeDirection)direction) { - case kUIViewSwipeUp: - keycode = Common::KEYCODE_RIGHT; - break; - case kUIViewSwipeDown: - keycode = Common::KEYCODE_LEFT; - break; - case kUIViewSwipeLeft: - keycode = Common::KEYCODE_UP; - break; - case kUIViewSwipeRight: - keycode = Common::KEYCODE_DOWN; - break; - default: - return false; - } + case kUIViewSwipeLeft: + keycode = Common::KEYCODE_LEFT; break; - } - - event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode; - event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0; - event.type = Common::EVENT_KEYDOWN; - _queuedInputEvent.type = Common::EVENT_KEYUP; - event.kbd.flags = _queuedInputEvent.kbd.flags = 0; - _queuedEventTime = getMillis() + kQueuedInputEventDelay; - - return true; - } - else if (touches == 2) { - switch ((UIViewSwipeDirection)direction) { - case kUIViewSwipeUp: { - _mouseClickAndDragEnabled = !_mouseClickAndDragEnabled; - const char *dialogMsg; - if (_mouseClickAndDragEnabled) { - _touchpadModeEnabled = false; - dialogMsg = _("Mouse-click-and-drag mode enabled."); - } else - dialogMsg = _("Mouse-click-and-drag mode disabled."); - GUI::TimedMessageDialog dialog(dialogMsg, 1500); - dialog.runModal(); + case kUIViewSwipeRight: + keycode = Common::KEYCODE_RIGHT; + break; + default: return false; } - - case kUIViewSwipeDown: { - // Swipe down - event.type = Common::EVENT_MAINMENU; - _queuedInputEvent.type = Common::EVENT_INVALID; - _queuedEventTime = getMillis() + kQueuedInputEventDelay; - return true; - } - - case kUIViewSwipeRight: { - // Swipe right - _touchpadModeEnabled = !_touchpadModeEnabled; - const char *dialogMsg; - if (_touchpadModeEnabled) - dialogMsg = _("Touchpad mode enabled."); - else - dialogMsg = _("Touchpad mode disabled."); - GUI::TimedMessageDialog dialog(dialogMsg, 1500); - dialog.runModal(); + break; + case kScreenOrientationLandscape: + switch ((UIViewSwipeDirection)direction) { + case kUIViewSwipeUp: + keycode = Common::KEYCODE_LEFT; + break; + case kUIViewSwipeDown: + keycode = Common::KEYCODE_RIGHT; + break; + case kUIViewSwipeLeft: + keycode = Common::KEYCODE_DOWN; + break; + case kUIViewSwipeRight: + keycode = Common::KEYCODE_UP; + break; + default: return false; } - - default: + break; + case kScreenOrientationFlippedLandscape: + switch ((UIViewSwipeDirection)direction) { + case kUIViewSwipeUp: + keycode = Common::KEYCODE_RIGHT; break; + case kUIViewSwipeDown: + keycode = Common::KEYCODE_LEFT; + break; + case kUIViewSwipeLeft: + keycode = Common::KEYCODE_UP; + break; + case kUIViewSwipeRight: + keycode = Common::KEYCODE_DOWN; + break; + default: + return false; } + break; } - return false; -} -bool OSystem_IPHONE::handleEvent_tap(Common::Event &event, UIViewTapDescription type, int touches) { - if (touches == 1) { - if (type == kUIViewTapDouble) { - event.type = Common::EVENT_RBUTTONDOWN; - _queuedInputEvent.type = Common::EVENT_RBUTTONUP; - _queuedEventTime = getMillis() + kQueuedInputEventDelay; - return true; - } - } - else if (touches == 2) { - if (type == kUIViewTapDouble) { - event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE; - event.type = Common::EVENT_KEYDOWN; - _queuedInputEvent.type = Common::EVENT_KEYUP; - event.kbd.flags = _queuedInputEvent.kbd.flags = 0; - _queuedEventTime = getMillis() + kQueuedInputEventDelay; - return true; - } - } - return false; + event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode; + event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0; + event.type = Common::EVENT_KEYDOWN; + _queuedInputEvent.type = Common::EVENT_KEYUP; + event.kbd.flags = _queuedInputEvent.kbd.flags = 0; + _queuedEventTime = getMillis() + kQueuedInputEventDelay; + + return true; } diff --git a/backends/platform/iphone/osys_main.cpp b/backends/platform/iphone/osys_main.cpp index ef3499d597..0ce21b44c1 100644 --- a/backends/platform/iphone/osys_main.cpp +++ b/backends/platform/iphone/osys_main.cpp @@ -38,8 +38,6 @@ #include "backends/saves/default/default-saves.h" #include "backends/timer/default/default-timer.h" -#include "backends/fs/chroot/chroot-fs-factory.h" -#include "backends/fs/posix/posix-fs.h" #include "audio/mixer.h" #include "audio/mixer_intern.h" @@ -65,11 +63,7 @@ OSystem_IPHONE::OSystem_IPHONE() : _mouseCursorPaletteEnabled(false), _gfxTransactionError(kTransactionSuccess) { _queuedInputEvent.type = Common::EVENT_INVALID; _touchpadModeEnabled = !iPhone_isHighResDevice(); -#ifdef IPHONE_OFFICIAL - _fsFactory = new ChRootFilesystemFactory(iPhone_getDocumentsDir()); -#else _fsFactory = new POSIXFilesystemFactory(); -#endif initVideoContext(); memset(_gamePalette, 0, sizeof(_gamePalette)); @@ -89,10 +83,6 @@ OSystem_IPHONE::~OSystem_IPHONE() { _mouseBuffer.free(); } -bool OSystem_IPHONE::touchpadModeEnabled() const { - return _touchpadModeEnabled; -} - int OSystem_IPHONE::timerHandler(int t) { DefaultTimerManager *tm = (DefaultTimerManager *)g_system->getTimerManager(); tm->handler(); @@ -101,7 +91,7 @@ int OSystem_IPHONE::timerHandler(int t) { void OSystem_IPHONE::initBackend() { #ifdef IPHONE_OFFICIAL - _savefileManager = new DefaultSaveFileManager("/Savegames"); + _savefileManager = new DefaultSaveFileManager(iPhone_getDocumentsDir()); #else _savefileManager = new DefaultSaveFileManager(SCUMMVM_SAVE_PATH); #endif @@ -263,7 +253,8 @@ OSystem *OSystem_IPHONE_create() { Common::String OSystem_IPHONE::getDefaultConfigFileName() { #ifdef IPHONE_OFFICIAL - Common::String path = "/Preferences"; + Common::String path = iPhone_getDocumentsDir(); + path += "/Preferences"; return path; #else return SCUMMVM_PREFS_PATH; @@ -279,14 +270,7 @@ void OSystem_IPHONE::addSysArchivesToSearchSet(Common::SearchSet &s, int priorit if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf))) { // Success: Add it to the search path Common::String bundlePath((const char *)buf); -#ifdef IPHONE_OFFICIAL - POSIXFilesystemNode *posixNode = new POSIXFilesystemNode(bundlePath); - Common::FSNode *node = new Common::FSNode(posixNode); - s.add("__OSX_BUNDLE__", new Common::FSDirectory(*node), priority); -#else - // OS X s.add("__OSX_BUNDLE__", new Common::FSDirectory(bundlePath), priority); -#endif } CFRelease(fileUrl); } @@ -304,11 +288,6 @@ void OSystem_IPHONE::logMessage(LogMessageType::Type type, const char *message) fflush(output); } -bool iphone_touchpadModeEnabled() { - OSystem_IPHONE *sys = (OSystem_IPHONE *) g_system; - return sys && sys->touchpadModeEnabled(); -} - void iphone_main(int argc, char *argv[]) { //OSystem_IPHONE::migrateApp(); diff --git a/backends/platform/iphone/osys_main.h b/backends/platform/iphone/osys_main.h index 04a531613f..0159eee1be 100644 --- a/backends/platform/iphone/osys_main.h +++ b/backends/platform/iphone/osys_main.h @@ -131,8 +131,6 @@ public: virtual int16 getHeight(); virtual int16 getWidth(); - bool touchpadModeEnabled() const; - #ifdef USE_RGB_COLOR virtual Graphics::PixelFormat getScreenFormat() const { return _framebuffer.format; } virtual Common::List getSupportedFormats() const; @@ -206,8 +204,7 @@ protected: static void AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB); static int timerHandler(int t); - bool handleEvent_swipe(Common::Event &event, int direction, int touches); - bool handleEvent_tap(Common::Event &event, UIViewTapDescription type, int touches); + bool handleEvent_swipe(Common::Event &event, int direction); void handleEvent_keyPressed(Common::Event &event, int keyPressed); void handleEvent_orientationChanged(int orientation); -- cgit v1.2.3