From caa3b6707e4cd6a20f2d20d57f9748b8ece89852 Mon Sep 17 00:00:00 2001 From: Robert Špalek Date: Sun, 27 Sep 2009 20:49:59 +0000 Subject: Improved the interface of Sprite and Animation concerning relative coordinates and scaling. It is no longer needed to modify the underlying animations when drawing them on the screen or testing pixels in them. Read access is enough, because the displacement of the object is passed as a parameter. Added some more const's where they logically belong. svn-id: r44419 --- engines/draci/animation.cpp | 101 ++++++++------------------------------------ engines/draci/animation.h | 9 ++-- engines/draci/script.cpp | 4 +- engines/draci/sprite.cpp | 48 +++++++++++---------- engines/draci/sprite.h | 28 +++++++----- 5 files changed, 64 insertions(+), 126 deletions(-) (limited to 'engines') diff --git a/engines/draci/animation.cpp b/engines/draci/animation.cpp index e3f87feb8b..cae4897329 100644 --- a/engines/draci/animation.cpp +++ b/engines/draci/animation.cpp @@ -33,10 +33,7 @@ Animation::Animation(DraciEngine *vm, int index) : _vm(vm) { _id = kUnused; _index = index; _z = 0; - _relX = 0; - _relY = 0; - _scaleX = 1.0; - _scaleY = 1.0; + _displacement = kNoDisplacement; _playing = false; _looping = false; _paused = false; @@ -59,8 +56,8 @@ void Animation::setRelative(int relx, int rely) { if (_frames.size() > 0) markDirtyRect(_vm->_screen->getSurface()); - _relX = relx; - _relY = rely; + _displacement.relX = relx; + _displacement.relY = rely; } void Animation::setLooping(bool looping) { @@ -72,14 +69,7 @@ void Animation::setLooping(bool looping) { void Animation::markDirtyRect(Surface *surface) const { // Fetch the current frame's rectangle Drawable *frame = _frames[_currentFrame]; - Common::Rect frameRect = frame->getRect(); - - // Translate rectangle to compensate for relative coordinates - frameRect.translate(_relX, _relY); - - // Take animation scaling into account - frameRect.setWidth((int) (frameRect.width() * _scaleX)); - frameRect.setHeight((int) (frameRect.height() * _scaleY)); + Common::Rect frameRect = frame->getRect(_displacement); // Mark the rectangle dirty on the surface surface->markDirtyRect(frameRect); @@ -135,42 +125,13 @@ void Animation::drawFrame(Surface *surface) { if (_frames.size() == 0 || !_playing) return; - Drawable *frame = _frames[_currentFrame]; + const Drawable *frame = _frames[_currentFrame]; if (_id == kOverlayImage) { frame->draw(surface, false); } else { - - int x = frame->getX(); - int y = frame->getY(); - - // Take account relative coordinates - int newX = x + _relX; - int newY = y + _relY; - - // Translate the frame to those relative coordinates - frame->setX(newX); - frame->setY(newY); - - // Save scaled width and height - int scaledWidth = frame->getScaledWidth(); - int scaledHeight = frame->getScaledHeight(); - - // Take into account per-animation scaling and adjust the current frames dimensions - if (_scaleX != 1.0 || _scaleY != 1.0) - frame->setScaled( - (int) (scaledWidth * _scaleX), - (int) (scaledHeight * _scaleY)); - // Draw frame - frame->drawScaled(surface, false); - - // Revert back to old coordinates - frame->setX(x); - frame->setY(y); - - // Revert back to old dimensions - frame->setScaled(scaledWidth, scaledHeight); + frame->drawReScaled(surface, false, _displacement); } } @@ -191,11 +152,11 @@ uint Animation::getZ() const { } int Animation::getRelativeX() const { - return _relX; + return _displacement.relX; } int Animation::getRelativeY() const { - return _relY; + return _displacement.relY; } bool Animation::isPlaying() const { @@ -223,16 +184,16 @@ void Animation::setScaleFactors(double scaleX, double scaleY) { markDirtyRect(_vm->_screen->getSurface()); - _scaleX = scaleX; - _scaleY = scaleY; + _displacement.extraScaleX = scaleX; + _displacement.extraScaleY = scaleY; } double Animation::getScaleX() const { - return _scaleX; + return _displacement.extraScaleX; } double Animation::getScaleY() const { - return _scaleY; + return _displacement.extraScaleY; } void Animation::addFrame(Drawable *frame) { @@ -574,9 +535,9 @@ void AnimationManager::deleteAfterIndex(int index) { _lastIndex = index; } -int AnimationManager::getTopAnimationID(int x, int y) { +int AnimationManager::getTopAnimationID(int x, int y) const { - Common::List::iterator it; + Common::List::const_iterator it; // The default return value if no animations were found on these coordinates (not even overlays) // i.e. the black background shows through so treat it as an overlay @@ -594,53 +555,25 @@ int AnimationManager::getTopAnimationID(int x, int y) { continue; } - Drawable *frame = anim->getFrame(); + const Drawable *frame = anim->getFrame(); if (frame == NULL) { continue; } - int oldX = frame->getX(); - int oldY = frame->getY(); - - // Take account relative coordinates - int newX = oldX + anim->getRelativeX(); - int newY = oldY + anim->getRelativeY(); - - // Translate the frame to those relative coordinates - frame->setX(newX); - frame->setY(newY); - - // Save scaled width and height - int scaledWidth = frame->getScaledWidth(); - int scaledHeight = frame->getScaledHeight(); - - // Take into account per-animation scaling and adjust the current frames dimensions - if (anim->getScaleX() != 1.0 || anim->getScaleY() != 1.0) - frame->setScaled( - (int) (scaledWidth * anim->getScaleX()), - (int) (scaledHeight * anim->getScaleY())); - - if (frame->getRect().contains(x, y)) { + if (frame->getRect(anim->getDisplacement()).contains(x, y)) { if (frame->getType() == kDrawableText) { retval = anim->getID(); } else if (frame->getType() == kDrawableSprite && - reinterpret_cast(frame)->getPixel(x, y) != transparent) { + reinterpret_cast(frame)->getPixel(x, y, anim->getDisplacement()) != transparent) { retval = anim->getID(); } } - // Revert back to old coordinates - frame->setX(oldX); - frame->setY(oldY); - - // Revert back to old dimensions - frame->setScaled(scaledWidth, scaledHeight); - // Found an animation if (retval != kOverlayImage) break; diff --git a/engines/draci/animation.h b/engines/draci/animation.h index 2358775d8d..24ee5368c1 100644 --- a/engines/draci/animation.h +++ b/engines/draci/animation.h @@ -92,6 +92,7 @@ public: void setRelative(int relx, int rely); int getRelativeX() const; int getRelativeY() const; + const Displacement &getDisplacement() const { return _displacement; } int getIndex() const; void setIndex(int index); @@ -128,11 +129,7 @@ private: uint _currentFrame; uint _z; - int _relX; - int _relY; - - double _scaleX; - double _scaleY; + Displacement _displacement; uint _tick; bool _playing; @@ -176,7 +173,7 @@ public: int getLastIndex() const; void deleteAfterIndex(int index); - int getTopAnimationID(int x, int y); + int getTopAnimationID(int x, int y) const; private: void sortAnimations(); diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp index 3622f2d028..8a256f4fcc 100644 --- a/engines/draci/script.cpp +++ b/engines/draci/script.cpp @@ -676,7 +676,7 @@ void Script::talk(Common::Queue ¶ms) { const Person *person = _vm->_game->getPerson(personID); // Set the string and text colour - surface->markDirtyRect(speechFrame->getRect(true)); + surface->markDirtyRect(speechFrame->getRect()); speechFrame->setText(Common::String((const char *)f->_data+1, f->_length-1)); speechFrame->setColour(person->_fontColour); @@ -712,7 +712,7 @@ void Script::talk(Common::Queue ¶ms) { _vm->_game->loop(); // Delete the text - _vm->_screen->getSurface()->markDirtyRect(speechFrame->getRect(true)); + _vm->_screen->getSurface()->markDirtyRect(speechFrame->getRect()); speechFrame->setText(""); // Revert to "normal" loop status diff --git a/engines/draci/sprite.cpp b/engines/draci/sprite.cpp index 2028f7ab4b..1e3e749e1e 100644 --- a/engines/draci/sprite.cpp +++ b/engines/draci/sprite.cpp @@ -33,6 +33,8 @@ namespace Draci { +const Displacement kNoDisplacement = { 0, 0, 1.0, 1.0 }; + /** * @brief Transforms an image from column-wise to row-wise * @param img pointer to the buffer containing the image data @@ -129,19 +131,19 @@ void Sprite::setMirrorOff() { } -int Sprite::getPixel(int x, int y) const { +int Sprite::getPixel(int x, int y, const Displacement &displacement) const { - Common::Rect rect = getRect(); + Common::Rect rect = getRect(displacement); int dy = y - rect.top; int dx = x - rect.left; // Calculate scaling factors - double scaleX = double(_scaledWidth) / _width; - double scaleY = double(_scaledHeight) / _height; + double scaleX = double(rect.width()) / _width; + double scaleY = double(rect.height()) / _height; - int sy = scummvm_lround(dy * scaleY); - int sx = scummvm_lround(dx * scaleX); + int sy = scummvm_lround(dy / scaleY); + int sx = scummvm_lround(dx / scaleX); if (_mirror) return _data[sy * _width + (_width - sx)]; @@ -150,10 +152,15 @@ int Sprite::getPixel(int x, int y) const { } -void Sprite::drawScaled(Surface *surface, bool markDirty) const { +void Sprite::drawReScaled(Surface *surface, bool markDirty, const Displacement &displacement) const { Common::Rect sourceRect(0, 0, _width, _height); - Common::Rect destRect(_x, _y, _x + _scaledWidth, _y + _scaledHeight); + Common::Rect destRect(getRect(displacement)); + + // Calculate scaling factors + double scaleX = double(destRect.width()) / _width; + double scaleY = double(destRect.height()) / _height; + Common::Rect surfaceRect(0, 0, surface->w, surface->h); Common::Rect clippedDestRect(destRect); @@ -184,10 +191,6 @@ void Sprite::drawScaled(Surface *surface, bool markDirty) const { int *rowIndices = new int[rows]; int *columnIndices = new int[columns]; - // Calculate scaling factors - double scaleX = double(_scaledWidth) / _width; - double scaleY = double(_scaledHeight) / _height; - // Precalculate pixel indexes for (int i = 0; i < rows; ++i) { rowIndices[i] = scummvm_lround(i / scaleY); @@ -241,10 +244,10 @@ void Sprite::drawScaled(Surface *surface, bool markDirty) const { * Draws the sprite to a Draci::Surface and marks its rectangle on the surface as dirty. * It is safe to call it for sprites that would overflow the surface. */ -void Sprite::draw(Surface *surface, bool markDirty) const { +void Sprite::draw(Surface *surface, bool markDirty, int relX, int relY) const { Common::Rect sourceRect(0, 0, _width, _height); - Common::Rect destRect(_x, _y, _x + _width, _y + _height); + Common::Rect destRect(_x + relX, _y + relY, _x + relX + _width, _y + relY + _height); Common::Rect surfaceRect(0, 0, surface->w, surface->h); Common::Rect clippedDestRect(destRect); @@ -295,11 +298,10 @@ void Sprite::draw(Surface *surface, bool markDirty) const { } -Common::Rect Sprite::getRect(bool scaled) const { - if (scaled) - return Common::Rect(_x, _y, _x + _scaledWidth, _y + _scaledHeight); - else - return Common::Rect(_x, _y, _x + _width, _y + _height); +Common::Rect Sprite::getRect(const Displacement &displacement) const { + return Common::Rect(_x + displacement.relX, _y + displacement.relY, + _x + displacement.relX + (int) (_scaledWidth * displacement.extraScaleX), + _y + displacement.relY + (int) (_scaledHeight * displacement.extraScaleY)); } Text::Text(const Common::String &str, const Font *font, byte fontColour, @@ -356,13 +358,13 @@ uint Text::getLength() const { return _length; } -void Text::draw(Surface *surface, bool markDirty) const { - _font->drawString(surface, _text, _x, _y, _colour, _spacing); +void Text::draw(Surface *surface, bool markDirty, int relX, int relY) const { + _font->drawString(surface, _text, _x + relX, _y + relY, _colour, _spacing); } // TODO: Handle scaled parameter properly by implementing Text scaling -Common::Rect Text::getRect(bool scaled) const { - return Common::Rect(_x, _y, _x + _width, _y + _height); +Common::Rect Text::getRect(const Displacement &displacement) const { + return Common::Rect(_x + displacement.relX, _y + displacement.relY, _x + displacement.relX + _width, _y + displacement.relY + _height); } void Text::setFont(const Font *font) { diff --git a/engines/draci/sprite.h b/engines/draci/sprite.h index 0488043c7e..ce2d516437 100644 --- a/engines/draci/sprite.h +++ b/engines/draci/sprite.h @@ -33,11 +33,17 @@ namespace Draci { enum DrawableType { kDrawableText, kDrawableSprite }; +struct Displacement { + int relX, relY; + double extraScaleX, extraScaleY; +}; +extern const Displacement kNoDisplacement; + class Drawable { public: - virtual void draw(Surface *surface, bool markDirty = true) const = 0; - virtual void drawScaled(Surface *surface, bool markDirty = true) const = 0; + virtual void draw(Surface *surface, bool markDirty, int relX=0, int relY=0) const = 0; + virtual void drawReScaled(Surface *surface, bool markDirty, const Displacement &displacement = kNoDisplacement) const = 0; virtual ~Drawable() {}; @@ -61,7 +67,7 @@ public: void setDelay(int delay) { _delay = delay; } int getDelay() const { return _delay; } - virtual Common::Rect getRect(bool scaled = true) const = 0; + virtual Common::Rect getRect(const Displacement &displacement = kNoDisplacement) const = 0; virtual DrawableType getType() const = 0; @@ -100,16 +106,16 @@ public: ~Sprite(); - void draw(Surface *surface, bool markDirty = true) const; - void drawScaled(Surface *surface, bool markDirty = true) const; + void draw(Surface *surface, bool markDirty, int relX=0, int relY=0) const; + void drawReScaled(Surface *surface, bool markDirty, const Displacement &displacement = kNoDisplacement) const; void setMirrorOn(); void setMirrorOff(); - Common::Rect getRect(bool scaled = true) const; + Common::Rect getRect(const Displacement &displacement = kNoDisplacement) const; const byte *getBuffer() const { return _data; } - int getPixel(int x, int y) const; + int getPixel(int x, int y, const Displacement &displacement = kNoDisplacement) const; DrawableType getType() const { return kDrawableSprite; } @@ -132,13 +138,13 @@ public: uint getLength() const; - void draw(Surface *surface, bool markDirty = true) const; + void draw(Surface *surface, bool markDirty, int relX=0, int relY=0) const; - // TODO: drawScaled just calls draw so Text can be accessed through a Drawable pointer. + // TODO: drawReScaled just calls draw so Text can be accessed through a Drawable pointer. // Handle scaling text sometimes (not essential). - void drawScaled(Surface *surface, bool markDirty = true) const { draw(surface, markDirty); } - Common::Rect getRect(bool) const; + void drawReScaled(Surface *surface, bool markDirty, const Displacement &displacement = kNoDisplacement) const { draw(surface, markDirty, displacement.relX, displacement.relY); } + Common::Rect getRect(const Displacement &displacement = kNoDisplacement) const; DrawableType getType() const { return kDrawableText; } -- cgit v1.2.3