diff options
Diffstat (limited to 'engines/gob/aniobject.cpp')
-rw-r--r-- | engines/gob/aniobject.cpp | 156 |
1 files changed, 114 insertions, 42 deletions
diff --git a/engines/gob/aniobject.cpp b/engines/gob/aniobject.cpp index 0ca850d1fb..7e3668a0ce 100644 --- a/engines/gob/aniobject.cpp +++ b/engines/gob/aniobject.cpp @@ -22,20 +22,26 @@ #include "gob/surface.h" #include "gob/anifile.h" +#include "gob/cmpfile.h" #include "gob/aniobject.h" namespace Gob { -ANIObject::ANIObject(const ANIFile &ani) : _ani(&ani), - _visible(false), _paused(false), _mode(kModeContinuous), - _x(0), _y(0), _background(0), _drawn(false) { +ANIObject::ANIObject(const ANIFile &ani) : _ani(&ani), _cmp(0), + _visible(false), _paused(false), _mode(kModeContinuous), _x(0), _y(0) { + + setAnimation(0); + setPosition(); +} + +ANIObject::ANIObject(const CMPFile &cmp) : _ani(0), _cmp(&cmp), + _visible(false), _paused(false), _mode(kModeContinuous), _x(0), _y(0) { setAnimation(0); setPosition(); } ANIObject::~ANIObject() { - delete _background; } void ANIObject::setVisible(bool visible) { @@ -67,7 +73,15 @@ void ANIObject::rewind() { _frame = 0; } +void ANIObject::setFrame(uint16 frame) { + _frame = frame % _ani->getAnimationInfo(_animation).frameCount; +} + void ANIObject::setPosition() { + // CMP "animations" have no default position + if (_cmp) + return; + if (_animation >= _ani->getAnimationCount()) return; @@ -87,7 +101,13 @@ void ANIObject::getPosition(int16 &x, int16 &y) const { y = _y; } -void ANIObject::getFramePosition(int16 &x, int16 &y) const { +void ANIObject::getFramePosition(int16 &x, int16 &y, uint16 n) const { + // CMP "animations" have no specific frame positions + if (_cmp) { + getPosition(x, y); + return; + } + if (_animation >= _ani->getAnimationCount()) return; @@ -95,11 +115,31 @@ void ANIObject::getFramePosition(int16 &x, int16 &y) const { if (_frame >= animation.frameCount) return; - x = _x + animation.frameAreas[_frame].left; - y = _y + animation.frameAreas[_frame].top; + // If we're paused, we don't advance any frames + if (_paused) + n = 0; + + // Number of cycles run through after n frames + uint16 cycles = (_frame + n) / animation.frameCount; + // Frame position after n frames + uint16 frame = (_frame + n) % animation.frameCount; + + // Only doing one cycle? + if (_mode == kModeOnce) + cycles = MAX<uint16>(cycles, 1); + + x = _x + animation.frameAreas[frame].left + cycles * animation.deltaX; + y = _y + animation.frameAreas[frame].top + cycles * animation.deltaY; } -void ANIObject::getFrameSize(int16 &width, int16 &height) const { +void ANIObject::getFrameSize(int16 &width, int16 &height, uint16 n) const { + if (_cmp) { + width = _cmp->getWidth (_animation); + height = _cmp->getHeight(_animation); + + return; + } + if (_animation >= _ani->getAnimationCount()) return; @@ -107,8 +147,15 @@ void ANIObject::getFrameSize(int16 &width, int16 &height) const { if (_frame >= animation.frameCount) return; - width = animation.frameAreas[_frame].right - animation.frameAreas[_frame].left + 1; - height = animation.frameAreas[_frame].bottom - animation.frameAreas[_frame].top + 1; + // If we're paused, we don't advance any frames + if (_paused) + n = 0; + + // Frame position after n frames + uint16 frame = (_frame + n) % animation.frameCount; + + width = animation.frameAreas[frame].right - animation.frameAreas[frame].left + 1; + height = animation.frameAreas[frame].bottom - animation.frameAreas[frame].top + 1; } bool ANIObject::isIn(int16 x, int16 y) const { @@ -141,67 +188,88 @@ bool ANIObject::isIn(const ANIObject &obj) const { obj.isIn(frameX + frameWidth - 1, frameY + frameHeight - 1); } -void ANIObject::draw(Surface &dest, int16 &left, int16 &top, +bool ANIObject::draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) { if (!_visible) - return; + return false; + + if (_cmp) + return drawCMP(dest, left, top, right, bottom); + else if (_ani) + return drawANI(dest, left, top, right, bottom); + + return false; +} - if (!_background) { +bool ANIObject::drawCMP(Surface &dest, int16 &left, int16 &top, + int16 &right, int16 &bottom) { + + if (!hasBuffer()) { + uint16 width, height; + + _cmp->getMaxSize(width, height); + + resizeBuffer(width, height); + } + + left = _x; + top = _y; + right = _x + _cmp->getWidth (_animation) - 1; + bottom = _y + _cmp->getHeight(_animation) - 1; + + if (!saveScreen(dest, left, top, right, bottom)) + return false; + + _cmp->draw(dest, _animation, _x, _y, 0); + + return true; +} + +bool ANIObject::drawANI(Surface &dest, int16 &left, int16 &top, + int16 &right, int16 &bottom) { + + if (!hasBuffer()) { uint16 width, height; _ani->getMaxSize(width, height); - _background = new Surface(width, height, dest.getBPP()); + resizeBuffer(width, height); } const ANIFile::Animation &animation = _ani->getAnimationInfo(_animation); if (_frame >= animation.frameCount) - return; + return false; const ANIFile::FrameArea &area = animation.frameAreas[_frame]; - _backgroundLeft = CLIP<int16>(area.left + _x, 0, dest.getWidth () - 1); - _backgroundTop = CLIP<int16>(area.top + _y, 0, dest.getHeight() - 1); - _backgroundRight = CLIP<int16>(area.right + _x, 0, dest.getWidth () - 1); - _backgroundBottom = CLIP<int16>(area.bottom + _y, 0, dest.getHeight() - 1); + left = _x + area.left; + top = _y + area.top; + right = _x + area.right; + bottom = _y + area.bottom; - _background->blit(dest, _backgroundLeft , _backgroundTop, - _backgroundRight, _backgroundBottom, 0, 0); + if (!saveScreen(dest, left, top, right, bottom)) + return false; _ani->draw(dest, _animation, _frame, _x, _y); - _drawn = true; - - left = _backgroundLeft; - top = _backgroundTop; - right = _backgroundRight; - bottom = _backgroundBottom; + return true; } -void ANIObject::clear(Surface &dest, int16 &left, int16 &top, +bool ANIObject::clear(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) { - if (!_drawn) - return; - - const int16 bgRight = _backgroundRight - _backgroundLeft; - const int16 bgBottom = _backgroundBottom - _backgroundTop; - - dest.blit(*_background, 0, 0, bgRight, bgBottom, _backgroundLeft, _backgroundTop); - - _drawn = false; - - left = _backgroundLeft; - top = _backgroundTop; - right = _backgroundRight; - bottom = _backgroundBottom; + return restoreScreen(dest, left, top, right, bottom); } void ANIObject::advance() { if (_paused) return; + // CMP "animations" have only one frame + if (_cmp) + return; + if (_animation >= _ani->getAnimationCount()) return; @@ -229,6 +297,10 @@ uint16 ANIObject::getFrame() const { } bool ANIObject::lastFrame() const { + // CMP "animations" have only one frame + if (_cmp) + return true; + if (_animation >= _ani->getAnimationCount()) return true; |