iOS: stronger haptics, obey strength setting

fixes #15625
This commit is contained in:
Eric Warmenhoven committed 2025-11-01 12:14:58 -04:00
1 parent 683899e5dc
commit 357fce853e
2 files changed
+119 -11

No files matched your search

+105 -5
View File
@@ -29,6 +29,7 @@
#include "../../retroarch.h"
#include "../../driver.h"
#include "../../configuration.h"
#include "../drivers_keyboard/keyboard_event_apple.h"
#include "../../ui/drivers/cocoa/cocoa_common.h"
@@ -41,6 +42,9 @@ static CMMotionManager *motionManager;
#ifdef HAVE_MFI
#import <GameController/GameController.h>
#endif
#if TARGET_OS_IOS
#import <CoreHaptics/CoreHaptics.h>
#endif
#if TARGET_OS_IPHONE
#define HIDKEY(X) X
@@ -72,6 +76,10 @@ float cocoa_screen_get_backing_scale_factor(void);
static bool small_keyboard_active = false;
static icade_map_t icade_maps[MAX_ICADE_PROFILES][MAX_ICADE_KEYS];
#if TARGET_OS_IOS
#define KEYPRESS_HAPTIC_AVAIL API_AVAILABLE(ios(14.0))
static CHHapticEngine *keypressHapticEngine KEYPRESS_HAPTIC_AVAIL;
static id<CHHapticPatternPlayer> keypressHapticPlayer KEYPRESS_HAPTIC_AVAIL;
/* Fallback for iOS 10-13 */
static UISelectionFeedbackGenerator *feedbackGenerator;
#endif
#endif
@@ -379,9 +387,39 @@ static void *cocoa_input_init(const char *joypad_driver)
#endif
#if TARGET_OS_IOS
if (!feedbackGenerator)
feedbackGenerator = [[UISelectionFeedbackGenerator alloc] init];
[feedbackGenerator prepare];
if (@available(iOS 14, *))
{
if (!keypressHapticEngine && CHHapticEngine.capabilitiesForHardware.supportsHaptics)
{
NSError *error;
keypressHapticEngine = [[CHHapticEngine alloc] initAndReturnError:&error];
if (!error)
{
[keypressHapticEngine startAndReturnError:&error];
if (!error)
{
keypressHapticEngine.stoppedHandler = ^(CHHapticEngineStoppedReason reason) {
keypressHapticPlayer = nil;
keypressHapticEngine = nil;
};
keypressHapticEngine.resetHandler = ^{
if (keypressHapticEngine)
[keypressHapticEngine startAndReturnError:nil];
};
}
}
}
}
else
{
/* Fallback for iOS 10-13 */
if (@available(iOS 10, *))
{
if (!feedbackGenerator)
feedbackGenerator = [[UISelectionFeedbackGenerator alloc] init];
[feedbackGenerator prepare];
}
}
#endif
/* TODO/FIXME - shouldn't we free the above in case this fails for
@@ -861,8 +899,70 @@ static float cocoa_input_get_sensor_input(void *data, unsigned port, unsigned id
#if TARGET_OS_IOS
static void cocoa_input_keypress_vibrate(void)
{
[feedbackGenerator selectionChanged];
[feedbackGenerator prepare];
if (@available(iOS 14, *))
{
settings_t *settings = config_get_ptr();
if (!settings || !keypressHapticEngine)
return;
NSError *error;
unsigned rumble_gain = settings->uints.input_rumble_gain;
float intensity = (float)rumble_gain / 100.0f;
/* Create player on first use */
if (!keypressHapticPlayer)
{
CHHapticEventParameter *intense;
CHHapticEventParameter *sharp;
CHHapticEvent *event;
CHHapticPattern *pattern;
intense = [[CHHapticEventParameter alloc]
initWithParameterID:CHHapticEventParameterIDHapticIntensity
value:intensity];
sharp = [[CHHapticEventParameter alloc]
initWithParameterID:CHHapticEventParameterIDHapticSharpness
value:1.0];
event = [[CHHapticEvent alloc]
initWithEventType:CHHapticEventTypeHapticTransient
parameters:[NSArray arrayWithObjects:intense, sharp, nil]
relativeTime:0];
pattern = [[CHHapticPattern alloc]
initWithEvents:[NSArray arrayWithObject:event]
parameters:[[NSArray alloc] init]
error:&error];
if (error)
return;
keypressHapticPlayer = [keypressHapticEngine createPlayerWithPattern:pattern error:&error];
if (error)
return;
}
else
{
/* Update intensity for existing player */
CHHapticDynamicParameter *param = [[CHHapticDynamicParameter alloc]
initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl
value:intensity
relativeTime:0];
[keypressHapticPlayer sendParameters:[NSArray arrayWithObject:param] atTime:0 error:&error];
}
[keypressHapticPlayer startAtTime:0 error:&error];
}
else
{
/* Fallback for iOS 10-13 */
if (@available(iOS 10, *))
{
if (feedbackGenerator)
{
[feedbackGenerator selectionChanged];
[feedbackGenerator prepare];
}
}
}
}
#endif
+14 -6
View File
@@ -50,7 +50,7 @@ static uint32_t mfi_buttons[MAX_USERS];
static int16_t mfi_axes[MAX_USERS][MAX_MFI_AXES];
static uint32_t mfi_controllers[MAX_MFI_CONTROLLERS];
static MFIRumbleController *mfi_rumblers[MAX_MFI_CONTROLLERS];
#define MFI_WEAK_RUMBLE 0.3f
#define MFI_WEAK_RUMBLE 0.5f
static NSMutableArray *mfiControllers;
static bool mfi_inited;
@@ -372,12 +372,17 @@ static void mfi_joypad_autodetect_add(unsigned autoconf_pad, const char *display
CHHapticEvent *event;
CHHapticPattern *pattern;
CHHapticEventParameter *sharp;
intense = [[CHHapticEventParameter alloc]
initWithParameterID:CHHapticEventParameterIDHapticIntensity
value:intensity];
sharp = [[CHHapticEventParameter alloc]
initWithParameterID:CHHapticEventParameterIDHapticSharpness
value:1.0];
event = [[CHHapticEvent alloc]
initWithEventType:CHHapticEventTypeHapticContinuous
parameters:[NSArray arrayWithObjects:intense, nil]
parameters:[NSArray arrayWithObjects:intense, sharp, nil]
relativeTime:0
duration:GCHapticDurationInfinite];
pattern = [[CHHapticPattern alloc]
@@ -573,12 +578,17 @@ static id<CHHapticPatternPlayer> apple_gamecontroller_device_haptics_create_play
CHHapticPattern *pattern;
NSError *error;
CHHapticEventParameter *sharp;
intense = [[CHHapticEventParameter alloc]
initWithParameterID:CHHapticEventParameterIDHapticIntensity
value:intensity];
sharp = [[CHHapticEventParameter alloc]
initWithParameterID:CHHapticEventParameterIDHapticSharpness
value:1.0];
event = [[CHHapticEvent alloc]
initWithEventType:CHHapticEventTypeHapticContinuous
parameters:[NSArray arrayWithObjects:intense, nil]
parameters:[NSArray arrayWithObjects:intense, sharp, nil]
relativeTime:0
duration:GCHapticDurationInfinite];
pattern = [[CHHapticPattern alloc]
@@ -606,7 +616,7 @@ static id<CHHapticPatternPlayer> apple_gamecontroller_device_haptics_strong_play
static id<CHHapticPatternPlayer> apple_gamecontroller_device_haptics_weak_player(void) IPHONE_RUMBLE_AVAIL
{
if (!deviceWeakPlayer)
deviceWeakPlayer = apple_gamecontroller_device_haptics_create_player(0.5f);
deviceWeakPlayer = apple_gamecontroller_device_haptics_create_player(0.7f);
return deviceWeakPlayer;
}
#endif
@@ -770,8 +780,6 @@ static bool apple_gamecontroller_joypad_set_rumble(unsigned pad,
{
CHHapticDynamicParameter *param = NULL;
float str = (float)strength / 65535.0f;
if (type == RETRO_RUMBLE_WEAK)
str *= MFI_WEAK_RUMBLE;
param = [[CHHapticDynamicParameter alloc]
initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl
value:str