Compare commits

...
2 Commits
Author SHA1 Message Date
Chloe 915e232011 redo controller api 2025-12-16 23:28:48 -07:00
Chloe cf4cd8335e my attempt 2 2025-09-20 17:41:40 -07:00
4 changed files with 436 additions and 27 deletions

No files matched your search

+4
View File
@@ -22,6 +22,7 @@
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.LIGHTS" />
<uses-feature <uses-feature
android:name="android.hardware.wifi" android:name="android.hardware.wifi"
@@ -29,6 +30,9 @@
<uses-feature <uses-feature
android:glEsVersion="0x00020000" android:glEsVersion="0x00020000"
android:required="true" /> android:required="true" />
<uses-feature
android:name="android.hardware.gamepad"
android:required="false" />
<application <application
android:allowBackup="true" android:allowBackup="true"
@@ -588,8 +588,8 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
mGLSurfaceView?.sendTimestampEvents = true mGLSurfaceView?.sendTimestampEvents = true
true true
} }
GeodeUtils.CAPABILITY_INTERNAL_CALLBACKS -> { GeodeUtils.CAPABILITY_RICH_INPUT -> {
mGLSurfaceView?.sendInternalTimestampEvents = true mGLSurfaceView?.enableControllerEvents()
true true
} }
else -> false else -> false
@@ -7,6 +7,9 @@ import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.hardware.lights.Light
import android.hardware.lights.LightState
import android.hardware.lights.LightsRequest
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Environment import android.os.Environment
@@ -16,6 +19,7 @@ import android.os.VibratorManager
import android.provider.DocumentsContract import android.provider.DocumentsContract
import android.provider.Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION import android.provider.Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
import android.util.Log import android.util.Log
import android.view.InputDevice
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
@@ -546,7 +550,7 @@ object GeodeUtils {
const val CAPABILITY_EXTENDED_INPUT = "extended_input" const val CAPABILITY_EXTENDED_INPUT = "extended_input"
const val CAPABILITY_TIMESTAMP_INPUT = "timestamp_inputs" const val CAPABILITY_TIMESTAMP_INPUT = "timestamp_inputs"
const val CAPABILITY_INTERNAL_CALLBACKS = "internal_callbacks_v1" const val CAPABILITY_RICH_INPUT = "internal_callbacks_v2"
private var capabilityListener: WeakReference<CapabilityListener?> = WeakReference(null) private var capabilityListener: WeakReference<CapabilityListener?> = WeakReference(null)
@@ -576,6 +580,188 @@ object GeodeUtils {
.launchUrl(activity, url.toUri()) .launchUrl(activity, url.toUri())
} }
/**
* Determines if any gamepad or joystick input devices are connected.
* This is useful during start, but tracking inputDeviceAdded events is better during runtime.
*/
@JvmStatic
fun controllersConnected(): Int {
val deviceIds = InputDevice.getDeviceIds()
return deviceIds.count {
InputDevice.getDevice(it)?.run {
sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD || sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
} ?: false
}
}
@JvmStatic
fun getConnectedDevices(): IntArray = InputDevice.getDeviceIds()
@JvmStatic
fun getDevice(deviceId: Int): InputDevice? = InputDevice.getDevice(deviceId)
@JvmStatic
fun getDeviceBatteryCapacity(deviceId: Int): Float {
val device = InputDevice.getDevice(deviceId) ?: return 0.0f
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
device.batteryState.capacity
} else {
0.0f
}
}
@JvmStatic
fun deviceHasBattery(deviceId: Int): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
return false
}
val device = InputDevice.getDevice(deviceId) ?: return false
return device.batteryState.isPresent
}
@JvmStatic
fun getDeviceBatteryStatus(deviceId: Int): Int {
val device = InputDevice.getDevice(deviceId) ?: return 0
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
device.batteryState.status
} else {
0
}
}
@JvmStatic
fun getDeviceLightsCount(deviceId: Int): Int {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
return 0
}
val device = InputDevice.getDevice(deviceId) ?: return 0
val lightsManager = device.lightsManager
return lightsManager.lights.size
}
// this is based on paddleboat's api
@JvmStatic
fun getLightType(deviceId: Int): Int {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
return 0
}
val device = InputDevice.getDevice(deviceId) ?: return 0
val lightsManager = device.lightsManager
var flags = 0
lightsManager.lights.forEach { light ->
if (light.type == Light.LIGHT_TYPE_PLAYER_ID) {
flags = flags or 1
} else if (light.hasRgbControl()) {
flags = flags or 2
}
}
return flags
}
/**
* Sets the color for a device.
* @return false if the given device does not exist or setting lights was otherwise unsuccessful
*/
@JvmStatic
fun setDeviceLightColor(deviceId: Int, color: Int, type: Int): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
return false
}
val device = InputDevice.getDevice(deviceId) ?: return false
val lightsManager = device.lightsManager
val lights = lightsManager.lights
if (lights.isEmpty()) {
return false
}
val actedLights = lights.count { light ->
val state = LightState.Builder()
if (light.type == Light.LIGHT_TYPE_PLAYER_ID && (type and 1 == 1)) {
state.setPlayerId(color)
} else if (light.hasRgbControl() && (type and 2 == 2)) {
state.setColor(color)
} else {
return@count false
}
val request = LightsRequest.Builder()
.addLight(light, state.build())
.build()
lightsManager.openSession()
.requestLights(request)
true
}
return actedLights > 0
}
@JvmStatic
fun getDeviceHapticsCount(deviceId: Int): Int {
val device = InputDevice.getDevice(deviceId) ?: return 0
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
return if (device.vibrator.hasVibrator()) 1 else 0
}
val vibratorManager = device.vibratorManager
val vibratorIds = vibratorManager.vibratorIds
return vibratorIds.size
}
private fun performVibration(vibrator: Vibrator?, durationMs: Long, intensity: Int) {
vibrator?.apply {
if (intensity == 0) {
cancel()
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val vibrationEffect = VibrationEffect.createOneShot(durationMs, intensity)
vibrate(vibrationEffect)
} else {
vibrate(durationMs)
}
}
}
}
/**
* Vibrates a given device. Set motorIdx == -1 to vibrate all available motors on a device.
*/
@JvmStatic
fun vibrateDevice(deviceId: Int, durationMs: Long, intensity: Int, motorIdx: Int): Boolean {
val device = InputDevice.getDevice(deviceId) ?: return false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val vibratorManager = device.vibratorManager
val vibratorIds = vibratorManager.vibratorIds
if (motorIdx == -1) {
vibratorIds.forEach {
val vibrator = vibratorManager.getVibrator(it)
performVibration(vibrator, durationMs, intensity)
}
} else {
val deviceId = vibratorIds.getOrNull(motorIdx) ?: return false
val vibrator = vibratorManager.getVibrator(deviceId)
performVibration(vibrator, durationMs, intensity)
}
} else {
val vibrator = device.vibrator
performVibration(vibrator, durationMs, intensity)
}
return true
}
external fun nativeKeyUp(keyCode: Int, modifiers: Int) external fun nativeKeyUp(keyCode: Int, modifiers: Int)
external fun nativeKeyDown(keyCode: Int, modifiers: Int, isRepeating: Boolean) external fun nativeKeyDown(keyCode: Int, modifiers: Int, isRepeating: Boolean)
external fun nativeActionScroll(scrollX: Float, scrollY: Float) external fun nativeActionScroll(scrollX: Float, scrollY: Float)
@@ -587,5 +773,18 @@ object GeodeUtils {
* @see reportPlatformCapability * @see reportPlatformCapability
*/ */
external fun setNextInputTimestamp(timestamp: Long) external fun setNextInputTimestamp(timestamp: Long)
external fun setNextInputTimestampInternal(timestamp: Long)
const val TOUCH_TYPE_BEGIN = 0
const val TOUCH_TYPE_MOVE = 1
const val TOUCH_TYPE_END = 2
const val TOUCH_TYPE_CANCEL = 3
external fun internalKeyEvent(timestamp: Long, deviceId: Int, eventSource: Int, keyCode: Int, modifiers: Int, isDown: Boolean, repeatCount: Int)
external fun internalTouchEvent(timestamp: Long, deviceId: Int, eventSource: Int, eventType: Int, ids: IntArray, xs: FloatArray, ys: FloatArray)
external fun internalScrollEvent(timestamp: Long, deviceId: Int, eventSource: Int, scrollX: Float, scrollY: Float)
external fun internalJoystickEvent(timestamp: Long, deviceId: Int, eventSource: Int, leftX: FloatArray, leftY: FloatArray, rightX: FloatArray, rightY: FloatArray, hatX: FloatArray, hatY: FloatArray, leftTrigger: FloatArray, rightTrigger: FloatArray)
external fun inputDeviceAdded(deviceId: Int)
external fun inputDeviceChanged(deviceId: Int)
external fun inputDeviceRemoved(deviceId: Int)
} }
@@ -2,12 +2,14 @@ package org.cocos2dx.lib
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.hardware.input.InputManager
import android.opengl.GLSurfaceView import android.opengl.GLSurfaceView
import android.os.Build import android.os.Build
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.os.Message import android.os.Message
import android.util.Log import android.util.Log
import android.view.InputDevice
import android.view.KeyEvent import android.view.KeyEvent
import android.view.MotionEvent import android.view.MotionEvent
import android.view.Surface import android.view.Surface
@@ -16,6 +18,7 @@ import androidx.annotation.RequiresApi
import androidx.appcompat.widget.AppCompatEditText import androidx.appcompat.widget.AppCompatEditText
import com.customRobTop.BaseRobTopActivity import com.customRobTop.BaseRobTopActivity
import com.geode.launcher.utils.GeodeUtils import com.geode.launcher.utils.GeodeUtils
import kotlin.math.abs
private const val HANDLER_OPEN_IME_KEYBOARD = 2 private const val HANDLER_OPEN_IME_KEYBOARD = 2
private const val HANDLER_CLOSE_IME_KEYBOARD = 3 private const val HANDLER_CLOSE_IME_KEYBOARD = 3
@@ -56,8 +59,9 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
} }
var sendTimestampEvents = false var sendTimestampEvents = false
var sendInternalTimestampEvents = false
var manualBackEvents = false var manualBackEvents = false
var controllerEventsEnabled = false
private set
var cocos2dxEditText: AppCompatEditText? = null var cocos2dxEditText: AppCompatEditText? = null
set(value) { set(value) {
@@ -154,9 +158,6 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
private fun sendNextEventTimestamp(timestamp: Long) { private fun sendNextEventTimestamp(timestamp: Long) {
if (sendTimestampEvents) if (sendTimestampEvents)
GeodeUtils.setNextInputTimestamp(timestamp) GeodeUtils.setNextInputTimestamp(timestamp)
if (sendInternalTimestampEvents)
GeodeUtils.setNextInputTimestampInternal(timestamp)
} }
override fun onTouchEvent(motionEvent: MotionEvent): Boolean { override fun onTouchEvent(motionEvent: MotionEvent): Boolean {
@@ -179,7 +180,15 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
val f = ys[0] val f = ys[0]
queueEvent { queueEvent {
sendNextEventTimestamp(timestamp) sendNextEventTimestamp(timestamp)
cocos2dxRenderer.handleActionDown(idDown, xDown, f)
if (controllerEventsEnabled)
GeodeUtils.internalTouchEvent(
timestamp, motionEvent.deviceId, motionEvent.source,
// slice here to convert to single element array
GeodeUtils.TOUCH_TYPE_BEGIN, ids.sliceArray(0..0), xs.sliceArray(0..0), ys.sliceArray(0..0)
)
else
cocos2dxRenderer.handleActionDown(idDown, xDown, f)
} }
true true
} }
@@ -189,21 +198,42 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
val f3 = ys[0] val f3 = ys[0]
queueEvent { queueEvent {
sendNextEventTimestamp(timestamp) sendNextEventTimestamp(timestamp)
cocos2dxRenderer.handleActionUp(idUp, f2, f3)
if (controllerEventsEnabled)
GeodeUtils.internalTouchEvent(
timestamp, motionEvent.deviceId, motionEvent.source,
GeodeUtils.TOUCH_TYPE_END, ids.sliceArray(0..0), xs.sliceArray(0..0), ys.sliceArray(0..0)
)
else
cocos2dxRenderer.handleActionUp(idUp, f2, f3)
} }
true true
} }
MotionEvent.ACTION_MOVE -> { MotionEvent.ACTION_MOVE -> {
queueEvent { queueEvent {
sendNextEventTimestamp(timestamp) sendNextEventTimestamp(timestamp)
cocos2dxRenderer.handleActionMove(ids, xs, ys)
if (controllerEventsEnabled)
GeodeUtils.internalTouchEvent(
timestamp, motionEvent.deviceId, motionEvent.source,
GeodeUtils.TOUCH_TYPE_MOVE, ids, xs, ys
)
else
cocos2dxRenderer.handleActionMove(ids, xs, ys)
} }
true true
} }
MotionEvent.ACTION_CANCEL -> { MotionEvent.ACTION_CANCEL -> {
queueEvent { queueEvent {
sendNextEventTimestamp(timestamp) sendNextEventTimestamp(timestamp)
cocos2dxRenderer.handleActionCancel(ids, xs, ys)
if (controllerEventsEnabled)
GeodeUtils.internalTouchEvent(
timestamp, motionEvent.deviceId, motionEvent.source,
GeodeUtils.TOUCH_TYPE_CANCEL, ids, xs, ys
)
else
cocos2dxRenderer.handleActionCancel(ids, xs, ys)
} }
true true
} }
@@ -214,7 +244,14 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
val y = motionEvent.getY(indexPointerDown) val y = motionEvent.getY(indexPointerDown)
queueEvent { queueEvent {
sendNextEventTimestamp(timestamp) sendNextEventTimestamp(timestamp)
cocos2dxRenderer.handleActionDown(idPointerDown, xPointerDown, y)
if (controllerEventsEnabled)
GeodeUtils.internalTouchEvent(
timestamp, motionEvent.deviceId, motionEvent.source,
GeodeUtils.TOUCH_TYPE_BEGIN, intArrayOf(idPointerDown), floatArrayOf(xPointerDown), floatArrayOf(y)
)
else
cocos2dxRenderer.handleActionDown(idPointerDown, xPointerDown, y)
} }
true true
} }
@@ -225,7 +262,14 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
val y2 = motionEvent.getY(indexPointUp) val y2 = motionEvent.getY(indexPointUp)
queueEvent { queueEvent {
sendNextEventTimestamp(timestamp) sendNextEventTimestamp(timestamp)
cocos2dxRenderer.handleActionUp(idPointerUp, xPointerUp, y2)
if (controllerEventsEnabled)
GeodeUtils.internalTouchEvent(
timestamp, motionEvent.deviceId, motionEvent.source,
GeodeUtils.TOUCH_TYPE_END, intArrayOf(idPointerUp), floatArrayOf(xPointerUp), floatArrayOf(y2)
)
else
cocos2dxRenderer.handleActionUp(idPointerUp, xPointerUp, y2)
} }
true true
} }
@@ -266,21 +310,42 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
return return
} }
if (useKeyboardEvents) { val currentTime = System.nanoTime()
queueEvent { queueEvent {
cocos2dxRenderer.handleKeyDown(KeyEvent.KEYCODE_BACK) sendNextEventTimestamp(currentTime)
if (controllerEventsEnabled) {
GeodeUtils.internalKeyEvent(
currentTime,
-1,
InputDevice.SOURCE_ANY,
KeyEvent.KEYCODE_BACK,
0,
true,
0
)
GeodeUtils.internalKeyEvent(
currentTime,
-1,
InputDevice.SOURCE_ANY,
KeyEvent.KEYCODE_BACK,
0,
false,
0
)
} }
} else {
val currentTime = System.nanoTime() if (useKeyboardEvents) {
queueEvent {
sendNextEventTimestamp(currentTime)
GeodeUtils.nativeKeyDown(KeyEvent.KEYCODE_BACK, 0, false) GeodeUtils.nativeKeyDown(KeyEvent.KEYCODE_BACK, 0, false)
GeodeUtils.nativeKeyUp(KeyEvent.KEYCODE_BACK, 0)
} else if (!controllerEventsEnabled) {
cocos2dxRenderer.handleKeyDown(KeyEvent.KEYCODE_BACK)
} }
} }
} }
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (!useKeyboardEvents) { if (!useKeyboardEvents && !controllerEventsEnabled) {
return legacyKeyDown(keyCode, event) return legacyKeyDown(keyCode, event)
} }
@@ -296,7 +361,14 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
queueEvent { queueEvent {
sendNextEventTimestamp(event.eventTime * MS_TO_NS) sendNextEventTimestamp(event.eventTime * MS_TO_NS)
GeodeUtils.nativeKeyDown(keyCode, event.modifiers, event.repeatCount != 0)
if (useKeyboardEvents) {
GeodeUtils.nativeKeyDown(keyCode, event.modifiers, event.repeatCount != 0)
}
if (controllerEventsEnabled) {
GeodeUtils.internalKeyEvent(event.eventTime * MS_TO_NS, event.deviceId, event.source, event.keyCode, event.modifiers, true, event.repeatCount)
}
} }
true true
} }
@@ -304,7 +376,7 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
} }
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
if (!useKeyboardEvents) { if (!useKeyboardEvents && !controllerEventsEnabled) {
return super.onKeyUp(keyCode, event) return super.onKeyUp(keyCode, event)
} }
@@ -319,7 +391,14 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
queueEvent { queueEvent {
sendNextEventTimestamp(event.eventTime * MS_TO_NS) sendNextEventTimestamp(event.eventTime * MS_TO_NS)
GeodeUtils.nativeKeyUp(keyCode, event.modifiers)
if (useKeyboardEvents) {
GeodeUtils.nativeKeyUp(keyCode, event.modifiers)
}
if (controllerEventsEnabled) {
GeodeUtils.internalKeyEvent(event.eventTime * MS_TO_NS, event.deviceId, event.source, event.keyCode, event.modifiers, false, event.repeatCount)
}
} }
true true
@@ -327,8 +406,67 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
} }
} }
// i'm lazy.
// https://developer.android.com/develop/ui/views/touch-and-input/game-controllers/controller-input
private fun getCenteredAxis(
event: MotionEvent,
device: InputDevice,
axis: Int,
historyPos: Int
): Float {
device.getMotionRange(axis, event.source)?.apply {
val value: Float = if (historyPos < 0) {
event.getAxisValue(axis)
} else {
event.getHistoricalAxisValue(axis, historyPos)
}
if (abs(value) > flat) {
return value
}
}
return 0.0f
}
private fun getJoystickMotion(event: MotionEvent, axisHorizontal: Int, axisVertical: Int): Pair<FloatArray, FloatArray> {
val positionChangesX = ArrayList<Float>()
val positionChangesY = ArrayList<Float>()
val inputDevice = event.device
(0 until event.historySize).forEach { i ->
val x = getCenteredAxis(event, inputDevice, axisHorizontal, i)
val y = getCenteredAxis(event, inputDevice, axisVertical, i)
positionChangesX.add(x)
positionChangesY.add(y)
}
val x = getCenteredAxis(event, inputDevice, axisHorizontal, -1)
val y = getCenteredAxis(event, inputDevice, axisVertical, -1)
positionChangesX.add(x)
positionChangesY.add(y)
return Pair(positionChangesX.toFloatArray(), positionChangesY.toFloatArray())
}
private fun getJoystickMotion(event: MotionEvent, axis: Int): FloatArray {
val positionChanges = ArrayList<Float>()
val inputDevice = event.device
(0 until event.historySize).forEach { i ->
val x = getCenteredAxis(event, inputDevice, axis, i)
positionChanges.add(x)
}
val x = getCenteredAxis(event, inputDevice, axis, -1)
positionChanges.add(x)
return positionChanges.toFloatArray()
}
override fun onGenericMotionEvent(event: MotionEvent?): Boolean { override fun onGenericMotionEvent(event: MotionEvent?): Boolean {
if (!useKeyboardEvents) { if (!useKeyboardEvents && !controllerEventsEnabled) {
return super.onGenericMotionEvent(event) return super.onGenericMotionEvent(event)
} }
@@ -340,7 +478,39 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
queueEvent { queueEvent {
sendNextEventTimestamp(timestamp) sendNextEventTimestamp(timestamp)
GeodeUtils.nativeActionScroll(scrollX, scrollY)
if (useKeyboardEvents) {
GeodeUtils.nativeActionScroll(scrollX, scrollY)
}
if (controllerEventsEnabled) {
GeodeUtils.internalScrollEvent(timestamp, event.deviceId, event.source, scrollX, scrollY)
}
}
return true
}
if (controllerEventsEnabled && event?.action == MotionEvent.ACTION_MOVE && event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK) {
val (motionLeftX, motionLeftY) = getJoystickMotion(event, MotionEvent.AXIS_X, MotionEvent.AXIS_Y)
val (motionRightX, motionRightY) = getJoystickMotion(event, MotionEvent.AXIS_Z, MotionEvent.AXIS_RZ)
val (motionDPadX, motionDPadY) = getJoystickMotion(event, MotionEvent.AXIS_HAT_X, MotionEvent.AXIS_HAT_Y)
val motionLTrigger = getJoystickMotion(event, MotionEvent.AXIS_LTRIGGER)
val motionRTrigger = getJoystickMotion(event, MotionEvent.AXIS_RTRIGGER)
// i'm sure this is great for performance
val timestamp = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
event.eventTimeNanos else event.eventTime * MS_TO_NS
queueEvent {
GeodeUtils.internalJoystickEvent(
timestamp, event.deviceId, event.source,
motionLeftX, motionLeftY,
motionRightX, motionRightY,
motionDPadX, motionDPadY,
motionLTrigger, motionRTrigger
)
} }
return true return true
@@ -365,4 +535,40 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
fun deleteBackward() { fun deleteBackward() {
queueEvent { cocos2dxRenderer.handleDeleteBackward() } queueEvent { cocos2dxRenderer.handleDeleteBackward() }
} }
fun enableControllerEvents() {
if (controllerEventsEnabled) {
return
}
controllerEventsEnabled = true
val inputManager = context.getSystemService(Context.INPUT_SERVICE) as InputManager
inputManager.registerInputDeviceListener(InputListener, null)
}
fun disableControllerEvents() {
if (!controllerEventsEnabled) {
return
}
controllerEventsEnabled = true
val inputManager = context.getSystemService(Context.INPUT_SERVICE) as InputManager
inputManager.unregisterInputDeviceListener(InputListener)
}
object InputListener : InputManager.InputDeviceListener {
override fun onInputDeviceAdded(deviceId: Int) {
GeodeUtils.inputDeviceAdded(deviceId)
}
override fun onInputDeviceChanged(deviceId: Int) {
GeodeUtils.inputDeviceChanged(deviceId)
}
override fun onInputDeviceRemoved(deviceId: Int) {
GeodeUtils.inputDeviceRemoved(deviceId)
}
}
} }