diff --git a/cmake/Platform.cmake b/cmake/Platform.cmake index e88b01d74..46441bf57 100644 --- a/cmake/Platform.cmake +++ b/cmake/Platform.cmake @@ -27,11 +27,12 @@ if (GEODE_TARGET_PLATFORM STREQUAL "iOS") ) target_link_libraries(${PROJECT_NAME} INTERFACE - "-framework OpenGLES" # needed for CCClippingNode reimpl and ScrollLayer - "-framework UIKit" # needed for file picking (UIApplication) - "-framework Foundation" # needed for many things - "-framework AVFoundation" # needed for microphone access - "-framework CoreGraphics" # needed for image saving + "-framework OpenGLES" # needed for CCClippingNode reimpl and ScrollLayer + "-framework UIKit" # needed for file picking (UIApplication) + "-framework Foundation" # needed for many things + "-framework AVFoundation" # needed for microphone access + "-framework CoreGraphics" # needed for image saving + "-framework GameController" # needed for controller input ${GEODE_LOADER_PATH}/include/link/ios/libcares.a ${GEODE_LOADER_PATH}/include/link/ios/libcurl.a ${GEODE_LOADER_PATH}/include/link/ios/libnghttp2.a diff --git a/loader/src/cocos2d-ext/CCKeyboardDispatcher.cpp b/loader/src/cocos2d-ext/CCKeyboardDispatcher.cpp index a2bdc80b1..c98db10b2 100644 --- a/loader/src/cocos2d-ext/CCKeyboardDispatcher.cpp +++ b/loader/src/cocos2d-ext/CCKeyboardDispatcher.cpp @@ -134,6 +134,7 @@ bool CCKeyboardDispatcher::dispatchKeyboardMSG(enumKeyCodes key, bool isKeyDown, { delegate->keyUp(key, timestamp); } + break; } m_bUnknown38 = false; diff --git a/loader/src/platform/ios/input.mm b/loader/src/platform/ios/input.mm index 979dfd1b8..1b162d226 100644 --- a/loader/src/platform/ios/input.mm +++ b/loader/src/platform/ios/input.mm @@ -9,6 +9,7 @@ #include #include #include +#include using namespace geode::prelude; @@ -149,6 +150,29 @@ static enumKeyCodes keyToKeyCode(int code) { } } +static enumKeyCodes buttonToKeyCode(GCExtendedGamepad* pad, GCControllerButtonInput* btn) { + if (btn == pad.buttonA) return enumKeyCodes::CONTROLLER_A; + if (btn == pad.buttonB) return enumKeyCodes::CONTROLLER_B; + if (btn == pad.buttonX) return enumKeyCodes::CONTROLLER_X; + if (btn == pad.buttonY) return enumKeyCodes::CONTROLLER_Y; + + if (btn == pad.leftShoulder) return enumKeyCodes::CONTROLLER_LB; + if (btn == pad.rightShoulder) return enumKeyCodes::CONTROLLER_RB; + + if (btn == pad.leftTrigger) return enumKeyCodes::CONTROLLER_LT; + if (btn == pad.rightTrigger) return enumKeyCodes::CONTROLLER_RT; + + if (btn == pad.dpad.up) return enumKeyCodes::CONTROLLER_Up; + if (btn == pad.dpad.down) return enumKeyCodes::CONTROLLER_Down; + if (btn == pad.dpad.left) return enumKeyCodes::CONTROLLER_Left; + if (btn == pad.dpad.right) return enumKeyCodes::CONTROLLER_Right; + + if (btn == pad.buttonOptions) return enumKeyCodes::CONTROLLER_Back; + if (btn == pad.buttonMenu) return enumKeyCodes::CONTROLLER_Start; + + return enumKeyCodes::KEY_Unknown; +} + @implementation UIWindow (KeyInterceptor) - (void)handleKeyDown:(UIEvent*) event withPress:(UIPress*) press withTime:(double) timestamp withRepeat:(bool) isRepeat { @@ -182,7 +206,7 @@ KeyboardInputData data( modifiers ); - auto res = KeyboardInputEvent(keyCode).send(data); + if (KeyboardInputEvent(keyCode).send(data) != ListenerResult::Propagate) return; isDown = data.action != KeyboardInputData::Action::Release; isRepeat = data.action == KeyboardInputData::Action::Repeat; @@ -234,7 +258,7 @@ KeyboardInputData data( modifiers ); - auto res = KeyboardInputEvent(keyCode).send(data); + if (KeyboardInputEvent(keyCode).send(data) != ListenerResult::Propagate) return; isDown = data.action != KeyboardInputData::Action::Release; isRepeat = data.action == KeyboardInputData::Action::Repeat; @@ -322,10 +346,67 @@ - (void)g_sendEvent:(UIEvent*)event { [self g_sendEvent:event]; } +inline void handleControllerButton(GCExtendedGamepad* gamepad, GCControllerButtonInput* btn) { + CCIMEDispatcher* imeDispatcher = CCIMEDispatcher::sharedDispatcher(); + CCKeyboardDispatcher* keyboardDispatcher = CCKeyboardDispatcher::get(); + enumKeyCodes key = buttonToKeyCode(gamepad, btn); + KeyboardInputData data( + key, + [btn isPressed] ? KeyboardInputData::Action::Press : KeyboardInputData::Action::Release, + {0}, // Controller buttons don't have native codes. + (double) [gamepad lastEventTimestamp], + KeyboardModifier::None + ); + if (KeyboardInputEvent(key).send(data) != ListenerResult::Propagate) return; + if (data.key != KEY_Unknown && (!imeDispatcher->hasDelegate() || data.key == KEY_Escape || data.key == KEY_Enter)) { + keyboardDispatcher->dispatchKeyboardMSG(data.key, data.action != KeyboardInputData::Action::Release, data.action == KeyboardInputData::Action::Repeat, data.timestamp); + } +} + $execute { Method m1 = class_getInstanceMethod([UIWindow class], @selector(sendEvent:)); Method m2 = class_getInstanceMethod([UIWindow class], @selector(g_sendEvent:)); method_exchangeImplementations(m1, m2); + + [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidConnectNotification object:nil queue:nil usingBlock:^(NSNotification* note) { + GCController* controller = [note object]; + if (![controller extendedGamepad]) return; + GCExtendedGamepad* pad = [controller extendedGamepad]; + pad.valueChangedHandler = ^(GCExtendedGamepad* gamepad, GCControllerElement* element) { + if ([element isKindOfClass:[GCControllerButtonInput class]]) { + handleControllerButton(gamepad, (GCControllerButtonInput*) element); + } else if ([element isKindOfClass:[GCControllerDirectionPad class]]) { + if (element == [pad dpad]) { + static BOOL prevUp, prevDown, prevLeft, prevRight; + bool upPressed = [[[pad dpad] up] isPressed]; + bool downPressed = [[[pad dpad] down] isPressed]; + bool leftPressed = [[[pad dpad] left] isPressed]; + bool rightPressed = [[[pad dpad] right] isPressed]; + if (upPressed != prevUp) { + auto btn = [[pad dpad] up]; + handleControllerButton(gamepad, btn); + prevUp = upPressed; + } + if (downPressed != prevDown) { + auto btn = [[pad dpad] down]; + handleControllerButton(gamepad, btn); + prevDown = downPressed; + } + if (leftPressed != prevLeft) { + auto btn = [[pad dpad] left]; + handleControllerButton(gamepad, btn); + prevLeft = leftPressed; + } + if (rightPressed != prevRight) { + auto btn = [[pad dpad] right]; + handleControllerButton(gamepad, btn); + prevRight = rightPressed; + } + } + } + }; + + }]; } @end \ No newline at end of file