diff options
Diffstat (limited to 'platform/ios')
| -rw-r--r-- | platform/ios/SCsub | 2 | ||||
| -rw-r--r-- | platform/ios/detect.py | 12 | ||||
| -rw-r--r-- | platform/ios/display_layer.h | 3 | ||||
| -rw-r--r-- | platform/ios/display_layer.mm | 29 | ||||
| -rw-r--r-- | platform/ios/display_server_ios.h | 10 | ||||
| -rw-r--r-- | platform/ios/display_server_ios.mm | 98 | ||||
| -rw-r--r-- | platform/ios/export/export_plugin.cpp | 7 | ||||
| -rw-r--r-- | platform/ios/godot_view.h | 5 | ||||
| -rw-r--r-- | platform/ios/godot_view.mm | 98 | ||||
| -rw-r--r-- | platform/ios/godot_view_gesture_recognizer.mm | 186 | ||||
| -rw-r--r-- | platform/ios/joypad_ios.mm | 19 | ||||
| -rw-r--r-- | platform/ios/key_mapping_ios.h (renamed from platform/ios/godot_view_gesture_recognizer.h) | 24 | ||||
| -rw-r--r-- | platform/ios/key_mapping_ios.mm | 186 | ||||
| -rw-r--r-- | platform/ios/keyboard_input_view.mm | 18 | ||||
| -rw-r--r-- | platform/ios/view_controller.mm | 59 |
15 files changed, 414 insertions, 342 deletions
diff --git a/platform/ios/SCsub b/platform/ios/SCsub index bf12ab6dd7..18ba6617af 100644 --- a/platform/ios/SCsub +++ b/platform/ios/SCsub @@ -17,9 +17,9 @@ ios_lib = [ "display_layer.mm", "godot_app_delegate.m", "godot_view_renderer.mm", - "godot_view_gesture_recognizer.mm", "device_metrics.m", "keyboard_input_view.mm", + "key_mapping_ios.mm", ] env_ios = env.Clone() diff --git a/platform/ios/detect.py b/platform/ios/detect.py index 38e62134b5..71612cf1fa 100644 --- a/platform/ios/detect.py +++ b/platform/ios/detect.py @@ -99,8 +99,8 @@ def configure(env: "Environment"): if env["ios_simulator"]: detect_darwin_sdk_path("iossimulator", env) - env.Append(ASFLAGS=["-mios-simulator-version-min=13.0"]) - env.Append(CCFLAGS=["-mios-simulator-version-min=13.0"]) + env.Append(ASFLAGS=["-mios-simulator-version-min=11.0"]) + env.Append(CCFLAGS=["-mios-simulator-version-min=11.0"]) env.extra_suffix = ".simulator" + env.extra_suffix else: detect_darwin_sdk_path("ios", env) @@ -153,3 +153,11 @@ def configure(env: "Environment"): if env["vulkan"]: env.Append(CPPDEFINES=["VULKAN_ENABLED"]) + + if env["opengl3"]: + env.Append(CPPDEFINES=["GLES3_ENABLED"]) + env.Prepend( + CPPPATH=[ + "$IOS_SDK_PATH/System/Library/Frameworks/OpenGLES.framework/Headers", + ] + ) diff --git a/platform/ios/display_layer.h b/platform/ios/display_layer.h index 10f42264df..e719a42cd9 100644 --- a/platform/ios/display_layer.h +++ b/platform/ios/display_layer.h @@ -33,7 +33,8 @@ @protocol DisplayLayer <NSObject> -- (void)renderDisplayLayer; +- (void)startRenderDisplayLayer; +- (void)stopRenderDisplayLayer; - (void)initializeDisplayLayer; - (void)layoutDisplayLayer; diff --git a/platform/ios/display_layer.mm b/platform/ios/display_layer.mm index 24614fea56..3129ebb276 100644 --- a/platform/ios/display_layer.mm +++ b/platform/ios/display_layer.mm @@ -60,7 +60,10 @@ - (void)layoutDisplayLayer { } -- (void)renderDisplayLayer { +- (void)startRenderDisplayLayer { +} + +- (void)stopRenderDisplayLayer { } @end @@ -76,8 +79,6 @@ } - (void)initializeDisplayLayer { - // Get our backing layer - // Configure it so that it is opaque, does not retain the contents of the backbuffer when displayed, and uses RGBA8888 color. self.opaque = YES; self.drawableProperties = [NSDictionary @@ -87,8 +88,6 @@ kEAGLDrawablePropertyColorFormat, nil]; - // FIXME: Add Vulkan support via MoltenVK. Add fallback code back? - // Create GL ES 3 context if (GLOBAL_GET("rendering/renderer/rendering_method") == "gl_compatibility") { context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; @@ -115,8 +114,22 @@ [self createFramebuffer]; } -- (void)renderDisplayLayer { +- (void)startRenderDisplayLayer { [EAGLContext setCurrentContext:context]; + + glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); +} + +- (void)stopRenderDisplayLayer { + glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); + [context presentRenderbuffer:GL_RENDERBUFFER_OES]; + +#ifdef DEBUG_ENABLED + GLenum err = glGetError(); + if (err) { + NSLog(@"DrawView: %x error", err); + } +#endif } - (void)dealloc { @@ -154,11 +167,15 @@ return NO; } + GLES3::TextureStorage::system_fbo = viewFramebuffer; + return YES; } // Clean up any buffers we have allocated. - (void)destroyFramebuffer { + GLES3::TextureStorage::system_fbo = 0; + glDeleteFramebuffersOES(1, &viewFramebuffer); viewFramebuffer = 0; glDeleteRenderbuffersOES(1, &viewRenderbuffer); diff --git a/platform/ios/display_server_ios.h b/platform/ios/display_server_ios.h index dd1157f668..6eaa7c8edc 100644 --- a/platform/ios/display_server_ios.h +++ b/platform/ios/display_server_ios.h @@ -47,6 +47,10 @@ #endif #endif +#if defined(GLES3_ENABLED) +#include "drivers/gles3/rasterizer_gles3.h" +#endif // GLES3_ENABLED + #import <Foundation/Foundation.h> #import <QuartzCore/CAMetalLayer.h> @@ -109,11 +113,12 @@ public: void touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click); void touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y, float p_pressure, Vector2 p_tilt); - void touches_cancelled(int p_idx); + void touches_canceled(int p_idx); // MARK: Keyboard - void key(Key p_key, char32_t p_char, bool p_pressed); + void key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed); + bool is_keyboard_active() const; // MARK: Motion @@ -216,6 +221,7 @@ public: virtual bool screen_is_kept_on() const override; void resize_window(CGSize size); + virtual void swap_buffers() override {} }; #endif // DISPLAY_SERVER_IOS_H diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm index bea88a7f9b..469bc9be17 100644 --- a/platform/ios/display_server_ios.mm +++ b/platform/ios/display_server_ios.mm @@ -36,6 +36,7 @@ #import "device_metrics.h" #import "godot_view.h" #include "ios.h" +#import "key_mapping_ios.h" #import "keyboard_input_view.h" #include "os_ios.h" #include "tts_ios.h" @@ -50,52 +51,14 @@ DisplayServerIOS *DisplayServerIOS::get_singleton() { } DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) { + KeyMappingIOS::initialize(); + rendering_driver = p_rendering_driver; // Init TTS tts = [[TTS_IOS alloc] init]; -#if defined(GLES3_ENABLED) - // FIXME: Add support for both OpenGL and Vulkan when OpenGL is implemented - // again, - // Note that we should be checking "opengl3" as the driver, might never enable this seeing OpenGL is deprecated on iOS - // We are hardcoding the rendering_driver to "vulkan" down below - - if (rendering_driver == "opengl3") { - bool gl_initialization_error = false; - - // FIXME: Add Vulkan support via MoltenVK. Add fallback code back? - - if (RasterizerGLES3::is_viable() == OK) { - RasterizerGLES3::register_config(); - RasterizerGLES3::make_current(); - } else { - gl_initialization_error = true; - } - - if (gl_initialization_error) { - OS::get_singleton()->alert("Your device does not support any of the supported OpenGL versions.", "Unable to initialize video driver"); - // return ERR_UNAVAILABLE; - } - - // rendering_server = memnew(RenderingServerDefault); - // // FIXME: Reimplement threaded rendering - // if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - // rendering_server = memnew(RenderingServerWrapMT(rendering_server, - // false)); - // } - // rendering_server->init(); - // rendering_server->cursor_set_visible(false, 0); - - // reset this to what it should be, it will have been set to 0 after - // rendering_server->init() is called - // RasterizerStorageGLES3system_fbo = gl_view_base_fb; - } -#endif - #if defined(VULKAN_ENABLED) - rendering_driver = "vulkan"; - context_vulkan = nullptr; rendering_device_vulkan = nullptr; @@ -110,13 +73,14 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode CALayer *layer = [AppDelegate.viewController.godotView initializeRenderingForDriver:@"vulkan"]; if (!layer) { - ERR_FAIL_MSG("Failed to create iOS rendering layer."); + ERR_FAIL_MSG("Failed to create iOS Vulkan rendering layer."); } Size2i size = Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_max_scale(); if (context_vulkan->window_create(MAIN_WINDOW_ID, p_vsync_mode, layer, size.width, size.height) != OK) { memdelete(context_vulkan); context_vulkan = nullptr; + r_error = ERR_UNAVAILABLE; ERR_FAIL_MSG("Failed to create Vulkan window."); } @@ -127,6 +91,18 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode } #endif +#if defined(GLES3_ENABLED) + if (rendering_driver == "opengl3") { + CALayer *layer = [AppDelegate.viewController.godotView initializeRenderingForDriver:@"opengl3"]; + + if (!layer) { + ERR_FAIL_MSG("Failed to create iOS OpenGLES rendering layer."); + } + + RasterizerGLES3::make_current(); + } +#endif + bool keep_screen_on = bool(GLOBAL_GET("display/window/energy_saving/keep_screen_on")); screen_set_keep_on(keep_screen_on); @@ -252,20 +228,35 @@ void DisplayServerIOS::perform_event(const Ref<InputEvent> &p_event) { Input::get_singleton()->parse_input_event(p_event); } -void DisplayServerIOS::touches_cancelled(int p_idx) { +void DisplayServerIOS::touches_canceled(int p_idx) { touch_press(p_idx, -1, -1, false, false); } // MARK: Keyboard -void DisplayServerIOS::key(Key p_key, char32_t p_char, bool p_pressed) { +void DisplayServerIOS::key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed) { Ref<InputEventKey> ev; ev.instantiate(); ev->set_echo(false); ev->set_pressed(p_pressed); - ev->set_keycode(p_key); - ev->set_physical_keycode(p_key); - ev->set_unicode(p_char); + ev->set_keycode(fix_keycode(p_char, p_key)); + if (@available(iOS 13.4, *)) { + if (p_key != Key::SHIFT) { + ev->set_shift_pressed(p_modifier & UIKeyModifierShift); + } + if (p_key != Key::CTRL) { + ev->set_ctrl_pressed(p_modifier & UIKeyModifierControl); + } + if (p_key != Key::ALT) { + ev->set_alt_pressed(p_modifier & UIKeyModifierAlternate); + } + if (p_key != Key::META) { + ev->set_meta_pressed(p_modifier & UIKeyModifierCommand); + } + } + ev->set_key_label(p_unshifted); + ev->set_physical_keycode(p_physical); + ev->set_unicode(fix_unicode(p_char)); perform_event(ev); } @@ -643,6 +634,10 @@ void DisplayServerIOS::virtual_keyboard_show(const String &p_existing_text, cons cursorEnd:_convert_utf32_offset_to_utf16(p_existing_text, p_cursor_end)]; } +bool DisplayServerIOS::is_keyboard_active() const { + return [AppDelegate.viewController.keyboardView isFirstResponder]; +} + void DisplayServerIOS::virtual_keyboard_hide() { [AppDelegate.viewController.keyboardView resignFirstResponder]; } @@ -689,15 +684,18 @@ void DisplayServerIOS::resize_window(CGSize viewSize) { void DisplayServerIOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { _THREAD_SAFE_METHOD_ #if defined(VULKAN_ENABLED) - context_vulkan->set_vsync_mode(p_window, p_vsync_mode); + if (context_vulkan) { + context_vulkan->set_vsync_mode(p_window, p_vsync_mode); + } #endif } DisplayServer::VSyncMode DisplayServerIOS::window_get_vsync_mode(WindowID p_window) const { _THREAD_SAFE_METHOD_ #if defined(VULKAN_ENABLED) - return context_vulkan->get_vsync_mode(p_window); -#else - return DisplayServer::VSYNC_ENABLED; + if (context_vulkan) { + return context_vulkan->get_vsync_mode(p_window); + } #endif + return DisplayServer::VSYNC_ENABLED; } diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp index ccd3480d11..c6f7ec09b1 100644 --- a/platform/ios/export/export_plugin.cpp +++ b/platform/ios/export/export_plugin.cpp @@ -43,6 +43,7 @@ void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const { // Vulkan and OpenGL ES 3.0 both mandate ETC2 support. r_features->push_back("etc2"); + r_features->push_back("astc"); Vector<String> architectures = _get_preset_architectures(p_preset); for (int i = 0; i < architectures.size(); ++i) { @@ -1572,7 +1573,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p int ret = unzGoToFirstFile(src_pkg_zip); Vector<uint8_t> project_file_data; while (ret == UNZ_OK) { -#if defined(MACOS_ENABLED) || defined(X11_ENABLED) +#if defined(MACOS_ENABLED) || defined(LINUXBSD_ENABLED) bool is_execute = false; #endif @@ -1605,7 +1606,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p continue; //ignore! } found_library = true; -#if defined(MACOS_ENABLED) || defined(X11_ENABLED) +#if defined(MACOS_ENABLED) || defined(LINUXBSD_ENABLED) is_execute = true; #endif file = file.replace(library_to_use, binary_name + ".xcframework"); @@ -1648,7 +1649,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p f->store_buffer(data.ptr(), data.size()); } -#if defined(MACOS_ENABLED) || defined(X11_ENABLED) +#if defined(MACOS_ENABLED) || defined(LINUXBSD_ENABLED) if (is_execute) { // we need execute rights on this file chmod(file.utf8().get_data(), 0755); diff --git a/platform/ios/godot_view.h b/platform/ios/godot_view.h index 077584baa6..b00ca37ebe 100644 --- a/platform/ios/godot_view.h +++ b/platform/ios/godot_view.h @@ -59,9 +59,4 @@ class String; - (void)stopRendering; - (void)startRendering; -- (void)godotTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; - @end diff --git a/platform/ios/godot_view.mm b/platform/ios/godot_view.mm index 1c8c578bd2..fafec79bf6 100644 --- a/platform/ios/godot_view.mm +++ b/platform/ios/godot_view.mm @@ -35,7 +35,6 @@ #include "core/string/ustring.h" #import "display_layer.h" #include "display_server_ios.h" -#import "godot_view_gesture_recognizer.h" #import "godot_view_renderer.h" #import <CoreMotion/CoreMotion.h> @@ -60,8 +59,6 @@ static const float earth_gravity = 9.80665; @property(strong, nonatomic) CMMotionManager *motionManager; -@property(strong, nonatomic) GodotViewGestureRecognizer *delayGestureRecognizer; - @end @implementation GodotView @@ -74,16 +71,20 @@ static const float earth_gravity = 9.80665; CALayer<DisplayLayer> *layer; if ([driverName isEqualToString:@"vulkan"]) { +#if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR + if (@available(iOS 13, *)) { + layer = [GodotMetalLayer layer]; + } else { + return nil; + } +#else layer = [GodotMetalLayer layer]; +#endif } else if ([driverName isEqualToString:@"opengl3"]) { if (@available(iOS 13, *)) { NSLog(@"OpenGL ES is deprecated on iOS 13"); } -#if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR - return nil; -#else layer = [GodotOpenGLLayer layer]; -#endif } else { return nil; } @@ -144,10 +145,6 @@ static const float earth_gravity = 9.80665; [self.animationTimer invalidate]; self.animationTimer = nil; } - - if (self.delayGestureRecognizer) { - self.delayGestureRecognizer = nil; - } } - (void)godot_commonInit { @@ -167,11 +164,6 @@ static const float earth_gravity = 9.80665; self.motionManager = nil; } } - - // Initialize delay gesture recognizer - GodotViewGestureRecognizer *gestureRecognizer = [[GodotViewGestureRecognizer alloc] init]; - self.delayGestureRecognizer = gestureRecognizer; - [self addGestureRecognizer:self.delayGestureRecognizer]; } - (void)stopRendering { @@ -238,7 +230,7 @@ static const float earth_gravity = 9.80665; [self.displayLink setPaused:NO]; } - [self.renderingLayer renderDisplayLayer]; + [self.renderingLayer startRenderDisplayLayer]; if (!self.renderer) { return; @@ -258,6 +250,8 @@ static const float earth_gravity = 9.80665; [self handleMotion]; [self.renderer renderOnView:self]; + + [self.renderingLayer stopRenderDisplayLayer]; } - (BOOL)canRender { @@ -341,58 +335,42 @@ static const float earth_gravity = 9.80665; } } -- (void)godotTouchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touchesSet containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - CGPoint touchPoint = [touch locationInView:self]; - DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1); - } +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in touches) { + int tid = [self getTouchIDForTouch:touch]; + ERR_FAIL_COND(tid == -1); + CGPoint touchPoint = [touch locationInView:self]; + DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1); } } -- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touches containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - CGPoint touchPoint = [touch locationInView:self]; - CGPoint prev_point = [touch previousLocationInView:self]; - CGFloat alt = [touch altitudeAngle]; - CGVector azim = [touch azimuthUnitVectorInView:self]; - DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt)); - } +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in touches) { + int tid = [self getTouchIDForTouch:touch]; + ERR_FAIL_COND(tid == -1); + CGPoint touchPoint = [touch locationInView:self]; + CGPoint prev_point = [touch previousLocationInView:self]; + CGFloat alt = [touch altitudeAngle]; + CGVector azim = [touch azimuthUnitVectorInView:self]; + DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt)); } } -- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touches containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - [self removeTouch:touch]; - CGPoint touchPoint = [touch locationInView:self]; - DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false); - } +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in touches) { + int tid = [self getTouchIDForTouch:touch]; + ERR_FAIL_COND(tid == -1); + [self removeTouch:touch]; + CGPoint touchPoint = [touch locationInView:self]; + DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false); } } -- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touches containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - DisplayServerIOS::get_singleton()->touches_cancelled(tid); - } +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in touches) { + int tid = [self getTouchIDForTouch:touch]; + ERR_FAIL_COND(tid == -1); + DisplayServerIOS::get_singleton()->touches_canceled(tid); } [self clearTouches]; } diff --git a/platform/ios/godot_view_gesture_recognizer.mm b/platform/ios/godot_view_gesture_recognizer.mm deleted file mode 100644 index 9b71228864..0000000000 --- a/platform/ios/godot_view_gesture_recognizer.mm +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************/ -/* godot_view_gesture_recognizer.mm */ -/**************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/**************************************************************************/ -/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/**************************************************************************/ - -#import "godot_view_gesture_recognizer.h" - -#import "godot_view.h" - -#include "core/config/project_settings.h" - -// Minimum distance for touches to move to fire -// a delay timer before scheduled time. -// Should be the low enough to not cause issues with dragging -// but big enough to allow click to work. -const CGFloat kGLGestureMovementDistance = 0.5; - -@interface GodotViewGestureRecognizer () - -@property(nonatomic, readwrite, assign) NSTimeInterval delayTimeInterval; - -@end - -@interface GodotViewGestureRecognizer () - -// Timer used to delay begin touch message. -// Should work as simple emulation of UIDelayedAction -@property(strong, nonatomic) NSTimer *delayTimer; - -// Delayed touch parameters -@property(strong, nonatomic) NSSet *delayedTouches; -@property(strong, nonatomic) UIEvent *delayedEvent; - -@end - -@implementation GodotViewGestureRecognizer - -- (GodotView *)godotView { - return (GodotView *)self.view; -} - -- (instancetype)init { - self = [super init]; - - self.cancelsTouchesInView = YES; - self.delaysTouchesBegan = YES; - self.delaysTouchesEnded = YES; - self.requiresExclusiveTouchType = NO; - - self.delayTimeInterval = GLOBAL_GET("input_devices/pointing/ios/touch_delay"); - - return self; -} - -- (void)dealloc { - if (self.delayTimer) { - [self.delayTimer invalidate]; - self.delayTimer = nil; - } - - if (self.delayedTouches) { - self.delayedTouches = nil; - } - - if (self.delayedEvent) { - self.delayedEvent = nil; - } -} - -- (void)delayTouches:(NSSet *)touches andEvent:(UIEvent *)event { - [self.delayTimer fire]; - - self.delayedTouches = touches; - self.delayedEvent = event; - - self.delayTimer = [NSTimer - scheduledTimerWithTimeInterval:self.delayTimeInterval - target:self - selector:@selector(fireDelayedTouches:) - userInfo:nil - repeats:NO]; -} - -- (void)fireDelayedTouches:(id)timer { - [self.delayTimer invalidate]; - self.delayTimer = nil; - - if (self.delayedTouches) { - [self.godotView godotTouchesBegan:self.delayedTouches withEvent:self.delayedEvent]; - } - - self.delayedTouches = nil; - self.delayedEvent = nil; -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseBegan]; - [self delayTouches:cleared andEvent:event]; - - [super touchesBegan:touches withEvent:event]; -} - -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseMoved]; - - if (self.delayTimer) { - // We should check if movement was significant enough to fire an event - // for dragging to work correctly. - for (UITouch *touch in cleared) { - CGPoint from = [touch locationInView:self.godotView]; - CGPoint to = [touch previousLocationInView:self.godotView]; - CGFloat xDistance = from.x - to.x; - CGFloat yDistance = from.y - to.y; - - CGFloat distance = sqrt(xDistance * xDistance + yDistance * yDistance); - - // Early exit, since one of touches has moved enough to fire a drag event. - if (distance > kGLGestureMovementDistance) { - [self.delayTimer fire]; - [self.godotView godotTouchesMoved:cleared withEvent:event]; - return; - } - } - - return; - } - - [self.godotView godotTouchesMoved:cleared withEvent:event]; - - [super touchesMoved:touches withEvent:event]; -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - [self.delayTimer fire]; - - NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseEnded]; - [self.godotView godotTouchesEnded:cleared withEvent:event]; - - [super touchesEnded:touches withEvent:event]; -} - -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - [self.delayTimer fire]; - [self.godotView godotTouchesCancelled:touches withEvent:event]; - - [super touchesCancelled:touches withEvent:event]; -} - -- (NSSet *)copyClearedTouches:(NSSet *)touches phase:(UITouchPhase)phaseToSave { - NSMutableSet *cleared = [touches mutableCopy]; - - for (UITouch *touch in touches) { - if (touch.view != self.view || touch.phase != phaseToSave) { - [cleared removeObject:touch]; - } - } - - return cleared; -} - -@end diff --git a/platform/ios/joypad_ios.mm b/platform/ios/joypad_ios.mm index 057f439b81..9194b09ef6 100644 --- a/platform/ios/joypad_ios.mm +++ b/platform/ios/joypad_ios.mm @@ -305,6 +305,25 @@ void JoypadIOS::start_processing() { float value = gamepad.rightTrigger.value; Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_RIGHT, value); } + + if (@available(iOS 13, *)) { + // iOS uses 'buttonOptions' and 'buttonMenu' names for BACK and START joy buttons. + if (element == gamepad.buttonOptions) { + Input::get_singleton()->joy_button(joy_id, JoyButton::BACK, + gamepad.buttonOptions.isPressed); + } else if (element == gamepad.buttonMenu) { + Input::get_singleton()->joy_button(joy_id, JoyButton::START, + gamepad.buttonMenu.isPressed); + } + } + + if (@available(iOS 14, *)) { + // iOS uses 'buttonHome' for the GUIDE joy button. + if (element == gamepad.buttonHome) { + Input::get_singleton()->joy_button(joy_id, JoyButton::GUIDE, + gamepad.buttonHome.isPressed); + } + } }; } else if (controller.microGamepad != nil) { // micro gamepads were added in OS 9 and feature just 2 buttons and a d-pad diff --git a/platform/ios/godot_view_gesture_recognizer.h b/platform/ios/key_mapping_ios.h index 57bfc75568..6cc61175bb 100644 --- a/platform/ios/godot_view_gesture_recognizer.h +++ b/platform/ios/key_mapping_ios.h @@ -1,5 +1,5 @@ /**************************************************************************/ -/* godot_view_gesture_recognizer.h */ +/* key_mapping_ios.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,19 +28,19 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -// GLViewGestureRecognizer allows iOS gestures to work correctly by -// emulating UIScrollView's UIScrollViewDelayedTouchesBeganGestureRecognizer. -// It catches all gestures incoming to UIView and delays them for 150ms -// (the same value used by UIScrollViewDelayedTouchesBeganGestureRecognizer) -// If touch cancellation or end message is fired it fires delayed -// begin touch immediately as well as last touch signal +#ifndef KEY_MAPPING_IOS_H +#define KEY_MAPPING_IOS_H -#import <UIKit/UIKit.h> +#include "core/os/keyboard.h" -@interface GodotViewGestureRecognizer : UIGestureRecognizer +#import <UIKit/UIKit.h> -@property(nonatomic, readonly, assign) NSTimeInterval delayTimeInterval; +class KeyMappingIOS { + KeyMappingIOS() {} -- (instancetype)init; +public: + static void initialize(); + static Key remap_key(CFIndex p_keycode); +}; -@end +#endif // KEY_MAPPING_IOS_H diff --git a/platform/ios/key_mapping_ios.mm b/platform/ios/key_mapping_ios.mm new file mode 100644 index 0000000000..c378186778 --- /dev/null +++ b/platform/ios/key_mapping_ios.mm @@ -0,0 +1,186 @@ +/**************************************************************************/ +/* key_mapping_ios.mm */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "key_mapping_ios.h" + +#include "core/templates/hash_map.h" + +struct HashMapHasherKeys { + static _FORCE_INLINE_ uint32_t hash(const Key p_key) { return hash_fmix32(static_cast<uint32_t>(p_key)); } + static _FORCE_INLINE_ uint32_t hash(const CFIndex p_key) { return hash_fmix32(p_key); } +}; + +HashMap<CFIndex, Key, HashMapHasherKeys> keyusage_map; + +void KeyMappingIOS::initialize() { + if (@available(iOS 13.4, *)) { + keyusage_map[UIKeyboardHIDUsageKeyboardA] = Key::A; + keyusage_map[UIKeyboardHIDUsageKeyboardB] = Key::B; + keyusage_map[UIKeyboardHIDUsageKeyboardC] = Key::C; + keyusage_map[UIKeyboardHIDUsageKeyboardD] = Key::D; + keyusage_map[UIKeyboardHIDUsageKeyboardE] = Key::E; + keyusage_map[UIKeyboardHIDUsageKeyboardF] = Key::F; + keyusage_map[UIKeyboardHIDUsageKeyboardG] = Key::G; + keyusage_map[UIKeyboardHIDUsageKeyboardH] = Key::H; + keyusage_map[UIKeyboardHIDUsageKeyboardI] = Key::I; + keyusage_map[UIKeyboardHIDUsageKeyboardJ] = Key::J; + keyusage_map[UIKeyboardHIDUsageKeyboardK] = Key::K; + keyusage_map[UIKeyboardHIDUsageKeyboardL] = Key::L; + keyusage_map[UIKeyboardHIDUsageKeyboardM] = Key::M; + keyusage_map[UIKeyboardHIDUsageKeyboardN] = Key::N; + keyusage_map[UIKeyboardHIDUsageKeyboardO] = Key::O; + keyusage_map[UIKeyboardHIDUsageKeyboardP] = Key::P; + keyusage_map[UIKeyboardHIDUsageKeyboardQ] = Key::Q; + keyusage_map[UIKeyboardHIDUsageKeyboardR] = Key::R; + keyusage_map[UIKeyboardHIDUsageKeyboardS] = Key::S; + keyusage_map[UIKeyboardHIDUsageKeyboardT] = Key::T; + keyusage_map[UIKeyboardHIDUsageKeyboardU] = Key::U; + keyusage_map[UIKeyboardHIDUsageKeyboardV] = Key::V; + keyusage_map[UIKeyboardHIDUsageKeyboardW] = Key::W; + keyusage_map[UIKeyboardHIDUsageKeyboardX] = Key::X; + keyusage_map[UIKeyboardHIDUsageKeyboardY] = Key::Y; + keyusage_map[UIKeyboardHIDUsageKeyboardZ] = Key::Z; + keyusage_map[UIKeyboardHIDUsageKeyboard0] = Key::KEY_0; + keyusage_map[UIKeyboardHIDUsageKeyboard1] = Key::KEY_1; + keyusage_map[UIKeyboardHIDUsageKeyboard2] = Key::KEY_2; + keyusage_map[UIKeyboardHIDUsageKeyboard3] = Key::KEY_3; + keyusage_map[UIKeyboardHIDUsageKeyboard4] = Key::KEY_4; + keyusage_map[UIKeyboardHIDUsageKeyboard5] = Key::KEY_5; + keyusage_map[UIKeyboardHIDUsageKeyboard6] = Key::KEY_6; + keyusage_map[UIKeyboardHIDUsageKeyboard7] = Key::KEY_7; + keyusage_map[UIKeyboardHIDUsageKeyboard8] = Key::KEY_8; + keyusage_map[UIKeyboardHIDUsageKeyboard9] = Key::KEY_9; + keyusage_map[UIKeyboardHIDUsageKeyboardBackslash] = Key::BACKSLASH; + keyusage_map[UIKeyboardHIDUsageKeyboardCloseBracket] = Key::BRACKETRIGHT; + keyusage_map[UIKeyboardHIDUsageKeyboardComma] = Key::COMMA; + keyusage_map[UIKeyboardHIDUsageKeyboardEqualSign] = Key::EQUAL; + keyusage_map[UIKeyboardHIDUsageKeyboardHyphen] = Key::MINUS; + keyusage_map[UIKeyboardHIDUsageKeyboardNonUSBackslash] = Key::SECTION; + keyusage_map[UIKeyboardHIDUsageKeyboardNonUSPound] = Key::ASCIITILDE; + keyusage_map[UIKeyboardHIDUsageKeyboardOpenBracket] = Key::BRACKETLEFT; + keyusage_map[UIKeyboardHIDUsageKeyboardPeriod] = Key::PERIOD; + keyusage_map[UIKeyboardHIDUsageKeyboardQuote] = Key::QUOTEDBL; + keyusage_map[UIKeyboardHIDUsageKeyboardSemicolon] = Key::SEMICOLON; + keyusage_map[UIKeyboardHIDUsageKeyboardSeparator] = Key::SECTION; + keyusage_map[UIKeyboardHIDUsageKeyboardSlash] = Key::SLASH; + keyusage_map[UIKeyboardHIDUsageKeyboardSpacebar] = Key::SPACE; + keyusage_map[UIKeyboardHIDUsageKeyboardCapsLock] = Key::CAPSLOCK; + keyusage_map[UIKeyboardHIDUsageKeyboardLeftAlt] = Key::ALT; + keyusage_map[UIKeyboardHIDUsageKeyboardLeftControl] = Key::CTRL; + keyusage_map[UIKeyboardHIDUsageKeyboardLeftShift] = Key::SHIFT; + keyusage_map[UIKeyboardHIDUsageKeyboardRightAlt] = Key::ALT; + keyusage_map[UIKeyboardHIDUsageKeyboardRightControl] = Key::CTRL; + keyusage_map[UIKeyboardHIDUsageKeyboardRightShift] = Key::SHIFT; + keyusage_map[UIKeyboardHIDUsageKeyboardScrollLock] = Key::SCROLLLOCK; + keyusage_map[UIKeyboardHIDUsageKeyboardLeftArrow] = Key::LEFT; + keyusage_map[UIKeyboardHIDUsageKeyboardRightArrow] = Key::RIGHT; + keyusage_map[UIKeyboardHIDUsageKeyboardUpArrow] = Key::UP; + keyusage_map[UIKeyboardHIDUsageKeyboardDownArrow] = Key::DOWN; + keyusage_map[UIKeyboardHIDUsageKeyboardPageUp] = Key::PAGEUP; + keyusage_map[UIKeyboardHIDUsageKeyboardPageDown] = Key::PAGEDOWN; + keyusage_map[UIKeyboardHIDUsageKeyboardHome] = Key::HOME; + keyusage_map[UIKeyboardHIDUsageKeyboardEnd] = Key::END; + keyusage_map[UIKeyboardHIDUsageKeyboardDeleteForward] = Key::KEY_DELETE; + keyusage_map[UIKeyboardHIDUsageKeyboardDeleteOrBackspace] = Key::BACKSPACE; + keyusage_map[UIKeyboardHIDUsageKeyboardEscape] = Key::ESCAPE; + keyusage_map[UIKeyboardHIDUsageKeyboardInsert] = Key::INSERT; + keyusage_map[UIKeyboardHIDUsageKeyboardReturn] = Key::ENTER; + keyusage_map[UIKeyboardHIDUsageKeyboardTab] = Key::TAB; + keyusage_map[UIKeyboardHIDUsageKeyboardF1] = Key::F1; + keyusage_map[UIKeyboardHIDUsageKeyboardF2] = Key::F2; + keyusage_map[UIKeyboardHIDUsageKeyboardF3] = Key::F3; + keyusage_map[UIKeyboardHIDUsageKeyboardF4] = Key::F4; + keyusage_map[UIKeyboardHIDUsageKeyboardF5] = Key::F5; + keyusage_map[UIKeyboardHIDUsageKeyboardF6] = Key::F6; + keyusage_map[UIKeyboardHIDUsageKeyboardF7] = Key::F7; + keyusage_map[UIKeyboardHIDUsageKeyboardF8] = Key::F8; + keyusage_map[UIKeyboardHIDUsageKeyboardF9] = Key::F9; + keyusage_map[UIKeyboardHIDUsageKeyboardF10] = Key::F10; + keyusage_map[UIKeyboardHIDUsageKeyboardF11] = Key::F11; + keyusage_map[UIKeyboardHIDUsageKeyboardF12] = Key::F12; + keyusage_map[UIKeyboardHIDUsageKeyboardF13] = Key::F13; + keyusage_map[UIKeyboardHIDUsageKeyboardF14] = Key::F14; + keyusage_map[UIKeyboardHIDUsageKeyboardF15] = Key::F15; + keyusage_map[UIKeyboardHIDUsageKeyboardF16] = Key::F16; + keyusage_map[UIKeyboardHIDUsageKeyboardF17] = Key::F17; + keyusage_map[UIKeyboardHIDUsageKeyboardF18] = Key::F18; + keyusage_map[UIKeyboardHIDUsageKeyboardF19] = Key::F19; + keyusage_map[UIKeyboardHIDUsageKeyboardF20] = Key::F20; + keyusage_map[UIKeyboardHIDUsageKeyboardF21] = Key::F21; + keyusage_map[UIKeyboardHIDUsageKeyboardF22] = Key::F22; + keyusage_map[UIKeyboardHIDUsageKeyboardF23] = Key::F23; + keyusage_map[UIKeyboardHIDUsageKeyboardF24] = Key::F24; + keyusage_map[UIKeyboardHIDUsageKeypad0] = Key::KP_0; + keyusage_map[UIKeyboardHIDUsageKeypad1] = Key::KP_1; + keyusage_map[UIKeyboardHIDUsageKeypad2] = Key::KP_2; + keyusage_map[UIKeyboardHIDUsageKeypad3] = Key::KP_3; + keyusage_map[UIKeyboardHIDUsageKeypad4] = Key::KP_4; + keyusage_map[UIKeyboardHIDUsageKeypad5] = Key::KP_5; + keyusage_map[UIKeyboardHIDUsageKeypad6] = Key::KP_6; + keyusage_map[UIKeyboardHIDUsageKeypad7] = Key::KP_7; + keyusage_map[UIKeyboardHIDUsageKeypad8] = Key::KP_8; + keyusage_map[UIKeyboardHIDUsageKeypad9] = Key::KP_9; + keyusage_map[UIKeyboardHIDUsageKeypadAsterisk] = Key::KP_MULTIPLY; + keyusage_map[UIKeyboardHIDUsageKeyboardGraveAccentAndTilde] = Key::BAR; + keyusage_map[UIKeyboardHIDUsageKeypadEnter] = Key::KP_ENTER; + keyusage_map[UIKeyboardHIDUsageKeypadHyphen] = Key::KP_SUBTRACT; + keyusage_map[UIKeyboardHIDUsageKeypadNumLock] = Key::NUMLOCK; + keyusage_map[UIKeyboardHIDUsageKeypadPeriod] = Key::KP_PERIOD; + keyusage_map[UIKeyboardHIDUsageKeypadPlus] = Key::KP_ADD; + keyusage_map[UIKeyboardHIDUsageKeypadSlash] = Key::KP_DIVIDE; + keyusage_map[UIKeyboardHIDUsageKeyboardPause] = Key::PAUSE; + keyusage_map[UIKeyboardHIDUsageKeyboardStop] = Key::STOP; + keyusage_map[UIKeyboardHIDUsageKeyboardMute] = Key::VOLUMEMUTE; + keyusage_map[UIKeyboardHIDUsageKeyboardVolumeUp] = Key::VOLUMEUP; + keyusage_map[UIKeyboardHIDUsageKeyboardVolumeDown] = Key::VOLUMEDOWN; + keyusage_map[UIKeyboardHIDUsageKeyboardFind] = Key::SEARCH; + keyusage_map[UIKeyboardHIDUsageKeyboardHelp] = Key::HELP; + keyusage_map[UIKeyboardHIDUsageKeyboardLeftGUI] = Key::META; + keyusage_map[UIKeyboardHIDUsageKeyboardRightGUI] = Key::META; + keyusage_map[UIKeyboardHIDUsageKeyboardMenu] = Key::MENU; + keyusage_map[UIKeyboardHIDUsageKeyboardPrintScreen] = Key::PRINT; + keyusage_map[UIKeyboardHIDUsageKeyboardReturnOrEnter] = Key::ENTER; + keyusage_map[UIKeyboardHIDUsageKeyboardSysReqOrAttention] = Key::SYSREQ; + keyusage_map[0x01AE] = Key::KEYBOARD; // On-screen keyboard key on smart connector keyboard. + keyusage_map[0x029D] = Key::GLOBE; // "Globe" key on smart connector / Mac keyboard. + keyusage_map[UIKeyboardHIDUsageKeyboardLANG1] = Key::JIS_EISU; + keyusage_map[UIKeyboardHIDUsageKeyboardLANG2] = Key::JIS_KANA; + } +} + +Key KeyMappingIOS::remap_key(CFIndex p_keycode) { + if (@available(iOS 13.4, *)) { + const Key *key = keyusage_map.getptr(p_keycode); + if (key) { + return *key; + } + } + return Key::NONE; +} diff --git a/platform/ios/keyboard_input_view.mm b/platform/ios/keyboard_input_view.mm index f40db48ee3..2764403d68 100644 --- a/platform/ios/keyboard_input_view.mm +++ b/platform/ios/keyboard_input_view.mm @@ -115,8 +115,8 @@ - (void)deleteText:(NSInteger)charactersToDelete { for (int i = 0; i < charactersToDelete; i++) { - DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, true); - DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, false); + DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, true); + DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, false); } } @@ -134,20 +134,10 @@ key = Key::ENTER; } else if (character == 0x2006) { key = Key::SPACE; - } else if (character == U'¥') { - key = Key::YEN; - } else if (character == U'§') { - key = Key::SECTION; - } else if (character >= 0x20 && character <= 0x7E) { // ASCII. - if (character > 0x60 && character < 0x7B) { // Lowercase ASCII. - key = (Key)(character - 32); - } else { - key = (Key)character; - } } - DisplayServerIOS::get_singleton()->key(key, character, true); - DisplayServerIOS::get_singleton()->key(key, character, false); + DisplayServerIOS::get_singleton()->key(key, character, key, Key::NONE, 0, true); + DisplayServerIOS::get_singleton()->key(key, character, key, Key::NONE, 0, false); } } diff --git a/platform/ios/view_controller.mm b/platform/ios/view_controller.mm index b787ed6709..a5aba201d7 100644 --- a/platform/ios/view_controller.mm +++ b/platform/ios/view_controller.mm @@ -33,6 +33,7 @@ #include "display_server_ios.h" #import "godot_view.h" #import "godot_view_renderer.h" +#import "key_mapping_ios.h" #import "keyboard_input_view.h" #include "os_ios.h" @@ -54,6 +55,64 @@ return (GodotView *)self.view; } +- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event { + [super pressesBegan:presses withEvent:event]; + + if (!DisplayServerIOS::get_singleton() || DisplayServerIOS::get_singleton()->is_keyboard_active()) { + return; + } + if (@available(iOS 13.4, *)) { + for (UIPress *press in presses) { + String u32lbl = String::utf8([press.key.charactersIgnoringModifiers UTF8String]); + String u32text = String::utf8([press.key.characters UTF8String]); + Key key = KeyMappingIOS::remap_key(press.key.keyCode); + + if (press.key.keyCode == 0 && u32text.is_empty() && u32lbl.is_empty()) { + continue; + } + + char32_t us = 0; + if (!u32lbl.is_empty() && !u32lbl.begins_with("UIKey")) { + us = u32lbl[0]; + } + + if (!u32text.is_empty() && !u32text.begins_with("UIKey")) { + for (int i = 0; i < u32text.length(); i++) { + const char32_t c = u32text[i]; + DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), c, fix_key_label(us, key), key, press.key.modifierFlags, true); + } + } else { + DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, true); + } + } + } +} + +- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event { + [super pressesEnded:presses withEvent:event]; + + if (!DisplayServerIOS::get_singleton() || DisplayServerIOS::get_singleton()->is_keyboard_active()) { + return; + } + if (@available(iOS 13.4, *)) { + for (UIPress *press in presses) { + String u32lbl = String::utf8([press.key.charactersIgnoringModifiers UTF8String]); + Key key = KeyMappingIOS::remap_key(press.key.keyCode); + + if (press.key.keyCode == 0 && u32lbl.is_empty()) { + continue; + } + + char32_t us = 0; + if (!u32lbl.is_empty() && !u32lbl.begins_with("UIKey")) { + us = u32lbl[0]; + } + + DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, false); + } + } +} + - (void)loadView { GodotView *view = [[GodotView alloc] init]; GodotViewRenderer *renderer = [[GodotViewRenderer alloc] init]; |