DS: WIP virtual keyboard support

This commit is contained in:
Cameron Cawley 2021-08-25 22:21:58 +01:00
parent 78f0c7a3c7
commit 224d626e65
8 changed files with 261 additions and 26 deletions

View File

@ -69,25 +69,27 @@ void DSEventSource::addEventsToQueue() {
uint32 held = keysHeld(), keysPressed = keysDown(), keysReleased = keysUp();
// Touch screen events
if (held & KEY_TOUCH) {
touchPosition touchPos;
touchRead(&touchPos);
event.mouse = dynamic_cast<OSystem_DS *>(g_system)->transformPoint(touchPos.px, touchPos.py);
if (_handleTouch) {
if (held & KEY_TOUCH) {
touchPosition touchPos;
touchRead(&touchPos);
event.mouse = dynamic_cast<OSystem_DS *>(g_system)->transformPoint(touchPos.px, touchPos.py);
if (event.mouse.x != _lastTouch.x || event.mouse.y != _lastTouch.y) {
event.type = Common::EVENT_MOUSEMOVE;
if (event.mouse.x != _lastTouch.x || event.mouse.y != _lastTouch.y) {
event.type = Common::EVENT_MOUSEMOVE;
_eventQueue.push(event);
}
if (keysPressed & KEY_TOUCH) {
event.type = Common::EVENT_LBUTTONDOWN;
_eventQueue.push(event);
}
_lastTouch = event.mouse;
} else if (keysReleased & KEY_TOUCH) {
event.mouse = _lastTouch;
event.type = Common::EVENT_LBUTTONUP;
_eventQueue.push(event);
}
if (keysPressed & KEY_TOUCH) {
event.type = Common::EVENT_LBUTTONDOWN;
_eventQueue.push(event);
}
_lastTouch = event.mouse;
} else if (keysReleased & KEY_TOUCH) {
event.mouse = _lastTouch;
event.type = Common::EVENT_LBUTTONUP;
_eventQueue.push(event);
}
// Button events

View File

@ -30,17 +30,20 @@
*/
class DSEventSource : public Common::EventSource {
public:
DSEventSource() : _firstPoll(true) {}
DSEventSource() : _firstPoll(true), _handleTouch(true) {}
/**
* Gets and processes events.
*/
virtual bool pollEvent(Common::Event &event);
virtual void handleTouch(bool enabled) { _handleTouch = enabled; }
protected:
Common::Queue<Common::Event> _eventQueue;
Common::Point _lastTouch;
bool _firstPoll;
bool _handleTouch;
void addEventsToQueue();
void addJoyButtonEvent(u32 keysPressed, u32 keysReleased, u32 ndsKey, uint8 svmButton);

View File

@ -149,6 +149,7 @@ void initHardware() {
videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
vramSetBankB(VRAM_B_MAIN_BG_0x06020000);
vramSetBankC(VRAM_C_SUB_BG_0x06200000);
vramSetBankD(VRAM_D_MAIN_BG_0x06040000);
vramSetBankE(VRAM_E_MAIN_SPRITE);
@ -159,19 +160,15 @@ void initHardware() {
subScTargetX = 0;
subScTargetY = 0;
lcdMainOnBottom();
//irqs are nice
irqSet(IRQ_VBLANK, VBlankHandler);
irqEnable(IRQ_VBLANK);
#ifndef DISABLE_TEXT_CONSOLE
videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
vramSetBankH(VRAM_H_SUB_BG);
consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 15, 0, false, true);
videoSetModeSub(MODE_0_2D);
consoleInit(NULL, 1, BgType_Text4bpp, BgSize_T_256x256, 30, 0, false, true);
#else
videoSetModeSub(MODE_3_2D | DISPLAY_BG3_ACTIVE);
vramSetBankC(VRAM_C_SUB_BG_0x06200000);
#endif
}
@ -180,10 +177,15 @@ void initHardware() {
void OSystem_DS::initGraphics() {
DS::initHardware();
setSwapLCDs(false);
oamInit(&oamMain, SpriteMapping_Bmp_1D_128, false);
_cursorSprite = oamAllocateGfx(&oamMain, SpriteSize_64x64, SpriteColorFormat_Bmp);
_overlay.create(256, 192, true, 2, false, 0, false);
_keyboard = new DS::Keyboard(_eventManager->getEventDispatcher());
_keyboard->init(0, 34, 1, false);
}
void OSystem_DS::setMainScreen(int32 x, int32 y, int32 sx, int32 sy) {
@ -199,22 +201,42 @@ void OSystem_DS::setSubScreen(int32 x, int32 y, int32 sx, int32 sy) {
}
bool OSystem_DS::hasFeature(Feature f) {
return (f == kFeatureCursorPalette) || (f == kFeatureStretchMode);
return (f == kFeatureCursorPalette) || (f == kFeatureStretchMode) || (f == kFeatureVirtualKeyboard);
}
void OSystem_DS::setFeatureState(Feature f, bool enable) {
if (f == kFeatureCursorPalette) {
_disableCursorPalette = !enable;
_cursorDirty = true;
} else if (f == kFeatureVirtualKeyboard) {
if (enable) {
setSwapLCDs(true);
_keyboard->show();
} else {
_keyboard->hide();
setSwapLCDs(false);
}
}
}
bool OSystem_DS::getFeatureState(Feature f) {
if (f == kFeatureCursorPalette)
return !_disableCursorPalette;
else if (f == kFeatureVirtualKeyboard)
return _keyboard->isVisible();
return false;
}
void OSystem_DS::setSwapLCDs(bool swap) {
if (swap) {
lcdMainOnTop();
_eventSource->handleTouch(false);
} else {
lcdMainOnBottom();
_eventSource->handleTouch(true);
}
}
static const OSystem::GraphicsMode graphicsModes[] = {
{ "NONE", _s("Unscaled"), GFX_NOSCALE },
{ "HW", _s("Hardware scale (fast, but low quality)"), GFX_HWSCALE },

View File

@ -0,0 +1,147 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM 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 <nds.h>
#include "backends/platform/ds/keyboard.h"
#include "common/system.h"
namespace DS {
Keyboard::Keyboard(Common::EventDispatcher *eventDispatcher) :
_eventDispatcher(eventDispatcher),
_lastKey(NOKEY),
_visible(false) {
_eventDispatcher->registerSource(this, false);
_eventDispatcher->registerObserver(this, 10, false);
}
Keyboard::~Keyboard() {
_eventDispatcher->unregisterObserver(this);
_eventDispatcher->unregisterSource(this);
}
void Keyboard::init(int layer, int mapBase, int tileBase, bool mainDisplay) {
keyboardInit(nullptr, layer, BgType_Text4bpp, BgSize_T_256x512, mapBase, tileBase, mainDisplay, true);
}
void Keyboard::show() {
keyboardShow();
_visible = true;
}
void Keyboard::hide() {
keyboardHide();
_visible = false;
}
bool Keyboard::mapKey(int key, Common::KeyState &ks) {
switch (key) {
case DVK_BACKSPACE:
ks = Common::KeyState(Common::KEYCODE_BACKSPACE, Common::ASCII_BACKSPACE);
break;
case DVK_TAB:
ks = Common::KeyState(Common::KEYCODE_TAB, Common::ASCII_TAB);
break;
case DVK_ENTER:
ks = Common::KeyState(Common::KEYCODE_RETURN, Common::ASCII_RETURN);
break;
case DVK_SPACE:
ks = Common::KeyState(Common::KEYCODE_SPACE, Common::ASCII_SPACE);
break;
case DVK_MENU:
ks = Common::KeyState(Common::KEYCODE_MENU);
break;
case DVK_SHIFT:
ks = Common::KeyState(Common::KEYCODE_LSHIFT);
break;
case DVK_CAPS:
ks = Common::KeyState(Common::KEYCODE_CAPSLOCK);
break;
case DVK_CTRL:
ks = Common::KeyState(Common::KEYCODE_LCTRL);
break;
case DVK_UP:
ks = Common::KeyState(Common::KEYCODE_UP);
break;
case DVK_RIGHT:
ks = Common::KeyState(Common::KEYCODE_RIGHT);
break;
case DVK_DOWN:
ks = Common::KeyState(Common::KEYCODE_DOWN);
break;
case DVK_LEFT:
ks = Common::KeyState(Common::KEYCODE_LEFT);
break;
case DVK_FOLD:
ks = Common::KeyState(Common::KEYCODE_ESCAPE, Common::ASCII_ESCAPE);
break;
case DVK_ALT:
ks = Common::KeyState(Common::KEYCODE_LALT);
break;
default:
if (key < Common::KEYCODE_SPACE || key > Common::KEYCODE_z)
return false;
ks = Common::KeyState((Common::KeyCode)tolower(key), key);
break;
}
return true;
}
bool Keyboard::pollEvent(Common::Event &event) {
if (!_visible)
return false;
int key = keyboardUpdate();
if (key == _lastKey)
return false;
if (key == NOKEY) {
event.type = Common::EVENT_KEYUP;
if (!mapKey(_lastKey, event.kbd))
return false;
} else {
event.type = Common::EVENT_KEYDOWN;
if (!mapKey(key, event.kbd))
return false;
}
_lastKey = key;
// TODO: Handle flags
return true;
}
bool Keyboard::notifyEvent(const Common::Event &event) {
if (event.type == Common::EVENT_VIRTUAL_KEYBOARD) {
if (g_system->getFeatureState(OSystem::kFeatureVirtualKeyboard))
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
else
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
return true;
}
return false;
}
} // End of namespace DS

View File

@ -0,0 +1,56 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM 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.
*
*/
#ifndef DS_KEYBOARD_H
#define DS_KEYBOARD_H
#include "common/events.h"
namespace DS {
class Keyboard : public Common::EventSource, public Common::EventObserver {
public:
Keyboard(Common::EventDispatcher *eventDispatcher);
~Keyboard();
void init(int layer, int mapBase, int tileBase, bool mainDisplay);
void show();
void hide();
inline bool isVisible() const { return _visible; }
// Implementation of the EventSource interface
virtual bool pollEvent(Common::Event &event);
virtual bool notifyEvent(const Common::Event &event) override;
protected:
Common::EventDispatcher *_eventDispatcher;
int _lastKey;
bool _visible;
bool mapKey(int key, Common::KeyState &ks);
};
} // End of namespace DS
#endif // #ifndef DS_KEYBOARD_H

View File

@ -5,6 +5,7 @@ MODULE_OBJS := \
blitters_arm.o \
ds-graphics.o \
dsmain.o \
keyboard.o \
osystem_ds.o
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.

View File

@ -71,8 +71,6 @@ void timerTickHandler() {
}
void OSystem_DS::initBackend() {
initGraphics();
defaultExceptionHandler();
ConfMan.setInt("autosave_period", 0);
@ -88,6 +86,8 @@ void OSystem_DS::initBackend() {
_mixerManager = new MaxModMixerManager(11025, 32768);
_mixerManager->init();
initGraphics();
BaseBackend::initBackend();
}

View File

@ -28,6 +28,7 @@
#include "backends/events/ds/ds-events.h"
#include "backends/mixer/mixer.h"
#include "backends/platform/ds/background.h"
#include "backends/platform/ds/keyboard.h"
#include "graphics/surface.h"
#include "graphics/palette.h"
@ -60,6 +61,7 @@ protected:
bool _cursorVisible;
DSEventSource *_eventSource;
DS::Keyboard *_keyboard;
void initGraphics();
@ -145,6 +147,8 @@ public:
virtual void setCursorPalette(const byte *colors, uint start, uint num);
void setSwapLCDs(bool swap);
void refreshCursor(u16 *dst, const Graphics::Surface &src, const uint16 *palette);
virtual void logMessage(LogMessageType::Type type, const char *message);