mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-16 22:58:09 +00:00
TWINE: implement ui control via mouse
Also optimized the on-screen keyboard rendering a lot, renamed parameters and started to use Common::Rect
This commit is contained in:
parent
0c3fb36127
commit
e8fcff6e6d
@ -164,4 +164,12 @@ bool Input::isMouseHovering(int32 left, int32 top, int32 right, int32 bottom) co
|
||||
return point.x >= left && point.x <= right && point.y >= top && point.y <= bottom;
|
||||
}
|
||||
|
||||
bool Input::isMouseHovering(const Common::Rect &rect) const {
|
||||
if (!_engine->cfgfile.Mouse) {
|
||||
return false;
|
||||
}
|
||||
Common::Point point = g_system->getEventManager()->getMousePos();
|
||||
return point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.bottom;
|
||||
}
|
||||
|
||||
} // namespace TwinE
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "common/keyboard.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/util.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
@ -129,6 +130,7 @@ public:
|
||||
bool isActionActive(TwinEActionType actionType, bool onlyFirstTime = true) const;
|
||||
|
||||
bool isMouseHovering(int32 left, int32 top, int32 right, int32 bottom) const;
|
||||
bool isMouseHovering(const Common::Rect &rect) const;
|
||||
|
||||
/**
|
||||
* @brief If the action is active, the internal state is reset and a following call of this method won't return
|
||||
|
@ -228,7 +228,11 @@ void Interface::drawTransparentBox(int32 left, int32 top, int32 right, int32 bot
|
||||
} while (height2 > 0);
|
||||
}
|
||||
|
||||
void Interface::drawSplittedBox(int32 left, int32 top, int32 right, int32 bottom, uint8 e) { // Box
|
||||
void Interface::drawSplittedBox(const Common::Rect &rect, uint8 colorIndex) {
|
||||
drawSplittedBox(rect.left, rect.top, rect.right, rect.bottom, colorIndex);
|
||||
}
|
||||
|
||||
void Interface::drawSplittedBox(int32 left, int32 top, int32 right, int32 bottom, uint8 colorIndex) { // Box
|
||||
if (left > SCREEN_TEXTLIMIT_RIGHT) {
|
||||
return;
|
||||
}
|
||||
@ -249,7 +253,7 @@ void Interface::drawSplittedBox(int32 left, int32 top, int32 right, int32 bottom
|
||||
|
||||
for (int32 x = top; x < bottom; x++) {
|
||||
for (int32 y = left; y < right; y++) {
|
||||
*(ptr++) = e;
|
||||
*(ptr++) = colorIndex;
|
||||
}
|
||||
ptr += offset;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define TWINE_INTERFACE_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Graphics {
|
||||
class ManagedSurface;
|
||||
@ -91,7 +92,8 @@ public:
|
||||
*/
|
||||
void drawTransparentBox(int32 left, int32 top, int32 right, int32 bottom, int32 colorAdj);
|
||||
|
||||
void drawSplittedBox(int32 left, int32 top, int32 right, int32 bottom, uint8 e);
|
||||
void drawSplittedBox(int32 left, int32 top, int32 right, int32 bottom, uint8 colorIndex);
|
||||
void drawSplittedBox(const Common::Rect &rect, uint8 colorIndex);
|
||||
|
||||
void setClip(int32 left, int32 top, int32 right, int32 bottom);
|
||||
void saveClip(); // saveTextWindow
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "common/scummsys.h"
|
||||
#include "common/system.h"
|
||||
#include "common/util.h"
|
||||
#include "graphics/cursorman.h"
|
||||
#include "twine/actor.h"
|
||||
#include "twine/animations.h"
|
||||
#include "twine/gamestate.h"
|
||||
@ -231,11 +232,15 @@ void Menu::processPlasmaEffect(int32 left, int32 top, int32 color) {
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::drawBox(const Common::Rect &rect) {
|
||||
_engine->_interface->drawLine(rect.left, rect.top, rect.right, rect.top, 79); // top line
|
||||
_engine->_interface->drawLine(rect.left, rect.top, rect.left, rect.bottom, 79); // left line
|
||||
_engine->_interface->drawLine(rect.right, rect.top + 1, rect.right, rect.bottom, 73); // right line
|
||||
_engine->_interface->drawLine(rect.left + 1, rect.bottom, rect.right, rect.bottom, 73); // bottom line
|
||||
}
|
||||
|
||||
void Menu::drawBox(int32 left, int32 top, int32 right, int32 bottom) {
|
||||
_engine->_interface->drawLine(left, top, right, top, 79); // top line
|
||||
_engine->_interface->drawLine(left, top, left, bottom, 79); // left line
|
||||
_engine->_interface->drawLine(right, top + 1, right, bottom, 73); // right line
|
||||
_engine->_interface->drawLine(left + 1, bottom, right, bottom, 73); // bottom line
|
||||
drawBox(Common::Rect(left, top, right, bottom));
|
||||
}
|
||||
|
||||
void Menu::drawButtonGfx(const MenuSettings *menuSettings, int32 left, int32 top, int32 right, int32 bottom, int32 buttonId, const char *dialText, bool hover) {
|
||||
@ -506,19 +511,20 @@ int32 Menu::processMenu(MenuSettings *menuSettings) {
|
||||
}
|
||||
|
||||
if (buttonsNeedRedraw) {
|
||||
menuSettings->setActiveButton(currentButton);
|
||||
|
||||
// draw all buttons
|
||||
const int16 mouseButtonHovered = drawButtons(menuSettings, false);
|
||||
if (mouseButtonHovered != -1) {
|
||||
currentButton = mouseButtonHovered;
|
||||
}
|
||||
buttonsNeedRedraw = false;
|
||||
menuSettings->setActiveButton(currentButton);
|
||||
}
|
||||
|
||||
// draw plasma effect for the current selected button
|
||||
const int16 mouseButtonHovered = drawButtons(menuSettings, true);
|
||||
if (mouseButtonHovered != -1) {
|
||||
if (mouseButtonHovered != currentButton) {
|
||||
buttonsNeedRedraw = true;
|
||||
}
|
||||
currentButton = mouseButtonHovered;
|
||||
}
|
||||
|
||||
@ -543,6 +549,7 @@ int32 Menu::advoptionsMenu() {
|
||||
_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
|
||||
_engine->flip();
|
||||
|
||||
ScopedCursor scoped(_engine);
|
||||
for (;;) {
|
||||
switch (processMenu(&advOptionsMenuState)) {
|
||||
case TextId::kReturnMenu: {
|
||||
@ -567,6 +574,7 @@ int32 Menu::savemanageMenu() {
|
||||
_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
|
||||
_engine->flip();
|
||||
|
||||
ScopedCursor scoped(_engine);
|
||||
for (;;) {
|
||||
switch (processMenu(&saveManageMenuState)) {
|
||||
case TextId::kReturnMenu:
|
||||
@ -592,6 +600,7 @@ int32 Menu::volumeMenu() {
|
||||
_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
|
||||
_engine->flip();
|
||||
|
||||
ScopedCursor scoped(_engine);
|
||||
for (;;) {
|
||||
switch (processMenu(&volumeMenuState)) {
|
||||
case TextId::kReturnMenu:
|
||||
@ -631,6 +640,7 @@ int32 Menu::optionsMenu() {
|
||||
_engine->_sound->stopSamples();
|
||||
//_engine->_music->playCDtrack(9);
|
||||
|
||||
ScopedCursor scoped(_engine);
|
||||
for (;;) {
|
||||
switch (processMenu(&optionsMenuState)) {
|
||||
case TextId::kReturnGame:
|
||||
@ -659,10 +669,37 @@ int32 Menu::optionsMenu() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const byte cursorArrow[] = {
|
||||
1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
1, 0, 1, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
1, 0, 0, 1, 3, 3, 3, 3, 3, 3, 3,
|
||||
1, 0, 0, 0, 1, 3, 3, 3, 3, 3, 3,
|
||||
1, 0, 0, 0, 0, 1, 3, 3, 3, 3, 3,
|
||||
1, 0, 0, 0, 0, 0, 1, 3, 3, 3, 3,
|
||||
1, 0, 0, 0, 0, 0, 0, 1, 3, 3, 3,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 1, 3, 3,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3,
|
||||
1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
|
||||
1, 0, 0, 1, 0, 0, 1, 3, 3, 3, 3,
|
||||
1, 0, 1, 3, 1, 0, 0, 1, 3, 3, 3,
|
||||
1, 1, 3, 3, 1, 0, 0, 1, 3, 3, 3,
|
||||
1, 3, 3, 3, 3, 1, 0, 0, 1, 3, 3,
|
||||
3, 3, 3, 3, 3, 1, 0, 0, 1, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 1, 3, 3
|
||||
};
|
||||
|
||||
static const byte cursorPalette[] = {
|
||||
0, 0, 0,
|
||||
0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
bool Menu::init() {
|
||||
// load menu effect file only once
|
||||
plasmaEffectPtr = (uint8 *)malloc(kPlasmaEffectFilesize);
|
||||
memset(plasmaEffectPtr, 0, kPlasmaEffectFilesize);
|
||||
|
||||
CursorMan.pushCursor(cursorArrow, 11, 16, 1, 1, 3);
|
||||
CursorMan.pushCursorPalette(cursorPalette, 0, 2);
|
||||
return HQR::getEntry(plasmaEffectPtr, Resources::HQR_RESS_FILE, RESSHQR_PLASMAEFFECT) > 0;
|
||||
}
|
||||
|
||||
@ -673,6 +710,7 @@ EngineState Menu::run() {
|
||||
_engine->_music->playTrackMusic(9); // LBA's Theme
|
||||
_engine->_sound->stopSamples();
|
||||
|
||||
ScopedCursor scoped(_engine);
|
||||
switch (processMenu(&mainMenuState)) {
|
||||
case TextId::kNewGame: {
|
||||
if (_engine->_menuOptions->newGameMenu()) {
|
||||
@ -714,6 +752,8 @@ int32 Menu::giveupMenu() {
|
||||
localMenu = &giveUpMenuWithSaveState;
|
||||
}
|
||||
|
||||
ScopedCursor scoped(_engine);
|
||||
|
||||
int32 menuId;
|
||||
do {
|
||||
_engine->_text->initTextBank(TextBankId::Options_and_menus);
|
||||
@ -800,8 +840,7 @@ void Menu::drawInfoMenu(int16 left, int16 top) {
|
||||
_engine->copyBlockPhys(left, top, left + 450, top + 135);
|
||||
}
|
||||
|
||||
// TODO: convert cantDrawBox to bool
|
||||
void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, int16 cantDrawBox) {
|
||||
Common::Rect Menu::calcBehaviourRect(HeroBehaviourType behaviour) const {
|
||||
const int border = 110;
|
||||
const int32 padding = 11;
|
||||
const int32 width = 99;
|
||||
@ -811,15 +850,24 @@ void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, int16 cantDra
|
||||
const int32 boxRight = boxLeft + width;
|
||||
const int32 boxTop = border;
|
||||
const int32 boxBottom = boxTop + height;
|
||||
return Common::Rect(boxLeft, boxTop, boxRight, boxBottom);
|
||||
}
|
||||
|
||||
bool Menu::isBehaviourHovered(HeroBehaviourType behaviour) const {
|
||||
const Common::Rect &boxRect = calcBehaviourRect(behaviour);
|
||||
return _engine->_input->isMouseHovering(boxRect);
|
||||
}
|
||||
|
||||
void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, bool cantDrawBox) {
|
||||
const Common::Rect &boxRect = calcBehaviourRect(behaviour);
|
||||
const int titleOffset = 10;
|
||||
const int titleHeight = 40;
|
||||
const int32 titleBoxLeft = border;
|
||||
const int32 titleBoxLeft = 110;
|
||||
const int32 titleBoxRight = 540;
|
||||
const int32 titleBoxTop = boxBottom + titleOffset;
|
||||
const int32 titleBoxTop = boxRect.bottom + titleOffset;
|
||||
const int32 titleBoxBottom = titleBoxTop + titleHeight;
|
||||
|
||||
uint8 *currentAnim = _engine->_resources->animTable[_engine->_actor->heroAnimIdx[(byte)behaviour]];
|
||||
const uint8 *currentAnim = _engine->_resources->animTable[_engine->_actor->heroAnimIdx[(byte)behaviour]];
|
||||
int16 currentAnimState = behaviourAnimState[(byte)behaviour];
|
||||
|
||||
if (_engine->_animations->setModelAnimation(currentAnimState, currentAnim, behaviourEntity, &behaviourAnimData[(byte)behaviour])) {
|
||||
@ -830,17 +878,19 @@ void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, int16 cantDra
|
||||
behaviourAnimState[(byte)behaviour] = currentAnimState;
|
||||
}
|
||||
|
||||
if (cantDrawBox == 0) {
|
||||
drawBox(boxLeft - 1, boxTop - 1, boxRight + 1, boxBottom + 1);
|
||||
if (!cantDrawBox) {
|
||||
Common::Rect boxRectCopy(boxRect);
|
||||
boxRectCopy.grow(1);
|
||||
drawBox(boxRectCopy);
|
||||
}
|
||||
|
||||
_engine->_interface->saveClip();
|
||||
_engine->_interface->resetClip();
|
||||
|
||||
if (behaviour != _engine->_actor->heroBehaviour) { // unselected
|
||||
_engine->_interface->drawSplittedBox(boxLeft, boxTop, boxRight, boxBottom, 0);
|
||||
_engine->_interface->drawSplittedBox(boxRect, 0);
|
||||
} else { // selected
|
||||
_engine->_interface->drawSplittedBox(boxLeft, boxTop, boxRight, boxBottom, 69);
|
||||
_engine->_interface->drawSplittedBox(boxRect, 69);
|
||||
|
||||
// behaviour menu title
|
||||
_engine->_interface->drawSplittedBox(titleBoxLeft, titleBoxTop, titleBoxRight, titleBoxBottom, 0);
|
||||
@ -851,12 +901,12 @@ void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, int16 cantDra
|
||||
char dialText[256];
|
||||
_engine->_text->getMenuText(_engine->_actor->getTextIdForBehaviour(), dialText, sizeof(dialText));
|
||||
|
||||
_engine->_text->drawText((650 - _engine->_text->getTextSize(dialText)) / 2, titleBoxTop + 1, dialText);
|
||||
_engine->_text->drawText(SCREEN_WIDTH / 2 - _engine->_text->getTextSize(dialText) / 2, titleBoxTop + 1, dialText);
|
||||
}
|
||||
|
||||
_engine->_renderer->renderBehaviourModel(boxLeft, boxTop, boxRight, boxBottom, -600, angle, behaviourEntity);
|
||||
_engine->_renderer->renderBehaviourModel(boxRect, -600, angle, behaviourEntity);
|
||||
|
||||
_engine->copyBlockPhys(boxLeft, boxTop, boxRight, boxBottom);
|
||||
_engine->copyBlockPhys(boxRect);
|
||||
_engine->copyBlockPhys(titleBoxLeft, titleBoxTop, titleBoxRight, titleBoxBottom);
|
||||
|
||||
_engine->_interface->loadClip();
|
||||
@ -864,7 +914,7 @@ void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, int16 cantDra
|
||||
|
||||
void Menu::prepareAndDrawBehaviour(int32 angle, HeroBehaviourType behaviour) {
|
||||
_engine->_animations->setAnimAtKeyframe(behaviourAnimState[(byte)behaviour], _engine->_resources->animTable[_engine->_actor->heroAnimIdx[(byte)behaviour]], behaviourEntity, &behaviourAnimData[(byte)behaviour]);
|
||||
drawBehaviour(behaviour, angle, 0);
|
||||
drawBehaviour(behaviour, angle, false);
|
||||
}
|
||||
|
||||
void Menu::drawBehaviourMenu(int32 angle) {
|
||||
@ -911,10 +961,25 @@ void Menu::processBehaviourMenu() {
|
||||
|
||||
int32 tmpTime = _engine->lbaTime;
|
||||
|
||||
ScopedKeyMap scoped(_engine, uiKeyMapId);
|
||||
#if 0
|
||||
ScopedCursor scopedCursor(_engine);
|
||||
#endif
|
||||
ScopedKeyMap scopedKeyMap(_engine, uiKeyMapId);
|
||||
while (_engine->_input->isActionActive(TwinEActionType::BehaviourMenu) || _engine->_input->isQuickBehaviourActionActive()) {
|
||||
_engine->readKeys();
|
||||
|
||||
#if 0
|
||||
if (isBehaviourHovered(HeroBehaviourType::kNormal)) {
|
||||
_engine->_actor->heroBehaviour = HeroBehaviourType::kNormal;
|
||||
} else if (isBehaviourHovered(HeroBehaviourType::kAthletic)) {
|
||||
_engine->_actor->heroBehaviour = HeroBehaviourType::kAthletic;
|
||||
} else if (isBehaviourHovered(HeroBehaviourType::kAggressive)) {
|
||||
_engine->_actor->heroBehaviour = HeroBehaviourType::kAggressive;
|
||||
} else if (isBehaviourHovered(HeroBehaviourType::kDiscrete)) {
|
||||
_engine->_actor->heroBehaviour = HeroBehaviourType::kDiscrete;
|
||||
}
|
||||
#endif
|
||||
|
||||
int heroBehaviour = (int)_engine->_actor->heroBehaviour;
|
||||
if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft)) {
|
||||
heroBehaviour--;
|
||||
@ -931,13 +996,13 @@ void Menu::processBehaviourMenu() {
|
||||
_engine->_actor->heroBehaviour = (HeroBehaviourType)heroBehaviour;
|
||||
|
||||
if (tmpHeroBehaviour != _engine->_actor->heroBehaviour) {
|
||||
drawBehaviour(tmpHeroBehaviour, _engine->_scene->sceneHero->angle, 1);
|
||||
drawBehaviour(tmpHeroBehaviour, _engine->_scene->sceneHero->angle, true);
|
||||
tmpHeroBehaviour = _engine->_actor->heroBehaviour;
|
||||
_engine->_movements->setActorAngleSafe(_engine->_scene->sceneHero->angle, _engine->_scene->sceneHero->angle - ANGLE_90, 50, &moveMenu);
|
||||
_engine->_animations->setAnimAtKeyframe(behaviourAnimState[(byte)_engine->_actor->heroBehaviour], _engine->_resources->animTable[_engine->_actor->heroAnimIdx[(byte)_engine->_actor->heroBehaviour]], behaviourEntity, &behaviourAnimData[(byte)_engine->_actor->heroBehaviour]);
|
||||
}
|
||||
|
||||
drawBehaviour(_engine->_actor->heroBehaviour, -1, 1);
|
||||
drawBehaviour(_engine->_actor->heroBehaviour, -1, true);
|
||||
|
||||
_engine->_system->delayMillis(1000 / 50);
|
||||
_engine->lbaTime++;
|
||||
@ -1023,9 +1088,10 @@ void Menu::processInventoryMenu() {
|
||||
_engine->_text->setFontCrossColor(4);
|
||||
_engine->_text->initDialogueBox();
|
||||
|
||||
Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
|
||||
keymapper->getKeymap(uiKeyMapId)->setEnabled(true);
|
||||
|
||||
#if 0
|
||||
ScopedCursor scopedCursor(_engine);
|
||||
#endif
|
||||
ScopedKeyMap scopedKeyMap(_engine, uiKeyMapId);
|
||||
for (;;) {
|
||||
_engine->readKeys();
|
||||
int32 prevSelectedItem = inventorySelectedItem;
|
||||
@ -1114,8 +1180,6 @@ void Menu::processInventoryMenu() {
|
||||
_engine->_system->delayMillis(1);
|
||||
}
|
||||
|
||||
keymapper->getKeymap(uiKeyMapId)->setEnabled(false);
|
||||
|
||||
_engine->_text->_hasValidTextHandle = false;
|
||||
|
||||
_engine->_scene->alphaLight = tmpAlphaLight;
|
||||
|
@ -165,7 +165,9 @@ private:
|
||||
/** Used to run the save game management menu */
|
||||
int32 savemanageMenu();
|
||||
void drawInfoMenu(int16 left, int16 top);
|
||||
void drawBehaviour(HeroBehaviourType behaviour, int32 angle, int16 cantDrawBox);
|
||||
Common::Rect calcBehaviourRect(HeroBehaviourType behaviour) const;
|
||||
bool isBehaviourHovered(HeroBehaviourType behaviour) const;
|
||||
void drawBehaviour(HeroBehaviourType behaviour, int32 angle, bool cantDrawBox);
|
||||
void drawInventoryItems();
|
||||
void prepareAndDrawBehaviour(int32 angle, HeroBehaviourType behaviour);
|
||||
void drawBehaviourMenu(int32 angle);
|
||||
@ -218,7 +220,7 @@ public:
|
||||
* @param bottom end height to draw the button
|
||||
*/
|
||||
void drawBox(int32 left, int32 top, int32 right, int32 bottom);
|
||||
|
||||
void drawBox(const Common::Rect &rect);
|
||||
/**
|
||||
* Where the main menu options are processed
|
||||
* @param menuSettings menu settings array with the information to build the menu options
|
||||
|
@ -42,9 +42,6 @@
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
#define ONSCREENKEYBOARD_WIDTH 14
|
||||
#define ONSCREENKEYBOARD_HEIGHT 5
|
||||
|
||||
static const char allowedCharIndex[] = " ABCDEFGHIJKLM.NOPQRSTUVWXYZ-abcdefghijklm?nopqrstuvwxyz!0123456789\040\b\r\0";
|
||||
|
||||
void MenuOptions::newGame() {
|
||||
@ -121,19 +118,34 @@ void MenuOptions::showCredits() {
|
||||
_engine->setPalette(_engine->_screens->paletteRGBA);
|
||||
}
|
||||
|
||||
void MenuOptions::drawSelectableCharacter(int32 x, int32 y, bool selected) {
|
||||
char buffer[2];
|
||||
void MenuOptions::drawSelectableCharacter(int32 x, int32 y) {
|
||||
const int32 borderTop = 200;
|
||||
const int32 borderLeft = 25;
|
||||
const int32 halfButtonHeight = 25;
|
||||
const int32 halfButtonWidth = 20;
|
||||
const int32 buttonDistanceX = halfButtonWidth * 2 + 5;
|
||||
const int32 buttonDistanceY = halfButtonHeight * 2 + 5;
|
||||
const int32 centerX = x * buttonDistanceX + borderLeft;
|
||||
const int32 centerY = y * buttonDistanceY + borderTop;
|
||||
const int32 left = centerX - halfButtonWidth;
|
||||
const int32 right = centerX + halfButtonWidth;
|
||||
const int32 top = centerY - halfButtonHeight;
|
||||
const int32 bottom = centerY + halfButtonHeight;
|
||||
|
||||
buffer[0] = allowedCharIndex[y + x * ONSCREENKEYBOARD_WIDTH];
|
||||
buffer[1] = '\0';
|
||||
if (_engine->_input->isMouseHovering(left, top, right, bottom)) {
|
||||
setOnScreenKeyboard(x, y);
|
||||
}
|
||||
|
||||
const int32 centerX = y * 45 + 25;
|
||||
const int32 left = centerX - 20;
|
||||
const int32 right = centerX + 20;
|
||||
const int32 top = x * 56 + 200 - 25;
|
||||
const int32 centerY = x * 56 + 200;
|
||||
const int32 bottom = x * 56 + 200 + 25;
|
||||
const int idx = x + y * ONSCREENKEYBOARD_WIDTH;
|
||||
if (_onScreenKeyboardDirty[idx] == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
--_onScreenKeyboardDirty[idx];
|
||||
|
||||
const char buffer[] { allowedCharIndex[idx], '\0' };
|
||||
|
||||
const bool selected = _onScreenKeyboardX == x && _onScreenKeyboardY == y;
|
||||
if (selected) {
|
||||
_engine->_interface->drawSplittedBox(left, top, right, bottom, 91);
|
||||
} else {
|
||||
@ -144,15 +156,44 @@ void MenuOptions::drawSelectableCharacter(int32 x, int32 y, bool selected) {
|
||||
_engine->_menu->drawBox(left, top, right, bottom);
|
||||
|
||||
_engine->_text->setFontColor(15);
|
||||
_engine->_text->drawText(centerX - _engine->_text->getTextSize(buffer) / 2, centerY - 18, buffer);
|
||||
const uint8 character = (uint8)allowedCharIndex[idx];
|
||||
const int32 textX = centerX - _engine->_text->getCharWidth(character) / 2;
|
||||
const int32 textY = centerY - _engine->_text->getCharHeight(character) / 2;
|
||||
_engine->_text->drawText(textX, textY, buffer);
|
||||
|
||||
_engine->copyBlockPhys(left, top, right, bottom);
|
||||
}
|
||||
|
||||
void MenuOptions::setOnScreenKeyboard(int x, int y) {
|
||||
if (x < 0) {
|
||||
x = ONSCREENKEYBOARD_WIDTH - 1;
|
||||
} else if (x >= ONSCREENKEYBOARD_WIDTH) {
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
y = ONSCREENKEYBOARD_HEIGHT - 1;
|
||||
} else if (y >= ONSCREENKEYBOARD_HEIGHT) {
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if (_onScreenKeyboardX == x && _onScreenKeyboardY == y) {
|
||||
return;
|
||||
}
|
||||
|
||||
++_onScreenKeyboardDirty[_onScreenKeyboardX + _onScreenKeyboardY * ONSCREENKEYBOARD_WIDTH];
|
||||
++_onScreenKeyboardDirty[x + y * ONSCREENKEYBOARD_WIDTH];
|
||||
|
||||
_onScreenKeyboardX = x;
|
||||
_onScreenKeyboardY = y;
|
||||
|
||||
_onScreenKeyboardLeaveViaOkButton = true;
|
||||
}
|
||||
|
||||
void MenuOptions::drawSelectableCharacters() {
|
||||
for (int8 x = 0; x < ONSCREENKEYBOARD_HEIGHT; x++) {
|
||||
for (int8 y = 0; y < ONSCREENKEYBOARD_WIDTH; y++) {
|
||||
drawSelectableCharacter(x, y, _onScreenKeyboardY == x && _onScreenKeyboardX == y);
|
||||
for (int8 x = 0; x < ONSCREENKEYBOARD_WIDTH; x++) {
|
||||
for (int8 y = 0; y < ONSCREENKEYBOARD_HEIGHT; y++) {
|
||||
drawSelectableCharacter(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -202,6 +243,7 @@ bool MenuOptions::enterPlayerName(int32 textIdx) {
|
||||
_engine->copyBlockPhys(0, 0, SCREEN_WIDTH - 1, 99);
|
||||
_engine->flip();
|
||||
|
||||
Common::fill(&_onScreenKeyboardDirty[0], &_onScreenKeyboardDirty[ARRAYSIZE(_onScreenKeyboardDirty)], 1);
|
||||
ScopedFeatureState scopedVirtualKeyboard(OSystem::kFeatureVirtualKeyboard, true);
|
||||
for (;;) {
|
||||
Common::Event event;
|
||||
@ -246,30 +288,14 @@ bool MenuOptions::enterPlayerName(int32 textIdx) {
|
||||
return false;
|
||||
}
|
||||
if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft)) {
|
||||
--_onScreenKeyboardX;
|
||||
if (_onScreenKeyboardX < 0) {
|
||||
_onScreenKeyboardX = ONSCREENKEYBOARD_WIDTH - 1;
|
||||
}
|
||||
_onScreenKeyboardLeaveViaOkButton = true;
|
||||
setOnScreenKeyboard(_onScreenKeyboardX - 1, _onScreenKeyboardY);
|
||||
} else if (_engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
|
||||
++_onScreenKeyboardX;
|
||||
if (_onScreenKeyboardX >= ONSCREENKEYBOARD_WIDTH) {
|
||||
_onScreenKeyboardX = 0;
|
||||
}
|
||||
_onScreenKeyboardLeaveViaOkButton = true;
|
||||
setOnScreenKeyboard(_onScreenKeyboardX + 1, _onScreenKeyboardY);
|
||||
}
|
||||
if (_engine->_input->toggleActionIfActive(TwinEActionType::UIUp)) {
|
||||
--_onScreenKeyboardY;
|
||||
if (_onScreenKeyboardY < 0) {
|
||||
_onScreenKeyboardY = ONSCREENKEYBOARD_HEIGHT - 1;
|
||||
}
|
||||
_onScreenKeyboardLeaveViaOkButton = true;
|
||||
setOnScreenKeyboard(_onScreenKeyboardX, _onScreenKeyboardY - 1);
|
||||
} else if (_engine->_input->toggleActionIfActive(TwinEActionType::UIDown)) {
|
||||
++_onScreenKeyboardY;
|
||||
if (_onScreenKeyboardY >= ONSCREENKEYBOARD_HEIGHT) {
|
||||
_onScreenKeyboardY = 0;
|
||||
}
|
||||
_onScreenKeyboardLeaveViaOkButton = true;
|
||||
setOnScreenKeyboard(_onScreenKeyboardX, _onScreenKeyboardY + 1);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -23,6 +23,9 @@
|
||||
#ifndef TWINE_MENUOPTIONS_H
|
||||
#define TWINE_MENUOPTIONS_H
|
||||
|
||||
#define ONSCREENKEYBOARD_WIDTH 14
|
||||
#define ONSCREENKEYBOARD_HEIGHT 5
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "twine/actor.h"
|
||||
|
||||
@ -32,14 +35,18 @@ class MenuOptions {
|
||||
private:
|
||||
TwinEEngine *_engine;
|
||||
|
||||
uint8 _onScreenKeyboardDirty[ONSCREENKEYBOARD_WIDTH * ONSCREENKEYBOARD_HEIGHT] { 0 };
|
||||
|
||||
int _onScreenKeyboardX = 0;
|
||||
int _onScreenKeyboardY = 0;
|
||||
bool _onScreenKeyboardLeaveViaOkButton = false;
|
||||
|
||||
void setOnScreenKeyboard(int x, int y);
|
||||
|
||||
bool enterPlayerName(int32 textIdx);
|
||||
void drawSelectableCharacters();
|
||||
void drawPlayerName(int32 centerx, int32 top, int32 type);
|
||||
void drawSelectableCharacter(int32 x, int32 y, bool selected);
|
||||
void drawSelectableCharacter(int32 x, int32 y);
|
||||
int chooseSave(int textIdx, bool showEmptySlots = false);
|
||||
|
||||
public:
|
||||
|
@ -128,6 +128,13 @@ static const ExtraGuiOption OptMovies = {
|
||||
true
|
||||
};
|
||||
|
||||
static const ExtraGuiOption OptMouse = {
|
||||
_s("Enable mouse"),
|
||||
_s("Enable the mouse for the UI"),
|
||||
"mouse",
|
||||
true
|
||||
};
|
||||
|
||||
static const ExtraGuiOption OptUSAVersion = {
|
||||
_s("Use the USA version"),
|
||||
_s("Enable the USA specific version flags"),
|
||||
@ -147,6 +154,7 @@ const ExtraGuiOptions TwinEMetaEngine::getExtraGuiOptions(const Common::String &
|
||||
options.push_back(OptUSAVersion);
|
||||
options.push_back(OptVoices);
|
||||
options.push_back(OptText);
|
||||
options.push_back(OptMouse);
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -335,11 +343,13 @@ Common::KeymapArray TwinEMetaEngine::initKeymaps(const char *target) const {
|
||||
act->setCustomEngineActionEvent(TwinEActionType::UIEnter);
|
||||
act->addDefaultInputMapping("RETURN");
|
||||
act->addDefaultInputMapping("KP_ENTER");
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
uiKeyMap->addAction(act);
|
||||
|
||||
act = new Action("ABORT", _("Abort"));
|
||||
act->setCustomEngineActionEvent(TwinEActionType::UIAbort);
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
uiKeyMap->addAction(act);
|
||||
|
||||
act = new Action("UP", _("Up"));
|
||||
@ -358,12 +368,14 @@ Common::KeymapArray TwinEMetaEngine::initKeymaps(const char *target) const {
|
||||
act->setCustomEngineActionEvent(TwinEActionType::UIRight);
|
||||
act->addDefaultInputMapping("RIGHT");
|
||||
act->addDefaultInputMapping("KP6");
|
||||
act->addDefaultInputMapping("MOUSE_WHEEL_UP");
|
||||
uiKeyMap->addAction(act);
|
||||
|
||||
act = new Action("LEFT", _("Left"));
|
||||
act->setCustomEngineActionEvent(TwinEActionType::UILeft);
|
||||
act->addDefaultInputMapping("LEFT");
|
||||
act->addDefaultInputMapping("KP4");
|
||||
act->addDefaultInputMapping("MOUSE_WHEEL_DOWN");
|
||||
uiKeyMap->addAction(act);
|
||||
|
||||
act = new Action("NEXTPAGE", _("Next Page"));
|
||||
|
@ -1688,6 +1688,10 @@ void Renderer::copyActorInternAnim(const uint8 *bodyPtrSrc, uint8 *bodyPtrDest)
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::renderBehaviourModel(const Common::Rect &rect, int32 y, int32 angle, uint8 *entityPtr) {
|
||||
renderBehaviourModel(rect.left, rect.top, rect.right, rect.bottom, y, angle, entityPtr);
|
||||
}
|
||||
|
||||
void Renderer::renderBehaviourModel(int32 boxLeft, int32 boxTop, int32 boxRight, int32 boxBottom, int32 y, int32 angle, uint8 *entityPtr) {
|
||||
int32 tmpBoxRight = boxRight;
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define TWINE_RENDERER_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
#define POLYGONTYPE_FLAT 0
|
||||
#define POLYGONTYPE_COPPER 1
|
||||
@ -240,6 +241,7 @@ public:
|
||||
void copyActorInternAnim(const uint8 *bodyPtrSrc, uint8 *bodyPtrDest);
|
||||
|
||||
void renderBehaviourModel(int32 boxLeft, int32 boxTop, int32 boxRight, int32 boxBottom, int32 y, int32 angle, uint8 *entityPtr);
|
||||
void renderBehaviourModel(const Common::Rect &rect, int32 y, int32 angle, uint8 *entityPtr);
|
||||
|
||||
void renderInventoryItem(int32 x, int32 y, uint8 *itemBodyPtr, int32 angle, int32 param);
|
||||
};
|
||||
|
@ -140,8 +140,6 @@ private:
|
||||
* @param counter The amount of characters to handle - max 32
|
||||
*/
|
||||
void fadeInCharacters(int32 counter, int32 fontColor);
|
||||
int32 getCharWidth(uint8 chr) const;
|
||||
int32 getCharHeight(uint8 chr) const;
|
||||
/**
|
||||
* Copy dialogue text
|
||||
* @param src source text buffer
|
||||
@ -254,6 +252,8 @@ public:
|
||||
* @param dialogue ascii text to display
|
||||
*/
|
||||
int32 getTextSize(const char *dialogue);
|
||||
int32 getCharWidth(uint8 chr) const;
|
||||
int32 getCharHeight(uint8 chr) const;
|
||||
|
||||
void initDialogueBox();
|
||||
void initInventoryDialogueBox();
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "engines/metaengine.h"
|
||||
#include "engines/util.h"
|
||||
#include "graphics/colormasks.h"
|
||||
#include "graphics/cursorman.h"
|
||||
#include "graphics/fontman.h"
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
@ -81,6 +82,14 @@ ScopedEngineFreeze::~ScopedEngineFreeze() {
|
||||
_engine->unfreezeTime();
|
||||
}
|
||||
|
||||
ScopedCursor::ScopedCursor(const TwinEEngine* engine) {
|
||||
CursorMan.showMouse(engine->cfgfile.Mouse);
|
||||
}
|
||||
|
||||
ScopedCursor::~ScopedCursor() {
|
||||
CursorMan.showMouse(false);
|
||||
}
|
||||
|
||||
TwinEEngine::TwinEEngine(OSystem *system, Common::Language language, uint32 flags, TwineGameType gameType)
|
||||
: Engine(system), _gameType(gameType), _gameLang(language), _gameFlags(flags), _rnd("twine") {
|
||||
// Add default file directories
|
||||
@ -323,6 +332,7 @@ void TwinEEngine::initConfigurations() {
|
||||
cfgfile.Movie = ConfGetIntOrDefault("movie", CONF_MOVIE_FLA);
|
||||
cfgfile.Fps = ConfGetIntOrDefault("fps", DEFAULT_FRAMES_PER_SECOND);
|
||||
cfgfile.Debug = ConfGetBoolOrDefault("debug", false);
|
||||
cfgfile.Mouse = ConfGetIntOrDefault("mouse", true);
|
||||
|
||||
cfgfile.UseAutoSaving = ConfGetBoolOrDefault("useautosaving", false);
|
||||
cfgfile.CrossFade = ConfGetBoolOrDefault("crossfade", false);
|
||||
@ -941,6 +951,10 @@ void TwinEEngine::flip() {
|
||||
g_system->updateScreen();
|
||||
}
|
||||
|
||||
void TwinEEngine::copyBlockPhys(const Common::Rect &rect) {
|
||||
copyBlockPhys(rect.left, rect.top, rect.right, rect.bottom);
|
||||
}
|
||||
|
||||
void TwinEEngine::copyBlockPhys(int32 left, int32 top, int32 right, int32 bottom) {
|
||||
assert(left <= right);
|
||||
assert(top <= bottom);
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "backends/keymapper/keymap.h"
|
||||
#include "common/random.h"
|
||||
#include "common/rect.h"
|
||||
#include "engines/engine.h"
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
@ -111,6 +112,7 @@ struct ConfigFile {
|
||||
bool WallCollision = false;
|
||||
/** Use original autosaving system or save when you want */
|
||||
bool UseAutoSaving = false;
|
||||
bool Mouse = false;
|
||||
|
||||
// these settings can be changed in-game - and must be persisted
|
||||
/** Shadow mode type, value: all, character only, none */
|
||||
@ -161,6 +163,11 @@ struct ScopedEngineFreeze {
|
||||
~ScopedEngineFreeze();
|
||||
};
|
||||
|
||||
struct ScopedCursor {
|
||||
ScopedCursor(const TwinEEngine* engine);
|
||||
~ScopedCursor();
|
||||
};
|
||||
|
||||
class TwinEEngine : public Engine {
|
||||
private:
|
||||
int32 isTimeFreezed = 0;
|
||||
@ -298,6 +305,7 @@ public:
|
||||
* @param bottom bottom position to start copy
|
||||
*/
|
||||
void copyBlockPhys(int32 left, int32 top, int32 right, int32 bottom);
|
||||
void copyBlockPhys(const Common::Rect &rect);
|
||||
|
||||
/** Cross fade feature
|
||||
* @param buffer screen buffer
|
||||
|
Loading…
Reference in New Issue
Block a user