mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2026-04-24 11:37:15 -04:00
Fix[input]: make hotbar behave more like an android button, move hotbar handling into a separate class
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.mouse;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import net.kdt.pojavlaunch.LwjglGlfwKeycode;
|
||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||
import net.kdt.pojavlaunch.utils.MCOptionUtils;
|
||||
|
||||
import org.lwjgl.glfw.CallbackBridge;
|
||||
|
||||
import static net.kdt.pojavlaunch.utils.MCOptionUtils.getMcScale;
|
||||
|
||||
import android.os.Handler;
|
||||
|
||||
public class HotbarTracker implements MCOptionUtils.MCOptionListener {
|
||||
|
||||
private static final int[] HOTBAR_KEYS = {
|
||||
LwjglGlfwKeycode.GLFW_KEY_1, LwjglGlfwKeycode.GLFW_KEY_2, LwjglGlfwKeycode.GLFW_KEY_3,
|
||||
LwjglGlfwKeycode.GLFW_KEY_4, LwjglGlfwKeycode.GLFW_KEY_5, LwjglGlfwKeycode.GLFW_KEY_6,
|
||||
LwjglGlfwKeycode.GLFW_KEY_7, LwjglGlfwKeycode.GLFW_KEY_8, LwjglGlfwKeycode.GLFW_KEY_9};
|
||||
private int mLastHudKey, mHudPointerId;
|
||||
private final DropGesture mDropGesture;
|
||||
private int mBarWidth, mBarHeight;
|
||||
private final float mScaleFactor;
|
||||
|
||||
/**
|
||||
* @param mGestureHandler the gesture handler for the integrated drop gesture
|
||||
* @param mScaleFactor the screen scale factor
|
||||
*/
|
||||
public HotbarTracker(Handler mGestureHandler, float mScaleFactor) {
|
||||
computeBarDimensions();
|
||||
MCOptionUtils.addMCOptionListener(this);
|
||||
this.mScaleFactor = mScaleFactor;
|
||||
mDropGesture = new DropGesture(mGestureHandler);
|
||||
mHudPointerId = -1;
|
||||
}
|
||||
|
||||
public boolean begin(MotionEvent motionEvent) {
|
||||
if(mHudPointerId != -1) return false;
|
||||
int pointer = motionEvent.getActionIndex();
|
||||
if(motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) pointer = 0;
|
||||
int x = (int)motionEvent.getX(pointer);
|
||||
if(isWithinHotbar(x, (int)motionEvent.getY(pointer))) {
|
||||
mHudPointerId = motionEvent.getPointerId(pointer);
|
||||
hotbarClick(x);
|
||||
mDropGesture.submit(true);
|
||||
return true;
|
||||
}else {
|
||||
mHudPointerId = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean track(MotionEvent motionEvent, int trackedIndex, boolean hasDoubleTapped) {
|
||||
if(mHudPointerId == -1) return false;
|
||||
int index = motionEvent.findPointerIndex(mHudPointerId);
|
||||
if(index == -1) {
|
||||
cancel();
|
||||
return false;
|
||||
}
|
||||
int x = (int)motionEvent.getX(index);
|
||||
if(isWithinHotbar(x, (int)motionEvent.getY(index))) {
|
||||
hotbarClick(x);
|
||||
mDropGesture.submit(true);
|
||||
if(hasDoubleTapped && !LauncherPreferences.PREF_DISABLE_SWAP_HAND) {
|
||||
CallbackBridge.sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_F);
|
||||
}
|
||||
}else {
|
||||
mDropGesture.submit(false);
|
||||
}
|
||||
return trackedIndex == index;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
mDropGesture.cancel();
|
||||
mHudPointerId = -1;
|
||||
}
|
||||
|
||||
private boolean isWithinHotbar(int x, int y) {
|
||||
int barY = CallbackBridge.physicalHeight - mBarHeight;
|
||||
if(y < barY) return false;
|
||||
|
||||
int barX = (CallbackBridge.physicalWidth / 2) - (mBarWidth / 2);
|
||||
return x >= barX && x < barX + mBarWidth;
|
||||
}
|
||||
|
||||
private void hotbarClick(int x) {
|
||||
int barX = (CallbackBridge.physicalWidth / 2) - (mBarWidth / 2);
|
||||
if(x < barX || x >= barX + mBarWidth) return;
|
||||
|
||||
int key = HOTBAR_KEYS[(int) net.kdt.pojavlaunch.utils.MathUtils.map(x, barX, barX + mBarWidth, 0, 9)];
|
||||
if(key != mLastHudKey) {
|
||||
CallbackBridge.sendKeyPress(key);
|
||||
// The GUI bar is handled before the gesture will be submitted, so this
|
||||
// will be resubmitted again soon (with the timer restarted)
|
||||
mDropGesture.cancel();
|
||||
mLastHudKey = key;
|
||||
}
|
||||
}
|
||||
|
||||
private int mcScale(int input, int guiScale) {
|
||||
return (int)((guiScale * input)/ mScaleFactor);
|
||||
}
|
||||
|
||||
private void computeBarDimensions() {
|
||||
int guiScale = getMcScale();
|
||||
mBarHeight = mcScale(20, guiScale);
|
||||
mBarWidth = mcScale(180, guiScale);
|
||||
}
|
||||
@Override
|
||||
public void onOptionChanged() {
|
||||
computeBarDimensions();
|
||||
}
|
||||
}
|
||||
@@ -1,68 +1,47 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.mouse;
|
||||
|
||||
import static net.kdt.pojavlaunch.utils.MCOptionUtils.getMcScale;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import net.kdt.pojavlaunch.LwjglGlfwKeycode;
|
||||
import net.kdt.pojavlaunch.TapDetector;
|
||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||
import net.kdt.pojavlaunch.utils.MCOptionUtils;
|
||||
|
||||
import org.lwjgl.glfw.CallbackBridge;
|
||||
|
||||
public class InGameEventProcessor implements TouchEventProcessor {
|
||||
|
||||
private int mGuiScale;
|
||||
@SuppressWarnings("FieldCanBeLocal") // it can't, otherwise the weak reference will disappear
|
||||
private final MCOptionUtils.MCOptionListener mGuiScaleListener = () -> mGuiScale = getMcScale();
|
||||
private final Handler mGestureHandler = new Handler(Looper.getMainLooper());
|
||||
private static final int[] HOTBAR_KEYS = {
|
||||
LwjglGlfwKeycode.GLFW_KEY_1, LwjglGlfwKeycode.GLFW_KEY_2, LwjglGlfwKeycode.GLFW_KEY_3,
|
||||
LwjglGlfwKeycode.GLFW_KEY_4, LwjglGlfwKeycode.GLFW_KEY_5, LwjglGlfwKeycode.GLFW_KEY_6,
|
||||
LwjglGlfwKeycode.GLFW_KEY_7, LwjglGlfwKeycode.GLFW_KEY_8, LwjglGlfwKeycode.GLFW_KEY_9};
|
||||
private int mLastHudKey;
|
||||
private final float mScaleFactor;
|
||||
private final double mSensitivity;
|
||||
private final PointerTracker mTracker = new PointerTracker();
|
||||
private final HotbarTracker mGuiBarTracker;
|
||||
private final LeftClickGesture mLeftClickGesture = new LeftClickGesture(mGestureHandler);
|
||||
private final RightClickGesture mRightClickGesture = new RightClickGesture(mGestureHandler);
|
||||
private final DropGesture mDropGesture = new DropGesture(mGestureHandler);
|
||||
private final TapDetector mDoubleTapDetector = new TapDetector(2, TapDetector.DETECTION_METHOD_DOWN);
|
||||
|
||||
public InGameEventProcessor(float scaleFactor, double sensitivity) {
|
||||
MCOptionUtils.addMCOptionListener(mGuiScaleListener);
|
||||
mScaleFactor = scaleFactor;
|
||||
mGuiBarTracker = new HotbarTracker(mGestureHandler, scaleFactor);
|
||||
mSensitivity = sensitivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processTouchEvent(MotionEvent motionEvent) {
|
||||
boolean hasDoubleTapped = mDoubleTapDetector.onTouchEvent(motionEvent);
|
||||
boolean hasGuiBarHit = handleGuiBar(motionEvent);
|
||||
// Handle this gesture separately, outside of the event masking to avoid inconsistencies
|
||||
// with the double tap detector.
|
||||
if(hasGuiBarHit && hasDoubleTapped && !LauncherPreferences.PREF_DISABLE_SWAP_HAND) {
|
||||
CallbackBridge.sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_F);
|
||||
}
|
||||
// Handle the rest of the in-game motion.
|
||||
switch (motionEvent.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if(mGuiBarTracker.begin(motionEvent)) break;
|
||||
mTracker.startTracking(motionEvent);
|
||||
if(LauncherPreferences.PREF_DISABLE_GESTURES) break;
|
||||
checkGestures(handleGuiBar(motionEvent));
|
||||
checkGestures();
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
mGuiBarTracker.begin(motionEvent);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
mTracker.trackEvent(motionEvent);
|
||||
if(!LauncherPreferences.PREF_DISABLE_GESTURES) {
|
||||
checkGestures(hasGuiBarHit);
|
||||
}
|
||||
// Only send new mouse positions if the event hasn't hit the inventory bar.
|
||||
// Note that the events are sent to the tracker regardless, to prevent cursor
|
||||
// jumps when leaving the inventory bar in one single touch gesture.
|
||||
if(hasGuiBarHit) break;
|
||||
int trackedIndex = mTracker.trackEvent(motionEvent);
|
||||
// Don't send mouse positions if there's a finger in the gui bar *and* the camera tracker
|
||||
// tracks the same finger as the gui bar.
|
||||
if(mGuiBarTracker.track(motionEvent, trackedIndex, hasDoubleTapped)) break;
|
||||
checkGestures();
|
||||
float[] motionVector = mTracker.getMotionVector();
|
||||
CallbackBridge.mouseX += motionVector[0] * mSensitivity;
|
||||
CallbackBridge.mouseY += motionVector[1] * mSensitivity;
|
||||
@@ -70,6 +49,7 @@ public class InGameEventProcessor implements TouchEventProcessor {
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
mGuiBarTracker.cancel();
|
||||
mTracker.cancelTracking();
|
||||
cancelGestures(false);
|
||||
}
|
||||
@@ -81,56 +61,13 @@ public class InGameEventProcessor implements TouchEventProcessor {
|
||||
cancelGestures(true);
|
||||
}
|
||||
|
||||
private void checkGestures(boolean hasGuiBarHit) {
|
||||
if(!hasGuiBarHit) {
|
||||
mLeftClickGesture.inputEvent();
|
||||
mRightClickGesture.inputEvent();
|
||||
}
|
||||
mDropGesture.submit(hasGuiBarHit);
|
||||
private void checkGestures() {
|
||||
mLeftClickGesture.inputEvent();
|
||||
mRightClickGesture.inputEvent();
|
||||
}
|
||||
|
||||
private void cancelGestures(boolean isSwitching) {
|
||||
mLeftClickGesture.cancel(isSwitching);
|
||||
mRightClickGesture.cancel(isSwitching);
|
||||
mDropGesture.cancel();
|
||||
}
|
||||
|
||||
private boolean handleGuiBar(MotionEvent motionEvent) {
|
||||
int hudKeyHandled = -1;
|
||||
for(int i = 0; i < motionEvent.getPointerCount(); i++) {
|
||||
hudKeyHandled = handleGuiBar(
|
||||
(int)motionEvent.getX(i), (int)motionEvent.getY(i)
|
||||
);
|
||||
if(hudKeyHandled != -1) break;
|
||||
}
|
||||
boolean hasGuiBarHit = hudKeyHandled != -1;
|
||||
if(hasGuiBarHit && hudKeyHandled != mLastHudKey) {
|
||||
CallbackBridge.sendKeyPress(hudKeyHandled);
|
||||
// The GUI bar is handled before the gesture will be submitted, so this
|
||||
// will be resubmitted again soon (with the timer restarted)
|
||||
mDropGesture.cancel();
|
||||
mLastHudKey = hudKeyHandled;
|
||||
}
|
||||
return hasGuiBarHit;
|
||||
}
|
||||
|
||||
/** @return the hotbar key, given the position. -1 if no key are pressed */
|
||||
public int handleGuiBar(int x, int y) {
|
||||
if (!CallbackBridge.isGrabbing()) return -1;
|
||||
|
||||
int barHeight = mcScale(20);
|
||||
int barY = CallbackBridge.physicalHeight - barHeight;
|
||||
if(y < barY) return -1;
|
||||
|
||||
int barWidth = mcScale(180);
|
||||
int barX = (CallbackBridge.physicalWidth / 2) - (barWidth / 2);
|
||||
if(x < barX || x >= barX + barWidth) return -1;
|
||||
|
||||
return HOTBAR_KEYS[(int) net.kdt.pojavlaunch.utils.MathUtils.map(x, barX, barX + barWidth, 0, 9)];
|
||||
}
|
||||
|
||||
/** Return the size, given the UI scale size */
|
||||
private int mcScale(int input) {
|
||||
return (int)((mGuiScale * input)/ mScaleFactor);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user