From f36dda306412215ced3711c07196368f90813163 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Thu, 25 Jan 2024 13:09:00 -0500 Subject: [PATCH] v2.3.1: added a setting for vibration & improved vibration support logic --- .../com/watabou/input/ControllerHandler.java | 6 +- .../src/main/java/com/watabou/noosa/Game.java | 4 +- .../com/watabou/utils/PlatformSupport.java | 2 + .../android/AndroidPlatformSupport.java | 5 + .../shatteredpixeldungeon/SPDSettings.java | 132 ++++++++++-------- .../shatteredpixeldungeon/ui/Button.java | 5 +- .../windows/WndSettings.java | 24 +++- .../desktop/DesktopPlatformSupport.java | 7 + .../ios/IOSPlatformSupport.java | 34 ++++- 9 files changed, 147 insertions(+), 72 deletions(-) diff --git a/SPD-classes/src/main/java/com/watabou/input/ControllerHandler.java b/SPD-classes/src/main/java/com/watabou/input/ControllerHandler.java index 389880f7b..1e3145cf9 100644 --- a/SPD-classes/src/main/java/com/watabou/input/ControllerHandler.java +++ b/SPD-classes/src/main/java/com/watabou/input/ControllerHandler.java @@ -84,8 +84,12 @@ public class ControllerHandler implements ControllerListener { } } + public static boolean vibrationSupported(){ + return isControllerConnected() && Controllers.getCurrent().canVibrate(); + } + public static void vibrate( int millis ){ - if (Controllers.getCurrent().canVibrate()) { + if (vibrationSupported()) { Controllers.getCurrent().startVibration(millis, 1f); } } diff --git a/SPD-classes/src/main/java/com/watabou/noosa/Game.java b/SPD-classes/src/main/java/com/watabou/noosa/Game.java index 891a1a947..051faa822 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/Game.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/Game.java @@ -317,7 +317,9 @@ public class Game implements ApplicationListener { } public static void vibrate( int milliseconds ) { - platform.vibrate( milliseconds ); + if (platform.supportsVibration()) { + platform.vibrate(milliseconds); + } } public interface SceneChangeCallback{ diff --git a/SPD-classes/src/main/java/com/watabou/utils/PlatformSupport.java b/SPD-classes/src/main/java/com/watabou/utils/PlatformSupport.java index 9f1a2bf31..ba40f38d3 100644 --- a/SPD-classes/src/main/java/com/watabou/utils/PlatformSupport.java +++ b/SPD-classes/src/main/java/com/watabou/utils/PlatformSupport.java @@ -39,6 +39,8 @@ public abstract class PlatformSupport { public abstract boolean connectedToUnmeteredNetwork(); + public abstract boolean supportsVibration(); + public void vibrate( int millis ){ if (ControllerHandler.isControllerConnected()) { ControllerHandler.vibrate(millis); diff --git a/android/src/main/java/com/shatteredpixel/shatteredpixeldungeon/android/AndroidPlatformSupport.java b/android/src/main/java/com/shatteredpixel/shatteredpixeldungeon/android/AndroidPlatformSupport.java index 9c38064fb..db6dc795b 100644 --- a/android/src/main/java/com/shatteredpixel/shatteredpixeldungeon/android/AndroidPlatformSupport.java +++ b/android/src/main/java/com/shatteredpixel/shatteredpixeldungeon/android/AndroidPlatformSupport.java @@ -166,6 +166,11 @@ public class AndroidPlatformSupport extends PlatformSupport { } } + @Override + public boolean supportsVibration() { + return true; //always true on Android + } + /* FONT SUPPORT */ //droid sans / roboto, or a custom pixel font, for use with Latin and Cyrillic languages diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/SPDSettings.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/SPDSettings.java index c8e58a03a..48d22fb10 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/SPDSettings.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/SPDSettings.java @@ -143,6 +143,8 @@ public class SPDSettings extends GameSettings { public static final String KEY_FLIPTAGS = "flip_tags"; public static final String KEY_BARMODE = "toolbar_mode"; public static final String KEY_SLOTWATERSKIN= "quickslot_waterskin"; + public static final String KEY_SYSTEMFONT = "system_font"; + public static final String KEY_VIBRATION = "vibration"; //0 = mobile, 1 = mixed (large without inventory in main UI), 2 = large public static void interfaceSize( int value ){ @@ -201,7 +203,24 @@ public class SPDSettings extends GameSettings { public static boolean quickslotWaterskin(){ return getBoolean( KEY_SLOTWATERSKIN, true ); } - + + public static void systemFont(boolean value){ + put(KEY_SYSTEMFONT, value); + } + + public static boolean systemFont(){ + return getBoolean(KEY_SYSTEMFONT, + (language() == Languages.KOREAN || language() == Languages.CHINESE || language() == Languages.JAPANESE)); + } + + public static void vibration(boolean value){ + put(KEY_VIBRATION, value); + } + + public static boolean vibration(){ + return getBoolean(KEY_VIBRATION, true); + } + //Game State public static final String KEY_LAST_CLASS = "last_class"; @@ -281,6 +300,55 @@ public class SPDSettings extends GameSettings { return getInt(KEY_MOVE_SENS, 3, 0, 4); } + //Connectivity + + public static final String KEY_NEWS = "news"; + public static final String KEY_UPDATES = "updates"; + public static final String KEY_BETAS = "betas"; + public static final String KEY_WIFI = "wifi"; + + public static final String KEY_NEWS_LAST_READ = "news_last_read"; + + public static void news(boolean value){ + put(KEY_NEWS, value); + } + + public static boolean news(){ + return getBoolean(KEY_NEWS, true); + } + + public static void updates(boolean value){ + put(KEY_UPDATES, value); + } + + public static boolean updates(){ + return getBoolean(KEY_UPDATES, true); + } + + public static void betas(boolean value){ + put(KEY_BETAS, value); + } + + public static boolean betas(){ + return getBoolean(KEY_BETAS, Game.version.contains("BETA") || Game.version.contains("RC")); + } + + public static void WiFi(boolean value){ + put(KEY_WIFI, value); + } + + public static boolean WiFi(){ + return getBoolean(KEY_WIFI, true); + } + + public static void newsLastRead(long lastRead){ + put(KEY_NEWS_LAST_READ, lastRead); + } + + public static long newsLastRead(){ + return getLong(KEY_NEWS_LAST_READ, 0); + } + //Audio public static final String KEY_MUSIC = "music"; @@ -343,10 +411,9 @@ public class SPDSettings extends GameSettings { return getBoolean( KEY_MUSIC_BG, true); } - //Languages and Font + //Languages public static final String KEY_LANG = "language"; - public static final String KEY_SYSTEMFONT = "system_font"; public static void language(Languages lang) { put( KEY_LANG, lang.code()); @@ -360,65 +427,7 @@ public class SPDSettings extends GameSettings { return Languages.matchCode(code); } } - - public static void systemFont(boolean value){ - put(KEY_SYSTEMFONT, value); - } - - public static boolean systemFont(){ - return getBoolean(KEY_SYSTEMFONT, - (language() == Languages.KOREAN || language() == Languages.CHINESE || language() == Languages.JAPANESE)); - } - //Connectivity - - public static final String KEY_NEWS = "news"; - public static final String KEY_UPDATES = "updates"; - public static final String KEY_BETAS = "betas"; - public static final String KEY_WIFI = "wifi"; - - public static final String KEY_NEWS_LAST_READ = "news_last_read"; - - public static void news(boolean value){ - put(KEY_NEWS, value); - } - - public static boolean news(){ - return getBoolean(KEY_NEWS, true); - } - - public static void updates(boolean value){ - put(KEY_UPDATES, value); - } - - public static boolean updates(){ - return getBoolean(KEY_UPDATES, true); - } - - public static void betas(boolean value){ - put(KEY_BETAS, value); - } - - public static boolean betas(){ - return getBoolean(KEY_BETAS, Game.version.contains("BETA") || Game.version.contains("RC")); - } - - public static void WiFi(boolean value){ - put(KEY_WIFI, value); - } - - public static boolean WiFi(){ - return getBoolean(KEY_WIFI, true); - } - - public static void newsLastRead(long lastRead){ - put(KEY_NEWS_LAST_READ, lastRead); - } - - public static long newsLastRead(){ - return getLong(KEY_NEWS_LAST_READ, 0); - } - //Window management (desktop only atm) public static final String KEY_WINDOW_WIDTH = "window_width"; @@ -444,5 +453,4 @@ public class SPDSettings extends GameSettings { public static boolean windowMaximized(){ return getBoolean( KEY_WINDOW_MAXIMIZED, false ); } - } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Button.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Button.java index e2ebe5be4..dd13575f2 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Button.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Button.java @@ -21,6 +21,7 @@ package com.shatteredpixel.shatteredpixeldungeon.ui; +import com.shatteredpixel.shatteredpixeldungeon.SPDSettings; import com.watabou.input.ControllerHandler; import com.watabou.input.GameAction; import com.watabou.input.KeyBindings; @@ -161,7 +162,9 @@ public class Button extends Component { clickReady = false; //did a long click, can't do a regular one onPointerUp(); - Game.vibrate( 50 ); + if (SPDSettings.vibration()) { + Game.vibrate(50); + } } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java index 1e0b8a8fd..33cea4994 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java @@ -413,6 +413,7 @@ public class WndSettings extends WndTabbed { CheckBox chkFlipTags; ColorBlock sep2; CheckBox chkFont; + CheckBox chkVibrate; @Override protected void createChildren() { @@ -630,6 +631,17 @@ public class WndSettings extends WndTabbed { }; chkFont.checked(SPDSettings.systemFont()); add(chkFont); + + chkVibrate = new CheckBox(Messages.get(this, "vibration")){ + @Override + protected void onClick() { + super.onClick(); + SPDSettings.vibration(checked()); + } + }; + chkVibrate.checked(SPDSettings.vibration()); + chkVibrate.enable(Game.platform.supportsVibration()); + add(chkVibrate); } @Override @@ -667,8 +679,16 @@ public class WndSettings extends WndTabbed { sep2.size(width, 1); sep2.y = height + GAP; - chkFont.setRect(0, sep2.y + 1 + GAP, width, BTN_HEIGHT); - height = chkFont.bottom(); + if (width > 200) { + chkFont.setRect(0, sep2.y + 1 + GAP, width/2-1, BTN_HEIGHT); + chkVibrate.setRect(chkFont.right()+2, chkFont.top(), width/2-1, BTN_HEIGHT); + height = chkVibrate.bottom(); + + } else { + chkFont.setRect(0, sep2.y + 1 + GAP, width, BTN_HEIGHT); + chkVibrate.setRect(0, chkFont.bottom() + GAP, width, BTN_HEIGHT); + height = chkVibrate.bottom(); + } } } diff --git a/desktop/src/main/java/com/shatteredpixel/shatteredpixeldungeon/desktop/DesktopPlatformSupport.java b/desktop/src/main/java/com/shatteredpixel/shatteredpixeldungeon/desktop/DesktopPlatformSupport.java index 65370bfde..fe69bc51b 100644 --- a/desktop/src/main/java/com/shatteredpixel/shatteredpixeldungeon/desktop/DesktopPlatformSupport.java +++ b/desktop/src/main/java/com/shatteredpixel/shatteredpixeldungeon/desktop/DesktopPlatformSupport.java @@ -26,6 +26,7 @@ import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.g2d.PixmapPacker; import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; import com.shatteredpixel.shatteredpixeldungeon.SPDSettings; +import com.watabou.input.ControllerHandler; import com.watabou.noosa.Game; import com.watabou.utils.PlatformSupport; import com.watabou.utils.Point; @@ -76,6 +77,12 @@ public class DesktopPlatformSupport extends PlatformSupport { return true; //no easy way to check this in desktop, just assume user doesn't care } + @Override + public boolean supportsVibration() { + //only supports vibration via controller + return ControllerHandler.vibrationSupported(); + } + /* FONT SUPPORT */ //custom pixel font, for use with Latin and Cyrillic languages diff --git a/ios/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ios/IOSPlatformSupport.java b/ios/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ios/IOSPlatformSupport.java index dff4e71fe..9e3af923c 100644 --- a/ios/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ios/IOSPlatformSupport.java +++ b/ios/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ios/IOSPlatformSupport.java @@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.ios; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; +import com.badlogic.gdx.backends.iosrobovm.custom.HWMachine; import com.badlogic.gdx.backends.iosrobovm.objectal.OALSimpleAudio; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.g2d.PixmapPacker; @@ -82,16 +83,39 @@ public class IOSPlatformSupport extends PlatformSupport { return !test.getFlags().contains(SCNetworkReachabilityFlags.IsWWAN); } - public void vibrate( int millis ){ + @Override + public boolean supportsVibration() { + //Devices with haptics... + if (Gdx.input.isPeripheralAvailable(Input.Peripheral.HapticFeedback)){ + return true; + }; + + //...or with a supported controller connected + if (ControllerHandler.vibrationSupported()){ + return true; + } + + //...or with 3d touch + String machineString = HWMachine.getMachineString(); + if (machineString.equals("iPhone8,4")){ //1st gen SE has no 3D touch specifically + return false; + } else { // 6s/7/8/X/XR have 3D touch + return machineString.contains("iphone8") //6s + || machineString.contains("iphone9") //7 + || machineString.contains("iphone10") //8, and X + || machineString.contains("iphone11"); //XS (also XR but that has haptic) + } + } + + public void vibrate(int millis ){ if (ControllerHandler.isControllerConnected()){ - if (ControllerHandler.isControllerConnected()) { - ControllerHandler.vibrate(millis); - } + ControllerHandler.vibrate(millis); } else if (Gdx.input.isPeripheralAvailable(Input.Peripheral.HapticFeedback)){ Gdx.input.vibrate( millis ); } else { - //devices without haptics support use a short vibrate on iPhone 6+, no vibration otherwise + //devices without haptics but with 3d touch use a short vibrate AudioServices.playSystemSound(1520); + // no vibration otherwise } }