ANDROID: Support swipe-based virtcontrols
Touching and holding the left side of the screen functions as a joystick. Swiping the middle side allows fine control over arrow keys (eg. dialogues), tapping it sends an enter key. Swiping the right side up/down sends pageup/pagedown.
This commit is contained in:
parent
dcfade91e9
commit
471e4748b3
11 changed files with 243 additions and 119 deletions
|
@ -150,7 +150,9 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
|
||||||
_touchpad_scale(66),
|
_touchpad_scale(66),
|
||||||
_dpad_scale(4),
|
_dpad_scale(4),
|
||||||
_fingersDown(0),
|
_fingersDown(0),
|
||||||
_trackball_scale(2) {
|
_trackball_scale(2),
|
||||||
|
_joystickPressing(Common::KEYCODE_INVALID),
|
||||||
|
_arrows_texture(0) {
|
||||||
|
|
||||||
_fsFactory = new POSIXFilesystemFactory();
|
_fsFactory = new POSIXFilesystemFactory();
|
||||||
|
|
||||||
|
@ -180,8 +182,6 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
_activePointers[i] = -1;
|
_activePointers[i] = -1;
|
||||||
|
|
||||||
_joystickPressing = Common::KEYCODE_INVALID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OSystem_Android::~OSystem_Android() {
|
OSystem_Android::~OSystem_Android() {
|
||||||
|
@ -194,6 +194,11 @@ OSystem_Android::~OSystem_Android() {
|
||||||
delete _timerManager;
|
delete _timerManager;
|
||||||
_timerManager = 0;
|
_timerManager = 0;
|
||||||
|
|
||||||
|
if (_arrows_texture) {
|
||||||
|
delete _arrows_texture;
|
||||||
|
_arrows_texture = 0;
|
||||||
|
}
|
||||||
|
|
||||||
deleteMutex(_event_queue_lock);
|
deleteMutex(_event_queue_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -252,18 +252,10 @@ private:
|
||||||
kTouchAreaCenter = 0xfffe,
|
kTouchAreaCenter = 0xfffe,
|
||||||
kTouchAreaRight = 0xfffd,
|
kTouchAreaRight = 0xfffd,
|
||||||
kTouchAreaNone = 0xfffc,
|
kTouchAreaNone = 0xfffc,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint16 getTouchArea(int x, int y);
|
uint16 getTouchArea(int x, int y);
|
||||||
|
|
||||||
struct VirtControl {
|
|
||||||
int x, y;
|
|
||||||
bool sticky;
|
|
||||||
Common::KeyCode keyCode;
|
|
||||||
bool active;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Pointer {
|
struct Pointer {
|
||||||
uint16 startX, startY;
|
uint16 startX, startY;
|
||||||
uint16 currentX, currentY;
|
uint16 currentX, currentY;
|
||||||
|
@ -271,16 +263,27 @@ private:
|
||||||
bool active;
|
bool active;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CardinalSwipe {
|
||||||
|
CardinalSwipe(int dX, int dY);
|
||||||
|
uint16 distance;
|
||||||
|
enum Direction {
|
||||||
|
kDirectionLeft,
|
||||||
|
kDirectionUp,
|
||||||
|
kDirectionRight,
|
||||||
|
kDirectionDown
|
||||||
|
} direction;
|
||||||
|
};
|
||||||
|
|
||||||
enum { kNumPointers = 5 };
|
enum { kNumPointers = 5 };
|
||||||
static int _virt_numControls;
|
|
||||||
static VirtControl _virtcontrols[];
|
|
||||||
int _virt_numDivisions;
|
|
||||||
Pointer _pointers[kNumPointers];
|
Pointer _pointers[kNumPointers];
|
||||||
int _activePointers[4];
|
int _activePointers[4];
|
||||||
Common::KeyCode _joystickPressing;
|
Common::KeyCode _joystickPressing;
|
||||||
int &pointerFor(TouchArea ta);
|
int &pointerFor(TouchArea ta);
|
||||||
|
const Common::Rect clipFor(const CardinalSwipe &cs);
|
||||||
|
|
||||||
void initVirtControls();
|
void initVirtControls();
|
||||||
void drawVirtControls();
|
void drawVirtControls();
|
||||||
|
GLESTexture *_arrows_texture;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// PaletteManager API
|
// PaletteManager API
|
||||||
|
|
|
@ -23,6 +23,7 @@ PATH_DIST = $(srcdir)/dists/android
|
||||||
PATH_RESOURCES = $(PATH_DIST)/res
|
PATH_RESOURCES = $(PATH_DIST)/res
|
||||||
|
|
||||||
PORT_DISTFILES = $(PATH_DIST)/README.Android
|
PORT_DISTFILES = $(PATH_DIST)/README.Android
|
||||||
|
DIST_ANDROID_CONTROLS = $(PATH_DIST)/assets/arrows.tga
|
||||||
|
|
||||||
RESOURCES = \
|
RESOURCES = \
|
||||||
$(PATH_RESOURCES)/values/strings.xml \
|
$(PATH_RESOURCES)/values/strings.xml \
|
||||||
|
@ -121,9 +122,9 @@ $(PATH_STAGE_PREFIX).%/res/drawable/residualvm.png: $(PATH_RESOURCES)/drawable/r
|
||||||
@$(MKDIR) -p $(@D)
|
@$(MKDIR) -p $(@D)
|
||||||
$(CP) $< $@
|
$(CP) $< $@
|
||||||
|
|
||||||
$(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA)
|
$(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_ANDROID_CONTROLS)
|
||||||
$(INSTALL) -d $(PATH_BUILD_ASSETS)
|
$(INSTALL) -d $(PATH_BUILD_ASSETS)
|
||||||
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(PATH_BUILD_ASSETS)/
|
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_ANDROID_CONTROLS) $(PATH_BUILD_ASSETS)/
|
||||||
work_dir=`pwd`; \
|
work_dir=`pwd`; \
|
||||||
for i in $(PATH_BUILD_ASSETS)/*.zip; do \
|
for i in $(PATH_BUILD_ASSETS)/*.zip; do \
|
||||||
echo "recompress $$i"; \
|
echo "recompress $$i"; \
|
||||||
|
|
|
@ -235,6 +235,25 @@ static Common::KeyCode determineKey(int dX, int dY) {
|
||||||
return Common::KEYCODE_INVALID;
|
return Common::KEYCODE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OSystem_Android::CardinalSwipe::CardinalSwipe(int dX, int dY) {
|
||||||
|
if (abs(dX) > abs(dY)) {
|
||||||
|
if (dX > 0) {
|
||||||
|
distance = dX;
|
||||||
|
direction = kDirectionRight;
|
||||||
|
} else {
|
||||||
|
distance = abs(dX);
|
||||||
|
direction = kDirectionLeft;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dY > 0) {
|
||||||
|
distance = dY;
|
||||||
|
direction = kDirectionDown;
|
||||||
|
} else {
|
||||||
|
distance = abs(dY);
|
||||||
|
direction = kDirectionUp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const int kQueuedInputEventDelay = 50;
|
static const int kQueuedInputEventDelay = 50;
|
||||||
|
|
||||||
|
@ -328,28 +347,7 @@ void OSystem_Android::updateEventScale() {
|
||||||
_eventScaleX = 100 * 640 / tex->width();
|
_eventScaleX = 100 * 640 / tex->width();
|
||||||
}
|
}
|
||||||
|
|
||||||
int OSystem_Android::_virt_numControls = 6;
|
|
||||||
OSystem_Android::VirtControl OSystem_Android::_virtcontrols[] = {
|
|
||||||
{-2, 1, false, Common::KEYCODE_u, false},
|
|
||||||
{-3, 1, false, Common::KEYCODE_p, false},
|
|
||||||
{-1, 5, false, Common::KEYCODE_i, false},
|
|
||||||
{-1, 0, false, Common::KEYCODE_PAGEDOWN, false},
|
|
||||||
{-1, 1, false, Common::KEYCODE_KP_ENTER, false},
|
|
||||||
{-1, 2, false, Common::KEYCODE_PAGEUP, false},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
uint16 OSystem_Android::getTouchArea(int x, int y) {
|
uint16 OSystem_Android::getTouchArea(int x, int y) {
|
||||||
int scaledX = _virt_numDivisions * x / _egl_surface_width;
|
|
||||||
int scaledY = _virt_numDivisions * (_egl_surface_height - y) / _egl_surface_height;
|
|
||||||
for (uint16 i = 0; i < _virt_numControls; ++i) {
|
|
||||||
int testX = _virtcontrols[i].x < 0
|
|
||||||
? (_virtcontrols[i].x + _virt_numDivisions)
|
|
||||||
: _virtcontrols[i].x;
|
|
||||||
if (scaledX == testX && scaledY == _virtcontrols[i].y)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
float xPercent = float(x) / _egl_surface_width;
|
float xPercent = float(x) / _egl_surface_width;
|
||||||
|
|
||||||
if (xPercent < 0.3)
|
if (xPercent < 0.3)
|
||||||
|
@ -707,8 +705,6 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||||
if (idx == kTouchAreaCenter) {
|
if (idx == kTouchAreaCenter) {
|
||||||
e.kbd.keycode = Common::KEYCODE_RETURN;
|
e.kbd.keycode = Common::KEYCODE_RETURN;
|
||||||
e.kbd.ascii = Common::ASCII_RETURN;
|
e.kbd.ascii = Common::ASCII_RETURN;
|
||||||
} else {
|
|
||||||
e.kbd.keycode = _virtcontrols[idx].keyCode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lockMutex(_event_queue_lock);
|
lockMutex(_event_queue_lock);
|
||||||
|
@ -813,9 +809,6 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||||
_pointers[arg1].startX = _pointers[arg1].currentX = arg3;
|
_pointers[arg1].startX = _pointers[arg1].currentX = arg3;
|
||||||
_pointers[arg1].startY = _pointers[arg1].currentY = arg4;
|
_pointers[arg1].startY = _pointers[arg1].currentY = arg4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (touchArea == kTouchAreaJoystick)
|
|
||||||
LOGW("Started joystick move at (%d,%d)", arg3, arg4);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -839,7 +832,6 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||||
|
|
||||||
_joystickPressing = newPressing;
|
_joystickPressing = newPressing;
|
||||||
}
|
}
|
||||||
LOGW("Joystick moved to (%d,%d)", arg3, arg4);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -880,34 +872,36 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||||
|
|
||||||
unlockMutex(_event_queue_lock);
|
unlockMutex(_event_queue_lock);
|
||||||
} else {
|
} else {
|
||||||
_pointers[arg1].active = false;
|
|
||||||
int dX = _pointers[arg1].currentX - _pointers[arg1].startX;
|
int dX = _pointers[arg1].currentX - _pointers[arg1].startX;
|
||||||
int dY = _pointers[arg1].currentY - _pointers[arg1].startY;
|
int dY = _pointers[arg1].currentY - _pointers[arg1].startY;
|
||||||
|
struct CardinalSwipe cs(dX, dY);
|
||||||
|
|
||||||
switch (_pointers[arg1].function) {
|
switch (_pointers[arg1].function) {
|
||||||
case kTouchAreaCenter: {
|
case kTouchAreaCenter: {
|
||||||
pointerFor(kTouchAreaCenter) = -1;
|
pointerFor(kTouchAreaCenter) = -1;
|
||||||
if (abs(dX) < 100 && abs(dY) < 100) {
|
if (cs.distance < 100) {
|
||||||
sendKey(Common::KEYCODE_u);
|
sendKey(Common::KEYCODE_RETURN);
|
||||||
} else if (abs(dX) > abs(dY)) {
|
break;
|
||||||
if (dX > 0) {
|
}
|
||||||
sendKey(Common::KEYCODE_RIGHT);
|
switch (cs.direction) {
|
||||||
} else {
|
case CardinalSwipe::kDirectionLeft:
|
||||||
sendKey(Common::KEYCODE_LEFT);
|
sendKey(Common::KEYCODE_LEFT);
|
||||||
}
|
break;
|
||||||
} else {
|
case CardinalSwipe::kDirectionUp:
|
||||||
if (dY > 0) {
|
sendKey(Common::KEYCODE_UP);
|
||||||
sendKey(Common::KEYCODE_DOWN);
|
break;
|
||||||
} else {
|
case CardinalSwipe::kDirectionRight:
|
||||||
sendKey(Common::KEYCODE_UP);
|
sendKey(Common::KEYCODE_RIGHT);
|
||||||
}
|
break;
|
||||||
|
case CardinalSwipe::kDirectionDown:
|
||||||
|
sendKey(Common::KEYCODE_DOWN);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case kTouchAreaJoystick:
|
case kTouchAreaJoystick:
|
||||||
pointerFor(kTouchAreaJoystick) = -1;
|
pointerFor(kTouchAreaJoystick) = -1;
|
||||||
LOGW("Joystick move ended at (%d,%d)", arg3, arg4);
|
|
||||||
if (_joystickPressing != Common::KEYCODE_INVALID) {
|
if (_joystickPressing != Common::KEYCODE_INVALID) {
|
||||||
lockMutex(_event_queue_lock);
|
lockMutex(_event_queue_lock);
|
||||||
e.kbd.keycode = _joystickPressing;
|
e.kbd.keycode = _joystickPressing;
|
||||||
|
@ -919,13 +913,15 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||||
|
|
||||||
case kTouchAreaRight:
|
case kTouchAreaRight:
|
||||||
pointerFor(kTouchAreaRight) = -1;
|
pointerFor(kTouchAreaRight) = -1;
|
||||||
if (abs(dX) > 50 || abs(dY) < 100) {
|
if ( cs.direction == CardinalSwipe::kDirectionLeft
|
||||||
|
|| cs.direction == CardinalSwipe::kDirectionRight
|
||||||
|
|| cs.distance < 100) {
|
||||||
sendKey(Common::KEYCODE_i);
|
sendKey(Common::KEYCODE_i);
|
||||||
} else {
|
} else {
|
||||||
if (dY > 0) {
|
if (cs.direction == CardinalSwipe::kDirectionUp) {
|
||||||
sendKey(Common::KEYCODE_PAGEDOWN);
|
|
||||||
} else {
|
|
||||||
sendKey(Common::KEYCODE_PAGEUP);
|
sendKey(Common::KEYCODE_PAGEUP);
|
||||||
|
} else {
|
||||||
|
sendKey(Common::KEYCODE_PAGEDOWN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -934,6 +930,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
_pointers[arg1].active = false;
|
||||||
_pointers[arg1].function = kTouchAreaNone;
|
_pointers[arg1].function = kTouchAreaNone;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
#include "common/endian.h"
|
#include "common/endian.h"
|
||||||
#include "graphics/conversion.h"
|
#include "graphics/conversion.h"
|
||||||
|
#include "graphics/decoders/tga.h"
|
||||||
#include "graphics/opengles2/shader.h"
|
#include "graphics/opengles2/shader.h"
|
||||||
|
|
||||||
#include "backends/platform/android/android.h"
|
#include "backends/platform/android/android.h"
|
||||||
|
@ -569,57 +570,82 @@ void OSystem_Android::updateScreen() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Graphics::Shader *_virtcontrols_shader = NULL;
|
static GLES8888Texture *loadBuiltinTexture(const char *filename) {
|
||||||
static const char *_virtVertex =
|
Common::ArchiveMemberPtr member = SearchMan.getMember(filename);
|
||||||
"#version 100\n"
|
Common::SeekableReadStream *str = member->createReadStream();
|
||||||
"attribute vec2 position;\n"
|
Graphics::TGADecoder dec;
|
||||||
"uniform vec2 offsetXY;\n"
|
dec.loadStream(*str);
|
||||||
"uniform vec2 sizeWH;\n"
|
void *pixels = dec.getSurface()->pixels;
|
||||||
"void main() {\n"
|
|
||||||
"vec2 pos = offsetXY + position * sizeWH;\n"
|
|
||||||
"pos.x = pos.x * 2.0 - 1.0;\n"
|
|
||||||
"pos.y = pos.y * 2.0 - 1.0;\n"
|
|
||||||
"gl_Position = vec4(pos, 0.0, 1.0);\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
static const char *_virtFragment =
|
GLES8888Texture *ret = new GLES8888Texture();
|
||||||
"#version 100\n"
|
uint16 w = dec.getSurface()->w;
|
||||||
"precision mediump float;\n"
|
uint16 h = dec.getSurface()->h;
|
||||||
"uniform bool active;\n"
|
uint16 pitch = dec.getSurface()->pitch;
|
||||||
"void main() {\n"
|
ret->allocBuffer(w, h);
|
||||||
"gl_FragColor = vec4(1.0, 1.0, 1.0, active ? 0.8 : 0.3);\n"
|
ret->updateBuffer(0, 0, w, h, pixels, pitch);
|
||||||
"}\n";
|
|
||||||
|
delete str;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void OSystem_Android::initVirtControls() {
|
void OSystem_Android::initVirtControls() {
|
||||||
if (_virtcontrols_shader)
|
if (!_arrows_texture)
|
||||||
return;
|
_arrows_texture = loadBuiltinTexture("arrows.tga");
|
||||||
|
}
|
||||||
|
|
||||||
const char* attributes[] = { "position", NULL };
|
const Common::Rect OSystem_Android::clipFor(const CardinalSwipe &cs) {
|
||||||
_virtcontrols_shader = Graphics::Shader::fromStrings("key", _virtVertex, _virtFragment, attributes);
|
switch (cs.direction) {
|
||||||
_virtcontrols_shader->enableVertexAttribute("position", g_verticesVBO, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
|
case CardinalSwipe::kDirectionLeft:
|
||||||
_virt_numDivisions = _egl_surface_width > 800 ? 12 : 8;
|
return Common::Rect(0, 128, 128, 256);
|
||||||
|
case CardinalSwipe::kDirectionUp:
|
||||||
|
return Common::Rect(0, 0, 128, 128);
|
||||||
|
case CardinalSwipe::kDirectionRight:
|
||||||
|
return Common::Rect(128, 128, 256, 256);
|
||||||
|
case CardinalSwipe::kDirectionDown:
|
||||||
|
return Common::Rect(128, 0, 256, 128);
|
||||||
|
default: // unreachable
|
||||||
|
return Common::Rect(0, 0, 1, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_Android::drawVirtControls() {
|
void OSystem_Android::drawVirtControls() {
|
||||||
if (_show_overlay)
|
if (_show_overlay)
|
||||||
return;
|
return;
|
||||||
_virtcontrols_shader->use();
|
|
||||||
float div = 1.0 / _virt_numDivisions;
|
|
||||||
float divX = div;
|
|
||||||
float divY = div;
|
|
||||||
_virtcontrols_shader->setUniform("sizeWH", 0.9 * Math::Vector2d(divX, divY));
|
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
int joyPtr = pointerFor(kTouchAreaJoystick);
|
||||||
|
if (joyPtr != -1) {
|
||||||
|
Pointer &joy = _pointers[joyPtr];
|
||||||
|
CardinalSwipe cs(joy.currentX - joy.startX, joy.currentY - joy.startY);
|
||||||
|
|
||||||
for (int control = 0; control < _virt_numControls; ++control) {
|
if (cs.distance >= 50) {
|
||||||
float offsetX = (_virtcontrols[control].x + 0.1) * divX;
|
Common::Rect clip = clipFor(cs);
|
||||||
float offsetY = (_virtcontrols[control].y + 0.1) * divY;
|
_arrows_texture->drawTexture(2 * _egl_surface_width / 10, _egl_surface_height / 2, 64, 64, clip);
|
||||||
if (offsetX < 0)
|
}
|
||||||
offsetX += 1.0;
|
}
|
||||||
|
|
||||||
_virtcontrols_shader->setUniform("offsetXY", Math::Vector2d(offsetX, offsetY));
|
int centerPtr = pointerFor(kTouchAreaCenter);
|
||||||
_virtcontrols_shader->setUniform("active", _virtcontrols[control].active);
|
if (centerPtr != -1) {
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
Pointer ¢er = _pointers[centerPtr];
|
||||||
|
CardinalSwipe cs(center.currentX - center.startX, center.currentY - center.startY);
|
||||||
|
|
||||||
|
if (cs.distance >= 100) {
|
||||||
|
Common::Rect clip = clipFor(cs);
|
||||||
|
_arrows_texture->drawTexture(_egl_surface_width / 2, _egl_surface_height / 2, 64, 64, clip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rightPtr = pointerFor(kTouchAreaRight);
|
||||||
|
if (rightPtr != -1) {
|
||||||
|
Pointer &right = _pointers[rightPtr];
|
||||||
|
CardinalSwipe cs(right.currentX - right.startX, right.currentY - right.startY);
|
||||||
|
|
||||||
|
if (cs.distance >= 100) {
|
||||||
|
if ( cs.direction == CardinalSwipe::kDirectionDown
|
||||||
|
|| cs.direction == CardinalSwipe::kDirectionUp) {
|
||||||
|
Common::Rect clip = clipFor(cs);
|
||||||
|
_arrows_texture->drawTexture( 8 * _egl_surface_width / 10, _egl_surface_height / 2, 64, 64, clip);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ void GLESBaseTexture::initGL() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* attributes[] = { "position", "texcoord", NULL };
|
const char* attributes[] = { "position", "texcoord", NULL };
|
||||||
g_box_shader = Graphics::Shader::fromStrings("box", Graphics::BuiltinShaders::boxVertex, Graphics::BuiltinShaders::boxFragment, attributes);
|
g_box_shader = Graphics::Shader::fromStrings("control", Graphics::BuiltinShaders::controlVertex, Graphics::BuiltinShaders::controlFragment, attributes);
|
||||||
g_verticesVBO = Graphics::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(vertices), vertices);
|
g_verticesVBO = Graphics::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(vertices), vertices);
|
||||||
g_box_shader->enableVertexAttribute("position", g_verticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
|
g_box_shader->enableVertexAttribute("position", g_verticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
|
||||||
g_box_shader->enableVertexAttribute("texcoord", g_verticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
|
g_box_shader->enableVertexAttribute("texcoord", g_verticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
|
||||||
|
@ -186,7 +186,7 @@ void GLESBaseTexture::allocBuffer(GLuint w, GLuint h) {
|
||||||
initSize();
|
initSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLESBaseTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
|
void GLESBaseTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip) {
|
||||||
// LOGD("*** Texture %p: Drawing %dx%d rect to (%d,%d)", this, w, h, x, y);
|
// LOGD("*** Texture %p: Drawing %dx%d rect to (%d,%d)", this, w, h, x, y);
|
||||||
|
|
||||||
assert(g_box_shader);
|
assert(g_box_shader);
|
||||||
|
@ -197,13 +197,14 @@ void GLESBaseTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
|
||||||
const GLfloat offsetY = float(y) / float(JNI::egl_surface_height);
|
const GLfloat offsetY = float(y) / float(JNI::egl_surface_height);
|
||||||
const GLfloat sizeW = float(w) / float(JNI::egl_surface_width);
|
const GLfloat sizeW = float(w) / float(JNI::egl_surface_width);
|
||||||
const GLfloat sizeH = float(h) / float(JNI::egl_surface_height);
|
const GLfloat sizeH = float(h) / float(JNI::egl_surface_height);
|
||||||
const GLfloat tex_width = float(_surface.w) / float(_texture_width);
|
Math::Vector4d clipV = Math::Vector4d(clip.left, clip.top, clip.right, clip.bottom);
|
||||||
const GLfloat tex_height = float(_surface.h) / float(_texture_height);
|
clipV.x() /= _texture_width; clipV.y() /= _texture_height;
|
||||||
|
clipV.z() /= _texture_width; clipV.w() /= _texture_height;
|
||||||
// LOGD("*** Drawing at (%f,%f) , size %f x %f", float(x) / float(_surface.w), float(y) / float(_surface.h), tex_width, tex_height);
|
// LOGD("*** Drawing at (%f,%f) , size %f x %f", float(x) / float(_surface.w), float(y) / float(_surface.h), tex_width, tex_height);
|
||||||
|
|
||||||
g_box_shader->setUniform("offsetXY", Math::Vector2d(offsetX, offsetY));
|
g_box_shader->setUniform("offsetXY", Math::Vector2d(offsetX, offsetY));
|
||||||
g_box_shader->setUniform("sizeWH", Math::Vector2d(sizeW, sizeH));
|
g_box_shader->setUniform("sizeWH", Math::Vector2d(sizeW, sizeH));
|
||||||
g_box_shader->setUniform("texcrop", Math::Vector2d(tex_width, tex_height));
|
g_box_shader->setUniform("clip", clipV);
|
||||||
g_box_shader->setUniform("flipY", !_is_game_texture);
|
g_box_shader->setUniform("flipY", !_is_game_texture);
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
@ -281,7 +282,7 @@ void GLESTexture::fillBuffer(uint32 color) {
|
||||||
setDirty();
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
|
void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip) {
|
||||||
if (_all_dirty) {
|
if (_all_dirty) {
|
||||||
_dirty_rect.top = 0;
|
_dirty_rect.top = 0;
|
||||||
_dirty_rect.left = 0;
|
_dirty_rect.left = 0;
|
||||||
|
@ -323,7 +324,7 @@ void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
|
||||||
dwidth, dheight, _glFormat, _glType, _tex));
|
dwidth, dheight, _glFormat, _glType, _tex));
|
||||||
}
|
}
|
||||||
|
|
||||||
GLESBaseTexture::drawTexture(x, y, w, h);
|
GLESBaseTexture::drawTexture(x, y, w, h, clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES4444Texture::GLES4444Texture() :
|
GLES4444Texture::GLES4444Texture() :
|
||||||
|
@ -333,6 +334,13 @@ GLES4444Texture::GLES4444Texture() :
|
||||||
GLES4444Texture::~GLES4444Texture() {
|
GLES4444Texture::~GLES4444Texture() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLES8888Texture::GLES8888Texture() :
|
||||||
|
GLESTexture(GL_RGBA, GL_UNSIGNED_BYTE, pixelFormat()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
GLES8888Texture::~GLES8888Texture() {
|
||||||
|
}
|
||||||
|
|
||||||
GLES5551Texture::GLES5551Texture() :
|
GLES5551Texture::GLES5551Texture() :
|
||||||
GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixelFormat()) {
|
GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixelFormat()) {
|
||||||
}
|
}
|
||||||
|
@ -419,8 +427,7 @@ void GLESFakePaletteTexture::updateBuffer(GLuint x, GLuint y, GLuint w,
|
||||||
} while (--h);
|
} while (--h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLESFakePaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w,
|
void GLESFakePaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip) {
|
||||||
GLshort h) {
|
|
||||||
if (_all_dirty) {
|
if (_all_dirty) {
|
||||||
_dirty_rect.top = 0;
|
_dirty_rect.top = 0;
|
||||||
_dirty_rect.left = 0;
|
_dirty_rect.left = 0;
|
||||||
|
@ -452,7 +459,7 @@ void GLESFakePaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w,
|
||||||
dwidth, dheight, _glFormat, _glType, _buf));
|
dwidth, dheight, _glFormat, _glType, _buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
GLESBaseTexture::drawTexture(x, y, w, h);
|
GLESBaseTexture::drawTexture(x, y, w, h, clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Graphics::PixelFormat &GLESFakePaletteTexture::getPixelFormat() const {
|
const Graphics::PixelFormat &GLESFakePaletteTexture::getPixelFormat() const {
|
||||||
|
|
|
@ -57,7 +57,11 @@ public:
|
||||||
const void *buf, int pitch_buf) = 0;
|
const void *buf, int pitch_buf) = 0;
|
||||||
virtual void fillBuffer(uint32 color) = 0;
|
virtual void fillBuffer(uint32 color) = 0;
|
||||||
|
|
||||||
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
|
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
|
||||||
|
drawTexture(x, y, w, h, Common::Rect(0, 0, width(), height()));
|
||||||
|
}
|
||||||
|
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip);
|
||||||
|
|
||||||
|
|
||||||
inline void setDrawRect(const Common::Rect &rect) {
|
inline void setDrawRect(const Common::Rect &rect) {
|
||||||
_draw_rect = rect;
|
_draw_rect = rect;
|
||||||
|
@ -203,13 +207,26 @@ public:
|
||||||
const void *buf, int pitch_buf);
|
const void *buf, int pitch_buf);
|
||||||
virtual void fillBuffer(uint32 color);
|
virtual void fillBuffer(uint32 color);
|
||||||
|
|
||||||
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
|
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
|
||||||
|
drawTexture(x, y, w, h, Common::Rect(0, 0, width(), height()));
|
||||||
|
}
|
||||||
|
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
byte *_pixels;
|
byte *_pixels;
|
||||||
byte *_buf;
|
byte *_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GLES8888Texture : public GLESTexture {
|
||||||
|
public:
|
||||||
|
GLES8888Texture();
|
||||||
|
virtual ~GLES8888Texture();
|
||||||
|
|
||||||
|
static Graphics::PixelFormat pixelFormat() {
|
||||||
|
return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// RGBA4444 texture
|
// RGBA4444 texture
|
||||||
class GLES4444Texture : public GLESTexture {
|
class GLES4444Texture : public GLESTexture {
|
||||||
public:
|
public:
|
||||||
|
@ -256,7 +273,10 @@ public:
|
||||||
const void *buf, int pitch_buf);
|
const void *buf, int pitch_buf);
|
||||||
virtual void fillBuffer(uint32 color);
|
virtual void fillBuffer(uint32 color);
|
||||||
|
|
||||||
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
|
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
|
||||||
|
drawTexture(x, y, w, h, Common::Rect(0, 0, width(), height()));
|
||||||
|
}
|
||||||
|
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip);
|
||||||
|
|
||||||
virtual const byte *palette_const() const {
|
virtual const byte *palette_const() const {
|
||||||
return (byte *)_palette;
|
return (byte *)_palette;
|
||||||
|
|
BIN
dists/android/assets/arrows.tga
Normal file
BIN
dists/android/assets/arrows.tga
Normal file
Binary file not shown.
After Width: | Height: | Size: 256 KiB |
|
@ -23,6 +23,7 @@ MODULE_OBJS := \
|
||||||
pixelbuffer.o \
|
pixelbuffer.o \
|
||||||
opengles2/shader.o \
|
opengles2/shader.o \
|
||||||
opengles2/box_shaders.o \
|
opengles2/box_shaders.o \
|
||||||
|
opengles2/control_shaders.o \
|
||||||
opengles2/compat_shaders.o \
|
opengles2/compat_shaders.o \
|
||||||
tinygl/api.o \
|
tinygl/api.o \
|
||||||
tinygl/arrays.o \
|
tinygl/arrays.o \
|
||||||
|
|
65
graphics/opengles2/control_shaders.cpp
Normal file
65
graphics/opengles2/control_shaders.cpp
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/scummsys.h"
|
||||||
|
|
||||||
|
#ifdef USE_GLES2
|
||||||
|
|
||||||
|
namespace Graphics {
|
||||||
|
namespace BuiltinShaders {
|
||||||
|
|
||||||
|
const char *controlVertex =
|
||||||
|
"#version 100\n"
|
||||||
|
"attribute vec2 position;\n"
|
||||||
|
"attribute vec2 texcoord;\n"
|
||||||
|
"uniform vec2 offsetXY;\n"
|
||||||
|
"uniform vec2 sizeWH;\n"
|
||||||
|
"uniform vec4 clip;\n"
|
||||||
|
"uniform bool flipY;\n"
|
||||||
|
"varying vec2 Texcoord;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
"Texcoord = clip.xy + texcoord * (clip.zw - clip.xy);\n"
|
||||||
|
"vec2 pos = offsetXY + position * sizeWH;\n"
|
||||||
|
"pos.x = pos.x * 2.0 - 1.0;\n"
|
||||||
|
"pos.y = pos.y * 2.0 - 1.0;\n"
|
||||||
|
"if (flipY)\n"
|
||||||
|
"pos.y *= -1.0;\n"
|
||||||
|
"gl_Position = vec4(pos, 0.0, 1.0);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
const char *controlFragment =
|
||||||
|
"#version 100\n"
|
||||||
|
"#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
|
||||||
|
"precision highp float;\n"
|
||||||
|
"#else\n"
|
||||||
|
"precision mediump float;\n"
|
||||||
|
"#endif\n"
|
||||||
|
"varying vec2 Texcoord;\n"
|
||||||
|
"uniform sampler2D tex;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
"gl_FragColor = texture2D(tex, Texcoord);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -34,10 +34,9 @@
|
||||||
namespace Graphics {
|
namespace Graphics {
|
||||||
|
|
||||||
namespace BuiltinShaders {
|
namespace BuiltinShaders {
|
||||||
extern const char *boxVertex;
|
extern const char *boxVertex, *boxFragment;
|
||||||
extern const char *boxFragment;
|
extern const char *compatVertex, *compatFragment;
|
||||||
extern const char *compatVertex;
|
extern const char *controlVertex, *controlFragment;
|
||||||
extern const char *compatFragment;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VertexAttrib {
|
struct VertexAttrib {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue