diff options
Diffstat (limited to 'backends/common')
-rw-r--r-- | backends/common/virtual-keyboard-parser.cpp | 26 | ||||
-rw-r--r-- | backends/common/virtual-keyboard-parser.h | 3 | ||||
-rw-r--r-- | backends/common/virtual-keyboard.cpp | 83 | ||||
-rw-r--r-- | backends/common/virtual-keyboard.h | 40 |
4 files changed, 127 insertions, 25 deletions
diff --git a/backends/common/virtual-keyboard-parser.cpp b/backends/common/virtual-keyboard-parser.cpp index 26da9f465a..8e788f53d4 100644 --- a/backends/common/virtual-keyboard-parser.cpp +++ b/backends/common/virtual-keyboard-parser.cpp @@ -143,8 +143,6 @@ bool VirtualKeyboardParser::parserCallback_Mode() { _keyboard->_modes[name] = mode; _mode = &(_keyboard->_modes[name]); - // if this is the keyboard's initial mode - // then set it to be the current mode if (name == _initialModeName) _keyboard->_initialMode = _mode; } else @@ -153,11 +151,14 @@ bool VirtualKeyboardParser::parserCallback_Mode() { Common::String resolutions = modeNode->values["resolutions"]; Common::StringTokenizer tok (resolutions, " ,"); + // select best resolution simply by minimising the difference between the + // overlay size and the resolution dimensions. + // TODO: improve this by giving preference to a resolution that is smaller + // than the overlay res (so the keyboard can't be too big for the screen) uint16 scrW = g_system->getOverlayWidth(), scrH = g_system->getOverlayHeight(); uint32 diff = 0xFFFFFFFF; Common::String newResolution; for (Common::String res = tok.nextToken(); res.size() > 0; res = tok.nextToken()) { - // TODO: improve the resolution selection int resW, resH; if (sscanf(res.c_str(), "%dx%d", &resW, &resH) != 2) { return parserError("Invalid resolution specification"); @@ -166,7 +167,7 @@ bool VirtualKeyboardParser::parserCallback_Mode() { newResolution = res; break; } else { - uint16 newDiff = ABS(scrW - resW) + ABS(scrH - resH); + uint32 newDiff = ABS(scrW - resW) + ABS(scrH - resH); if (newDiff < diff) { diff = newDiff; newResolution = res; @@ -192,13 +193,15 @@ bool VirtualKeyboardParser::parserCallback_Mode() { } _mode->resolution = newResolution; - + _layoutParsed = false; + return true; } bool VirtualKeyboardParser::parserCallback_ModeClosed() { - if (!_mode->image) + if (!_layoutParsed) { return parserError("'%s' layout missing from '%s' mode", _mode->resolution.c_str(), _mode->name.c_str()); + } return true; } @@ -287,13 +290,22 @@ bool VirtualKeyboardParser::parserCallback_Layout() { _mode->bitmapName = layoutNode->values["bitmap"]; - if (!ImageMan.registerSurface(_mode->bitmapName, 0)) return parserError("Error loading bitmap '%s'", _mode->bitmapName.c_str()); _mode->image = ImageMan.getSurface(_mode->bitmapName); if (!_mode->image) return parserError("Error loading bitmap '%s'", _mode->bitmapName.c_str()); + + if (layoutNode->values.contains("transparent_color")) { + int r, g, b; + if (!parseIntegerKey(layoutNode->values["transparent_color"].c_str(), 3, &r, &g, &b)) + return parserError("Could not parse color value"); + _mode->transparentColor = g_system->RGBToColor(r, g, b); + } else + _mode->transparentColor = g_system->RGBToColor(255, 0, 255); // default to purple + + _layoutParsed = true; return true; } diff --git a/backends/common/virtual-keyboard-parser.h b/backends/common/virtual-keyboard-parser.h index c716d27733..69ca0a99a6 100644 --- a/backends/common/virtual-keyboard-parser.h +++ b/backends/common/virtual-keyboard-parser.h @@ -54,8 +54,9 @@ protected: /** internal state variables of parser */ ParseMode _parseMode; VirtualKeyboard::Mode *_mode; // pointer to mode currently being parsed - Common::String _initialModeName; // name of initial keyboard mode + Common::String _initialModeName; bool _kbdParsed; + bool _layoutParsed; bool keyCallback(Common::String keyName); bool closedKeyCallback(Common::String keyName); diff --git a/backends/common/virtual-keyboard.cpp b/backends/common/virtual-keyboard.cpp index 37fa922bd1..21d188dced 100644 --- a/backends/common/virtual-keyboard.cpp +++ b/backends/common/virtual-keyboard.cpp @@ -27,9 +27,11 @@ #include "backends/common/virtual-keyboard-parser.h" #include "common/config-manager.h" #include "common/events.h" +#include "common/unzip.h" +#include "graphics/cursorman.h" #include "graphics/imageman.h" #include "graphics/surface-keycolored.h" -#include "common/unzip.h" +#include "gui/newgui.h" namespace Common { @@ -40,6 +42,8 @@ VirtualKeyboard::VirtualKeyboard() : _currentMode(0), _keyDown(0) { _parser = new VirtualKeyboardParser(this); _loaded = _displaying = _drag = false; _lastScreenChanged = _system->getScreenChangeID(); + + memset(_cursor, 0xFF, sizeof(_cursor)); } VirtualKeyboard::~VirtualKeyboard() { @@ -76,9 +80,6 @@ void VirtualKeyboard::deleteEventData() { bool VirtualKeyboard::loadKeyboardPack(Common::String packName) { - if (ConfMan.hasKey("extrapath")) - Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); - if (Common::File::exists(packName + ".xml")) { // uncompressed keyboard pack if (!_parser->loadFile(packName + ".xml")) @@ -102,6 +103,7 @@ bool VirtualKeyboard::loadKeyboardPack(Common::String packName) { return false; } } else { + warning("Could not find %s.xml file in %s.zip keyboard pack\n", packName.c_str(), packName.c_str()); unzClose(zipFile); return false; } @@ -210,9 +212,9 @@ void VirtualKeyboard::processClick(const Common::String& area) { } void VirtualKeyboard::switchMode(Mode *newMode) { + _kbdBound.setWidth(newMode->image->w); + _kbdBound.setHeight(newMode->image->h); _currentMode = newMode; - _kbdBound.setWidth(_currentMode->image->w); - _kbdBound.setHeight(_currentMode->image->h); _needRedraw = true; } @@ -226,8 +228,11 @@ void VirtualKeyboard::switchMode(const Common::String& newMode) { void VirtualKeyboard::show() { if (!_loaded) { - warning("Keyboard not loaded therefore can't be shown"); - return; + // if not loaded then load default "vkeybd" pack + if (!loadKeyboardPack("vkeybd")) { + warning("Keyboard not loaded therefore can't be shown"); + return; + } } if (_lastScreenChanged != _system->getScreenChangeID()) screenChanged(); @@ -237,9 +242,22 @@ void VirtualKeyboard::show() { _firstRun = false; setDefaultPosition(); } - _system->showOverlay(); + + if (!g_gui.isActive()) { + _system->showOverlay(); + _system->clearOverlay(); + } + + _overlayBackup.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); + _system->grabOverlay((OverlayColor*)_overlayBackup.pixels, _overlayBackup.w); + setupCursor(); + runLoop(); - _system->hideOverlay(); + + removeCursor(); + _system->copyRectToOverlay((OverlayColor*)_overlayBackup.pixels, _overlayBackup.w, 0, 0, _overlayBackup.w, _overlayBackup.h); + if (!g_gui.isActive()) _system->hideOverlay(); + _overlayBackup.free(); } void VirtualKeyboard::hide() { @@ -258,6 +276,7 @@ void VirtualKeyboard::runLoop() { while (_displaying) { if (_needRedraw) redraw(); + animateCursor(); _system->updateScreen(); Common::Event event; while (eventMan->pollEvent(event)) { @@ -317,10 +336,9 @@ void VirtualKeyboard::redraw() { Graphics::SurfaceKeyColored surf; surf.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); - - _system->clearOverlay(); - _system->grabOverlay((OverlayColor*)surf.pixels, surf.w); - surf.blit(_currentMode->image, _kbdBound.left, _kbdBound.top, _system->RGBToColor(0xff, 0, 0xff)); + + memcpy(surf.pixels, _overlayBackup.pixels, surf.w * surf.h * sizeof(OverlayColor)); + surf.blit(_currentMode->image, _kbdBound.left, _kbdBound.top, _currentMode->transparentColor); _system->copyRectToOverlay((OverlayColor*)surf.pixels, surf.w, 0, 0, surf.w, surf.h); @@ -329,4 +347,39 @@ void VirtualKeyboard::redraw() { _needRedraw = false; } -} // end of namespace GUI +void VirtualKeyboard::setupCursor() { + const byte palette[] = { + 255, 255, 255, 0, + 255, 255, 255, 0, + 171, 171, 171, 0, + 87, 87, 87, 0 + }; + + CursorMan.pushCursorPalette(palette, 0, 4); + CursorMan.pushCursor(NULL, 0, 0, 0, 0); + CursorMan.showMouse(true); +} + +void VirtualKeyboard::animateCursor() { + int time = _system->getMillis(); + if (time > _cursorAnimateTimer + kCursorAnimateDelay) { + for (int i = 0; i < 15; i++) { + if ((i < 6) || (i > 8)) { + _cursor[16 * 7 + i] = _cursorAnimateCounter; + _cursor[16 * i + 7] = _cursorAnimateCounter; + } + } + + CursorMan.replaceCursor(_cursor, 16, 16, 7, 7); + + _cursorAnimateTimer = time; + _cursorAnimateCounter = (_cursorAnimateCounter + 1) % 4; + } +} + +void VirtualKeyboard::removeCursor() { + CursorMan.popCursor(); + CursorMan.popCursorPalette(); +} + +} // end of namespace Common diff --git a/backends/common/virtual-keyboard.h b/backends/common/virtual-keyboard.h index 74c3043a4c..fc2300c24c 100644 --- a/backends/common/virtual-keyboard.h +++ b/backends/common/virtual-keyboard.h @@ -43,7 +43,6 @@ class VirtualKeyboardParser; class VirtualKeyboard { - /** Type of key event */ enum EventType { kEventKey, kEventSwitchMode, @@ -53,6 +52,7 @@ class VirtualKeyboard { struct Event { Common::String name; EventType type; + Graphics::Surface *rollOverImage; void *data; }; @@ -63,6 +63,7 @@ class VirtualKeyboard { Common::String resolution; Common::String bitmapName; Graphics::Surface *image; + OverlayColor transparentColor; Common::ImageMap imageMap; EventMap events; Mode() : image(0) {} @@ -85,13 +86,38 @@ class VirtualKeyboard { public: VirtualKeyboard(); virtual ~VirtualKeyboard(); - + + /** + * Loads the keyboard pack with the given name. + * The system first looks for an uncompressed keyboard pack by searching + * for packName.xml in the filesystem, if this does not exist then it + * searches for a compressed keyboard pack by looking for packName.zip. + * @param packName name of the keyboard pack + */ bool loadKeyboardPack(Common::String packName); + + /** + * Shows the keyboard, starting an event loop that will intercept all + * user input (like a modal GUI dialog). + * It is assumed that the game has been paused, before this is called + */ void show(); + + /** + * Hides the keyboard, ending the event loop. + */ void hide(); + + /** + * Returns true if the keyboard is currently being shown + */ bool isDisplaying() { return _displaying; } + + /** + * Returns true if the keyboard is loaded and ready to be shown + */ bool isLoaded() { return _loaded; } @@ -118,6 +144,8 @@ protected: void runLoop(); void redraw(); + Graphics::Surface _overlayBackup; + bool _loaded; bool _displaying; bool _needRedraw; @@ -140,6 +168,14 @@ protected: Common::Queue<Common::KeyState> _keyQueue; Common::KeyState *_keyDown; + static const int kCursorAnimateDelay = 250; + int _cursorAnimateCounter; + int _cursorAnimateTimer; + byte _cursor[2048]; + void setupCursor(); + void removeCursor(); + void animateCursor(); + }; |