From 68937edbe03472b2f11a236fd7b76b472a5a47ea Mon Sep 17 00:00:00 2001 From: Edgar J San Martin <29460583+ej-sanmartin@users.noreply.github.com> Date: Mon, 17 Nov 2025 19:01:05 -0500 Subject: [PATCH 1/3] Implement modern vibration API for iOS with CHHapticEngine. --- src/common/ios.h | 6 +++-- src/common/ios.mm | 48 ++++++++++++++++++++++++++++++++++- src/modules/system/System.cpp | 2 +- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/common/ios.h b/src/common/ios.h index 39eb6b141..b98f76e33 100644 --- a/src/common/ios.h +++ b/src/common/ios.h @@ -43,9 +43,11 @@ namespace ios std::string getLoveInResources(bool &fused); /** - * Causes devices with vibration support to vibrate for about 0.5 seconds. + * Causes devices with vibration support to vibrate for the specified duration. + * On iOS 13+, uses Core Haptics for precise duration control. + * On iOS < 13, falls back to legacy 0.5 seconds of vibration. **/ -void vibrate(); +void vibrate(double seconds); /** * Enable mix mode (e.g. with background music apps) and playback with a muted device. diff --git a/src/common/ios.mm b/src/common/ios.mm index 7cf2d3d7d..7f1ca0a73 100644 --- a/src/common/ios.mm +++ b/src/common/ios.mm @@ -30,6 +30,7 @@ #import #import +#import #include "modules/audio/Audio.h" @@ -364,10 +365,55 @@ - (void)applicationBecameActive:(NSNotification *)note return path; } -void vibrate() +void vibrate(double seconds) { @autoreleasepool { + if (@available(iOS 13.0, *)) + { + NSError *error = nil; + CHHapticEngine *engine = [[CHHapticEngine alloc] + initAndReturnError:&error]; + + if (engine != nil) + { + [engine startAndReturnError:nil]; + + NSDictionary *hapticDict = @{ + CHHapticPatternKeyEvent: @[@{ + CHHapticPatternKeyEventType: + CHHapticEventTypeHapticContinuous, + CHHapticPatternKeyTime: @0.0, + CHHapticPatternKeyEventDuration: @(seconds), + CHHapticPatternKeyEventParameters: @[ + @{ + CHHapticPatternKeyParameterID: + CHHapticEventParameterIDHapticIntensity, + CHHapticPatternKeyParameterValue: @1.0 + }, + @{ + CHHapticPatternKeyParameterID: + CHHapticEventParameterIDHapticSharpness, + CHHapticPatternKeyParameterValue: @0.5 + } + ] + }] + }; + + CHHapticPattern *pattern = [[CHHapticPattern alloc] + initWithDictionary:hapticDict error:nil]; + + if (pattern != nil) + { + id player = + [engine createPlayerWithPattern:pattern error:nil]; + [player startAtTime:0 error:nil]; + return; // Success - haptic playing. + } + } + } + + // Fallback: iOS < 13 or Core Haptics unavailable. AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); } } diff --git a/src/modules/system/System.cpp b/src/modules/system/System.cpp index 19e763176..dc529350a 100644 --- a/src/modules/system/System.cpp +++ b/src/modules/system/System.cpp @@ -62,7 +62,7 @@ void System::vibrate(double seconds) const #ifdef LOVE_ANDROID love::android::vibrate(seconds); #elif defined(LOVE_IOS) - love::ios::vibrate(); + love::ios::vibrate(seconds); #else LOVE_UNUSED(seconds); #endif From cc4b60ce6a95dcba545bdbbc13ab96fef808a765 Mon Sep 17 00:00:00 2001 From: Edgar J San Martin <29460583+ej-sanmartin@users.noreply.github.com> Date: Mon, 17 Nov 2025 19:06:48 -0500 Subject: [PATCH 2/3] Clarify CHHapticPatternKeyParameterID configs. --- src/common/ios.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/ios.mm b/src/common/ios.mm index 7f1ca0a73..5c6fa4a05 100644 --- a/src/common/ios.mm +++ b/src/common/ios.mm @@ -408,7 +408,7 @@ void vibrate(double seconds) id player = [engine createPlayerWithPattern:pattern error:nil]; [player startAtTime:0 error:nil]; - return; // Success - haptic playing. + return; } } } From fbb0c7f1a208f5635b908489a57f46a06eda537f Mon Sep 17 00:00:00 2001 From: Edgar J San Martin <29460583+ej-sanmartin@users.noreply.github.com> Date: Mon, 17 Nov 2025 19:13:03 -0500 Subject: [PATCH 3/3] Clarify CHHapticPatternKeyParameterID configs. Comments added. --- src/common/ios.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/ios.mm b/src/common/ios.mm index 5c6fa4a05..857fdc84f 100644 --- a/src/common/ios.mm +++ b/src/common/ios.mm @@ -386,11 +386,13 @@ void vibrate(double seconds) CHHapticPatternKeyTime: @0.0, CHHapticPatternKeyEventDuration: @(seconds), CHHapticPatternKeyEventParameters: @[ + // Correlates to Android's default high intensity vibration. @{ CHHapticPatternKeyParameterID: CHHapticEventParameterIDHapticIntensity, CHHapticPatternKeyParameterValue: @1.0 }, + // Medium sharpness, 0.0 is dull rumble while 1.0 is crisp tap. @{ CHHapticPatternKeyParameterID: CHHapticEventParameterIDHapticSharpness,