[Scummvm-git-logs] scummvm master -> 64eb1c0afe0bd8af9cf331b8ec62c0c6eee927d2
antoniou79
a.antoniou79 at gmail.com
Sat Oct 24 23:30:42 UTC 2020
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
64eb1c0afe ANDROID: A tentative handling of handling joystick control
Commit: 64eb1c0afe0bd8af9cf331b8ec62c0c6eee927d2
https://github.com/scummvm/scummvm/commit/64eb1c0afe0bd8af9cf331b8ec62c0c6eee927d2
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-10-25T02:30:32+03:00
Commit Message:
ANDROID: A tentative handling of handling joystick control
Basically as a virtual mouse
Changed paths:
backends/platform/android/android.cpp
backends/platform/android/android.h
backends/platform/android/events.cpp
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
backends/platform/android/org/scummvm/scummvm/ScummVMEventsBase.java
backends/platform/android/org/scummvm/scummvm/ScummVMEventsModern.java
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 37757bf4ae..69e014e500 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -499,6 +499,24 @@ bool OSystem_Android::getFeatureState(Feature f) {
}
}
+// TODO Re-eval if we need this here
+Common::HardwareInputSet *OSystem_Android::getHardwareInputSet() {
+ using namespace Common;
+
+ CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
+ inputSet->addHardwareInputSet(new MouseHardwareInputSet(defaultMouseButtons));
+ inputSet->addHardwareInputSet(new KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
+ inputSet->addHardwareInputSet(new JoystickHardwareInputSet(defaultJoystickButtons, defaultJoystickAxes));
+
+ return inputSet;
+}
+
+// TODO Re-eval if we need this here
+Common::KeymapArray OSystem_Android::getGlobalKeymaps() {
+ Common::KeymapArray globalMaps = BaseBackend::getGlobalKeymaps();
+ return globalMaps;
+}
+
Common::KeymapperDefaultBindings *OSystem_Android::getKeymapperDefaultBindings() {
Common::KeymapperDefaultBindings *keymapperDefaultBindings = new Common::KeymapperDefaultBindings();
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index fcd6a89f9a..4dcaea07bc 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -115,6 +115,8 @@ private:
public:
virtual bool pollEvent(Common::Event &event) override;
+ virtual Common::HardwareInputSet *getHardwareInputSet() override;
+ virtual Common::KeymapArray getGlobalKeymaps() override;
virtual Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() override;
virtual uint32 getMillis(bool skipRecord = false) override;
diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp
index 42e6045c0a..2a4972e9cb 100644
--- a/backends/platform/android/events.cpp
+++ b/backends/platform/android/events.cpp
@@ -902,22 +902,65 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
break;
case JE_JOYSTICK:
- e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
switch (arg1) {
+ // AMOTION_EVENT_ACTION_MOVE is 2 in NDK (https://developer.android.com/ndk/reference/group/input)
case AMOTION_EVENT_ACTION_MOVE:
+ e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
e.type = Common::EVENT_MOUSEMOVE;
// already multiplied by 100
e.mouse.x += arg2 * _joystick_scale / _eventScaleX;
e.mouse.y += arg3 * _joystick_scale / _eventScaleY;
+ break;
+ case AKEY_EVENT_ACTION_DOWN:
+ e.type = Common::EVENT_KEYDOWN;
+ break;
+ case AKEY_EVENT_ACTION_UP:
+ e.type = Common::EVENT_KEYUP;
break;
default:
LOGE("unhandled jaction on joystick: %d", arg1);
return;
}
+ if (arg1 != AMOTION_EVENT_ACTION_MOVE) {
+ switch (arg2) {
+ case AKEYCODE_BUTTON_1:
+ case AKEYCODE_BUTTON_2:
+ switch (arg1) {
+ case AKEY_EVENT_ACTION_DOWN:
+ e.type = (arg2 == AKEYCODE_BUTTON_1?
+ Common::EVENT_LBUTTONDOWN :
+ Common::EVENT_RBUTTONDOWN);
+ break;
+ case AKEY_EVENT_ACTION_UP:
+ e.type = (arg2 == AKEYCODE_BUTTON_1?
+ Common::EVENT_LBUTTONUP :
+ Common::EVENT_RBUTTONUP);
+ break;
+ }
+
+ e.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
+
+ break;
+
+ case AKEYCODE_BUTTON_3:
+ e.kbd.keycode = Common::KEYCODE_ESCAPE;
+ e.kbd.ascii = Common::ASCII_ESCAPE;
+ break;
+
+ case AKEYCODE_BUTTON_4:
+ e.type = Common::EVENT_MAINMENU;
+ break;
+
+ default:
+ LOGW("unmapped gamepad key: %d", arg2);
+ return;
+ }
+ }
+
pushEvent(e);
return;
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 86901e12f0..ee9453aa8a 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -404,6 +404,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
public void onText(CharSequence p1) {}
+ // TODO - "Swipe" behavior does not seem to work currently. Should we support it?
public void swipeLeft() {
//Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeLeft");
}
@@ -451,7 +452,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
_screenKeyboard = builtinKeyboard;
// TODO better to have specific dimensions in dp and not adjusted to parent
// it may resolve the issue of resizing the keyboard wrongly (smaller) when returning to the suspended Activity in low resolution
- FrameLayout.LayoutParams sKeyboardLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL | Gravity.FILL_HORIZONTAL);
+ FrameLayout.LayoutParams sKeyboardLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
_videoLayout.addView(_screenKeyboard, sKeyboardLayout);
_videoLayout.bringChildToFront(_screenKeyboard);
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMEventsBase.java b/backends/platform/android/org/scummvm/scummvm/ScummVMEventsBase.java
index 9080829ff4..79b1ab2c8f 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMEventsBase.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMEventsBase.java
@@ -4,7 +4,6 @@ import android.os.Handler;
import android.os.Message;
import android.content.Context;
//import android.util.Log;
-import android.util.Log;
import android.view.KeyEvent;
import android.view.KeyCharacterMap;
import android.view.MotionEvent;
@@ -328,6 +327,13 @@ public class ScummVMEventsBase implements
case KeyEvent.KEYCODE_BUTTON_MODE:
type = JE_GAMEPAD;
break;
+ case KeyEvent.KEYCODE_BUTTON_1:
+ case KeyEvent.KEYCODE_BUTTON_2:
+ case KeyEvent.KEYCODE_BUTTON_3:
+ case KeyEvent.KEYCODE_BUTTON_4:
+ // These are oddly detected with SOURCE_KEYBOARD for joystick so don't bother checking the e.getSource()
+ type = JE_JOYSTICK;
+ break;
default:
if (e.isSystem()) {
type = JE_SYS_KEY;
@@ -337,7 +343,7 @@ public class ScummVMEventsBase implements
break;
}
-// _scummvm.displayMessageOnOSD("GetKey: " + keyCode + " unic=" + eventUnicodeChar+ " arg3= " + (eventUnicodeChar& KeyCharacterMap.COMBINING_ACCENT_MASK));
+ //_scummvm.displayMessageOnOSD("GetKey: " + keyCode + " unic=" + eventUnicodeChar+ " arg3= " + (eventUnicodeChar& KeyCharacterMap.COMBINING_ACCENT_MASK));
// look in events.cpp for how this is handled
_scummvm.pushEvent(type,
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMEventsModern.java b/backends/platform/android/org/scummvm/scummvm/ScummVMEventsModern.java
index ccaf7e1167..5ea0e42c9d 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMEventsModern.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMEventsModern.java
@@ -1,26 +1,202 @@
package org.scummvm.scummvm;
import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.InputDevice;
+import androidx.annotation.NonNull;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
// A class that extends the basic ScummVMEventsBase, supporting Android APIs > HONEYCOMB_MR1 (API 12)
public class ScummVMEventsModern extends ScummVMEventsBase {
+ private static final int MSG_REPEAT = 3;
+ private static final int REPEAT_INTERVAL = 20; // ~50 keys per second
+ private static final int REPEAT_START_DELAY = 40;
+
public ScummVMEventsModern(Context context, ScummVM scummvm, MouseHelper mouseHelper) {
super(context, scummvm, mouseHelper);
}
+ // Custom handler code (to avoid mem leaks, see warning "This Handler Class Should Be Static Or Leaks Might Occurâ) based on:
+ // https://stackoverflow.com/a/27826094
+ public static class ScummVMEventsModernHandler extends Handler {
+
+ private final WeakReference<ScummVMEventsModern> mListenerReference;
+
+ public ScummVMEventsModernHandler(ScummVMEventsModern listener) {
+ mListenerReference = new WeakReference<>(listener);
+ }
+
+ @Override
+ public synchronized void handleMessage(@NonNull Message msg) {
+ ScummVMEventsModern listener = mListenerReference.get();
+ if(listener != null) {
+ switch (msg.what) {
+ case MSG_REPEAT:
+ if (listener.repeatMove()) {
+ Message repeat = Message.obtain(this, MSG_REPEAT);
+ sendMessageDelayed(repeat, REPEAT_INTERVAL);
+ }
+ break;
+ }
+ }
+ }
+
+ public void clear() {
+ this.removeCallbacksAndMessages(null);
+ }
+ }
+
@Override
- public boolean onGenericMotionEvent(MotionEvent e) {
- if ((e.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
- _scummvm.pushEvent(JE_JOYSTICK, e.getAction(),
- (int)(e.getAxisValue(MotionEvent.AXIS_X)*100),
- (int)(e.getAxisValue(MotionEvent.AXIS_Y)*100),
- 0, 0, 0);
- return true;
+ public void clearEventHandler() {
+ super.clearEventHandler();
+ mHandler.clear();
+ }
+
+ private ScummVMEventsModernHandler mHandler = new ScummVMEventsModernHandler(this);
+ private float repeatingX = 0.0f;
+ private float repeatingY = 0.0f;
+
+ private static float getCenteredAxis(MotionEvent event, InputDevice device, int axis, int historyPos) {
+ final InputDevice.MotionRange range = device.getMotionRange(axis, event.getSource());
+ final int actionPointerIndex = event.getActionIndex();
+
+ // A joystick at rest does not always report an absolute position of
+ // (0,0). Use the getFlat() method to determine the range of values
+ // bounding the joystick axis center.
+ if (range != null) {
+ final float flat = range.getFlat();
+
+// if (axis == MotionEvent.AXIS_X
+// || axis == MotionEvent.AXIS_HAT_X
+// || axis == MotionEvent.AXIS_Z) {
+// Log.d(ScummVM.LOG_TAG, "Flat X= " + flat);
+// } else {
+// Log.d(ScummVM.LOG_TAG, "Flat Y= " + flat);
+// }
+
+ float axisVal = (historyPos < 0) ? event.getAxisValue( range.getAxis(), actionPointerIndex) : event.getHistoricalAxisValue( range.getAxis(), actionPointerIndex, historyPos);
+ // Normalize
+ final float value = (axisVal - range.getMin() ) / range.getRange() * 2.0f - 1.0f;
+
+ // Ignore axis values that are within the 'flat' region of the
+ // joystick axis center.
+ if (Math.abs(value) > flat) {
+ return value;
+ }
}
+ return 0;
+ }
- return false;
+ private void removeMessages() {
+ if (mHandler != null) {
+ mHandler.removeMessages(MSG_REPEAT);
+ }
+ }
+
+ private boolean repeatMove() {
+ _scummvm.pushEvent(JE_JOYSTICK, MotionEvent.ACTION_MOVE,
+ (int) (repeatingX * 100),
+ (int) (repeatingY * 100),
+ 0, 0, 0);
+ return true;
+ }
+
+ private void processJoystickInput(MotionEvent event, int historyPos) {
+
+ InputDevice inputDevice = event.getDevice();
+
+ // Calculate the horizontal distance to move by
+ // using the input value from one of these physical controls:
+ // the left control stick, hat axis, or the right control stick.
+ float x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X, historyPos);
+ //Log.d(ScummVM.LOG_TAG, "JOYSTICK - LEFT: x= " +x);
+ if (x == 0) {
+ x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_X, historyPos);
+ //Log.d(ScummVM.LOG_TAG, "JOYSTICK - HAT: x= " +x);
+ }
+ if (x == 0) {
+ x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z, historyPos);
+ //Log.d(ScummVM.LOG_TAG, "JOYSTICK - RIGHT: x= " +x);
+ }
+
+ // Calculate the vertical distance to move by
+ // using the input value from one of these physical controls:
+ // the left control stick, hat switch, or the right control stick.
+ float y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y, historyPos);
+ //Log.d(ScummVM.LOG_TAG, "JOYSTICK - LEFT: y= " +y);
+ if (y == 0) {
+ y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_Y, historyPos);
+ //Log.d(ScummVM.LOG_TAG, "JOYSTICK - HAT: y= " +y);
+ }
+ if (y == 0) {
+ y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ, historyPos);
+ //Log.d(ScummVM.LOG_TAG, "JOYSTICK - RIGHT: y= " +y);
+ }
+
+ // extra filter to stop repetition in order to avoid cases when android does not send onGenericMotionEvent()
+ // for small x or y (while abs is still larger than range.getflat())
+ // In such case we would end up with a slow moving "mouse" cursor - so we need this extra filter
+ if (Math.abs(x * 100) < 20.0f && Math.abs(y * 100) < 20.0f) {
+ //Log.d(ScummVM.LOG_TAG, "JOYSTICK - pushEvent(): STOPPED: " + (int)(x * 100) + " y= " + (int)(y * 100));
+ removeMessages();
+ // do the move anyway, just don't repeat
+ repeatMove();
+ repeatingX = 0.0f;
+ repeatingY = 0.0f;
+ } else {
+ //Log.d(ScummVM.LOG_TAG, "JOYSTICK - pushEvent(): x= " + (int)(x * 100) + " y= " + (int)(y * 100));
+ if (repeatingX != 0.0f || repeatingY != 0.0f) {
+ // already repeating - just update the movement co-ords
+ repeatingX = x;
+ repeatingY = y;
+ } else {
+ // start repeating
+ //removeMessages();
+ repeatingX = x;
+ repeatingY = y;
+ Message msg = mHandler.obtainMessage(MSG_REPEAT);
+ mHandler.sendMessageDelayed(msg, REPEAT_START_DELAY);
+ repeatMove();
+ }
+ }
+ }
+
+ @Override
+ public boolean onGenericMotionEvent(MotionEvent event) {
+ // Check that the event came from a joystick
+ if (((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK
+ || (event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0)) {
+ int action = event.getActionMasked();
+ if (action == MotionEvent.ACTION_MOVE) {
+
+ // Process all historical movement samples in the batch
+ final int historySize = event.getHistorySize();
+
+ // Process the movements starting from the
+ // earliest historical position in the batch
+ for (int i = 0; i < historySize; i++) {
+ // Process the event at historical position i
+ //Log.d(ScummVM.LOG_TAG, "JOYSTICK - onGenericMotionEvent(m) hist: ");
+ processJoystickInput(event, i);
+ }
+
+ // Process the current movement sample in the batch (position -1)
+ //Log.d(ScummVM.LOG_TAG, "JOYSTICK - onGenericMotionEvent(m): " );
+ processJoystickInput(event, -1);
+ return true;
+ }
+ }
+ // this basically returns false since the super just returns false
+ return super.onGenericMotionEvent(event);
}
}
More information about the Scummvm-git-logs
mailing list