diff --git a/app_pojavlauncher/src/main/assets/components/lwjgl3/lwjgl-glfw-classes.jar b/app_pojavlauncher/src/main/assets/components/lwjgl3/lwjgl-glfw-classes.jar index 4141a08bb..beb1da2cb 100644 Binary files a/app_pojavlauncher/src/main/assets/components/lwjgl3/lwjgl-glfw-classes.jar and b/app_pojavlauncher/src/main/assets/components/lwjgl3/lwjgl-glfw-classes.jar differ diff --git a/app_pojavlauncher/src/main/assets/components/lwjgl3/version b/app_pojavlauncher/src/main/assets/components/lwjgl3/version index a4b0232d5..f476a7b5a 100644 --- a/app_pojavlauncher/src/main/assets/components/lwjgl3/version +++ b/app_pojavlauncher/src/main/assets/components/lwjgl3/version @@ -1 +1 @@ -1732218529630 \ No newline at end of file +1735293224932 \ No newline at end of file diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLSurface.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLSurface.java index dd9f5f10f..415d13f26 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLSurface.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLSurface.java @@ -29,6 +29,7 @@ import androidx.annotation.RequiresApi; import net.kdt.pojavlaunch.customcontrols.ControlLayout; import net.kdt.pojavlaunch.customcontrols.gamepad.DefaultDataProvider; import net.kdt.pojavlaunch.customcontrols.gamepad.Gamepad; +import net.kdt.pojavlaunch.customcontrols.gamepad.direct.DirectGamepad; import net.kdt.pojavlaunch.customcontrols.mouse.AbstractTouchpad; import net.kdt.pojavlaunch.customcontrols.mouse.AndroidPointerCapture; import net.kdt.pojavlaunch.customcontrols.mouse.InGUIEventProcessor; @@ -40,6 +41,7 @@ import net.kdt.pojavlaunch.utils.MCOptionUtils; import org.lwjgl.glfw.CallbackBridge; +import fr.spse.gamepad_remapper.GamepadHandler; import fr.spse.gamepad_remapper.RemapperManager; import fr.spse.gamepad_remapper.RemapperView; @@ -48,7 +50,7 @@ import fr.spse.gamepad_remapper.RemapperView; */ public class MinecraftGLSurface extends View implements GrabListener { /* Gamepad object for gamepad inputs, instantiated on need */ - private Gamepad mGamepad = null; + private GamepadHandler mGamepadHandler; /* The RemapperView.Builder object allows you to set which buttons to remap */ private final RemapperManager mInputManager = new RemapperManager(getContext(), new RemapperView.Builder(null) .remapA(true) @@ -203,7 +205,11 @@ public class MinecraftGLSurface extends View implements GrabListener { } private void createGamepad(View contextView, InputDevice inputDevice) { - mGamepad = new Gamepad(contextView, inputDevice, DefaultDataProvider.INSTANCE, true); + if(LauncherPreferences.PREF_DIRECT_CONTROLLER) { + mGamepadHandler = new DirectGamepad(); + }else { + mGamepadHandler = new Gamepad(contextView, inputDevice, DefaultDataProvider.INSTANCE, true); + } } /** @@ -215,9 +221,9 @@ public class MinecraftGLSurface extends View implements GrabListener { int mouseCursorIndex = -1; if(Gamepad.isGamepadEvent(event)){ - if(mGamepad == null) createGamepad(this, event.getDevice()); + if(mGamepadHandler == null) createGamepad(this, event.getDevice()); - mInputManager.handleMotionEventInput(getContext(), event, mGamepad); + mInputManager.handleMotionEventInput(getContext(), event, mGamepadHandler); return true; } @@ -287,9 +293,9 @@ public class MinecraftGLSurface extends View implements GrabListener { } if(Gamepad.isGamepadEvent(event)){ - if(mGamepad == null) createGamepad(this, event.getDevice()); + if(mGamepadHandler == null) createGamepad(this, event.getDevice()); - mInputManager.handleKeyEventInput(getContext(), event, mGamepad); + mInputManager.handleKeyEventInput(getContext(), event, mGamepadHandler); return true; } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java index 49fccca08..03466a3e7 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java @@ -26,7 +26,6 @@ import androidx.core.math.MathUtils; import net.kdt.pojavlaunch.GrabListener; import net.kdt.pojavlaunch.LwjglGlfwKeycode; import net.kdt.pojavlaunch.R; -import net.kdt.pojavlaunch.prefs.LauncherPreferences; import net.kdt.pojavlaunch.utils.MCOptionUtils; import org.lwjgl.glfw.CallbackBridge; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/DirectGamepad.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/DirectGamepad.java new file mode 100644 index 000000000..2d600eec2 --- /dev/null +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/DirectGamepad.java @@ -0,0 +1,74 @@ +package net.kdt.pojavlaunch.customcontrols.gamepad.direct; + +import static android.view.MotionEvent.AXIS_HAT_X; +import static android.view.MotionEvent.AXIS_HAT_Y; +import static org.lwjgl.glfw.CallbackBridge.sGamepadAxisBuffer; +import static org.lwjgl.glfw.CallbackBridge.sGamepadButtonBuffer; + +import android.util.Log; +import android.view.KeyEvent; +import android.view.MotionEvent; + +import fr.spse.gamepad_remapper.GamepadHandler; + +public class DirectGamepad implements GamepadHandler { + @Override + public void handleGamepadInput(int keycode, float value) { + int gKeycode = -1, gAxis = -1; + switch (keycode) { + case KeyEvent.KEYCODE_BUTTON_A: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_A; break; + case KeyEvent.KEYCODE_BUTTON_B: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_B; break; + case KeyEvent.KEYCODE_BUTTON_X: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_X; break; + case KeyEvent.KEYCODE_BUTTON_Y: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_Y; break; + case KeyEvent.KEYCODE_BUTTON_L1: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER; break; + case KeyEvent.KEYCODE_BUTTON_R1: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER; break; + case KeyEvent.KEYCODE_BUTTON_L2: + case MotionEvent.AXIS_LTRIGGER: + gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER; + break; + case KeyEvent.KEYCODE_BUTTON_R2: + case MotionEvent.AXIS_RTRIGGER: + gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER; + break; + case KeyEvent.KEYCODE_BUTTON_THUMBL: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_LEFT_THUMB; break; + case KeyEvent.KEYCODE_BUTTON_THUMBR: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB; break; + case KeyEvent.KEYCODE_BUTTON_START: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_START; break; + case KeyEvent.KEYCODE_BUTTON_SELECT: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_BACK; break; + case KeyEvent.KEYCODE_DPAD_UP: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_UP; break; + case KeyEvent.KEYCODE_DPAD_DOWN: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_DOWN; break; + case KeyEvent.KEYCODE_DPAD_LEFT: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_LEFT; break; + case KeyEvent.KEYCODE_DPAD_RIGHT: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT; break; + case KeyEvent.KEYCODE_DPAD_CENTER: break; // TODO + case MotionEvent.AXIS_X: gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_LEFT_X; break; + case MotionEvent.AXIS_Y: gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_LEFT_Y; break; + case MotionEvent.AXIS_Z: gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_RIGHT_X; break; + case MotionEvent.AXIS_RZ: gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_RIGHT_Y; break; + case AXIS_HAT_X: + sGamepadButtonBuffer.put( + GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_LEFT, + value < -0.85 ? GamepadKeycodes.GLFW_PRESS : GamepadKeycodes.GLFW_RELEASE + ); + sGamepadButtonBuffer.put( + GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT, + value > 0.85 ? GamepadKeycodes.GLFW_PRESS : GamepadKeycodes.GLFW_RELEASE + ); + return; + case AXIS_HAT_Y: + sGamepadButtonBuffer.put( + GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_UP, + value < -0.85 ? GamepadKeycodes.GLFW_PRESS : GamepadKeycodes.GLFW_RELEASE + ); + sGamepadButtonBuffer.put( + GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_DOWN, + value > 0.85 ? GamepadKeycodes.GLFW_PRESS : GamepadKeycodes.GLFW_RELEASE + ); + return; + } + if(gKeycode != -1) { + sGamepadButtonBuffer.put(gKeycode, value > 0.85 ? GamepadKeycodes.GLFW_PRESS : GamepadKeycodes.GLFW_RELEASE); + } + if(gAxis != -1) { + sGamepadAxisBuffer.put(gAxis, value); + } + } +} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/GamepadKeycodes.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/GamepadKeycodes.java new file mode 100644 index 000000000..b175e3d66 --- /dev/null +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/GamepadKeycodes.java @@ -0,0 +1,36 @@ +package net.kdt.pojavlaunch.customcontrols.gamepad.direct; + +public class GamepadKeycodes { + public static final byte GLFW_RELEASE = 0; + public static final byte GLFW_PRESS = 1; + public static int NUM_KEYCODES = 0; + + public static final short GLFW_GAMEPAD_BUTTON_A = 0; + public static final short GLFW_GAMEPAD_BUTTON_B = 1; + public static final short GLFW_GAMEPAD_BUTTON_X = 2; + public static final short GLFW_GAMEPAD_BUTTON_Y = 3; + public static final short GLFW_GAMEPAD_BUTTON_LEFT_BUMPER = 4; + public static final short GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER = 5; + public static final short GLFW_GAMEPAD_BUTTON_BACK = 6; + public static final short GLFW_GAMEPAD_BUTTON_START = 7; + public static final short GLFW_GAMEPAD_BUTTON_GUIDE = 8; + public static final short GLFW_GAMEPAD_BUTTON_LEFT_THUMB = 9; + public static final short GLFW_GAMEPAD_BUTTON_RIGHT_THUMB = 10; + public static final short GLFW_GAMEPAD_BUTTON_DPAD_UP = 11; + public static final short GLFW_GAMEPAD_BUTTON_DPAD_RIGHT = 12; + public static final short GLFW_GAMEPAD_BUTTON_DPAD_DOWN = 13; + public static final short GLFW_GAMEPAD_BUTTON_DPAD_LEFT = 14; + public static final short GLFW_GAMEPAD_BUTTON_LAST = GLFW_GAMEPAD_BUTTON_DPAD_LEFT; + public static final short GLFW_GAMEPAD_BUTTON_CROSS = GLFW_GAMEPAD_BUTTON_A; + public static final short GLFW_GAMEPAD_BUTTON_CIRCLE = GLFW_GAMEPAD_BUTTON_B; + public static final short GLFW_GAMEPAD_BUTTON_SQUARE = GLFW_GAMEPAD_BUTTON_X; + public static final short GLFW_GAMEPAD_BUTTON_TRIANGLE = GLFW_GAMEPAD_BUTTON_Y; + + public static final short GLFW_GAMEPAD_AXIS_LEFT_X = 0; + public static final short GLFW_GAMEPAD_AXIS_LEFT_Y = 1; + public static final short GLFW_GAMEPAD_AXIS_RIGHT_X = 2; + public static final short GLFW_GAMEPAD_AXIS_RIGHT_Y = 3; + public static final short GLFW_GAMEPAD_AXIS_LEFT_TRIGGER = 4; + public static final short GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER = 5; + public static final short GLFW_GAMEPAD_AXIS_LAST = GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER; +} diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java index b5480596f..fa2b25461 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java @@ -67,6 +67,7 @@ public class LauncherPreferences { public static String PREF_DOWNLOAD_SOURCE = "default"; public static boolean PREF_SKIP_NOTIFICATION_PERMISSION_CHECK = false; public static boolean PREF_VSYNC_IN_ZINK = true; + public static boolean PREF_DIRECT_CONTROLLER = false; public static void loadPreferences(Context ctx) { @@ -109,6 +110,7 @@ public class LauncherPreferences { PREF_VERIFY_MANIFEST = DEFAULT_PREF.getBoolean("verifyManifest", true); PREF_SKIP_NOTIFICATION_PERMISSION_CHECK = DEFAULT_PREF.getBoolean(PREF_KEY_SKIP_NOTIFICATION_CHECK, false); PREF_VSYNC_IN_ZINK = DEFAULT_PREF.getBoolean("vsync_in_zink", true); + PREF_DIRECT_CONTROLLER = DEFAULT_PREF.getBoolean("directController", false); String argLwjglLibname = "-Dorg.lwjgl.opengl.libname="; for (String arg : JREUtils.parseJavaArguments(PREF_CUSTOM_JAVA_ARGS)) { diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceControlFragment.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceControlFragment.java index 11f34e5dc..b9ae1e60e 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceControlFragment.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceControlFragment.java @@ -89,6 +89,7 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen requirePreference("gyroInvertX").setVisible(LauncherPreferences.PREF_ENABLE_GYRO); requirePreference("gyroInvertY").setVisible(LauncherPreferences.PREF_ENABLE_GYRO); requirePreference("gyroSmoothing").setVisible(LauncherPreferences.PREF_ENABLE_GYRO); + requirePreference("_frag_changeKeyBindings").setVisible(!LauncherPreferences.PREF_DIRECT_CONTROLLER); } } diff --git a/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java b/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java index 6a2697c74..a41b5e228 100644 --- a/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java +++ b/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java @@ -8,6 +8,9 @@ import android.view.Choreographer; import androidx.annotation.Keep; import androidx.annotation.Nullable; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; import java.util.ArrayList; import dalvik.annotation.optimization.CriticalNative; @@ -27,6 +30,9 @@ public class CallbackBridge { public volatile static boolean holdingAlt, holdingCapslock, holdingCtrl, holdingNumlock, holdingShift; + public static final ByteBuffer sGamepadButtonBuffer; + public static final FloatBuffer sGamepadAxisBuffer; + public static void putMouseEventWithCoords(int button, float x, float y) { putMouseEventWithCoords(button, true, x, y); sChoreographer.postFrameCallbackDelayed(l -> putMouseEventWithCoords(button, false, x, y), 33); @@ -193,6 +199,11 @@ public class CallbackBridge { grabListeners.remove(listener); } } + public static FloatBuffer createGamepadAxisBuffer() { + ByteBuffer axisByteBuffer = nativeCreateGamepadAxisBuffer(); + // NOTE: hardcoded order (also in jre_lwjgl3glfw CallbackBridge) + return axisByteBuffer.order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer(); + } @Keep @CriticalNative public static native void nativeSetUseInputStackQueue(boolean useInputStackQueue); @@ -206,8 +217,12 @@ public class CallbackBridge { @Keep @CriticalNative private static native void nativeSendScroll(double xoffset, double yoffset); @Keep @CriticalNative private static native void nativeSendScreenSize(int width, int height); public static native void nativeSetWindowAttrib(int attrib, int value); + private static native ByteBuffer nativeCreateGamepadButtonBuffer(); + private static native ByteBuffer nativeCreateGamepadAxisBuffer(); static { System.loadLibrary("pojavexec"); + sGamepadButtonBuffer = nativeCreateGamepadButtonBuffer(); + sGamepadAxisBuffer = createGamepadAxisBuffer(); } } diff --git a/app_pojavlauncher/src/main/jni/environ/environ.h b/app_pojavlauncher/src/main/jni/environ/environ.h index fbfdb1b09..62ec4a45d 100644 --- a/app_pojavlauncher/src/main/jni/environ/environ.h +++ b/app_pojavlauncher/src/main/jni/environ/environ.h @@ -28,6 +28,11 @@ typedef void GLFW_invoke_Key_func(void* window, int key, int scancode, int actio typedef void GLFW_invoke_MouseButton_func(void* window, int button, int action, int mods); typedef void GLFW_invoke_Scroll_func(void* window, double xoffset, double yoffset); +typedef struct { + unsigned char buttons [15]; + float axes[6]; +} GLFWgamepadstate; + struct pojav_environ_s { struct ANativeWindow* pojavWindow; basic_render_window_t* mainWindowBundle; @@ -58,6 +63,7 @@ struct pojav_environ_s { bool isInputReady, isCursorEntered, isUseStackQueueCall, shouldUpdateMouse; bool shouldUpdateMonitorSize, monitorSizeConsumed; int savedWidth, savedHeight; + GLFWgamepadstate gamepadState; #define ADD_CALLBACK_WWIN(NAME) \ GLFW_invoke_##NAME##_func* GLFW_invoke_##NAME; ADD_CALLBACK_WWIN(Char); diff --git a/app_pojavlauncher/src/main/jni/input_bridge_v3.c b/app_pojavlauncher/src/main/jni/input_bridge_v3.c index 03bb79f62..3bfac1f07 100644 --- a/app_pojavlauncher/src/main/jni/input_bridge_v3.c +++ b/app_pojavlauncher/src/main/jni/input_bridge_v3.c @@ -40,9 +40,10 @@ jint JNI_OnLoad(JavaVM* vm, __attribute__((unused)) void* reserved) { //Save dalvik global JavaVM pointer pojav_environ->dalvikJavaVMPtr = vm; (*vm)->GetEnv(vm, (void**) &pojav_environ->dalvikJNIEnvPtr_ANDROID, JNI_VERSION_1_4); - pojav_environ->bridgeClazz = (*pojav_environ->dalvikJNIEnvPtr_ANDROID)->NewGlobalRef(pojav_environ->dalvikJNIEnvPtr_ANDROID,(*pojav_environ->dalvikJNIEnvPtr_ANDROID) ->FindClass(pojav_environ->dalvikJNIEnvPtr_ANDROID,"org/lwjgl/glfw/CallbackBridge")); - pojav_environ->method_accessAndroidClipboard = (*pojav_environ->dalvikJNIEnvPtr_ANDROID)->GetStaticMethodID(pojav_environ->dalvikJNIEnvPtr_ANDROID, pojav_environ->bridgeClazz, "accessAndroidClipboard", "(ILjava/lang/String;)Ljava/lang/String;"); - pojav_environ->method_onGrabStateChanged = (*pojav_environ->dalvikJNIEnvPtr_ANDROID)->GetStaticMethodID(pojav_environ->dalvikJNIEnvPtr_ANDROID, pojav_environ->bridgeClazz, "onGrabStateChanged", "(Z)V"); + JNIEnv *env = pojav_environ->dalvikJNIEnvPtr_ANDROID; + pojav_environ->bridgeClazz = (*env)->NewGlobalRef(env,(*env) ->FindClass(env,"org/lwjgl/glfw/CallbackBridge")); + pojav_environ->method_accessAndroidClipboard = (*env)->GetStaticMethodID(env, pojav_environ->bridgeClazz, "accessAndroidClipboard", "(ILjava/lang/String;)Ljava/lang/String;"); + pojav_environ->method_onGrabStateChanged = (*env)->GetStaticMethodID(env, pojav_environ->bridgeClazz, "onGrabStateChanged", "(Z)V"); pojav_environ->isUseStackQueueCall = JNI_FALSE; } else if (pojav_environ->dalvikJavaVMPtr != vm) { __android_log_print(ANDROID_LOG_INFO, "Native", "Saving JVM environ..."); @@ -644,3 +645,18 @@ static void registerFunctions(JNIEnv *env) { use_critical_cc ? critical_fcns : noncritical_fcns, sizeof(critical_fcns)/sizeof(critical_fcns[0])); } + +JNIEXPORT jlong JNICALL +Java_org_lwjgl_glfw_GLFW_internalGetGamepadDataPointer(JNIEnv *env, jclass clazz) { + return (jlong) &pojav_environ->gamepadState; +} + +JNIEXPORT jobject JNICALL +Java_org_lwjgl_glfw_CallbackBridge_nativeCreateGamepadButtonBuffer(JNIEnv *env, jclass clazz) { + return (*env)->NewDirectByteBuffer(env, &pojav_environ->gamepadState.buttons, sizeof(pojav_environ->gamepadState.buttons)); +} + +JNIEXPORT jobject JNICALL +Java_org_lwjgl_glfw_CallbackBridge_nativeCreateGamepadAxisBuffer(JNIEnv *env, jclass clazz) { + return (*env)->NewDirectByteBuffer(env, &pojav_environ->gamepadState.axes, sizeof(pojav_environ->gamepadState.axes)); +} \ No newline at end of file diff --git a/app_pojavlauncher/src/main/res/values/strings.xml b/app_pojavlauncher/src/main/res/values/strings.xml index 91104432d..2aff163bf 100644 --- a/app_pojavlauncher/src/main/res/values/strings.xml +++ b/app_pojavlauncher/src/main/res/values/strings.xml @@ -422,4 +422,6 @@ Unsuitable username The username must be between 3–16 characters long, and must only contain latin letters, arabic numerals and underscores. Quick settings + Use direct controller input + Disables keyboard/mouse emulation and lets the game use gamepad inputs directly. diff --git a/app_pojavlauncher/src/main/res/xml/pref_control.xml b/app_pojavlauncher/src/main/res/xml/pref_control.xml index 0d2778e17..cd0093bce 100644 --- a/app_pojavlauncher/src/main/res/xml/pref_control.xml +++ b/app_pojavlauncher/src/main/res/xml/pref_control.xml @@ -144,7 +144,13 @@ + diff --git a/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/CallbackBridge.java b/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/CallbackBridge.java index 74b923867..17d25e203 100644 --- a/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/CallbackBridge.java +++ b/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/CallbackBridge.java @@ -1,4 +1,5 @@ package org.lwjgl.glfw; +import java.nio.ByteBuffer; import java.util.*; public class CallbackBridge { @@ -47,5 +48,7 @@ public class CallbackBridge { public static native boolean nativeSetInputReady(boolean ready); public static native String nativeClipboard(int action, byte[] copy); public static native void nativeSetGrabbing(boolean grab); + public static native ByteBuffer nativeCreateGamepadButtonBuffer(); + public static native ByteBuffer nativeCreateGamepadAxisBuffer(); } diff --git a/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java b/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java index 53ea33596..b878cb149 100644 --- a/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java +++ b/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java @@ -13,6 +13,7 @@ import javax.annotation.*; import org.lwjgl.*; import org.lwjgl.system.*; +import org.lwjgl.system.MemoryUtil; import static org.lwjgl.opengl.GL20.*; import static org.lwjgl.system.APIUtil.*; @@ -24,8 +25,9 @@ import java.util.*; public class GLFW { - static FloatBuffer joystickData = (FloatBuffer)FloatBuffer.allocate(8).flip(); - static ByteBuffer buttonData = (ByteBuffer)ByteBuffer.allocate(8).flip(); + static FloatBuffer joystickAxisData; + static ByteBuffer joystickButtonData; + static ByteBuffer empty = (ByteBuffer)ByteBuffer.allocate(0); /** The major version number of the GLFW library. This is incremented when the API is changed in non-compatible ways. */ public static final int GLFW_VERSION_MAJOR = 3; @@ -515,6 +517,7 @@ public class GLFW private static final String PROP_WINDOW_WIDTH = "glfwstub.windowWidth"; private static final String PROP_WINDOW_HEIGHT= "glfwstub.windowHeight"; public static long mainContext = 0; + private static long gamepadDataPointer; static { try { @@ -636,6 +639,8 @@ public class GLFW return win; } + private static native long internalGetGamepadDataPointer(); + // Generated stub callback methods public static GLFWCharCallback glfwSetCharCallback(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("GLFWcharfun") GLFWCharCallbackI cbfun) { GLFWCharCallback lastCallback = mGLFWCharCallback; @@ -805,6 +810,10 @@ public class GLFW mGLFWInitialTime = (double) System.nanoTime(); long __functionAddress = Functions.Init; isGLFWReady = invokeI(__functionAddress) != 0; + gamepadDataPointer = internalGetGamepadDataPointer(); + // NOTE: hardcoded order (also in android CallbackBridge) + joystickAxisData = CallbackBridge.nativeCreateGamepadAxisBuffer().order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer(); + joystickButtonData = CallbackBridge.nativeCreateGamepadButtonBuffer(); } return isGLFWReady; } @@ -1201,50 +1210,59 @@ public class GLFW } public static boolean glfwJoystickPresent(int jid) { - if(jid == 0) { + if(jid == GLFW_JOYSTICK_1) { return true; }else return false; } public static String glfwGetJoystickName(int jid) { - if(jid == 0) { - return "AIC event bus controller"; + if(jid == GLFW_JOYSTICK_1) { + return "Pojav XBOX 360 compatible gamepad"; }else return null; } public static FloatBuffer glfwGetJoystickAxes(int jid) { - if(jid == 0) { - return joystickData; + if(jid == GLFW_JOYSTICK_1) { + return joystickAxisData; }else return null; } public static ByteBuffer glfwGetJoystickButtons(int jid) { - if(jid == 0) { - return buttonData; + if(jid == GLFW_JOYSTICK_1) { + return joystickButtonData; }else return null; } - public static ByteBuffer glfwGetjoystickHats(int jid) { - return null; + public static ByteBuffer glfwGetJoystickHats(int jid) { + if(jid == GLFW_JOYSTICK_1) { + return empty; // Maybe implement this later? + }else return null; } public static boolean glfwJoystickIsGamepad(int jid) { - if(jid == 0) return true; + if(jid == GLFW_JOYSTICK_1) return true; else return false; } public static String glfwGetJoystickGUID(int jid) { - if(jid == 0) return "aio0"; + // 16 8-bit characters to be compatible with SDL_GUID + if(jid == GLFW_JOYSTICK_1) return "AAAAAAAAAAAAAAAA"; else return null; } + + private static long mUserPointer; + public static long glfwGetJoystickUserPointer(int jid) { - return 0; + return mUserPointer; } public static void glfwSetJoystickUserPointer(int jid, long pointer) { - + mUserPointer = pointer; } public static boolean glfwUpdateGamepadMappings(ByteBuffer string) { return false; } public static String glfwGetGamepadName(int jid) { - return null; + if(jid == GLFW_JOYSTICK_1) return "Pojav XBOX 360 compatible gamepad"; + else return null; } public static boolean glfwGetGamepadState(int jid, GLFWGamepadState state) { - return false; + if(jid != 0) return false; + MemoryUtil.memCopy(gamepadDataPointer, state.address(), state.sizeof()); + return true; } /** Array version of: {@link #glfwGetVersion GetVersion} */