mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2026-04-20 17:47:03 -04:00
v
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,3 +2,6 @@
|
||||
/build
|
||||
/*/build
|
||||
app_pojavlauncher/src/main/assets/components/jre
|
||||
local.properties
|
||||
.idea/
|
||||
app_pojavlauncher/.cxx/
|
||||
|
||||
@@ -116,14 +116,17 @@ dependencies {
|
||||
// implementation 'com.wu-man:android-bsf-api:3.1.3'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||
implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation 'androidx.annotation:annotation:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation 'androidx.annotation:annotation:1.2.0'
|
||||
implementation 'androidx.browser:browser:1.3.0'
|
||||
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
|
||||
|
||||
implementation 'com.rarepebble:colorpicker:3.0.1'
|
||||
implementation 'com.github.duanhong169:checkerboarddrawable:1.0.2'
|
||||
|
||||
|
||||
// implementation 'com.intuit.sdp:sdp-android:1.0.5'
|
||||
// implementation 'com.intuit.ssp:ssp-android:1.0.5'
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.kdt;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
public class DefocusableScrollView extends ScrollView {
|
||||
|
||||
/*
|
||||
What is this class for ?
|
||||
It allows to ignore the focusing from an item such an EditText.
|
||||
Ignoring it will stop the scrollView from refocusing on the view
|
||||
*/
|
||||
|
||||
private boolean keepFocusing = false;
|
||||
|
||||
|
||||
public DefocusableScrollView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public DefocusableScrollView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public DefocusableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public DefocusableScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public void setKeepFocusing(boolean shouldKeepFocusing){
|
||||
keepFocusing = shouldKeepFocusing;
|
||||
}
|
||||
|
||||
public boolean isKeepFocusing(){
|
||||
return keepFocusing;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
|
||||
if(!keepFocusing) return 0;
|
||||
return super.computeScrollDeltaToGetChildRectOnScreen(rect);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
package net.kdt.pojavlaunch;
|
||||
|
||||
import android.util.*;
|
||||
import android.view.*;
|
||||
|
||||
import java.net.CookieHandler;
|
||||
import java.util.*;
|
||||
|
||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||
import org.lwjgl.glfw.*;
|
||||
|
||||
public class AndroidLWJGLKeycode {
|
||||
// Fix double letters on MC 1.9 and above
|
||||
public static boolean isBackspaceAfterChar = true;
|
||||
public static final ArrayMap<Integer, Integer> androidToLwjglMap;
|
||||
public static String[] androidKeyNameArray;
|
||||
|
||||
static {
|
||||
// Mapping Android Keycodes to LWJGL Keycodes
|
||||
androidToLwjglMap = new ArrayMap<Integer, Integer>();
|
||||
|
||||
// 0-9 keys
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_0, LWJGLGLFWKeycode.GLFW_KEY_0);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_1, LWJGLGLFWKeycode.GLFW_KEY_1);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_2, LWJGLGLFWKeycode.GLFW_KEY_2);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_3, LWJGLGLFWKeycode.GLFW_KEY_3);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_4, LWJGLGLFWKeycode.GLFW_KEY_4);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_5, LWJGLGLFWKeycode.GLFW_KEY_5);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_6, LWJGLGLFWKeycode.GLFW_KEY_6);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_7, LWJGLGLFWKeycode.GLFW_KEY_7);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_8, LWJGLGLFWKeycode.GLFW_KEY_8);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_9, LWJGLGLFWKeycode.GLFW_KEY_9);
|
||||
|
||||
// A-Z keys
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_A, LWJGLGLFWKeycode.GLFW_KEY_A);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_B, LWJGLGLFWKeycode.GLFW_KEY_B);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_C, LWJGLGLFWKeycode.GLFW_KEY_C);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_D, LWJGLGLFWKeycode.GLFW_KEY_D);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_E, LWJGLGLFWKeycode.GLFW_KEY_E);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F, LWJGLGLFWKeycode.GLFW_KEY_F);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_G, LWJGLGLFWKeycode.GLFW_KEY_G);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_H, LWJGLGLFWKeycode.GLFW_KEY_H);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_I, LWJGLGLFWKeycode.GLFW_KEY_I);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_J, LWJGLGLFWKeycode.GLFW_KEY_J);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_K, LWJGLGLFWKeycode.GLFW_KEY_K);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_L, LWJGLGLFWKeycode.GLFW_KEY_L);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_M, LWJGLGLFWKeycode.GLFW_KEY_M);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_N, LWJGLGLFWKeycode.GLFW_KEY_N);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_O, LWJGLGLFWKeycode.GLFW_KEY_O);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_P, LWJGLGLFWKeycode.GLFW_KEY_P);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_Q, LWJGLGLFWKeycode.GLFW_KEY_Q);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_R, LWJGLGLFWKeycode.GLFW_KEY_R);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_S, LWJGLGLFWKeycode.GLFW_KEY_S);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_T, LWJGLGLFWKeycode.GLFW_KEY_T);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_U, LWJGLGLFWKeycode.GLFW_KEY_U);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_V, LWJGLGLFWKeycode.GLFW_KEY_V);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_W, LWJGLGLFWKeycode.GLFW_KEY_W);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_X, LWJGLGLFWKeycode.GLFW_KEY_X);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_Y, LWJGLGLFWKeycode.GLFW_KEY_Y);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_Z, LWJGLGLFWKeycode.GLFW_KEY_Z);
|
||||
|
||||
// Alt keys
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_ALT_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT_ALT);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_ALT_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_ALT);
|
||||
|
||||
// Escape key
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_BACK, LWJGLGLFWKeycode.GLFW_KEY_ESCAPE);
|
||||
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_BACKSLASH, LWJGLGLFWKeycode.GLFW_KEY_BACKSLASH);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_BREAK, LWJGLGLFWKeycode.GLFW_KEY_PAUSE);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_CAPS_LOCK, LWJGLGLFWKeycode.GLFW_KEY_CAPS_LOCK);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_COMMA, LWJGLGLFWKeycode.GLFW_KEY_COMMA);
|
||||
|
||||
// Control keys
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_CTRL_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT_CONTROL);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_CTRL_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_CONTROL);
|
||||
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_DEL, LWJGLGLFWKeycode.GLFW_KEY_BACKSPACE); // Backspace
|
||||
|
||||
// Arrow keys
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_DPAD_DOWN, LWJGLGLFWKeycode.GLFW_KEY_DOWN);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_DPAD_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_DPAD_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_DPAD_UP, LWJGLGLFWKeycode.GLFW_KEY_UP);
|
||||
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_ENTER, LWJGLGLFWKeycode.GLFW_KEY_ENTER);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_EQUALS, LWJGLGLFWKeycode.GLFW_KEY_EQUAL);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_ESCAPE, LWJGLGLFWKeycode.GLFW_KEY_ESCAPE);
|
||||
|
||||
// Fn keys
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F1, LWJGLGLFWKeycode.GLFW_KEY_F1);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F2, LWJGLGLFWKeycode.GLFW_KEY_F2);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F3, LWJGLGLFWKeycode.GLFW_KEY_F3);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F4, LWJGLGLFWKeycode.GLFW_KEY_F4);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F5, LWJGLGLFWKeycode.GLFW_KEY_F5);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F6, LWJGLGLFWKeycode.GLFW_KEY_F6);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F7, LWJGLGLFWKeycode.GLFW_KEY_F7);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F8, LWJGLGLFWKeycode.GLFW_KEY_F8);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F9, LWJGLGLFWKeycode.GLFW_KEY_F9);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F10, LWJGLGLFWKeycode.GLFW_KEY_F10);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F11, LWJGLGLFWKeycode.GLFW_KEY_F11);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_F12, LWJGLGLFWKeycode.GLFW_KEY_F12);
|
||||
// FIXME GLFW Function key
|
||||
// androidToLwjglMap.put(KeyEvent.KEYCODE_FUNCTION, LWJGLGLFWKeycode.GLFW_KEY_FUNCTION);
|
||||
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_GRAVE, LWJGLGLFWKeycode.GLFW_KEY_GRAVE_ACCENT);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_HOME, LWJGLGLFWKeycode.GLFW_KEY_HOME);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_INSERT, LWJGLGLFWKeycode.GLFW_KEY_INSERT);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_KANA, LWJGLGLFWKeycode.GLFW_KEY_K);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_LEFT_BRACKET, LWJGLGLFWKeycode.GLFW_KEY_LEFT_BRACKET);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_MINUS, LWJGLGLFWKeycode.GLFW_KEY_MINUS);
|
||||
|
||||
// Num keys
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUM_LOCK, LWJGLGLFWKeycode.GLFW_KEY_NUM_LOCK);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_0, LWJGLGLFWKeycode.GLFW_KEY_0);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_1, LWJGLGLFWKeycode.GLFW_KEY_1);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_2, LWJGLGLFWKeycode.GLFW_KEY_2);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_3, LWJGLGLFWKeycode.GLFW_KEY_3);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_4, LWJGLGLFWKeycode.GLFW_KEY_4);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_5, LWJGLGLFWKeycode.GLFW_KEY_5);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_6, LWJGLGLFWKeycode.GLFW_KEY_6);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_7, LWJGLGLFWKeycode.GLFW_KEY_7);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_8, LWJGLGLFWKeycode.GLFW_KEY_8);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_9, LWJGLGLFWKeycode.GLFW_KEY_9);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_ADD, LWJGLGLFWKeycode.GLFW_KEY_KP_ADD);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_COMMA, LWJGLGLFWKeycode.GLFW_KEY_COMMA);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE, LWJGLGLFWKeycode.GLFW_KEY_KP_DIVIDE);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_DOT, LWJGLGLFWKeycode.GLFW_KEY_PERIOD);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_ENTER, LWJGLGLFWKeycode.GLFW_KEY_ENTER);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_EQUALS, LWJGLGLFWKeycode.GLFW_KEY_EQUAL);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY, LWJGLGLFWKeycode.GLFW_KEY_KP_MULTIPLY);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT, LWJGLGLFWKeycode.GLFW_KEY_KP_SUBTRACT);
|
||||
|
||||
// Page keys
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_PAGE_DOWN, LWJGLGLFWKeycode.GLFW_KEY_PAGE_DOWN);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_PAGE_UP, LWJGLGLFWKeycode.GLFW_KEY_PAGE_UP);
|
||||
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_PERIOD, LWJGLGLFWKeycode.GLFW_KEY_PERIOD);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_PLUS, LWJGLGLFWKeycode.GLFW_KEY_KP_ADD);
|
||||
// androidToLwjglMap.put(KeyEvent.KEYCODE_POWER, LWJGLGLFWKeycode.GLFW_KEY_POWER);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_RIGHT_BRACKET, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_BRACKET);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_SEMICOLON, LWJGLGLFWKeycode.GLFW_KEY_SEMICOLON);
|
||||
|
||||
// Shift keys
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_SHIFT_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_SHIFT_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_SHIFT);
|
||||
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_SLASH, LWJGLGLFWKeycode.GLFW_KEY_SLASH);
|
||||
// androidToLwjglMap.put(KeyEvent.KEYCODE_SLEEP, LWJGLGLFWKeycode.GLFW_KEY_SLEEP);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_SPACE, LWJGLGLFWKeycode.GLFW_KEY_SPACE);
|
||||
// androidToLwjglMap.put(KeyEvent.KEYCODE_SYSRQ, LWJGLGLFWKeycode.GLFW_KEY_SYSRQ);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_TAB, LWJGLGLFWKeycode.GLFW_KEY_TAB);
|
||||
// androidToLwjglMap.put(KeyEvent.KEYCODE_YEN, LWJGLGLFWKeycode.GLFW_KEY_YEN);
|
||||
|
||||
// androidToLwjglMap.put(KeyEvent.KEYCODE_BUTTON_1, LWJGLGLFWKeycode.G
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_AT,LWJGLGLFWKeycode.GLFW_KEY_2);
|
||||
androidToLwjglMap.put(KeyEvent.KEYCODE_POUND,LWJGLGLFWKeycode.GLFW_KEY_3);
|
||||
}
|
||||
|
||||
public static String[] generateKeyName() {
|
||||
if (androidKeyNameArray == null) {
|
||||
List<String> keyName = new ArrayList<String>();
|
||||
for (Integer perKey : androidToLwjglMap.keySet()) {
|
||||
keyName.add(KeyEvent.keyCodeToString(perKey.intValue()).replace("KEYCODE_", ""));
|
||||
}
|
||||
androidKeyNameArray = keyName.toArray(new String[0]);
|
||||
}
|
||||
return androidKeyNameArray;
|
||||
}
|
||||
|
||||
public static void execKey(KeyEvent keyEvent, int i, boolean isDown) {
|
||||
CallbackBridge.holdingAlt = keyEvent.isAltPressed();
|
||||
CallbackBridge.holdingCapslock = keyEvent.isCapsLockOn();
|
||||
CallbackBridge.holdingCtrl = keyEvent.isCtrlPressed();
|
||||
CallbackBridge.holdingNumlock = keyEvent.isNumLockOn();
|
||||
CallbackBridge.holdingShift = keyEvent.isShiftPressed();
|
||||
|
||||
try {
|
||||
System.out.println(keyEvent.getKeyCode() + " " +keyEvent.getDisplayLabel());
|
||||
if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && LauncherPreferences.PREF_BACK_TO_RIGHT_MOUSE) {
|
||||
BaseMainActivity.sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, keyEvent.getAction() == KeyEvent.ACTION_DOWN);
|
||||
} else {
|
||||
if(keyEvent.getUnicodeChar() != 0) {
|
||||
char key = (char)keyEvent.getUnicodeChar();
|
||||
BaseMainActivity.sendKeyPress(
|
||||
androidToLwjglMap.get(keyEvent.getKeyCode()),
|
||||
key,
|
||||
0,
|
||||
CallbackBridge.getCurrentMods(),
|
||||
keyEvent.getAction() == KeyEvent.ACTION_DOWN);
|
||||
}else{
|
||||
BaseMainActivity.sendKeyPress(
|
||||
androidToLwjglMap.get(keyEvent.getKeyCode()),
|
||||
CallbackBridge.getCurrentMods(),
|
||||
keyEvent.getAction()==KeyEvent.ACTION_DOWN);
|
||||
}
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
th.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void execKeyIndex(BaseMainActivity mainActivity, int index) {
|
||||
mainActivity.sendKeyPress(getKeyByIndex(index));
|
||||
|
||||
}
|
||||
|
||||
public static int getKeyByIndex(int index) {
|
||||
return androidToLwjglMap.valueAt(index);
|
||||
}
|
||||
|
||||
public static int getIndexByLWJGLKey(int lwjglKey) {
|
||||
for (int i = 0; i < androidToLwjglMap.size(); i++) {
|
||||
int currKey = androidToLwjglMap.valueAt(i);
|
||||
if (currKey == lwjglKey) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -60,7 +60,10 @@ public class CustomControlsActivity extends BaseActivity
|
||||
load(ctrlLayout);
|
||||
break;
|
||||
case R.id.menu_ctrl_add:
|
||||
ctrlLayout.addControlButton(new ControlData("New", LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN, 100, 100));
|
||||
ctrlLayout.addControlButton(new ControlData("New"));
|
||||
break;
|
||||
case R.id.menu_ctrl_add_drawer:
|
||||
ctrlLayout.addDrawer(new ControlDrawerData());
|
||||
break;
|
||||
case R.id.menu_ctrl_selectdefault:
|
||||
dialogSelectDefaultCtrl(ctrlLayout);
|
||||
@@ -150,6 +153,7 @@ public class CustomControlsActivity extends BaseActivity
|
||||
if(ctx instanceof MainActivity) {
|
||||
((MainActivity) ctx).leaveCustomControls();
|
||||
}else{
|
||||
((CustomControlsActivity) ctx).isModified = false;
|
||||
((Activity)ctx).onBackPressed();
|
||||
}
|
||||
// setResult(Activity.RESULT_OK, new Intent());
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
package net.kdt.pojavlaunch;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||
|
||||
import org.lwjgl.glfw.CallbackBridge;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class EfficientAndroidLWJGLKeycode {
|
||||
|
||||
//This old version of this class was using an ArrayMap, a generic Key -> Value data structure.
|
||||
//The key being the android keycode from a KeyEvent
|
||||
//The value its LWJGL equivalent.
|
||||
private static final int KEYCODE_COUNT = 102;
|
||||
private static final int[] androidKeycodes = new int[KEYCODE_COUNT];
|
||||
private static final short[] LWJGLKeycodes = new short[KEYCODE_COUNT];
|
||||
private static String[] androidKeyNameArray; /* = new String[androidKeycodes.length]; */
|
||||
|
||||
static {
|
||||
/* BINARY SEARCH IS PERFORMED ON THE androidKeycodes ARRAY !
|
||||
WHEN ADDING A MAPPING, ADD IT SO THE androidKeycodes ARRAY STAYS SORTED ! */
|
||||
// Mapping Android Keycodes to LWJGL Keycodes
|
||||
add(KeyEvent.KEYCODE_UNKNOWN,LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN);
|
||||
add(KeyEvent.KEYCODE_HOME, LWJGLGLFWKeycode.GLFW_KEY_HOME);
|
||||
// Escape key
|
||||
add(KeyEvent.KEYCODE_BACK, LWJGLGLFWKeycode.GLFW_KEY_ESCAPE);
|
||||
|
||||
// 0-9 keys
|
||||
add(KeyEvent.KEYCODE_0, LWJGLGLFWKeycode.GLFW_KEY_0); //7
|
||||
add(KeyEvent.KEYCODE_1, LWJGLGLFWKeycode.GLFW_KEY_1);
|
||||
add(KeyEvent.KEYCODE_2, LWJGLGLFWKeycode.GLFW_KEY_2);
|
||||
add(KeyEvent.KEYCODE_3, LWJGLGLFWKeycode.GLFW_KEY_3);
|
||||
add(KeyEvent.KEYCODE_4, LWJGLGLFWKeycode.GLFW_KEY_4);
|
||||
add(KeyEvent.KEYCODE_5, LWJGLGLFWKeycode.GLFW_KEY_5);
|
||||
add(KeyEvent.KEYCODE_6, LWJGLGLFWKeycode.GLFW_KEY_6);
|
||||
add(KeyEvent.KEYCODE_7, LWJGLGLFWKeycode.GLFW_KEY_7);
|
||||
add(KeyEvent.KEYCODE_8, LWJGLGLFWKeycode.GLFW_KEY_8);
|
||||
add(KeyEvent.KEYCODE_9, LWJGLGLFWKeycode.GLFW_KEY_9); //16
|
||||
|
||||
add(KeyEvent.KEYCODE_POUND,LWJGLGLFWKeycode.GLFW_KEY_3);
|
||||
|
||||
// Arrow keys
|
||||
add(KeyEvent.KEYCODE_DPAD_UP, LWJGLGLFWKeycode.GLFW_KEY_UP); //19
|
||||
add(KeyEvent.KEYCODE_DPAD_DOWN, LWJGLGLFWKeycode.GLFW_KEY_DOWN);
|
||||
add(KeyEvent.KEYCODE_DPAD_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT);
|
||||
add(KeyEvent.KEYCODE_DPAD_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT); //22
|
||||
|
||||
// A-Z keys
|
||||
add(KeyEvent.KEYCODE_A, LWJGLGLFWKeycode.GLFW_KEY_A); //29
|
||||
add(KeyEvent.KEYCODE_B, LWJGLGLFWKeycode.GLFW_KEY_B);
|
||||
add(KeyEvent.KEYCODE_C, LWJGLGLFWKeycode.GLFW_KEY_C);
|
||||
add(KeyEvent.KEYCODE_D, LWJGLGLFWKeycode.GLFW_KEY_D);
|
||||
add(KeyEvent.KEYCODE_E, LWJGLGLFWKeycode.GLFW_KEY_E);
|
||||
add(KeyEvent.KEYCODE_F, LWJGLGLFWKeycode.GLFW_KEY_F);
|
||||
add(KeyEvent.KEYCODE_G, LWJGLGLFWKeycode.GLFW_KEY_G);
|
||||
add(KeyEvent.KEYCODE_H, LWJGLGLFWKeycode.GLFW_KEY_H);
|
||||
add(KeyEvent.KEYCODE_I, LWJGLGLFWKeycode.GLFW_KEY_I);
|
||||
add(KeyEvent.KEYCODE_J, LWJGLGLFWKeycode.GLFW_KEY_J);
|
||||
add(KeyEvent.KEYCODE_K, LWJGLGLFWKeycode.GLFW_KEY_K);
|
||||
add(KeyEvent.KEYCODE_L, LWJGLGLFWKeycode.GLFW_KEY_L);
|
||||
add(KeyEvent.KEYCODE_M, LWJGLGLFWKeycode.GLFW_KEY_M);
|
||||
add(KeyEvent.KEYCODE_N, LWJGLGLFWKeycode.GLFW_KEY_N);
|
||||
add(KeyEvent.KEYCODE_O, LWJGLGLFWKeycode.GLFW_KEY_O);
|
||||
add(KeyEvent.KEYCODE_P, LWJGLGLFWKeycode.GLFW_KEY_P);
|
||||
add(KeyEvent.KEYCODE_Q, LWJGLGLFWKeycode.GLFW_KEY_Q);
|
||||
add(KeyEvent.KEYCODE_R, LWJGLGLFWKeycode.GLFW_KEY_R);
|
||||
add(KeyEvent.KEYCODE_S, LWJGLGLFWKeycode.GLFW_KEY_S);
|
||||
add(KeyEvent.KEYCODE_T, LWJGLGLFWKeycode.GLFW_KEY_T);
|
||||
add(KeyEvent.KEYCODE_U, LWJGLGLFWKeycode.GLFW_KEY_U);
|
||||
add(KeyEvent.KEYCODE_V, LWJGLGLFWKeycode.GLFW_KEY_V);
|
||||
add(KeyEvent.KEYCODE_W, LWJGLGLFWKeycode.GLFW_KEY_W);
|
||||
add(KeyEvent.KEYCODE_X, LWJGLGLFWKeycode.GLFW_KEY_X);
|
||||
add(KeyEvent.KEYCODE_Y, LWJGLGLFWKeycode.GLFW_KEY_Y);
|
||||
add(KeyEvent.KEYCODE_Z, LWJGLGLFWKeycode.GLFW_KEY_Z); //54
|
||||
|
||||
|
||||
add(KeyEvent.KEYCODE_COMMA, LWJGLGLFWKeycode.GLFW_KEY_COMMA);
|
||||
|
||||
// Alt keys
|
||||
add(KeyEvent.KEYCODE_ALT_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT_ALT);
|
||||
add(KeyEvent.KEYCODE_ALT_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_ALT);
|
||||
|
||||
// Shift keys
|
||||
add(KeyEvent.KEYCODE_SHIFT_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT);
|
||||
add(KeyEvent.KEYCODE_SHIFT_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_SHIFT);
|
||||
|
||||
add(KeyEvent.KEYCODE_TAB, LWJGLGLFWKeycode.GLFW_KEY_TAB);
|
||||
add(KeyEvent.KEYCODE_SPACE, LWJGLGLFWKeycode.GLFW_KEY_SPACE);
|
||||
add(KeyEvent.KEYCODE_ENTER, LWJGLGLFWKeycode.GLFW_KEY_ENTER); //66
|
||||
add(KeyEvent.KEYCODE_DEL, LWJGLGLFWKeycode.GLFW_KEY_BACKSPACE); // Backspace
|
||||
add(KeyEvent.KEYCODE_GRAVE, LWJGLGLFWKeycode.GLFW_KEY_GRAVE_ACCENT);
|
||||
add(KeyEvent.KEYCODE_MINUS, LWJGLGLFWKeycode.GLFW_KEY_MINUS);
|
||||
add(KeyEvent.KEYCODE_EQUALS, LWJGLGLFWKeycode.GLFW_KEY_EQUAL);
|
||||
add(KeyEvent.KEYCODE_LEFT_BRACKET, LWJGLGLFWKeycode.GLFW_KEY_LEFT_BRACKET);
|
||||
add(KeyEvent.KEYCODE_RIGHT_BRACKET, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_BRACKET);
|
||||
add(KeyEvent.KEYCODE_BACKSLASH, LWJGLGLFWKeycode.GLFW_KEY_BACKSLASH);
|
||||
add(KeyEvent.KEYCODE_SEMICOLON, LWJGLGLFWKeycode.GLFW_KEY_SEMICOLON); //74
|
||||
|
||||
add(KeyEvent.KEYCODE_SLASH, LWJGLGLFWKeycode.GLFW_KEY_SLASH); //76
|
||||
add(KeyEvent.KEYCODE_AT,LWJGLGLFWKeycode.GLFW_KEY_2);
|
||||
|
||||
add(KeyEvent.KEYCODE_PLUS, LWJGLGLFWKeycode.GLFW_KEY_KP_ADD);
|
||||
|
||||
// Page keys
|
||||
add(KeyEvent.KEYCODE_PAGE_UP, LWJGLGLFWKeycode.GLFW_KEY_PAGE_UP); //92
|
||||
add(KeyEvent.KEYCODE_PAGE_DOWN, LWJGLGLFWKeycode.GLFW_KEY_PAGE_DOWN);
|
||||
|
||||
add(KeyEvent.KEYCODE_ESCAPE, LWJGLGLFWKeycode.GLFW_KEY_ESCAPE);
|
||||
|
||||
// Control keys
|
||||
add(KeyEvent.KEYCODE_CTRL_LEFT, LWJGLGLFWKeycode.GLFW_KEY_LEFT_CONTROL);
|
||||
add(KeyEvent.KEYCODE_CTRL_RIGHT, LWJGLGLFWKeycode.GLFW_KEY_RIGHT_CONTROL);
|
||||
|
||||
add(KeyEvent.KEYCODE_CAPS_LOCK, LWJGLGLFWKeycode.GLFW_KEY_CAPS_LOCK);
|
||||
add(KeyEvent.KEYCODE_BREAK, LWJGLGLFWKeycode.GLFW_KEY_PAUSE);
|
||||
add(KeyEvent.KEYCODE_INSERT, LWJGLGLFWKeycode.GLFW_KEY_INSERT);
|
||||
|
||||
// Fn keys
|
||||
add(KeyEvent.KEYCODE_F1, LWJGLGLFWKeycode.GLFW_KEY_F1); //131
|
||||
add(KeyEvent.KEYCODE_F2, LWJGLGLFWKeycode.GLFW_KEY_F2);
|
||||
add(KeyEvent.KEYCODE_F3, LWJGLGLFWKeycode.GLFW_KEY_F3);
|
||||
add(KeyEvent.KEYCODE_F4, LWJGLGLFWKeycode.GLFW_KEY_F4);
|
||||
add(KeyEvent.KEYCODE_F5, LWJGLGLFWKeycode.GLFW_KEY_F5);
|
||||
add(KeyEvent.KEYCODE_F6, LWJGLGLFWKeycode.GLFW_KEY_F6);
|
||||
add(KeyEvent.KEYCODE_F7, LWJGLGLFWKeycode.GLFW_KEY_F7);
|
||||
add(KeyEvent.KEYCODE_F8, LWJGLGLFWKeycode.GLFW_KEY_F8);
|
||||
add(KeyEvent.KEYCODE_F9, LWJGLGLFWKeycode.GLFW_KEY_F9);
|
||||
add(KeyEvent.KEYCODE_F10, LWJGLGLFWKeycode.GLFW_KEY_F10);
|
||||
add(KeyEvent.KEYCODE_F11, LWJGLGLFWKeycode.GLFW_KEY_F11);
|
||||
add(KeyEvent.KEYCODE_F12, LWJGLGLFWKeycode.GLFW_KEY_F12); //142
|
||||
|
||||
// Num keys
|
||||
add(KeyEvent.KEYCODE_NUM_LOCK, LWJGLGLFWKeycode.GLFW_KEY_NUM_LOCK); //143
|
||||
add(KeyEvent.KEYCODE_NUMPAD_0, LWJGLGLFWKeycode.GLFW_KEY_0);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_1, LWJGLGLFWKeycode.GLFW_KEY_1);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_2, LWJGLGLFWKeycode.GLFW_KEY_2);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_3, LWJGLGLFWKeycode.GLFW_KEY_3);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_4, LWJGLGLFWKeycode.GLFW_KEY_4);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_5, LWJGLGLFWKeycode.GLFW_KEY_5);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_6, LWJGLGLFWKeycode.GLFW_KEY_6);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_7, LWJGLGLFWKeycode.GLFW_KEY_7);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_8, LWJGLGLFWKeycode.GLFW_KEY_8);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_9, LWJGLGLFWKeycode.GLFW_KEY_9);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_DIVIDE, LWJGLGLFWKeycode.GLFW_KEY_KP_DIVIDE);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_MULTIPLY, LWJGLGLFWKeycode.GLFW_KEY_KP_MULTIPLY);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_SUBTRACT, LWJGLGLFWKeycode.GLFW_KEY_KP_SUBTRACT);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_ADD, LWJGLGLFWKeycode.GLFW_KEY_KP_ADD);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_DOT, LWJGLGLFWKeycode.GLFW_KEY_PERIOD);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_COMMA, LWJGLGLFWKeycode.GLFW_KEY_COMMA);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_ENTER, LWJGLGLFWKeycode.GLFW_KEY_ENTER);
|
||||
add(KeyEvent.KEYCODE_NUMPAD_EQUALS, LWJGLGLFWKeycode.GLFW_KEY_EQUAL); //161
|
||||
|
||||
}
|
||||
|
||||
private static short index = 0;
|
||||
|
||||
private static void add(int androidKeycode, short LWJGLKeycode){
|
||||
androidKeycodes[index] = androidKeycode;
|
||||
LWJGLKeycodes[index] = LWJGLKeycode;
|
||||
++index;
|
||||
}
|
||||
|
||||
|
||||
public static boolean containsKey(int keycode){
|
||||
return getIndexByKey(keycode) >= 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static String[] generateKeyName() {
|
||||
if (androidKeyNameArray == null) {
|
||||
androidKeyNameArray = new String[androidKeycodes.length];
|
||||
for(int i=0; i < androidKeyNameArray.length; ++i){
|
||||
androidKeyNameArray[i] = KeyEvent.keyCodeToString(androidKeycodes[i]).replace("KEYCODE_", "");
|
||||
}
|
||||
}
|
||||
return androidKeyNameArray;
|
||||
}
|
||||
|
||||
public static void execKey(KeyEvent keyEvent) {
|
||||
execKey(keyEvent, getIndexByKey(keyEvent.getKeyCode()));
|
||||
}
|
||||
|
||||
|
||||
public static void execKey(KeyEvent keyEvent, int valueIndex) {
|
||||
//valueIndex points to where the value is stored in the array.
|
||||
CallbackBridge.holdingAlt = keyEvent.isAltPressed();
|
||||
CallbackBridge.holdingCapslock = keyEvent.isCapsLockOn();
|
||||
CallbackBridge.holdingCtrl = keyEvent.isCtrlPressed();
|
||||
CallbackBridge.holdingNumlock = keyEvent.isNumLockOn();
|
||||
CallbackBridge.holdingShift = keyEvent.isShiftPressed();
|
||||
|
||||
try {
|
||||
System.out.println(keyEvent.getKeyCode() + " " +keyEvent.getDisplayLabel());
|
||||
if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && LauncherPreferences.PREF_BACK_TO_RIGHT_MOUSE) {
|
||||
BaseMainActivity.sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, keyEvent.getAction() == KeyEvent.ACTION_DOWN);
|
||||
} else {
|
||||
char key = (char)(keyEvent.getUnicodeChar() != 0 ? keyEvent.getUnicodeChar() : '\u0000');
|
||||
BaseMainActivity.sendKeyPress(
|
||||
getValueByIndex(valueIndex),
|
||||
key,
|
||||
0,
|
||||
CallbackBridge.getCurrentMods(),
|
||||
keyEvent.getAction() == KeyEvent.ACTION_DOWN);
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
th.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void execKeyIndex(int index){
|
||||
//Send a quick key press.
|
||||
BaseMainActivity.sendKeyPress(getValueByIndex(index));
|
||||
}
|
||||
|
||||
public static int getValueByIndex(int index) {
|
||||
return LWJGLKeycodes[index];
|
||||
}
|
||||
|
||||
public static int getIndexByKey(int key){
|
||||
return Arrays.binarySearch(androidKeycodes, key);
|
||||
}
|
||||
|
||||
public static short getValue(int key){
|
||||
return LWJGLKeycodes[Arrays.binarySearch(androidKeycodes, key)];
|
||||
}
|
||||
|
||||
public static int getIndexByValue(int lwjglKey) {
|
||||
//Since the LWJGL keycodes aren't sorted, linear search is used.
|
||||
//You should avoid using this function on performance critical areas
|
||||
for (int i = 0; i < LWJGLKeycodes.length; i++) {
|
||||
if(LWJGLKeycodes[i] == lwjglKey) return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -108,8 +108,8 @@ public class JavaGUILauncherActivity extends LoggableActivity implements View.On
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
}
|
||||
float mouseX = mousePointer.getTranslationX();
|
||||
float mouseY = mousePointer.getTranslationY();
|
||||
float mouseX = mousePointer.getX();
|
||||
float mouseY = mousePointer.getY();
|
||||
|
||||
if (gestureDetector.onTouchEvent(event)) {
|
||||
|
||||
@@ -250,13 +250,13 @@ public class JavaGUILauncherActivity extends LoggableActivity implements View.On
|
||||
}
|
||||
|
||||
public void placeMouseAdd(float x, float y) {
|
||||
this.mousePointer.setTranslationX(mousePointer.getTranslationX() + x);
|
||||
this.mousePointer.setTranslationY(mousePointer.getTranslationY() + y);
|
||||
this.mousePointer.setX(mousePointer.getX() + x);
|
||||
this.mousePointer.setY(mousePointer.getY() + y);
|
||||
}
|
||||
|
||||
public void placeMouseAt(float x, float y) {
|
||||
this.mousePointer.setTranslationX(x);
|
||||
this.mousePointer.setTranslationY(y);
|
||||
this.mousePointer.setX(x);
|
||||
this.mousePointer.setY(y);
|
||||
}
|
||||
|
||||
void sendScaledMousePosition(float x, float y){
|
||||
|
||||
@@ -33,10 +33,10 @@ package net.kdt.pojavlaunch;
|
||||
public class LWJGLGLFWKeycode
|
||||
{
|
||||
/** The unknown key. */
|
||||
public static final int GLFW_KEY_UNKNOWN = 0; // should be -1
|
||||
public static final short GLFW_KEY_UNKNOWN = 0; // should be -1
|
||||
|
||||
/** Printable keys. */
|
||||
public static final int
|
||||
public static final short
|
||||
GLFW_KEY_SPACE = 32,
|
||||
GLFW_KEY_APOSTROPHE = 39,
|
||||
GLFW_KEY_COMMA = 44,
|
||||
@@ -89,7 +89,7 @@ public class LWJGLGLFWKeycode
|
||||
GLFW_KEY_WORLD_2 = 162;
|
||||
|
||||
/** Function keys. */
|
||||
public static final int
|
||||
public static final short
|
||||
GLFW_KEY_ESCAPE = 256,
|
||||
GLFW_KEY_ENTER = 257,
|
||||
GLFW_KEY_TAB = 258,
|
||||
@@ -182,7 +182,7 @@ public class LWJGLGLFWKeycode
|
||||
|
||||
|
||||
/** Mouse buttons. See <a target="_blank" href="http://www.glfw.org/docs/latest/input.html#input_mouse_button">mouse button input</a> for how these are used. */
|
||||
public static final int
|
||||
public static final short
|
||||
GLFW_MOUSE_BUTTON_1 = 0,
|
||||
GLFW_MOUSE_BUTTON_2 = 1,
|
||||
GLFW_MOUSE_BUTTON_3 = 2,
|
||||
|
||||
@@ -10,6 +10,7 @@ import androidx.annotation.Nullable;
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
|
||||
import net.kdt.pojavlaunch.customcontrols.*;
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton;
|
||||
import net.kdt.pojavlaunch.prefs.*;
|
||||
import net.kdt.pojavlaunch.utils.MCOptionUtils;
|
||||
|
||||
@@ -37,7 +38,10 @@ public class MainActivity extends BaseMainActivity {
|
||||
CustomControlsActivity.load(mControlLayout);
|
||||
break;
|
||||
case R.id.menu_ctrl_add:
|
||||
mControlLayout.addControlButton(new ControlData("New", LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN, 100, 100));
|
||||
mControlLayout.addControlButton(new ControlData("New"));
|
||||
break;
|
||||
case R.id.menu_ctrl_add_drawer:
|
||||
mControlLayout.addDrawer(new ControlDrawerData());
|
||||
break;
|
||||
case R.id.menu_ctrl_selectdefault:
|
||||
CustomControlsActivity.dialogSelectDefaultCtrl(mControlLayout);
|
||||
@@ -56,18 +60,20 @@ public class MainActivity extends BaseMainActivity {
|
||||
public void onClick(View view) {
|
||||
if (view instanceof ControlButton) {
|
||||
ControlButton button = (ControlButton) view;
|
||||
switch (button.getProperties().keycode) {
|
||||
case ControlData.SPECIALBTN_KEYBOARD:
|
||||
showKeyboard();
|
||||
break;
|
||||
for(int keycode : button.getProperties().keycodes){
|
||||
switch (keycode) {
|
||||
case ControlData.SPECIALBTN_KEYBOARD:
|
||||
showKeyboard();
|
||||
break;
|
||||
|
||||
case ControlData.SPECIALBTN_TOGGLECTRL:
|
||||
mControlLayout.toggleControlVisible();
|
||||
break;
|
||||
case ControlData.SPECIALBTN_TOGGLECTRL:
|
||||
mControlLayout.toggleControlVisible();
|
||||
break;
|
||||
|
||||
case ControlData.SPECIALBTN_VIRTUALMOUSE:
|
||||
toggleMouse(button);
|
||||
break;
|
||||
case ControlData.SPECIALBTN_VIRTUALMOUSE:
|
||||
toggleMouse(button);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,32 +99,34 @@ public class MainActivity extends BaseMainActivity {
|
||||
|
||||
if (view instanceof ControlButton) {
|
||||
ControlButton button = (ControlButton) view;
|
||||
switch (button.getProperties().keycode) {
|
||||
case ControlData.SPECIALBTN_MOUSEPRI:
|
||||
sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, isDown);
|
||||
break;
|
||||
for(int keycode : button.getProperties().keycodes) {
|
||||
switch (keycode) {
|
||||
case ControlData.SPECIALBTN_MOUSEPRI:
|
||||
sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, isDown);
|
||||
break;
|
||||
|
||||
case ControlData.SPECIALBTN_MOUSEMID:
|
||||
sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_MIDDLE, isDown);
|
||||
break;
|
||||
case ControlData.SPECIALBTN_MOUSEMID:
|
||||
sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_MIDDLE, isDown);
|
||||
break;
|
||||
|
||||
case ControlData.SPECIALBTN_MOUSESEC:
|
||||
if (CallbackBridge.isGrabbing()) {
|
||||
sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown);
|
||||
} else {
|
||||
CallbackBridge.putMouseEventWithCoords(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown ? 1 : 0, CallbackBridge.mouseX, CallbackBridge.mouseY);
|
||||
case ControlData.SPECIALBTN_MOUSESEC:
|
||||
if (CallbackBridge.isGrabbing()) {
|
||||
sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown);
|
||||
} else {
|
||||
CallbackBridge.putMouseEventWithCoords(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown ? 1 : 0, CallbackBridge.mouseX, CallbackBridge.mouseY);
|
||||
|
||||
setRightOverride(isDown);
|
||||
}
|
||||
break;
|
||||
|
||||
case ControlData.SPECIALBTN_SCROLLDOWN:
|
||||
if(!isDown)CallbackBridge.sendScroll(0, 1d);
|
||||
break;
|
||||
|
||||
case ControlData.SPECIALBTN_SCROLLUP:
|
||||
if(!isDown)CallbackBridge.sendScroll(0, -1d);
|
||||
break;
|
||||
setRightOverride(isDown);
|
||||
}
|
||||
break;
|
||||
|
||||
case ControlData.SPECIALBTN_SCROLLDOWN:
|
||||
if (!isDown) CallbackBridge.sendScroll(0, 1d);
|
||||
break;
|
||||
|
||||
case ControlData.SPECIALBTN_SCROLLUP:
|
||||
if (!isDown) CallbackBridge.sendScroll(0, -1d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,8 +33,7 @@ import static android.os.Build.VERSION_CODES.P;
|
||||
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_IGNORE_NOTCH;
|
||||
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_NOTCH_SIZE;
|
||||
|
||||
public final class Tools
|
||||
{
|
||||
public final class Tools {
|
||||
public static final boolean ENABLE_DEV_FEATURES = BuildConfig.DEBUG;
|
||||
|
||||
public static String APP_NAME = "null";
|
||||
@@ -417,10 +416,13 @@ public final class Tools
|
||||
}
|
||||
|
||||
public static float dpToPx(float dp) {
|
||||
// 921600 = 1280 * 720, default scale
|
||||
// TODO better way to scaling
|
||||
float scaledDp = dp; // / DisplayMetrics.DENSITY_XHIGH * currentDisplayMetrics.densityDpi;
|
||||
return (scaledDp * currentDisplayMetrics.density);
|
||||
//Better hope for the currentDisplayMetrics to be good
|
||||
return dp * currentDisplayMetrics.density;
|
||||
}
|
||||
|
||||
public static float pxToDp(float px){
|
||||
//Better hope for the currentDisplayMetrics to be good
|
||||
return px / currentDisplayMetrics.density;
|
||||
}
|
||||
|
||||
public static void copyAssetFile(Context ctx, String fileName, String output, boolean overwrite) throws IOException {
|
||||
@@ -438,31 +440,7 @@ public final class Tools
|
||||
write(file2.getAbsolutePath(), loadFromAssetToByte(ctx, fileName));
|
||||
}
|
||||
}
|
||||
/*
|
||||
public static void extractAssetFolder(Activity ctx, String path, String output) throws Exception {
|
||||
extractAssetFolder(ctx, path, output, false);
|
||||
}
|
||||
|
||||
public static void extractAssetFolder(Activity ctx, String path, String output, boolean overwrite) throws Exception {
|
||||
AssetManager assetManager = ctx.getAssets();
|
||||
String assets[] = null;
|
||||
try {
|
||||
assets = assetManager.list(path);
|
||||
if (assets.length == 0) {
|
||||
Tools.copyAssetFile(ctx, path, output, overwrite);
|
||||
} else {
|
||||
File dir = new File(output, path);
|
||||
if (!dir.exists())
|
||||
dir.mkdirs();
|
||||
for (String sub : assets) {
|
||||
extractAssetFolder(ctx, path + "/" + sub, output, overwrite);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
showError(ctx, e);
|
||||
}
|
||||
}
|
||||
*/
|
||||
public static void showError(Context ctx, Throwable e) {
|
||||
showError(ctx, e, false);
|
||||
}
|
||||
@@ -487,45 +465,27 @@ public final class Tools
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder((Context) ctx)
|
||||
.setTitle(titleId)
|
||||
.setMessage(errMsg)
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface p1, int p2)
|
||||
{
|
||||
if(exitIfOk) {
|
||||
if (ctx instanceof BaseMainActivity) {
|
||||
BaseMainActivity.fullyExit();
|
||||
} else if (ctx instanceof Activity) {
|
||||
((Activity) ctx).finish();
|
||||
}
|
||||
.setPositiveButton(android.R.string.ok, (DialogInterface.OnClickListener) (p1, p2) -> {
|
||||
if(exitIfOk) {
|
||||
if (ctx instanceof BaseMainActivity) {
|
||||
BaseMainActivity.fullyExit();
|
||||
} else if (ctx instanceof Activity) {
|
||||
((Activity) ctx).finish();
|
||||
}
|
||||
}
|
||||
})
|
||||
.setNegativeButton(showMore ? R.string.error_show_less : R.string.error_show_more, new DialogInterface.OnClickListener(){
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface p1, int p2)
|
||||
{
|
||||
showError(ctx, titleId, e, exitIfOk, !showMore);
|
||||
}
|
||||
})
|
||||
.setNeutralButton(android.R.string.copy, new DialogInterface.OnClickListener(){
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface p1, int p2)
|
||||
{
|
||||
android.content.ClipboardManager mgr = (android.content.ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
mgr.setPrimaryClip(ClipData.newPlainText("error", Log.getStackTraceString(e)));
|
||||
if(exitIfOk) {
|
||||
if (ctx instanceof BaseMainActivity) {
|
||||
BaseMainActivity.fullyExit();
|
||||
} else {
|
||||
((Activity) ctx).finish();
|
||||
}
|
||||
.setNegativeButton(showMore ? R.string.error_show_less : R.string.error_show_more, (DialogInterface.OnClickListener) (p1, p2) -> showError(ctx, titleId, e, exitIfOk, !showMore))
|
||||
.setNeutralButton(android.R.string.copy, (DialogInterface.OnClickListener) (p1, p2) -> {
|
||||
ClipboardManager mgr = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
mgr.setPrimaryClip(ClipData.newPlainText("error", Log.getStackTraceString(e)));
|
||||
if(exitIfOk) {
|
||||
if (ctx instanceof BaseMainActivity) {
|
||||
BaseMainActivity.fullyExit();
|
||||
} else {
|
||||
((Activity) ctx).finish();
|
||||
}
|
||||
}
|
||||
})
|
||||
//.setNegativeButton("Report (not available)", null)
|
||||
.setCancelable(!exitIfOk);
|
||||
try {
|
||||
builder.show();
|
||||
@@ -543,18 +503,11 @@ public final class Tools
|
||||
}
|
||||
|
||||
public static void dialogOnUiThread(final Activity ctx, final CharSequence title, final CharSequence message) {
|
||||
ctx.runOnUiThread(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
new AlertDialog.Builder(ctx)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
|
||||
ctx.runOnUiThread(() -> new AlertDialog.Builder(ctx)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show());
|
||||
}
|
||||
|
||||
public static void moveInside(String from, String to) {
|
||||
@@ -919,5 +872,5 @@ public final class Tools
|
||||
Tools.updateWindowSize(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
package net.kdt.pojavlaunch.customcontrols;
|
||||
|
||||
import android.content.*;
|
||||
import android.graphics.*;
|
||||
import android.util.*;
|
||||
import android.view.*;
|
||||
import android.view.View.*;
|
||||
import android.widget.*;
|
||||
import net.kdt.pojavlaunch.customcontrols.handleview.*;
|
||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||
import net.kdt.pojavlaunch.*;
|
||||
import org.lwjgl.glfw.*;
|
||||
|
||||
public class ControlButton extends androidx.appcompat.widget.AppCompatButton implements OnLongClickListener
|
||||
{
|
||||
private Paint mRectPaint;
|
||||
|
||||
private GestureDetector mGestureDetector;
|
||||
private ControlData mProperties;
|
||||
private SelectionEndHandleView mHandleView;
|
||||
|
||||
private boolean mModifiable = false;
|
||||
private boolean mCanTriggerLongClick = true;
|
||||
|
||||
private boolean mChecked = false;
|
||||
|
||||
private float mScaleAt;
|
||||
|
||||
public ControlButton(ControlLayout layout, ControlData properties) {
|
||||
super(layout.getContext());
|
||||
setPadding(4, 4, 4, 4);
|
||||
setWillNotDraw(false);
|
||||
|
||||
mScaleAt = layout.mLayout.scaledAt;
|
||||
|
||||
mGestureDetector = new GestureDetector(getContext(), new SingleTapConfirm());
|
||||
|
||||
if (!LauncherPreferences.PREF_BUTTON_FLAT) {
|
||||
setBackgroundResource(R.drawable.control_button);
|
||||
} else {
|
||||
setBackgroundResource(R.drawable.control_button_black);
|
||||
}
|
||||
setOnLongClickListener(this);
|
||||
|
||||
setProperties(properties);
|
||||
setModified(false);
|
||||
|
||||
mHandleView = new SelectionEndHandleView(this);
|
||||
|
||||
final TypedValue value = new TypedValue();
|
||||
getContext().getTheme().resolveAttribute(R.attr.colorAccent, value, true);
|
||||
|
||||
mRectPaint = new Paint();
|
||||
mRectPaint.setColor(value.data);
|
||||
mRectPaint.setAlpha(128);
|
||||
}
|
||||
|
||||
public HandleView getHandleView() {
|
||||
return mHandleView;
|
||||
}
|
||||
|
||||
public ControlData getProperties() {
|
||||
return mProperties;
|
||||
}
|
||||
|
||||
public void setProperties(ControlData properties) {
|
||||
setProperties(properties, true);
|
||||
}
|
||||
|
||||
public void setProperties(ControlData properties, boolean changePos) {
|
||||
mProperties = properties;
|
||||
mProperties.transparency = mProperties.hidden ? 100 : mProperties.transparency;
|
||||
properties.update();
|
||||
|
||||
// com.android.internal.R.string.delete
|
||||
// android.R.string.
|
||||
setText(properties.name);
|
||||
if (changePos) {
|
||||
setTranslationX(moveX = properties.x);
|
||||
setTranslationY(moveY = properties.y);
|
||||
}
|
||||
if (!LauncherPreferences.PREF_BUTTON_FLAT) {
|
||||
setBackgroundResource(mProperties.isRound ? R.drawable.control_button_round : R.drawable.control_button);
|
||||
} else {
|
||||
setBackgroundResource(mProperties.isRound ? R.drawable.control_button_round_black : R.drawable.control_button_black);
|
||||
}
|
||||
if (properties.specialButtonListener == null) {
|
||||
// A non-special button or inside custom controls screen so skip listener
|
||||
} else if (properties.specialButtonListener instanceof View.OnClickListener) {
|
||||
setOnClickListener((View.OnClickListener) properties.specialButtonListener);
|
||||
// setOnLongClickListener(null);
|
||||
// setOnTouchListener(null);
|
||||
} else if (properties.specialButtonListener instanceof View.OnTouchListener) {
|
||||
// setOnLongClickListener(null);
|
||||
setOnTouchListener((View.OnTouchListener) properties.specialButtonListener);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Field " + ControlData.class.getName() + ".specialButtonListener must be View.OnClickListener or View.OnTouchListener, but was " +
|
||||
properties.specialButtonListener.getClass().getName());
|
||||
}
|
||||
|
||||
setLayoutParams(new FrameLayout.LayoutParams((int) properties.width, (int) properties.height));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayoutParams(ViewGroup.LayoutParams params) {
|
||||
super.setLayoutParams(params);
|
||||
|
||||
mProperties.width = params.width;
|
||||
mProperties.height = params.height;
|
||||
|
||||
// Re-calculate position
|
||||
mProperties.update();
|
||||
setTranslationX(mProperties.x);
|
||||
setTranslationY(mProperties.y);
|
||||
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTranslationX(float x) {
|
||||
super.setTranslationX(x);
|
||||
|
||||
if (!mProperties.isDynamicBtn) {
|
||||
mProperties.x = x;
|
||||
mProperties.dynamicX = Float.toString(x / CallbackBridge.physicalWidth) + " * ${screen_width}";
|
||||
setModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTranslationY(float y) {
|
||||
super.setTranslationY(y);
|
||||
|
||||
if (!mProperties.isDynamicBtn) {
|
||||
mProperties.y = y;
|
||||
mProperties.dynamicY = Float.toString(y / CallbackBridge.physicalHeight) + " * ${screen_height}";
|
||||
setModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateProperties() {
|
||||
setProperties(mProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (mChecked) {
|
||||
canvas.drawRect(0, getHeight() - 10 * mScaleAt, getWidth(), getHeight(), mRectPaint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View p1) {
|
||||
if (mCanTriggerLongClick && mModifiable) {
|
||||
if (mHandleView.isShowing()) {
|
||||
mHandleView.hide();
|
||||
} else {
|
||||
if (getParent() != null) {
|
||||
((ControlLayout) getParent()).hideAllHandleViews();
|
||||
}
|
||||
|
||||
try {
|
||||
mHandleView.show();
|
||||
} catch (Throwable th) {
|
||||
th.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mCanTriggerLongClick;
|
||||
}
|
||||
|
||||
private void setHolding(boolean isDown) {
|
||||
if (mProperties.holdAlt) {
|
||||
CallbackBridge.holdingAlt = isDown;
|
||||
MainActivity.sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_LEFT_ALT,0,isDown);
|
||||
System.out.println("holdingAlt="+CallbackBridge.holdingAlt);
|
||||
} if (mProperties.keycode == LWJGLGLFWKeycode.GLFW_KEY_CAPS_LOCK) {
|
||||
CallbackBridge.holdingCapslock = isDown;
|
||||
//MainActivity.sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_CAPS_LOCK,0,isDown);
|
||||
System.out.println("holdingCapslock="+CallbackBridge.holdingCapslock);
|
||||
} if (mProperties.holdCtrl) {
|
||||
CallbackBridge.holdingCtrl = isDown;
|
||||
MainActivity.sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_LEFT_CONTROL,0,isDown);
|
||||
System.out.println("holdingCtrl="+CallbackBridge.holdingCtrl);
|
||||
} if (mProperties.keycode == LWJGLGLFWKeycode.GLFW_KEY_NUM_LOCK) {
|
||||
CallbackBridge.holdingNumlock = isDown;
|
||||
//MainActivity.sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_NUM_LOCK,0,isDown);
|
||||
System.out.println("holdingNumlock="+CallbackBridge.holdingNumlock);
|
||||
} if (mProperties.holdShift) {
|
||||
CallbackBridge.holdingShift = isDown;
|
||||
MainActivity.sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT,0,isDown);
|
||||
System.out.println("holdingShift="+CallbackBridge.holdingShift);
|
||||
}
|
||||
}
|
||||
|
||||
private float moveX, moveY;
|
||||
private float downX, downY;
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (!mModifiable) {
|
||||
mCanTriggerLongClick = false;
|
||||
if(event.getAction() == MotionEvent.ACTION_MOVE && CallbackBridge.isGrabbing() && mProperties.passThruEnabled) {
|
||||
MinecraftGLView v = ((ControlLayout) this.getParent()).findViewById(R.id.main_game_render_view);
|
||||
if(v != null) {
|
||||
v.dispatchTouchEvent(event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (mProperties.keycode >= 0) {
|
||||
if (!mProperties.isToggle) {
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN: // 0
|
||||
case MotionEvent.ACTION_POINTER_DOWN: // 5
|
||||
setHolding(true);
|
||||
MainActivity.sendKeyPress(mProperties.keycode, CallbackBridge.getCurrentMods(), true);
|
||||
break;
|
||||
case MotionEvent.ACTION_UP: // 1
|
||||
case MotionEvent.ACTION_CANCEL: // 3
|
||||
case MotionEvent.ACTION_POINTER_UP: // 6
|
||||
setHolding(false);
|
||||
MainActivity.sendKeyPress(mProperties.keycode, CallbackBridge.getCurrentMods(), false);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (mGestureDetector.onTouchEvent(event)) {
|
||||
mChecked = !mChecked;
|
||||
invalidate();
|
||||
setHolding(mChecked);
|
||||
MainActivity.sendKeyPress(mProperties.keycode, CallbackBridge.getCurrentMods(), mChecked);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (mGestureDetector.onTouchEvent(event)) {
|
||||
mCanTriggerLongClick = true;
|
||||
onLongClick(this);
|
||||
}
|
||||
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mCanTriggerLongClick = true;
|
||||
downX = event.getX();
|
||||
downY = event.getY();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
mCanTriggerLongClick = false;
|
||||
moveX += event.getX() - downX;
|
||||
moveY += event.getY() - downY;
|
||||
|
||||
if (!mProperties.isDynamicBtn) {
|
||||
setTranslationX(moveX);
|
||||
setTranslationY(moveY);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
public void setModifiable(boolean z) {
|
||||
mModifiable = z;
|
||||
}
|
||||
|
||||
private void setModified(boolean modified) {
|
||||
if (getParent() != null) {
|
||||
((ControlLayout) getParent()).setModified(modified);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,14 +7,11 @@ import net.kdt.pojavlaunch.utils.*;
|
||||
import net.objecthunter.exp4j.*;
|
||||
import org.lwjgl.glfw.*;
|
||||
|
||||
import static net.kdt.pojavlaunch.LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN;
|
||||
|
||||
public class ControlData implements Cloneable
|
||||
{
|
||||
/*
|
||||
public static int pixelOf2dp = (int) Tools.dpToPx(2);
|
||||
public static int pixelOf30dp = (int) Tools.dpToPx(30);
|
||||
public static int pixelOf50dp = Tools.dpToPx(50);;
|
||||
public static int pixelOf80dp;
|
||||
*/
|
||||
|
||||
public static final int SPECIALBTN_KEYBOARD = -1;
|
||||
public static final int SPECIALBTN_TOGGLECTRL = -2;
|
||||
public static final int SPECIALBTN_MOUSEPRI = -3;
|
||||
@@ -38,22 +35,21 @@ public class ControlData implements Cloneable
|
||||
* bigger device or vice versa.
|
||||
*/
|
||||
public String dynamicX, dynamicY;
|
||||
public boolean isDynamicBtn, isToggle, passThruEnabled, isRound;
|
||||
public boolean isDynamicBtn, isToggle, passThruEnabled;
|
||||
|
||||
public static ControlData[] getSpecialButtons(){
|
||||
if (SPECIAL_BUTTONS == null) {
|
||||
ControlData[] specialButtons = new ControlData[]{
|
||||
new ControlData("Keyboard", SPECIALBTN_KEYBOARD, "${margin} * 3 + ${width} * 2", "${margin}", false),
|
||||
new ControlData("GUI", SPECIALBTN_TOGGLECTRL, "${margin}", "${bottom} - ${margin}"),
|
||||
new ControlData("PRI", SPECIALBTN_MOUSEPRI, "${margin}", "${screen_height} - ${margin} * 3 - ${height} * 3"),
|
||||
new ControlData("SEC", SPECIALBTN_MOUSESEC, "${margin} * 3 + ${width} * 2", "${screen_height} - ${margin} * 3 - ${height} * 3"),
|
||||
new ControlData("Mouse", SPECIALBTN_VIRTUALMOUSE, "${right}", "${margin}", false),
|
||||
SPECIAL_BUTTONS = new ControlData[]{
|
||||
new ControlData("Keyboard", new int[]{SPECIALBTN_KEYBOARD}, "${margin} * 3 + ${width} * 2", "${margin}", false),
|
||||
new ControlData("GUI", new int[]{SPECIALBTN_TOGGLECTRL}, "${margin}", "${bottom} - ${margin}"),
|
||||
new ControlData("PRI", new int[]{SPECIALBTN_MOUSEPRI}, "${margin}", "${screen_height} - ${margin} * 3 - ${height} * 3"),
|
||||
new ControlData("SEC", new int[]{SPECIALBTN_MOUSESEC}, "${margin} * 3 + ${width} * 2", "${screen_height} - ${margin} * 3 - ${height} * 3"),
|
||||
new ControlData("Mouse", new int[]{SPECIALBTN_VIRTUALMOUSE}, "${right}", "${margin}", false),
|
||||
|
||||
new ControlData("MID", SPECIALBTN_MOUSEMID, "${margin}", "${margin}"),
|
||||
new ControlData("SCROLLUP", SPECIALBTN_SCROLLUP, "${margin}", "${margin}"),
|
||||
new ControlData("SCROLLDOWN", SPECIALBTN_SCROLLDOWN, "${margin}", "${margin}")
|
||||
new ControlData("MID", new int[]{SPECIALBTN_MOUSEMID}, "${margin}", "${margin}"),
|
||||
new ControlData("SCROLLUP", new int[]{SPECIALBTN_SCROLLUP}, "${margin}", "${margin}"),
|
||||
new ControlData("SCROLLDOWN", new int[]{SPECIALBTN_SCROLLDOWN}, "${margin}", "${margin}")
|
||||
};
|
||||
SPECIAL_BUTTONS = specialButtons;
|
||||
}
|
||||
|
||||
return SPECIAL_BUTTONS;
|
||||
@@ -74,76 +70,89 @@ public class ControlData implements Cloneable
|
||||
public String name;
|
||||
public float x;
|
||||
public float y;
|
||||
public float width;
|
||||
public float height;
|
||||
public int keycode;
|
||||
public int transparency;
|
||||
@Deprecated
|
||||
public boolean hidden;
|
||||
public boolean holdCtrl;
|
||||
public boolean holdAlt;
|
||||
public boolean holdShift;
|
||||
private float width; //Dp instead of Px now
|
||||
private float height; //Dp instead of Px now
|
||||
public int[] keycodes; //Should store up to 4 keys
|
||||
public float opacity; //Alpha value from 0 to 1;
|
||||
public int bgColor;
|
||||
public int strokeColor;
|
||||
public int strokeWidth; //0-100%
|
||||
public float cornerRadius; //0-100%
|
||||
public boolean isSwipeable;
|
||||
|
||||
public Object specialButtonListener;
|
||||
|
||||
public ControlData() {
|
||||
this("", LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN, 0, 0);
|
||||
this("button");
|
||||
}
|
||||
|
||||
public ControlData(String name, int keycode) {
|
||||
this(name, keycode, 0, 0);
|
||||
public ControlData(String name){
|
||||
this(name, new int[] {});
|
||||
}
|
||||
|
||||
public ControlData(String name, int keycode, float x, float y) {
|
||||
this(name, keycode, x, y, Tools.dpToPx(50), Tools.dpToPx(50));
|
||||
public ControlData(String name, int[] keycodes) {
|
||||
this(name, keycodes, Tools.currentDisplayMetrics.widthPixels/2, Tools.currentDisplayMetrics.heightPixels/2);
|
||||
}
|
||||
|
||||
public ControlData(android.content.Context ctx, int resId, int keycode, float x, float y, boolean isSquare) {
|
||||
this(ctx.getResources().getString(resId), keycode, x, y, isSquare);
|
||||
public ControlData(String name, int[] keycodes, float x, float y) {
|
||||
this(name, keycodes, x, y, 50, 50);
|
||||
}
|
||||
|
||||
public ControlData(String name, int keycode, float x, float y, boolean isSquare) {
|
||||
this(name, keycode, x, y, isSquare ? Tools.dpToPx(50) : Tools.dpToPx(80), isSquare ? Tools.dpToPx(50) : Tools.dpToPx(30));
|
||||
public ControlData(android.content.Context ctx, int resId, int[] keycodes, float x, float y, boolean isSquare) {
|
||||
this(ctx.getResources().getString(resId), keycodes, x, y, isSquare);
|
||||
}
|
||||
|
||||
public ControlData(String name, int keycode, float x, float y, float width, float height) {
|
||||
this(name, keycode, Float.toString(x), Float.toString(y), width, height, false);
|
||||
public ControlData(String name, int[] keycodes, float x, float y, boolean isSquare) {
|
||||
this(name, keycodes, x, y, isSquare ? 50 : 80, isSquare ? 50 : 30);
|
||||
}
|
||||
|
||||
public ControlData(String name, int[] keycodes, float x, float y, float width, float height) {
|
||||
this(name, keycodes, Float.toString(x), Float.toString(y), width, height, false);
|
||||
this.isDynamicBtn = false;
|
||||
}
|
||||
|
||||
public ControlData(String name, int keycode, String dynamicX, String dynamicY) {
|
||||
this(name, keycode, dynamicX, dynamicY, Tools.dpToPx(50), Tools.dpToPx(50), false);
|
||||
public ControlData(String name, int[] keycodes, String dynamicX, String dynamicY) {
|
||||
this(name, keycodes, dynamicX, dynamicY, 50, 50, false);
|
||||
}
|
||||
|
||||
public ControlData(android.content.Context ctx, int resId, int keycode, String dynamicX, String dynamicY, boolean isSquare) {
|
||||
this(ctx.getResources().getString(resId), keycode, dynamicX, dynamicY, isSquare);
|
||||
public ControlData(android.content.Context ctx, int resId, int[] keycodes, String dynamicX, String dynamicY, boolean isSquare) {
|
||||
this(ctx.getResources().getString(resId), keycodes, dynamicX, dynamicY, isSquare);
|
||||
}
|
||||
|
||||
public ControlData(String name, int keycode, String dynamicX, String dynamicY, boolean isSquare) {
|
||||
this(name, keycode, dynamicX, dynamicY, isSquare ? Tools.dpToPx(50) : Tools.dpToPx(80), isSquare ? Tools.dpToPx(50) : Tools.dpToPx(30), false);
|
||||
public ControlData(String name, int[] keycodes, String dynamicX, String dynamicY, boolean isSquare) {
|
||||
this(name, keycodes, dynamicX, dynamicY, isSquare ? 50 : 80, isSquare ? 50 : 30, false);
|
||||
}
|
||||
|
||||
public ControlData(String name, int keycode, String dynamicX, String dynamicY, float width, float height, boolean isToggle) {
|
||||
public ControlData(String name, int[] keycodes, String dynamicX, String dynamicY, float width, float height, boolean isToggle){
|
||||
this(name, keycodes, dynamicX, dynamicY, width, height, isToggle, 1,0x4D000000, 0xFFFFFFFF,0,0);
|
||||
}
|
||||
|
||||
public ControlData(String name, int[] keycodes, String dynamicX, String dynamicY, float width, float height, boolean isToggle, float opacity, int bgColor, int strokeColor, int strokeWidth, float cornerRadius) {
|
||||
this.name = name;
|
||||
this.keycode = keycode;
|
||||
this.keycodes = inflateKeycodeArray(keycodes);
|
||||
this.dynamicX = dynamicX;
|
||||
this.dynamicY = dynamicY;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.isDynamicBtn = true;
|
||||
this.isToggle = isToggle;
|
||||
this.opacity = opacity;
|
||||
this.bgColor = bgColor;
|
||||
this.strokeColor = strokeColor;
|
||||
this.strokeWidth = strokeWidth;
|
||||
this.cornerRadius = cornerRadius;
|
||||
update();
|
||||
}
|
||||
|
||||
public void execute(BaseMainActivity act, boolean isDown) {
|
||||
act.sendKeyPress(keycode, 0, isDown);
|
||||
public void execute(boolean isDown) {
|
||||
for(int keycode : keycodes){
|
||||
BaseMainActivity.sendKeyPress(keycode, 0, isDown);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ControlData clone() {
|
||||
if (this instanceof ControlData) {
|
||||
return new ControlData(name, keycode, ((ControlData) this).dynamicX, ((ControlData) this).dynamicY, width, height, isToggle);
|
||||
} else {
|
||||
return new ControlData(name, keycode, x, y, width, height);
|
||||
}
|
||||
return new ControlData(name, keycodes, dynamicX, dynamicY, width, height, isToggle, opacity, bgColor, strokeColor,strokeWidth, cornerRadius);
|
||||
}
|
||||
|
||||
public float insertDynamicPos(String dynamicPos) {
|
||||
@@ -151,10 +160,10 @@ public class ControlData implements Cloneable
|
||||
Map<String, String> keyValueMap = new ArrayMap<>();
|
||||
keyValueMap.put("top", "0");
|
||||
keyValueMap.put("left", "0");
|
||||
keyValueMap.put("right", Float.toString(CallbackBridge.physicalWidth - width));
|
||||
keyValueMap.put("bottom", Float.toString(CallbackBridge.physicalHeight - height));
|
||||
keyValueMap.put("width", Float.toString(width));
|
||||
keyValueMap.put("height", Float.toString(height));
|
||||
keyValueMap.put("right", Float.toString(CallbackBridge.physicalWidth - getWidth()));
|
||||
keyValueMap.put("bottom", Float.toString(CallbackBridge.physicalHeight - getHeight()));
|
||||
keyValueMap.put("width", Float.toString(getWidth()));
|
||||
keyValueMap.put("height", Float.toString(getHeight()));
|
||||
keyValueMap.put("screen_width", Integer.toString(CallbackBridge.physicalWidth));
|
||||
keyValueMap.put("screen_height", Integer.toString(CallbackBridge.physicalHeight));
|
||||
keyValueMap.put("margin", Integer.toString((int) Tools.dpToPx(2)));
|
||||
@@ -167,15 +176,17 @@ public class ControlData implements Cloneable
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (keycode < 0 && SPECIAL_BUTTONS != null) {
|
||||
for (ControlData data : getSpecialButtons()) {
|
||||
if (keycode == data.keycode) {
|
||||
specialButtonListener = data.specialButtonListener;
|
||||
}
|
||||
}
|
||||
} if (dynamicX == null) {
|
||||
if(SPECIAL_BUTTONS != null)
|
||||
for(int keycode : keycodes)
|
||||
for (ControlData data : getSpecialButtons())
|
||||
if (keycode == data.keycodes[0])
|
||||
specialButtonListener = data.specialButtonListener;
|
||||
|
||||
|
||||
if (dynamicX == null) {
|
||||
dynamicX = Float.toString(x);
|
||||
} if (dynamicY == null) {
|
||||
}
|
||||
if (dynamicY == null) {
|
||||
dynamicY = Float.toString(y);
|
||||
}
|
||||
|
||||
@@ -186,4 +197,37 @@ public class ControlData implements Cloneable
|
||||
private static float calculate(String math) {
|
||||
return (float) new ExpressionBuilder(math).build().evaluate();
|
||||
}
|
||||
|
||||
private static int[] inflateKeycodeArray(int[] keycodes){
|
||||
int[] inflatedArray = new int[]{GLFW_KEY_UNKNOWN, GLFW_KEY_UNKNOWN, GLFW_KEY_UNKNOWN, GLFW_KEY_UNKNOWN};
|
||||
System.arraycopy(keycodes, 0, inflatedArray, 0, keycodes.length);
|
||||
return inflatedArray;
|
||||
}
|
||||
|
||||
|
||||
public boolean containsKeycode(int keycodeToCheck){
|
||||
for(int keycode : keycodes)
|
||||
if(keycodeToCheck == keycode)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//Getters || setters (with conversion for ease of use)
|
||||
public float getWidth() {
|
||||
return Tools.dpToPx(width);
|
||||
}
|
||||
|
||||
public float getHeight(){
|
||||
return Tools.dpToPx(height);
|
||||
}
|
||||
|
||||
|
||||
public void setWidth(float widthInPx){
|
||||
width = Tools.pxToDp(widthInPx);
|
||||
}
|
||||
|
||||
public void setHeight(float heightInPx){
|
||||
height = Tools.pxToDp(heightInPx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package net.kdt.pojavlaunch.customcontrols;
|
||||
|
||||
import net.kdt.pojavlaunch.Tools;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static net.kdt.pojavlaunch.customcontrols.ControlDrawerData.Orientation.DOWN;
|
||||
import static net.kdt.pojavlaunch.customcontrols.ControlDrawerData.Orientation.LEFT;
|
||||
import static net.kdt.pojavlaunch.customcontrols.ControlDrawerData.Orientation.RIGHT;
|
||||
import static net.kdt.pojavlaunch.customcontrols.ControlDrawerData.Orientation.UP;
|
||||
|
||||
public class ControlDrawerData {
|
||||
|
||||
public ArrayList<ControlData> buttonProperties;
|
||||
public ControlData properties;
|
||||
public Orientation orientation;
|
||||
|
||||
public enum Orientation {
|
||||
DOWN,
|
||||
LEFT,
|
||||
UP,
|
||||
RIGHT
|
||||
}
|
||||
|
||||
public static Orientation[] getOrientations(){
|
||||
return new Orientation[]{DOWN,LEFT,UP,RIGHT};
|
||||
}
|
||||
|
||||
public static int orientationToInt(Orientation orientation){
|
||||
switch (orientation){
|
||||
case DOWN:
|
||||
return 0;
|
||||
case LEFT:
|
||||
return 1;
|
||||
case UP:
|
||||
return 2;
|
||||
case RIGHT:
|
||||
return 3;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static Orientation intToOrientation(int by){
|
||||
switch (by){
|
||||
case 0:
|
||||
return Orientation.DOWN;
|
||||
case 1:
|
||||
return Orientation.LEFT;
|
||||
case 2:
|
||||
return Orientation.UP;
|
||||
case 3:
|
||||
return RIGHT;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ControlDrawerData(){
|
||||
this(new ArrayList<>());
|
||||
}
|
||||
|
||||
public ControlDrawerData(ArrayList<ControlData> buttonProperties){
|
||||
this(buttonProperties, new ControlData("Drawer", new int[] {}, Tools.currentDisplayMetrics.widthPixels/2, Tools.currentDisplayMetrics.heightPixels/2));
|
||||
}
|
||||
|
||||
public ControlDrawerData(ArrayList<ControlData> buttonProperties, ControlData properties){
|
||||
this(buttonProperties, properties, Orientation.LEFT);
|
||||
}
|
||||
|
||||
|
||||
public ControlDrawerData(ArrayList<ControlData> buttonProperties, ControlData properties, Orientation orientation){
|
||||
this.buttonProperties = buttonProperties;
|
||||
this.properties = properties;
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,10 +6,19 @@ import android.widget.*;
|
||||
import com.google.gson.*;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import net.kdt.pojavlaunch.*;
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton;
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlDrawer;
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlSubButton;
|
||||
import net.kdt.pojavlaunch.customcontrols.handleview.HandleView;
|
||||
import net.kdt.pojavlaunch.prefs.*;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.lwjgl.glfw.*;
|
||||
|
||||
public class ControlLayout extends FrameLayout
|
||||
@@ -28,59 +37,62 @@ public class ControlLayout extends FrameLayout
|
||||
}
|
||||
|
||||
public void hideAllHandleViews() {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View view = getChildAt(i);
|
||||
if (view instanceof ControlButton) {
|
||||
((ControlButton) view).getHandleView().hide();
|
||||
}
|
||||
for(ControlButton button : getButtonChildren()){
|
||||
HandleView hv = button.getHandleView();
|
||||
if(hv != null) hv.hide();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadLayout(String jsonPath) throws IOException, JsonSyntaxException {
|
||||
loadLayout(Tools.GLOBAL_GSON.fromJson(Tools.read(jsonPath), CustomControls.class));
|
||||
CustomControls layout = LayoutConverter.loadAndConvertIfNecessary(jsonPath);
|
||||
if(layout != null) {
|
||||
loadLayout(layout);
|
||||
}else{
|
||||
throw new IOException("Unsupported control layout version");
|
||||
}
|
||||
}
|
||||
|
||||
public void loadLayout(CustomControls controlLayout) {
|
||||
if (mModifiable) {
|
||||
if (mModifiable)
|
||||
hideAllHandleViews();
|
||||
}
|
||||
/*if (getChildAt(0) instanceof MinecraftGLView) {
|
||||
View viewGL = getChildAt(0);
|
||||
View viewTouchpad = getChildAt(1);
|
||||
removeAllViews();
|
||||
addView(viewGL);
|
||||
addView(viewTouchpad);
|
||||
} else {
|
||||
removeAllViews();*/
|
||||
removeAllButtons();
|
||||
//}
|
||||
if (mLayout != null) {
|
||||
mLayout.mControlDataList = null;
|
||||
mLayout = null;
|
||||
}
|
||||
|
||||
removeAllButtons();
|
||||
if(mLayout != null) {
|
||||
mLayout.mControlDataList = null;
|
||||
mLayout = null;
|
||||
}
|
||||
|
||||
System.gc();
|
||||
mapTable.clear();
|
||||
|
||||
// Cleanup buttons only when input layout is null
|
||||
if (controlLayout == null) return;
|
||||
|
||||
mLayout = controlLayout;
|
||||
|
||||
|
||||
//CONTROL BUTTON
|
||||
for (ControlData button : controlLayout.mControlDataList) {
|
||||
button.isHideable = button.keycode != ControlData.SPECIALBTN_TOGGLECTRL && button.keycode != ControlData.SPECIALBTN_VIRTUALMOUSE;
|
||||
button.width = button.width / controlLayout.scaledAt * LauncherPreferences.PREF_BUTTONSIZE;
|
||||
button.height = button.height / controlLayout.scaledAt * LauncherPreferences.PREF_BUTTONSIZE;
|
||||
if (!button.isDynamicBtn) {
|
||||
button.dynamicX = Float.toString(button.x / CallbackBridge.physicalWidth) + " * ${screen_width}";
|
||||
button.dynamicY = Float.toString(button.y / CallbackBridge.physicalHeight) + " * ${screen_height}";
|
||||
}
|
||||
button.update();
|
||||
addControlView(button);
|
||||
}
|
||||
|
||||
//CONTROL DRAWER
|
||||
for(ControlDrawerData drawerData : controlLayout.mDrawerDataList){
|
||||
ControlDrawer drawer = addDrawerView(drawerData);
|
||||
if(mModifiable) drawer.areButtonsVisible = true;
|
||||
|
||||
|
||||
//CONTROL SUB BUTTON
|
||||
for (ControlData subButton : drawerData.buttonProperties) {
|
||||
addSubView(drawer, subButton);
|
||||
}
|
||||
}
|
||||
|
||||
mLayout.scaledAt = LauncherPreferences.PREF_BUTTONSIZE;
|
||||
|
||||
setModified(false);
|
||||
}
|
||||
} // loadLayout
|
||||
|
||||
//CONTROL BUTTON
|
||||
public void addControlButton(ControlData controlButton) {
|
||||
mLayout.mControlDataList.add(controlButton);
|
||||
addControlView(controlButton);
|
||||
@@ -90,7 +102,7 @@ public class ControlLayout extends FrameLayout
|
||||
final ControlButton view = new ControlButton(this, controlButton);
|
||||
view.setModifiable(mModifiable);
|
||||
if (!mModifiable) {
|
||||
view.setAlpha(1f - view.getProperties().transparency / 100f);
|
||||
view.setAlpha(view.getProperties().opacity);
|
||||
view.setFocusable(false);
|
||||
view.setFocusableInTouchMode(false);
|
||||
}
|
||||
@@ -98,22 +110,63 @@ public class ControlLayout extends FrameLayout
|
||||
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
// CONTROL DRAWER
|
||||
public void addDrawer(ControlDrawerData drawerData){
|
||||
mLayout.mDrawerDataList.add(drawerData);
|
||||
addDrawerView();
|
||||
}
|
||||
|
||||
private void addDrawerView(){
|
||||
addDrawerView(null);
|
||||
}
|
||||
|
||||
private ControlDrawer addDrawerView(ControlDrawerData drawerData){
|
||||
|
||||
final ControlDrawer view = new ControlDrawer(this,drawerData == null ? mLayout.mDrawerDataList.get(mLayout.mDrawerDataList.size()-1) : drawerData);
|
||||
view.setModifiable(mModifiable);
|
||||
if (!mModifiable) {
|
||||
view.setAlpha(view.getProperties().opacity);
|
||||
view.setFocusable(false);
|
||||
view.setFocusableInTouchMode(false);
|
||||
}
|
||||
addView(view);
|
||||
|
||||
setModified(true);
|
||||
return view;
|
||||
}
|
||||
|
||||
//CONTROL SUB-BUTTON
|
||||
public void addSubButton(ControlDrawer drawer, ControlData controlButton){
|
||||
//Yep there isn't much here
|
||||
drawer.getDrawerData().buttonProperties.add(controlButton);
|
||||
addSubView(drawer, drawer.getDrawerData().buttonProperties.get(drawer.getDrawerData().buttonProperties.size()-1 ));
|
||||
}
|
||||
|
||||
public void addSubView(ControlDrawer drawer, ControlData controlButton){
|
||||
final ControlSubButton view = new ControlSubButton(this, controlButton, drawer);
|
||||
view.setModifiable(mModifiable);
|
||||
if (!mModifiable) {
|
||||
view.setAlpha(view.getProperties().opacity);
|
||||
view.setFocusable(false);
|
||||
view.setFocusableInTouchMode(false);
|
||||
}
|
||||
drawer.addButton(view);
|
||||
addView(view);
|
||||
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
private void removeAllButtons() {
|
||||
List<View> viewList = new ArrayList<>();
|
||||
View v;
|
||||
for(int i = 0; i < getChildCount(); i++) {
|
||||
v = getChildAt(i);
|
||||
if(v instanceof ControlButton) viewList.add(v);
|
||||
for(View v : getButtonChildren()){
|
||||
removeView(v);
|
||||
}
|
||||
v = null;
|
||||
for(View v2 : viewList) {
|
||||
removeView(v2);
|
||||
}
|
||||
viewList = null;
|
||||
|
||||
System.gc();
|
||||
//i wanna be sure that all the removed Views will be removed after a reload
|
||||
//because if frames will slowly go down after many control changes it will be warm and bad
|
||||
}
|
||||
|
||||
public void removeControlButton(ControlButton controlButton) {
|
||||
mLayout.mControlDataList.remove(controlButton.getProperties());
|
||||
controlButton.setVisibility(View.GONE);
|
||||
@@ -122,6 +175,22 @@ public class ControlLayout extends FrameLayout
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
public void removeControlDrawer(ControlDrawer controlDrawer){
|
||||
mLayout.mDrawerDataList.remove(controlDrawer.getDrawerData());
|
||||
controlDrawer.setVisibility(GONE);
|
||||
removeView(controlDrawer);
|
||||
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
public void removeControlSubButton(ControlSubButton subButton){
|
||||
subButton.parentDrawer.drawerData.buttonProperties.remove(subButton.getProperties());
|
||||
subButton.parentDrawer.buttons.remove(subButton);
|
||||
|
||||
subButton.setVisibility(GONE);
|
||||
removeView(subButton);
|
||||
}
|
||||
|
||||
public void saveLayout(String path) throws Exception {
|
||||
mLayout.save(path);
|
||||
setModified(false);
|
||||
@@ -130,34 +199,97 @@ public class ControlLayout extends FrameLayout
|
||||
public void setActivity(CustomControlsActivity activity) {
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
public void toggleControlVisible() {
|
||||
if (mModifiable) return; // Not using on custom controls activity
|
||||
|
||||
|
||||
public void toggleControlVisible(){
|
||||
mControlVisible = !mControlVisible;
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View view = getChildAt(i);
|
||||
if (view instanceof ControlButton && ((ControlButton) view).getProperties().isHideable) {
|
||||
((ControlButton) view).setVisibility(mControlVisible ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
setControlVisible(mControlVisible);
|
||||
}
|
||||
|
||||
public float getLayoutScale(){
|
||||
return mLayout.scaledAt;
|
||||
}
|
||||
|
||||
public void setControlVisible(boolean isVisible) {
|
||||
if (mModifiable) return; // Not using on custom controls activity
|
||||
|
||||
mControlVisible = isVisible;
|
||||
for(ControlButton button : getButtonChildren()){
|
||||
button.setVisible(isVisible);
|
||||
}
|
||||
}
|
||||
|
||||
public void setModifiable(boolean z) {
|
||||
mModifiable = z;
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View v = getChildAt(i);
|
||||
if (v instanceof ControlButton) {
|
||||
ControlButton cv = ((ControlButton) v);
|
||||
cv.setModifiable(z);
|
||||
if (!z) {
|
||||
cv.setAlpha(1f - cv.getProperties().transparency / 100f);
|
||||
}
|
||||
}
|
||||
public void setModifiable(boolean isModifiable) {
|
||||
mModifiable = isModifiable;
|
||||
for(ControlButton button : getButtonChildren()){
|
||||
button.setModifiable(isModifiable);
|
||||
if (!isModifiable)
|
||||
button.setAlpha(button.getProperties().opacity);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setModified(boolean z) {
|
||||
if (mActivity != null) mActivity.isModified = z;
|
||||
public boolean getModifiable(){
|
||||
return mModifiable;
|
||||
}
|
||||
|
||||
public void setModified(boolean isModified) {
|
||||
if (mActivity != null) mActivity.isModified = isModified;
|
||||
|
||||
}
|
||||
|
||||
private ArrayList<ControlButton> getButtonChildren(){
|
||||
ArrayList<ControlButton> children = new ArrayList<>();
|
||||
for(int i=0; i<getChildCount(); ++i){
|
||||
View v = getChildAt(i);
|
||||
if(v instanceof ControlButton)
|
||||
children.add(((ControlButton) v));
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
HashMap<View, ControlButton> mapTable = new HashMap<>();
|
||||
//While this is called onTouch, this should only be called from a ControlButton.
|
||||
public boolean onTouch(View v, MotionEvent ev) {
|
||||
ControlButton lastControlButton = mapTable.get(v);
|
||||
|
||||
//Check if the action is cancelling, reset the lastControl button associated to the view
|
||||
if(ev.getActionMasked() == MotionEvent.ACTION_UP || ev.getActionMasked() == MotionEvent.ACTION_CANCEL){
|
||||
if(lastControlButton != null) lastControlButton.onTouchEvent(ev);
|
||||
mapTable.put(v, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(ev.getActionMasked() != MotionEvent.ACTION_MOVE) return false;
|
||||
|
||||
//Optimization pass to avoid looking at all children again
|
||||
if(lastControlButton != null){
|
||||
if( ev.getRawX() > lastControlButton.getX() && ev.getRawX() < lastControlButton.getX() + lastControlButton.getWidth() &&
|
||||
ev.getRawY() > lastControlButton.getY() && ev.getRawY() < lastControlButton.getY() + lastControlButton.getHeight()){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Release the last key
|
||||
ev.setAction(MotionEvent.ACTION_POINTER_UP);
|
||||
if (lastControlButton != null) lastControlButton.onTouchEvent(ev);
|
||||
mapTable.put(v, null);
|
||||
|
||||
//Look for another SWIPEABLE button
|
||||
for(ControlButton button : getButtonChildren()){
|
||||
if(!button.getProperties().isSwipeable) continue;
|
||||
|
||||
if( ev.getRawX() > button.getX() && ev.getRawX() < button.getX() + button.getWidth() &&
|
||||
ev.getRawY() > button.getY() && ev.getRawY() < button.getY() + button.getHeight()){
|
||||
|
||||
//Press the new key
|
||||
if(!button.equals(lastControlButton)){
|
||||
ev.setAction(MotionEvent.ACTION_POINTER_DOWN);
|
||||
button.onTouchEvent(ev);
|
||||
|
||||
mapTable.put(v, button);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,26 @@
|
||||
package net.kdt.pojavlaunch.customcontrols;
|
||||
import android.content.*;
|
||||
import com.google.gson.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import net.kdt.pojavlaunch.*;
|
||||
import org.lwjgl.glfw.*;
|
||||
|
||||
public class CustomControls
|
||||
{
|
||||
public class CustomControls {
|
||||
public int version = -1;
|
||||
public float scaledAt;
|
||||
public List<ControlData> mControlDataList;
|
||||
public List<ControlDrawerData> mDrawerDataList;
|
||||
public CustomControls() {
|
||||
this(new ArrayList<ControlData>());
|
||||
this(new ArrayList<>(), new ArrayList<>());
|
||||
}
|
||||
|
||||
public CustomControls(List<ControlData> mControlDataList) {
|
||||
|
||||
|
||||
|
||||
public CustomControls(List<ControlData> mControlDataList, List<ControlDrawerData> mDrawerDataList) {
|
||||
this.mControlDataList = mControlDataList;
|
||||
this.mDrawerDataList = mDrawerDataList;
|
||||
this.scaledAt = 100f;
|
||||
}
|
||||
|
||||
@@ -27,35 +33,42 @@ public class CustomControls
|
||||
this.mControlDataList.add(ControlData.getSpecialButtons()[3].clone()); // Secondary Mouse mControlDataList
|
||||
this.mControlDataList.add(ControlData.getSpecialButtons()[4].clone()); // Virtual mouse toggle
|
||||
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_debug, LWJGLGLFWKeycode.GLFW_KEY_F3, "${margin}", "${margin}", false));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_chat, LWJGLGLFWKeycode.GLFW_KEY_T, "${margin} * 2 + ${width}", "${margin}", false));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_listplayers, LWJGLGLFWKeycode.GLFW_KEY_TAB, "${margin} * 4 + ${width} * 3", "${margin}", false));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_thirdperson, LWJGLGLFWKeycode.GLFW_KEY_F5, "${margin}", "${height} + ${margin}", false));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_debug, new int[]{LWJGLGLFWKeycode.GLFW_KEY_F3}, "${margin}", "${margin}", false));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_chat, new int[]{LWJGLGLFWKeycode.GLFW_KEY_T}, "${margin} * 2 + ${width}", "${margin}", false));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_listplayers, new int[]{LWJGLGLFWKeycode.GLFW_KEY_TAB}, "${margin} * 4 + ${width} * 3", "${margin}", false));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_thirdperson, new int[]{LWJGLGLFWKeycode.GLFW_KEY_F5}, "${margin}", "${height} + ${margin}", false));
|
||||
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_up, LWJGLGLFWKeycode.GLFW_KEY_W, "${margin} * 2 + ${width}", "${bottom} - ${margin} * 3 - ${height} * 2", true));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_left, LWJGLGLFWKeycode.GLFW_KEY_A, "${margin}", "${bottom} - ${margin} * 2 - ${height}", true));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_down, LWJGLGLFWKeycode.GLFW_KEY_S, "${margin} * 2 + ${width}", "${bottom} - ${margin}", true));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_right, LWJGLGLFWKeycode.GLFW_KEY_D, "${margin} * 3 + ${width} * 2", "${bottom} - ${margin} * 2 - ${height}", true));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_up, new int[]{LWJGLGLFWKeycode.GLFW_KEY_W}, "${margin} * 2 + ${width}", "${bottom} - ${margin} * 3 - ${height} * 2", true));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_left, new int[]{LWJGLGLFWKeycode.GLFW_KEY_A}, "${margin}", "${bottom} - ${margin} * 2 - ${height}", true));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_down, new int[]{LWJGLGLFWKeycode.GLFW_KEY_S}, "${margin} * 2 + ${width}", "${bottom} - ${margin}", true));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_right, new int[]{LWJGLGLFWKeycode.GLFW_KEY_D}, "${margin} * 3 + ${width} * 2", "${bottom} - ${margin} * 2 - ${height}", true));
|
||||
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_inventory, LWJGLGLFWKeycode.GLFW_KEY_E, "${margin} * 3 + ${width} * 2", "${bottom} - ${margin}", true));
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_inventory, new int[]{LWJGLGLFWKeycode.GLFW_KEY_E}, "${margin} * 3 + ${width} * 2", "${bottom} - ${margin}", true));
|
||||
|
||||
ControlData shiftData = new ControlData(ctx, R.string.control_shift, LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT, "${margin} * 2 + ${width}", "${screen_height} - ${margin} * 2 - ${height} * 2", true);
|
||||
ControlData shiftData = new ControlData(ctx, R.string.control_shift, new int[]{LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT}, "${margin} * 2 + ${width}", "${screen_height} - ${margin} * 2 - ${height} * 2", true);
|
||||
shiftData.isToggle = true;
|
||||
this.mControlDataList.add(shiftData);
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_jump, LWJGLGLFWKeycode.GLFW_KEY_SPACE, "${right} - ${margin} * 2 - ${width}", "${bottom} - ${margin} * 2 - ${height}", true));
|
||||
|
||||
this.mControlDataList.add(new ControlData(ctx, R.string.control_jump, new int[]{LWJGLGLFWKeycode.GLFW_KEY_SPACE}, "${right} - ${margin} * 2 - ${width}", "${bottom} - ${margin} * 2 - ${height}", true));
|
||||
|
||||
//The default controls are conform to the V2
|
||||
version = 2;
|
||||
}
|
||||
|
||||
public ControlData findControlData(int keycode) {
|
||||
for (ControlData data : mControlDataList) {
|
||||
if (data.keycode == keycode) {
|
||||
return data;
|
||||
}
|
||||
for(int dataKeycode : data.keycodes){
|
||||
if (dataKeycode == keycode) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void save(String path) throws Exception {
|
||||
public void save(String path) throws IOException {
|
||||
//Current version is the V2 so the version as to be marked as 2 !
|
||||
version = 2;
|
||||
|
||||
Tools.write(path, Tools.GLOBAL_GSON.toJson(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package net.kdt.pojavlaunch.customcontrols;
|
||||
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import net.kdt.pojavlaunch.LWJGLGLFWKeycode;
|
||||
import net.kdt.pojavlaunch.Tools;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class LayoutConverter {
|
||||
public static boolean convertLookType = false; //false = flat; true = classic
|
||||
public static CustomControls loadAndConvertIfNecessary(String jsonPath) throws IOException, JsonSyntaxException {
|
||||
String jsonLayoutData = Tools.read(jsonPath);
|
||||
try {
|
||||
JSONObject layoutJobj = new JSONObject(jsonLayoutData);
|
||||
|
||||
if(!layoutJobj.has("version")) { //v1 layout
|
||||
CustomControls layout = LayoutConverter.convertV1Layout(layoutJobj);
|
||||
layout.save(jsonPath);
|
||||
return layout;
|
||||
}else if (layoutJobj.getInt("version") == 2) {
|
||||
return Tools.GLOBAL_GSON.fromJson(jsonLayoutData, CustomControls.class);
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}catch (JSONException e) {
|
||||
throw new JsonSyntaxException("Failed to load",e);
|
||||
}
|
||||
}
|
||||
public static CustomControls convertV1Layout(JSONObject oldLayoutJson) throws JSONException {
|
||||
CustomControls empty = new CustomControls();
|
||||
JSONArray layoutMainArray = oldLayoutJson.getJSONArray("mControlDataList");
|
||||
for(int i = 0; i < layoutMainArray.length(); i++) {
|
||||
JSONObject button = layoutMainArray.getJSONObject(i);
|
||||
ControlData n_button = new ControlData();
|
||||
int[] keycodes = new int[] {LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN,
|
||||
LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN,
|
||||
LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN,
|
||||
LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN};
|
||||
n_button.dynamicX = button.getString("dynamicX");
|
||||
n_button.dynamicY = button.getString("dynamicY");
|
||||
n_button.isDynamicBtn = button.getBoolean("isDynamicBtn");
|
||||
n_button.name = button.getString("name");
|
||||
n_button.opacity = ((float)((button.getInt("transparency")-100)*-1))/100f;
|
||||
n_button.passThruEnabled = button.getBoolean("passThruEnabled");
|
||||
n_button.isToggle = button.getBoolean("isToggle");
|
||||
n_button.x = button.getInt("x");
|
||||
n_button.y = button.getInt("y");
|
||||
n_button.setHeight(button.getInt("height"));
|
||||
n_button.setWidth(button.getInt("width"));
|
||||
if(convertLookType) {
|
||||
n_button.strokeColor = 0xdd7f7f7f;
|
||||
n_button.bgColor = 0x807f7f7f;
|
||||
n_button.strokeWidth = 10;
|
||||
}else{
|
||||
n_button.bgColor = 0x4d000000;
|
||||
n_button.strokeWidth = 0;
|
||||
}
|
||||
if(button.getBoolean("isRound")) { n_button.cornerRadius = 35f; }
|
||||
int next_idx = 0;
|
||||
if(button.getBoolean("holdShift")) { keycodes[next_idx] = LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT; next_idx++; }
|
||||
if(button.getBoolean("holdCtrl")) { keycodes[next_idx] = LWJGLGLFWKeycode.GLFW_KEY_LEFT_CONTROL; next_idx++; }
|
||||
if(button.getBoolean("holdAlt")) { keycodes[next_idx] = LWJGLGLFWKeycode.GLFW_KEY_LEFT_ALT; next_idx++; }
|
||||
keycodes[next_idx] = button.getInt("keycode");
|
||||
n_button.keycodes = keycodes;
|
||||
n_button.update();
|
||||
empty.mControlDataList.add(n_button);
|
||||
}
|
||||
empty.scaledAt = (float)oldLayoutJson.getDouble("scaledAt");
|
||||
empty.version = 2;
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.buttons;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.*;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.util.*;
|
||||
import android.view.*;
|
||||
import android.view.View.*;
|
||||
import android.widget.*;
|
||||
|
||||
import net.kdt.pojavlaunch.customcontrols.ControlData;
|
||||
import net.kdt.pojavlaunch.customcontrols.ControlLayout;
|
||||
import net.kdt.pojavlaunch.customcontrols.handleview.*;
|
||||
import net.kdt.pojavlaunch.*;
|
||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||
|
||||
import org.lwjgl.glfw.*;
|
||||
|
||||
import static net.kdt.pojavlaunch.LWJGLGLFWKeycode.GLFW_KEY_UNKNOWN;
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
public class ControlButton extends androidx.appcompat.widget.AppCompatButton implements OnLongClickListener
|
||||
{
|
||||
private Paint mRectPaint;
|
||||
|
||||
protected GestureDetector mGestureDetector;
|
||||
protected ControlData mProperties;
|
||||
protected SelectionEndHandleView mHandleView;
|
||||
|
||||
protected boolean mModifiable = false;
|
||||
protected boolean mCanTriggerLongClick = true;
|
||||
|
||||
protected boolean isToggled = false;
|
||||
protected boolean isPointerOutOfBounds = false;
|
||||
|
||||
public ControlButton(ControlLayout layout, ControlData properties) {
|
||||
super(layout.getContext());
|
||||
setPadding(4, 4, 4, 4);
|
||||
|
||||
setOnLongClickListener(this);
|
||||
|
||||
//When a button is created, the width/height has yet to be processed to fit the scaling.
|
||||
setProperties(preProcessProperties(properties, layout));
|
||||
setModified(false);
|
||||
|
||||
|
||||
//For the toggle layer
|
||||
final TypedValue value = new TypedValue();
|
||||
getContext().getTheme().resolveAttribute(R.attr.colorAccent, value, true);
|
||||
|
||||
mRectPaint = new Paint();
|
||||
mRectPaint.setColor(value.data);
|
||||
mRectPaint.setAlpha(128);
|
||||
}
|
||||
|
||||
public HandleView getHandleView() {
|
||||
return mHandleView;
|
||||
}
|
||||
|
||||
public ControlData getProperties() {
|
||||
return mProperties;
|
||||
}
|
||||
|
||||
public void setProperties(ControlData properties) {
|
||||
setProperties(properties, true);
|
||||
}
|
||||
|
||||
public ControlData preProcessProperties(ControlData properties, ControlLayout layout){
|
||||
//When a button is created, properties have to be modified to fit the screen.
|
||||
//Size
|
||||
properties.setWidth(properties.getWidth() / layout.getLayoutScale() * LauncherPreferences.PREF_BUTTONSIZE);
|
||||
properties.setHeight(properties.getHeight() / layout.getLayoutScale() * LauncherPreferences.PREF_BUTTONSIZE);
|
||||
|
||||
//Visibility
|
||||
properties.isHideable = !properties.containsKeycode(ControlData.SPECIALBTN_TOGGLECTRL) && !properties.containsKeycode(ControlData.SPECIALBTN_VIRTUALMOUSE);
|
||||
|
||||
//Position
|
||||
if (!properties.isDynamicBtn) {
|
||||
properties.dynamicX = properties.x / CallbackBridge.physicalWidth + " * ${screen_width}";
|
||||
properties.dynamicY = properties.y / CallbackBridge.physicalHeight + " * ${screen_height}";
|
||||
}
|
||||
|
||||
properties.update();
|
||||
return properties;
|
||||
}
|
||||
|
||||
public void setProperties(ControlData properties, boolean changePos) {
|
||||
mProperties = properties;
|
||||
|
||||
properties.update();
|
||||
|
||||
// com.android.internal.R.string.delete
|
||||
// android.R.string.
|
||||
setText(properties.name);
|
||||
|
||||
if (changePos) {
|
||||
setX(properties.x);
|
||||
setY(properties.y);
|
||||
}
|
||||
|
||||
if (properties.specialButtonListener == null) {
|
||||
// A non-special button or inside custom controls screen so skip listener
|
||||
} else if (properties.specialButtonListener instanceof View.OnClickListener) {
|
||||
setOnClickListener((View.OnClickListener) properties.specialButtonListener);
|
||||
// setOnLongClickListener(null);
|
||||
// setOnTouchListener(null);
|
||||
} else if (properties.specialButtonListener instanceof View.OnTouchListener) {
|
||||
// setOnLongClickListener(null);
|
||||
setOnTouchListener((View.OnTouchListener) properties.specialButtonListener);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Field " + ControlData.class.getName() + ".specialButtonListener must be View.OnClickListener or View.OnTouchListener, but was " +
|
||||
properties.specialButtonListener.getClass().getName());
|
||||
}
|
||||
|
||||
setLayoutParams(new FrameLayout.LayoutParams((int) properties.getWidth(), (int) properties.getHeight() ));
|
||||
}
|
||||
|
||||
public void setBackground(){
|
||||
GradientDrawable gd = new GradientDrawable();
|
||||
gd.setColor(mProperties.bgColor);
|
||||
gd.setStroke(computeStrokeWidth(mProperties.strokeWidth), mProperties.strokeColor);
|
||||
gd.setCornerRadius(computeCornerRadius(mProperties.cornerRadius));
|
||||
|
||||
setBackground(gd);
|
||||
}
|
||||
|
||||
public void setModifiable(boolean isModifiable) {
|
||||
mModifiable = isModifiable;
|
||||
}
|
||||
|
||||
private void setModified(boolean modified) {
|
||||
if (getParent() != null)
|
||||
((ControlLayout) getParent()).setModified(modified);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setLayoutParams(ViewGroup.LayoutParams params) {
|
||||
super.setLayoutParams(params);
|
||||
|
||||
mProperties.setWidth(params.width);
|
||||
mProperties.setHeight(params.height);
|
||||
setBackground();
|
||||
|
||||
// Re-calculate position
|
||||
mProperties.update();
|
||||
setX(mProperties.x);
|
||||
setY(mProperties.y);
|
||||
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
public void setVisible(boolean isVisible){
|
||||
if(mProperties.isHideable)
|
||||
setVisibility(isVisible ? VISIBLE : GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setX(float x) {
|
||||
super.setX(x);
|
||||
|
||||
if (!mProperties.isDynamicBtn) {
|
||||
mProperties.x = x;
|
||||
mProperties.dynamicX = x / CallbackBridge.physicalWidth + " * ${screen_width}";
|
||||
setModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setY(float y) {
|
||||
super.setY(y);
|
||||
|
||||
if (!mProperties.isDynamicBtn) {
|
||||
mProperties.y = y;
|
||||
mProperties.dynamicY = y / CallbackBridge.physicalHeight + " * ${screen_height}";
|
||||
setModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateProperties() {
|
||||
setProperties(mProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (isToggled)
|
||||
canvas.drawRoundRect(0, 0, getWidth(), getHeight(), mProperties.cornerRadius, mProperties.cornerRadius, mRectPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (mCanTriggerLongClick && mModifiable) {
|
||||
//Instantiate on need only
|
||||
if(mHandleView == null) mHandleView = new SelectionEndHandleView(this);
|
||||
|
||||
if (mHandleView.isShowing()) {
|
||||
mHandleView.hide();
|
||||
} else {
|
||||
if (getParent() != null) {
|
||||
((ControlLayout) getParent()).hideAllHandleViews();
|
||||
}
|
||||
|
||||
try {
|
||||
mHandleView.show(this);
|
||||
} catch (Throwable th) {
|
||||
th.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mCanTriggerLongClick;
|
||||
}
|
||||
|
||||
protected float downX, downY;
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if(!mModifiable){
|
||||
mCanTriggerLongClick = false;
|
||||
|
||||
switch (event.getActionMasked()){
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
//Send the event to be taken as a mouse action
|
||||
if(mProperties.passThruEnabled && CallbackBridge.isGrabbing()){
|
||||
MinecraftGLView v = ((ControlLayout) this.getParent()).findViewById(R.id.main_game_render_view);
|
||||
if (v != null) v.dispatchTouchEvent(event);
|
||||
}
|
||||
|
||||
//If out of bounds
|
||||
if(event.getX() < getLeft() || event.getX() > getRight() ||
|
||||
event.getY() < getTop() || event.getY() > getBottom()){
|
||||
if(mProperties.isSwipeable && !isPointerOutOfBounds){
|
||||
//Remove keys
|
||||
if(!triggerToggle(event)) {
|
||||
sendKeyPresses(event, false);
|
||||
}
|
||||
}
|
||||
isPointerOutOfBounds = true;
|
||||
((ControlLayout) getParent()).onTouch(this, event);
|
||||
break;
|
||||
}
|
||||
|
||||
//Else if we now are in bounds
|
||||
if(isPointerOutOfBounds) {
|
||||
((ControlLayout) getParent()).onTouch(this, event);
|
||||
//RE-press the button
|
||||
if(mProperties.isSwipeable && !mProperties.isToggle){
|
||||
sendKeyPresses(event, true);
|
||||
}
|
||||
}
|
||||
isPointerOutOfBounds = false;
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_DOWN: // 0
|
||||
case MotionEvent.ACTION_POINTER_DOWN: // 5
|
||||
if(!mProperties.isToggle){
|
||||
sendKeyPresses(event, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP: // 1
|
||||
case MotionEvent.ACTION_CANCEL: // 3
|
||||
case MotionEvent.ACTION_POINTER_UP: // 6
|
||||
if(isPointerOutOfBounds) ((ControlLayout) getParent()).onTouch(this, event);
|
||||
isPointerOutOfBounds = false;
|
||||
|
||||
if(!triggerToggle(event)) {
|
||||
sendKeyPresses(event, false);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If the button can be modified/moved */
|
||||
//Instantiate the gesture detector only when needed
|
||||
if(mGestureDetector == null) mGestureDetector = new GestureDetector(getContext(), new SingleTapConfirm());
|
||||
|
||||
if (mGestureDetector.onTouchEvent(event)) {
|
||||
mCanTriggerLongClick = true;
|
||||
onLongClick(this);
|
||||
}
|
||||
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mCanTriggerLongClick = true;
|
||||
downX = event.getRawX() - getX();
|
||||
downY = event.getRawY() - getY();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
mCanTriggerLongClick = false;
|
||||
|
||||
if (!mProperties.isDynamicBtn) {
|
||||
setX(event.getRawX() - downX);
|
||||
setY(event.getRawY() - downY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
public int computeStrokeWidth(float widthInPercent){
|
||||
float maxSize = Math.max(mProperties.getWidth(), mProperties.getHeight());
|
||||
return (int)((maxSize/2) * (widthInPercent/100));
|
||||
}
|
||||
|
||||
public float computeCornerRadius(float radiusInPercent){
|
||||
float minSize = Math.min(mProperties.getWidth(), mProperties.getHeight());
|
||||
return (minSize/2) * (radiusInPercent/100);
|
||||
}
|
||||
|
||||
public boolean triggerToggle(MotionEvent event){
|
||||
//returns true a the toggle system is triggered
|
||||
if(mProperties.isToggle){
|
||||
isToggled = !isToggled;
|
||||
invalidate();
|
||||
sendKeyPresses(event, isToggled);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void sendKeyPresses(MotionEvent event, boolean isDown){
|
||||
for(int keycode : mProperties.keycodes){
|
||||
if(keycode >= GLFW_KEY_UNKNOWN){
|
||||
MainActivity.sendKeyPress(keycode, CallbackBridge.getCurrentMods(), isDown);
|
||||
CallbackBridge.setModifiers(keycode, isDown);
|
||||
}else {
|
||||
super.onTouchEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.buttons;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import net.kdt.pojavlaunch.Tools;
|
||||
import net.kdt.pojavlaunch.customcontrols.ControlData;
|
||||
import net.kdt.pojavlaunch.customcontrols.ControlDrawerData;
|
||||
import net.kdt.pojavlaunch.customcontrols.ControlLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
public class ControlDrawer extends ControlButton {
|
||||
|
||||
|
||||
public ArrayList<ControlSubButton> buttons;
|
||||
public ControlDrawerData drawerData;
|
||||
public ControlLayout mLayout;
|
||||
public boolean areButtonsVisible = false;
|
||||
|
||||
|
||||
public ControlDrawer(ControlLayout layout, ControlDrawerData drawerData) {
|
||||
super(layout, drawerData.properties);
|
||||
|
||||
buttons = new ArrayList<>(drawerData.buttonProperties.size());
|
||||
mLayout = layout;
|
||||
this.drawerData = drawerData;
|
||||
}
|
||||
|
||||
|
||||
public void addButton(ControlData properties){
|
||||
addButton(new ControlSubButton(mLayout, properties, this));
|
||||
}
|
||||
|
||||
public void addButton(ControlSubButton button){
|
||||
buttons.add(button);
|
||||
setControlButtonVisibility(button, mModifiable || areButtonsVisible);
|
||||
syncButtons();
|
||||
}
|
||||
|
||||
private void setControlButtonVisibility(ControlButton button, boolean isVisible){
|
||||
button.setVisible(isVisible);
|
||||
}
|
||||
|
||||
private void switchButtonVisibility(){
|
||||
areButtonsVisible = !areButtonsVisible;
|
||||
for(ControlButton button : buttons){
|
||||
button.setVisible(areButtonsVisible);
|
||||
}
|
||||
}
|
||||
|
||||
//Syncing stuff
|
||||
private void alignButtons(){
|
||||
|
||||
if(buttons == null) return;
|
||||
for(int i=0; i < buttons.size(); ++i){
|
||||
switch (drawerData.orientation){
|
||||
case RIGHT:
|
||||
buttons.get(i).setX(drawerData.properties.x + (drawerData.properties.getWidth() + Tools.dpToPx(2))*(i+1) );
|
||||
buttons.get(i).setY(drawerData.properties.y);
|
||||
break;
|
||||
|
||||
case LEFT:
|
||||
buttons.get(i).setX(drawerData.properties.x - (drawerData.properties.getWidth() + Tools.dpToPx(2))*(i+1) );
|
||||
buttons.get(i).setY(drawerData.properties.y);
|
||||
break;
|
||||
|
||||
case UP:
|
||||
buttons.get(i).setY(drawerData.properties.y - (drawerData.properties.getHeight() + Tools.dpToPx(2))*(i+1) );
|
||||
buttons.get(i).setX(drawerData.properties.x);
|
||||
break;
|
||||
|
||||
case DOWN:
|
||||
buttons.get(i).setY(drawerData.properties.y + (drawerData.properties.getHeight() + Tools.dpToPx(2))*(i+1) );
|
||||
buttons.get(i).setX(drawerData.properties.x);
|
||||
break;
|
||||
}
|
||||
buttons.get(i).updateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void resizeButtons(){
|
||||
if (buttons == null) return;
|
||||
for(ControlSubButton subButton : buttons){
|
||||
subButton.mProperties.setWidth(mProperties.getWidth());
|
||||
subButton.mProperties.setHeight(mProperties.getHeight());
|
||||
|
||||
subButton.updateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
private void syncButtons(){
|
||||
alignButtons();
|
||||
resizeButtons();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ControlData preProcessProperties(ControlData properties, ControlLayout layout) {
|
||||
ControlData data = super.preProcessProperties(properties, layout);
|
||||
data.isHideable = true;
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean isVisible) {
|
||||
//TODO replicate changes to his children ?
|
||||
setVisibility(isVisible ? VISIBLE : GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if(!mModifiable){
|
||||
switch (event.getActionMasked()){
|
||||
case MotionEvent.ACTION_UP: // 1
|
||||
case MotionEvent.ACTION_POINTER_UP: // 6
|
||||
switchButtonVisibility();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setX(float x) {
|
||||
super.setX(x);
|
||||
alignButtons();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setY(float y) {
|
||||
super.setY(y);
|
||||
alignButtons();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayoutParams(ViewGroup.LayoutParams params) {
|
||||
super.setLayoutParams(params);
|
||||
syncButtons();
|
||||
}
|
||||
|
||||
//Getters
|
||||
public ControlDrawerData getDrawerData() {
|
||||
return drawerData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.buttons;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import net.kdt.pojavlaunch.SingleTapConfirm;
|
||||
import net.kdt.pojavlaunch.customcontrols.ControlData;
|
||||
import net.kdt.pojavlaunch.customcontrols.ControlLayout;
|
||||
|
||||
public class ControlSubButton extends ControlButton {
|
||||
|
||||
public ControlDrawer parentDrawer;
|
||||
|
||||
public ControlSubButton(ControlLayout layout, ControlData properties, ControlDrawer parentDrawer) {
|
||||
super(layout, properties);
|
||||
this.parentDrawer = parentDrawer;
|
||||
|
||||
//Delayed to let the button inflate first
|
||||
if(!layout.getModifiable())
|
||||
new Handler(Looper.getMainLooper()).postDelayed(() -> setVisibility(parentDrawer.areButtonsVisible ? VISIBLE : GONE), 0);
|
||||
|
||||
filterProperties();
|
||||
}
|
||||
|
||||
private void filterProperties(){
|
||||
mProperties.setHeight(parentDrawer.getProperties().getHeight());
|
||||
mProperties.setWidth(parentDrawer.getProperties().getWidth());
|
||||
mProperties.isDynamicBtn = false;
|
||||
|
||||
setProperties(mProperties, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean isVisible) {
|
||||
setVisibility(isVisible ? (parentDrawer.areButtonsVisible ? VISIBLE : GONE) : (!mProperties.isHideable && parentDrawer.getVisibility() == GONE) ? VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayoutParams(ViewGroup.LayoutParams params) {
|
||||
if(parentDrawer != null){
|
||||
params.width = (int)parentDrawer.mProperties.getWidth();
|
||||
params.height = (int)parentDrawer.mProperties.getHeight();
|
||||
}
|
||||
super.setLayoutParams(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if(!mModifiable){
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
if(mGestureDetector == null) mGestureDetector = new GestureDetector(getContext(), new SingleTapConfirm());
|
||||
|
||||
if (mGestureDetector.onTouchEvent(event)) {
|
||||
mCanTriggerLongClick = true;
|
||||
onLongClick(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.gamepad;
|
||||
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.core.math.MathUtils;
|
||||
|
||||
import net.kdt.pojavlaunch.BaseMainActivity;
|
||||
import net.kdt.pojavlaunch.LWJGLGLFWKeycode;
|
||||
import net.kdt.pojavlaunch.MainActivity;
|
||||
import net.kdt.pojavlaunch.R;
|
||||
|
||||
import org.lwjgl.glfw.CallbackBridge;
|
||||
|
||||
import static net.kdt.pojavlaunch.customcontrols.gamepad.GamepadJoystick.DIRECTION_EAST;
|
||||
import static net.kdt.pojavlaunch.customcontrols.gamepad.GamepadJoystick.DIRECTION_NONE;
|
||||
import static net.kdt.pojavlaunch.customcontrols.gamepad.GamepadJoystick.DIRECTION_NORTH;
|
||||
import static net.kdt.pojavlaunch.customcontrols.gamepad.GamepadJoystick.DIRECTION_NORTH_EAST;
|
||||
import static net.kdt.pojavlaunch.customcontrols.gamepad.GamepadJoystick.DIRECTION_NORTH_WEST;
|
||||
import static net.kdt.pojavlaunch.customcontrols.gamepad.GamepadJoystick.DIRECTION_SOUTH;
|
||||
import static net.kdt.pojavlaunch.customcontrols.gamepad.GamepadJoystick.DIRECTION_SOUTH_EAST;
|
||||
import static net.kdt.pojavlaunch.customcontrols.gamepad.GamepadJoystick.DIRECTION_SOUTH_WEST;
|
||||
import static net.kdt.pojavlaunch.customcontrols.gamepad.GamepadJoystick.DIRECTION_WEST;
|
||||
import static net.kdt.pojavlaunch.customcontrols.gamepad.GamepadJoystick.isJoystickEvent;
|
||||
|
||||
public class Gamepad {
|
||||
|
||||
private final BaseMainActivity gameActivity;
|
||||
private final ImageView pointerView;
|
||||
|
||||
private final GamepadDpad gamepadDpad = new GamepadDpad();
|
||||
|
||||
private final GamepadJoystick leftJoystick;
|
||||
private int currentJoystickDirection = DIRECTION_NONE;
|
||||
|
||||
private final GamepadJoystick rightJoystick;
|
||||
private float lastHorizontalValue = 0.0f;
|
||||
private float lastVerticalValue = 0.0f;
|
||||
|
||||
private final double mouseMaxAcceleration = 2f;
|
||||
private double acceleration = 0.0f;
|
||||
|
||||
private double mouseMagnitude;
|
||||
private double mouseAngle;
|
||||
private double mouseSensitivity = 19;
|
||||
|
||||
private final GamepadMap gameMap = GamepadMap.getDefaultGameMap();
|
||||
private final GamepadMap menuMap = GamepadMap.getDefaultMenuMap();
|
||||
private GamepadMap currentMap = gameMap;
|
||||
|
||||
private boolean lastGrabbingState = true;
|
||||
private final boolean hasDigitalTriggers;
|
||||
|
||||
private final Handler handler = new Handler(Looper.getMainLooper());
|
||||
private final Runnable switchStateRunnable;
|
||||
|
||||
public Gamepad(BaseMainActivity gameActivity, InputDevice inputDevice){
|
||||
//Toast.makeText(gameActivity.getApplicationContext(),"GAMEPAD CREATED", Toast.LENGTH_LONG).show();
|
||||
|
||||
leftJoystick = new GamepadJoystick(MotionEvent.AXIS_X, MotionEvent.AXIS_Y, inputDevice);
|
||||
rightJoystick = new GamepadJoystick(MotionEvent.AXIS_Z, MotionEvent.AXIS_RZ, inputDevice);
|
||||
hasDigitalTriggers = inputDevice.hasKeys(KeyEvent.KEYCODE_BUTTON_R2)[0];
|
||||
|
||||
this.gameActivity = gameActivity;
|
||||
pointerView = this.gameActivity.findViewById(R.id.console_pointer);
|
||||
pointerView.getDrawable().setFilterBitmap(false);
|
||||
notifyGUISizeChange(gameActivity.getMcScale());
|
||||
|
||||
Runnable handlerRunnable = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
updateGrabbingState();
|
||||
tick();
|
||||
|
||||
handler.postDelayed(this, 16);
|
||||
}
|
||||
};
|
||||
|
||||
handler.postDelayed(handlerRunnable, 16);
|
||||
|
||||
//Initialize runnables to be used by the input system, avoiding generating one each time is better memory.
|
||||
switchStateRunnable = () -> {
|
||||
currentMap.resetPressedState();
|
||||
if(lastGrabbingState){
|
||||
currentMap = gameMap;
|
||||
pointerView.setVisibility(View.INVISIBLE);
|
||||
mouseSensitivity = 22 / gameActivity.sensitivityFactor; //sensitivity in menus is resolution dependent.
|
||||
return;
|
||||
}
|
||||
|
||||
currentMap = menuMap;
|
||||
sendDirectionalKeycode(currentJoystickDirection, false, gameMap); // removing what we were doing
|
||||
|
||||
gameActivity.mouse_x = CallbackBridge.windowWidth/2;
|
||||
gameActivity.mouse_y = CallbackBridge.windowHeight/2;
|
||||
CallbackBridge.sendCursorPos(gameActivity.mouse_x, gameActivity.mouse_y);
|
||||
placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2);
|
||||
pointerView.setVisibility(View.VISIBLE);
|
||||
mouseSensitivity = 14; //sensitivity in game doesn't need to be resolution dependent
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void tick(){
|
||||
//update mouse position
|
||||
if(lastHorizontalValue != 0 || lastVerticalValue != 0){
|
||||
GamepadJoystick currentJoystick = lastGrabbingState ? leftJoystick : rightJoystick;
|
||||
|
||||
acceleration = (mouseMagnitude - currentJoystick.getDeadzone())/(1 - currentJoystick.getDeadzone());
|
||||
acceleration = Math.pow(acceleration, mouseMaxAcceleration);
|
||||
if(acceleration > 1) acceleration = 1;
|
||||
|
||||
CallbackBridge.mouseX += Math.cos(mouseAngle) * acceleration * mouseSensitivity;
|
||||
CallbackBridge.mouseY -= Math.sin(mouseAngle) * acceleration * mouseSensitivity;
|
||||
|
||||
if(!lastGrabbingState){
|
||||
CallbackBridge.mouseX = MathUtils.clamp(CallbackBridge.mouseX, 0, CallbackBridge.windowWidth);
|
||||
CallbackBridge.mouseY = MathUtils.clamp(CallbackBridge.mouseY, 0, CallbackBridge.windowHeight);
|
||||
placePointerView((int) (CallbackBridge.mouseX /gameActivity.scaleFactor), (int) (CallbackBridge.mouseY/gameActivity.scaleFactor));
|
||||
}
|
||||
|
||||
gameActivity.mouse_x = CallbackBridge.mouseX;
|
||||
gameActivity.mouse_y = CallbackBridge.mouseY;
|
||||
|
||||
//Send the mouse to the game
|
||||
CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void updateGrabbingState() {
|
||||
boolean lastGrabbingValue = lastGrabbingState;
|
||||
lastGrabbingState = CallbackBridge.isGrabbing();
|
||||
if(lastGrabbingValue != lastGrabbingState){
|
||||
gameActivity.runOnUiThread(switchStateRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(KeyEvent event){
|
||||
sendButton(event);
|
||||
}
|
||||
|
||||
public void update(MotionEvent event){
|
||||
updateDirectionalJoystick(event);
|
||||
updateMouseJoystick(event);
|
||||
updateAnalogTriggers(event);
|
||||
sendButton(gamepadDpad.convertEvent(event));
|
||||
}
|
||||
|
||||
private void updateMouseJoystick(MotionEvent event){
|
||||
GamepadJoystick currentJoystick = lastGrabbingState ? rightJoystick : leftJoystick;
|
||||
lastHorizontalValue = currentJoystick.getHorizontalAxis(event);
|
||||
lastVerticalValue = currentJoystick.getVerticalAxis(event);
|
||||
|
||||
mouseMagnitude = currentJoystick.getMagnitude(event);
|
||||
mouseAngle = currentJoystick.getAngleRadian(event);
|
||||
}
|
||||
|
||||
private void updateDirectionalJoystick(MotionEvent event){
|
||||
GamepadJoystick currentJoystick = lastGrabbingState ? leftJoystick : rightJoystick;
|
||||
|
||||
int lastJoystickDirection = currentJoystickDirection;
|
||||
currentJoystickDirection = currentJoystick.getHeightDirection(event);
|
||||
|
||||
if(currentJoystickDirection != lastJoystickDirection){
|
||||
sendDirectionalKeycode(lastJoystickDirection, false, getCurrentMap());
|
||||
sendDirectionalKeycode(currentJoystickDirection, true, getCurrentMap());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAnalogTriggers(MotionEvent event){
|
||||
if(!hasDigitalTriggers){
|
||||
getCurrentMap().TRIGGER_LEFT.update((event.getAxisValue(MotionEvent.AXIS_LTRIGGER) > 0.5) || (event.getAxisValue(MotionEvent.AXIS_BRAKE) > 0.5));
|
||||
getCurrentMap().TRIGGER_RIGHT.update((event.getAxisValue(MotionEvent.AXIS_RTRIGGER) > 0.5) || (event.getAxisValue(MotionEvent.AXIS_GAS) > 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyGUISizeChange(int newSize){
|
||||
//Change the pointer size to match UI
|
||||
int size = (int) ((22 * newSize) / gameActivity.scaleFactor);
|
||||
gameActivity.runOnUiThread(() -> pointerView.setLayoutParams(new FrameLayout.LayoutParams(size, size)));
|
||||
}
|
||||
|
||||
private GamepadMap getCurrentMap(){
|
||||
return currentMap;
|
||||
}
|
||||
|
||||
private static void sendDirectionalKeycode(int direction, boolean isDown, GamepadMap map){
|
||||
switch (direction){
|
||||
case DIRECTION_NORTH:
|
||||
sendInput(map.DIRECTION_FORWARD, isDown);
|
||||
break;
|
||||
case DIRECTION_NORTH_EAST:
|
||||
sendInput(map.DIRECTION_FORWARD, isDown);
|
||||
sendInput(map.DIRECTION_RIGHT, isDown);
|
||||
break;
|
||||
case DIRECTION_EAST:
|
||||
sendInput(map.DIRECTION_RIGHT, isDown);
|
||||
break;
|
||||
case DIRECTION_SOUTH_EAST:
|
||||
sendInput(map.DIRECTION_RIGHT, isDown);
|
||||
sendInput(map.DIRECTION_BACKWARD, isDown);
|
||||
break;
|
||||
case DIRECTION_SOUTH:
|
||||
sendInput(map.DIRECTION_BACKWARD, isDown);
|
||||
break;
|
||||
case DIRECTION_SOUTH_WEST:
|
||||
sendInput(map.DIRECTION_BACKWARD, isDown);
|
||||
sendInput(map.DIRECTION_LEFT, isDown);
|
||||
break;
|
||||
case DIRECTION_WEST:
|
||||
sendInput(map.DIRECTION_LEFT, isDown);
|
||||
break;
|
||||
case DIRECTION_NORTH_WEST:
|
||||
sendInput(map.DIRECTION_FORWARD, isDown);
|
||||
sendInput(map.DIRECTION_LEFT, isDown);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void placePointerView(int x, int y){
|
||||
pointerView.setX(x - pointerView.getWidth()/2);
|
||||
pointerView.setY(y - pointerView.getHeight()/2);
|
||||
}
|
||||
|
||||
|
||||
public void sendButton(KeyEvent event){
|
||||
int keycode = event.getKeyCode();
|
||||
switch (keycode){
|
||||
case KeyEvent.KEYCODE_BUTTON_A:
|
||||
getCurrentMap().BUTTON_A.update(event);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_B:
|
||||
getCurrentMap().BUTTON_B.update(event);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_X:
|
||||
getCurrentMap().BUTTON_X.update(event);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_Y:
|
||||
getCurrentMap().BUTTON_Y.update(event);
|
||||
break;
|
||||
|
||||
//Shoulders
|
||||
case KeyEvent.KEYCODE_BUTTON_L1:
|
||||
getCurrentMap().SHOULDER_LEFT.update(event);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R1:
|
||||
getCurrentMap().SHOULDER_RIGHT.update(event);
|
||||
break;
|
||||
|
||||
//Triggers
|
||||
case KeyEvent.KEYCODE_BUTTON_L2:
|
||||
getCurrentMap().TRIGGER_LEFT.update(event);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R2:
|
||||
getCurrentMap().TRIGGER_RIGHT.update(event);
|
||||
break;
|
||||
|
||||
//L3 || R3
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBL:
|
||||
getCurrentMap().THUMBSTICK_LEFT.update(event);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBR:
|
||||
getCurrentMap().THUMBSTICK_RIGHT.update(event);
|
||||
break;
|
||||
|
||||
//DPAD
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
getCurrentMap().DPAD_UP.update(event);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
getCurrentMap().DPAD_DOWN.update(event);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
getCurrentMap().DPAD_LEFT.update(event);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
getCurrentMap().DPAD_RIGHT.update(event);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_CENTER:
|
||||
getCurrentMap().DPAD_RIGHT.update(false);
|
||||
getCurrentMap().DPAD_LEFT.update(false);
|
||||
getCurrentMap().DPAD_UP.update(false);
|
||||
getCurrentMap().DPAD_DOWN.update(false);
|
||||
break;
|
||||
|
||||
//Start/select
|
||||
case KeyEvent.KEYCODE_BUTTON_START:
|
||||
getCurrentMap().BUTTON_START.update(event);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_SELECT:
|
||||
getCurrentMap().BUTTON_SELECT.update(event);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
MainActivity.sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_SPACE, CallbackBridge.getCurrentMods(), event.getAction() == KeyEvent.ACTION_DOWN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendInput(int[] keycodes, boolean isDown){
|
||||
for(int keycode : keycodes){
|
||||
switch (keycode){
|
||||
case GamepadMap.MOUSE_SCROLL_DOWN:
|
||||
if(isDown) CallbackBridge.sendScroll(0, -1);
|
||||
break;
|
||||
case GamepadMap.MOUSE_SCROLL_UP:
|
||||
if(isDown) CallbackBridge.sendScroll(0, 1);
|
||||
break;
|
||||
|
||||
case LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT:
|
||||
MainActivity.sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT, isDown);
|
||||
break;
|
||||
case LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT:
|
||||
MainActivity.sendMouseButton(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, isDown);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
MainActivity.sendKeyPress(keycode, CallbackBridge.getCurrentMods(), isDown);
|
||||
break;
|
||||
}
|
||||
CallbackBridge.setModifiers(keycode, isDown);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static boolean isGamepadEvent(MotionEvent event){
|
||||
return isJoystickEvent(event);
|
||||
}
|
||||
|
||||
public static boolean isGamepadEvent(KeyEvent event){
|
||||
return ((event.getSource() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD
|
||||
|| GamepadDpad.isDpadEvent(event) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.gamepad;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
public class GamepadButton {
|
||||
|
||||
/*
|
||||
Just a simple button, that auto deal with the great habit from android to just SPAAAMS input events
|
||||
*/
|
||||
public int[] keycodes;
|
||||
public boolean isToggleable = false;
|
||||
private boolean isDown = false;
|
||||
private boolean isToggled = false;
|
||||
|
||||
public void update(KeyEvent event){
|
||||
boolean isKeyDown = (event.getAction() == KeyEvent.ACTION_DOWN);
|
||||
update(isKeyDown);
|
||||
}
|
||||
|
||||
public void update(boolean isKeyDown){
|
||||
if(isKeyDown != isDown){
|
||||
isDown = isKeyDown;
|
||||
if(isToggleable){
|
||||
if(isKeyDown){
|
||||
isToggled = !isToggled;
|
||||
Gamepad.sendInput(keycodes, isToggled);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Gamepad.sendInput(keycodes, isDown);
|
||||
}
|
||||
}
|
||||
|
||||
public void resetButtonState(){
|
||||
if(isDown || isToggled){
|
||||
Gamepad.sendInput(keycodes, false);
|
||||
}
|
||||
isDown = false;
|
||||
isToggled = false;
|
||||
}
|
||||
|
||||
public boolean isDown(){
|
||||
return isToggleable ? isToggled : isDown;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.gamepad;
|
||||
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import net.kdt.pojavlaunch.LWJGLGLFWKeycode;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static android.view.InputDevice.KEYBOARD_TYPE_NON_ALPHABETIC;
|
||||
import static android.view.InputDevice.SOURCE_DPAD;
|
||||
import static android.view.KeyEvent.KEYCODE_DPAD_CENTER;
|
||||
import static android.view.KeyEvent.KEYCODE_DPAD_DOWN;
|
||||
import static android.view.KeyEvent.KEYCODE_DPAD_LEFT;
|
||||
import static android.view.KeyEvent.KEYCODE_DPAD_RIGHT;
|
||||
import static android.view.KeyEvent.KEYCODE_DPAD_UP;
|
||||
|
||||
/*
|
||||
Reflection is used to avoid memory churning, and only has an negative impact at start
|
||||
*/
|
||||
|
||||
public class GamepadDpad {
|
||||
|
||||
|
||||
private int lastKeycode = KEYCODE_DPAD_CENTER;
|
||||
private KeyEvent dummyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, lastKeycode);
|
||||
private Field eventCodeField;
|
||||
private Field eventActionField;
|
||||
|
||||
{
|
||||
try {
|
||||
eventCodeField = dummyEvent.getClass().getDeclaredField("mKeyCode");
|
||||
eventCodeField.setAccessible(true);
|
||||
|
||||
eventActionField = dummyEvent.getClass().getDeclaredField("mAction");
|
||||
eventActionField.setAccessible(true);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public KeyEvent convertEvent(MotionEvent event){
|
||||
// Use the hat axis value to find the D-pad direction
|
||||
float xaxis = event.getAxisValue(MotionEvent.AXIS_HAT_X);
|
||||
float yaxis = event.getAxisValue(MotionEvent.AXIS_HAT_Y);
|
||||
int action = KeyEvent.ACTION_DOWN;
|
||||
|
||||
// Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad
|
||||
// LEFT and RIGHT direction accordingly.
|
||||
if (Float.compare(xaxis, -1.0f) == 0) {
|
||||
lastKeycode = KEYCODE_DPAD_LEFT;
|
||||
} else if (Float.compare(xaxis, 1.0f) == 0) {
|
||||
lastKeycode = KEYCODE_DPAD_RIGHT;
|
||||
}
|
||||
// Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad
|
||||
// UP and DOWN direction accordingly.
|
||||
else if (Float.compare(yaxis, -1.0f) == 0) {
|
||||
lastKeycode = KEYCODE_DPAD_UP;
|
||||
} else if (Float.compare(yaxis, 1.0f) == 0) {
|
||||
lastKeycode = KEYCODE_DPAD_DOWN;
|
||||
}else {
|
||||
//No keycode change
|
||||
action = KeyEvent.ACTION_UP;
|
||||
}
|
||||
|
||||
setDummyEventKeycode(lastKeycode);
|
||||
setDummyEventAction(action);
|
||||
dummyEvent.setSource(SOURCE_DPAD);
|
||||
return dummyEvent;
|
||||
|
||||
}
|
||||
|
||||
private void setDummyEventKeycode(int fakeKeycode){
|
||||
try {
|
||||
eventCodeField.setInt(dummyEvent, fakeKeycode);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void setDummyEventAction(int action){
|
||||
try {
|
||||
eventActionField.setInt(dummyEvent, action);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isDpadEvent(MotionEvent event) {
|
||||
// Check that input comes from a device with directional pads.
|
||||
// And... also the joystick since it declares sometimes as a joystick.
|
||||
return (event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK;
|
||||
}
|
||||
|
||||
public static boolean isDpadEvent(KeyEvent event){
|
||||
return ((event.getSource() & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) && (event.getDevice().getKeyboardType() == KEYBOARD_TYPE_NON_ALPHABETIC);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.gamepad;
|
||||
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
|
||||
import com.google.android.material.math.MathUtils;
|
||||
|
||||
public class GamepadJoystick {
|
||||
|
||||
//Directions
|
||||
public static final int DIRECTION_NONE = -1; //GamepadJoystick at the center
|
||||
|
||||
public static final int DIRECTION_EAST = 0;
|
||||
public static final int DIRECTION_NORTH_EAST = 1;
|
||||
public static final int DIRECTION_NORTH = 2;
|
||||
public static final int DIRECTION_NORTH_WEST = 3;
|
||||
public static final int DIRECTION_WEST = 4;
|
||||
public static final int DIRECTION_SOUTH_WEST = 5;
|
||||
public static final int DIRECTION_SOUTH = 6;
|
||||
public static final int DIRECTION_SOUTH_EAST = 7;
|
||||
|
||||
private float deadzone;
|
||||
|
||||
private final int verticalAxis;
|
||||
private final int horizontalAxis;
|
||||
|
||||
public GamepadJoystick(int horizontalAxis, int verticalAxis, InputDevice device){
|
||||
this.verticalAxis = verticalAxis;
|
||||
this.horizontalAxis = horizontalAxis;
|
||||
|
||||
//Some controllers aren't recognized as such by android, so we fallback to a default value of 0.2
|
||||
//And some others don't report their MotionRange. This was the case with the xbox one series S controller.
|
||||
|
||||
try { deadzone = Math.max(device.getMotionRange(verticalAxis).getFlat(), device.getMotionRange(horizontalAxis).getFlat()) * 1.9f; }
|
||||
catch (NullPointerException e){ deadzone = 0.2f; }
|
||||
|
||||
if(deadzone < 0.2) deadzone = 0.2f;
|
||||
}
|
||||
|
||||
public double getAngleRadian(MotionEvent event){
|
||||
//From -PI to PI
|
||||
return -Math.atan2(getVerticalAxis(event), getHorizontalAxis(event));
|
||||
}
|
||||
|
||||
|
||||
public double getAngleDegree(MotionEvent event){
|
||||
//From 0 to 360 degrees
|
||||
double result = Math.toDegrees(getAngleRadian(event));
|
||||
if(result < 0) result += 360;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public double getMagnitude(MotionEvent event){
|
||||
float x = Math.abs(event.getAxisValue(horizontalAxis));
|
||||
float y = Math.abs(event.getAxisValue(verticalAxis));
|
||||
|
||||
return MathUtils.dist(0,0, x, y);
|
||||
}
|
||||
|
||||
public float getVerticalAxis(MotionEvent event){
|
||||
return applyDeadzone(event, verticalAxis);
|
||||
}
|
||||
|
||||
public float getHorizontalAxis(MotionEvent event){
|
||||
return applyDeadzone(event, horizontalAxis);
|
||||
}
|
||||
|
||||
private float applyDeadzone(MotionEvent event, int axis){
|
||||
//This piece of code also modifies the value
|
||||
//to make it seem like there was no deadzone in the first place
|
||||
|
||||
double magnitude = getMagnitude(event);
|
||||
if (magnitude < deadzone) return 0;
|
||||
|
||||
return (float) ( (event.getAxisValue(axis) / magnitude) * ((magnitude - deadzone) / (1 - deadzone)) );
|
||||
}
|
||||
|
||||
public static boolean isJoystickEvent(MotionEvent event){
|
||||
return (event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK
|
||||
&& event.getAction() == MotionEvent.ACTION_MOVE;
|
||||
}
|
||||
|
||||
|
||||
public int getHeightDirection(MotionEvent event){
|
||||
if(getMagnitude(event) <= deadzone) return DIRECTION_NONE;
|
||||
return ((int) ((getAngleDegree(event)+22.5)/45)) % 8;
|
||||
}
|
||||
|
||||
|
||||
public float getDeadzone() {
|
||||
return deadzone;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.gamepad;
|
||||
|
||||
import net.kdt.pojavlaunch.LWJGLGLFWKeycode;
|
||||
|
||||
public class GamepadMap {
|
||||
|
||||
public static final int MOUSE_SCROLL_DOWN = -1;
|
||||
public static final int MOUSE_SCROLL_UP = -2;
|
||||
|
||||
/*
|
||||
This class is just here to store the mapping
|
||||
can be modified to create re-mappable controls I guess
|
||||
|
||||
Be warned, you should define ALL keys if you want to avoid a non defined exception
|
||||
*/
|
||||
|
||||
public GamepadButton BUTTON_A = new GamepadButton();
|
||||
public GamepadButton BUTTON_B = new GamepadButton();
|
||||
public GamepadButton BUTTON_X = new GamepadButton();
|
||||
public GamepadButton BUTTON_Y = new GamepadButton();
|
||||
|
||||
public GamepadButton BUTTON_START = new GamepadButton();
|
||||
public GamepadButton BUTTON_SELECT = new GamepadButton();
|
||||
|
||||
public GamepadButton TRIGGER_RIGHT = new GamepadButton(); //R2
|
||||
public GamepadButton TRIGGER_LEFT = new GamepadButton(); //L2
|
||||
|
||||
public GamepadButton SHOULDER_RIGHT = new GamepadButton(); //R1
|
||||
public GamepadButton SHOULDER_LEFT = new GamepadButton(); //L1
|
||||
|
||||
public int[] DIRECTION_FORWARD;
|
||||
public int[] DIRECTION_BACKWARD;
|
||||
public int[] DIRECTION_RIGHT;
|
||||
public int[] DIRECTION_LEFT;
|
||||
|
||||
public GamepadButton THUMBSTICK_RIGHT = new GamepadButton(); //R3
|
||||
public GamepadButton THUMBSTICK_LEFT = new GamepadButton(); //L3
|
||||
|
||||
public GamepadButton DPAD_UP = new GamepadButton();
|
||||
public GamepadButton DPAD_RIGHT = new GamepadButton();
|
||||
public GamepadButton DPAD_DOWN = new GamepadButton();
|
||||
public GamepadButton DPAD_LEFT = new GamepadButton();
|
||||
|
||||
|
||||
/*
|
||||
* Sets all buttons to a not pressed state, sending an input if needed
|
||||
*/
|
||||
public void resetPressedState(){
|
||||
BUTTON_A.resetButtonState();
|
||||
BUTTON_B.resetButtonState();
|
||||
BUTTON_X.resetButtonState();
|
||||
BUTTON_Y.resetButtonState();
|
||||
|
||||
BUTTON_START.resetButtonState();
|
||||
BUTTON_SELECT.resetButtonState();
|
||||
|
||||
TRIGGER_LEFT.resetButtonState();
|
||||
TRIGGER_RIGHT.resetButtonState();
|
||||
|
||||
SHOULDER_LEFT.resetButtonState();
|
||||
SHOULDER_RIGHT.resetButtonState();
|
||||
|
||||
THUMBSTICK_LEFT.resetButtonState();
|
||||
THUMBSTICK_RIGHT.resetButtonState();
|
||||
|
||||
DPAD_UP.resetButtonState();
|
||||
DPAD_RIGHT.resetButtonState();
|
||||
DPAD_DOWN.resetButtonState();
|
||||
DPAD_LEFT.resetButtonState();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a pre-done mapping used when the mouse is grabbed by the game.
|
||||
*/
|
||||
public static GamepadMap getDefaultGameMap(){
|
||||
GamepadMap gameMap = new GamepadMap();
|
||||
|
||||
gameMap.BUTTON_A.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_SPACE};
|
||||
gameMap.BUTTON_B.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_Q};
|
||||
gameMap.BUTTON_X.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_E};
|
||||
gameMap.BUTTON_Y.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_F};
|
||||
|
||||
gameMap.DIRECTION_FORWARD = new int[]{LWJGLGLFWKeycode.GLFW_KEY_W};
|
||||
gameMap.DIRECTION_BACKWARD = new int[]{LWJGLGLFWKeycode.GLFW_KEY_S};
|
||||
gameMap.DIRECTION_RIGHT = new int[]{LWJGLGLFWKeycode.GLFW_KEY_D};
|
||||
gameMap.DIRECTION_LEFT = new int[]{LWJGLGLFWKeycode.GLFW_KEY_A};
|
||||
|
||||
gameMap.DPAD_UP.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT};
|
||||
gameMap.DPAD_DOWN.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_O}; //For mods ?
|
||||
gameMap.DPAD_RIGHT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_K}; //For mods ?
|
||||
gameMap.DPAD_LEFT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_J}; //For mods ?
|
||||
|
||||
gameMap.SHOULDER_LEFT.keycodes = new int[]{GamepadMap.MOUSE_SCROLL_UP};
|
||||
gameMap.SHOULDER_RIGHT.keycodes = new int[]{GamepadMap.MOUSE_SCROLL_DOWN};
|
||||
|
||||
gameMap.TRIGGER_LEFT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT};
|
||||
gameMap.TRIGGER_RIGHT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT};
|
||||
|
||||
gameMap.THUMBSTICK_LEFT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_LEFT_CONTROL};
|
||||
gameMap.THUMBSTICK_RIGHT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT};
|
||||
gameMap.THUMBSTICK_RIGHT.isToggleable = true;
|
||||
|
||||
gameMap.BUTTON_START.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_ESCAPE};
|
||||
gameMap.BUTTON_SELECT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_TAB};
|
||||
|
||||
return gameMap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a pre-done mapping used when the mouse is NOT grabbed by the game.
|
||||
*/
|
||||
public static GamepadMap getDefaultMenuMap(){
|
||||
GamepadMap menuMap = new GamepadMap();
|
||||
|
||||
menuMap.BUTTON_A.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT};
|
||||
menuMap.BUTTON_B.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_ESCAPE};
|
||||
menuMap.BUTTON_X.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT};
|
||||
menuMap.BUTTON_Y.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT, LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT}; //Oops, doesn't work since left shift isn't properly applied.
|
||||
|
||||
menuMap.DIRECTION_FORWARD = new int[]{GamepadMap.MOUSE_SCROLL_UP, GamepadMap.MOUSE_SCROLL_UP, GamepadMap.MOUSE_SCROLL_UP, GamepadMap.MOUSE_SCROLL_UP, GamepadMap.MOUSE_SCROLL_UP};
|
||||
menuMap.DIRECTION_BACKWARD = new int[]{GamepadMap.MOUSE_SCROLL_DOWN, GamepadMap.MOUSE_SCROLL_DOWN, GamepadMap.MOUSE_SCROLL_DOWN, GamepadMap.MOUSE_SCROLL_DOWN, GamepadMap.MOUSE_SCROLL_DOWN};
|
||||
menuMap.DIRECTION_RIGHT = new int[]{};
|
||||
menuMap.DIRECTION_LEFT = new int[]{};
|
||||
|
||||
menuMap.DPAD_UP.keycodes = new int[]{};
|
||||
menuMap.DPAD_DOWN.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_O}; //For mods ?
|
||||
menuMap.DPAD_RIGHT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_K}; //For mods ?
|
||||
menuMap.DPAD_LEFT.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_J}; //For mods ?
|
||||
|
||||
menuMap.SHOULDER_LEFT.keycodes = new int[]{GamepadMap.MOUSE_SCROLL_UP};
|
||||
menuMap.SHOULDER_RIGHT.keycodes = new int[]{GamepadMap.MOUSE_SCROLL_DOWN};
|
||||
|
||||
menuMap.TRIGGER_LEFT.keycodes = new int[]{};
|
||||
menuMap.TRIGGER_RIGHT.keycodes = new int[]{};
|
||||
|
||||
menuMap.THUMBSTICK_LEFT.keycodes = new int[]{};
|
||||
menuMap.THUMBSTICK_RIGHT.keycodes = new int[]{};
|
||||
|
||||
menuMap.BUTTON_START.keycodes = new int[]{LWJGLGLFWKeycode.GLFW_KEY_ESCAPE};
|
||||
menuMap.BUTTON_SELECT.keycodes = new int[]{};
|
||||
|
||||
return menuMap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns all GamepadButtons, does not include directional keys
|
||||
*/
|
||||
public GamepadButton[] getButtons(){
|
||||
return new GamepadButton[]{ BUTTON_A, BUTTON_B, BUTTON_X, BUTTON_Y,
|
||||
BUTTON_SELECT, BUTTON_START,
|
||||
TRIGGER_LEFT, TRIGGER_RIGHT,
|
||||
SHOULDER_LEFT, SHOULDER_RIGHT,
|
||||
THUMBSTICK_LEFT, THUMBSTICK_RIGHT,
|
||||
DPAD_UP, DPAD_RIGHT, DPAD_DOWN, DPAD_LEFT};
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an pre-initialized GamepadMap with only empty keycodes
|
||||
*/
|
||||
public static GamepadMap getEmptyMap(){
|
||||
GamepadMap emptyMap = new GamepadMap();
|
||||
for(GamepadButton button : emptyMap.getButtons())
|
||||
button.keycodes = new int[]{};
|
||||
|
||||
emptyMap.DIRECTION_LEFT = new int[]{};
|
||||
emptyMap.DIRECTION_FORWARD = new int[]{};
|
||||
emptyMap.DIRECTION_RIGHT = new int[]{};
|
||||
emptyMap.DIRECTION_BACKWARD = new int[]{};
|
||||
|
||||
return emptyMap;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.handleview;
|
||||
|
||||
import android.content.*;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.view.*;
|
||||
import android.view.ViewGroup.*;
|
||||
import android.widget.*;
|
||||
@@ -28,14 +29,24 @@ import net.kdt.pojavlaunch.*;
|
||||
|
||||
import android.view.View.OnClickListener;
|
||||
import net.kdt.pojavlaunch.customcontrols.*;
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton;
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlDrawer;
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlSubButton;
|
||||
|
||||
import androidx.appcompat.app.*;
|
||||
|
||||
import com.rarepebble.colorpicker.ColorPickerView;
|
||||
|
||||
public class ActionPopupWindow extends PinnedPopupWindow implements OnClickListener {
|
||||
|
||||
private TextView mEditTextView;
|
||||
private TextView mDeleteTextView;
|
||||
|
||||
public ActionPopupWindow(HandleView handleView) {
|
||||
|
||||
private Object editedButton;
|
||||
|
||||
public ActionPopupWindow(HandleView handleView, Object object){
|
||||
super(handleView);
|
||||
this.editedButton = object;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,178 +88,50 @@ public class ActionPopupWindow extends PinnedPopupWindow implements OnClickListe
|
||||
|
||||
@Override
|
||||
public void onClick(final View view) {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(view.getContext());
|
||||
alert.setCancelable(false);
|
||||
if (view == mEditTextView) {
|
||||
alert.setTitle(view.getResources().getString(R.string.customctrl_edit, mHandleView.mView.getText()));
|
||||
alert.setView(R.layout.control_setting);
|
||||
alert.setPositiveButton(android.R.string.ok, null);
|
||||
alert.setNegativeButton(android.R.string.cancel, null);
|
||||
final AlertDialog dialog = alert.create();
|
||||
final ControlData properties = mHandleView.mView.getProperties();
|
||||
|
||||
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
||||
if(editedButton instanceof ControlSubButton){
|
||||
new EditControlSubButtonPopup((ControlSubButton) editedButton);
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShow(DialogInterface dialogInterface) {
|
||||
final EditText editName = dialog.findViewById(R.id.controlsetting_edit_name);
|
||||
editName.setText(properties.name);
|
||||
if(editedButton instanceof ControlDrawer){
|
||||
new EditControlDrawerPopup((ControlDrawer) editedButton);
|
||||
return;
|
||||
}
|
||||
|
||||
final Spinner spinnerKeycode = dialog.findViewById(R.id.controlsetting_spinner_lwjglkeycode);
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<String>(view.getContext(), android.R.layout.simple_spinner_item);
|
||||
if(editedButton instanceof ControlButton){
|
||||
new EditControlButtonPopup((ControlButton) editedButton);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] oldSpecialArr = ControlData.buildSpecialButtonArray();
|
||||
final String[] specialArr = new String[oldSpecialArr.length];
|
||||
for (int i = 0; i < specialArr.length; i++) {
|
||||
specialArr[i] = "SPECIAL_" + oldSpecialArr[specialArr.length - i - 1];
|
||||
}
|
||||
|
||||
adapter.addAll(specialArr);
|
||||
adapter.addAll(AndroidLWJGLKeycode.generateKeyName());
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice);
|
||||
spinnerKeycode.setAdapter(adapter);
|
||||
if (properties.keycode < 0) {
|
||||
spinnerKeycode.setSelection(properties.keycode + specialArr.length);
|
||||
} else {
|
||||
spinnerKeycode.setSelection(AndroidLWJGLKeycode.getIndexByLWJGLKey(properties.keycode) + specialArr.length);
|
||||
}
|
||||
|
||||
final CheckBox checkToggle = dialog.findViewById(R.id.controlsetting_checkbox_toggle);
|
||||
checkToggle.setChecked(properties.isToggle);
|
||||
final CheckBox checkPassthru = dialog.findViewById(R.id.controlsetting_checkbox_passthru);
|
||||
checkPassthru.setChecked(properties.passThruEnabled);
|
||||
final CheckBox checkRound = dialog.findViewById(R.id.controlsetting_checkbox_round);
|
||||
checkRound.setChecked(properties.isRound);
|
||||
final EditText editWidth = dialog.findViewById(R.id.controlsetting_edit_width);
|
||||
final EditText editHeight = dialog.findViewById(R.id.controlsetting_edit_height);
|
||||
editWidth.setText(Float.toString(properties.width));
|
||||
editHeight.setText(Float.toString(properties.height));
|
||||
|
||||
final EditText editDynamicX = dialog.findViewById(R.id.controlsetting_edit_dynamicpos_x);
|
||||
final EditText editDynamicY = dialog.findViewById(R.id.controlsetting_edit_dynamicpos_y);
|
||||
editDynamicX.setEnabled(properties.isDynamicBtn);
|
||||
editDynamicY.setEnabled(properties.isDynamicBtn);
|
||||
|
||||
final SeekBar seekTransparency = dialog.findViewById(R.id.controlsetting_seek_transparency);
|
||||
seekTransparency.setMax(100);
|
||||
seekTransparency.setProgress(properties.hidden ? 100 : properties.transparency);
|
||||
|
||||
final CheckBox checkDynamicPos = dialog.findViewById(R.id.controlsetting_checkbox_dynamicpos);
|
||||
checkDynamicPos.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener(){
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton btn, boolean checked) {
|
||||
editDynamicX.setEnabled(checked);
|
||||
editDynamicY.setEnabled(checked);
|
||||
}
|
||||
});
|
||||
checkDynamicPos.setChecked(properties.isDynamicBtn);
|
||||
|
||||
editDynamicX.setHint(Float.toString(properties.x));
|
||||
editDynamicX.setText(properties.dynamicX);
|
||||
|
||||
editDynamicY.setHint(Float.toString(properties.y));
|
||||
editDynamicY.setText(properties.dynamicY);
|
||||
|
||||
final CheckBox checkHoldAlt = dialog.findViewById(R.id.controlsetting_checkbox_keycombine_alt);
|
||||
checkHoldAlt.setChecked(properties.holdAlt);
|
||||
|
||||
final CheckBox checkHoldControl = dialog.findViewById(R.id.controlsetting_checkbox_keycombine_control);
|
||||
checkHoldControl.setChecked(properties.holdCtrl);
|
||||
|
||||
final CheckBox checkHoldShift = dialog.findViewById(R.id.controlsetting_checkbox_keycombine_shift);
|
||||
checkHoldShift.setChecked(properties.holdShift);
|
||||
|
||||
Button button = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
button.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View view2) {
|
||||
if (editName.getText().toString().isEmpty()) {
|
||||
editName.setError(view.getResources().getString(R.string.global_error_field_empty));
|
||||
} else {
|
||||
/*
|
||||
String errorAt = null;
|
||||
try {
|
||||
errorAt = "DynamicX";
|
||||
properties.insertDynamicPos(editDynamicX.getText().toString());
|
||||
errorAt = "DynamicY";
|
||||
properties.insertDynamicPos(editDynamicY.getText().toString());
|
||||
} catch (Throwable th) {
|
||||
Error e = new Error(errorAt, th);
|
||||
e.setStackTrace(null);
|
||||
Tools.showError(view.getContext(), e);
|
||||
return;
|
||||
}
|
||||
errorAt = null;
|
||||
*/
|
||||
|
||||
if (properties.isDynamicBtn) {
|
||||
int errorAt = 0;
|
||||
try {
|
||||
properties.insertDynamicPos(editDynamicX.getText().toString());
|
||||
errorAt = 1;
|
||||
properties.insertDynamicPos(editDynamicY.getText().toString());
|
||||
} catch (Throwable th) {
|
||||
(errorAt == 0 ? editDynamicX : editDynamicY)
|
||||
.setError(th.getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (spinnerKeycode.getSelectedItemPosition() < specialArr.length) {
|
||||
properties.keycode = spinnerKeycode.getSelectedItemPosition() - specialArr.length;
|
||||
} else {
|
||||
properties.keycode = AndroidLWJGLKeycode.getKeyByIndex(spinnerKeycode.getSelectedItemPosition() - specialArr.length);
|
||||
}
|
||||
properties.name = editName.getText().toString();
|
||||
|
||||
properties.transparency = seekTransparency.getProgress();
|
||||
|
||||
properties.hidden = false;
|
||||
properties.isToggle = checkToggle.isChecked();
|
||||
properties.passThruEnabled = checkPassthru.isChecked();
|
||||
properties.isRound = checkRound.isChecked();
|
||||
properties.isDynamicBtn = checkDynamicPos.isChecked();
|
||||
properties.width = Float.parseFloat(editWidth.getText().toString());
|
||||
properties.height = Float.parseFloat(editHeight.getText().toString());
|
||||
properties.dynamicX = editDynamicX.getText().toString();
|
||||
properties.dynamicY = editDynamicY.getText().toString();
|
||||
|
||||
properties.holdAlt = checkHoldAlt.isChecked();
|
||||
properties.holdCtrl = checkHoldControl.isChecked();
|
||||
properties.holdShift = checkHoldShift.isChecked();
|
||||
|
||||
if (properties.dynamicX.isEmpty()) {
|
||||
properties.dynamicX = Float.toString(properties.x);
|
||||
} if (properties.dynamicY.isEmpty()) {
|
||||
properties.dynamicY = Float.toString(properties.y);
|
||||
}
|
||||
|
||||
mHandleView.mView.updateProperties();
|
||||
|
||||
dialog.dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
} else if (view == mDeleteTextView) {
|
||||
alert.setMessage(view.getContext().getString(R.string.customctrl_remove, mHandleView.mView.getText()) + "?");
|
||||
alert.setPositiveButton(R.string.global_remove, new DialogInterface.OnClickListener(){
|
||||
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(view.getContext());
|
||||
alertBuilder.setCancelable(false);
|
||||
alertBuilder.setMessage(view.getContext().getString(R.string.customctrl_remove, mHandleView.mView.getText()) + "?");
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface p1, int p2)
|
||||
{
|
||||
ControlLayout layout = ((ControlLayout) mHandleView.mView.getParent());
|
||||
layout.removeControlButton(mHandleView.mView);
|
||||
}
|
||||
});
|
||||
alert.setNegativeButton(android.R.string.cancel, null);
|
||||
alert.show();
|
||||
alertBuilder.setPositiveButton(R.string.global_remove, (p1, p2) -> {
|
||||
ControlLayout layout = ((ControlLayout) mHandleView.mView.getParent());
|
||||
|
||||
if(editedButton instanceof ControlSubButton){
|
||||
layout.removeControlSubButton((ControlSubButton) editedButton);
|
||||
return;
|
||||
}
|
||||
|
||||
if(editedButton instanceof ControlDrawer){
|
||||
layout.removeControlDrawer((ControlDrawer) editedButton);
|
||||
return;
|
||||
}
|
||||
|
||||
if(editedButton instanceof ControlButton){
|
||||
layout.removeControlButton((ControlButton) editedButton);
|
||||
}
|
||||
|
||||
layout.removeControlButton(mHandleView.mView);
|
||||
});
|
||||
alertBuilder.setNegativeButton(android.R.string.cancel, null);
|
||||
alertBuilder.show();
|
||||
}
|
||||
|
||||
hide();
|
||||
@@ -257,32 +140,37 @@ public class ActionPopupWindow extends PinnedPopupWindow implements OnClickListe
|
||||
@Override
|
||||
protected int getTextOffset() {
|
||||
return 0;
|
||||
// return (mTextView.getSelectionStart() + mTextView.getSelectionEnd()) / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getVerticalLocalPosition(int line) {
|
||||
// return mTextView.getLayout().getLineTop(line) - mContentView.getMeasuredHeight();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int clipVertically(int positionY) {
|
||||
/*
|
||||
if (positionY < 0) {
|
||||
final int offset = getTextOffset();
|
||||
final Layout layout = mTextView.getLayout();
|
||||
final int line = layout.getLineForOffset(offset);
|
||||
positionY += layout.getLineBottom(line) - layout.getLineTop(line);
|
||||
positionY += mContentView.getMeasuredHeight();
|
||||
|
||||
// Assumes insertion and selection handles share the same height
|
||||
final Drawable handle = mHandleView.getContext().getDrawable(
|
||||
mTextView.mTextSelectHandleRes);
|
||||
positionY += handle.getIntrinsicHeight();
|
||||
}
|
||||
*/
|
||||
|
||||
return positionY;
|
||||
}
|
||||
|
||||
|
||||
public static void showColorPicker(Context ctx,String title, boolean showAlpha, ImageView v){
|
||||
int startColor = ((ColorDrawable)v.getDrawable()).getColor();
|
||||
|
||||
ColorPickerView picker = new ColorPickerView(ctx);
|
||||
picker.setColor(startColor);
|
||||
picker.showAlpha(showAlpha);
|
||||
|
||||
AlertDialog.Builder dialog = new AlertDialog.Builder(ctx);
|
||||
dialog.setTitle(title);
|
||||
dialog.setView(picker);
|
||||
dialog.setNegativeButton(android.R.string.cancel, null);
|
||||
dialog.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> v.setImageDrawable(new ColorDrawable(picker.getColor())));
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void setPercentageText(TextView textView, int progress){
|
||||
textView.setText(progress + " %");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.handleview;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import net.kdt.pojavlaunch.EfficientAndroidLWJGLKeycode;
|
||||
import net.kdt.pojavlaunch.R;
|
||||
import net.kdt.pojavlaunch.Tools;
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton;
|
||||
import net.kdt.pojavlaunch.customcontrols.ControlData;
|
||||
|
||||
import top.defaults.checkerboarddrawable.CheckerboardDrawable;
|
||||
|
||||
import static net.kdt.pojavlaunch.customcontrols.handleview.ActionPopupWindow.setPercentageText;
|
||||
|
||||
public class EditControlButtonPopup {
|
||||
|
||||
protected Dialog dialog;
|
||||
protected View v;
|
||||
protected AlertDialog.Builder builder;
|
||||
|
||||
protected EditText editName;
|
||||
protected Spinner[] spinnersKeycode;
|
||||
|
||||
protected CheckBox checkToggle;
|
||||
protected CheckBox checkPassThrough;
|
||||
protected CheckBox checkBoxSwipeable;
|
||||
protected CheckBox checkDynamicPosition;
|
||||
|
||||
protected EditText editWidth;
|
||||
protected EditText editHeight;
|
||||
protected EditText editDynamicX;
|
||||
protected EditText editDynamicY;
|
||||
|
||||
protected SeekBar seekBarOpacity;
|
||||
protected SeekBar seekBarCornerRadius;
|
||||
protected SeekBar seekBarStrokeWidth;
|
||||
|
||||
protected ImageButton buttonBackgroundColor;
|
||||
protected ImageButton buttonStrokeColor;
|
||||
|
||||
protected TextView textOpacity;
|
||||
protected TextView textCornerRadius;
|
||||
protected TextView textStrokeWidth;
|
||||
|
||||
protected final ControlButton button;
|
||||
protected final ControlData properties;
|
||||
|
||||
protected ArrayAdapter<String> adapter;
|
||||
protected String[] specialArr;
|
||||
|
||||
|
||||
public EditControlButtonPopup(ControlButton button){
|
||||
this.button = button;
|
||||
this.properties = button.getProperties();
|
||||
|
||||
initializeEditDialog(button.getContext());
|
||||
|
||||
//Create the finalized dialog
|
||||
dialog = builder.create();
|
||||
dialog.setOnShowListener(dialogInterface -> setEditDialogValues());
|
||||
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
protected void initializeEditDialog(Context ctx){
|
||||
//Create the editing dialog
|
||||
LayoutInflater layoutInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
v = layoutInflater.inflate(R.layout.control_button_setting,null);
|
||||
|
||||
builder = new AlertDialog.Builder(ctx);
|
||||
builder.setTitle(ctx.getResources().getString(R.string.customctrl_edit, properties.name));
|
||||
builder.setView(v);
|
||||
|
||||
//Linking a lot of stuff
|
||||
editName = v.findViewById(R.id.editName_editText);
|
||||
|
||||
spinnersKeycode = new Spinner[]{
|
||||
v.findViewById(R.id.editMapping_spinner_1),
|
||||
v.findViewById(R.id.editMapping_spinner_2),
|
||||
v.findViewById(R.id.editMapping_spinner_3),
|
||||
v.findViewById(R.id.editMapping_spinner_4)
|
||||
};
|
||||
|
||||
checkToggle = v.findViewById(R.id.checkboxToggle);
|
||||
checkPassThrough = v.findViewById(R.id.checkboxPassThrough);
|
||||
checkBoxSwipeable = v.findViewById(R.id.checkboxSwipeable);
|
||||
|
||||
editWidth = v.findViewById(R.id.editSize_editTextX);
|
||||
editHeight = v.findViewById(R.id.editSize_editTextY);
|
||||
|
||||
editDynamicX = v.findViewById(R.id.editDynamicPositionX_editText);
|
||||
editDynamicY = v.findViewById(R.id.editDynamicPositionY_editText);
|
||||
|
||||
seekBarOpacity = v.findViewById(R.id.editButtonOpacity_seekbar);
|
||||
seekBarCornerRadius = v.findViewById(R.id.editCornerRadius_seekbar);
|
||||
seekBarStrokeWidth = v.findViewById(R.id.editStrokeWidth_seekbar);
|
||||
|
||||
SeekBar.OnSeekBarChangeListener changeListener = new SeekBar.OnSeekBarChangeListener() {
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
|
||||
if(seekBar.equals(seekBarCornerRadius)) {
|
||||
setPercentageText(textCornerRadius, i);
|
||||
return;
|
||||
}
|
||||
if(seekBar.equals(seekBarOpacity)) {
|
||||
setPercentageText(textOpacity, i);
|
||||
return;
|
||||
}
|
||||
if(seekBar.equals(seekBarStrokeWidth)) {
|
||||
setPercentageText(textStrokeWidth, i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {/*STUB*/}
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {/*STUB*/}
|
||||
};
|
||||
|
||||
//Add listeners, too bad I don't need all the methods
|
||||
seekBarOpacity.setOnSeekBarChangeListener(changeListener);
|
||||
seekBarCornerRadius.setOnSeekBarChangeListener(changeListener);
|
||||
seekBarStrokeWidth.setOnSeekBarChangeListener(changeListener);
|
||||
|
||||
buttonBackgroundColor = v.findViewById(R.id.editBackgroundColor_imageButton);
|
||||
buttonStrokeColor = v.findViewById(R.id.editStrokeColor_imageButton);
|
||||
|
||||
textOpacity = v.findViewById(R.id.editButtonOpacity_textView_percent);
|
||||
textCornerRadius = v.findViewById(R.id.editCornerRadius_textView_percent);
|
||||
textStrokeWidth = v.findViewById(R.id.editStrokeWidth_textView_percent);
|
||||
|
||||
checkDynamicPosition = v.findViewById(R.id.checkboxDynamicPosition);
|
||||
checkDynamicPosition.setOnCheckedChangeListener((btn, checked) -> {
|
||||
editDynamicX.setEnabled(checked);
|
||||
editDynamicY.setEnabled(checked);
|
||||
});
|
||||
|
||||
|
||||
//Initialize adapter for keycodes
|
||||
adapter = new ArrayAdapter<>(ctx, android.R.layout.simple_spinner_item);
|
||||
String[] oldSpecialArr = ControlData.buildSpecialButtonArray();
|
||||
specialArr = new String[oldSpecialArr.length];
|
||||
for (int i = 0; i < specialArr.length; i++) {
|
||||
specialArr[i] = "SPECIAL_" + oldSpecialArr[specialArr.length - i - 1];
|
||||
}
|
||||
adapter.addAll(specialArr);
|
||||
adapter.addAll(EfficientAndroidLWJGLKeycode.generateKeyName());
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice);
|
||||
|
||||
for (Spinner spinner : spinnersKeycode) {
|
||||
spinner.setAdapter(adapter);
|
||||
}
|
||||
|
||||
//Set color imageButton behavior
|
||||
buttonBackgroundColor.setOnClickListener(view -> ActionPopupWindow.showColorPicker(ctx, "Edit background color", true, buttonBackgroundColor));
|
||||
buttonStrokeColor.setOnClickListener(view -> ActionPopupWindow.showColorPicker(ctx, "Edit stroke color", false, buttonStrokeColor));
|
||||
|
||||
|
||||
//Set dialog buttons behavior
|
||||
setupDialogButtons();
|
||||
|
||||
hideUselessViews();
|
||||
|
||||
setupCheckerboards();
|
||||
}
|
||||
|
||||
protected void setupDialogButtons(){
|
||||
//Set dialog buttons behavior
|
||||
builder.setPositiveButton(android.R.string.ok, (dialogInterface1, i) -> {
|
||||
if(!hasPropertiesErrors(dialog.getContext())){
|
||||
saveProperties();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
}
|
||||
|
||||
protected void hideUselessViews(){
|
||||
(v.findViewById(R.id.editOrientation_textView)).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void setupCheckerboards(){
|
||||
CheckerboardDrawable drawable = new CheckerboardDrawable.Builder()
|
||||
.colorEven(Color.LTGRAY)
|
||||
.colorOdd(Color.WHITE)
|
||||
.size((int) Tools.dpToPx(20))
|
||||
.build();
|
||||
|
||||
buttonBackgroundColor.setBackground(drawable);
|
||||
buttonStrokeColor.setBackground(drawable);
|
||||
}
|
||||
|
||||
protected void setEditDialogValues(){
|
||||
|
||||
editName.setText(properties.name);
|
||||
|
||||
checkToggle.setChecked(properties.isToggle);
|
||||
checkPassThrough.setChecked(properties.passThruEnabled);
|
||||
checkBoxSwipeable.setChecked(properties.isSwipeable);
|
||||
|
||||
editWidth.setText(Float.toString(properties.getWidth()));
|
||||
editHeight.setText(Float.toString(properties.getHeight()));
|
||||
|
||||
editDynamicX.setEnabled(properties.isDynamicBtn);
|
||||
editDynamicY.setEnabled(properties.isDynamicBtn);
|
||||
editDynamicX.setHint(Float.toString(properties.x));
|
||||
editDynamicX.setText(properties.dynamicX);
|
||||
editDynamicY.setHint(Float.toString(properties.y));
|
||||
editDynamicY.setText(properties.dynamicY);
|
||||
|
||||
seekBarOpacity.setProgress((int) (properties.opacity*100));
|
||||
seekBarStrokeWidth.setProgress(properties.strokeWidth);
|
||||
seekBarCornerRadius.setProgress((int)properties.cornerRadius);
|
||||
|
||||
buttonBackgroundColor.setImageDrawable(new ColorDrawable(properties.bgColor));
|
||||
buttonStrokeColor.setImageDrawable(new ColorDrawable(properties.strokeColor));
|
||||
|
||||
setPercentageText(textCornerRadius,seekBarCornerRadius.getProgress());
|
||||
setPercentageText(textOpacity,seekBarOpacity.getProgress());
|
||||
setPercentageText(textStrokeWidth,seekBarStrokeWidth.getProgress());
|
||||
|
||||
checkDynamicPosition.setChecked(properties.isDynamicBtn);
|
||||
|
||||
for(int i=0; i< properties.keycodes.length; i++){
|
||||
if (properties.keycodes[i] < 0) {
|
||||
spinnersKeycode[i].setSelection(properties.keycodes[i] + specialArr.length);
|
||||
} else {
|
||||
spinnersKeycode[i].setSelection(EfficientAndroidLWJGLKeycode.getIndexByValue(properties.keycodes[i]) + specialArr.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected boolean hasPropertiesErrors(Context ctx){
|
||||
if (editName.getText().toString().isEmpty()) {
|
||||
editName.setError(ctx.getResources().getString(R.string.global_error_field_empty));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (properties.isDynamicBtn) {
|
||||
|
||||
int errorAt = 0;
|
||||
try {
|
||||
properties.insertDynamicPos(editDynamicX.getText().toString());
|
||||
errorAt = 1;
|
||||
properties.insertDynamicPos(editDynamicY.getText().toString());
|
||||
} catch (Throwable th) {
|
||||
(errorAt == 0 ? editDynamicX : editDynamicY).setError(th.getMessage());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void saveProperties(){
|
||||
//This method assumes there are no error.
|
||||
properties.name = editName.getText().toString();
|
||||
|
||||
//Keycodes
|
||||
for(int i=0; i<spinnersKeycode.length; ++i){
|
||||
if (spinnersKeycode[i].getSelectedItemPosition() < specialArr.length) {
|
||||
properties.keycodes[i] = spinnersKeycode[i].getSelectedItemPosition() - specialArr.length;
|
||||
} else {
|
||||
properties.keycodes[i] = EfficientAndroidLWJGLKeycode.getValueByIndex(spinnersKeycode[i].getSelectedItemPosition() - specialArr.length);
|
||||
}
|
||||
}
|
||||
|
||||
properties.opacity = seekBarOpacity.getProgress()/100f;
|
||||
properties.strokeWidth = seekBarStrokeWidth.getProgress();
|
||||
properties.cornerRadius = seekBarCornerRadius.getProgress();
|
||||
|
||||
properties.bgColor = ((ColorDrawable)buttonBackgroundColor.getDrawable()).getColor();
|
||||
properties.strokeColor = ((ColorDrawable) buttonStrokeColor.getDrawable()).getColor();
|
||||
|
||||
properties.isToggle = checkToggle.isChecked();
|
||||
properties.passThruEnabled = checkPassThrough.isChecked();
|
||||
properties.isSwipeable = checkBoxSwipeable.isChecked();
|
||||
|
||||
properties.setWidth(Float.parseFloat(editWidth.getText().toString()));
|
||||
properties.setHeight(Float.parseFloat(editHeight.getText().toString()));
|
||||
|
||||
properties.isDynamicBtn = checkDynamicPosition.isChecked();
|
||||
properties.dynamicX = editDynamicX.getText().toString().isEmpty() ? properties.dynamicX = Float.toString(properties.x) : editDynamicX.getText().toString();
|
||||
properties.dynamicY = editDynamicY.getText().toString().isEmpty() ? properties.dynamicY = Float.toString(properties.y) : editDynamicY.getText().toString();
|
||||
|
||||
button.updateProperties();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.handleview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import net.kdt.pojavlaunch.R;
|
||||
import net.kdt.pojavlaunch.customcontrols.ControlData;
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlDrawer;
|
||||
import net.kdt.pojavlaunch.customcontrols.ControlDrawerData;
|
||||
import net.kdt.pojavlaunch.customcontrols.ControlLayout;
|
||||
|
||||
public class EditControlDrawerPopup extends EditControlButtonPopup{
|
||||
private Spinner spinnerOrientation;
|
||||
|
||||
|
||||
private ControlDrawer drawer;
|
||||
private ControlDrawerData drawerData;
|
||||
|
||||
public EditControlDrawerPopup(ControlDrawer editedButton) {
|
||||
super(editedButton);
|
||||
drawer = editedButton;
|
||||
drawerData = editedButton.getDrawerData();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void hideUselessViews() {
|
||||
(v.findViewById(R.id.editMapping_textView)).setVisibility(View.GONE);
|
||||
checkPassThrough.setVisibility(View.GONE);
|
||||
checkToggle.setVisibility(View.GONE);
|
||||
checkBoxSwipeable.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeEditDialog(Context ctx) {
|
||||
super.initializeEditDialog(ctx);
|
||||
|
||||
spinnerOrientation = v.findViewById(R.id.editOrientation_spinner);
|
||||
|
||||
ArrayAdapter<ControlDrawerData.Orientation> adapter = new ArrayAdapter<>(ctx, android.R.layout.simple_spinner_item);
|
||||
adapter.addAll(ControlDrawerData.getOrientations());
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice);
|
||||
|
||||
spinnerOrientation.setAdapter(adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setEditDialogValues() {
|
||||
super.setEditDialogValues();
|
||||
|
||||
spinnerOrientation.setSelection(ControlDrawerData.orientationToInt(drawerData.orientation));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupDialogButtons() {
|
||||
super.setupDialogButtons();
|
||||
|
||||
builder.setNeutralButton(v.getResources().getString(R.string.customctrl_addsubbutton), (dialogInterface, i) -> {
|
||||
ControlLayout layout = (ControlLayout) drawer.getParent();
|
||||
ControlData controlData = drawerData.properties.clone();
|
||||
controlData.name = "new";
|
||||
layout.addSubButton(drawer, controlData);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveProperties() {
|
||||
drawerData.orientation = ControlDrawerData.intToOrientation(spinnerOrientation.getSelectedItemPosition());
|
||||
super.saveProperties();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.handleview;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import net.kdt.pojavlaunch.R;
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton;
|
||||
|
||||
public class EditControlSubButtonPopup extends EditControlButtonPopup{
|
||||
|
||||
|
||||
public EditControlSubButtonPopup(ControlButton button){
|
||||
super(button);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void hideUselessViews() {
|
||||
(v.findViewById(R.id.editSize_textView)).setVisibility(View.GONE);
|
||||
(v.findViewById(R.id.editOrientation_textView)).setVisibility(View.GONE);
|
||||
|
||||
checkDynamicPosition.setVisibility(View.GONE);
|
||||
|
||||
(v.findViewById(R.id.editDynamicPositionX_textView)).setVisibility(View.GONE);
|
||||
editDynamicX.setVisibility(View.GONE);
|
||||
|
||||
(v.findViewById(R.id.editDynamicPositionY_textView)).setVisibility(View.GONE);
|
||||
editDynamicY.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
@@ -22,13 +22,12 @@ package net.kdt.pojavlaunch.customcontrols.handleview;
|
||||
import android.graphics.*;
|
||||
import android.graphics.drawable.*;
|
||||
import android.os.*;
|
||||
import android.text.*;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
import android.content.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
import net.kdt.pojavlaunch.*;
|
||||
import net.kdt.pojavlaunch.customcontrols.*;
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton;
|
||||
|
||||
|
||||
public abstract class HandleView extends View implements ViewPositionListener, View.OnLongClickListener
|
||||
{
|
||||
@@ -100,6 +99,7 @@ public abstract class HandleView extends View implements ViewPositionListener, V
|
||||
mIdealVerticalOffset = 0.7f * handleHeight;
|
||||
}
|
||||
|
||||
|
||||
protected void updateDrawable() {
|
||||
// final int offset = getCurrentCursorOffset();
|
||||
final boolean isRtlCharAtOffset = true; // mView.getLayout().isRtlCharAt(offset);
|
||||
@@ -189,9 +189,9 @@ public abstract class HandleView extends View implements ViewPositionListener, V
|
||||
getPositionListener().removeSubscriber(this);
|
||||
}
|
||||
|
||||
void showActionPopupWindow(int delay) {
|
||||
void showActionPopupWindow(int delay, Object object) {
|
||||
if (mActionPopupWindow == null) {
|
||||
mActionPopupWindow = new ActionPopupWindow(this);
|
||||
mActionPopupWindow = new ActionPopupWindow(this, object);
|
||||
}
|
||||
if (mActionPopupShower == null) {
|
||||
mActionPopupShower = new Runnable() {
|
||||
@@ -314,13 +314,6 @@ public abstract class HandleView extends View implements ViewPositionListener, V
|
||||
protected int getCursorOffset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Addition
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
showActionPopupWindow(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Addition
|
||||
private float mDownX, mDownY;
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.handleview;
|
||||
|
||||
import android.graphics.drawable.*;
|
||||
import android.text.*;
|
||||
import android.view.*;
|
||||
import android.os.*;
|
||||
import net.kdt.pojavlaunch.customcontrols.*;
|
||||
|
||||
import net.kdt.pojavlaunch.customcontrols.buttons.ControlButton;
|
||||
|
||||
|
||||
public class SelectionEndHandleView extends HandleView
|
||||
{
|
||||
@@ -50,11 +50,9 @@ public class SelectionEndHandleView extends HandleView
|
||||
return 0; // mView.getSelectionEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
public void show(Object object){
|
||||
super.show();
|
||||
|
||||
showActionPopupWindow(0);
|
||||
showActionPopupWindow(0, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,10 +66,11 @@ public class SelectionEndHandleView extends HandleView
|
||||
// updatePosition((int) x, (int) y, false, false);
|
||||
positionAtCursorOffset(0, false);
|
||||
}
|
||||
/*
|
||||
public void setActionPopupWindow(ActionPopupWindow actionPopupWindow) {
|
||||
mActionPopupWindow = actionPopupWindow;
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
//TODO stub
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,21 +8,21 @@ public class LauncherPreferences
|
||||
{
|
||||
public static SharedPreferences DEFAULT_PREF;
|
||||
public static String PREF_RENDERER = "opengles2";
|
||||
public static boolean PREF_VERTYPE_RELEASE = true;
|
||||
public static boolean PREF_VERTYPE_SNAPSHOT = false;
|
||||
public static boolean PREF_VERTYPE_OLDALPHA = false;
|
||||
public static boolean PREF_VERTYPE_OLDBETA = false;
|
||||
public static boolean PREF_FREEFORM = false;
|
||||
public static boolean PREF_HIDE_SIDEBAR = false;
|
||||
public static boolean PREF_IGNORE_NOTCH = false;
|
||||
public static boolean PREF_BACK_TO_RIGHT_MOUSE = false;
|
||||
public static boolean PREF_BUTTON_FLAT = false;
|
||||
public static int PREF_NOTCH_SIZE = 0;
|
||||
public static float PREF_BUTTONSIZE = 100f;
|
||||
public static float PREF_MOUSESCALE = 100f;
|
||||
public static int PREF_LONGPRESS_TRIGGER = 500;
|
||||
public static String PREF_DEFAULTCTRL_PATH = Tools.CTRLDEF_FILE;
|
||||
public static String PREF_CUSTOM_JAVA_ARGS;
|
||||
|
||||
public static boolean PREF_VERTYPE_RELEASE = true;
|
||||
public static boolean PREF_VERTYPE_SNAPSHOT = false;
|
||||
public static boolean PREF_VERTYPE_OLDALPHA = false;
|
||||
public static boolean PREF_VERTYPE_OLDBETA = false;
|
||||
public static boolean PREF_FREEFORM = false;
|
||||
public static boolean PREF_HIDE_SIDEBAR = false;
|
||||
public static boolean PREF_IGNORE_NOTCH = false;
|
||||
public static boolean PREF_BACK_TO_RIGHT_MOUSE = false;
|
||||
public static int PREF_NOTCH_SIZE = 0;
|
||||
public static float PREF_BUTTONSIZE = 100f;
|
||||
public static float PREF_MOUSESCALE = 100f;
|
||||
public static int PREF_LONGPRESS_TRIGGER = 500;
|
||||
public static String PREF_DEFAULTCTRL_PATH = Tools.CTRLDEF_FILE;
|
||||
public static String PREF_CUSTOM_JAVA_ARGS;
|
||||
public static String PREF_CUSTOM_OPENGL_LIBNAME = "libgl4es_114.so";
|
||||
public static String PREF_LANGUAGE = "default";
|
||||
public static String PREF_VERSION_REPOS = "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json";
|
||||
@@ -33,20 +33,20 @@ public class LauncherPreferences
|
||||
public static String PREF_DEFAULT_RUNTIME;
|
||||
public static void loadPreferences() {
|
||||
PREF_RENDERER = DEFAULT_PREF.getString("renderer", "opengles2");
|
||||
PREF_BUTTONSIZE = DEFAULT_PREF.getInt("buttonscale", 100);
|
||||
PREF_MOUSESCALE = DEFAULT_PREF.getInt("mousescale", 100);
|
||||
PREF_MOUSESPEED = ((float)DEFAULT_PREF.getInt("mousespeed",100))/100f;
|
||||
PREF_FREEFORM = DEFAULT_PREF.getBoolean("freeform", false);
|
||||
PREF_HIDE_SIDEBAR = DEFAULT_PREF.getBoolean("hideSidebar", false);
|
||||
PREF_IGNORE_NOTCH = DEFAULT_PREF.getBoolean("ignoreNotch", false);
|
||||
PREF_BACK_TO_RIGHT_MOUSE = DEFAULT_PREF.getBoolean("backToRightMouse", false);
|
||||
PREF_BUTTON_FLAT = DEFAULT_PREF.getBoolean("flatButtonStyle", false);
|
||||
PREF_VERTYPE_RELEASE = DEFAULT_PREF.getBoolean("vertype_release", true);
|
||||
PREF_VERTYPE_SNAPSHOT = DEFAULT_PREF.getBoolean("vertype_snapshot", false);
|
||||
PREF_VERTYPE_OLDALPHA = DEFAULT_PREF.getBoolean("vertype_oldalpha", false);
|
||||
PREF_VERTYPE_OLDBETA = DEFAULT_PREF.getBoolean("vertype_oldbeta", false);
|
||||
PREF_LONGPRESS_TRIGGER = DEFAULT_PREF.getInt("timeLongPressTrigger", 500);
|
||||
PREF_DEFAULTCTRL_PATH = DEFAULT_PREF.getString("defaultCtrl", Tools.CTRLDEF_FILE);
|
||||
|
||||
PREF_BUTTONSIZE = DEFAULT_PREF.getInt("buttonscale", 100);
|
||||
PREF_MOUSESCALE = DEFAULT_PREF.getInt("mousescale", 100);
|
||||
PREF_MOUSESPEED = ((float)DEFAULT_PREF.getInt("mousespeed",100))/100f;
|
||||
PREF_FREEFORM = DEFAULT_PREF.getBoolean("freeform", false);
|
||||
PREF_HIDE_SIDEBAR = DEFAULT_PREF.getBoolean("hideSidebar", false);
|
||||
PREF_IGNORE_NOTCH = DEFAULT_PREF.getBoolean("ignoreNotch", false);
|
||||
PREF_BACK_TO_RIGHT_MOUSE = DEFAULT_PREF.getBoolean("backToRightMouse", false);
|
||||
PREF_VERTYPE_RELEASE = DEFAULT_PREF.getBoolean("vertype_release", true);
|
||||
PREF_VERTYPE_SNAPSHOT = DEFAULT_PREF.getBoolean("vertype_snapshot", false);
|
||||
PREF_VERTYPE_OLDALPHA = DEFAULT_PREF.getBoolean("vertype_oldalpha", false);
|
||||
PREF_VERTYPE_OLDBETA = DEFAULT_PREF.getBoolean("vertype_oldbeta", false);
|
||||
PREF_LONGPRESS_TRIGGER = DEFAULT_PREF.getInt("timeLongPressTrigger", 500);
|
||||
PREF_DEFAULTCTRL_PATH = DEFAULT_PREF.getString("defaultCtrl", Tools.CTRLDEF_FILE);
|
||||
PREF_LANGUAGE = DEFAULT_PREF.getString("language", "default");
|
||||
PREF_CHECK_LIBRARY_SHA = DEFAULT_PREF.getBoolean("checkLibraries",true);
|
||||
PREF_DISABLE_GESTURES = DEFAULT_PREF.getBoolean("disableGestures",false);
|
||||
|
||||
@@ -44,15 +44,15 @@ public class CallbackBridge {
|
||||
}
|
||||
|
||||
private static boolean threadAttached;
|
||||
public static void sendCursorPos(int x, int y) {
|
||||
public static void sendCursorPos(float x, float y) {
|
||||
if (!threadAttached) {
|
||||
threadAttached = CallbackBridge.nativeAttachThreadToOther(true, BaseMainActivity.isInputStackCall);
|
||||
}
|
||||
|
||||
DEBUG_STRING.append("CursorPos=" + x + ", " + y + "\n");
|
||||
mouseX = x;
|
||||
mouseY = y;
|
||||
nativeSendCursorPos(x, y);
|
||||
DEBUG_STRING.append("CursorPos=").append(x).append(", ").append(y).append("\n");
|
||||
mouseX = (int) x;
|
||||
mouseY = (int) y;
|
||||
nativeSendCursorPos(mouseX, mouseY);
|
||||
}
|
||||
|
||||
public static void sendPrepareGrabInitialPos() {
|
||||
@@ -61,7 +61,7 @@ public class CallbackBridge {
|
||||
}
|
||||
|
||||
public static void sendKeycode(int keycode, char keychar, int scancode, int modifiers, boolean isDown) {
|
||||
DEBUG_STRING.append("KeyCode=" + keycode + ", Char=" + keychar);
|
||||
DEBUG_STRING.append("KeyCode=").append(keycode).append(", Char=").append(keychar);
|
||||
// TODO CHECK: This may cause input issue, not receive input!
|
||||
/*
|
||||
if (!nativeSendCharMods((int) keychar, modifiers) || !nativeSendChar(keychar)) {
|
||||
@@ -71,7 +71,7 @@ public class CallbackBridge {
|
||||
|
||||
//nativeSendKeycode(keycode, keychar, scancode, isDown ? 1 : 0, modifiers);
|
||||
if(keycode != 0) nativeSendKey(keycode,scancode,isDown ? 1 : 0, modifiers);
|
||||
else nativeSendKey(32,scancode,isDown ? 1 : 0, modifiers);
|
||||
//else nativeSendKey(32,scancode,isDown ? 1 : 0, modifiers);
|
||||
if(isDown && keychar != '\u0000') {
|
||||
nativeSendCharMods(keychar,modifiers);
|
||||
nativeSendChar(keychar);
|
||||
@@ -81,7 +81,7 @@ public class CallbackBridge {
|
||||
}
|
||||
|
||||
public static void sendMouseKeycode(int button, int modifiers, boolean isDown) {
|
||||
DEBUG_STRING.append("MouseKey=" + button + ", down=" + isDown + "\n");
|
||||
DEBUG_STRING.append("MouseKey=").append(button).append(", down=").append(isDown).append("\n");
|
||||
// if (isGrabbing()) DEBUG_STRING.append("MouseGrabStrace: " + android.util.Log.getStackTraceString(new Throwable()) + "\n");
|
||||
nativeSendMouseButton(button, isDown ? 1 : 0, modifiers);
|
||||
}
|
||||
@@ -92,7 +92,7 @@ public class CallbackBridge {
|
||||
}
|
||||
|
||||
public static void sendScroll(double xoffset, double yoffset) {
|
||||
DEBUG_STRING.append("ScrollX=" + xoffset + ",ScrollY=" + yoffset);
|
||||
DEBUG_STRING.append("ScrollX=").append(xoffset).append(",ScrollY=").append(yoffset);
|
||||
nativeSendScroll(xoffset, yoffset);
|
||||
}
|
||||
|
||||
@@ -166,6 +166,30 @@ public class CallbackBridge {
|
||||
return currMods;
|
||||
}
|
||||
|
||||
public static void setModifiers(int keyCode, boolean isDown){
|
||||
switch (keyCode){
|
||||
case LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT:
|
||||
CallbackBridge.holdingShift = isDown;
|
||||
return;
|
||||
|
||||
case LWJGLGLFWKeycode.GLFW_KEY_LEFT_CONTROL:
|
||||
CallbackBridge.holdingCtrl = isDown;
|
||||
return;
|
||||
|
||||
case LWJGLGLFWKeycode.GLFW_KEY_LEFT_ALT:
|
||||
CallbackBridge.holdingAlt = isDown;
|
||||
return;
|
||||
|
||||
case LWJGLGLFWKeycode.GLFW_KEY_CAPS_LOCK:
|
||||
CallbackBridge.holdingCapslock = isDown;
|
||||
return;
|
||||
|
||||
case LWJGLGLFWKeycode.GLFW_KEY_NUM_LOCK:
|
||||
CallbackBridge.holdingNumlock = isDown;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static native boolean nativeAttachThreadToOther(boolean isAndroid, boolean isUsePushPoll);
|
||||
|
||||
private static native boolean nativeSendChar(char codepoint);
|
||||
@@ -179,8 +203,6 @@ public class CallbackBridge {
|
||||
private static native void nativeSendScreenSize(int width, int height);
|
||||
|
||||
public static native boolean nativeIsGrabbing();
|
||||
public static native void nativePutControllerAxes(FloatBuffer axBuf);
|
||||
public static native void nativePutControllerButtons(ByteBuffer axBuf);
|
||||
static {
|
||||
System.loadLibrary("pojavexec");
|
||||
}
|
||||
|
||||
@@ -363,43 +363,3 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendScroll(JNIEn
|
||||
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_GLFW_nglfwSetShowingWindow(JNIEnv* env, jclass clazz, jlong window) {
|
||||
showingWindow = (long) window;
|
||||
}
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_lwjgl_glfw_CallbackBridge_nativePutControllerAxes(JNIEnv *env, jclass clazz,
|
||||
jobject ax_buf) {
|
||||
// TODO: implement nativePutControllerAxes()
|
||||
if(isInputReady) {
|
||||
jbyte *src = (jbyte *)((*env)->GetDirectBufferAddress(*env,ax_buf));
|
||||
jclass glfw_joystick_class = (*runtimeJNIEnvPtr_ANDROID)->FindClass(runtimeJNIEnvPtr_ANDROID,"org/lwjgl/glfw/GLFW");
|
||||
if(glfw_joystick_class == NULL) {
|
||||
__android_log_print(ANDROID_LOG_ERROR,"ControllerPipeNative","GLFW is not attached!");
|
||||
return;
|
||||
}
|
||||
jfieldID glfw_controller_axis_data = (*runtimeJNIEnvPtr_ANDROID)->GetStaticFieldID(runtimeJNIEnvPtr_ANDROID,glfw_joystick_class,"joystickData",
|
||||
"Ljava/nio/FloatBuffer;");
|
||||
if(glfw_controller_axis_data == NULL) {
|
||||
__android_log_print(ANDROID_LOG_ERROR,"ControllerPipeNative","Unable to find the field!");
|
||||
return;
|
||||
}
|
||||
(*runtimeJNIEnvPtr_ANDROID)->SetStaticObjectField(runtimeJNIEnvPtr_ANDROID,glfw_joystick_class,glfw_controller_axis_data,(*runtimeJNIEnvPtr_ANDROID)->NewDirectByteBuffer(runtimeJNIEnvPtr_ANDROID,src,(*env)->GetDirectBufferCapacity(env,ax_buf)));
|
||||
}
|
||||
}
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_lwjgl_glfw_CallbackBridge_nativePutControllerButtons(JNIEnv *env, jclass clazz,
|
||||
jobject ax_buf) {
|
||||
// TODO: implement nativePutControllerButtons()
|
||||
if(isInputReady) {
|
||||
jbyte *src = (jbyte *)((*env)->GetDirectBufferAddress(*env,ax_buf));
|
||||
jclass glfw_joystick_class = (*runtimeJNIEnvPtr_ANDROID)->FindClass(runtimeJNIEnvPtr_ANDROID,"org/lwjgl/glfw/GLFW");
|
||||
if(glfw_joystick_class == NULL) {
|
||||
__android_log_print(ANDROID_LOG_ERROR,"ControllerPipeNative","GLFW is not attached!");
|
||||
return;
|
||||
}
|
||||
jfieldID glfw_controller_button_data = (*runtimeJNIEnvPtr_ANDROID)->GetStaticFieldID(runtimeJNIEnvPtr_ANDROID,glfw_joystick_class,"buttonData",
|
||||
"Ljava/nio/ByteBuffer;");
|
||||
if(glfw_controller_button_data == NULL) {
|
||||
__android_log_print(ANDROID_LOG_ERROR,"ControllerPipeNative","Unable to find the field!");
|
||||
return;
|
||||
}
|
||||
(*runtimeJNIEnvPtr_ANDROID)->SetStaticObjectField(runtimeJNIEnvPtr_ANDROID,glfw_joystick_class,glfw_controller_button_data,(*runtimeJNIEnvPtr_ANDROID)->NewDirectByteBuffer(runtimeJNIEnvPtr_ANDROID,src,(*env)->GetDirectBufferCapacity(env,ax_buf)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#4D000000" />
|
||||
<padding android:left="8.0dip" android:top="0.0dip" android:right="8.0dip" android:bottom="0.0dip" />
|
||||
</shape>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true" android:drawable="@drawable/control_button_round_pressed" />
|
||||
<item android:drawable="@drawable/control_button_round_normal" />
|
||||
</selector>
|
||||
@@ -1,5 +0,0 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#4D000000" />
|
||||
<corners android:radius="6dp" />
|
||||
<padding android:left="8.0dip" android:top="0.0dip" android:right="8.0dip" android:bottom="0.0dip" />
|
||||
</shape>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#807f7f7f" />
|
||||
<stroke android:width="2.0dip" android:color="#dd7f7f7f" />
|
||||
<corners android:radius="6dp" />
|
||||
<padding android:left="8.0dip" android:top="0.0dip" android:right="8.0dip" android:bottom="0.0dip" />
|
||||
</shape>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#dd7f7f7f" />
|
||||
<stroke android:width="2.0dip" android:color="#dd7f7f7f" />
|
||||
<corners android:radius="6dp" />
|
||||
<padding android:left="8.0dip" android:top="0.0dip" android:right="8.0dip" android:bottom="0.0dip" />
|
||||
</shape>
|
||||
BIN
app_pojavlauncher/src/main/res/drawable/pointer.png
Normal file
BIN
app_pojavlauncher/src/main/res/drawable/pointer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 695 B |
459
app_pojavlauncher/src/main/res/layout/control_button_setting.xml
Normal file
459
app_pojavlauncher/src/main/res/layout/control_button_setting.xml
Normal file
@@ -0,0 +1,459 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.kdt.DefocusableScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="500dp"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_optimizationLevel="standard|dimensions|chains">
|
||||
|
||||
|
||||
<!-- EDIT NAME SECTION -->
|
||||
<TextView
|
||||
android:id="@+id/editName_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:text="@string/global_name"
|
||||
android:gravity="center"
|
||||
android:paddingEnd="5dp"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editName_editText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@+id/editName_textView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/editName_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/editName_textView"
|
||||
/>
|
||||
|
||||
<!-- SIZE SECTION -->
|
||||
<TextView
|
||||
android:id="@+id/editSize_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="45dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/customctrl_size"
|
||||
android:paddingEnd="5dp"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editName_textView"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editSize_editTextX"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintStart_toEndOf="@id/editSize_textView"
|
||||
app:layout_constraintTop_toTopOf="@id/editSize_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editSize_textView"
|
||||
app:layout_constraintEnd_toStartOf="@id/editSize_editTextY"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editSize_editTextY"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editSize_editTextX"
|
||||
app:layout_constraintTop_toTopOf="@id/editSize_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editSize_textView"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:text="x"
|
||||
android:gravity="center"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editSize_editTextX"
|
||||
app:layout_constraintEnd_toStartOf="@id/editSize_editTextY"
|
||||
app:layout_constraintTop_toTopOf="@id/editSize_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editSize_textView" />
|
||||
|
||||
<!-- MAPPING SECTION -->
|
||||
<TextView
|
||||
android:id="@+id/editMapping_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="70dp"
|
||||
android:text="@string/customctrl_mapping"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="5dp"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editSize_textView"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/editMapping_spinner_1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/transparent"
|
||||
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintVertical_chainStyle="spread"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editMapping_textView"
|
||||
app:layout_constraintTop_toTopOf="@id/editMapping_textView"
|
||||
app:layout_constraintEnd_toStartOf="@id/editMapping_spinner_2"
|
||||
app:layout_constraintBottom_toTopOf="@id/editMapping_spinner_3"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editMapping_plus_1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:text="+"
|
||||
android:gravity="center"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editMapping_spinner_1"
|
||||
app:layout_constraintEnd_toStartOf="@id/editMapping_spinner_2"
|
||||
app:layout_constraintTop_toTopOf="@id/editMapping_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editMapping_spinner_1"
|
||||
/>
|
||||
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/editMapping_spinner_2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/transparent"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editMapping_spinner_1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/editMapping_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editMapping_spinner_1"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editMapping_plus_2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:text="+"
|
||||
android:gravity="center"
|
||||
|
||||
app:layout_constraintBottom_toBottomOf="@id/editMapping_textView"
|
||||
app:layout_constraintEnd_toEndOf="@id/editMapping_textView"
|
||||
app:layout_constraintTop_toTopOf="@id/editMapping_spinner_3"
|
||||
|
||||
/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/editMapping_spinner_3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/transparent"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editMapping_textView"
|
||||
app:layout_constraintTop_toBottomOf="@id/editMapping_spinner_1"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editMapping_textView"
|
||||
app:layout_constraintEnd_toStartOf="@id/editMapping_spinner_4"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editMapping_plus_3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:text="+"
|
||||
android:gravity="center"
|
||||
|
||||
|
||||
app:layout_constraintBottom_toBottomOf="@id/editMapping_textView"
|
||||
app:layout_constraintStart_toEndOf="@id/editMapping_spinner_3"
|
||||
app:layout_constraintEnd_toStartOf="@id/editMapping_spinner_4"
|
||||
app:layout_constraintTop_toTopOf="@id/editMapping_spinner_4"
|
||||
|
||||
/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/editMapping_spinner_4"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/transparent"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editMapping_spinner_3"
|
||||
app:layout_constraintTop_toBottomOf="@id/editMapping_spinner_2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editMapping_textView"
|
||||
/>
|
||||
|
||||
<!-- ORIENTATION SECTION -->
|
||||
<TextView
|
||||
android:id="@+id/editOrientation_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="45dp"
|
||||
android:text="@string/customctrl_orientation"
|
||||
android:gravity="center"
|
||||
android:paddingEnd="5dp"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editMapping_textView"
|
||||
/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/editOrientation_spinner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/transparent"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editOrientation_textView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/editOrientation_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editOrientation_textView"
|
||||
/>
|
||||
|
||||
<!-- TOGGLE SECTION -->
|
||||
<CheckBox
|
||||
android:id="@+id/checkboxToggle"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/customctrl_toggle"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editOrientation_textView"
|
||||
/>
|
||||
|
||||
<!-- MOUSE PASS THROUGH SECTION -->
|
||||
<CheckBox
|
||||
android:id="@+id/checkboxPassThrough"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/customctrl_passthru"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/checkboxToggle"
|
||||
/>
|
||||
|
||||
<!-- SWIPEABLE BUTTON SECTION -->
|
||||
<CheckBox
|
||||
android:id="@+id/checkboxSwipeable"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/customctrl_swipeable"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/checkboxPassThrough"
|
||||
/>
|
||||
|
||||
<!-- BACKGROUND COLOR SECTION -->
|
||||
<TextView
|
||||
android:id="@+id/editBackgroundColor_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
android:text="@string/customctrl_background_color"
|
||||
android:gravity="center"
|
||||
android:paddingEnd="5dp"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/checkboxSwipeable"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/editBackgroundColor_imageButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginHorizontal="50dp"
|
||||
android:layout_marginVertical="5dp"
|
||||
|
||||
android:background="#FFFFFFFF"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editBackgroundColor_textView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/editBackgroundColor_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editBackgroundColor_textView"
|
||||
/>
|
||||
|
||||
<!-- STROKE WIDTH -->
|
||||
<TextView
|
||||
android:id="@+id/editStrokeWidth_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
android:text="@string/customctrl_stroke_width"
|
||||
android:gravity="center"
|
||||
android:paddingEnd="5dp"
|
||||
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editBackgroundColor_textView"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/editStrokeWidth_seekbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editStrokeWidth_textView"
|
||||
app:layout_constraintTop_toTopOf="@id/editStrokeWidth_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editStrokeWidth_textView"
|
||||
app:layout_constraintEnd_toStartOf="@id/editStrokeWidth_textView_percent"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editStrokeWidth_textView_percent"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="0dp"
|
||||
android:text="100%"
|
||||
android:gravity="center"
|
||||
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/editStrokeWidth_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editStrokeWidth_textView"
|
||||
/>
|
||||
|
||||
<!-- STROKE COLOR VERSION -->
|
||||
<TextView
|
||||
android:id="@+id/editStrokeColor_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
android:text="@string/customctrl_stroke_color"
|
||||
android:gravity="center"
|
||||
android:paddingEnd="5dp"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editStrokeWidth_textView"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/editStrokeColor_imageButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginHorizontal="50dp"
|
||||
android:layout_marginVertical="5dp"
|
||||
|
||||
android:background="#FFFFFFFF"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editStrokeColor_textView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/editStrokeColor_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editStrokeColor_textView"
|
||||
/>
|
||||
|
||||
<!-- CORNER RADIUS SECTION -->
|
||||
<TextView
|
||||
android:id="@+id/editCornerRadius_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
android:text="@string/customctrl_corner_radius"
|
||||
android:gravity="center"
|
||||
android:paddingEnd="5dp"
|
||||
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editStrokeColor_textView"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/editCornerRadius_seekbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editCornerRadius_textView"
|
||||
app:layout_constraintTop_toTopOf="@id/editCornerRadius_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editCornerRadius_textView"
|
||||
app:layout_constraintEnd_toStartOf="@id/editCornerRadius_textView_percent"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editCornerRadius_textView_percent"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="0dp"
|
||||
android:text="100%"
|
||||
android:gravity="center"
|
||||
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/editCornerRadius_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editCornerRadius_textView"
|
||||
/>
|
||||
|
||||
<!-- BUTTON OPACITY SECTION -->
|
||||
<TextView
|
||||
android:id="@+id/editButtonOpacity_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
android:text="@string/customctrl_button_opacity"
|
||||
android:gravity="center"
|
||||
android:paddingEnd="5dp"
|
||||
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editCornerRadius_textView"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/editButtonOpacity_seekbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
|
||||
app:layout_constraintStart_toEndOf="@id/editButtonOpacity_textView"
|
||||
app:layout_constraintTop_toTopOf="@id/editButtonOpacity_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editButtonOpacity_textView"
|
||||
app:layout_constraintEnd_toStartOf="@id/editButtonOpacity_textView_percent"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editButtonOpacity_textView_percent"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="0dp"
|
||||
android:text="100%"
|
||||
android:gravity="center"
|
||||
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/editButtonOpacity_textView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/editButtonOpacity_textView"
|
||||
/>
|
||||
|
||||
<!-- DYNAMIC BUTTON SECTION -->
|
||||
<CheckBox
|
||||
android:id="@+id/checkboxDynamicPosition"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/customctrl_dynamicpos"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editButtonOpacity_textView"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editDynamicPositionX_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/customctrl_dynamicpos_x"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/checkboxDynamicPosition"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editDynamicPositionX_editText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editDynamicPositionX_textView"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/editDynamicPositionY_textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/customctrl_dynamicpos_y"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editDynamicPositionX_editText"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editDynamicPositionY_editText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/editDynamicPositionY_textView"
|
||||
/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.kdt.DefocusableScrollView>
|
||||
@@ -1,158 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/customctrl_keyname"/>
|
||||
|
||||
<Spinner
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/controlsetting_spinner_lwjglkeycode"/>
|
||||
|
||||
<TextView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/global_name"/>
|
||||
|
||||
<EditText
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:singleLine="true"
|
||||
android:id="@+id/controlsetting_edit_name"/>
|
||||
|
||||
<TextView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/customctrl_transparency_bg"/>
|
||||
|
||||
<SeekBar
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/controlsetting_seek_transparency"/>
|
||||
|
||||
<CheckBox
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/customctrl_toggle"
|
||||
android:id="@+id/controlsetting_checkbox_toggle"/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/controlsetting_checkbox_passthru"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/customctrl_passthru" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/controlsetting_checkbox_round"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/customctrl_rounded" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/customctrl_size"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center">
|
||||
|
||||
<EditText
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.0"
|
||||
android:id="@+id/controlsetting_edit_width"
|
||||
android:hint="@string/customctrl_size_width"
|
||||
android:inputType="numberDecimal"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="×"
|
||||
android:gravity="center"/>
|
||||
|
||||
<EditText
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.0"
|
||||
android:id="@+id/controlsetting_edit_height"
|
||||
android:hint="@string/customctrl_size_height"
|
||||
android:inputType="numberDecimal"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<CheckBox
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/customctrl_dynamicpos"
|
||||
android:id="@+id/controlsetting_checkbox_dynamicpos"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/customctrl_dynamicpos_x"/>
|
||||
|
||||
<EditText
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:singleLine="true"
|
||||
android:id="@+id/controlsetting_edit_dynamicpos_x"/>
|
||||
|
||||
<TextView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/customctrl_dynamicpos_y"/>
|
||||
|
||||
<EditText
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:singleLine="true"
|
||||
android:id="@+id/controlsetting_edit_dynamicpos_y"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/customctrl_keycombine"/>
|
||||
|
||||
<CheckBox
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/customctrl_keycombine_alt"
|
||||
android:id="@+id/controlsetting_checkbox_keycombine_alt"/>
|
||||
|
||||
<CheckBox
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/customctrl_keycombine_control"
|
||||
android:id="@+id/controlsetting_checkbox_keycombine_control"/>
|
||||
|
||||
<CheckBox
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/customctrl_keycombine_shift"
|
||||
android:id="@+id/controlsetting_checkbox_keycombine_shift"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
@@ -39,6 +39,13 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/console_pointer"
|
||||
android:visibility="invisible"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/pointer" />
|
||||
|
||||
</net.kdt.pojavlaunch.customcontrols.ControlLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
android:id="@+id/menu_ctrl_add"
|
||||
android:title="@string/customctrl_addbutton"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_ctrl_add_drawer"
|
||||
android:title="@string/customctrl_addbutton_drawer"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_ctrl_load"
|
||||
android:title="@string/global_load"/>
|
||||
|
||||
@@ -170,18 +170,28 @@
|
||||
<string name="customctrl_size">Size</string>
|
||||
<string name="customctrl_size_width">Width</string>
|
||||
<string name="customctrl_size_height">Height</string>
|
||||
|
||||
<string name="customctrl_mapping">Mapping</string>
|
||||
<string name="customctrl_orientation">Orientation</string>
|
||||
<string name="customctrl_background_color">Background color</string>
|
||||
<string name="customctrl_corner_radius">Corner radius</string>
|
||||
<string name="customctrl_stroke_width">Stroke width</string>
|
||||
<string name="customctrl_stroke_color">Stroke color</string>
|
||||
|
||||
<string name="customctrl_dynamicpos">Dynamic position</string>
|
||||
<string name="customctrl_dynamicpos_x">Dynamic X</string>
|
||||
<string name="customctrl_dynamicpos_y">Dynamic Y</string>
|
||||
|
||||
<string name="customctrl_transparency_bg">Background transparency</string>
|
||||
<string name="customctrl_button_opacity">Button Opacity</string>
|
||||
|
||||
<string name="customctrl_keycombine">Key combination</string>
|
||||
<string name="customctrl_keycombine_alt">Alt</string>
|
||||
<string name="customctrl_keycombine_control">Ctrl</string>
|
||||
<string name="customctrl_keycombine_shift">Shift</string>
|
||||
<string name="customctrl_addbutton">Add button</string>
|
||||
<string name="customctrl_addbutton_drawer">Add button drawer</string>
|
||||
<string name="customctrl_addsubbutton">Add sub-button</string>
|
||||
|
||||
<string name="customctrl_selectdefault">Select default Control json</string>
|
||||
|
||||
@@ -207,6 +217,7 @@
|
||||
<string name="mcl_setting_title_mousespeed">Mouse Speed</string>
|
||||
<string name="mcl_setting_subtitle_mousespeed">Changes the speed of the software mouse</string>
|
||||
<string name="customctrl_passthru">Mouse pass-thru</string>
|
||||
<string name="customctrl_swipeable">Swipeable</string>
|
||||
<string name="customctrl_rounded">Rounded</string>
|
||||
<string name="memory_warning_msg">The current amount of free RAM (%d) is lower than allocated RAM (%d), which may lead to crashes. Change the allocation if the game crashes.</string>
|
||||
<string name="mcl_memory_allocation">Memory allocation</string>
|
||||
|
||||
@@ -24,12 +24,6 @@
|
||||
app2:selectable="false"
|
||||
app2:icon="@drawable/tap_len" />
|
||||
|
||||
<androidx.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="flatButtonStyle"
|
||||
android:summary="@string/mcl_setting_subtitle_flat_button_style"
|
||||
android:title="@string/mcl_setting_title_flat_button_style"
|
||||
app2:icon="@drawable/ic_flatstyle" />
|
||||
|
||||
<androidx.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
|
||||
Reference in New Issue
Block a user