mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-19 06:45:39 +00:00
Android: Add analog touchscreen controls
This commit is contained in:
parent
4f0007dd55
commit
897f2dadf8
|
@ -55,6 +55,12 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
|
||||||
return mPreferences.getString(key, defaultValue);
|
return mPreferences.getString(key, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setStringSetting(String key, String value) {
|
||||||
|
SharedPreferences.Editor editor = mPreferences.edit();
|
||||||
|
editor.putString(key, value);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
public void reportError(String message) {
|
public void reportError(String message) {
|
||||||
Log.e("EmulationActivity", message);
|
Log.e("EmulationActivity", message);
|
||||||
|
|
||||||
|
@ -175,16 +181,7 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
|
||||||
mContentView.getHolder().addCallback(this);
|
mContentView.getHolder().addCallback(this);
|
||||||
|
|
||||||
// Hook up controller input.
|
// Hook up controller input.
|
||||||
final String controllerType = getStringSetting("Controller1/Type", "DigitalController");
|
updateControllers();
|
||||||
Log.i("EmulationActivity", "Controller type: " + controllerType);
|
|
||||||
mContentView.initControllerKeyMapping(controllerType);
|
|
||||||
|
|
||||||
// Create touchscreen controller.
|
|
||||||
FrameLayout activityLayout = findViewById(R.id.frameLayout);
|
|
||||||
mTouchscreenController = new TouchscreenControllerView(this);
|
|
||||||
activityLayout.addView(mTouchscreenController);
|
|
||||||
mTouchscreenController.init(0, controllerType);
|
|
||||||
setTouchscreenControllerVisibility(getBooleanSetting("Controller1/EnableTouchscreenController", true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -263,51 +260,43 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
|
||||||
if (mGameTitle != null && !mGameTitle.isEmpty())
|
if (mGameTitle != null && !mGameTitle.isEmpty())
|
||||||
builder.setTitle(mGameTitle);
|
builder.setTitle(mGameTitle);
|
||||||
|
|
||||||
builder.setItems(R.array.emulation_menu, new DialogInterface.OnClickListener() {
|
builder.setItems(R.array.emulation_menu, (dialogInterface, i) -> {
|
||||||
@Override
|
switch (i)
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
{
|
||||||
switch (i)
|
case 0: // Quick Load
|
||||||
{
|
{
|
||||||
case 0: // Quick Load
|
AndroidHostInterface.getInstance().loadState(false, 0);
|
||||||
{
|
return;
|
||||||
AndroidHostInterface.getInstance().loadState(false, 0);
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 1: // Quick Save
|
case 1: // Quick Save
|
||||||
{
|
{
|
||||||
AndroidHostInterface.getInstance().saveState(false, 0);
|
AndroidHostInterface.getInstance().saveState(false, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2: // Toggle Speed Limiter
|
case 2: // Toggle Speed Limiter
|
||||||
{
|
{
|
||||||
boolean newSetting = !getBooleanSetting("Main/SpeedLimiterEnabled", true);
|
boolean newSetting = !getBooleanSetting("Main/SpeedLimiterEnabled", true);
|
||||||
setBooleanSetting("Main/SpeedLimiterEnabled", newSetting);
|
setBooleanSetting("Main/SpeedLimiterEnabled", newSetting);
|
||||||
applySettings();
|
applySettings();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 3: // More Options
|
case 3: // More Options
|
||||||
{
|
{
|
||||||
showMoreMenu();
|
showMoreMenu();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 4: // Quit
|
case 4: // Quit
|
||||||
{
|
{
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
builder.setOnDismissListener(dialogInterface -> enableFullscreenImmersive());
|
||||||
@Override
|
|
||||||
public void onDismiss(DialogInterface dialogInterface) {
|
|
||||||
enableFullscreenImmersive();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,56 +305,59 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
|
||||||
if (mGameTitle != null && !mGameTitle.isEmpty())
|
if (mGameTitle != null && !mGameTitle.isEmpty())
|
||||||
builder.setTitle(mGameTitle);
|
builder.setTitle(mGameTitle);
|
||||||
|
|
||||||
builder.setItems(R.array.emulation_more_menu, new DialogInterface.OnClickListener() {
|
builder.setItems(R.array.emulation_more_menu, (dialogInterface, i) -> {
|
||||||
@Override
|
switch (i)
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
{
|
||||||
switch (i)
|
case 0: // Reset
|
||||||
{
|
{
|
||||||
case 0: // Reset
|
AndroidHostInterface.getInstance().resetSystem();
|
||||||
{
|
return;
|
||||||
AndroidHostInterface.getInstance().resetSystem();
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 1: // Cheats
|
case 1: // Cheats
|
||||||
{
|
{
|
||||||
showCheatsMenu();
|
showCheatsMenu();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2: // Change Disc
|
case 2: // Change Disc
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 3: // Toggle Touchscreen Controller
|
case 3: // Change Touchscreen Controller
|
||||||
{
|
{
|
||||||
setTouchscreenControllerVisibility(!mTouchscreenControllerVisible);
|
showTouchscreenControllerMenu();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 4: // Settings
|
case 4: // Settings
|
||||||
{
|
{
|
||||||
Intent intent = new Intent(EmulationActivity.this, SettingsActivity.class);
|
Intent intent = new Intent(EmulationActivity.this, SettingsActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
startActivityForResult(intent, REQUEST_CODE_SETTINGS);
|
startActivityForResult(intent, REQUEST_CODE_SETTINGS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 5: // Quit
|
case 5: // Quit
|
||||||
{
|
{
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
builder.setOnDismissListener(dialogInterface -> enableFullscreenImmersive());
|
||||||
@Override
|
builder.create().show();
|
||||||
public void onDismiss(DialogInterface dialogInterface) {
|
}
|
||||||
enableFullscreenImmersive();
|
|
||||||
}
|
private void showTouchscreenControllerMenu() {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setItems(R.array.settings_touchscreen_controller_view_entries, (dialogInterface, i) -> {
|
||||||
|
String[] values = getResources().getStringArray(R.array.settings_touchscreen_controller_view_values);
|
||||||
|
setStringSetting("Controller1/TouchscreenControllerView", values[i]);
|
||||||
|
updateControllers();
|
||||||
});
|
});
|
||||||
|
builder.setOnDismissListener(dialogInterface -> enableFullscreenImmersive());
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,18 +376,8 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
|
||||||
items[i] = String.format("%s %s", cc.isEnabled() ? "(ON)" : "(OFF)", cc.getName());
|
items[i] = String.format("%s %s", cc.isEnabled() ? "(ON)" : "(OFF)", cc.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.setItems(items, new DialogInterface.OnClickListener() {
|
builder.setItems(items, (dialogInterface, i) -> AndroidHostInterface.getInstance().setCheatEnabled(i, !cheats[i].isEnabled()));
|
||||||
@Override
|
builder.setOnDismissListener(dialogInterface -> enableFullscreenImmersive());
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
|
||||||
AndroidHostInterface.getInstance().setCheatEnabled(i, !cheats[i].isEnabled());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
|
||||||
@Override
|
|
||||||
public void onDismiss(DialogInterface dialogInterface) {
|
|
||||||
enableFullscreenImmersive();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,10 +385,29 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
|
||||||
* Touchscreen controller overlay
|
* Touchscreen controller overlay
|
||||||
*/
|
*/
|
||||||
TouchscreenControllerView mTouchscreenController;
|
TouchscreenControllerView mTouchscreenController;
|
||||||
private boolean mTouchscreenControllerVisible = true;
|
|
||||||
|
|
||||||
private void setTouchscreenControllerVisibility(boolean visible) {
|
public void updateControllers() {
|
||||||
mTouchscreenControllerVisible = visible;
|
final String controllerType = getStringSetting("Controller1/Type", "DigitalController");
|
||||||
mTouchscreenController.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
|
final String viewType = getStringSetting("Controller1/TouchscreenControllerView", "digital");
|
||||||
|
final FrameLayout activityLayout = findViewById(R.id.frameLayout);
|
||||||
|
|
||||||
|
Log.i("EmulationActivity", "Controller type: " + controllerType);
|
||||||
|
Log.i("EmulationActivity", "View type: " + viewType);
|
||||||
|
|
||||||
|
mContentView.initControllerKeyMapping(controllerType);
|
||||||
|
|
||||||
|
if (controllerType == "none" || viewType == "none") {
|
||||||
|
if (mTouchscreenController != null) {
|
||||||
|
activityLayout.removeView(mTouchscreenController);
|
||||||
|
mTouchscreenController = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mTouchscreenController == null) {
|
||||||
|
mTouchscreenController = new TouchscreenControllerView(this);
|
||||||
|
activityLayout.addView(mTouchscreenController);
|
||||||
|
}
|
||||||
|
|
||||||
|
mTouchscreenController.init(0, controllerType, viewType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
package com.github.stenzek.duckstation;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
public class TouchscreenControllerAxisView extends View {
|
||||||
|
private Drawable mBaseDrawable;
|
||||||
|
private Drawable mStickUnpressedDrawable;
|
||||||
|
private Drawable mStickPressedDrawable;
|
||||||
|
private boolean mPressed = false;
|
||||||
|
private int mPointerId = 0;
|
||||||
|
private float mXValue = 0.0f;
|
||||||
|
private float mYValue = 0.0f;
|
||||||
|
private int mDrawXPos = 0;
|
||||||
|
private int mDrawYPos = 0;
|
||||||
|
|
||||||
|
private int mControllerIndex = -1;
|
||||||
|
private int mXAxisCode = -1;
|
||||||
|
private int mYAxisCode = -1;
|
||||||
|
private int mLeftButtonCode = -1;
|
||||||
|
private int mRightButtonCode = -1;
|
||||||
|
private int mUpButtonCode = -1;
|
||||||
|
private int mDownButtonCode = -1;
|
||||||
|
|
||||||
|
public TouchscreenControllerAxisView(Context context) {
|
||||||
|
super(context);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TouchscreenControllerAxisView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TouchscreenControllerAxisView(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
mBaseDrawable = getContext().getDrawable(R.drawable.ic_controller_analog_base);
|
||||||
|
mBaseDrawable.setCallback(this);
|
||||||
|
mStickUnpressedDrawable = getContext().getDrawable(R.drawable.ic_controller_analog_stick_unpressed);
|
||||||
|
mStickUnpressedDrawable.setCallback(this);
|
||||||
|
mStickPressedDrawable = getContext().getDrawable(R.drawable.ic_controller_analog_stick_pressed);
|
||||||
|
mStickPressedDrawable.setCallback(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControllerAxis(int controllerIndex, int xCode, int yCode) {
|
||||||
|
mControllerIndex = controllerIndex;
|
||||||
|
mXAxisCode = xCode;
|
||||||
|
mYAxisCode = yCode;
|
||||||
|
mLeftButtonCode = -1;
|
||||||
|
mRightButtonCode = -1;
|
||||||
|
mUpButtonCode = -1;
|
||||||
|
mDownButtonCode = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControllerButtons(int controllerIndex, int leftCode, int rightCode, int upCode, int downCode) {
|
||||||
|
mControllerIndex = controllerIndex;
|
||||||
|
mXAxisCode = -1;
|
||||||
|
mYAxisCode = -1;
|
||||||
|
mLeftButtonCode = leftCode;
|
||||||
|
mRightButtonCode = rightCode;
|
||||||
|
mUpButtonCode = upCode;
|
||||||
|
mDownButtonCode = downCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUnpressed() {
|
||||||
|
if (!mPressed && mXValue == 0.0f && mYValue == 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mPressed = false;
|
||||||
|
mXValue = 0.0f;
|
||||||
|
mYValue = 0.0f;
|
||||||
|
mDrawXPos = 0;
|
||||||
|
mDrawYPos = 0;
|
||||||
|
invalidate();
|
||||||
|
updateControllerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPressed(int pointerId, float pointerX, float pointerY) {
|
||||||
|
final float dx = pointerX - (float)(getX() + (float)(getWidth() / 2));
|
||||||
|
final float dy = pointerY - (float)(getY() + (float)(getHeight() / 2));
|
||||||
|
// Log.i("SetPressed", String.format("px=%f,py=%f dx=%f,dy=%f", pointerX, pointerY, dx, dy));
|
||||||
|
|
||||||
|
final float pointerDistance = Math.max(Math.abs(dx), Math.abs(dy));
|
||||||
|
final float angle = (float)Math.atan2((double)dy, (double)dx);
|
||||||
|
|
||||||
|
final float maxDistance = (float)Math.min((getWidth() - getPaddingLeft() - getPaddingRight()) / 2, (getHeight() - getPaddingTop() - getPaddingBottom()) / 2);
|
||||||
|
final float length = Math.min(pointerDistance / maxDistance, 1.0f);
|
||||||
|
// Log.i("SetPressed", String.format("pointerDist=%f,angle=%f,w=%d,h=%d,maxDist=%f,length=%f", pointerDistance, angle, getWidth(), getHeight(), maxDistance, length));
|
||||||
|
|
||||||
|
final float xValue = (float)Math.cos((double)angle) * length;
|
||||||
|
final float yValue = (float)Math.sin((double)angle) * length;
|
||||||
|
mDrawXPos = (int)(xValue * maxDistance);
|
||||||
|
mDrawYPos = (int)(yValue * maxDistance);
|
||||||
|
|
||||||
|
boolean doUpdate = (pointerId != mPointerId || !mPressed || (xValue != mXValue || yValue != mYValue));
|
||||||
|
mPointerId = pointerId;
|
||||||
|
mPressed = true;
|
||||||
|
mXValue = xValue;
|
||||||
|
mYValue = yValue;
|
||||||
|
// Log.i("SetPressed", String.format("xval=%f,yval=%f,drawX=%d,drawY=%d", mXValue, mYValue, mDrawXPos, mDrawYPos));
|
||||||
|
|
||||||
|
if (doUpdate) {
|
||||||
|
invalidate();
|
||||||
|
updateControllerState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateControllerState() {
|
||||||
|
final float BUTTON_THRESHOLD = 0.33f;
|
||||||
|
|
||||||
|
AndroidHostInterface hostInterface = AndroidHostInterface.getInstance();
|
||||||
|
if (mXAxisCode >= 0)
|
||||||
|
hostInterface.setControllerAxisState(mControllerIndex, mXAxisCode, mXValue);
|
||||||
|
if (mYAxisCode >= 0)
|
||||||
|
hostInterface.setControllerAxisState(mControllerIndex, mYAxisCode, mYValue);
|
||||||
|
|
||||||
|
if (mLeftButtonCode >= 0)
|
||||||
|
hostInterface.setControllerButtonState(mControllerIndex, mLeftButtonCode, (mXValue <= -BUTTON_THRESHOLD));
|
||||||
|
if (mRightButtonCode >= 0)
|
||||||
|
hostInterface.setControllerButtonState(mControllerIndex, mRightButtonCode, (mXValue >= BUTTON_THRESHOLD));
|
||||||
|
if (mUpButtonCode >= 0)
|
||||||
|
hostInterface.setControllerButtonState(mControllerIndex, mUpButtonCode, (mYValue <= -BUTTON_THRESHOLD));
|
||||||
|
if (mDownButtonCode >= 0)
|
||||||
|
hostInterface.setControllerButtonState(mControllerIndex, mDownButtonCode, (mYValue >= BUTTON_THRESHOLD));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
|
||||||
|
final int paddingLeft = getPaddingLeft();
|
||||||
|
final int paddingTop = getPaddingTop();
|
||||||
|
final int paddingRight = getPaddingRight();
|
||||||
|
final int paddingBottom = getPaddingBottom();
|
||||||
|
final int contentWidth = getWidth() - paddingLeft - paddingRight;
|
||||||
|
final int contentHeight = getHeight() - paddingTop - paddingBottom;
|
||||||
|
|
||||||
|
mBaseDrawable.setBounds(paddingLeft, paddingTop,
|
||||||
|
paddingLeft + contentWidth, paddingTop + contentHeight);
|
||||||
|
mBaseDrawable.draw(canvas);
|
||||||
|
|
||||||
|
final int stickWidth = contentWidth / 3;
|
||||||
|
final int stickHeight = contentHeight / 3;
|
||||||
|
final int halfStickWidth = stickWidth / 2;
|
||||||
|
final int halfStickHeight = stickHeight / 2;
|
||||||
|
final int centerX = getWidth() / 2;
|
||||||
|
final int centerY = getHeight() / 2;
|
||||||
|
final int drawX = centerX + mDrawXPos;
|
||||||
|
final int drawY = centerY + mDrawYPos;
|
||||||
|
|
||||||
|
Drawable stickDrawable = mPressed ? mStickPressedDrawable : mStickUnpressedDrawable;
|
||||||
|
stickDrawable.setBounds(drawX - halfStickWidth, drawY - halfStickHeight, drawX + halfStickWidth, drawY + halfStickHeight);
|
||||||
|
stickDrawable.draw(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPressed() {
|
||||||
|
return mPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPointerId() {
|
||||||
|
return mPointerId >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPointerId() {
|
||||||
|
return mPointerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointerId(int mPointerId) {
|
||||||
|
this.mPointerId = mPointerId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,8 +16,8 @@ public class TouchscreenControllerButtonView extends View {
|
||||||
private Drawable mUnpressedDrawable;
|
private Drawable mUnpressedDrawable;
|
||||||
private Drawable mPressedDrawable;
|
private Drawable mPressedDrawable;
|
||||||
private boolean mPressed = false;
|
private boolean mPressed = false;
|
||||||
|
private int mControllerIndex = -1;
|
||||||
private int mButtonCode = -1;
|
private int mButtonCode = -1;
|
||||||
private String mButtonName = "";
|
|
||||||
|
|
||||||
public TouchscreenControllerButtonView(Context context) {
|
public TouchscreenControllerButtonView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
@ -56,13 +56,12 @@ public class TouchscreenControllerButtonView extends View {
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
super.onDraw(canvas);
|
super.onDraw(canvas);
|
||||||
|
|
||||||
int paddingLeft = getPaddingLeft();
|
final int paddingLeft = getPaddingLeft();
|
||||||
int paddingTop = getPaddingTop();
|
final int paddingTop = getPaddingTop();
|
||||||
int paddingRight = getPaddingRight();
|
final int paddingRight = getPaddingRight();
|
||||||
int paddingBottom = getPaddingBottom();
|
final int paddingBottom = getPaddingBottom();
|
||||||
|
final int contentWidth = getWidth() - paddingLeft - paddingRight;
|
||||||
int contentWidth = getWidth() - paddingLeft - paddingRight;
|
final int contentHeight = getHeight() - paddingTop - paddingBottom;
|
||||||
int contentHeight = getHeight() - paddingTop - paddingBottom;
|
|
||||||
|
|
||||||
// Draw the example drawable on top of the text.
|
// Draw the example drawable on top of the text.
|
||||||
Drawable drawable = mPressed ? mPressedDrawable : mUnpressedDrawable;
|
Drawable drawable = mPressed ? mPressedDrawable : mUnpressedDrawable;
|
||||||
|
@ -77,24 +76,25 @@ public class TouchscreenControllerButtonView extends View {
|
||||||
return mPressed;
|
return mPressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPressed(boolean pressed) { mPressed = pressed; invalidate(); }
|
public void setPressed(boolean pressed) {
|
||||||
|
if (pressed == mPressed)
|
||||||
|
return;
|
||||||
|
|
||||||
public String getButtonName() {
|
mPressed = pressed;
|
||||||
return mButtonName;
|
invalidate();
|
||||||
|
updateControllerState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setButtonName(String buttonName) {
|
public void setButtonCode(int controllerIndex, int code) {
|
||||||
mButtonName = buttonName;
|
mControllerIndex = controllerIndex;
|
||||||
}
|
|
||||||
|
|
||||||
public int getButtonCode() {
|
|
||||||
return mButtonCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setButtonCode(int code) {
|
|
||||||
mButtonCode = code;
|
mButtonCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateControllerState() {
|
||||||
|
if (mButtonCode >= 0)
|
||||||
|
AndroidHostInterface.getInstance().setControllerButtonState(mControllerIndex, mButtonCode, mPressed);
|
||||||
|
}
|
||||||
|
|
||||||
public Drawable getPressedDrawable() {
|
public Drawable getPressedDrawable() {
|
||||||
return mPressedDrawable;
|
return mPressedDrawable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.github.stenzek.duckstation;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.text.method.Touch;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -11,7 +10,6 @@ import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: document your custom view class.
|
* TODO: document your custom view class.
|
||||||
|
@ -19,7 +17,9 @@ import java.util.HashMap;
|
||||||
public class TouchscreenControllerView extends FrameLayout {
|
public class TouchscreenControllerView extends FrameLayout {
|
||||||
private int mControllerIndex;
|
private int mControllerIndex;
|
||||||
private String mControllerType;
|
private String mControllerType;
|
||||||
|
private View mMainView;
|
||||||
private ArrayList<TouchscreenControllerButtonView> mButtonViews = new ArrayList<>();
|
private ArrayList<TouchscreenControllerButtonView> mButtonViews = new ArrayList<>();
|
||||||
|
private ArrayList<TouchscreenControllerAxisView> mAxisViews = new ArrayList<>();
|
||||||
|
|
||||||
public TouchscreenControllerView(Context context) {
|
public TouchscreenControllerView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
@ -33,43 +33,72 @@ public class TouchscreenControllerView extends FrameLayout {
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(int controllerIndex, String controllerType) {
|
public void init(int controllerIndex, String controllerType, String viewType) {
|
||||||
mControllerIndex = controllerIndex;
|
mControllerIndex = controllerIndex;
|
||||||
mControllerType = controllerType;
|
mControllerType = controllerType;
|
||||||
|
|
||||||
|
mButtonViews.clear();
|
||||||
|
mAxisViews.clear();
|
||||||
|
removeAllViews();
|
||||||
|
|
||||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||||
View view = inflater.inflate(R.layout.layout_touchscreen_controller, this, true);
|
switch (viewType)
|
||||||
view.setOnTouchListener((view1, event) -> {
|
{
|
||||||
|
case "none":
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "digital":
|
||||||
|
mMainView = inflater.inflate(R.layout.layout_touchscreen_controller_digital, this, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "analog_stick":
|
||||||
|
mMainView = inflater.inflate(R.layout.layout_touchscreen_controller_analog_stick, this, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "analog_sticks":
|
||||||
|
mMainView = inflater.inflate(R.layout.layout_touchscreen_controller_analog_sticks, this, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
mMainView = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mMainView.setOnTouchListener((view1, event) -> {
|
||||||
return handleTouchEvent(event);
|
return handleTouchEvent(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Make dynamic, editable.
|
linkButton(mMainView, R.id.controller_button_up, "Up");
|
||||||
mButtonViews.clear();
|
linkButton(mMainView, R.id.controller_button_right, "Right");
|
||||||
linkButton(view, R.id.controller_button_up, "Up");
|
linkButton(mMainView, R.id.controller_button_down, "Down");
|
||||||
linkButton(view, R.id.controller_button_right, "Right");
|
linkButton(mMainView, R.id.controller_button_left, "Left");
|
||||||
linkButton(view, R.id.controller_button_down, "Down");
|
linkButton(mMainView, R.id.controller_button_l1, "L1");
|
||||||
linkButton(view, R.id.controller_button_left, "Left");
|
linkButton(mMainView, R.id.controller_button_l2, "L2");
|
||||||
linkButton(view, R.id.controller_button_l1, "L1");
|
linkButton(mMainView, R.id.controller_button_select, "Select");
|
||||||
linkButton(view, R.id.controller_button_l2, "L2");
|
linkButton(mMainView, R.id.controller_button_start, "Start");
|
||||||
linkButton(view, R.id.controller_button_select, "Select");
|
linkButton(mMainView, R.id.controller_button_triangle, "Triangle");
|
||||||
linkButton(view, R.id.controller_button_start, "Start");
|
linkButton(mMainView, R.id.controller_button_circle, "Circle");
|
||||||
linkButton(view, R.id.controller_button_triangle, "Triangle");
|
linkButton(mMainView, R.id.controller_button_cross, "Cross");
|
||||||
linkButton(view, R.id.controller_button_circle, "Circle");
|
linkButton(mMainView, R.id.controller_button_square, "Square");
|
||||||
linkButton(view, R.id.controller_button_cross, "Cross");
|
linkButton(mMainView, R.id.controller_button_r1, "R1");
|
||||||
linkButton(view, R.id.controller_button_square, "Square");
|
linkButton(mMainView, R.id.controller_button_r2, "R2");
|
||||||
linkButton(view, R.id.controller_button_r1, "R1");
|
|
||||||
linkButton(view, R.id.controller_button_r2, "R2");
|
if (!linkAxis(mMainView, R.id.controller_axis_left, "Left"))
|
||||||
|
linkAxisToButtons(mMainView, R.id.controller_axis_left, "");
|
||||||
|
|
||||||
|
linkAxis(mMainView, R.id.controller_axis_right, "Right");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void linkButton(View view, int id, String buttonName) {
|
private void linkButton(View view, int id, String buttonName) {
|
||||||
TouchscreenControllerButtonView buttonView = (TouchscreenControllerButtonView) view.findViewById(id);
|
TouchscreenControllerButtonView buttonView = (TouchscreenControllerButtonView) view.findViewById(id);
|
||||||
buttonView.setButtonName(buttonName);
|
if (buttonView == null)
|
||||||
|
return;
|
||||||
|
|
||||||
int code = AndroidHostInterface.getInstance().getControllerButtonCode(mControllerType, buttonName);
|
int code = AndroidHostInterface.getInstance().getControllerButtonCode(mControllerType, buttonName);
|
||||||
buttonView.setButtonCode(code);
|
|
||||||
Log.i("TouchscreenController", String.format("%s -> %d", buttonName, code));
|
Log.i("TouchscreenController", String.format("%s -> %d", buttonName, code));
|
||||||
|
|
||||||
if (code >= 0) {
|
if (code >= 0) {
|
||||||
|
buttonView.setButtonCode(mControllerIndex, code);
|
||||||
mButtonViews.add(buttonView);
|
mButtonViews.add(buttonView);
|
||||||
} else {
|
} else {
|
||||||
Log.e("TouchscreenController", String.format("Unknown button name '%s' " +
|
Log.e("TouchscreenController", String.format("Unknown button name '%s' " +
|
||||||
|
@ -77,12 +106,53 @@ public class TouchscreenControllerView extends FrameLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean linkAxis(View view, int id, String axisName) {
|
||||||
|
TouchscreenControllerAxisView axisView = (TouchscreenControllerAxisView) view.findViewById(id);
|
||||||
|
if (axisView == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int xCode = AndroidHostInterface.getInstance().getControllerAxisCode(mControllerType, axisName + "X");
|
||||||
|
int yCode = AndroidHostInterface.getInstance().getControllerAxisCode(mControllerType, axisName + "Y");
|
||||||
|
Log.i("TouchscreenController", String.format("%s -> %d/%d", axisName, xCode, yCode));
|
||||||
|
if (xCode < 0 && yCode < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
axisView.setControllerAxis(mControllerIndex, xCode, yCode);
|
||||||
|
mAxisViews.add(axisView);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean linkAxisToButtons(View view, int id, String buttonPrefix) {
|
||||||
|
TouchscreenControllerAxisView axisView = (TouchscreenControllerAxisView) view.findViewById(id);
|
||||||
|
if (axisView == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int leftCode = AndroidHostInterface.getInstance().getControllerButtonCode(mControllerType, buttonPrefix + "Left");
|
||||||
|
int rightCode = AndroidHostInterface.getInstance().getControllerButtonCode(mControllerType, buttonPrefix + "Right");
|
||||||
|
int upCode = AndroidHostInterface.getInstance().getControllerButtonCode(mControllerType, buttonPrefix + "Up");
|
||||||
|
int downCode = AndroidHostInterface.getInstance().getControllerButtonCode(mControllerType, buttonPrefix + "Down");
|
||||||
|
Log.i("TouchscreenController", String.format("%s(ButtonAxis) -> %d,%d,%d,%d", buttonPrefix, leftCode, rightCode, upCode, downCode));
|
||||||
|
if (leftCode < 0 && rightCode < 0 && upCode < 0 && downCode < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
axisView.setControllerButtons(mControllerIndex, leftCode, rightCode, upCode, downCode);
|
||||||
|
mAxisViews.add(axisView);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean handleTouchEvent(MotionEvent event) {
|
private boolean handleTouchEvent(MotionEvent event) {
|
||||||
switch (event.getActionMasked())
|
switch (event.getActionMasked())
|
||||||
{
|
{
|
||||||
case MotionEvent.ACTION_UP:
|
case MotionEvent.ACTION_UP:
|
||||||
{
|
{
|
||||||
clearAllButtonPressedStates();
|
for (TouchscreenControllerButtonView buttonView : mButtonViews) {
|
||||||
|
buttonView.setPressed(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TouchscreenControllerAxisView axisView : mAxisViews) {
|
||||||
|
axisView.setUnpressed();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,13 +173,37 @@ public class TouchscreenControllerView extends FrameLayout {
|
||||||
|
|
||||||
final int x = (int) event.getX(i);
|
final int x = (int) event.getX(i);
|
||||||
final int y = (int) event.getY(i);
|
final int y = (int) event.getY(i);
|
||||||
pressed |= rect.contains(x, y);
|
if (rect.contains(x, y)) {
|
||||||
|
buttonView.setPressed(true);
|
||||||
|
pressed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (buttonView.isPressed() == pressed)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
buttonView.setPressed(pressed);
|
if (!pressed)
|
||||||
AndroidHostInterface.getInstance().setControllerButtonState(mControllerIndex, buttonView.getButtonCode(), pressed);
|
buttonView.setPressed(pressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TouchscreenControllerAxisView axisView : mAxisViews) {
|
||||||
|
axisView.getHitRect(rect);
|
||||||
|
boolean pressed = false;
|
||||||
|
for (int i = 0; i < pointerCount; i++) {
|
||||||
|
if (i == liftedPointerIndex)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
final int pointerId = event.getPointerId(i);
|
||||||
|
final int x = (int) event.getX(i);
|
||||||
|
final int y = (int) event.getY(i);
|
||||||
|
|
||||||
|
if ((rect.contains(x, y) && !axisView.isPressed()) ||
|
||||||
|
(axisView.isPressed() && axisView.getPointerId() == pointerId)) {
|
||||||
|
axisView.setPressed(pointerId, x, y);
|
||||||
|
pressed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pressed)
|
||||||
|
axisView.setUnpressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -118,14 +212,4 @@ public class TouchscreenControllerView extends FrameLayout {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearAllButtonPressedStates() {
|
|
||||||
for (TouchscreenControllerButtonView buttonView : mButtonViews) {
|
|
||||||
if (!buttonView.isPressed())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
AndroidHostInterface.getInstance().setControllerButtonState(mControllerIndex, buttonView.getButtonCode(), false);
|
|
||||||
buttonView.setPressed(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="194.89dp"
|
||||||
|
android:height="194.89dp"
|
||||||
|
android:viewportWidth="194.89"
|
||||||
|
android:viewportHeight="194.89">
|
||||||
|
<path
|
||||||
|
android:pathData="M194.89,97.445A97.445,97.445 0,0 1,97.445 194.89,97.445 97.445,0 0,1 0,97.445 97.445,97.445 0,0 1,97.445 0,97.445 97.445,0 0,1 194.89,97.445Z"
|
||||||
|
android:strokeAlpha="0.50645"
|
||||||
|
android:fillColor="#1a1a1a"
|
||||||
|
android:fillAlpha="0.504414"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M178.82,97.445A81.381,81.381 0,0 1,97.439 178.826,81.381 81.381,0 0,1 16.058,97.445 81.381,81.381 0,0 1,97.439 16.064,81.381 81.381,0 0,1 178.82,97.445Z"
|
||||||
|
android:strokeAlpha="0.50645"
|
||||||
|
android:fillColor="#333333"
|
||||||
|
android:fillAlpha="0.504414"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M159.05,97.445A61.609,61.609 0,0 1,97.441 159.054,61.609 61.609,0 0,1 35.832,97.445 61.609,61.609 0,0 1,97.441 35.836,61.609 61.609,0 0,1 159.05,97.445Z"
|
||||||
|
android:strokeAlpha="0.50645"
|
||||||
|
android:fillColor="#1a1a1a"
|
||||||
|
android:fillAlpha="0.504414"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="191.756dp"
|
||||||
|
android:height="191.756dp"
|
||||||
|
android:viewportWidth="191.756"
|
||||||
|
android:viewportHeight="191.756">
|
||||||
|
<path
|
||||||
|
android:pathData="M191.756,95.878A95.878,95.878 0,0 1,95.878 191.756,95.878 95.878,0 0,1 0,95.878 95.878,95.878 0,0 1,95.878 0,95.878 95.878,0 0,1 191.756,95.878Z"
|
||||||
|
android:strokeAlpha="0.8"
|
||||||
|
android:fillColor="#666666"
|
||||||
|
android:fillAlpha="0.796784"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="191.756dp"
|
||||||
|
android:height="191.756dp"
|
||||||
|
android:viewportWidth="191.756"
|
||||||
|
android:viewportHeight="191.756">
|
||||||
|
<path
|
||||||
|
android:pathData="M191.756,95.878A95.878,95.878 0,0 1,95.878 191.756,95.878 95.878,0 0,1 0,95.878 95.878,95.878 0,0 1,95.878 0,95.878 95.878,0 0,1 191.756,95.878Z"
|
||||||
|
android:strokeAlpha="0.50645"
|
||||||
|
android:fillColor="#666666"
|
||||||
|
android:fillAlpha="0.504414"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,136 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/constraintLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_r2"
|
||||||
|
android:layout_width="70dp"
|
||||||
|
android:layout_height="35dp"
|
||||||
|
android:layout_marginEnd="60dp"
|
||||||
|
android:layout_marginBottom="280dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_r2_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_r2_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_r1"
|
||||||
|
android:layout_width="70dp"
|
||||||
|
android:layout_height="35dp"
|
||||||
|
android:layout_marginEnd="60dp"
|
||||||
|
android:layout_marginBottom="220dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_r1_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_r1_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_l1"
|
||||||
|
android:layout_width="70dp"
|
||||||
|
android:layout_height="35dp"
|
||||||
|
android:layout_marginStart="60dp"
|
||||||
|
android:layout_marginBottom="220dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_l1_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_l1_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_l2"
|
||||||
|
android:layout_width="70dp"
|
||||||
|
android:layout_height="35dp"
|
||||||
|
android:layout_marginStart="60dp"
|
||||||
|
android:layout_marginBottom="280dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_l2_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_l2_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_start"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="25dp"
|
||||||
|
android:layout_marginStart="80dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_start_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_start_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_select"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="25dp"
|
||||||
|
android:layout_marginEnd="50dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_select_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_select_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_cross"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginEnd="70dp"
|
||||||
|
android:layout_marginBottom="30dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_cross_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_cross_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_square"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginEnd="120dp"
|
||||||
|
android:layout_marginBottom="80dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_square_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_square_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_triangle"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginEnd="70dp"
|
||||||
|
android:layout_marginBottom="130dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_triangle_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_triangle_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_circle"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:layout_marginBottom="80dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_circle_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_circle_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerAxisView
|
||||||
|
android:id="@+id/controller_axis_left"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginBottom="30dp"
|
||||||
|
android:paddingTop="20dp"
|
||||||
|
android:paddingBottom="20dp"
|
||||||
|
android:paddingLeft="20dp"
|
||||||
|
android:paddingRight="20dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,201 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/constraintLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_r2"
|
||||||
|
android:layout_width="70dp"
|
||||||
|
android:layout_height="35dp"
|
||||||
|
android:layout_marginEnd="60dp"
|
||||||
|
android:layout_marginBottom="260dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_r2_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_r2_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_r1"
|
||||||
|
android:layout_width="70dp"
|
||||||
|
android:layout_height="35dp"
|
||||||
|
android:layout_marginEnd="60dp"
|
||||||
|
android:layout_marginBottom="200dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_r1_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_r1_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_l1"
|
||||||
|
android:layout_width="70dp"
|
||||||
|
android:layout_height="35dp"
|
||||||
|
android:layout_marginStart="60dp"
|
||||||
|
android:layout_marginBottom="200dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_l1_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_l1_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_l2"
|
||||||
|
android:layout_width="70dp"
|
||||||
|
android:layout_height="35dp"
|
||||||
|
android:layout_marginStart="60dp"
|
||||||
|
android:layout_marginBottom="260dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_l2_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_l2_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_start"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="25dp"
|
||||||
|
android:layout_marginStart="80dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_start_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_start_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_select"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="25dp"
|
||||||
|
android:layout_marginEnd="50dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_select_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_select_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_cross"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginEnd="70dp"
|
||||||
|
android:layout_marginBottom="30dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_cross_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_cross_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_square"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginEnd="120dp"
|
||||||
|
android:layout_marginBottom="80dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_square_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_square_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_triangle"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginEnd="70dp"
|
||||||
|
android:layout_marginBottom="130dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_triangle_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_triangle_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_circle"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:layout_marginBottom="80dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_circle_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_circle_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerAxisView
|
||||||
|
android:id="@+id/controller_axis_left"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginBottom="30dp"
|
||||||
|
android:paddingTop="20dp"
|
||||||
|
android:paddingBottom="20dp"
|
||||||
|
android:paddingLeft="20dp"
|
||||||
|
android:paddingRight="20dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerAxisView
|
||||||
|
android:id="@+id/controller_axis_right"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:layout_marginBottom="300dp"
|
||||||
|
android:paddingLeft="20dp"
|
||||||
|
android:paddingTop="20dp"
|
||||||
|
android:paddingRight="20dp"
|
||||||
|
android:paddingBottom="20dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_left"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginBottom="300dp"
|
||||||
|
android:paddingTop="50dp"
|
||||||
|
android:paddingBottom="50dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_left_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_left_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_down"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginBottom="300dp"
|
||||||
|
android:paddingStart="50dp"
|
||||||
|
android:paddingEnd="50dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_down_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_down_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_right"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:layout_marginStart="120dp"
|
||||||
|
android:layout_marginBottom="300dp"
|
||||||
|
android:paddingTop="50dp"
|
||||||
|
android:paddingBottom="50dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_right_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_right_button" />
|
||||||
|
|
||||||
|
<com.github.stenzek.duckstation.TouchscreenControllerButtonView
|
||||||
|
android:id="@+id/controller_button_up"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginBottom="400dp"
|
||||||
|
android:paddingStart="50dp"
|
||||||
|
android:paddingEnd="50dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:pressedDrawable="@drawable/ic_controller_up_button_pressed"
|
||||||
|
app:unpressedDrawable="@drawable/ic_controller_up_button" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -136,7 +136,7 @@
|
||||||
<item>Reset</item>
|
<item>Reset</item>
|
||||||
<item>Cheats</item>
|
<item>Cheats</item>
|
||||||
<item>Change Disc</item>
|
<item>Change Disc</item>
|
||||||
<item>Toggle Touch Controller</item>
|
<item>Change Touchscreen Controller</item>
|
||||||
<item>Settings</item>
|
<item>Settings</item>
|
||||||
<item>Quit</item>
|
<item>Quit</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
@ -164,4 +164,16 @@
|
||||||
<item>9</item>
|
<item>9</item>
|
||||||
<item>10</item>
|
<item>10</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array name="settings_touchscreen_controller_view_entries">
|
||||||
|
<item>None</item>
|
||||||
|
<item>Digital Pad</item>
|
||||||
|
<item>Single Analog Pad</item>
|
||||||
|
<item>Dual Analog Pad</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="settings_touchscreen_controller_view_values">
|
||||||
|
<item>none</item>
|
||||||
|
<item>digital</item>
|
||||||
|
<item>analog_stick</item>
|
||||||
|
<item>analog_sticks</item>
|
||||||
|
</string-array>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -271,10 +271,13 @@
|
||||||
app:title="Enable Analog Mode On Reset"
|
app:title="Enable Analog Mode On Reset"
|
||||||
app:defaultValue="false"
|
app:defaultValue="false"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
<SwitchPreferenceCompat
|
<ListPreference
|
||||||
app:key="Controller1/EnableTouchscreenController"
|
app:key="Controller1/TouchscreenControllerView"
|
||||||
app:title="Display Touchscreen Controller"
|
app:title="Touchscreen Controller View"
|
||||||
app:defaultValue="true"
|
app:entries="@array/settings_touchscreen_controller_view_entries"
|
||||||
|
app:entryValues="@array/settings_touchscreen_controller_view_values"
|
||||||
|
app:defaultValue="digital"
|
||||||
|
app:useSimpleSummaryProvider="true"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue