aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorBastien Bouclet2017-07-14 19:45:23 +0200
committerBastien Bouclet2017-07-14 19:45:23 +0200
commitef42fd3476eb5da3a832d09b35e1cf539f8c2b95 (patch)
treee61730f36a86272f134ac6fe07a35ca2a773c912 /engines
parentce81c5345d7c8c017e70472dfe043b082cefee43 (diff)
downloadscummvm-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.
Diffstat (limited to 'engines')
-rw-r--r--engines/mohawk/riven_card.cpp8
-rw-r--r--engines/mohawk/riven_card.h9
-rw-r--r--engines/mohawk/riven_graphics.cpp68
-rw-r--r--engines/mohawk/riven_graphics.h1
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;