Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support vibrate(intensity, mode) for iOS #1904

Open
ParticleG opened this issue Feb 22, 2023 · 5 comments
Open

Support vibrate(intensity, mode) for iOS #1904

ParticleG opened this issue Feb 22, 2023 · 5 comments
Labels
feature New feature or request iOS

Comments

@ParticleG
Copy link

On iOS 10.0+, iPadOS 10.0+ and Mac Catalyst 13.1+, it is possible for iPhones and iPads to generate different type of viberations, Not just a fixed 400ms one. Just Mapping seconds to UIFeedbackGenerator's subclasses like this:

if (@available(iOS 10.0, *)) {
	// iOS 10.0 and above
	UIImpactFeedbackGenerator *impact = nil;
	if (seconds >= 0.5 && seconds < 1.5) {
		impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
	} else if (seconds >= 1.5 && seconds < 2.5) {
		impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium];
	} else if (seconds >= 2.5) {
		impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleHeavy];
	} else {
		return;
	}
	[impact impactOccurred];
	return;
}
@ParticleG
Copy link
Author

And iOS13+ seems have even more options, I'll test them later

@ParticleG
Copy link
Author

Add the second param to vibrate method with default value default, while on iOS default means the old fixed 500ms vibration, so it won't affect existing codes:

// src/modules/system/wrap_System.cpp
int w_vibrate(lua_State *L)
{
	double seconds = luaL_optnumber(L, 1, 0.5);
	const char *mode = luaL_optstring(L, 2, "default");
	instance()->vibrate(seconds, mode);
	return 0;
}

And ignore mode param on Android(For now):

// src/modules/system/System.cpp
void System::vibrate(double seconds, const std::string &mode) const
{
#ifdef LOVE_ANDROID
	love::android::vibrate(seconds);
	LOVE_UNUSED(mode);
#elif defined(LOVE_IOS)
	love::ios::vibrate(seconds, mode);
#else
	LOVE_UNUSED(seconds);
	LOVE_UNUSED(mode);
#endif
}

Then process them on iOS:

void vibrate(const double intensity, const std::string &mode)
{
	@autoreleasepool
	{
		if (mode != "default" && @available(iOS 10.0, *)) {
			// iOS 10.0 and above
			UIImpactFeedbackGenerator *impact = nil;
			if (mode == "light") {
				impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
			} else if (mode == "medium") {
				impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium];
			} else if (mode == "heavy") {
				impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleHeavy];
			}
			if (@available(iOS 13.0, *)) {
				// iOS 13.0 and above
				if (mode == "soft") {
					impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleSoft];
				} else if (mode == "rigid") {
					impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleRigid];
				}
				if(impact != nil){
					[impact impactOccurredWithIntensity:(intensity < 0 ? 0 : (intensity > 1 ? 1 : intensity))];
					return;
				}
			}
			if(impact != nil){
				[impact impactOccurred];
				return;
			}
		}
		AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	}
}

@ParticleG ParticleG changed the title Support vibrate(seconds) for iOS Support vibrate(intensity, mode) for iOS Feb 23, 2023
@slime73
Copy link
Member

slime73 commented Feb 26, 2023

Per my comment in the pull request (#1905 (comment)), I don't really feel good about having platform-specific function parameters. I wonder if some of Android's haptic feedback APIs are similar enough to the ones you've investigated for iOS that the two backends can both implement a mode parameter.

@ParticleG
Copy link
Author

Android actually has similar "light", "medium" and "heavy" haptic feedbacks. Like EFFECT_TICK, EFFECT_CLICK and EFFECT_HEAVY_CLICK on Android 10+ , while android has much more customization options.

@ParticleG
Copy link
Author

Another solution is continue using simgle seconds parameter, since Android can automatically switch between haptic vibration and normal long vibration depends on how long the vibration is (On my OnePlus 7 Pro with A 13, shorter than 0.3s are haptic vibrations), maybe we could manually set a custom curve to tell iOS when to switch from haptic vibration to long vibration.

@slime73 slime73 added the feature New feature or request label Mar 4, 2023
@slime73 slime73 added the iOS label Jun 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request iOS
Projects
None yet
Development

No branches or pull requests

2 participants