diff options
author | Bastien Bouclet | 2017-07-14 19:45:23 +0200 |
---|---|---|
committer | Bastien Bouclet | 2017-07-14 19:45:23 +0200 |
commit | ef42fd3476eb5da3a832d09b35e1cf539f8c2b95 (patch) | |
tree | e61730f36a86272f134ac6fe07a35ca2a773c912 | |
parent | ce81c5345d7c8c017e70472dfe043b082cefee43 (diff) | |
download | scummvm-rg350-ef42fd3476eb5da3a832d09b35e1cf539f8c2b95.tar.gz scummvm-rg350-ef42fd3476eb5da3a832d09b35e1cf539f8c2b95.tar.bz2 scummvm-rg350-ef42fd3476eb5da3a832d09b35e1cf539f8c2b95.zip |
MOHAWK: Riven: Implement transition offsets
The games tries to match objects between the old and new card by
offsetting the transition of the new card.
Fixes #9947.
-rw-r--r-- | engines/mohawk/riven_card.cpp | 8 | ||||
-rw-r--r-- | engines/mohawk/riven_card.h | 9 | ||||
-rw-r--r-- | engines/mohawk/riven_graphics.cpp | 68 | ||||
-rw-r--r-- | engines/mohawk/riven_graphics.h | 1 |
4 files changed, 70 insertions, 16 deletions
diff --git a/engines/mohawk/riven_card.cpp b/engines/mohawk/riven_card.cpp index ed3f739cb7..f387bc450b 100644 --- a/engines/mohawk/riven_card.cpp +++ b/engines/mohawk/riven_card.cpp @@ -626,7 +626,7 @@ void RivenHotspot::loadFromStream(Common::ReadStream *stream) { _u0 = stream->readUint16BE(); _mouseCursor = stream->readUint16BE(); _index = stream->readUint16BE(); - _u1 = stream->readSint16BE(); + _transitionOffset = stream->readSint16BE(); _flags |= stream->readUint16BE(); // Read in the scripts now @@ -693,6 +693,10 @@ int16 RivenHotspot::getNameId() const { return _nameResource; } +int16 RivenHotspot::getTransitionOffset() const { + return _transitionOffset; +} + void RivenHotspot::dump() const { debug("index: %d", _index); debug("blstId: %d", _blstID); @@ -700,8 +704,8 @@ void RivenHotspot::dump() const { debug("rect: (%d, %d, %d, %d)", _rect.left, _rect.top, _rect.right, _rect.bottom); debug("flags: %d", _flags); debug("mouseCursor: %d", _mouseCursor); + debug("transitionOffset: %d", _transitionOffset); debug("u0: %d", _u0); - debug("u1: %d", _u1); debugN("\n"); for (uint i = 0; i < _scripts.size(); i++) { diff --git a/engines/mohawk/riven_card.h b/engines/mohawk/riven_card.h index 0d752ed5c0..24f2c137e7 100644 --- a/engines/mohawk/riven_card.h +++ b/engines/mohawk/riven_card.h @@ -244,6 +244,13 @@ public: /** Get the hotspot's enable list id */ uint16 getBlstId() const; + /** + * Get the offset used to control overlap during transitions + * + * -1 means no overlap. + */ + int16 getTransitionOffset() const; + /** Write all of the hotspot's data to standard output */ void dump() const; @@ -263,7 +270,7 @@ private: uint16 _u0; uint16 _mouseCursor; uint16 _index; - int16 _u1; + int16 _transitionOffset; uint16 _flags; RivenScriptList _scripts; }; diff --git a/engines/mohawk/riven_graphics.cpp b/engines/mohawk/riven_graphics.cpp index 4dfbcab0bb..6324af562a 100644 --- a/engines/mohawk/riven_graphics.cpp +++ b/engines/mohawk/riven_graphics.cpp @@ -51,7 +51,7 @@ public: bool isTimeBased() const { return _timeBased; } - virtual void drawFrame(uint32 elapsed) = 0; + virtual bool drawFrame(uint32 elapsed) = 0; protected: Common::Rect makeDirectionalInitalArea() const { @@ -101,7 +101,7 @@ public: _lastCopyArea = makeDirectionalInitalArea(); } - virtual void drawFrame(uint32 elapsed) override { + virtual bool drawFrame(uint32 elapsed) override { Common::Rect copyArea; switch (_type) { case kRivenTransitionWipeLeft: @@ -136,12 +136,14 @@ public: if (copyArea.isEmpty()) { // Nothing to draw - return; + return false; } _effectScreen->copyRectToSurface(*_mainScreen, copyArea.left, copyArea.top, copyArea); _system->copyRectToScreen(_effectScreen->getBasePtr(copyArea.left, copyArea.top), _effectScreen->pitch, copyArea.left, copyArea.top, copyArea.width(), copyArea.height()); + + return false; } private: @@ -151,14 +153,16 @@ private: class TransitionEffectPan : public TransitionEffect { public: TransitionEffectPan(OSystem *system, Graphics::Surface *mainScreen, Graphics::Surface *effectScreen, - RivenTransition type, uint duration, const Common::Rect &rect) : + RivenTransition type, uint duration, const Common::Rect &rect, int16 offset) : TransitionEffect(system, mainScreen, effectScreen, type, duration, rect) { _timeBased = true; + _offset = offset; _initialArea = makeDirectionalInitalArea(); + complete = false; } - virtual void drawFrame(uint32 elapsed) override { + virtual bool drawFrame(uint32 elapsed) override { Common::Rect newArea; switch (_type) { case kRivenTransitionPanLeft: @@ -191,7 +195,7 @@ public: if (newArea.isEmpty()) { // Nothing to draw - return; + return false; } Common::Rect oldArea = Common::Rect( @@ -203,21 +207,45 @@ public: int oldX = newArea.left != _rect.left ? _rect.left + newArea.width() : _rect.left; int oldY = newArea.top != _rect.top ? _rect.top + newArea.height() : _rect.top; - _system->copyRectToScreen(_effectScreen->getBasePtr(oldX, oldY), _effectScreen->pitch, - oldArea.left, oldArea.top, oldArea.width(), oldArea.height()); int newX = newArea.right != _rect.right ? _rect.left + oldArea.width() : _rect.left; int newY = newArea.bottom != _rect.bottom ? _rect.top + oldArea.height() : _rect.top; + + if (_offset != -1) { + if (_type == kRivenTransitionPanDown && oldArea.height() - _offset > 0) { + newY -= _offset; + } else if (_type == kRivenTransitionPanUp && newArea.height() + _offset < _rect.height()) { + newY += _offset; + } else if (_type == kRivenTransitionPanRight && oldArea.width() - _offset > 0) { + newX -= _offset; + } else if (_type == kRivenTransitionPanLeft && newArea.width() + _offset < _rect.width()) { + newX += _offset; + } else { + newX = 0; + newY = 0; + newArea = _rect; + oldArea = Common::Rect(); + } + } + + _system->copyRectToScreen(_effectScreen->getBasePtr(oldX, oldY), _effectScreen->pitch, + oldArea.left, oldArea.top, oldArea.width(), oldArea.height()); + _system->copyRectToScreen(_mainScreen->getBasePtr(newX, newY), _mainScreen->pitch, newArea.left, newArea.top, newArea.width(), newArea.height()); if (newArea == _rect) { _effectScreen->copyRectToSurface(*_mainScreen, _rect.left, _rect.top, _rect); + return true; // The transition is complete + } else { + return false; } } private: Common::Rect _initialArea; + int16 _offset; + bool complete; }; class TransitionEffectBlend : public TransitionEffect { @@ -229,13 +257,14 @@ public: _timeBased = false; } - virtual void drawFrame(uint32 elapsed) override { + virtual bool drawFrame(uint32 elapsed) override { assert(_effectScreen->format == _mainScreen->format); assert(_effectScreen->format == _system->getScreenFormat()); if (elapsed == _duration) { _effectScreen->copyRectToSurface(*_mainScreen, 0, 0, Common::Rect(_mainScreen->w, _mainScreen->h)); _system->copyRectToScreen(_effectScreen->getBasePtr(0, 0), _effectScreen->pitch, 0, 0, _effectScreen->w, _effectScreen->h); + return true; // The transition is complete } else { Graphics::Surface *screen = _system->lockScreen(); @@ -262,6 +291,7 @@ public: } _system->unlockScreen(); + return false; } } }; @@ -291,6 +321,7 @@ RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) : GraphicsManager(), _vm(vm _creditsPos = 0; _transitionMode = kRivenTransitionModeFastest; + _transitionOffset = -1; _fliesEffect = nullptr; } @@ -463,6 +494,13 @@ void RivenGraphics::setTransitionMode(RivenTransitionMode mode) { void RivenGraphics::scheduleTransition(RivenTransition id, const Common::Rect &rect) { _scheduledTransition = id; _transitionRect = rect; + + RivenHotspot *hotspot = _vm->getCard()->getCurHotspot(); + if (hotspot) { + _transitionOffset = hotspot->getTransitionOffset(); + } else { + _transitionOffset = -1; + } } void RivenGraphics::runScheduledTransition() { @@ -488,7 +526,7 @@ void RivenGraphics::runScheduledTransition() { case kRivenTransitionPanUp: case kRivenTransitionPanDown: { effect = new TransitionEffectPan(_vm->_system, _mainScreen, _effectScreen, - _scheduledTransition, _transitionDuration, _transitionRect); + _scheduledTransition, _transitionDuration, _transitionRect, _transitionOffset); break; } case kRivenTransitionBlend: @@ -503,14 +541,17 @@ void RivenGraphics::runScheduledTransition() { if (effect->isTimeBased()) { uint32 startTime = _vm->_system->getMillis(); uint32 timeElapsed = 0; - while (timeElapsed < _transitionDuration && !_vm->shouldQuit()) { - effect->drawFrame(timeElapsed); + bool transitionComplete = false; + while (timeElapsed < _transitionDuration && !transitionComplete && !_vm->shouldQuit()) { + transitionComplete = effect->drawFrame(timeElapsed); _vm->doFrame(); timeElapsed = _vm->_system->getMillis() - startTime; } - effect->drawFrame(_transitionDuration); + if (!transitionComplete) { + effect->drawFrame(_transitionDuration); + } } else { for (uint frame = 1; frame <= _transitionFrames && !_vm->shouldQuit(); frame++) { effect->drawFrame(frame); @@ -521,6 +562,7 @@ void RivenGraphics::runScheduledTransition() { delete effect; _scheduledTransition = kRivenTransitionNone; // Clear scheduled transition + _transitionOffset = -1; } void RivenGraphics::clearMainScreen() { diff --git a/engines/mohawk/riven_graphics.h b/engines/mohawk/riven_graphics.h index bdc1a2a0c0..62c48d1a9e 100644 --- a/engines/mohawk/riven_graphics.h +++ b/engines/mohawk/riven_graphics.h @@ -131,6 +131,7 @@ private: RivenTransitionMode _transitionMode; uint _transitionFrames; uint _transitionDuration; + int16 _transitionOffset; // Screen Related Graphics::Surface *_mainScreen; |