From 2755cc535256ac0578962d42b680e6f170a66caa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E6=88=98?= <40414978+PatriceJiang@users.noreply.github.com> Date: Wed, 22 Mar 2023 14:40:31 +0800 Subject: [PATCH] fix android controller (#339) --- sources/CMakeLists.txt | 1 + .../include/game-activity/GameActivity.cpp | 322 ++++++++++++------ .../include/game-activity/GameActivity.h | 15 +- .../include/game-activity/system_utils.cpp | 72 ++++ .../include/game-activity/system_utils.h | 32 ++ .../GameControllerGameActivityMirror.h | 1 + 6 files changed, 328 insertions(+), 115 deletions(-) create mode 100644 sources/android-gamesdk/GameActivity/game-activity/include/game-activity/system_utils.cpp create mode 100644 sources/android-gamesdk/GameActivity/game-activity/include/game-activity/system_utils.h diff --git a/sources/CMakeLists.txt b/sources/CMakeLists.txt index 7c1488d9..8c4308b4 100644 --- a/sources/CMakeLists.txt +++ b/sources/CMakeLists.txt @@ -57,6 +57,7 @@ endif() if(ANDROID) set(CC_GAME_ACTIVITY_SOURCES ${CMAKE_CURRENT_LIST_DIR}/android-gamesdk/GameActivity/game-activity/include/game-activity/GameActivity.cpp + ${CMAKE_CURRENT_LIST_DIR}/android-gamesdk/GameActivity/game-activity/include/game-activity/system_utils.cpp ${CMAKE_CURRENT_LIST_DIR}/android-gamesdk/GameActivity/game-activity/include/game-activity/native_app_glue/android_native_app_glue.c ${CMAKE_CURRENT_LIST_DIR}/android-gamesdk/GameActivity/game-activity/include/game-text-input/gametextinput.cpp ) diff --git a/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/GameActivity.cpp b/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/GameActivity.cpp index 130ea518..2a5ef017 100644 --- a/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/GameActivity.cpp +++ b/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/GameActivity.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "GameActivity" #include "GameActivity.h" +#include "system_utils.h" #include #include @@ -870,138 +871,119 @@ static struct { jmethodID getClassification; jmethodID getEdgeFlags; + jmethodID getHistorySize; + jmethodID getHistoricalEventTime; + jmethodID getPointerCount; jmethodID getPointerId; + + jmethodID getToolType; + jmethodID getRawX; jmethodID getRawY; jmethodID getXPrecision; jmethodID getYPrecision; jmethodID getAxisValue; + + jmethodID getHistoricalAxisValue; } gMotionEventClassInfo; +extern "C" void GameActivityMotionEvent_destroy( + GameActivityMotionEvent *c_event) { + delete c_event->historicalAxisValues; + delete c_event->historicalEventTimesMillis; + delete c_event->historicalEventTimesNanos; +} + extern "C" void GameActivityMotionEvent_fromJava( - JNIEnv *env, jobject motionEvent, GameActivityMotionEvent *out_event) { - static bool gMotionEventClassInfoInitialized = false; - if (!gMotionEventClassInfoInitialized) { - int sdkVersion = GetSystemPropAsInt("ro.build.version.sdk"); - gMotionEventClassInfo = {0}; - jclass motionEventClass = env->FindClass("android/view/MotionEvent"); - gMotionEventClassInfo.getDeviceId = - env->GetMethodID(motionEventClass, "getDeviceId", "()I"); - gMotionEventClassInfo.getSource = - env->GetMethodID(motionEventClass, "getSource", "()I"); - gMotionEventClassInfo.getAction = - env->GetMethodID(motionEventClass, "getAction", "()I"); - gMotionEventClassInfo.getEventTime = - env->GetMethodID(motionEventClass, "getEventTime", "()J"); - gMotionEventClassInfo.getDownTime = - env->GetMethodID(motionEventClass, "getDownTime", "()J"); - gMotionEventClassInfo.getFlags = - env->GetMethodID(motionEventClass, "getFlags", "()I"); - gMotionEventClassInfo.getMetaState = - env->GetMethodID(motionEventClass, "getMetaState", "()I"); - if (sdkVersion >= 23) { - gMotionEventClassInfo.getActionButton = - env->GetMethodID(motionEventClass, "getActionButton", "()I"); - } - if (sdkVersion >= 14) { - gMotionEventClassInfo.getButtonState = - env->GetMethodID(motionEventClass, "getButtonState", "()I"); - } - if (sdkVersion >= 29) { - gMotionEventClassInfo.getClassification = - env->GetMethodID(motionEventClass, "getClassification", "()I"); - } - gMotionEventClassInfo.getEdgeFlags = - env->GetMethodID(motionEventClass, "getEdgeFlags", "()I"); - gMotionEventClassInfo.getPointerCount = - env->GetMethodID(motionEventClass, "getPointerCount", "()I"); - gMotionEventClassInfo.getPointerId = - env->GetMethodID(motionEventClass, "getPointerId", "(I)I"); - if (sdkVersion >= 29) { - gMotionEventClassInfo.getRawX = - env->GetMethodID(motionEventClass, "getRawX", "(I)F"); - gMotionEventClassInfo.getRawY = - env->GetMethodID(motionEventClass, "getRawY", "(I)F"); - } - gMotionEventClassInfo.getXPrecision = - env->GetMethodID(motionEventClass, "getXPrecision", "()F"); - gMotionEventClassInfo.getYPrecision = - env->GetMethodID(motionEventClass, "getYPrecision", "()F"); - gMotionEventClassInfo.getAxisValue = - env->GetMethodID(motionEventClass, "getAxisValue", "(II)F"); - - gMotionEventClassInfoInitialized = true; - } - - int pointerCount = - env->CallIntMethod(motionEvent, gMotionEventClassInfo.getPointerCount); + JNIEnv *env, jobject motionEvent, GameActivityMotionEvent *out_event, + int pointerCount, int historySize, int deviceId, int source, int action, + int64_t eventTime, int64_t downTime, int flags, int metaState, + int actionButton, int buttonState, int classification, int edgeFlags, + float precisionX, float precisionY) { pointerCount = - std::min(pointerCount, GAMEACTIVITY_MAX_NUM_POINTERS_IN_MOTION_EVENT); + std::min(pointerCount, GAMEACTIVITY_MAX_NUM_POINTERS_IN_MOTION_EVENT); out_event->pointerCount = pointerCount; - for (int i = 0; i < pointerCount; ++i) { + for (jint i = 0; i < pointerCount; ++i) { out_event->pointers[i] = { - /*id=*/env->CallIntMethod(motionEvent, - gMotionEventClassInfo.getPointerId, i), - /*axisValues=*/{0}, - /*rawX=*/gMotionEventClassInfo.getRawX - ? env->CallFloatMethod(motionEvent, - gMotionEventClassInfo.getRawX, i) - : 0, - /*rawY=*/gMotionEventClassInfo.getRawY - ? env->CallFloatMethod(motionEvent, - gMotionEventClassInfo.getRawY, i) - : 0, + /*id=*/env->CallIntMethod(motionEvent, + gMotionEventClassInfo.getPointerId, i), + /*toolType=*/ + env->CallIntMethod(motionEvent, gMotionEventClassInfo.getToolType, + i), + /*axisValues=*/{0.0F}, + /*rawX=*/gMotionEventClassInfo.getRawX + ? env->CallFloatMethod(motionEvent, + gMotionEventClassInfo.getRawX, i) + : 0.0F, + /*rawY=*/gMotionEventClassInfo.getRawY + ? env->CallFloatMethod(motionEvent, + gMotionEventClassInfo.getRawY, i) + : 0.0F, }; for (int axisIndex = 0; axisIndex < GAME_ACTIVITY_POINTER_INFO_AXIS_COUNT; ++axisIndex) { if (enabledAxes[axisIndex]) { out_event->pointers[i].axisValues[axisIndex] = - env->CallFloatMethod(motionEvent, - gMotionEventClassInfo.getAxisValue, - axisIndex, i); + env->CallFloatMethod(motionEvent, + gMotionEventClassInfo.getAxisValue, + axisIndex, i); } } } - out_event->deviceId = - env->CallIntMethod(motionEvent, gMotionEventClassInfo.getDeviceId); - out_event->source = - env->CallIntMethod(motionEvent, gMotionEventClassInfo.getSource); - out_event->action = - env->CallIntMethod(motionEvent, gMotionEventClassInfo.getAction); - out_event->eventTime = - env->CallLongMethod(motionEvent, gMotionEventClassInfo.getEventTime) * - 1000000; - out_event->downTime = - env->CallLongMethod(motionEvent, gMotionEventClassInfo.getDownTime) * - 1000000; - out_event->flags = - env->CallIntMethod(motionEvent, gMotionEventClassInfo.getFlags); - out_event->metaState = - env->CallIntMethod(motionEvent, gMotionEventClassInfo.getMetaState); - out_event->actionButton = - gMotionEventClassInfo.getActionButton - ? env->CallIntMethod(motionEvent, - gMotionEventClassInfo.getActionButton) - : 0; - out_event->buttonState = - gMotionEventClassInfo.getButtonState - ? env->CallIntMethod(motionEvent, - gMotionEventClassInfo.getButtonState) - : 0; - out_event->classification = - gMotionEventClassInfo.getClassification - ? env->CallIntMethod(motionEvent, - gMotionEventClassInfo.getClassification) - : 0; - out_event->edgeFlags = - env->CallIntMethod(motionEvent, gMotionEventClassInfo.getEdgeFlags); - out_event->precisionX = - env->CallFloatMethod(motionEvent, gMotionEventClassInfo.getXPrecision); - out_event->precisionY = - env->CallFloatMethod(motionEvent, gMotionEventClassInfo.getYPrecision); + out_event->historySize = historySize; + out_event->historicalAxisValues = + new float[historySize * pointerCount * + GAME_ACTIVITY_POINTER_INFO_AXIS_COUNT]; + out_event->historicalEventTimesMillis = new long[historySize]; + out_event->historicalEventTimesNanos = new long[historySize]; + + for (int historyIndex = 0; historyIndex < historySize; historyIndex++) { + out_event->historicalEventTimesMillis[historyIndex] = + env->CallLongMethod(motionEvent, + gMotionEventClassInfo.getHistoricalEventTime, + historyIndex); + out_event->historicalEventTimesNanos[historyIndex] = + out_event->historicalEventTimesMillis[historyIndex] * 1000000; + for (int i = 0; i < pointerCount; ++i) { + int pointerOffset = i * GAME_ACTIVITY_POINTER_INFO_AXIS_COUNT; + int historyAxisOffset = historyIndex * pointerCount * + GAME_ACTIVITY_POINTER_INFO_AXIS_COUNT; + float *axisValues = + &out_event + ->historicalAxisValues[historyAxisOffset + pointerOffset]; + for (int axisIndex = 0; + axisIndex < GAME_ACTIVITY_POINTER_INFO_AXIS_COUNT; + ++axisIndex) { + if (enabledAxes[axisIndex]) { + axisValues[axisIndex] = env->CallFloatMethod( + motionEvent, + gMotionEventClassInfo.getHistoricalAxisValue, axisIndex, + i, historyIndex); + } + } + } + } + + out_event->deviceId = deviceId; + out_event->source = source; + out_event->action = action; + + out_event->eventTime = eventTime; + out_event->downTime = downTime; + + out_event->flags = flags; + out_event->metaState = metaState; + + out_event->actionButton = actionButton; + out_event->buttonState = buttonState; + out_event->classification = classification; + out_event->edgeFlags = edgeFlags; + + out_event->precisionX = precisionX; + out_event->precisionY = precisionY; } static struct { @@ -1018,6 +1000,8 @@ static struct { jmethodID getModifiers; jmethodID getRepeatCount; jmethodID getKeyCode; + jmethodID getScanCode; + jmethodID getUnicodeChar; } gKeyEventClassInfo; extern "C" void GameActivityKeyEvent_fromJava(JNIEnv *env, jobject keyEvent, @@ -1077,14 +1061,25 @@ extern "C" void GameActivityKeyEvent_fromJava(JNIEnv *env, jobject keyEvent, } static bool onTouchEvent_native(JNIEnv *env, jobject javaGameActivity, - jlong handle, jobject motionEvent) { + jlong handle, jobject motionEvent, + int pointerCount, int historySize, int deviceId, + int source, int action, int64_t eventTime, + int64_t downTime, int flags, int metaState, + int actionButton, int buttonState, + int classification, int edgeFlags, + float precisionX, float precisionY) { if (handle == 0) return false; NativeCode *code = (NativeCode *)handle; if (code->callbacks.onTouchEvent == nullptr) return false; static GameActivityMotionEvent c_event; - GameActivityMotionEvent_fromJava(env, motionEvent, &c_event); - return code->callbacks.onTouchEvent(code, &c_event); + GameActivityMotionEvent_fromJava( + env, motionEvent, &c_event, pointerCount, historySize, deviceId, source, + action, eventTime, downTime, flags, metaState, actionButton, + buttonState, classification, edgeFlags, precisionX, precisionY); + auto result = code->callbacks.onTouchEvent(code, &c_event); + GameActivityMotionEvent_destroy(&c_event); + return result; } static bool onKeyUp_native(JNIEnv *env, jobject javaGameActivity, jlong handle, @@ -1184,7 +1179,7 @@ static const JNINativeMethod g_methods[] = { {"onSurfaceRedrawNeededNative", "(JLandroid/view/Surface;)V", (void *)onSurfaceRedrawNeeded_native}, {"onSurfaceDestroyedNative", "(J)V", (void *)onSurfaceDestroyed_native}, - {"onTouchEventNative", "(JLandroid/view/MotionEvent;)Z", + {"onTouchEventNative", "(JLandroid/view/MotionEvent;IIIIIJJIIIIIIFF)Z", (void *)onTouchEvent_native}, {"onKeyDownNative", "(JLandroid/view/KeyEvent;)Z", (void *)onKeyDown_native}, @@ -1247,6 +1242,104 @@ static int jniRegisterNativeMethods(JNIEnv *env, const char *className, LOG_FATAL("RegisterNatives failed for '%s'; aborting...", className); } +static void initKeyEvents(JNIEnv *env) { + int sdkVersion = gamesdk::GetSystemPropAsInt("ro.build.version.sdk"); + gKeyEventClassInfo = {0}; + jclass keyEventClass = env->FindClass("android/view/KeyEvent"); + gKeyEventClassInfo.getDeviceId = + env->GetMethodID(keyEventClass, "getDeviceId", "()I"); + gKeyEventClassInfo.getSource = + env->GetMethodID(keyEventClass, "getSource", "()I"); + gKeyEventClassInfo.getAction = + env->GetMethodID(keyEventClass, "getAction", "()I"); + gKeyEventClassInfo.getEventTime = + env->GetMethodID(keyEventClass, "getEventTime", "()J"); + gKeyEventClassInfo.getDownTime = + env->GetMethodID(keyEventClass, "getDownTime", "()J"); + gKeyEventClassInfo.getFlags = + env->GetMethodID(keyEventClass, "getFlags", "()I"); + gKeyEventClassInfo.getMetaState = + env->GetMethodID(keyEventClass, "getMetaState", "()I"); + if (sdkVersion >= 13) { + gKeyEventClassInfo.getModifiers = + env->GetMethodID(keyEventClass, "getModifiers", "()I"); + } + gKeyEventClassInfo.getRepeatCount = + env->GetMethodID(keyEventClass, "getRepeatCount", "()I"); + gKeyEventClassInfo.getKeyCode = + env->GetMethodID(keyEventClass, "getKeyCode", "()I"); + gKeyEventClassInfo.getScanCode = + env->GetMethodID(keyEventClass, "getScanCode", "()I"); + gKeyEventClassInfo.getUnicodeChar = + env->GetMethodID(keyEventClass, "getUnicodeChar", "()I"); +} + +static void initMotionEvents(JNIEnv *env) { + int sdkVersion = gamesdk::GetSystemPropAsInt("ro.build.version.sdk"); + gMotionEventClassInfo = {0}; + jclass motionEventClass = env->FindClass("android/view/MotionEvent"); + gMotionEventClassInfo.getDeviceId = + env->GetMethodID(motionEventClass, "getDeviceId", "()I"); + gMotionEventClassInfo.getSource = + env->GetMethodID(motionEventClass, "getSource", "()I"); + gMotionEventClassInfo.getAction = + env->GetMethodID(motionEventClass, "getAction", "()I"); + gMotionEventClassInfo.getEventTime = + env->GetMethodID(motionEventClass, "getEventTime", "()J"); + gMotionEventClassInfo.getDownTime = + env->GetMethodID(motionEventClass, "getDownTime", "()J"); + gMotionEventClassInfo.getFlags = + env->GetMethodID(motionEventClass, "getFlags", "()I"); + gMotionEventClassInfo.getMetaState = + env->GetMethodID(motionEventClass, "getMetaState", "()I"); + if (sdkVersion >= 23) { + gMotionEventClassInfo.getActionButton = + env->GetMethodID(motionEventClass, "getActionButton", "()I"); + } + if (sdkVersion >= 14) { + gMotionEventClassInfo.getButtonState = + env->GetMethodID(motionEventClass, "getButtonState", "()I"); + } + if (sdkVersion >= 29) { + gMotionEventClassInfo.getClassification = + env->GetMethodID(motionEventClass, "getClassification", "()I"); + } + gMotionEventClassInfo.getEdgeFlags = + env->GetMethodID(motionEventClass, "getEdgeFlags", "()I"); + + gMotionEventClassInfo.getHistorySize = + env->GetMethodID(motionEventClass, "getHistorySize", "()I"); + gMotionEventClassInfo.getHistoricalEventTime = + env->GetMethodID(motionEventClass, "getHistoricalEventTime", "(I)J"); + + gMotionEventClassInfo.getPointerCount = + env->GetMethodID(motionEventClass, "getPointerCount", "()I"); + gMotionEventClassInfo.getPointerId = + env->GetMethodID(motionEventClass, "getPointerId", "(I)I"); + gMotionEventClassInfo.getToolType = + env->GetMethodID(motionEventClass, "getToolType", "(I)I"); + if (sdkVersion >= 29) { + gMotionEventClassInfo.getRawX = + env->GetMethodID(motionEventClass, "getRawX", "(I)F"); + gMotionEventClassInfo.getRawY = + env->GetMethodID(motionEventClass, "getRawY", "(I)F"); + } + gMotionEventClassInfo.getXPrecision = + env->GetMethodID(motionEventClass, "getXPrecision", "()F"); + gMotionEventClassInfo.getYPrecision = + env->GetMethodID(motionEventClass, "getYPrecision", "()F"); + gMotionEventClassInfo.getAxisValue = + env->GetMethodID(motionEventClass, "getAxisValue", "(II)F"); + + gMotionEventClassInfo.getHistoricalAxisValue = + env->GetMethodID(motionEventClass, "getHistoricalAxisValue", "(III)F"); +} + +static void GameActivityEventsInit(JNIEnv *env) { + initMotionEvents(env); + initKeyEvents(env); +} + extern "C" int GameActivity_register(JNIEnv *env) { ALOGD("GameActivity_register"); jclass activity_class; @@ -1289,6 +1382,9 @@ extern "C" int GameActivity_register(JNIEnv *env) { windowInsetsCompatType_class, methodNames[i], "()I"); }*/ + + GameActivityEventsInit(env); + return jniRegisterNativeMethods(env, kGameActivityPathName, g_methods, NELEM(g_methods)); } diff --git a/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/GameActivity.h b/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/GameActivity.h index da102bcb..495f32e1 100644 --- a/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/GameActivity.h +++ b/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/GameActivity.h @@ -137,6 +137,7 @@ typedef struct GameActivity { */ typedef struct GameActivityPointerAxes { int32_t id; + int32_t toolType; float axisValues[GAME_ACTIVITY_POINTER_INFO_AXIS_COUNT]; float rawX; float rawY; @@ -240,6 +241,12 @@ typedef struct GameActivityMotionEvent { float precisionX; float precisionY; + + int historySize; + long* historicalEventTimesMillis; + long* historicalEventTimesNanos; + float* historicalAxisValues; + } GameActivityMotionEvent; /** @@ -421,8 +428,12 @@ typedef struct GameActivityCallbacks { * activity. * Ownership of out_event is maintained by the caller. */ -void GameActivityMotionEvent_fromJava(JNIEnv* env, jobject motionEvent, - GameActivityMotionEvent* out_event); +void GameActivityMotionEvent_fromJava( + JNIEnv *env, jobject motionEvent, GameActivityMotionEvent *out_event, + int pointerCount, int historySize, int deviceId, int source, int action, + int64_t eventTime, int64_t downTime, int flags, int metaState, + int actionButton, int buttonState, int classification, int edgeFlags, + float precisionX, float precisionY); /** * \brief Convert a Java `KeyEvent` to a `GameActivityKeyEvent`. diff --git a/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/system_utils.cpp b/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/system_utils.cpp new file mode 100644 index 00000000..efc5b743 --- /dev/null +++ b/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/system_utils.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "system_utils.h" + +#include +#include +#include + +namespace gamesdk { + +#if __ANDROID_API__ >= 26 +std::string getSystemPropViaCallback(const char* key, + const char* default_value = "") { + const prop_info* prop = __system_property_find(key); + if (prop == nullptr) { + return default_value; + } + std::string return_value; + auto thunk = [](void* cookie, const char* /*name*/, const char* value, + uint32_t /*serial*/) { + if (value != nullptr) { + std::string* r = static_cast(cookie); + *r = value; + } + }; + __system_property_read_callback(prop, thunk, &return_value); + return return_value; +} +#else +std::string getSystemPropViaGet(const char* key, + const char* default_value = "") { + char buffer[PROP_VALUE_MAX + 1] = ""; // +1 for terminator + int bufferLen = __system_property_get(key, buffer); + if (bufferLen > 0) + return buffer; + else + return ""; +} +#endif + +std::string GetSystemProp(const char* key, const char* default_value) { +#if __ANDROID_API__ >= 26 + return getSystemPropViaCallback(key, default_value); +#else + return getSystemPropViaGet(key, default_value); +#endif +} + +int GetSystemPropAsInt(const char* key, int default_value) { + std::string prop = GetSystemProp(key); + return prop == "" ? default_value : strtoll(prop.c_str(), nullptr, 10); +} + +bool GetSystemPropAsBool(const char* key, bool default_value) { + return GetSystemPropAsInt(key, default_value) != 0; +} + +} // namespace gamesdk \ No newline at end of file diff --git a/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/system_utils.h b/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/system_utils.h new file mode 100644 index 00000000..488374bc --- /dev/null +++ b/sources/android-gamesdk/GameActivity/game-activity/include/game-activity/system_utils.h @@ -0,0 +1,32 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "string" + +namespace gamesdk { + +// Get the value of the given system property +std::string GetSystemProp(const char* key, const char* default_value = ""); + +// Get the value of the given system property as an integer +int GetSystemPropAsInt(const char* key, int default_value = 0); + +// Get the value of the given system property as a bool +bool GetSystemPropAsBool(const char* key, bool default_value = false); + +} // namespace gamesdk \ No newline at end of file diff --git a/sources/android-gamesdk/GameController/GameControllerGameActivityMirror.h b/sources/android-gamesdk/GameController/GameControllerGameActivityMirror.h index 74d3f0f3..cb73435e 100644 --- a/sources/android-gamesdk/GameController/GameControllerGameActivityMirror.h +++ b/sources/android-gamesdk/GameController/GameControllerGameActivityMirror.h @@ -33,6 +33,7 @@ namespace paddleboat { typedef struct Paddleboat_GameActivityPointerInfo { int32_t id; + int32_t toolType; // added in newer version float axisValues[PADDLEBOAT_GAME_ACTIVITY_POINTER_INFO_AXIS_COUNT]; float rawX; float rawY;