[Scummvm-git-logs] scummvm master -> b902f61b3f0a38404915c1e1b576643101270c99

fracturehill noreply at scummvm.org
Thu Oct 12 09:42:53 UTC 2023


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

Summary:
56b48f6186 NANCY: Add GetEngineData macro
dc3e14d4fc NANCY: Add MouseFollowObject class
b902f61b3f AGS: Fix AVX2 blitting


Commit: 56b48f61862c547a93250a34442a0f7614518bb4
    https://github.com/scummvm/scummvm/commit/56b48f61862c547a93250a34442a0f7614518bb4
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-10-12T12:42:28+03:00

Commit Message:
NANCY: Add GetEngineData macro

Added a macro that hides away the ugly casts whenever
an EngineData object is requested.

Changed paths:
    engines/nancy/action/actionmanager.cpp
    engines/nancy/action/conversation.cpp
    engines/nancy/action/miscrecords.cpp
    engines/nancy/action/overlay.cpp
    engines/nancy/action/puzzle/raycastpuzzle.cpp
    engines/nancy/action/puzzle/sliderpuzzle.cpp
    engines/nancy/action/soundrecords.cpp
    engines/nancy/console.cpp
    engines/nancy/cursor.cpp
    engines/nancy/font.cpp
    engines/nancy/graphics.cpp
    engines/nancy/misc/specialeffect.cpp
    engines/nancy/nancy.cpp
    engines/nancy/nancy.h
    engines/nancy/puzzledata.cpp
    engines/nancy/state/credits.cpp
    engines/nancy/state/help.cpp
    engines/nancy/state/loadsave.cpp
    engines/nancy/state/mainmenu.cpp
    engines/nancy/state/map.cpp
    engines/nancy/state/savedialog.cpp
    engines/nancy/state/scene.cpp
    engines/nancy/state/setupmenu.cpp
    engines/nancy/ui/clock.cpp
    engines/nancy/ui/inventorybox.cpp
    engines/nancy/ui/ornaments.cpp
    engines/nancy/ui/textbox.cpp
    engines/nancy/ui/viewport.cpp


diff --git a/engines/nancy/action/actionmanager.cpp b/engines/nancy/action/actionmanager.cpp
index 3424df17b6f..a7d762331c0 100644
--- a/engines/nancy/action/actionmanager.cpp
+++ b/engines/nancy/action/actionmanager.cpp
@@ -89,7 +89,7 @@ void ActionManager::handleInput(NancyInput &input) {
 
 						// Re-add the object to the inventory unless it's marked as a one-time use
 						if (item == NancySceneState.getHeldItem() && item != -1) {
-							const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+							auto *inventoryData = GetEngineData(INV);
 							assert(inventoryData);
 
 							switch (inventoryData->itemDescriptions[item].keepItem) {
diff --git a/engines/nancy/action/conversation.cpp b/engines/nancy/action/conversation.cpp
index a7748341dc5..fdf7ba505ed 100644
--- a/engines/nancy/action/conversation.cpp
+++ b/engines/nancy/action/conversation.cpp
@@ -165,7 +165,7 @@ void ConversationSound::execute() {
 	case kRun:
 		if (!_hasDrawnTextbox) {
 			_hasDrawnTextbox = true;
-			const TBOX *textboxData = (const TBOX *)g_nancy->getEngineData("TBOX");
+			auto *textboxData = GetEngineData(TBOX);
 			assert(textboxData);
 			NancySceneState.getTextbox().clear();
 			NancySceneState.getTextbox().setOverrideFont(textboxData->conversationFontID);
diff --git a/engines/nancy/action/miscrecords.cpp b/engines/nancy/action/miscrecords.cpp
index fcf720384d8..a3e8b13358b 100644
--- a/engines/nancy/action/miscrecords.cpp
+++ b/engines/nancy/action/miscrecords.cpp
@@ -128,7 +128,7 @@ void TableIndexSetValueHS::execute() {
 	case kActionTrigger: {
 		TableData *playerTable = (TableData *)NancySceneState.getPuzzleData(TableData::getTag());
 		assert(playerTable);
-		const TABL *tabl = (const TABL *)g_nancy->getEngineData("TABL");
+		auto *tabl = GetEngineData(TABL);
 		assert(tabl);
 
 		// Edit table. Values start from 1!
diff --git a/engines/nancy/action/overlay.cpp b/engines/nancy/action/overlay.cpp
index 5cfb87cd474..27406493ca4 100644
--- a/engines/nancy/action/overlay.cpp
+++ b/engines/nancy/action/overlay.cpp
@@ -424,7 +424,7 @@ void TableIndexOverlay::execute() {
 
 	TableData *playerTable = (TableData *)NancySceneState.getPuzzleData(TableData::getTag());
 	assert(playerTable);
-	const TABL *tabl = (const TABL *)g_nancy->getEngineData("TABL");
+	auto *tabl = GetEngineData(TABL);
 	assert(tabl);
 
 	if (_lastIndexVal != playerTable->currentIDs[_tableIndex - 1]) {
diff --git a/engines/nancy/action/puzzle/raycastpuzzle.cpp b/engines/nancy/action/puzzle/raycastpuzzle.cpp
index 16f4717a170..e3c0af9044e 100644
--- a/engines/nancy/action/puzzle/raycastpuzzle.cpp
+++ b/engines/nancy/action/puzzle/raycastpuzzle.cpp
@@ -106,7 +106,7 @@ public:
 };
 
 RaycastLevelBuilder::RaycastLevelBuilder(uint width, uint height, uint verticalHeight) {
-	_themeData = (const RCLB *)g_nancy->getEngineData("RCLB");
+	_themeData = GetEngineData(RCLB);
 	assert(_themeData);
 
 	_verticalHeight = verticalHeight;
@@ -896,7 +896,7 @@ private:
 bool RaycastDeferredLoader::loadInner() {
 	switch(_loadState) {
 	case kInitDrawSurface : {
-		const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+		auto *viewportData = GetEngineData(VIEW);
 		assert(viewportData);
 		
 		Common::Rect viewport = viewportData->bounds;
@@ -954,7 +954,7 @@ bool RaycastDeferredLoader::loadInner() {
 	}
 	case kInitTables1 : {
 		Common::Rect selectedBounds = _owner._puzzleData->screenViewportSizes[_owner._puzzleData->viewportSizeUsed];
-		const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+		auto *viewportData = GetEngineData(VIEW);
 		assert(viewportData);
 
 		_owner._wallCastColumnAngles.resize(viewportData->screenPosition.width());
@@ -972,7 +972,7 @@ bool RaycastDeferredLoader::loadInner() {
 		break;
 	}
 	case kInitTables2 : {
-		const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+		auto *viewportData = GetEngineData(VIEW);
 		assert(viewportData);
 
 		_owner._sinTable.resize(4096);
@@ -1065,7 +1065,7 @@ bool RaycastDeferredLoader::loadInner() {
 }
 
 void RaycastPuzzle::init() {
-	_puzzleData = (const RCPR *)g_nancy->getEngineData("RCPR");
+	_puzzleData = GetEngineData(RCPR);
 	assert(_puzzleData);
 
 	RaycastDeferredLoader *loader = _loaderPtr.get();
@@ -1350,7 +1350,7 @@ void RaycastPuzzle::updateGraphics() {
 
 void RaycastPuzzle::drawMap() {
 	// Improvement: the original map is drawn upside-down; ours isn't
-	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bootSummary = GetEngineData(BSUM);
 	assert(bootSummary);
 
 	_mapBaseSurface.create(_mapFullWidth, _mapFullHeight, g_nancy->_graphicsManager->getInputPixelFormat());
diff --git a/engines/nancy/action/puzzle/sliderpuzzle.cpp b/engines/nancy/action/puzzle/sliderpuzzle.cpp
index 9eea3498898..38d3f2ffbc9 100644
--- a/engines/nancy/action/puzzle/sliderpuzzle.cpp
+++ b/engines/nancy/action/puzzle/sliderpuzzle.cpp
@@ -44,7 +44,7 @@ void SliderPuzzle::init() {
 }
 
 void SliderPuzzle::readData(Common::SeekableReadStream &stream) {
-	_spuzData = (const SPUZ*)g_nancy->getEngineData("SPUZ");
+	_spuzData = GetEngineData(SPUZ);
 	assert(_spuzData);
 
 	_puzzleState = (SliderPuzzleData *)NancySceneState.getPuzzleData(SliderPuzzleData::getTag());
diff --git a/engines/nancy/action/soundrecords.cpp b/engines/nancy/action/soundrecords.cpp
index 3e07e9770b7..db704caba70 100644
--- a/engines/nancy/action/soundrecords.cpp
+++ b/engines/nancy/action/soundrecords.cpp
@@ -286,7 +286,7 @@ void TableIndexPlaySound::readData(Common::SeekableReadStream &stream) {
 void TableIndexPlaySound::execute() {
 	TableData *playerTable = (TableData *)NancySceneState.getPuzzleData(TableData::getTag());
 	assert(playerTable);
-	const TABL *tabl = (const TABL *)g_nancy->getEngineData("TABL");
+	auto *tabl = GetEngineData(TABL);
 	assert(tabl);
 
 	if (_lastIndexVal != playerTable->currentIDs[_tableIndex - 1]) {
diff --git a/engines/nancy/console.cpp b/engines/nancy/console.cpp
index 3db52724682..785aa363964 100644
--- a/engines/nancy/console.cpp
+++ b/engines/nancy/console.cpp
@@ -478,7 +478,7 @@ void NancyConsole::printActionRecord(const Nancy::Action::ActionRecord *record,
 void NancyConsole::recursePrintDependencies(const Nancy::Action::DependencyRecord &record) {
 	using namespace Nancy::Action;
 
-	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	auto *inventoryData = GetEngineData(INV);
 	assert(inventoryData);
 
 	for (const DependencyRecord &dep : record.children) {
@@ -816,7 +816,7 @@ bool NancyConsole::Cmd_getInventory(int argc, const char **argv) {
 	}
 
 	uint numItems = g_nancy->getStaticData().numItems;
-	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	auto *inventoryData = GetEngineData(INV);
 	assert(inventoryData);
 
 	debugPrintf("Total number of inventory items: %u\n", numItems);
@@ -853,7 +853,7 @@ bool NancyConsole::Cmd_getInventory(int argc, const char **argv) {
 }
 
 bool NancyConsole::Cmd_setInventory(int argc, const char **argv) {
-	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	auto *inventoryData = GetEngineData(INV);
 	assert(inventoryData);
 	
 	if (g_nancy->_gameFlow.curState != NancyState::kScene) {
diff --git a/engines/nancy/cursor.cpp b/engines/nancy/cursor.cpp
index 81c2e2a4dc8..29a1c323d59 100644
--- a/engines/nancy/cursor.cpp
+++ b/engines/nancy/cursor.cpp
@@ -92,7 +92,7 @@ void CursorManager::init(Common::SeekableReadStream *chunkStream) {
 	_primaryVideoInitialPos.x = chunkStream->readUint16LE();
 	_primaryVideoInitialPos.y = chunkStream->readUint16LE();
 
-	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	auto *inventoryData = GetEngineData(INV);
 	assert(inventoryData);
 
 	g_nancy->_resource->loadImage(inventoryData->inventoryCursorsImageName, _invCursorsSurface);
diff --git a/engines/nancy/font.cpp b/engines/nancy/font.cpp
index d9e05faa0a8..34918b5c2f2 100644
--- a/engines/nancy/font.cpp
+++ b/engines/nancy/font.cpp
@@ -117,7 +117,7 @@ void Font::read(Common::SeekableReadStream &stream) {
 		_fontHeight = MAX<int>(cur.height(), _fontHeight);
 	}
 
-	_textboxData = (const TBOX *)g_nancy->getEngineData("TBOX");
+	_textboxData = GetEngineData(TBOX);
 	assert(_textboxData);
 }
 
diff --git a/engines/nancy/graphics.cpp b/engines/nancy/graphics.cpp
index 33299a847c9..ca9e9334d75 100644
--- a/engines/nancy/graphics.cpp
+++ b/engines/nancy/graphics.cpp
@@ -40,7 +40,7 @@ GraphicsManager::GraphicsManager() :
 	_isSuppressed(false) {}
 
 void GraphicsManager::init() {
-	const BSUM *bsum = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bsum = GetEngineData(BSUM);
 	assert(bsum);
 
 	// Extract transparent color from the boot summary
@@ -133,7 +133,7 @@ void GraphicsManager::draw(bool updateScreen) {
 }
 
 void GraphicsManager::loadFonts(Common::SeekableReadStream *chunkStream) {
-	const BSUM *bsum = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bsum = GetEngineData(BSUM);
 	assert(bsum);
 	assert(chunkStream);
 
diff --git a/engines/nancy/misc/specialeffect.cpp b/engines/nancy/misc/specialeffect.cpp
index 307b3c25f91..b039824ba19 100644
--- a/engines/nancy/misc/specialeffect.cpp
+++ b/engines/nancy/misc/specialeffect.cpp
@@ -30,7 +30,7 @@ namespace Misc {
 void SpecialEffect::init() {
 	if (g_nancy->getGameType() <= kGameTypeNancy6) {
 		// nancy2-6 have a fixed number of frames for the effect, which is defined in the SPEC chunk
-		const SPEC *specialEffectData = (const SPEC *)g_nancy->getEngineData("SPEC");
+		auto *specialEffectData = GetEngineData(SPEC);
 		assert(specialEffectData);
 
 		_numFrames = _type == kBlackout ? specialEffectData->fadeToBlackNumFrames : specialEffectData->crossDissolveNumFrames;
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index b35465b30e2..e7ef2b78d1a 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -457,7 +457,7 @@ void NancyEngine::bootGameEngine() {
 	delete iff;
 
 	// Load convo texts and autotext
-	const BSUM *bsum = (const BSUM *)getEngineData("BSUM");
+	auto *bsum = GetEngineData(BSUM);
 	if (bsum && bsum->conversationTextsFilename.size() && bsum->autotextFilename.size())  {
 		iff = new IFF(bsum->conversationTextsFilename);
 		if (!iff->load()) {
@@ -566,7 +566,7 @@ void NancyEngine::destroyState(NancyState::NancyState state) const {
 }
 
 void NancyEngine::preloadCals() {
-	const PCAL *pcal = (const PCAL *)getEngineData("PCAL");
+	auto *pcal = GetEngineData(PCAL);
 	if (!pcal) {
 		// CALs only appeared in nancy2 so a PCAL chunk may not exist
 		return;
@@ -620,7 +620,7 @@ void NancyEngine::readDatFile() {
 }
 
 Common::Error NancyEngine::synchronize(Common::Serializer &ser) {
-	const BSUM *bootSummary = (const BSUM *)getEngineData("BSUM");
+	auto *bootSummary = GetEngineData(BSUM);
 	assert(bootSummary);
 
 	// Sync boot summary header, which includes full game title
diff --git a/engines/nancy/nancy.h b/engines/nancy/nancy.h
index 89dec377691..87847ed22e2 100644
--- a/engines/nancy/nancy.h
+++ b/engines/nancy/nancy.h
@@ -161,6 +161,7 @@ private:
 };
 
 extern NancyEngine *g_nancy;
+#define GetEngineData(s) (const s*)g_nancy->getEngineData(#s);
 
 } // End of namespace Nancy
 
diff --git a/engines/nancy/puzzledata.cpp b/engines/nancy/puzzledata.cpp
index 7a0a6199784..54549363457 100644
--- a/engines/nancy/puzzledata.cpp
+++ b/engines/nancy/puzzledata.cpp
@@ -137,7 +137,7 @@ void JournalData::synchronize(Common::Serializer &ser) {
 }
 
 TableData::TableData() {
-	const TABL *tabl = (const TABL *)g_nancy->getEngineData("TABL");
+	auto *tabl = GetEngineData(TABL);
 	assert(tabl);
 
 	currentIDs = tabl->startIDs;
diff --git a/engines/nancy/state/credits.cpp b/engines/nancy/state/credits.cpp
index 71587866033..14756f90273 100644
--- a/engines/nancy/state/credits.cpp
+++ b/engines/nancy/state/credits.cpp
@@ -69,7 +69,7 @@ bool Credits::onStateExit(const NancyState::NancyState nextState) {
 }
 
 void Credits::init() {
-	_creditsData = (const CRED *)g_nancy->getEngineData("CRED");
+	_creditsData = GetEngineData(CRED);
 	assert(_creditsData);
 
 	_background.init(_creditsData->imageName);
diff --git a/engines/nancy/state/help.cpp b/engines/nancy/state/help.cpp
index cb6d93f7fcb..9b244146ab9 100644
--- a/engines/nancy/state/help.cpp
+++ b/engines/nancy/state/help.cpp
@@ -80,7 +80,7 @@ bool Help::onStateExit(const NancyState::NancyState nextState) {
 }
 
 void Help::init() {
-	const HELP *helpData = (const HELP *)g_nancy->getEngineData("HELP");
+	auto *helpData = GetEngineData(HELP);
 	assert(helpData);
 	
 	_image.init(helpData->imageName);
@@ -110,7 +110,7 @@ void Help::run() {
 	_button->handleInput(input);
 
 	if (_button->_isClicked) {
-		const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+		auto *bootSummary = GetEngineData(BSUM);
 		assert(bootSummary);
 
 		_button->_isClicked = false;
diff --git a/engines/nancy/state/loadsave.cpp b/engines/nancy/state/loadsave.cpp
index 725426f9720..bc365e46e15 100644
--- a/engines/nancy/state/loadsave.cpp
+++ b/engines/nancy/state/loadsave.cpp
@@ -139,7 +139,7 @@ void LoadSaveMenu::registerGraphics() {
 }
 
 void LoadSaveMenu::init() {
-	_loadSaveData = (const LOAD*)g_nancy->getEngineData("LOAD");
+	_loadSaveData = GetEngineData(LOAD);
 	assert(_loadSaveData);
 
 	_background.init(_loadSaveData->_imageName);
@@ -449,7 +449,7 @@ void LoadSaveMenu::enterFilename() {
 }
 
 void LoadSaveMenu::save() {
-	const SDLG *sdlg = (const SDLG *)g_nancy->getEngineData("SDLG");
+	auto *sdlg = GetEngineData(SDLG);
 
 	if (sdlg && sdlg->dialogs.size() > 1) {
 		// nancy6 added a "Do you want to overwrite this save" dialog.
@@ -510,7 +510,7 @@ void LoadSaveMenu::save() {
 }
 
 void LoadSaveMenu::load() {
-	const SDLG *sdlg = (const SDLG *)g_nancy->getEngineData("SDLG");
+	auto *sdlg = GetEngineData(SDLG);
 
 	if (sdlg && sdlg->dialogs.size() > 1 && Nancy::State::Scene::hasInstance() && !g_nancy->_hasJustSaved) {
 		// nancy6 added a "Do you want load without saving" dialog.
diff --git a/engines/nancy/state/mainmenu.cpp b/engines/nancy/state/mainmenu.cpp
index 0e05748bbbd..83307df444c 100644
--- a/engines/nancy/state/mainmenu.cpp
+++ b/engines/nancy/state/mainmenu.cpp
@@ -84,7 +84,7 @@ void MainMenu::clearButtonState() {
 }
 
 void MainMenu::init() {
-	_menuData = (const MENU*)g_nancy->getEngineData("MENU");
+	_menuData = GetEngineData(MENU);
 	assert(_menuData);
 
 	_background.init(_menuData->_imageName);
diff --git a/engines/nancy/state/map.cpp b/engines/nancy/state/map.cpp
index 5b0d8df9f60..6ae39f44abc 100644
--- a/engines/nancy/state/map.cpp
+++ b/engines/nancy/state/map.cpp
@@ -54,7 +54,7 @@ Map::Map() : _state(kInit),
 			_label(7),
 			_closedLabel(7),
 			_background(0) {
-	_mapData = (const MAP*)g_nancy->getEngineData("MAP");
+	_mapData = GetEngineData(MAP);
 	assert(_mapData);
 }
 
@@ -146,7 +146,7 @@ void Map::setLabel(int labelID) {
 }
 
 void Map::MapViewport::init() {
-	const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+	auto *viewportData = GetEngineData(VIEW);
 	assert(viewportData);
 
 	moveTo(viewportData->screenPosition);
@@ -193,7 +193,7 @@ void TVDMap::init() {
 	_ornaments.init();
 	_globe.init();
 
-	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bootSummary = GetEngineData(BSUM);
 	assert(bootSummary);
 
 	Common::Rect textboxScreenPosition = bootSummary->textboxScreenPosition;
diff --git a/engines/nancy/state/savedialog.cpp b/engines/nancy/state/savedialog.cpp
index eea07a9362a..b9a860e46e4 100644
--- a/engines/nancy/state/savedialog.cpp
+++ b/engines/nancy/state/savedialog.cpp
@@ -89,7 +89,7 @@ void SaveDialog::registerGraphics() {
 }
 
 void SaveDialog::init() {
-	const SDLG* sdlg = (const SDLG*)g_nancy->getEngineData("SDLG");
+	auto *sdlg = GetEngineData(SDLG);
 	assert(sdlg);
 
 	_dialogData = &sdlg->dialogs[ConfMan.getInt("sdlg_id", ConfMan.kTransientDomain)];
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index fcbcbb6226d..54b69c79f7e 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -89,7 +89,7 @@ void Scene::SceneSummary::read(Common::SeekableReadStream &stream) {
 	ser.syncAsUint16LE((uint32 &)fastMoveTimeDelta);
 	ser.skip(1); // CD required for scene
 
-	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bootSummary = GetEngineData(BSUM);
 	assert(bootSummary);
 
 	if (bootSummary->overrideMovementTimeDeltas) {
@@ -269,7 +269,7 @@ void Scene::setPlayerTime(Time time, byte relative) {
 		_timers.playerTime = _timers.playerTime.getDays() * 86400000 + time;
 	}
 
-	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bootSummary = GetEngineData(BSUM);
 	assert(bootSummary);
 
 	_timers.playerTimeNextMinute = g_nancy->getTotalPlayTime() + bootSummary->playerTimeMinuteLength;
@@ -293,7 +293,7 @@ byte Scene::getPlayerTOD() const {
 		}
 	} else {
 		// nancy6 added the day start/end times (in minutes) to BSUM
-		const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+		auto *bootSummary = GetEngineData(BSUM);
 		assert(bootSummary);
 
 		uint16 minutes = _timers.playerTime.getHours() * 60 + _timers.playerTime.getMinutes();
@@ -381,7 +381,7 @@ void Scene::playItemCantSound(int16 itemID) {
 	}
 
 	// Improvement: nancy2 never shows the caption text, even though it exists in the data; we show it
-	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	auto *inventoryData = GetEngineData(INV);
 	assert(inventoryData);
 
 	if (itemID < 0) {
@@ -727,8 +727,8 @@ UI::Clock *Scene::getClock() {
 }
 
 void Scene::init() {
-	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
-	const HINT *hintData = (const HINT *)g_nancy->getEngineData("HINT");
+	auto *bootSummary = GetEngineData(BSUM);
+	auto *hintData = GetEngineData(HINT);
 	assert(bootSummary);
 
 	_flags.eventFlags.resize(g_nancy->getStaticData().numEventFlags, g_nancy->_false);
@@ -954,7 +954,7 @@ void Scene::run() {
 
 	// Calculate the in-game time (playerTime)
 	if (currentPlayTime > _timers.playerTimeNextMinute) {
-		const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+		auto *bootSummary = GetEngineData(BSUM);
 		assert(bootSummary);
 
 		_timers.playerTime += 60000; // Add a minute
@@ -1063,7 +1063,7 @@ void Scene::handleInput() {
 
 		if (_menuButton->_isClicked) {
 			if (_buttonPressActivationTime == 0) {
-				const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+				auto *bootSummary = GetEngineData(BSUM);
 				assert(bootSummary);
 
 				g_nancy->_sound->playSound("BUOK");
@@ -1081,7 +1081,7 @@ void Scene::handleInput() {
 
 		if (_helpButton->_isClicked) {
 			if (_buttonPressActivationTime == 0) {
-				const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+				auto *bootSummary = GetEngineData(BSUM);
 				assert(bootSummary);
 
 				g_nancy->_sound->playSound("BUOK");
@@ -1096,13 +1096,13 @@ void Scene::handleInput() {
 }
 
 void Scene::initStaticData() {
-	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bootSummary = GetEngineData(BSUM);
 	assert(bootSummary);
 
 	const ImageChunk *fr0 = (const ImageChunk *)g_nancy->getEngineData("FR0");
 	assert(fr0);
 
-	const MAP *mapData = (const MAP *)g_nancy->getEngineData("MAP");
+	auto *mapData = GetEngineData(MAP);
 
 	_frame.init(fr0->imageName);
 	_viewport.init();
diff --git a/engines/nancy/state/setupmenu.cpp b/engines/nancy/state/setupmenu.cpp
index 2064bcfc227..1d8ca45ee63 100644
--- a/engines/nancy/state/setupmenu.cpp
+++ b/engines/nancy/state/setupmenu.cpp
@@ -128,7 +128,7 @@ const Common::String SetupMenu::getToggleConfManKey(uint id) {
 }
 
 void SetupMenu::init() {
-	_setupData = (const SET*)g_nancy->getEngineData("SET");
+	_setupData = GetEngineData(SET);
 	assert(_setupData);
 
 	if (g_nancy->getGameType() == kGameTypeVampire) {
diff --git a/engines/nancy/ui/clock.cpp b/engines/nancy/ui/clock.cpp
index 104ee8737ba..c7567b6607f 100644
--- a/engines/nancy/ui/clock.cpp
+++ b/engines/nancy/ui/clock.cpp
@@ -125,7 +125,7 @@ void Clock::drawClockHands() {
 }
 
 void Clock::ClockAnim::init() {
-	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bootSummary = GetEngineData(BSUM);
 	assert(bootSummary);
 
 	_srcRects = _owner->_clockData->animSrcs;
@@ -187,7 +187,7 @@ void Clock::ClockAnim::onTrigger() {
 }
 
 void Nancy5Clock::init() {
-	_clockData = (const CLOK *)g_nancy->getEngineData("CLOK");
+	_clockData = GetEngineData(CLOK);
 	assert(_clockData);
 
 	setVisible(true);
diff --git a/engines/nancy/ui/inventorybox.cpp b/engines/nancy/ui/inventorybox.cpp
index f5400d15d9e..162516ca54c 100644
--- a/engines/nancy/ui/inventorybox.cpp
+++ b/engines/nancy/ui/inventorybox.cpp
@@ -49,10 +49,10 @@ InventoryBox::~InventoryBox() {
 }
 
 void InventoryBox::init() {
-	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bootSummary = GetEngineData(BSUM);
 	assert(bootSummary);
 
-	_inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	_inventoryData = GetEngineData(INV);
 	assert(_inventoryData);
 
 	_order.clear();
@@ -251,10 +251,10 @@ void InventoryBox::onScrollbarMove() {
 }
 
 void InventoryBox::Curtains::init() {
-	const INV *_inventoryData = (const INV *)g_nancy->getEngineData("INV");
-	assert(_inventoryData);
+	auto *inventoryData = GetEngineData(INV);
+	assert(inventoryData);
 
-	moveTo(_inventoryData->curtainsScreenPosition);
+	moveTo(inventoryData->curtainsScreenPosition);
 	Common::Rect bounds = _screenPosition;
 	bounds.moveTo(0, 0);
 	_drawSurface.create(bounds.width(), bounds.height(), g_nancy->_graphicsManager->getInputPixelFormat());
@@ -277,11 +277,11 @@ void InventoryBox::Curtains::updateGraphics() {
 	Time time = g_nancy->getTotalPlayTime();
 	if (_areOpen) {
 		if (_curFrame < g_nancy->getStaticData().numCurtainAnimationFrames && time > _nextFrameTime) {
-			const INV *_inventoryData = (const INV *)g_nancy->getEngineData("INV");
-			assert(_inventoryData);
+			auto *inventoryData = GetEngineData(INV);
+			assert(inventoryData);
 
 			setAnimationFrame(++_curFrame);
-			_nextFrameTime = time + _inventoryData->curtainsFrameTime;
+			_nextFrameTime = time + inventoryData->curtainsFrameTime;
 
 			if (!_soundTriggered) {
 				_soundTriggered = true;
@@ -290,11 +290,11 @@ void InventoryBox::Curtains::updateGraphics() {
 		}
 	} else {
 		if (_curFrame > 0 && time > _nextFrameTime) {
-			const INV *_inventoryData = (const INV *)g_nancy->getEngineData("INV");
-			assert(_inventoryData);
+			auto *inventoryData = GetEngineData(INV);
+			assert(inventoryData);
 
 			setAnimationFrame(--_curFrame);
-			_nextFrameTime = time + _inventoryData->curtainsFrameTime;
+			_nextFrameTime = time + inventoryData->curtainsFrameTime;
 
 			if (!_soundTriggered) {
 				_soundTriggered = true;
@@ -324,17 +324,17 @@ void InventoryBox::Curtains::setAnimationFrame(uint frame) {
 		setVisible(true);
 	}
 
-	const INV *_inventoryData = (const INV *)g_nancy->getEngineData("INV");
-	assert(_inventoryData);
+	auto *inventoryData = GetEngineData(INV);
+	assert(inventoryData);
 
 	_drawSurface.clear(g_nancy->_graphicsManager->getTransColor());
 
 	// Draw left curtain
-	srcRect = _inventoryData->curtainAnimationSrcs[frame * 2];
+	srcRect = inventoryData->curtainAnimationSrcs[frame * 2];
 	_drawSurface.blitFrom(_object0, srcRect, destPoint);
 
 	// Draw right curtain
-	srcRect = _inventoryData->curtainAnimationSrcs[frame * 2 + 1];
+	srcRect = inventoryData->curtainAnimationSrcs[frame * 2 + 1];
 	destPoint.x = getBounds().width() - srcRect.width();
 	_drawSurface.blitFrom(_object0, srcRect, destPoint);
 
diff --git a/engines/nancy/ui/ornaments.cpp b/engines/nancy/ui/ornaments.cpp
index 58fc6945d99..59521bcb270 100644
--- a/engines/nancy/ui/ornaments.cpp
+++ b/engines/nancy/ui/ornaments.cpp
@@ -29,7 +29,7 @@ namespace Nancy {
 namespace UI {
 
 void ViewportOrnaments::init() {
-	const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+	auto *viewportData = GetEngineData(VIEW);
 	assert(viewportData);
 
 	Common::Rect viewportBounds = viewportData->bounds;
@@ -74,10 +74,10 @@ void ViewportOrnaments::init() {
 }
 
 void TextboxOrnaments::init() {
-	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bootSummary = GetEngineData(BSUM);
 	assert(bootSummary);
 
-	const TBOX *textboxData = (const TBOX *)g_nancy->getEngineData("TBOX");
+	auto *textboxData = GetEngineData(TBOX);
 	assert(textboxData);
 
 	moveTo(bootSummary->textboxScreenPosition);
@@ -105,10 +105,10 @@ void TextboxOrnaments::init() {
 }
 
 void InventoryBoxOrnaments::init() {
-	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bootSummary = GetEngineData(BSUM);
 	assert(bootSummary);
 
-	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	auto *inventoryData = GetEngineData(INV);
 	assert(inventoryData);
 
 	moveTo(bootSummary->inventoryBoxScreenPosition);
diff --git a/engines/nancy/ui/textbox.cpp b/engines/nancy/ui/textbox.cpp
index e60f2232e35..83abe3b56f9 100644
--- a/engines/nancy/ui/textbox.cpp
+++ b/engines/nancy/ui/textbox.cpp
@@ -48,10 +48,10 @@ Textbox::~Textbox() {
 }
 
 void Textbox::init() {
-	const BSUM *bsum = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bsum = GetEngineData(BSUM);
 	assert(bsum);
 
-	const TBOX *tbox = (const TBOX *)g_nancy->getEngineData("TBOX");
+	auto *tbox = GetEngineData(TBOX);
 	assert(tbox);
 
 	moveTo(bsum->textboxScreenPosition);
@@ -135,7 +135,7 @@ void Textbox::handleInput(NancyInput &input) {
 }
 
 void Textbox::drawTextbox() {
-	const TBOX *tbox = (const TBOX *)g_nancy->getEngineData("TBOX");
+	auto *tbox = GetEngineData(TBOX);
 	assert(tbox);
 
 	Common::Rect textBounds = _fullSurface.getBounds();
@@ -179,7 +179,7 @@ void Textbox::addTextLine(const Common::String &text, uint32 autoClearTime) {
 }
 
 void Textbox::setOverrideFont(const uint fontID) {
-	const BSUM *bsum = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bsum = GetEngineData(BSUM);
 	assert(bsum);
 
 	if (fontID >= bsum->numFonts) {
@@ -212,7 +212,7 @@ uint16 Textbox::getInnerHeight() const {
 	// As early as nancy3 this behavior stopped being relevant, as the original
 	// engine always scrolls down to the bottom of the entire inner surface.
 	// However, that makes the scrollbar almost unusable, so I'm not changing this.
-	const TBOX *tbox = (const TBOX *)g_nancy->getEngineData("TBOX");
+	auto *tbox = GetEngineData(TBOX);
 	assert(tbox);
 
 	return _drawnTextHeight + tbox->upOffset + tbox->downOffset;
diff --git a/engines/nancy/ui/viewport.cpp b/engines/nancy/ui/viewport.cpp
index 41ac65c4ec8..6eb004a4232 100644
--- a/engines/nancy/ui/viewport.cpp
+++ b/engines/nancy/ui/viewport.cpp
@@ -38,10 +38,10 @@ namespace UI {
 
 // does NOT put the object in a valid state until loadVideo is called
 void Viewport::init() {
-	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	auto *bootSummary = GetEngineData(BSUM);
 	assert(bootSummary);
 
-	const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+	auto *viewportData = GetEngineData(VIEW);
 	assert(viewportData);
 
 	moveTo(viewportData->screenPosition);


Commit: dc3e14d4fc7df0d8c7ff7b9546abe89be3282e8f
    https://github.com/scummvm/scummvm/commit/dc3e14d4fc7df0d8c7ff7b9546abe89be3282e8f
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-10-12T12:42:28+03:00

Commit Message:
NANCY: Add MouseFollowObject class

Added a class that combines a certain behavior used by
several puzzles: that of an object that follows the mouse
cursor, but stays within the Viewport's bounds.

Changed paths:
  A engines/nancy/misc/mousefollow.cpp
  A engines/nancy/misc/mousefollow.h
    engines/nancy/action/puzzle/rippedletterpuzzle.cpp
    engines/nancy/action/puzzle/rippedletterpuzzle.h
    engines/nancy/action/puzzle/tangrampuzzle.cpp
    engines/nancy/action/puzzle/tangrampuzzle.h
    engines/nancy/action/puzzle/towerpuzzle.cpp
    engines/nancy/action/puzzle/towerpuzzle.h
    engines/nancy/module.mk


diff --git a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
index 3d8cfd36f72..21740ec4ec4 100644
--- a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
+++ b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
@@ -242,6 +242,7 @@ void RippedLetterPuzzle::handleInput(NancyInput &input) {
 						_pickedUpPiece._drawSurface.blitFrom(_drawSurface, _destRects[i], Common::Point());
 						_pickedUpPiece.setVisible(true);
 						_pickedUpPiece.setTransparent(true);
+						_pickedUpPiece.pickUp();
 
 						// ...then change the data...
 						_pickedUpPieceID = _puzzleState->order[i];
@@ -296,34 +297,9 @@ void RippedLetterPuzzle::handleInput(NancyInput &input) {
 		}
 	}
 
-	// Now move the carried piece
-	if (_pickedUpPieceID != -1) {
-		// First, move the piece so its center is below the mouse hotspot
-		Common::Rect newLocation = _pickedUpPiece._drawSurface.getBounds();
-		newLocation.moveTo(input.mousePos.x, input.mousePos.y);
-		newLocation.translate(-newLocation.width() / 2, -newLocation.height() / 2);
+	_pickedUpPiece.handleInput(input);
 
-		// Then, make sure it doesn't escape outside the viewport bounds
-		Common::Rect screen = NancySceneState.getViewport().getScreenPosition();
-
-		if (newLocation.left < screen.left) {
-			newLocation.translate(screen.left - newLocation.left, 0);
-		}
-
-		if (newLocation.top < screen.top) {
-			newLocation.translate(0, screen.top - newLocation.top);
-		}
-
-		if (newLocation.right > screen.right) {
-			newLocation.translate(screen.right - newLocation.right, 0);
-		}
-
-		if (newLocation.bottom > screen.bottom) {
-			newLocation.translate(0, screen.bottom - newLocation.bottom);
-		}
-
-		_pickedUpPiece.moveTo(newLocation);
-	} else {
+	if (_pickedUpPieceID == -1) {
 		// No piece picked up, check the exit hotspot
 		if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
 			g_nancy->_cursorManager->setCursorType(g_nancy->_cursorManager->_puzzleExitCursor);
diff --git a/engines/nancy/action/puzzle/rippedletterpuzzle.h b/engines/nancy/action/puzzle/rippedletterpuzzle.h
index 04207cc2037..49380dca5e1 100644
--- a/engines/nancy/action/puzzle/rippedletterpuzzle.h
+++ b/engines/nancy/action/puzzle/rippedletterpuzzle.h
@@ -23,6 +23,7 @@
 #define NANCY_ACTION_RIPPEDLETTERPUZZLE_H
 
 #include "engines/nancy/action/actionrecord.h"
+#include "engines/nancy/misc/mousefollow.h"
 
 namespace Nancy {
 
@@ -33,7 +34,7 @@ namespace Action {
 class RippedLetterPuzzle : public RenderActionRecord {
 public:
 	enum SolveState { kNotSolved, kWaitForSound };
-	RippedLetterPuzzle() : RenderActionRecord(7), _pickedUpPiece(8) {}
+	RippedLetterPuzzle() : RenderActionRecord(7) {}
 	virtual ~RippedLetterPuzzle() {}
 
 	void init() override;
@@ -60,7 +61,7 @@ public:
 	SceneChangeWithFlag _exitScene;
 	Common::Rect _exitHotspot;
 
-	RenderObject _pickedUpPiece;
+	Misc::MouseFollowObject _pickedUpPiece;
 	int8 _pickedUpPieceID = -1;
 	byte _pickedUpPieceRot = 0;
 
diff --git a/engines/nancy/action/puzzle/tangrampuzzle.cpp b/engines/nancy/action/puzzle/tangrampuzzle.cpp
index 8418930f28d..cf68b9549ea 100644
--- a/engines/nancy/action/puzzle/tangrampuzzle.cpp
+++ b/engines/nancy/action/puzzle/tangrampuzzle.cpp
@@ -253,29 +253,8 @@ void TangramPuzzle::handleInput(NancyInput &input) {
 			g_nancy->_sound->playSound(_putDownSound);
 			return;
 		}
-
-		// Move the tile under the cursor
-		Common::Rect newScreenPos = tileHolding._screenPosition;
-		newScreenPos.moveTo(mousePos);
-		newScreenPos.translate(-newScreenPos.width() / 2, -newScreenPos.height() / 2);
-
-		// Clip movement so the ring stays entirely inside the viewport
-		if (newScreenPos.left < viewport.left) {
-			newScreenPos.translate(viewport.left - newScreenPos.left, 0);
-		} else if (newScreenPos.right > viewport.right) {
-			newScreenPos.translate(viewport.right - newScreenPos.right, 0);
-		}
-
-		if (newScreenPos.top < viewport.top) {
-			newScreenPos.translate(0, viewport.top - newScreenPos.top);
-		} else if (newScreenPos.bottom > viewport.bottom) {
-			newScreenPos.translate(0, viewport.bottom - newScreenPos.bottom);
-		}
-
-		if (newScreenPos != tileHolding._screenPosition) {
-			tileHolding.moveTo(newScreenPos);
-		}
-
+		
+		tileHolding.handleInput(input);
 		bool rotated = false;
 
 		// Check if we need to rotate it
@@ -323,13 +302,11 @@ void TangramPuzzle::pickUpTile(uint id) {
 	Tile &tileToPickUp = _tiles[id];
 
 	moveToTop(id);
-
 	_pickedUpTile = id;
-
 	redrawBuffer(tileToPickUp._screenPosition);
+	tileToPickUp.pickUp();
 
 	// Make sure we don't have a frame with the correct zOrder, but wrong position
-	// This is not done when we're calling from rotate()
 	NancyInput input = g_nancy->_input->getInput();
 	input.input = 0;
 	handleInput(input);
@@ -340,6 +317,7 @@ void TangramPuzzle::putDownTile(uint id) {
 	_pickedUpTile = -1;
 	
 	drawToBuffer(tile);
+	tile.putDown();
 
 	if (tile._isHighlighted) {
 		tile.setHighlighted(false);
@@ -438,7 +416,7 @@ bool TangramPuzzle::checkBuffer(const Tile &tile) const {
 	return true;
 }
 
-TangramPuzzle::Tile::Tile() : RenderObject(1), _mask(nullptr), _id(0), _rotation(0), _isHighlighted(false) {}
+TangramPuzzle::Tile::Tile() : _mask(nullptr), _id(0), _rotation(0), _isHighlighted(false) {}
 
 TangramPuzzle::Tile::~Tile() {
 	delete _mask;
@@ -463,11 +441,6 @@ void TangramPuzzle::Tile::drawMask() {
 	}
 }
 
-void TangramPuzzle::Tile::setZ(uint z) {
-	_z = z;
-	_needsRedraw = true;
-}
-
 void TangramPuzzle::Tile::setHighlighted(bool highlighted) {
 	_isHighlighted = highlighted;
 	GraphicsManager::rotateBlit(_isHighlighted ? _highlightedSrcImage : _srcImage,
diff --git a/engines/nancy/action/puzzle/tangrampuzzle.h b/engines/nancy/action/puzzle/tangrampuzzle.h
index 218533601b2..84884add713 100644
--- a/engines/nancy/action/puzzle/tangrampuzzle.h
+++ b/engines/nancy/action/puzzle/tangrampuzzle.h
@@ -23,6 +23,7 @@
 #define NANCY_ACTION_TANGRAMPUZZLE_H
 
 #include "engines/nancy/action/actionrecord.h"
+#include "engines/nancy/misc/mousefollow.h"
 
 namespace Nancy {
 namespace Action {
@@ -46,14 +47,13 @@ protected:
 	Common::String getRecordTypeName() const override { return "TangramPuzzle"; }
 	bool isViewportRelative() const override { return true; }
 
-	class Tile : public RenderObject {
+	class Tile : public Misc::MouseFollowObject {
 		friend class TangramPuzzle;
 	public:
 		Tile();
 		virtual ~Tile();
 
 		void drawMask();
-		void setZ(uint z);
 		void setHighlighted(bool highlighted);
 
 		Graphics::ManagedSurface _srcImage;
diff --git a/engines/nancy/action/puzzle/towerpuzzle.cpp b/engines/nancy/action/puzzle/towerpuzzle.cpp
index 99b7ec735d0..cc7758b4f40 100644
--- a/engines/nancy/action/puzzle/towerpuzzle.cpp
+++ b/engines/nancy/action/puzzle/towerpuzzle.cpp
@@ -235,12 +235,15 @@ void TowerPuzzle::handleInput(NancyInput &input) {
 			_heldRing._drawSurface.create(_image, _heldRingSrcs[_heldRingID]);
 			_heldRing.setVisible(true);
 			_heldRing.setTransparent(true);
+			_heldRing.pickUp();
 
 			g_nancy->_sound->playSound(_takeSound);
 		}
 	}
 
 	if (_heldRingID != -1) {
+		_heldRing.handleInput(input);
+
 		// Holding a ring, check if it has just been dropped
 		if ((input.input & NancyInput::kLeftMouseButtonUp) || !(input.input & NancyInput::kLeftMouseButtonHeld)) {
 			// Check if dropped over a pole hotspot
@@ -277,38 +280,7 @@ void TowerPuzzle::handleInput(NancyInput &input) {
 
 			// Hide the held ring
 			_heldRing.setVisible(false);
-		} else {
-			// Still holding the ring, move under mouse
-
-			Common::Rect viewport = NancySceneState.getViewport().getScreenPosition();
-
-			// Do not move ring if mouse is outside viewport
-			if (!viewport.contains(input.mousePos)) {
-				return;
-			}
-
-			Common::Rect newScreenPos = _heldRingSrcs[_heldRingID];
-			newScreenPos.moveTo(input.mousePos);
-			newScreenPos.translate(-newScreenPos.width() / 2, -newScreenPos.height() / 2);
-
-			// Center of ring is at top left of cursor
-			const Common::Point &cursorHotspot = g_nancy->_cursorManager->getCurrentCursorHotspot();
-			newScreenPos.translate(-cursorHotspot.x, -cursorHotspot.y);
-
-			// Clip movement so the ring stays entirely inside the viewport
-			if (newScreenPos.left < viewport.left) {
-				newScreenPos.translate(viewport.left - newScreenPos.left, 0);
-			} else if (newScreenPos.right > viewport.right) {
-				newScreenPos.translate(viewport.right - newScreenPos.right, 0);
-			}
-
-			if (newScreenPos.top < viewport.top) {
-				newScreenPos.translate(0, viewport.top - newScreenPos.top);
-			} else if (newScreenPos.bottom > viewport.bottom) {
-				newScreenPos.translate(0, viewport.bottom - newScreenPos.bottom);
-			}
-
-			_heldRing.moveTo(newScreenPos);
+			_heldRing.putDown();
 		}
 	}
 }
diff --git a/engines/nancy/action/puzzle/towerpuzzle.h b/engines/nancy/action/puzzle/towerpuzzle.h
index 6f2159e7c1f..6f6a4c06e6f 100644
--- a/engines/nancy/action/puzzle/towerpuzzle.h
+++ b/engines/nancy/action/puzzle/towerpuzzle.h
@@ -23,6 +23,7 @@
 #define NANCY_ACTION_TOWERPUZZLE_H
 
 #include "engines/nancy/action/actionrecord.h"
+#include "engines/nancy/misc/mousefollow.h"
 
 namespace Nancy {
 
@@ -33,7 +34,7 @@ namespace Action {
 class TowerPuzzle : public RenderActionRecord {
 public:
 	enum SolveState { kNotSolved, kWaitForSound };
-	TowerPuzzle() : RenderActionRecord(7), _heldRing(8) {}
+	TowerPuzzle() : RenderActionRecord(7) {}
 	virtual ~TowerPuzzle() {}
 
 	void init() override;
@@ -67,7 +68,7 @@ protected:
 	Common::Rect _exitHotspot;
 
 	Graphics::ManagedSurface _image;
-	RenderObject _heldRing;
+	Misc::MouseFollowObject _heldRing;
 	int8 _heldRingID = -1;
 	int8 _heldRingPoleID = -1;
 	SolveState _solveState = kNotSolved;
diff --git a/engines/nancy/misc/mousefollow.cpp b/engines/nancy/misc/mousefollow.cpp
new file mode 100644
index 00000000000..cdcc6757478
--- /dev/null
+++ b/engines/nancy/misc/mousefollow.cpp
@@ -0,0 +1,70 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "engines/nancy/misc/mousefollow.h"
+#include "engines/nancy/enginedata.h"
+#include "engines/nancy/nancy.h"
+#include "engines/nancy/graphics.h"
+
+namespace Nancy {
+namespace Misc {
+
+MouseFollowObject::MouseFollowObject() 
+		: RenderObject(8) {
+	_viewportData = GetEngineData(VIEW);
+}
+
+void MouseFollowObject::handleInput(NancyInput &input) {
+	Common::Point mousePos = input.mousePos;
+	Common::Rect viewport = _viewportData->screenPosition;
+
+	if (!_isPickedUp || !viewport.contains(mousePos)) {
+		return;
+	}
+
+	mousePos.x -= viewport.left;
+	mousePos.y -= viewport.top;
+
+	// Move the tile under the cursor
+	Common::Rect newScreenPos = _drawSurface.getBounds();
+	newScreenPos.moveTo(mousePos);
+	newScreenPos.translate(-newScreenPos.width() / 2, -newScreenPos.height() / 2);
+
+	// Clip movement so the ring stays entirely inside the viewport
+	if (newScreenPos.left < 0) {
+		newScreenPos.translate(-newScreenPos.left, 0);
+	} else if (newScreenPos.right > viewport.width()) {
+		newScreenPos.translate(viewport.width() - newScreenPos.right, 0);
+	}
+
+	if (newScreenPos.top < 0) {
+		newScreenPos.translate(0, -newScreenPos.top);
+	} else if (newScreenPos.bottom > viewport.height()) {
+		newScreenPos.translate(0, viewport.height() - newScreenPos.bottom);
+	}
+
+	if (newScreenPos != _screenPosition) {
+		moveTo(newScreenPos);
+	}
+}
+
+} // End of namespace Misc
+} // End of namespace Nancy
diff --git a/engines/nancy/misc/mousefollow.h b/engines/nancy/misc/mousefollow.h
new file mode 100644
index 00000000000..197b1f720cb
--- /dev/null
+++ b/engines/nancy/misc/mousefollow.h
@@ -0,0 +1,65 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef NANCY_MISC_MOUSEFOLLOW_H
+#define NANCY_MISC_MOUSEFOLLOW_H
+
+#include "engines/nancy/renderobject.h"
+#include "engines/nancy/input.h"
+
+namespace Nancy {
+
+struct VIEW;
+
+namespace Misc {
+
+// Describes an object that follows the mouse's movement, making
+// sure that its center stays above the mouse hotspot. The position
+// of such an object is clipped to the Viewport. Used in puzzles:
+// - AssemblyPuzzle
+// - CubePuzzle
+// - RippedLetterPuzzle
+// - TowerPuzzle
+// - TangramPuzzle
+class MouseFollowObject : public RenderObject {
+public:
+	MouseFollowObject();
+	virtual ~MouseFollowObject() {}
+	
+	virtual void pickUp() { _isPickedUp = true; }
+	virtual void putDown() { _isPickedUp = false; }
+
+	void setZ(uint16 z) { _z = z; _needsRedraw = true; }
+	void handleInput(NancyInput &input);
+
+protected:
+	bool isViewportRelative() const override { return true; }
+
+	bool _isPickedUp = false;
+	byte _rotation = 0;
+
+	const VIEW *_viewportData = nullptr; 
+};
+
+} // End of namespace Misc
+} // End of namespace Nancy
+
+#endif // NANCY_MISC_MOUSEFOLLOW_H
diff --git a/engines/nancy/module.mk b/engines/nancy/module.mk
index e958e65daa7..906dfc9786a 100644
--- a/engines/nancy/module.mk
+++ b/engines/nancy/module.mk
@@ -55,6 +55,7 @@ MODULE_OBJS = \
   state/setupmenu.o \
   misc/hypertext.o \
   misc/lightning.o \
+  misc/mousefollow.o \
   misc/specialeffect.o \
   commontypes.o \
   console.o \


Commit: b902f61b3f0a38404915c1e1b576643101270c99
    https://github.com/scummvm/scummvm/commit/b902f61b3f0a38404915c1e1b576643101270c99
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-10-12T12:42:28+03:00

Commit Message:
AGS: Fix AVX2 blitting

The AVX2 path was previously completely broken, as all
blitting produced an alternating pattern of 4 correctly
blitted colors, followed by 4 black pixels. The intrinsics used
in the pixel drawing code have been changed so this is no
longer the case.

Changed paths:
    engines/ags/lib/allegro/surface_avx2.cpp


diff --git a/engines/ags/lib/allegro/surface_avx2.cpp b/engines/ags/lib/allegro/surface_avx2.cpp
index 360dda71861..70b0ea9d9ce 100644
--- a/engines/ags/lib/allegro/surface_avx2.cpp
+++ b/engines/ags/lib/allegro/surface_avx2.cpp
@@ -31,7 +31,8 @@
 namespace AGS3 {
 
 inline __m256i simd2BppTo4Bpp(__m256i pixels) {
-	__m256i x = _mm256_unpacklo_epi16(pixels, _mm256_setzero_si256());
+	__m128i x128 = _mm256_castsi256_si128(pixels);
+	__m256i x = _mm256_cvtepu16_epi32(x128);
 
 	// c is the extracted 5/6 bit color from the image
 	__m256i c = _mm256_srli_epi32(x, 11);
@@ -396,11 +397,11 @@ inline void drawPixelSIMD(byte *destPtr, const byte *srcP2, __m256i tint, __m256
 	if (DestBytesPerPixel == 4)
 		destCol = _mm256_loadu_si256((const __m256i *)destPtr);
 	else
-		destCol = simd2BppTo4Bpp(_mm256_and_si256(_mm256_loadu_si256((const __m256i *)destPtr), _mm256_set_epi64x(0, 0, -1, -1)));
+		destCol = simd2BppTo4Bpp(_mm256_loadu_si256((const __m256i *)destPtr));
 	if (SrcBytesPerPixel == 4)
 		srcCols = _mm256_loadu_si256((const __m256i *)(srcP2 + xDir * xCtrBpp));
 	else
-		srcCols = simd2BppTo4Bpp(_mm256_and_si256(_mm256_loadu_si256((const __m256i *)(srcP2 + xDir * xCtrBpp)), _mm256_set_epi64x(0, 0, -1, -1)));
+		srcCols = simd2BppTo4Bpp(_mm256_loadu_si256((const __m256i *)(srcP2 + xDir * xCtrBpp)));
 
 	// we do this here because we need to check if we should skip the pixel before we blend it
 	__m256i mask1 = skipTrans ? _mm256_cmpeq_epi32(_mm256_and_si256(srcCols, maskedAlphas), transColors) : _mm256_setzero_si256();




More information about the Scummvm-git-logs mailing list