From 039cf08f4fdbbf05798cbf22cec38f7ce76fbda9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2021 03:55:50 +0300 Subject: [PATCH] TRECISION: Fix drawing frames from disabled animations - bugs #12624, #12626 Fixes the chain shown incorrectly when entering the platforms and the shopkeeper's wife appearing frozen after she's left the storeroom --- engines/trecision/video.cpp | 42 +++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/engines/trecision/video.cpp b/engines/trecision/video.cpp index 3b74377486e..1cbaa88c0ee 100644 --- a/engines/trecision/video.cpp +++ b/engines/trecision/video.cpp @@ -436,14 +436,16 @@ void AnimManager::refreshSmkAnim(uint16 animation) { handleEndOfVideo(animation, kSmackerAction); } - for (int32 a = 0; a < MAXCHILD; a++) { - if (!(_animTab[animation]._flag & (SMKANIM_OFF1 << a)) && (_animTab[animation]._lim[a].bottom != 0)) { - _vm->_graphicsMgr->addDirtyRect(_animTab[animation]._lim[a], true); + for (int32 i = 0; i < MAXCHILD; i++) { + if (!(_animTab[animation]._flag & (SMKANIM_OFF1 << i)) && _animTab[animation]._lim[i].bottom != 0) { + _vm->_graphicsMgr->addDirtyRect(_animTab[animation]._lim[i], true); } } } void AnimManager::handleEndOfVideo(int animation, int slot) { + const bool isLoopingOrBackground = (_animTab[animation]._flag & SMKANIM_LOOP) || (_animTab[animation]._flag & SMKANIM_BKG); + if (_smkAnims[slot] == nullptr) { smkStop(slot); return; @@ -451,7 +453,7 @@ void AnimManager::handleEndOfVideo(int animation, int slot) { if (!_smkAnims[slot]->endOfFrames()) return; - if (!(_animTab[animation]._flag & SMKANIM_LOOP) && !(_animTab[animation]._flag & SMKANIM_BKG)) { + if (!isLoopingOrBackground) { smkStop(slot); _vm->_flagPaintCharacter = true; } else { @@ -461,6 +463,10 @@ void AnimManager::handleEndOfVideo(int animation, int slot) { } } +static bool rectsIntersect(Common::Rect r1, Common::Rect r2) { + return (r1.left <= r2.right) && (r1.right >= r2.left) && (r1.top <= r2.bottom) && (r1.bottom >= r2.top); +} + void AnimManager::drawSmkBackgroundFrame(int animation) { NightlongSmackerDecoder *smkDecoder = _smkAnims[kSmackerBackground]; if (smkDecoder == nullptr) @@ -473,20 +479,30 @@ void AnimManager::drawSmkBackgroundFrame(int animation) { const byte *palette = smkDecoder->getPalette(); if (smkDecoder->getCurFrame() == 0 && !_bgAnimRestarted) { - _vm->_graphicsMgr->blitToScreenBuffer(frame, 0, TOP, palette, true); + bool drawFrame = true; + + for (int32 i = 0; i < MAXCHILD; i++) { + if ((_animTab[animation]._flag & (SMKANIM_OFF1 << i))) { + drawFrame = false; + break; + } + } + + if (drawFrame) + _vm->_graphicsMgr->blitToScreenBuffer(frame, 0, TOP, palette, true); } else { while (lastRect) { - bool intersects = false; - for (int32 a = 0; a < MAXCHILD; a++) { - if (_animTab[animation]._flag & (SMKANIM_OFF1 << a)) { - if (_animTab[animation]._lim[a].intersects(*lastRect)) { - intersects = true; - break; - } + bool drawDirtyRect = true; + + for (int32 i = 0; i < MAXCHILD; i++) { + const bool intersect = rectsIntersect(_animTab[animation]._lim[i], *lastRect); + if ((_animTab[animation]._flag & (SMKANIM_OFF1 << i)) && intersect) { + drawDirtyRect = false; + break; } } - if (smkDecoder->getCurFrame() > 0 && !intersects) { + if (smkDecoder->getCurFrame() > 0 && drawDirtyRect) { Graphics::Surface anim = frame->getSubArea(*lastRect); _vm->_graphicsMgr->blitToScreenBuffer(&anim, lastRect->left, lastRect->top + TOP, palette, true); }