iOS: add optional haptic feedback for touch-control press edges

This commit is contained in:
Jpkovas authored and seedds committed 2026-10-24 09:12:59 +08:00
1 parent d4249e5e31
commit 80bc18896f
2 files changed
+14

No files matched your search

+1
View File
@@ -12,3 +12,4 @@ DM_OPMODE choice 1=Docked,0=Handheld DM_GAME_OPMODE always Console mode
DM_LANG choice languages build:DM_LANG languages>1 Game language
DM_SHOW_FPS toggle - build:DM_SHOW_FPS always Frame-rate counter
DM_METAL_HUD toggle - 0 always Performance HUD
DM_TOUCH_HAPTICS toggle - 1 always Touch feedback Haptic clicks when pressing touch controls.
1 # Player-facing settings: the iOS launcher (dm/ios/Sources/Launcher.swift) shows them before the game starts. dm/games/settings.py writes one game's list into its app (dm/launcher.json,
12 DM_LANG
13 DM_SHOW_FPS
14 DM_METAL_HUD
15 DM_TOUCH_HAPTICS
+13
View File
@@ -105,6 +105,8 @@ static __weak DmGamepad *g_view;
CAShapeLayer *_key[B_N]; CATextLayer *_label[B_N]; // one layer per key
CAShapeLayer *_ring, *_knob; // the left stick (the right one is not drawn)
CAShapeLayer *_swap; CATextLayer *_swapLabel; BOOL _swapHeld;
UIImpactFeedbackGenerator *_touchFeedback; // one short feedback per touch-control press edge
unsigned _hapticSticks;
BOOL _stickShown; // the left stick was held at the last refresh
BOOL _full, _tap; // the 3D layout / the Tap layout is current
CALayer *_controls; // holds every control layer: hidden while a physical controller is connected (the view itself stays, for game touches)
@@ -129,6 +131,11 @@ static BOOL fullOnly(int b) { return b == B_LS || b == B_RS || b >= B_LEFT; }
- (instancetype)initWithFrame:(CGRect)f {
if ((self = [super initWithFrame:f])) {
self.multipleTouchEnabled = YES; self.opaque = NO; self.backgroundColor = UIColor.clearColor;
const char *feedback = getenv("DM_TOUCH_HAPTICS");
if (!feedback || atoi(feedback)) {
_touchFeedback = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
[_touchFeedback prepare];
}
_owner = [NSMapTable strongToStrongObjectsMapTable]; _faceOf = [NSMapTable strongToStrongObjectsMapTable];
static dispatch_once_t once;
dispatch_once(&once, ^{
@@ -252,6 +259,12 @@ static CGFloat dist(CGPoint a, CGPoint b) { return hypot(a.x - b.x, a.y - b.y);
ax[i * 2] = (int32_t)lrint(o.x * m * 32767); ax[i * 2 + 1] = (int32_t)lrint(-o.y * m * 32767); // host: up is positive; rounded so full tilt is exactly 32767
}
BOOL changed = face != _faceBits || dpad != _dpadBits || btn != _btnBits || swap != _swapHeld;
uint64_t pressed = (face | dpad | btn) & ~(_faceBits | _dpadBits | _btnBits);
unsigned gripping = (_stick[0] ? 1u : 0) | (_stick[1] ? 2u : 0);
if (pressed || (swap && !_swapHeld) || (gripping & ~_hapticSticks)) {
[_touchFeedback impactOccurredWithIntensity:0.6]; [_touchFeedback prepare];
}
_hapticSticks = gripping;
_faceBits = face; _dpadBits = dpad; _btnBits = btn; _swapHeld = swap;
pthread_mutex_lock(&g_mu);
g_touch_btn = face | dpad | btn; g_touch_lx = ax[0]; g_touch_ly = ax[1]; g_touch_rx = ax[2]; g_touch_ry = ax[3];