mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2025-09-13 06:39:54 -04:00
Feat[input]: Minecraft hotbar as a View
This commit is contained in:
parent
781341eafd
commit
6bac7ee10b
@ -75,7 +75,7 @@ public class MinecraftGLSurface extends View implements GrabListener {
|
||||
/* View holding the surface, either a SurfaceView or a TextureView */
|
||||
View mSurface;
|
||||
|
||||
private final TouchEventProcessor mIngameProcessor = new InGameEventProcessor(mScaleFactor, mSensitivityFactor);
|
||||
private final TouchEventProcessor mIngameProcessor = new InGameEventProcessor(mSensitivityFactor);
|
||||
private final TouchEventProcessor mInGUIProcessor = new InGUIEventProcessor(mScaleFactor);
|
||||
private boolean mLastGrabState = false;
|
||||
|
||||
|
@ -15,12 +15,11 @@ public class DropGesture implements Runnable{
|
||||
this.mHandler = mHandler;
|
||||
}
|
||||
|
||||
public void submit(boolean hasGuiBarHit) {
|
||||
if(hasGuiBarHit && !mActive) {
|
||||
public void submit() {
|
||||
if(!mActive) {
|
||||
mActive = true;
|
||||
mHandler.postDelayed(this, LauncherPreferences.PREF_LONGPRESS_TRIGGER);
|
||||
}
|
||||
if(!hasGuiBarHit && mActive) cancel();
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
|
@ -1,114 +0,0 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.mouse;
|
||||
|
||||
import static net.kdt.pojavlaunch.utils.MCOptionUtils.getMcScale;
|
||||
|
||||
import android.os.Handler;
|
||||
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;
|
||||
|
||||
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, boolean hasDoubleTapped) {
|
||||
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, hasDoubleTapped);
|
||||
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, hasDoubleTapped);
|
||||
mDropGesture.submit(true);
|
||||
}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, boolean hasDoubleTapped) {
|
||||
if(hasDoubleTapped && !LauncherPreferences.PREF_DISABLE_SWAP_HAND) {
|
||||
CallbackBridge.sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_F);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package net.kdt.pojavlaunch.customcontrols.mouse;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.kdt.pojavlaunch.LwjglGlfwKeycode;
|
||||
import net.kdt.pojavlaunch.TapDetector;
|
||||
import net.kdt.pojavlaunch.Tools;
|
||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||
import net.kdt.pojavlaunch.utils.MCOptionUtils;
|
||||
import net.kdt.pojavlaunch.utils.MathUtils;
|
||||
|
||||
import org.lwjgl.glfw.CallbackBridge;
|
||||
|
||||
public class HotbarView extends View implements MCOptionUtils.MCOptionListener, View.OnLayoutChangeListener, Runnable {
|
||||
private final TapDetector mDoubleTapDetector = new TapDetector(2, TapDetector.DETECTION_METHOD_DOWN);
|
||||
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 final DropGesture mDropGesture = new DropGesture(new Handler(Looper.getMainLooper()));
|
||||
private final float mScaleFactor = LauncherPreferences.PREF_SCALE_FACTOR/100f;
|
||||
private int mWidth;
|
||||
private int mLastIndex;
|
||||
private int mGuiScale;
|
||||
|
||||
public HotbarView(Context context) {
|
||||
super(context);
|
||||
initialize();
|
||||
}
|
||||
|
||||
public HotbarView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initialize();
|
||||
}
|
||||
|
||||
public HotbarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
initialize();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused") // You suggested me this constructor, Android
|
||||
public HotbarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
MCOptionUtils.addMCOptionListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
ViewParent parent = getParent();
|
||||
if(parent == null) return;
|
||||
if(parent instanceof View) {
|
||||
View parentView = (View) parent;
|
||||
parentView.addOnLayoutChangeListener(this);
|
||||
}
|
||||
mGuiScale = MCOptionUtils.getMcScale();
|
||||
repositionView();
|
||||
}
|
||||
|
||||
private void repositionView() {
|
||||
ViewGroup.LayoutParams layoutParams = getLayoutParams();
|
||||
if(!(layoutParams instanceof ViewGroup.MarginLayoutParams))
|
||||
throw new RuntimeException("Incorrect LayoutParams type, expected ViewGroup.MarginLayoutParams");
|
||||
ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) layoutParams;
|
||||
int height;
|
||||
marginLayoutParams.width = mWidth = mcScale(180);
|
||||
marginLayoutParams.height = height = mcScale(20);
|
||||
marginLayoutParams.leftMargin = (CallbackBridge.physicalWidth / 2) - (mWidth / 2);
|
||||
marginLayoutParams.topMargin = CallbackBridge.physicalHeight - height;
|
||||
setLayoutParams(marginLayoutParams);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ClickableViewAccessibility") // performClick does not report coordinates.
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if(!CallbackBridge.isGrabbing()) return false;
|
||||
// Check if we are double-tapping to swap hands
|
||||
boolean hasDoubleTapped = mDoubleTapDetector.onTouchEvent(event);
|
||||
if(hasDoubleTapped && !LauncherPreferences.PREF_DISABLE_SWAP_HAND) CallbackBridge.sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_F);
|
||||
|
||||
// Check if we need to cancel the drop event
|
||||
int actionMasked = event.getActionMasked();
|
||||
if(isLastEventInGesture(actionMasked)) cancelDropGesture();
|
||||
else submitDropGesture();
|
||||
// Determine the hotbar slot
|
||||
float x = event.getX();
|
||||
if(x < 0 || x > mWidth) return true;
|
||||
int hotbarIndex = (int)MathUtils.map(x, 0, mWidth, 0, HOTBAR_KEYS.length);
|
||||
// Check if the slot changed and we need to make a key press
|
||||
if(hotbarIndex == mLastIndex) return true;
|
||||
mLastIndex = hotbarIndex;
|
||||
int hotbarKey = HOTBAR_KEYS[hotbarIndex];
|
||||
CallbackBridge.sendKeyPress(hotbarKey);
|
||||
// Cancel the event since we changed hotbar slots.
|
||||
cancelDropGesture();
|
||||
// Only resubmit the gesture only if it isn't the last event we will receive.
|
||||
if(!isLastEventInGesture(actionMasked)) submitDropGesture();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void submitDropGesture() {
|
||||
if(LauncherPreferences.PREF_DISABLE_GESTURES) return;
|
||||
mDropGesture.submit();
|
||||
}
|
||||
|
||||
private void cancelDropGesture() {
|
||||
if(LauncherPreferences.PREF_DISABLE_GESTURES) return;
|
||||
mDropGesture.cancel();
|
||||
}
|
||||
|
||||
private boolean isLastEventInGesture(int actionMasked) {
|
||||
return actionMasked == MotionEvent.ACTION_UP || actionMasked == MotionEvent.ACTION_CANCEL;
|
||||
}
|
||||
|
||||
private int mcScale(int input) {
|
||||
return (int)((mGuiScale * input)/ mScaleFactor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOptionChanged() {
|
||||
Tools.runOnUiThread(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if(getParent() == null) return;
|
||||
int scale = MCOptionUtils.getMcScale();
|
||||
if(scale == mGuiScale) return;
|
||||
mGuiScale = scale;
|
||||
repositionView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
|
||||
repositionView();
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import net.kdt.pojavlaunch.TapDetector;
|
||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||
|
||||
import org.lwjgl.glfw.CallbackBridge;
|
||||
@ -13,34 +12,24 @@ public class InGameEventProcessor implements TouchEventProcessor {
|
||||
private final Handler mGestureHandler = new Handler(Looper.getMainLooper());
|
||||
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 TapDetector mDoubleTapDetector = new TapDetector(2, TapDetector.DETECTION_METHOD_DOWN);
|
||||
|
||||
public InGameEventProcessor(float scaleFactor, double sensitivity) {
|
||||
mGuiBarTracker = new HotbarTracker(mGestureHandler, scaleFactor);
|
||||
public InGameEventProcessor(double sensitivity) {
|
||||
mSensitivity = sensitivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processTouchEvent(MotionEvent motionEvent) {
|
||||
boolean hasDoubleTapped = mDoubleTapDetector.onTouchEvent(motionEvent);
|
||||
switch (motionEvent.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if(mGuiBarTracker.begin(motionEvent, hasDoubleTapped)) break;
|
||||
mTracker.startTracking(motionEvent);
|
||||
if(LauncherPreferences.PREF_DISABLE_GESTURES) break;
|
||||
checkGestures();
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
mGuiBarTracker.begin(motionEvent, hasDoubleTapped);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
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;
|
||||
mTracker.trackEvent(motionEvent);
|
||||
if(LauncherPreferences.PREF_DISABLE_GESTURES) break;
|
||||
checkGestures();
|
||||
float[] motionVector = mTracker.getMotionVector();
|
||||
CallbackBridge.mouseX += motionVector[0] * mSensitivity;
|
||||
@ -49,7 +38,6 @@ public class InGameEventProcessor implements TouchEventProcessor {
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
mGuiBarTracker.cancel();
|
||||
mTracker.cancelTracking();
|
||||
cancelGestures(false);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class PointerTracker {
|
||||
public int trackEvent(MotionEvent motionEvent) {
|
||||
int trackedPointerIndex = motionEvent.findPointerIndex(mTrackedPointerId);
|
||||
int pointerCount = motionEvent.getPointerCount();
|
||||
if(trackedPointerIndex == -1 || mPointerCount != pointerCount || mColdStart) {
|
||||
if(trackedPointerIndex == -1 || mPointerCount != pointerCount || mColdStart) {
|
||||
startTracking(motionEvent);
|
||||
trackedPointerIndex = 0;
|
||||
}
|
||||
|
@ -51,6 +51,9 @@
|
||||
android:layout_height="12dp"
|
||||
android:elevation="10dp"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
<net.kdt.pojavlaunch.customcontrols.mouse.HotbarView
|
||||
android:layout_width="0px"
|
||||
android:layout_height="0px"/>
|
||||
|
||||
</net.kdt.pojavlaunch.customcontrols.ControlLayout>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user