mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-02 16:31:01 +00:00
ANDROID: Introduce back the touch controls for 3D
This commit is contained in:
parent
ebeb731ad7
commit
e4390abd86
@ -76,6 +76,7 @@ AndroidGraphics3dManager::AndroidGraphics3dManager() :
|
||||
_mouse_texture = _mouse_texture_palette;
|
||||
|
||||
initSurface();
|
||||
JNI::setTouch3DMode(true);
|
||||
}
|
||||
|
||||
AndroidGraphics3dManager::~AndroidGraphics3dManager() {
|
||||
@ -94,6 +95,7 @@ AndroidGraphics3dManager::~AndroidGraphics3dManager() {
|
||||
delete _mouse_texture_palette;
|
||||
delete _mouse_texture_rgb;
|
||||
|
||||
JNI::setTouch3DMode(false);
|
||||
}
|
||||
|
||||
static void logExtensions() {
|
||||
@ -150,7 +152,7 @@ void AndroidGraphics3dManager::initSurface() {
|
||||
clearScreen(kClearUpdate, 2);
|
||||
updateEventScale();
|
||||
|
||||
_touchControls.init(JNI::egl_surface_width, JNI::egl_surface_height);
|
||||
dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().init(JNI::egl_surface_width, JNI::egl_surface_height);
|
||||
}
|
||||
|
||||
void AndroidGraphics3dManager::deinitSurface() {
|
||||
@ -212,7 +214,7 @@ void AndroidGraphics3dManager::updateScreen() {
|
||||
_game_texture->drawTextureRect();
|
||||
if (!_show_overlay) {
|
||||
glEnable(GL_BLEND);
|
||||
_touchControls.draw();
|
||||
dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().draw();
|
||||
}
|
||||
|
||||
int cs = _mouse_targetscale;
|
||||
@ -316,6 +318,8 @@ bool AndroidGraphics3dManager::getFeatureState(OSystem::Feature f) const {
|
||||
void AndroidGraphics3dManager::showOverlay() {
|
||||
ENTER();
|
||||
|
||||
JNI::setTouch3DMode(false);
|
||||
|
||||
_show_overlay = true;
|
||||
_force_redraw = true;
|
||||
|
||||
@ -331,6 +335,8 @@ void AndroidGraphics3dManager::hideOverlay() {
|
||||
|
||||
_show_overlay = false;
|
||||
|
||||
JNI::setTouch3DMode(true);
|
||||
|
||||
updateEventScale();
|
||||
|
||||
warpMouse(_game_texture->width() / 2, _game_texture->height() / 2);
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "backends/graphics/graphics.h"
|
||||
#include "backends/graphics/android/android-graphics.h"
|
||||
#include "backends/graphics3d/android/texture.h"
|
||||
#include "backends/graphics3d/android/touchcontrols.h"
|
||||
|
||||
class AndroidGraphics3dManager : public GraphicsManager, public AndroidCommonGraphics {
|
||||
public:
|
||||
@ -175,8 +174,6 @@ private:
|
||||
int _mouse_targetscale;
|
||||
bool _show_mouse;
|
||||
bool _use_mouse_palette;
|
||||
|
||||
TouchControls _touchControls;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,314 +0,0 @@
|
||||
/* ResidualVM - A 3D game interpreter
|
||||
*
|
||||
* ResidualVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
// Allow use of stuff in <time.h>
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
|
||||
|
||||
//
|
||||
// Disable printf override in common/forbidden.h to avoid
|
||||
// clashes with log.h from the Android SDK.
|
||||
// That header file uses
|
||||
// __attribute__ ((format(printf, 3, 4)))
|
||||
// which gets messed up by our override mechanism; this could
|
||||
// be avoided by either changing the Android SDK to use the equally
|
||||
// legal and valid
|
||||
// __attribute__ ((format(printf, 3, 4)))
|
||||
// or by refining our printf override to use a varadic macro
|
||||
// (which then wouldn't be portable, though).
|
||||
// Anyway, for now we just disable the printf override globally
|
||||
// for the Android port
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
|
||||
|
||||
#include "common/fs.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/archive.h"
|
||||
#include "image/tga.h"
|
||||
|
||||
#include "backends/graphics3d/android/texture.h"
|
||||
#include "backends/graphics3d/android/touchcontrols.h"
|
||||
#include "backends/platform/android/android.h"
|
||||
|
||||
// action type
|
||||
enum {
|
||||
JACTION_DOWN = 0,
|
||||
JACTION_UP = 1,
|
||||
JACTION_MULTIPLE = 2,
|
||||
JACTION_POINTER_DOWN = 5,
|
||||
JACTION_POINTER_UP = 6
|
||||
};
|
||||
|
||||
static Common::Rect clipFor(const Common::KeyCode &cs) {
|
||||
switch (cs) {
|
||||
case Common::KEYCODE_UP:
|
||||
case Common::KEYCODE_PAGEUP:
|
||||
return Common::Rect(0, 0, 128, 128);
|
||||
case Common::KEYCODE_RIGHT:
|
||||
return Common::Rect(128, 0, 256, 128);
|
||||
case Common::KEYCODE_DOWN:
|
||||
case Common::KEYCODE_PAGEDOWN:
|
||||
return Common::Rect(256, 0, 384, 128);
|
||||
case Common::KEYCODE_LEFT:
|
||||
return Common::Rect(384, 0, 512, 128);
|
||||
case Common::KEYCODE_i:
|
||||
return Common::Rect(0, 128, 128, 256);
|
||||
case Common::KEYCODE_p:
|
||||
return Common::Rect(128, 128, 256, 256);
|
||||
case Common::KEYCODE_u:
|
||||
return Common::Rect(256, 128, 384, 256);
|
||||
case Common::KEYCODE_e:
|
||||
case Common::KEYCODE_l:
|
||||
return Common::Rect(384, 128, 512, 256);
|
||||
default: // unreachable
|
||||
return Common::Rect(0, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
TouchControls::TouchControls() :
|
||||
_arrows_texture(NULL),
|
||||
_joystickPressing(Common::KEYCODE_INVALID),
|
||||
_centerPressing(Common::KEYCODE_INVALID),
|
||||
_rightPressing(Common::KEYCODE_INVALID),
|
||||
_screen_width(0),
|
||||
_screen_height(0) {
|
||||
|
||||
for (int p = 0; p < kNumPointers; ++p) {
|
||||
Pointer &pp = _pointers[p];
|
||||
pp.currentX = pp.currentY = pp.startX = pp.startY = 0;
|
||||
pp.active = false;
|
||||
pp.function = kTouchAreaNone;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
_activePointers[i] = -1;
|
||||
}
|
||||
|
||||
TouchControls::~TouchControls() {
|
||||
if (_arrows_texture) {
|
||||
delete _arrows_texture;
|
||||
_arrows_texture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 TouchControls::getTouchArea(int x, int y) {
|
||||
float xPercent = float(x) / _screen_width;
|
||||
|
||||
if (xPercent < 0.3)
|
||||
return kTouchAreaJoystick;
|
||||
else if (xPercent < 0.8)
|
||||
return kTouchAreaCenter;
|
||||
else
|
||||
return kTouchAreaRight;
|
||||
}
|
||||
|
||||
static Common::KeyCode determineKey(int dX, int dY, Common::KeyCode def = Common::KEYCODE_INVALID) {
|
||||
if (dX * dX + dY * dY < 50 * 50)
|
||||
return def;
|
||||
|
||||
if (dY > abs(dX))
|
||||
return Common::KEYCODE_DOWN;
|
||||
if (dX > abs(dY))
|
||||
return Common::KEYCODE_RIGHT;
|
||||
if (-dY > abs(dX))
|
||||
return Common::KEYCODE_UP;
|
||||
if (-dX > abs(dY))
|
||||
return Common::KEYCODE_LEFT;
|
||||
|
||||
return Common::KEYCODE_INVALID;
|
||||
}
|
||||
|
||||
static GLES8888Texture *loadBuiltinTexture(const char *filename) {
|
||||
Common::ArchiveMemberPtr member = SearchMan.getMember(filename);
|
||||
Common::SeekableReadStream *str = member->createReadStream();
|
||||
Image::TGADecoder dec;
|
||||
dec.loadStream(*str);
|
||||
const void *pixels = dec.getSurface()->getPixels();
|
||||
|
||||
GLES8888Texture *ret = new GLES8888Texture();
|
||||
uint16 w = dec.getSurface()->w;
|
||||
uint16 h = dec.getSurface()->h;
|
||||
uint16 pitch = dec.getSurface()->pitch;
|
||||
ret->allocBuffer(w, h);
|
||||
ret->updateBuffer(0, 0, w, h, pixels, pitch);
|
||||
|
||||
delete str;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void TouchControls::init(int width, int height) {
|
||||
_arrows_texture = loadBuiltinTexture("arrows.tga");
|
||||
_screen_width = width;
|
||||
_screen_height = height;
|
||||
}
|
||||
|
||||
const uint _numRightKeycodes = 4;
|
||||
const Common::KeyCode _rightKeycodes[] = { Common::KEYCODE_i, Common::KEYCODE_p, Common::KEYCODE_u, Common::KEYCODE_e };
|
||||
|
||||
void TouchControls::draw() {
|
||||
if (_joystickPressing != Common::KEYCODE_INVALID) {
|
||||
Common::Rect clip = clipFor(_joystickPressing);
|
||||
_arrows_texture->drawTexture(2 * _screen_width / 10, _screen_height / 2, 64, 64, clip);
|
||||
}
|
||||
|
||||
if (_centerPressing != Common::KEYCODE_INVALID) {
|
||||
Common::Rect clip = clipFor(_centerPressing);
|
||||
_arrows_texture->drawTexture(_screen_width / 2, _screen_height / 2, 64, 64, clip);
|
||||
}
|
||||
|
||||
if (_rightPressing != Common::KEYCODE_INVALID) {
|
||||
Common::Rect clip = clipFor(_rightPressing);
|
||||
_arrows_texture->drawTexture( 8 * _screen_width / 10, _screen_height / 2, 64, 64, clip);
|
||||
}
|
||||
}
|
||||
|
||||
void TouchControls::update(int ptr, int action, int x, int y) {
|
||||
if (ptr > kNumPointers)
|
||||
return;
|
||||
|
||||
TouchArea touchArea = (TouchArea) getTouchArea(x, y);
|
||||
|
||||
switch (action) {
|
||||
case JACTION_POINTER_DOWN:
|
||||
case JACTION_DOWN:
|
||||
if (touchArea > kTouchAreaNone && -1 == pointerFor(touchArea)) {
|
||||
pointerFor(touchArea) = ptr;
|
||||
_pointers[ptr].active = true;
|
||||
_pointers[ptr].function = touchArea;
|
||||
_pointers[ptr].startX = _pointers[ptr].currentX = x;
|
||||
_pointers[ptr].startY = _pointers[ptr].currentY = y;
|
||||
// fall through to move case to initialize _{joy,center,right}Pressing
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
case JACTION_MULTIPLE: {
|
||||
_pointers[ptr].currentX = x;
|
||||
_pointers[ptr].currentY = y;
|
||||
int dX = x - _pointers[ptr].startX;
|
||||
int dY = y - _pointers[ptr].startY;
|
||||
|
||||
switch (_pointers[ptr].function) {
|
||||
case kTouchAreaJoystick: {
|
||||
Common::KeyCode newPressing = determineKey(dX, dY);
|
||||
if (newPressing != _joystickPressing) {
|
||||
keyUp(_joystickPressing);
|
||||
keyDown(newPressing);
|
||||
_joystickPressing = newPressing;
|
||||
} else if(abs(dY) > 150) {
|
||||
keyDown(Common::KEYCODE_LSHIFT);
|
||||
} else if(abs(dY) <= 150){
|
||||
keyUp(Common::KEYCODE_LSHIFT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case kTouchAreaCenter:
|
||||
_centerPressing = determineKey(dX, dY, Common::KEYCODE_RETURN);
|
||||
return;
|
||||
|
||||
case kTouchAreaRight:
|
||||
_rightPressing = determineKey(dX, dY, Common::KEYCODE_i);
|
||||
switch (_rightPressing) {
|
||||
case Common::KEYCODE_LEFT:
|
||||
case Common::KEYCODE_RIGHT:
|
||||
_rightPressing = _rightKeycodes[abs(dX / 100) % _numRightKeycodes];
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_UP:
|
||||
_rightPressing = Common::KEYCODE_PAGEUP;
|
||||
break;
|
||||
|
||||
case Common::KEYCODE_DOWN:
|
||||
_rightPressing = Common::KEYCODE_PAGEDOWN;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case JACTION_UP:
|
||||
case JACTION_POINTER_UP: {
|
||||
switch (_pointers[ptr].function) {
|
||||
case kTouchAreaJoystick:
|
||||
pointerFor(kTouchAreaJoystick) = -1;
|
||||
if (_joystickPressing != Common::KEYCODE_INVALID) {
|
||||
keyUp(_joystickPressing);
|
||||
_joystickPressing = Common::KEYCODE_INVALID;
|
||||
keyUp(Common::KEYCODE_LSHIFT);
|
||||
}
|
||||
break;
|
||||
|
||||
case kTouchAreaCenter:
|
||||
pointerFor(kTouchAreaCenter) = -1;
|
||||
keyPress(_centerPressing);
|
||||
_centerPressing = Common::KEYCODE_INVALID;
|
||||
break;
|
||||
|
||||
case kTouchAreaRight:
|
||||
pointerFor(kTouchAreaRight) = -1;
|
||||
keyPress(_rightPressing);
|
||||
_rightPressing = Common::KEYCODE_INVALID;
|
||||
break;
|
||||
|
||||
case kTouchAreaNone:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_pointers[ptr].active = false;
|
||||
_pointers[ptr].function = kTouchAreaNone;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int &TouchControls::pointerFor(TouchArea ta) {
|
||||
return _activePointers[ta - kTouchAreaNone];
|
||||
}
|
||||
|
||||
void TouchControls::keyDown(Common::KeyCode kc) {
|
||||
Common::Event ev;
|
||||
ev.type = Common::EVENT_KEYDOWN;
|
||||
ev.kbd.keycode = kc;
|
||||
dynamic_cast<OSystem_Android *>(g_system)->pushEvent(ev);
|
||||
}
|
||||
|
||||
void TouchControls::keyUp(Common::KeyCode kc) {
|
||||
Common::Event ev;
|
||||
ev.type = Common::EVENT_KEYUP;
|
||||
ev.kbd.keycode = kc;
|
||||
dynamic_cast<OSystem_Android *>(g_system)->pushEvent(ev);
|
||||
}
|
||||
|
||||
void TouchControls::keyPress(Common::KeyCode kc) {
|
||||
Common::Event ev;
|
||||
ev.kbd.keycode = kc;
|
||||
dynamic_cast<OSystem_Android *>(g_system)->pushKeyPressEvent(ev);
|
||||
}
|
||||
|
||||
#endif
|
@ -235,7 +235,6 @@ MODULE_OBJS += \
|
||||
graphics/android/android-graphics.o \
|
||||
graphics3d/android/android-graphics3d.o \
|
||||
graphics3d/android/texture.o \
|
||||
graphics3d/android/touchcontrols.o \
|
||||
mutex/pthread/pthread-mutex.o
|
||||
endif
|
||||
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include "backends/plugins/posix/posix-provider.h"
|
||||
#include "backends/fs/posix/posix-fs-factory.h"
|
||||
|
||||
#include "backends/platform/android/touchcontrols.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <android/log.h>
|
||||
@ -132,6 +134,8 @@ public:
|
||||
void pushEvent(const Common::Event &event);
|
||||
void pushKeyPressEvent(Common::Event &event);
|
||||
|
||||
TouchControls &getTouchControls() { return _touchControls; }
|
||||
|
||||
private:
|
||||
Common::Queue<Common::Event> _event_queue;
|
||||
Common::Event _queuedEvent;
|
||||
@ -151,6 +155,8 @@ private:
|
||||
int _secondPointerId;
|
||||
int _thirdPointerId;
|
||||
|
||||
TouchControls _touchControls;
|
||||
|
||||
public:
|
||||
bool pollEvent(Common::Event &event) override;
|
||||
Common::HardwareInputSet *getHardwareInputSet() override;
|
||||
|
@ -84,6 +84,7 @@ jmethodID JNI::_MID_isConnectionLimited = 0;
|
||||
jmethodID JNI::_MID_setWindowCaption = 0;
|
||||
jmethodID JNI::_MID_showVirtualKeyboard = 0;
|
||||
jmethodID JNI::_MID_showKeyboardControl = 0;
|
||||
jmethodID JNI::_MID_setTouch3DMode = 0;
|
||||
jmethodID JNI::_MID_showSAFRevokePermsControl = 0;
|
||||
jmethodID JNI::_MID_getSysArchives = 0;
|
||||
jmethodID JNI::_MID_getAllStorageLocations = 0;
|
||||
@ -118,6 +119,8 @@ const JNINativeMethod JNI::_natives[] = {
|
||||
(void *)JNI::main },
|
||||
{ "pushEvent", "(IIIIIII)V",
|
||||
(void *)JNI::pushEvent },
|
||||
{ "updateTouch", "(IIII)V",
|
||||
(void *)JNI::updateTouch },
|
||||
{ "setPause", "(Z)V",
|
||||
(void *)JNI::setPause },
|
||||
{ "getNativeVersionInfo", "()Ljava/lang/String;",
|
||||
@ -386,6 +389,19 @@ void JNI::showKeyboardControl(bool enable) {
|
||||
}
|
||||
}
|
||||
|
||||
void JNI::setTouch3DMode(bool touch3DMode) {
|
||||
JNIEnv *env = JNI::getEnv();
|
||||
|
||||
env->CallVoidMethod(_jobj, _MID_setTouch3DMode, touch3DMode);
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
LOGE("Error trying to show virtual keyboard control");
|
||||
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
}
|
||||
}
|
||||
|
||||
void JNI::showSAFRevokePermsControl(bool enable) {
|
||||
#ifndef BACKEND_ANDROID3D
|
||||
JNIEnv *env = JNI::getEnv();
|
||||
@ -571,6 +587,7 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
|
||||
FIND_METHOD(, isConnectionLimited, "()Z");
|
||||
FIND_METHOD(, showVirtualKeyboard, "(Z)V");
|
||||
FIND_METHOD(, showKeyboardControl, "(Z)V");
|
||||
FIND_METHOD(, setTouch3DMode, "(Z)V");
|
||||
FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;");
|
||||
FIND_METHOD(, getAllStorageLocations, "()[Ljava/lang/String;");
|
||||
FIND_METHOD(, initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;");
|
||||
@ -713,6 +730,18 @@ void JNI::pushEvent(JNIEnv *env, jobject self, int type, int arg1, int arg2,
|
||||
_system->pushEvent(type, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
|
||||
void JNI::updateTouch(JNIEnv *env, jobject self, int action, int ptr, int x, int y) {
|
||||
// drop events until we're ready and after we quit
|
||||
if (!_ready_for_events) {
|
||||
LOGW("dropping event");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(_system);
|
||||
|
||||
_system->getTouchControls().update((TouchControls::Action) action, ptr, x, y);
|
||||
}
|
||||
|
||||
void JNI::setPause(JNIEnv *env, jobject self, jboolean value) {
|
||||
if (!_system)
|
||||
return;
|
||||
|
@ -68,6 +68,7 @@ public:
|
||||
static bool isConnectionLimited();
|
||||
static void showVirtualKeyboard(bool enable);
|
||||
static void showKeyboardControl(bool enable);
|
||||
static void setTouch3DMode(bool touch3DMode);
|
||||
static void showSAFRevokePermsControl(bool enable);
|
||||
static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
|
||||
|
||||
@ -114,6 +115,7 @@ private:
|
||||
static jmethodID _MID_setWindowCaption;
|
||||
static jmethodID _MID_showVirtualKeyboard;
|
||||
static jmethodID _MID_showKeyboardControl;
|
||||
static jmethodID _MID_setTouch3DMode;
|
||||
static jmethodID _MID_showSAFRevokePermsControl;
|
||||
static jmethodID _MID_getSysArchives;
|
||||
static jmethodID _MID_getAllStorageLocations;
|
||||
@ -149,6 +151,7 @@ private:
|
||||
|
||||
static void pushEvent(JNIEnv *env, jobject self, int type, int arg1,
|
||||
int arg2, int arg3, int arg4, int arg5, int arg6);
|
||||
static void updateTouch(JNIEnv *env, jobject self, int action, int ptr, int x, int y);
|
||||
static void setPause(JNIEnv *env, jobject self, jboolean value);
|
||||
|
||||
static jstring getNativeVersionInfo(JNIEnv *env, jobject self);
|
||||
|
@ -6,7 +6,8 @@ MODULE_OBJS := \
|
||||
android.o \
|
||||
events.o \
|
||||
options.o \
|
||||
snprintf.o
|
||||
snprintf.o \
|
||||
touchcontrols.o
|
||||
|
||||
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
|
||||
MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
|
||||
|
@ -54,6 +54,8 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
|
||||
// Feed an event to ScummVM. Safe to call from other threads.
|
||||
final public native void pushEvent(int type, int arg1, int arg2, int arg3,
|
||||
int arg4, int arg5, int arg6);
|
||||
// Update the 3D touch controls
|
||||
final public native void updateTouch(int action, int ptr, int x, int y);
|
||||
|
||||
final public native String getNativeVersionInfo();
|
||||
|
||||
@ -68,6 +70,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
|
||||
abstract protected void setWindowCaption(String caption);
|
||||
abstract protected void showVirtualKeyboard(boolean enable);
|
||||
abstract protected void showKeyboardControl(boolean enable);
|
||||
abstract protected void setTouch3DMode(boolean touch3DMode);
|
||||
abstract protected void showSAFRevokePermsControl(boolean enable);
|
||||
abstract protected String[] getSysArchives();
|
||||
abstract protected String[] getAllStorageLocations();
|
||||
|
@ -699,6 +699,15 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setTouch3DMode(final boolean touch3DMode) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
_events.setTouch3DMode(touch3DMode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showSAFRevokePermsControl(final boolean enable) {
|
||||
runOnUiThread(new Runnable() {
|
||||
|
@ -50,6 +50,11 @@ public class ScummVMEventsBase implements
|
||||
public static final int JE_QUIT = 0x1000;
|
||||
public static final int JE_MENU = 0x1001;
|
||||
|
||||
public static final int JACTION_DOWN = 0;
|
||||
public static final int JACTION_MOVE = 1;
|
||||
public static final int JACTION_UP = 2;
|
||||
public static final int JACTION_CANCEL = 3;
|
||||
|
||||
final protected Context _context;
|
||||
final protected ScummVM _scummvm;
|
||||
final protected GestureDetector _gd;
|
||||
@ -57,6 +62,8 @@ public class ScummVMEventsBase implements
|
||||
final protected MouseHelper _mouseHelper;
|
||||
final protected MultitouchHelper _multitouchHelper;
|
||||
|
||||
protected boolean _touch3DMode;
|
||||
|
||||
// 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 ScummVMEventHandler extends Handler {
|
||||
@ -135,6 +142,13 @@ public class ScummVMEventsBase implements
|
||||
}
|
||||
}
|
||||
|
||||
final public void setTouch3DMode(boolean touch3DMode) {
|
||||
if (_touch3DMode != touch3DMode && !touch3DMode) {
|
||||
_scummvm.updateTouch(JACTION_CANCEL, 0, 0, 0);
|
||||
}
|
||||
_touch3DMode = touch3DMode;
|
||||
}
|
||||
|
||||
public void clearEventHandler() {
|
||||
_skeyHandler.clear();
|
||||
_multitouchHelper.clearEventHandler();
|
||||
@ -459,30 +473,60 @@ public class ScummVMEventsBase implements
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with LINT warning "ScummVMEvents#onTouch should call View#performClick when a click is detected"
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
v.performClick();
|
||||
break;
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
// fall through
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (_touch3DMode) {
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN: {
|
||||
int idx = event.getActionIndex();
|
||||
_scummvm.updateTouch(JACTION_DOWN, event.getPointerId(idx), (int)event.getX(idx), (int)event.getY(idx));
|
||||
// fall through
|
||||
}
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
for(int idx = 0; idx < event.getPointerCount(); idx++) {
|
||||
_scummvm.updateTouch(JACTION_MOVE, event.getPointerId(idx), (int)event.getX(idx), (int)event.getY(idx));
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP: {
|
||||
int idx = event.getActionIndex();
|
||||
_scummvm.updateTouch(JACTION_UP, event.getPointerId(idx), (int)event.getX(idx), (int)event.getY(idx));
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
_scummvm.updateTouch(JACTION_CANCEL, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
// check if the event can be handled as a multitouch event
|
||||
if (_multitouchHelper.handleMotionEvent(event)) {
|
||||
//return _gd.onTouchEvent(event);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Deal with LINT warning "ScummVMEvents#onTouch should call View#performClick when a click is detected"
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
v.performClick();
|
||||
break;
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
// fall through
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return _gd.onTouchEvent(event);
|
||||
// check if the event can be handled as a multitouch event
|
||||
if (_multitouchHelper.handleMotionEvent(event)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _gd.onTouchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
// OnGestureListener
|
||||
@Override
|
||||
final public boolean onDown(MotionEvent e) {
|
||||
// Log.d(ScummVM.LOG_TAG, "SCUMMV-EVENTS-BASE - onDOWN MotionEvent");
|
||||
_scummvm.pushEvent(JE_DOWN, (int)e.getX(), (int)e.getY(), 0, 0, 0, 0);
|
||||
if (!_touch3DMode) {
|
||||
_scummvm.pushEvent(JE_DOWN, (int)e.getX(), (int)e.getY(), 0, 0, 0, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -505,9 +549,10 @@ public class ScummVMEventsBase implements
|
||||
final public boolean onScroll(MotionEvent e1, MotionEvent e2,
|
||||
float distanceX, float distanceY) {
|
||||
// Log.d(ScummVM.LOG_TAG, "onScroll");
|
||||
_scummvm.pushEvent(JE_SCROLL, (int)e1.getX(), (int)e1.getY(),
|
||||
if (!_touch3DMode) {
|
||||
_scummvm.pushEvent(JE_SCROLL, (int)e1.getX(), (int)e1.getY(),
|
||||
(int)e2.getX(), (int)e2.getY(), 0, 0);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -518,9 +563,10 @@ public class ScummVMEventsBase implements
|
||||
@Override
|
||||
final public boolean onSingleTapUp(MotionEvent e) {
|
||||
// Log.d(ScummVM.LOG_TAG, "onSingleTapUp");
|
||||
_scummvm.pushEvent(JE_TAP, (int)e.getX(), (int)e.getY(),
|
||||
if (!_touch3DMode) {
|
||||
_scummvm.pushEvent(JE_TAP, (int)e.getX(), (int)e.getY(),
|
||||
(int)(e.getEventTime() - e.getDownTime()), 0, 0, 0);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -545,7 +591,9 @@ public class ScummVMEventsBase implements
|
||||
// } else {
|
||||
// Log.d(ScummVM.LOG_TAG, "onDoubleTapEvent UNKNOWN!!!!");
|
||||
// }
|
||||
_scummvm.pushEvent(JE_DOUBLE_TAP, (int)e.getX(), (int)e.getY(), e.getAction(), 0, 0, 0);
|
||||
if (!_touch3DMode) {
|
||||
_scummvm.pushEvent(JE_DOUBLE_TAP, (int)e.getX(), (int)e.getY(), e.getAction(), 0, 0, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
362
backends/platform/android/touchcontrols.cpp
Normal file
362
backends/platform/android/touchcontrols.cpp
Normal file
@ -0,0 +1,362 @@
|
||||
/* ResidualVM - A 3D game interpreter
|
||||
*
|
||||
* ResidualVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
// Allow use of stuff in <time.h>
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
|
||||
|
||||
//
|
||||
// Disable printf override in common/forbidden.h to avoid
|
||||
// clashes with log.h from the Android SDK.
|
||||
// That header file uses
|
||||
// __attribute__ ((format(printf, 3, 4)))
|
||||
// which gets messed up by our override mechanism; this could
|
||||
// be avoided by either changing the Android SDK to use the equally
|
||||
// legal and valid
|
||||
// __attribute__ ((format(printf, 3, 4)))
|
||||
// or by refining our printf override to use a varadic macro
|
||||
// (which then wouldn't be portable, though).
|
||||
// Anyway, for now we just disable the printf override globally
|
||||
// for the Android port
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
|
||||
|
||||
#include "common/fs.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/archive.h"
|
||||
#include "image/tga.h"
|
||||
|
||||
#include "backends/graphics3d/android/texture.h"
|
||||
#include "backends/platform/android/android.h"
|
||||
#include "backends/platform/android/touchcontrols.h"
|
||||
|
||||
TouchControls::TouchControls() :
|
||||
_arrows_texture(NULL),
|
||||
_screen_width(0),
|
||||
_screen_height(0) {
|
||||
}
|
||||
|
||||
TouchControls::~TouchControls() {
|
||||
if (_arrows_texture) {
|
||||
delete _arrows_texture;
|
||||
_arrows_texture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TouchControls::Function TouchControls::getFunction(int x, int y) {
|
||||
float xPercent = float(x) / _screen_width;
|
||||
|
||||
if (xPercent < 0.3)
|
||||
return kFunctionJoystick;
|
||||
else if (xPercent < 0.8)
|
||||
return kFunctionCenter;
|
||||
else
|
||||
return kFunctionRight;
|
||||
}
|
||||
|
||||
void TouchControls::touchToJoystickState(int dX, int dY, FunctionState &state) {
|
||||
int sqNorm = dX * dX + dY * dY;
|
||||
if (sqNorm < 50 * 50) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dY > abs(dX)) {
|
||||
state.main = Common::KEYCODE_DOWN;
|
||||
state.clip = Common::Rect(256, 0, 384, 128);
|
||||
} else if (dX > abs(dY)) {
|
||||
state.main = Common::KEYCODE_RIGHT;
|
||||
state.clip = Common::Rect(128, 0, 256, 128);
|
||||
} else if (-dY > abs(dX)) {
|
||||
state.main = Common::KEYCODE_UP;
|
||||
state.clip = Common::Rect(0, 0, 128, 128);
|
||||
} else if (-dX > abs(dY)) {
|
||||
state.main = Common::KEYCODE_LEFT;
|
||||
state.clip = Common::Rect(384, 0, 512, 128);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sqNorm > 20000) {
|
||||
state.modifier = Common::KEYCODE_LSHIFT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TouchControls::touchToCenterState(int dX, int dY, FunctionState &state) {
|
||||
int sqNorm = dX * dX + dY * dY;
|
||||
if (sqNorm < 50 * 50) {
|
||||
state.main = Common::KEYCODE_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
void TouchControls::touchToRightState(int dX, int dY, FunctionState &state) {
|
||||
if (dX * dX + dY * dY < 100 * 100)
|
||||
return;
|
||||
|
||||
if (dY > abs(dX)) {
|
||||
// down
|
||||
state.main = Common::KEYCODE_PAGEDOWN;
|
||||
state.clip = Common::Rect(256, 0, 384, 128);
|
||||
return;
|
||||
} else if (-dY > abs(dX)) {
|
||||
// up
|
||||
state.main = Common::KEYCODE_PAGEUP;
|
||||
state.clip = Common::Rect(0, 0, 128, 128);
|
||||
return;
|
||||
}
|
||||
|
||||
static Common::KeyCode keycodes[5] = {
|
||||
Common::KEYCODE_i, Common::KEYCODE_p, // left zone
|
||||
Common::KEYCODE_INVALID, // center
|
||||
Common::KEYCODE_u, Common::KEYCODE_l // right zone
|
||||
};
|
||||
|
||||
static int16 clips[5][4] = {
|
||||
{ 0, 128, 128, 256 }, // i
|
||||
{ 128, 128, 256, 256 }, // p
|
||||
{ 0, 0, 0, 0 }, // center
|
||||
{ 256, 128, 384, 256 }, // u
|
||||
{ 384, 128, 512, 256 } // l
|
||||
};
|
||||
static const unsigned int offset = (ARRAYSIZE(keycodes) - 1) / 2;
|
||||
|
||||
int idx = (dX / 100) + offset;
|
||||
if (idx < 0) {
|
||||
idx = 0;
|
||||
}
|
||||
if (idx >= ARRAYSIZE(keycodes)) {
|
||||
idx = ARRAYSIZE(keycodes) - 1;
|
||||
}
|
||||
state.main = keycodes[idx];
|
||||
state.clip = Common::Rect(clips[idx][0], clips[idx][1], clips[idx][2], clips[idx][3]);
|
||||
}
|
||||
|
||||
TouchControls::FunctionBehavior TouchControls::functionBehaviors[TouchControls::kFunctionMax+1] = {
|
||||
{ touchToJoystickState, false, .2f, .5f },
|
||||
{ touchToCenterState, true, .5f, .5f },
|
||||
{ touchToRightState, true, .8f, .5f }
|
||||
};
|
||||
|
||||
static GLES8888Texture *loadBuiltinTexture(const char *filename) {
|
||||
Common::ArchiveMemberPtr member = SearchMan.getMember(filename);
|
||||
Common::SeekableReadStream *str = member->createReadStream();
|
||||
Image::TGADecoder dec;
|
||||
dec.loadStream(*str);
|
||||
const void *pixels = dec.getSurface()->getPixels();
|
||||
|
||||
GLES8888Texture *ret = new GLES8888Texture();
|
||||
uint16 w = dec.getSurface()->w;
|
||||
uint16 h = dec.getSurface()->h;
|
||||
uint16 pitch = dec.getSurface()->pitch;
|
||||
ret->allocBuffer(w, h);
|
||||
ret->updateBuffer(0, 0, w, h, pixels, pitch);
|
||||
|
||||
delete str;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void TouchControls::init(int width, int height) {
|
||||
_arrows_texture = loadBuiltinTexture("arrows.tga");
|
||||
_screen_width = width;
|
||||
_screen_height = height;
|
||||
}
|
||||
|
||||
TouchControls::Pointer *TouchControls::getPointerFromId(int ptrId, bool createNotFound) {
|
||||
unsigned int freeEntry = -1;
|
||||
for (unsigned int i = 0; i < kNumPointers; i++) {
|
||||
Pointer &ptr = _pointers[i];
|
||||
if (ptr.active && (ptr.id == ptrId)) {
|
||||
return &ptr;
|
||||
}
|
||||
if (createNotFound && (freeEntry == -1) && !ptr.active) {
|
||||
freeEntry = i;
|
||||
}
|
||||
}
|
||||
// Too much fingers or not found
|
||||
if (freeEntry == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Pointer &ptr = _pointers[freeEntry];
|
||||
ptr.reset();
|
||||
ptr.id = ptrId;
|
||||
|
||||
return &ptr;
|
||||
}
|
||||
|
||||
TouchControls::Pointer *TouchControls::findPointerFromFunction(Function function) {
|
||||
for (unsigned int i = 0; i < kNumPointers; i++) {
|
||||
Pointer &ptr = _pointers[i];
|
||||
if (ptr.active && (ptr.function == function)) {
|
||||
return &ptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TouchControls::draw() {
|
||||
for (unsigned int i = 0; i < kFunctionMax+1; i++) {
|
||||
FunctionState &state = _functionStates[i];
|
||||
FunctionBehavior behavior = functionBehaviors[i];
|
||||
|
||||
if (state.clip.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
_arrows_texture->drawTexture(_screen_width * behavior.xRatio, _screen_height * behavior.yRatio, 64, 64, state.clip);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void TouchControls::update(Action action, int ptrId, int x, int y) {
|
||||
if (action == JACTION_DOWN) {
|
||||
Pointer *ptr = getPointerFromId(ptrId, true);
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
TouchControls::Function function = getFunction(x, y);
|
||||
// ptrId is active no matter what
|
||||
ptr->active = true;
|
||||
|
||||
if (findPointerFromFunction(function)) {
|
||||
// Some finger is already using this function: don't do anything
|
||||
return;
|
||||
}
|
||||
|
||||
ptr->startX = ptr->currentX = x;
|
||||
ptr->startY = ptr->currentY = y;
|
||||
ptr->function = function;
|
||||
} else if (action == JACTION_MOVE) {
|
||||
Pointer *ptr = getPointerFromId(ptrId, false);
|
||||
if (!ptr || ptr->function == kFunctionNone) {
|
||||
return;
|
||||
}
|
||||
|
||||
FunctionBehavior &behavior = functionBehaviors[ptr->function];
|
||||
|
||||
ptr->currentX = x;
|
||||
ptr->currentY = y;
|
||||
|
||||
int dX = x - ptr->startX;
|
||||
int dY = y - ptr->startY;
|
||||
|
||||
FunctionState newState;
|
||||
functionBehaviors[ptr->function].touchToState(dX, dY, newState);
|
||||
|
||||
FunctionState &oldState = _functionStates[ptr->function];
|
||||
|
||||
if (!behavior.keyPressOnRelease) {
|
||||
// send key presses continuously
|
||||
// first old remove main key, then update modifier, then press new main key
|
||||
if (oldState.main != newState.main) {
|
||||
keyUp(oldState.main);
|
||||
}
|
||||
if (oldState.modifier != newState.modifier) {
|
||||
keyUp(oldState.modifier);
|
||||
keyDown(newState.modifier);
|
||||
}
|
||||
if (oldState.main != newState.main) {
|
||||
keyDown(newState.main);
|
||||
}
|
||||
}
|
||||
oldState = newState;
|
||||
} else if (action == JACTION_UP) {
|
||||
Pointer *ptr = getPointerFromId(ptrId, false);
|
||||
if (!ptr || ptr->function == kFunctionNone) {
|
||||
return;
|
||||
}
|
||||
|
||||
FunctionBehavior &behavior = functionBehaviors[ptr->function];
|
||||
FunctionState &functionState = _functionStates[ptr->function];
|
||||
|
||||
if (!behavior.keyPressOnRelease) {
|
||||
// We sent key down continously: keyUp everything
|
||||
keyUp(functionState.main);
|
||||
keyUp(functionState.modifier);
|
||||
} else {
|
||||
int dX = x - ptr->startX;
|
||||
int dY = y - ptr->startY;
|
||||
|
||||
FunctionState newState;
|
||||
functionBehaviors[ptr->function].touchToState(dX, dY, newState);
|
||||
|
||||
keyDown(newState.modifier);
|
||||
keyPress(newState.main);
|
||||
keyUp(newState.modifier);
|
||||
}
|
||||
|
||||
functionState.reset();
|
||||
ptr->active = false;
|
||||
} else if (action == JACTION_CANCEL) {
|
||||
for (unsigned int i = 0; i < kNumPointers; i++) {
|
||||
Pointer &ptr = _pointers[i];
|
||||
ptr.reset();
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < kFunctionMax+1; i++) {
|
||||
FunctionBehavior &behavior = functionBehaviors[i];
|
||||
FunctionState &functionState = _functionStates[i];
|
||||
|
||||
if (!behavior.keyPressOnRelease) {
|
||||
// We sent key down continously: keyUp everything
|
||||
keyUp(functionState.main);
|
||||
keyUp(functionState.modifier);
|
||||
}
|
||||
|
||||
functionState.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TouchControls::keyDown(Common::KeyCode kc) {
|
||||
if (kc == Common::KEYCODE_INVALID) {
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Event ev;
|
||||
ev.type = Common::EVENT_KEYDOWN;
|
||||
ev.kbd.keycode = kc;
|
||||
dynamic_cast<OSystem_Android *>(g_system)->pushEvent(ev);
|
||||
}
|
||||
|
||||
void TouchControls::keyUp(Common::KeyCode kc) {
|
||||
if (kc == Common::KEYCODE_INVALID) {
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Event ev;
|
||||
ev.type = Common::EVENT_KEYUP;
|
||||
ev.kbd.keycode = kc;
|
||||
dynamic_cast<OSystem_Android *>(g_system)->pushEvent(ev);
|
||||
}
|
||||
|
||||
void TouchControls::keyPress(Common::KeyCode kc) {
|
||||
if (kc == Common::KEYCODE_INVALID) {
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Event ev;
|
||||
ev.kbd.keycode = kc;
|
||||
dynamic_cast<OSystem_Android *>(g_system)->pushKeyPressEvent(ev);
|
||||
}
|
||||
|
||||
#endif
|
@ -31,41 +31,80 @@
|
||||
|
||||
class TouchControls {
|
||||
public:
|
||||
// action type
|
||||
enum Action {
|
||||
JACTION_DOWN = 0,
|
||||
JACTION_MOVE = 1,
|
||||
JACTION_UP = 2,
|
||||
JACTION_CANCEL = 3
|
||||
};
|
||||
|
||||
TouchControls();
|
||||
~TouchControls();
|
||||
|
||||
void init(int width, int height);
|
||||
void draw();
|
||||
void update(int ptr, int action, int x, int y);
|
||||
void update(Action action, int ptr, int x, int y);
|
||||
|
||||
private:
|
||||
int _screen_width, _screen_height;
|
||||
|
||||
enum TouchArea{
|
||||
kTouchAreaJoystick = 0xffff,
|
||||
kTouchAreaCenter = 0xfffe,
|
||||
kTouchAreaRight = 0xfffd,
|
||||
kTouchAreaNone = 0xfffc,
|
||||
enum Function {
|
||||
kFunctionNone = -1,
|
||||
kFunctionJoystick = 0,
|
||||
kFunctionCenter = 1,
|
||||
kFunctionRight = 2,
|
||||
kFunctionMax = 2
|
||||
};
|
||||
|
||||
uint16 getTouchArea(int x, int y);
|
||||
Function getFunction(int x, int y);
|
||||
|
||||
struct Pointer {
|
||||
Pointer() : id(-1), startX(-1), startY(-1), currentX(-1), currentY(-1), function(kFunctionNone), active(false) {}
|
||||
void reset() { id = -1; startX = startY = currentX = currentY = -1; function = kFunctionNone; active = false; }
|
||||
|
||||
int id;
|
||||
uint16 startX, startY;
|
||||
uint16 currentX, currentY;
|
||||
TouchArea function;
|
||||
Function function;
|
||||
bool active;
|
||||
};
|
||||
|
||||
enum { kNumPointers = 5 };
|
||||
Pointer _pointers[kNumPointers];
|
||||
int _activePointers[4];
|
||||
Common::KeyCode _joystickPressing, _centerPressing, _rightPressing;
|
||||
int &pointerFor(TouchArea ta);
|
||||
|
||||
Pointer *getPointerFromId(int ptr, bool createNotFound);
|
||||
Pointer *findPointerFromFunction(Function function);
|
||||
|
||||
struct FunctionState {
|
||||
FunctionState() : main(Common::KEYCODE_INVALID), modifier(Common::KEYCODE_INVALID) { }
|
||||
void reset() { main = Common::KEYCODE_INVALID; modifier = Common::KEYCODE_INVALID; clip = Common::Rect(); }
|
||||
|
||||
Common::KeyCode main;
|
||||
Common::KeyCode modifier;
|
||||
Common::Rect clip;
|
||||
};
|
||||
|
||||
FunctionState _functionStates[kFunctionMax + 1];
|
||||
|
||||
GLESTexture *_arrows_texture;
|
||||
void keyDown(Common::KeyCode kc);
|
||||
void keyUp(Common::KeyCode kc);
|
||||
void keyPress(Common::KeyCode kc);
|
||||
|
||||
/* Functions implementations */
|
||||
struct FunctionBehavior {
|
||||
void (*touchToState)(int, int, TouchControls::FunctionState &);
|
||||
bool keyPressOnRelease;
|
||||
float xRatio;
|
||||
float yRatio;
|
||||
};
|
||||
static FunctionBehavior functionBehaviors[TouchControls::kFunctionMax+1];
|
||||
|
||||
static void touchToJoystickState(int dX, int dY, FunctionState &state);
|
||||
static void touchToCenterState(int dX, int dY, FunctionState &state);
|
||||
static void touchToRightState(int dX, int dY, FunctionState &state);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user