Merge pull request #60397 from timoschwarzer/ios-haptic-engine

This commit is contained in:
Rémi Verschelde 2022-04-27 09:40:58 +02:00 committed by GitHub
commit 8a996d7b38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 116 additions and 2 deletions

View File

@ -32,15 +32,26 @@
#define IOS_H #define IOS_H
#include "core/object/class_db.h" #include "core/object/class_db.h"
#import <CoreHaptics/CoreHaptics.h>
class iOS : public Object { class iOS : public Object {
GDCLASS(iOS, Object); GDCLASS(iOS, Object);
static void _bind_methods(); static void _bind_methods();
private:
CHHapticEngine *haptic_engine API_AVAILABLE(ios(13)) = nullptr;
CHHapticEngine *get_haptic_engine_instance() API_AVAILABLE(ios(13));
void start_haptic_engine();
void stop_haptic_engine();
public: public:
static void alert(const char *p_alert, const char *p_title); static void alert(const char *p_alert, const char *p_title);
bool supports_haptic_engine();
void vibrate_haptic_engine(float p_duration_seconds);
String get_model() const; String get_model() const;
String get_rate_url(int p_app_id) const; String get_rate_url(int p_app_id) const;

View File

@ -32,11 +32,110 @@
#import "app_delegate.h" #import "app_delegate.h"
#import "view_controller.h" #import "view_controller.h"
#import <CoreHaptics/CoreHaptics.h>
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
void iOS::_bind_methods() { void iOS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rate_url", "app_id"), &iOS::get_rate_url); ClassDB::bind_method(D_METHOD("get_rate_url", "app_id"), &iOS::get_rate_url);
ClassDB::bind_method(D_METHOD("supports_haptic_engine"), &iOS::supports_haptic_engine);
ClassDB::bind_method(D_METHOD("start_haptic_engine"), &iOS::start_haptic_engine);
ClassDB::bind_method(D_METHOD("stop_haptic_engine"), &iOS::stop_haptic_engine);
};
bool iOS::supports_haptic_engine() {
if (@available(iOS 13, *)) {
id<CHHapticDeviceCapability> capabilities = [CHHapticEngine capabilitiesForHardware];
return capabilities.supportsHaptics;
}
return false;
}
CHHapticEngine *iOS::get_haptic_engine_instance() API_AVAILABLE(ios(13)) {
if (haptic_engine == nullptr) {
NSError *error = nullptr;
haptic_engine = [[CHHapticEngine alloc] initAndReturnError:&error];
if (!error) {
[haptic_engine setAutoShutdownEnabled:true];
} else {
haptic_engine = nullptr;
NSLog(@"Could not initialize haptic engine: %@", error);
}
}
return haptic_engine;
}
void iOS::vibrate_haptic_engine(float p_duration_seconds) API_AVAILABLE(ios(13)) {
if (@available(iOS 13, *)) { // We need the @available check every time to make the compiler happy...
if (supports_haptic_engine()) {
CHHapticEngine *haptic_engine = get_haptic_engine_instance();
if (haptic_engine) {
NSDictionary *hapticDict = @{
CHHapticPatternKeyPattern : @[
@{CHHapticPatternKeyEvent : @{
CHHapticPatternKeyEventType : CHHapticEventTypeHapticTransient,
CHHapticPatternKeyTime : @(CHHapticTimeImmediate),
CHHapticPatternKeyEventDuration : @(p_duration_seconds)
},
},
],
};
NSError *error;
CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithDictionary:hapticDict error:&error];
[[haptic_engine createPlayerWithPattern:pattern error:&error] startAtTime:0 error:&error];
NSLog(@"Could not vibrate using haptic engine: %@", error);
}
return;
}
}
NSLog(@"Haptic engine is not supported in this version of iOS");
}
void iOS::start_haptic_engine() {
if (@available(iOS 13, *)) {
if (supports_haptic_engine()) {
CHHapticEngine *haptic_engine = get_haptic_engine_instance();
if (haptic_engine) {
[haptic_engine startWithCompletionHandler:^(NSError *returnedError) {
if (returnedError) {
NSLog(@"Could not start haptic engine: %@", returnedError);
}
}];
}
return;
}
}
NSLog(@"Haptic engine is not supported in this version of iOS");
}
void iOS::stop_haptic_engine() {
if (@available(iOS 13, *)) {
if (supports_haptic_engine()) {
CHHapticEngine *haptic_engine = get_haptic_engine_instance();
if (haptic_engine) {
[haptic_engine stopWithCompletionHandler:^(NSError *returnedError) {
if (returnedError) {
NSLog(@"Could not stop haptic engine: %@", returnedError);
}
}];
}
return;
}
}
NSLog(@"Haptic engine is not supported in this version of iOS");
} }
void iOS::alert(const char *p_alert, const char *p_title) { void iOS::alert(const char *p_alert, const char *p_title) {

View File

@ -298,8 +298,12 @@ String OSIPhone::get_processor_name() const {
} }
void OSIPhone::vibrate_handheld(int p_duration_ms) { void OSIPhone::vibrate_handheld(int p_duration_ms) {
// iOS does not support duration for vibration if (ios->supports_haptic_engine()) {
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); ios->vibrate_haptic_engine((float)p_duration_ms / 1000.f);
} else {
// iOS <13 does not support duration for vibration
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
} }
bool OSIPhone::_check_internal_feature_support(const String &p_feature) { bool OSIPhone::_check_internal_feature_support(const String &p_feature) {