Skip to content

Commit

Permalink
Core: adding haptics engine support for iOS/Android
Browse files Browse the repository at this point in the history
  • Loading branch information
Shchvova committed Oct 19, 2021
1 parent c3f73bb commit 4ddad36
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 15 deletions.
15 changes: 14 additions & 1 deletion librtt/Rtt_LuaLibSystem.cpp
Expand Up @@ -326,7 +326,20 @@ getTimer( lua_State *L )
static int
vibrate( lua_State *L )
{
LuaContext::GetPlatform( L ).GetDevice().Vibrate();
const char* hapticType = NULL;
const char* hapticStyle = NULL;

if ( lua_type( L, 1 ) == LUA_TSTRING)
{
hapticType = lua_tostring(L, 1);
}
if(lua_type( L, 2 ) == LUA_TSTRING)
{
hapticStyle = lua_tostring(L, 2);
}

LuaContext::GetPlatform( L ).GetDevice().Vibrate(hapticType, hapticStyle);

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions librtt/Rtt_MPlatformDevice.h
Expand Up @@ -96,6 +96,7 @@ class MPlatformDevice
virtual PlatformInputDeviceManager& GetInputDeviceManager() = 0;

public:
virtual void Vibrate(const char* hapticType, const char* hapticStyle = NULL) const { Vibrate(); };
virtual void Vibrate() const = 0;

public:
Expand Down
4 changes: 2 additions & 2 deletions platform/android/ndk/Rtt_AndroidDevice.cpp
Expand Up @@ -62,9 +62,9 @@ AndroidDevice::SetOrientation( DeviceOrientation::Type orientation )
}

void
AndroidDevice::Vibrate() const
AndroidDevice::Vibrate(const char * hapticType, const char* hapticStyle) const
{
fNativeToJavaBridge->Vibrate();
fNativeToJavaBridge->Vibrate(hapticType, hapticStyle);
}

void
Expand Down
3 changes: 2 additions & 1 deletion platform/android/ndk/Rtt_AndroidDevice.h
Expand Up @@ -50,7 +50,8 @@ class AndroidDevice : public MPlatformDevice
virtual PlatformInputDeviceManager& GetInputDeviceManager();

public:
virtual void Vibrate() const;
virtual void Vibrate(const char * hapticType, const char* hapticStyle) const;
virtual void Vibrate() const { Vibrate(NULL, NULL); }

public:
virtual void BeginNotifications( EventType type ) const;
Expand Down
23 changes: 21 additions & 2 deletions platform/android/ndk/jni/NativeToJavaBridge.cpp
Expand Up @@ -2067,10 +2067,29 @@ NativeToJavaBridge::MakeLowerCase(Rtt::String *stringToConvert)
}

void
NativeToJavaBridge::Vibrate()
NativeToJavaBridge::Vibrate(const char * hapticType, const char* hapticStyle)
{
CallVoidMethod( "callVibrate" );
HandleJavaException();
NativeTrace trace( "NativeToJavaBridge::Vibrate" );


jclassInstance bridge( GetJNIEnv(), kNativeToJavaBridge );

if ( bridge.isValid() ) {

jmethodID mid = bridge.getEnv()->GetStaticMethodID( bridge.getClass(),
"callVibrate", "(Lcom/ansca/corona/CoronaRuntime;Ljava/lang/String;Ljava/lang/String;)V" );

if ( mid != NULL ) {
jstringParam hapticTypeJ( bridge.getEnv(), hapticType );
jstringParam hapticStyleJ( bridge.getEnv(), hapticStyle );

bridge.getEnv()->CallStaticVoidMethod(
bridge.getClass(), mid, fCoronaRuntime, hapticTypeJ.getValue(), hapticStyleJ.getValue());
HandleJavaException();

}
}
}

void
Expand Down
2 changes: 1 addition & 1 deletion platform/android/ndk/jni/NativeToJavaBridge.h
Expand Up @@ -179,7 +179,7 @@ class NativeToJavaBridge
bool HasAccelerometer();
bool HasGyroscope();
bool HasHeadingHardware();
void Vibrate();
void Vibrate(const char * hapticType = NULL, const char* hapticStyle = NULL);

void DisplayObjectDestroy( int id );
void DisplayObjectSetVisible( int id, bool visible );
Expand Down
62 changes: 59 additions & 3 deletions platform/android/sdk/src/com/ansca/corona/Controller.java
Expand Up @@ -30,6 +30,7 @@
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.MediaStore.Images;
import android.provider.Settings.Secure;
Expand Down Expand Up @@ -1846,15 +1847,70 @@ public boolean hasHeadingHardware()
public void setEventNotification( int eventType, boolean enable ) {
mySensorManager.setEventNotification(eventType, enable);
}

public void vibrate() {
public void vibrate(String hapticType, String hapticStyle) {
Context context = myContext;
if (context == null) {
return;
}

Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate( 100 );
String type = "";
if(hapticType != null){
type = hapticType;
}
String style = "";
if(hapticStyle != null){
style = hapticType;
}
long[] timings = new long[]{};
int[] amplitudes= new int[]{};
long[] oldPattern= new long[]{};
if(type.equals("impact")){
if(style.equals("light")){
timings = new long[]{0, 50};
amplitudes = new int[]{0, 110};
oldPattern = new long[]{0, 20};
}
else if(style.equals("heavy")){
timings = new long[]{0, 60};
amplitudes = new int[]{0, 255};
oldPattern = new long[]{0, 61};
}
else{//medium
timings = new long[]{0, 43};
amplitudes = new int[]{0, 180};
oldPattern = new long[]{0, 43};
}
}else if(type.equals("selection")){
timings = new long[]{0, 100};
amplitudes = new int[]{0, 100};
oldPattern = new long[]{0, 70};
}else if(type.equals("notification")){
if(style.equals("warning")) {
timings = new long[]{0, 30, 40, 30, 50, 60};
amplitudes = new int[]{255, 255, 255, 255, 255, 255};
oldPattern = new long[]{0, 30, 40, 30, 50, 60};
}else if(style.equals("error")){
timings = new long[]{0, 27, 45, 50};
amplitudes = new int[]{0, 120, 0, 250};
oldPattern = new long[]{0, 27, 45, 50};
}else{//success
timings = new long[]{0, 35, 65, 21};
amplitudes = new int[]{0, 250, 0, 180};
oldPattern = new long[]{0, 35, 65, 21};
}
}else{
if(!type.isEmpty()){ Log.i("Corona", "WARNING: invalid hapticType");} //just in case user misspells or puts a wrong type
v.vibrate( 100 );
}
if(timings.length != 0 && amplitudes.length != 0 && oldPattern.length != 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createWaveform(timings, amplitudes, -1));
}else{
v.vibrate(oldPattern, -1);
}
}
}

public String getManufacturerName() {
Expand Down
Expand Up @@ -2256,9 +2256,9 @@ protected static String callDeletePreferences(String[] keyNames)
return null;
}

protected static void callVibrate(CoronaRuntime runtime)
protected static void callVibrate(CoronaRuntime runtime, String hapticType, String hapticStyle)
{
runtime.getController().vibrate();
runtime.getController().vibrate(hapticType, hapticStyle);
}

protected static void callSetLocationAccuracy( double meters, CoronaRuntime runtime )
Expand Down
3 changes: 2 additions & 1 deletion platform/iphone/Rtt_IPhoneDevice.h
Expand Up @@ -57,7 +57,8 @@ class IPhoneDevice : public MPlatformDevice
virtual PlatformInputDeviceManager& GetInputDeviceManager();

public:
virtual void Vibrate() const;
virtual void Vibrate(const char * hapticType, const char* hapticStyle) const;
virtual void Vibrate() const { Vibrate(NULL, NULL); }

public:
virtual void BeginNotifications( EventType type ) const;
Expand Down
52 changes: 50 additions & 2 deletions platform/iphone/Rtt_IPhoneDevice.mm
Expand Up @@ -323,9 +323,57 @@
}

void
IPhoneDevice::Vibrate() const
IPhoneDevice::Vibrate(const char * hapticType, const char* hapticStyle) const
{
AudioServicesPlaySystemSound( kSystemSoundID_Vibrate );
NSString * type = nil;
if(hapticType){
type = [[NSString alloc] initWithUTF8String:hapticType];
}
NSString * style = nil;
if(hapticStyle){
style = [[NSString alloc] initWithUTF8String:hapticStyle];
}
if([type isEqualToString:@"impact"]){
UIImpactFeedbackStyle feedbackStyle = UIImpactFeedbackStyleMedium; // default
if (style != nil) {
if ([style isEqualToString:@"light"]) {
feedbackStyle = UIImpactFeedbackStyleLight;
} else if ([style isEqualToString:@"heavy"]) {
feedbackStyle = UIImpactFeedbackStyleHeavy;
} else if ([style isEqualToString:@"rigid"]) {
if (@available(iOS 13.0, *)) {
feedbackStyle = UIImpactFeedbackStyleRigid;
}//else we use medium
} else if ([style isEqualToString:@"soft"]) {
if (@available(iOS 13.0, *)) {
feedbackStyle = UIImpactFeedbackStyleSoft;
}//else we use medium
}
}
UIImpactFeedbackGenerator *feedback = [[UIImpactFeedbackGenerator alloc] initWithStyle:feedbackStyle];
[feedback prepare];
[feedback impactOccurred];
feedback = nil;
}else if([type isEqualToString:@"selection"]){
UISelectionFeedbackGenerator *generator = [UISelectionFeedbackGenerator new];
[generator selectionChanged];
}else if([type isEqualToString:@"notification"]){
UINotificationFeedbackType feedbackType = UINotificationFeedbackTypeSuccess; // default
if (style != nil) {
if ([style isEqualToString:@"warning"]) {
feedbackType = UINotificationFeedbackTypeWarning;
} else if ([style isEqualToString:@"error"]) {
feedbackType = UINotificationFeedbackTypeError;
}
}
UINotificationFeedbackGenerator *feedback = [UINotificationFeedbackGenerator new];
[feedback prepare];
[feedback notificationOccurred:feedbackType];
feedback = nil;
}else{
if(type != nil){Rtt_Log("WARNING: invalid hapticType");} //just in case user misspells or puts a wrong type
AudioServicesPlaySystemSound( kSystemSoundID_Vibrate );
}
}

bool
Expand Down

0 comments on commit 4ddad36

Please sign in to comment.