[Scummvm-git-logs] scummvm master -> 25d8c6b1f143e99ae9fe123bb7f3611dcea6eda9

mgerhardy martin.gerhardy at gmail.com
Wed Nov 25 16:14:38 UTC 2020


This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
0c3fb36127 TWINE: removed unused member
e8fcff6e6d TWINE: implement ui control via mouse
1fbb881b19 TWINE: more use of Common::Rect
25d8c6b1f1 TWINE: toggle between mouse and keyboard input


Commit: 0c3fb3612723298166a9fda5d4d219f1d20c872c
    https://github.com/scummvm/scummvm/commit/0c3fb3612723298166a9fda5d4d219f1d20c872c
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-25T17:00:44+01:00

Commit Message:
TWINE: removed unused member

Changed paths:
    engines/twine/actor.h


diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index 3b7b11d3dd..5010186ce5 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -214,7 +214,6 @@ public:
 
 	//int costumeIndex;
 	int32 collision = 0;
-	int32 standPosition = 0;
 	int32 standOn = 0;
 	int32 zone = 0;
 


Commit: e8fcff6e6df41f5a2af8ef4d36e1ceeb2b803bcc
    https://github.com/scummvm/scummvm/commit/e8fcff6e6df41f5a2af8ef4d36e1ceeb2b803bcc
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-25T17:00:44+01:00

Commit Message:
TWINE: implement ui control via mouse

Also optimized the on-screen keyboard rendering a lot, renamed
parameters and started to use Common::Rect

Changed paths:
    engines/twine/input.cpp
    engines/twine/input.h
    engines/twine/interface.cpp
    engines/twine/interface.h
    engines/twine/menu.cpp
    engines/twine/menu.h
    engines/twine/menuoptions.cpp
    engines/twine/menuoptions.h
    engines/twine/metaengine.cpp
    engines/twine/renderer.cpp
    engines/twine/renderer.h
    engines/twine/text.h
    engines/twine/twine.cpp
    engines/twine/twine.h


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 2812f792e7..3cc30fe7e7 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -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
diff --git a/engines/twine/input.h b/engines/twine/input.h
index e5e670cea1..22da5d5bb2 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -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
diff --git a/engines/twine/interface.cpp b/engines/twine/interface.cpp
index 1527837517..d596b05b0b 100644
--- a/engines/twine/interface.cpp
+++ b/engines/twine/interface.cpp
@@ -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;
 	}
diff --git a/engines/twine/interface.h b/engines/twine/interface.h
index 269e07229c..c8ced70042 100644
--- a/engines/twine/interface.h
+++ b/engines/twine/interface.h
@@ -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
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 47929b3a2f..84381ae618 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -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;
diff --git a/engines/twine/menu.h b/engines/twine/menu.h
index 05239b8d3f..63258e125b 100644
--- a/engines/twine/menu.h
+++ b/engines/twine/menu.h
@@ -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
diff --git a/engines/twine/menuoptions.cpp b/engines/twine/menuoptions.cpp
index d318bc1e32..ef94dd2673 100644
--- a/engines/twine/menuoptions.cpp
+++ b/engines/twine/menuoptions.cpp
@@ -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;
+
+	if (_engine->_input->isMouseHovering(left, top, right, bottom)) {
+		setOnScreenKeyboard(x, y);
+	}
 
-	buffer[0] = allowedCharIndex[y + x * ONSCREENKEYBOARD_WIDTH];
-	buffer[1] = '\0';
+	const int idx = x + y * ONSCREENKEYBOARD_WIDTH;
+	if (_onScreenKeyboardDirty[idx] == 0) {
+		return;
+	}
 
-	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;
+	--_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;
diff --git a/engines/twine/menuoptions.h b/engines/twine/menuoptions.h
index 9054eb1309..3b70323475 100644
--- a/engines/twine/menuoptions.h
+++ b/engines/twine/menuoptions.h
@@ -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:
diff --git a/engines/twine/metaengine.cpp b/engines/twine/metaengine.cpp
index d61be15caf..cfdc4f07ee 100644
--- a/engines/twine/metaengine.cpp
+++ b/engines/twine/metaengine.cpp
@@ -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"));
diff --git a/engines/twine/renderer.cpp b/engines/twine/renderer.cpp
index b9520f91b5..1a4246b836 100644
--- a/engines/twine/renderer.cpp
+++ b/engines/twine/renderer.cpp
@@ -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;
 
diff --git a/engines/twine/renderer.h b/engines/twine/renderer.h
index 61c180293e..c1faeb3eca 100644
--- a/engines/twine/renderer.h
+++ b/engines/twine/renderer.h
@@ -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);
 };
diff --git a/engines/twine/text.h b/engines/twine/text.h
index f125f4361d..2e375bcc2e 100644
--- a/engines/twine/text.h
+++ b/engines/twine/text.h
@@ -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();
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index cd6e316a1a..1c512fdf6a 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -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);
diff --git a/engines/twine/twine.h b/engines/twine/twine.h
index af98f28399..6ea81aa596 100644
--- a/engines/twine/twine.h
+++ b/engines/twine/twine.h
@@ -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


Commit: 1fbb881b19ce402b8ed8367bc6ed5034e3a5ffbc
    https://github.com/scummvm/scummvm/commit/1fbb881b19ce402b8ed8367bc6ed5034e3a5ffbc
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-25T17:00:44+01:00

Commit Message:
TWINE: more use of Common::Rect

Changed paths:
    engines/twine/debug.cpp
    engines/twine/input.cpp
    engines/twine/input.h
    engines/twine/interface.cpp
    engines/twine/interface.h
    engines/twine/menu.cpp
    engines/twine/menu.h
    engines/twine/menuoptions.cpp
    engines/twine/redraw.cpp
    engines/twine/redraw.h


diff --git a/engines/twine/debug.cpp b/engines/twine/debug.cpp
index 7aace2d257..54df6327b1 100644
--- a/engines/twine/debug.cpp
+++ b/engines/twine/debug.cpp
@@ -426,12 +426,11 @@ void Debug::debugProcessWindow() {
 			if (_engine->shouldQuit()) {
 				break;
 			}
-			MouseStatusStruct mouseData;
-			_engine->_input->getMousePositions(&mouseData);
+			const Common::Point &point = _engine->_input->getMousePositions();
 
 			if (_engine->_input->toggleActionIfActive(TwinEActionType::DebugMenuActivate)) {
 				int type = 0;
-				if ((type = debugProcessButton(mouseData.x, mouseData.y)) != NO_ACTION) { // process menu item
+				if ((type = debugProcessButton(point.x, point.y)) != NO_ACTION) { // process menu item
 					if (debugTypeUseMenu(type)) {
 						_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
 						_engine->copyBlockPhys(205, 55, 634, 474);
diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 3cc30fe7e7..047c5e2294 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -153,22 +153,15 @@ void Input::readKeys() {
 	}
 }
 
-void Input::getMousePositions(MouseStatusStruct *mouseData) {
-	Common::Point point = g_system->getEventManager()->getMousePos();
-	mouseData->x = point.x;
-	mouseData->y = point.y;
-}
-
-bool Input::isMouseHovering(int32 left, int32 top, int32 right, int32 bottom) const {
-	Common::Point point = g_system->getEventManager()->getMousePos();
-	return point.x >= left && point.x <= right && point.y >= top && point.y <= bottom;
+Common::Point Input::getMousePositions() const {
+	return g_system->getEventManager()->getMousePos();
 }
 
 bool Input::isMouseHovering(const Common::Rect &rect) const {
 	if (!_engine->cfgfile.Mouse) {
 		return false;
 	}
-	Common::Point point = g_system->getEventManager()->getMousePos();
+	Common::Point point = getMousePositions();
 	return point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.bottom;
 }
 
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 22da5d5bb2..d12e097a4c 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -83,11 +83,6 @@ enum TwinEActionType {
 	Max
 };
 
-struct MouseStatusStruct {
-	int32 x = 0;
-	int32 y = 0;
-};
-
 /**
  * @brief Activates the given key map id that is registered in the meta engine
  */
@@ -129,7 +124,6 @@ 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;
 
 	/**
@@ -148,7 +142,7 @@ public:
 	 * Gets mouse positions
 	 * @param mouseData structure that contains mouse position info
 	 */
-	void getMousePositions(MouseStatusStruct *mouseData);
+	Common::Point getMousePositions() const;
 
 	/**
 	 * @brief Updates the internal action states
diff --git a/engines/twine/interface.cpp b/engines/twine/interface.cpp
index d596b05b0b..c80ef72158 100644
--- a/engines/twine/interface.cpp
+++ b/engines/twine/interface.cpp
@@ -152,6 +152,10 @@ void Interface::drawLine(int32 startWidth, int32 startHeight, int32 endWidth, in
 	}
 }
 
+void Interface::blitBox(const Common::Rect &rect, const Graphics::ManagedSurface &source, int32 leftDest, int32 topDest, Graphics::ManagedSurface &dest) {
+	blitBox(rect.left, rect.top, rect.right, rect.bottom, source, leftDest, topDest, dest);
+}
+
 void Interface::blitBox(int32 left, int32 top, int32 right, int32 bottom, const Graphics::ManagedSurface &source, int32 leftDest, int32 topDest, Graphics::ManagedSurface &dest) {
 	const int8 *s = (const int8 *)source.getBasePtr(left, top);
 	int8 *d = (int8 *)dest.getBasePtr(left, top);
@@ -175,6 +179,10 @@ void Interface::blitBox(int32 left, int32 top, int32 right, int32 bottom, const
 	}
 }
 
+void Interface::drawTransparentBox(const Common::Rect &rect, int32 colorAdj) {
+	drawTransparentBox(rect.left, rect.top, rect.right, rect.bottom, colorAdj);
+}
+
 void Interface::drawTransparentBox(int32 left, int32 top, int32 right, int32 bottom, int32 colorAdj) {
 	if (left > SCREEN_TEXTLIMIT_RIGHT) {
 		return;
@@ -259,6 +267,10 @@ void Interface::drawSplittedBox(int32 left, int32 top, int32 right, int32 bottom
 	}
 }
 
+void Interface::setClip(const Common::Rect &rect) {
+	setClip(rect.left, rect.top, rect.right, rect.bottom);
+}
+
 void Interface::setClip(int32 left, int32 top, int32 right, int32 bottom) {
 	if (left < 0) {
 		left = 0;
diff --git a/engines/twine/interface.h b/engines/twine/interface.h
index c8ced70042..dde51f6d9d 100644
--- a/engines/twine/interface.h
+++ b/engines/twine/interface.h
@@ -81,7 +81,7 @@ public:
 	 * @param dest destination screen buffer, in this case front buffer
 	 */
 	void blitBox(int32 left, int32 top, int32 right, int32 bottom, const Graphics::ManagedSurface &source, int32 leftDest, int32 topDest, Graphics::ManagedSurface &dest);
-
+	void blitBox(const Common::Rect &rect, const Graphics::ManagedSurface &source, int32 leftDest, int32 topDest, Graphics::ManagedSurface &dest);
 	/**
 	 * Draws inside buttons transparent area
 	 * @param left start width to draw the button
@@ -91,11 +91,13 @@ public:
 	 * @param colorAdj index to adjust the transparent box color
 	 */
 	void drawTransparentBox(int32 left, int32 top, int32 right, int32 bottom, int32 colorAdj);
+	void drawTransparentBox(const Common::Rect &rect, int32 colorAdj);
 
 	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 setClip(const Common::Rect &rect);
 	void saveClip(); // saveTextWindow
 	void loadClip(); // loadSavedTextWindow
 	void resetClip();
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 84381ae618..ae989039f1 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -243,62 +243,62 @@ void Menu::drawBox(int32 left, int32 top, int32 right, int32 bottom) {
 	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) {
+void Menu::drawButtonGfx(const MenuSettings *menuSettings, const Common::Rect &rect, int32 buttonId, const char *dialText, bool hover) {
 	if (hover) {
 		if (menuSettings == &volumeMenuState && buttonId <= MenuButtonTypes::kMasterVolume && buttonId >= MenuButtonTypes::kMusicVolume) {
 			int32 newWidth = 0;
 			switch (buttonId) {
 			case MenuButtonTypes::kMusicVolume: {
 				const int volume = _engine->_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
-				newWidth = _engine->_screens->crossDot(left, right, Audio::Mixer::kMaxMixerVolume, volume);
+				newWidth = _engine->_screens->crossDot(rect.left, rect.right, Audio::Mixer::kMaxMixerVolume, volume);
 				break;
 			}
 			case MenuButtonTypes::kSoundVolume: {
 				const int volume = _engine->_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kSFXSoundType);
-				newWidth = _engine->_screens->crossDot(left, right, Audio::Mixer::kMaxMixerVolume, volume);
+				newWidth = _engine->_screens->crossDot(rect.left, rect.right, Audio::Mixer::kMaxMixerVolume, volume);
 				break;
 			}
 			case MenuButtonTypes::kCDVolume: {
 				const AudioCDManager::Status status = _engine->_system->getAudioCDManager()->getStatus();
-				newWidth = _engine->_screens->crossDot(left, right, Audio::Mixer::kMaxMixerVolume, status.volume);
+				newWidth = _engine->_screens->crossDot(rect.left, rect.right, Audio::Mixer::kMaxMixerVolume, status.volume);
 				break;
 			}
 			case MenuButtonTypes::kLineVolume: {
 				const int volume = _engine->_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType);
-				newWidth = _engine->_screens->crossDot(left, right, Audio::Mixer::kMaxMixerVolume, volume);
+				newWidth = _engine->_screens->crossDot(rect.left, rect.right, Audio::Mixer::kMaxMixerVolume, volume);
 				break;
 			}
 			case MenuButtonTypes::kMasterVolume: {
 				const int volume = _engine->_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kPlainSoundType);
-				newWidth = _engine->_screens->crossDot(left, right, Audio::Mixer::kMaxMixerVolume, volume);
+				newWidth = _engine->_screens->crossDot(rect.left, rect.right, Audio::Mixer::kMaxMixerVolume, volume);
 				break;
 			}
 			}
 
-			processPlasmaEffect(left, top, 80);
+			processPlasmaEffect(rect.left, rect.top, 80);
 			if (!(_engine->getRandomNumber() % 5)) {
 				plasmaEffectPtr[_engine->getRandomNumber() % 140 * 10 + 1900] = 255;
 			}
-			_engine->_interface->drawSplittedBox(newWidth, top, right, bottom, 68);
+			_engine->_interface->drawSplittedBox(newWidth, rect.top, rect.right, rect.bottom, 68);
 		} else {
-			processPlasmaEffect(left, top, 64);
+			processPlasmaEffect(rect.left, rect.top, 64);
 			if (!(_engine->getRandomNumber() % 5)) {
 				plasmaEffectPtr[_engine->getRandomNumber() % 320 * 10 + 6400] = 255;
 			}
 		}
 	} else {
-		_engine->_interface->blitBox(left, top, right, bottom, _engine->workVideoBuffer, left, top, _engine->frontVideoBuffer);
-		_engine->_interface->drawTransparentBox(left, top, right, bottom, 4);
+		_engine->_interface->blitBox(rect, _engine->workVideoBuffer, rect.left, rect.top, _engine->frontVideoBuffer);
+		_engine->_interface->drawTransparentBox(rect, 4);
 	}
 
-	drawBox(left, top, right, bottom);
+	drawBox(rect);
 
 	_engine->_text->setFontColor(15);
 	_engine->_text->setFontParameters(2, 8);
 	const int32 textSize = _engine->_text->getTextSize(dialText);
-	_engine->_text->drawText((SCREEN_WIDTH / 2) - (textSize / 2), top + 7, dialText);
+	_engine->_text->drawText((SCREEN_WIDTH / 2) - (textSize / 2), rect.top + 7, dialText);
 
-	_engine->copyBlockPhys(left, top, right, bottom);
+	_engine->copyBlockPhys(rect);
 }
 
 int16 Menu::drawButtons(MenuSettings *menuSettings, bool hover) {
@@ -360,24 +360,21 @@ int16 Menu::drawButtons(MenuSettings *menuSettings, bool hover) {
 		}
 		const int32 menuItemId = menuSettings->getButtonState(i);
 		const char *text = menuSettings->getButtonText(_engine->_text, i);
-		const uint16 mainMenuButtonWidthHalf = 550 / 2;
-		const uint16 mainMenuButtonHeightHalf = 50 / 2;
-		const int32 left = (SCREEN_WIDTH / 2) - mainMenuButtonWidthHalf;
-		const int32 right = (SCREEN_WIDTH / 2) + mainMenuButtonWidthHalf;
-		const int32 top = topHeight - mainMenuButtonHeightHalf;
-		const int32 bottom = topHeight + mainMenuButtonHeightHalf;
+		const int32 border = 45;
+		const int32 mainMenuButtonHeightHalf = 25;
+		const Common::Rect rect(border, topHeight - mainMenuButtonHeightHalf, SCREEN_WIDTH - border, topHeight + mainMenuButtonHeightHalf);
 		if (hover) {
 			if (i == buttonNumber) {
-				drawButtonGfx(menuSettings, left, top, right, bottom, menuItemId, text, hover);
+				drawButtonGfx(menuSettings, rect, menuItemId, text, hover);
 			}
 		} else {
 			if (i == buttonNumber) {
-				drawButtonGfx(menuSettings, left, top, right, bottom, menuItemId, text, true);
+				drawButtonGfx(menuSettings, rect, menuItemId, text, true);
 			} else {
-				drawButtonGfx(menuSettings, left, top, right, bottom, menuItemId, text, false);
+				drawButtonGfx(menuSettings, rect, menuItemId, text, false);
 			}
 		}
-		if (_engine->_input->isMouseHovering(left, top, right, bottom)) {
+		if (_engine->_input->isMouseHovering(rect)) {
 			mouseActiveButton = i;
 		}
 
diff --git a/engines/twine/menu.h b/engines/twine/menu.h
index 63258e125b..37d1f08095 100644
--- a/engines/twine/menu.h
+++ b/engines/twine/menu.h
@@ -150,7 +150,7 @@ private:
 	 * @param dialText
 	 * @param hover flag to know if should draw as a hover button or not
 	 */
-	void drawButtonGfx(const MenuSettings *menuSettings, int32 left, int32 top, int32 right, int32 bottom, int32 buttonId, const char *dialText, bool hover);
+	void drawButtonGfx(const MenuSettings *menuSettings, const Common::Rect &rect, int32 buttonId, const char *dialText, bool hover);
 	void plasmaEffectRenderFrame();
 	/**
 	 * Process the menu button draw
diff --git a/engines/twine/menuoptions.cpp b/engines/twine/menuoptions.cpp
index ef94dd2673..e2e4eaf215 100644
--- a/engines/twine/menuoptions.cpp
+++ b/engines/twine/menuoptions.cpp
@@ -127,12 +127,9 @@ void MenuOptions::drawSelectableCharacter(int32 x, int32 y) {
 	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;
+	const Common::Rect rect(centerX - halfButtonWidth, centerY - halfButtonHeight, centerX + halfButtonWidth, centerY + halfButtonHeight);
 
-	if (_engine->_input->isMouseHovering(left, top, right, bottom)) {
+	if (_engine->_input->isMouseHovering(rect)) {
 		setOnScreenKeyboard(x, y);
 	}
 
@@ -147,13 +144,13 @@ void MenuOptions::drawSelectableCharacter(int32 x, int32 y) {
 
 	const bool selected = _onScreenKeyboardX == x && _onScreenKeyboardY == y;
 	if (selected) {
-		_engine->_interface->drawSplittedBox(left, top, right, bottom, 91);
+		_engine->_interface->drawSplittedBox(rect, 91);
 	} else {
-		_engine->_interface->blitBox(left, top, right, bottom, _engine->workVideoBuffer, left, top, _engine->frontVideoBuffer);
-		_engine->_interface->drawTransparentBox(left, top, right, bottom, 4);
+		_engine->_interface->blitBox(rect, _engine->workVideoBuffer, rect.left, rect.top, _engine->frontVideoBuffer);
+		_engine->_interface->drawTransparentBox(rect, 4);
 	}
 
-	_engine->_menu->drawBox(left, top, right, bottom);
+	_engine->_menu->drawBox(rect);
 
 	_engine->_text->setFontColor(15);
 	const uint8 character = (uint8)allowedCharIndex[idx];
@@ -161,7 +158,7 @@ void MenuOptions::drawSelectableCharacter(int32 x, int32 y) {
 	const int32 textY = centerY - _engine->_text->getCharHeight(character) / 2;
 	_engine->_text->drawText(textX, textY, buffer);
 
-	_engine->copyBlockPhys(left, top, right, bottom);
+	_engine->copyBlockPhys(rect);
 }
 
 void MenuOptions::setOnScreenKeyboard(int x, int y) {
diff --git a/engines/twine/redraw.cpp b/engines/twine/redraw.cpp
index fba1941160..f1c08afe54 100644
--- a/engines/twine/redraw.cpp
+++ b/engines/twine/redraw.cpp
@@ -102,6 +102,10 @@ void Redraw::addRedrawCurrentArea(int32 left, int32 top, int32 right, int32 bott
 	numOfRedrawBox++;
 }
 
+void Redraw::addRedrawArea(const Common::Rect &rect) {
+	addRedrawArea(rect.left, rect.top, rect.right, rect.bottom);
+}
+
 void Redraw::addRedrawArea(int32 left, int32 top, int32 right, int32 bottom) {
 	if (left < SCREEN_TEXTLIMIT_LEFT) {
 		left = SCREEN_TEXTLIMIT_LEFT;
@@ -640,9 +644,10 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 			}
 			case koInventoryItem: {
 				const int32 item = overlay->info0;
+				const Common::Rect rect(10, 10, 69, 69);
 
-				_engine->_interface->drawSplittedBox(10, 10, 69, 69, 0);
-				_engine->_interface->setClip(10, 10, 69, 69);
+				_engine->_interface->drawSplittedBox(rect, 0);
+				_engine->_interface->setClip(rect);
 
 				_engine->_renderer->prepareIsoModel(_engine->_resources->inventoryTable[item]);
 				_engine->_renderer->setCameraPosition(40, 40, 128, 200, 200);
@@ -651,8 +656,8 @@ void Redraw::redrawEngineActions(int32 bgRedraw) { // fullRedraw
 				overlayRotation += 1; // overlayRotation += 8;
 
 				_engine->_renderer->renderIsoModel(0, 0, 0, 0, overlayRotation, 0, _engine->_resources->inventoryTable[item]);
-				_engine->_menu->drawBox(10, 10, 69, 69);
-				addRedrawArea(10, 10, 69, 69);
+				_engine->_menu->drawBox(rect);
+				addRedrawArea(rect);
 				_engine->_gameState->initEngineProjections();
 				break;
 			}
diff --git a/engines/twine/redraw.h b/engines/twine/redraw.h
index 0b595f9574..7f50d9446f 100644
--- a/engines/twine/redraw.h
+++ b/engines/twine/redraw.h
@@ -24,6 +24,7 @@
 #define TWINE_REDRAW_H
 
 #include "common/scummsys.h"
+#include "common/rect.h"
 
 namespace TwinE {
 
@@ -139,6 +140,7 @@ public:
 	 * @param bottom end height to redraw the region
 	 */
 	void addRedrawArea(int32 left, int32 top, int32 right, int32 bottom);
+	void addRedrawArea(const Common::Rect &rect);
 
 	/**
 	 * Flip currentRedrawList regions in the screen


Commit: 25d8c6b1f143e99ae9fe123bb7f3611dcea6eda9
    https://github.com/scummvm/scummvm/commit/25d8c6b1f143e99ae9fe123bb7f3611dcea6eda9
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-25T17:14:16+01:00

Commit Message:
TWINE: toggle between mouse and keyboard input

Changed paths:
    engines/twine/menu.cpp


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index ae989039f1..4c30b3b5db 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -388,6 +388,8 @@ int32 Menu::processMenu(MenuSettings *menuSettings) {
 	bool buttonsNeedRedraw = true;
 	const int32 numEntry = menuSettings->getButtonCount();
 	int32 maxButton = numEntry - 1;
+	Common::Point mousepos = _engine->_input->getMousePositions();
+	bool useMouse = true;
 
 	_engine->_input->enableKeyMap(uiKeyMapId);
 
@@ -401,17 +403,25 @@ int32 Menu::processMenu(MenuSettings *menuSettings) {
 	do {
 		_engine->readKeys();
 
+		Common::Point newmousepos = _engine->_input->getMousePositions();
+		if (mousepos != newmousepos) {
+			useMouse = true;
+			mousepos = newmousepos;
+		}
+
 		if (_engine->_input->toggleActionIfActive(TwinEActionType::UIDown)) {
 			currentButton++;
 			if (currentButton == numEntry) { // if current button is the last, than next button is the first
 				currentButton = 0;
 			}
+			useMouse = false;
 			buttonsNeedRedraw = true;
 		} else if (_engine->_input->toggleActionIfActive(TwinEActionType::UIUp)) {
 			currentButton--;
 			if (currentButton < 0) { // if current button is the first, than previous button is the last
 				currentButton = maxButton;
 			}
+			useMouse = false;
 			buttonsNeedRedraw = true;
 		}
 
@@ -510,7 +520,7 @@ int32 Menu::processMenu(MenuSettings *menuSettings) {
 		if (buttonsNeedRedraw) {
 			// draw all buttons
 			const int16 mouseButtonHovered = drawButtons(menuSettings, false);
-			if (mouseButtonHovered != -1) {
+			if (useMouse && mouseButtonHovered != -1) {
 				currentButton = mouseButtonHovered;
 			}
 			menuSettings->setActiveButton(currentButton);
@@ -518,7 +528,7 @@ int32 Menu::processMenu(MenuSettings *menuSettings) {
 
 		// draw plasma effect for the current selected button
 		const int16 mouseButtonHovered = drawButtons(menuSettings, true);
-		if (mouseButtonHovered != -1) {
+		if (useMouse && mouseButtonHovered != -1) {
 			if (mouseButtonHovered != currentButton) {
 				buttonsNeedRedraw = true;
 			}




More information about the Scummvm-git-logs mailing list