From 150bd313cfa8700f361c1137831be870b1b722d2 Mon Sep 17 00:00:00 2001 From: gotoAndDie Date: Sun, 19 Jan 2020 07:13:07 +0000 Subject: [PATCH] Increase usability of on-screen virtual controller (#782) * Restore resize controls, Make buttons oval * Create new default configuration * Split Configuration Mode into separate Move and Resize modes --- app/src/main/java/com/limelight/Game.java | 5 +- .../virtual_controller/DigitalButton.java | 4 +- .../virtual_controller/VirtualController.java | 15 +- .../VirtualControllerConfigurationLoader.java | 162 +++++++++++------- .../VirtualControllerElement.java | 16 +- 5 files changed, 125 insertions(+), 77 deletions(-) diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java index dfcc3a90..03f3912c 100644 --- a/app/src/main/java/com/limelight/Game.java +++ b/app/src/main/java/com/limelight/Game.java @@ -1194,8 +1194,9 @@ public class Game extends Activity implements SurfaceHolder.Callback, else { if (virtualController != null && - virtualController.getControllerMode() == VirtualController.ControllerMode.Configuration) { - // Ignore presses when the virtual controller is in configuration mode + virtualController.getControllerMode() == VirtualController.ControllerMode.MoveButtons || + virtualController.getControllerMode() == VirtualController.ControllerMode.ResizeButtons) { + // Ignore presses when the virtual controller is being configured return true; } diff --git a/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java b/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java index 4614f42d..ce6a91b0 100644 --- a/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java +++ b/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java @@ -144,13 +144,13 @@ public class DigitalButton extends VirtualControllerElement { // set transparent background canvas.drawColor(Color.TRANSPARENT); - paint.setTextSize(getPercent(getWidth(), 30)); + paint.setTextSize(getPercent(getWidth(), 25)); paint.setTextAlign(Paint.Align.CENTER); paint.setStrokeWidth(getDefaultStrokeWidth()); paint.setColor(isPressed() ? pressedColor : getDefaultColor()); paint.setStyle(Paint.Style.STROKE); - canvas.drawRect(paint.getStrokeWidth(), paint.getStrokeWidth(), + canvas.drawOval(paint.getStrokeWidth(), paint.getStrokeWidth(), getWidth() - paint.getStrokeWidth(), getHeight() - paint.getStrokeWidth(), paint); if (icon != -1) { diff --git a/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualController.java b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualController.java index 2dbb070e..60dd3836 100644 --- a/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualController.java +++ b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualController.java @@ -34,7 +34,8 @@ public class VirtualController { public enum ControllerMode { Active, - Configuration + MoveButtons, + ResizeButtons } private static final boolean _PRINT_DEBUG_INFORMATION = false; @@ -72,13 +73,16 @@ public class VirtualController { public void onClick(View v) { String message; - if (currentMode == ControllerMode.Configuration) { + if (currentMode == ControllerMode.Active){ + currentMode = ControllerMode.MoveButtons; + message = "Entering configuration mode (Move buttons)"; + } else if (currentMode == ControllerMode.MoveButtons) { + currentMode = ControllerMode.ResizeButtons; + message = "Entering configuration mode (Resize buttons)"; + } else { currentMode = ControllerMode.Active; VirtualControllerConfigurationLoader.saveProfile(VirtualController.this, context); message = "Exiting configuration mode"; - } else { - currentMode = ControllerMode.Configuration; - message = "Entering configuration mode"; } Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); @@ -90,6 +94,7 @@ public class VirtualController { } } }); + } public void hide() { diff --git a/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerConfigurationLoader.java b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerConfigurationLoader.java index 5d945b09..55c21643 100644 --- a/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerConfigurationLoader.java +++ b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerConfigurationLoader.java @@ -24,6 +24,11 @@ public class VirtualControllerConfigurationLoader { return (int) (((float) total / (float) 100) * (float) percent); } + // The default controls are specified using a grid of 128*72 cells at 16:9 + private static int screenScale(int units, int height) { + return (int) (((float) height / (float) 72) * (float) units); + } + private static DigitalPad createDigitalPad( final VirtualController controller, final Context context) { @@ -145,147 +150,176 @@ public class VirtualControllerConfigurationLoader { return new RightAnalogStick(controller, context); } - private static final int BUTTON_BASE_X = 65; - private static final int BUTTON_BASE_Y = 5; - private static final int BUTTON_WIDTH = getPercent(30, 33); - private static final int BUTTON_HEIGHT = getPercent(40, 33); + + private static final int TRIGGER_L_BASE_X = 1; + private static final int TRIGGER_R_BASE_X = 92; + private static final int TRIGGER_DISTANCE = 23; + private static final int TRIGGER_BASE_Y = 31; + private static final int TRIGGER_WIDTH = 12; + private static final int TRIGGER_HEIGHT = 9; + + // Face buttons are defined based on the Y button (button number 9) + private static final int BUTTON_BASE_X = 106; + private static final int BUTTON_BASE_Y = 1; + private static final int BUTTON_SIZE = 10; + + private static final int DPAD_BASE_X = 4; + private static final int DPAD_BASE_Y = 41; + private static final int DPAD_SIZE = 30; + + private static final int ANALOG_L_BASE_X = 4; + private static final int ANALOG_L_BASE_Y = 1; + private static final int ANALOG_R_BASE_X = 96; + private static final int ANALOG_R_BASE_Y = 42; + private static final int ANALOG_SIZE = 28; + + private static final int START_X = 83; + private static final int BACK_X = 34; + private static final int START_BACK_Y = 64; + private static final int START_BACK_WIDTH = 12; + private static final int START_BACK_HEIGHT = 7; public static void createDefaultLayout(final VirtualController controller, final Context context) { DisplayMetrics screen = context.getResources().getDisplayMetrics(); PreferenceConfiguration config = PreferenceConfiguration.readPreferences(context); + // Displace controls on the right by this amount of pixels to account for different aspect ratios + int rightDisplacement = screen.widthPixels - screen.heightPixels * 16 / 9; + + int height = screen.heightPixels; + // NOTE: Some of these getPercent() expressions seem like they can be combined // into a single call. Due to floating point rounding, this isn't actually possible. if (!config.onlyL3R3) { controller.addElement(createDigitalPad(controller, context), - getPercent(5, screen.widthPixels), - getPercent(BUTTON_BASE_Y, screen.heightPixels), - getPercent(30, screen.widthPixels), - getPercent(40, screen.heightPixels) + screenScale(DPAD_BASE_X, height), + screenScale(DPAD_BASE_Y, height), + screenScale(DPAD_SIZE, height), + screenScale(DPAD_SIZE, height) ); controller.addElement(createDigitalButton( VirtualControllerElement.EID_A, ControllerPacket.A_FLAG, 0, 1, "A", -1, controller, context), - getPercent(BUTTON_BASE_X, screen.widthPixels) + getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_BASE_Y, screen.heightPixels) + 2 * getPercent(BUTTON_HEIGHT, screen.heightPixels), - getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_HEIGHT, screen.heightPixels) + screenScale(BUTTON_BASE_X, height) + rightDisplacement, + screenScale(BUTTON_BASE_Y + 2 * BUTTON_SIZE, height), + screenScale(BUTTON_SIZE, height), + screenScale(BUTTON_SIZE, height) ); controller.addElement(createDigitalButton( VirtualControllerElement.EID_B, ControllerPacket.B_FLAG, 0, 1, "B", -1, controller, context), - getPercent(BUTTON_BASE_X, screen.widthPixels) + 2 * getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_BASE_Y, screen.heightPixels) + getPercent(BUTTON_HEIGHT, screen.heightPixels), - getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_HEIGHT, screen.heightPixels) + screenScale(BUTTON_BASE_X + BUTTON_SIZE, height) + rightDisplacement, + screenScale(BUTTON_BASE_Y + BUTTON_SIZE, height), + screenScale(BUTTON_SIZE, height), + screenScale(BUTTON_SIZE, height) ); controller.addElement(createDigitalButton( VirtualControllerElement.EID_X, ControllerPacket.X_FLAG, 0, 1, "X", -1, controller, context), - getPercent(BUTTON_BASE_X, screen.widthPixels), - getPercent(BUTTON_BASE_Y, screen.heightPixels) + getPercent(BUTTON_HEIGHT, screen.heightPixels), - getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_HEIGHT, screen.heightPixels) + screenScale(BUTTON_BASE_X - BUTTON_SIZE, height) + rightDisplacement, + screenScale(BUTTON_BASE_Y + BUTTON_SIZE, height), + screenScale(BUTTON_SIZE, height), + screenScale(BUTTON_SIZE, height) ); controller.addElement(createDigitalButton( VirtualControllerElement.EID_Y, ControllerPacket.Y_FLAG, 0, 1, "Y", -1, controller, context), - getPercent(BUTTON_BASE_X, screen.widthPixels) + getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_BASE_Y, screen.heightPixels), - getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_HEIGHT, screen.heightPixels) + screenScale(BUTTON_BASE_X, height) + rightDisplacement, + screenScale(BUTTON_BASE_Y, height), + screenScale(BUTTON_SIZE, height), + screenScale(BUTTON_SIZE, height) ); controller.addElement(createLeftTrigger( 0, "LT", -1, controller, context), - getPercent(BUTTON_BASE_X, screen.widthPixels), - getPercent(BUTTON_BASE_Y, screen.heightPixels), - getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_HEIGHT, screen.heightPixels) + screenScale(TRIGGER_L_BASE_X, height), + screenScale(TRIGGER_BASE_Y, height), + screenScale(TRIGGER_WIDTH, height), + screenScale(TRIGGER_HEIGHT, height) ); controller.addElement(createRightTrigger( 0, "RT", -1, controller, context), - getPercent(BUTTON_BASE_X, screen.widthPixels) + 2 * getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_BASE_Y, screen.heightPixels), - getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_HEIGHT, screen.heightPixels) + screenScale(TRIGGER_R_BASE_X + TRIGGER_DISTANCE, height) + rightDisplacement, + screenScale(TRIGGER_BASE_Y, height), + screenScale(TRIGGER_WIDTH, height), + screenScale(TRIGGER_HEIGHT, height) ); controller.addElement(createDigitalButton( VirtualControllerElement.EID_LB, ControllerPacket.LB_FLAG, 0, 1, "LB", -1, controller, context), - getPercent(BUTTON_BASE_X, screen.widthPixels), - getPercent(BUTTON_BASE_Y, screen.heightPixels) + 2 * getPercent(BUTTON_HEIGHT, screen.heightPixels), - getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_HEIGHT, screen.heightPixels) + screenScale(TRIGGER_L_BASE_X + TRIGGER_DISTANCE, height), + screenScale(TRIGGER_BASE_Y, height), + screenScale(TRIGGER_WIDTH, height), + screenScale(TRIGGER_HEIGHT, height) ); controller.addElement(createDigitalButton( VirtualControllerElement.EID_RB, ControllerPacket.RB_FLAG, 0, 1, "RB", -1, controller, context), - getPercent(BUTTON_BASE_X, screen.widthPixels) + 2 * getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_BASE_Y, screen.heightPixels) + 2 * getPercent(BUTTON_HEIGHT, screen.heightPixels), - getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_HEIGHT, screen.heightPixels) + screenScale(TRIGGER_R_BASE_X, height) + rightDisplacement, + screenScale(TRIGGER_BASE_Y, height), + screenScale(TRIGGER_WIDTH, height), + screenScale(TRIGGER_HEIGHT, height) ); controller.addElement(createLeftStick(controller, context), - getPercent(5, screen.widthPixels), - getPercent(50, screen.heightPixels), - getPercent(40, screen.widthPixels), - getPercent(50, screen.heightPixels) + screenScale(ANALOG_L_BASE_X, height), + screenScale(ANALOG_L_BASE_Y, height), + screenScale(ANALOG_SIZE, height), + screenScale(ANALOG_SIZE, height) ); controller.addElement(createRightStick(controller, context), - getPercent(55, screen.widthPixels), - getPercent(50, screen.heightPixels), - getPercent(40, screen.widthPixels), - getPercent(50, screen.heightPixels) + screenScale(ANALOG_R_BASE_X, height) + rightDisplacement, + screenScale(ANALOG_R_BASE_Y, height), + screenScale(ANALOG_SIZE, height), + screenScale(ANALOG_SIZE, height) ); controller.addElement(createDigitalButton( VirtualControllerElement.EID_BACK, ControllerPacket.BACK_FLAG, 0, 2, "BACK", -1, controller, context), - getPercent(40, screen.widthPixels), - getPercent(90, screen.heightPixels), - getPercent(10, screen.widthPixels), - getPercent(10, screen.heightPixels) + screenScale(BACK_X, height), + screenScale(START_BACK_Y, height), + screenScale(START_BACK_WIDTH, height), + screenScale(START_BACK_HEIGHT, height) ); controller.addElement(createDigitalButton( VirtualControllerElement.EID_START, ControllerPacket.PLAY_FLAG, 0, 3, "START", -1, controller, context), - getPercent(40, screen.widthPixels) + getPercent(10, screen.widthPixels), - getPercent(90, screen.heightPixels), - getPercent(10, screen.widthPixels), - getPercent(10, screen.heightPixels) + screenScale(START_X, height) + rightDisplacement, + screenScale(START_BACK_Y, height), + screenScale(START_BACK_WIDTH, height), + screenScale(START_BACK_HEIGHT, height) ); } else { controller.addElement(createDigitalButton( VirtualControllerElement.EID_LSB, ControllerPacket.LS_CLK_FLAG, 0, 1, "L3", -1, controller, context), - getPercent(2, screen.widthPixels), - getPercent(80, screen.heightPixels), - getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_HEIGHT, screen.heightPixels) + screenScale(TRIGGER_L_BASE_X, height), + screenScale(TRIGGER_BASE_Y, height), + screenScale(TRIGGER_WIDTH, height), + screenScale(TRIGGER_HEIGHT, height) ); controller.addElement(createDigitalButton( VirtualControllerElement.EID_RSB, ControllerPacket.RS_CLK_FLAG, 0, 1, "R3", -1, controller, context), - getPercent(89, screen.widthPixels), - getPercent(80, screen.heightPixels), - getPercent(BUTTON_WIDTH, screen.widthPixels), - getPercent(BUTTON_HEIGHT, screen.heightPixels) + screenScale(TRIGGER_R_BASE_X + TRIGGER_DISTANCE, height), + screenScale(TRIGGER_BASE_Y, height), + screenScale(TRIGGER_WIDTH, height), + screenScale(TRIGGER_HEIGHT, height) ); } } diff --git a/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerElement.java b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerElement.java index 342ea342..f82fdc2d 100644 --- a/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerElement.java +++ b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerElement.java @@ -43,7 +43,8 @@ public abstract class VirtualControllerElement extends View { private int normalColor = 0xF0888888; protected int pressedColor = 0xF00000FF; - private int configNormalColor = 0xF0FF0000; + private int configMoveColor = 0xF0FF0000; + private int configResizeColor = 0xF0FF00FF; private int configSelectedColor = 0xF000FF00; protected int startSize_x; @@ -156,8 +157,12 @@ public abstract class VirtualControllerElement extends View { } protected int getDefaultColor() { - return (virtualController.getControllerMode() == VirtualController.ControllerMode.Configuration) ? - configNormalColor : normalColor; + if (virtualController.getControllerMode() == VirtualController.ControllerMode.MoveButtons) + return configMoveColor; + else if (virtualController.getControllerMode() == VirtualController.ControllerMode.ResizeButtons) + return configResizeColor; + else + return normalColor; } protected int getDefaultStrokeWidth() { @@ -230,7 +235,10 @@ public abstract class VirtualControllerElement extends View { startSize_x = getWidth(); startSize_y = getHeight(); - actionEnableMove(); + if (virtualController.getControllerMode() == VirtualController.ControllerMode.MoveButtons) + actionEnableMove(); + else if (virtualController.getControllerMode() == VirtualController.ControllerMode.ResizeButtons) + actionEnableResize(); return true; }