[Scummvm-git-logs] scummvm master -> c7714d3882343ef4322a93b8e5c7b8a05fd126d2
npjg
nathanael.gentrydb8 at gmail.com
Wed Jun 17 13:09:08 UTC 2020
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
75210d8186 DIRECTOR: Render sprites from channel structs
c7714d3882 DIRECTOR: Work around flashing reverse sprites
Commit: 75210d8186063dd11e90001de8fc1047ee3cc8e9
https://github.com/scummvm/scummvm/commit/75210d8186063dd11e90001de8fc1047ee3cc8e9
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-06-17T09:07:35-04:00
Commit Message:
DIRECTOR: Render sprites from channel structs
Among other rendering issues, this fixes the annoying jittery sprites issue when
a sprite is simultaneously animated and moveable.
Changed paths:
engines/director/events.cpp
engines/director/frame.cpp
engines/director/ink.cpp
engines/director/lingo/lingo-builtins.cpp
engines/director/lingo/lingo-code.cpp
engines/director/lingo/lingo-the.cpp
engines/director/score-loading.cpp
engines/director/score.cpp
engines/director/score.h
engines/director/sprite.cpp
engines/director/sprite.h
diff --git a/engines/director/events.cpp b/engines/director/events.cpp
index 128c86e66c..5f4db0bf61 100644
--- a/engines/director/events.cpp
+++ b/engines/director/events.cpp
@@ -82,11 +82,11 @@ void DirectorEngine::processEvents(bool bufferLingoEvents) {
sc->_lastRollTime = sc->_lastEventTime;
if (_draggingSprite) {
- Sprite *draggedSprite = sc->_sprites[_draggingSpriteId];
+ Sprite *draggedSprite = sc->getSpriteById(_draggingSpriteId);
if (draggedSprite->_moveable) {
pos = g_system->getEventManager()->getMousePos();
- Common::Point delta = pos - _draggingSpritePos;
- draggedSprite->translate(delta);
+
+ sc->_channels[_draggingSpriteId]->addDelta(pos - _draggingSpritePos);
_draggingSpritePos = pos;
} else {
releaseDraggedSprite();
@@ -101,7 +101,7 @@ void DirectorEngine::processEvents(bool bufferLingoEvents) {
// But we still want to know if the mouse is down for press effects.
spriteId = sc->getSpriteIDFromPos(pos);
sc->_currentMouseDownSpriteId = spriteId;
- if (sc->_sprites[spriteId]->_scriptId)
+ if (sc->getSpriteById(spriteId)->_scriptId)
sc->_currentClickOnSpriteId = spriteId;
sc->_lastEventTime = g_director->getMacTicks();
@@ -110,7 +110,7 @@ void DirectorEngine::processEvents(bool bufferLingoEvents) {
debugC(3, kDebugEvents, "event: Button Down @(%d, %d), sprite id: %d", pos.x, pos.y, spriteId);
_lingo->registerEvent(kEventMouseDown);
- if (sc->_sprites[spriteId]->_moveable)
+ if (sc->getSpriteById(spriteId)->_moveable)
g_director->setDraggedSprite(spriteId);
break;
@@ -120,7 +120,7 @@ void DirectorEngine::processEvents(bool bufferLingoEvents) {
spriteId = sc->getSpriteIDFromPos(pos);
- if (!sc->_sprites[sc->_currentMouseDownSpriteId]->_currentBbox.contains(pos))
+ if (!sc->getChannelById(sc->_currentMouseDownSpriteId)->getBbox().contains(pos))
sc->_currentMouseDownSpriteId = 0;
if (!(g_director->_wm->_mode & Graphics::kWMModeButtonDialogStyle))
@@ -131,7 +131,7 @@ void DirectorEngine::processEvents(bool bufferLingoEvents) {
releaseDraggedSprite();
{
- Cast *cast = g_director->getCastMember(sc->_sprites[spriteId]->_castId);
+ Cast *cast = g_director->getCastMember(sc->getSpriteById(spriteId)->_castId);
if (cast && cast->_type == kCastButton)
cast->_hilite = !cast->_hilite;
}
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index fd66254553..e33cf98602 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -288,8 +288,6 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) {
sprite._startPoint.y = (int16)stream->readUint16();
sprite._startPoint.x = (int16)stream->readUint16();
- sprite._currentPoint = sprite._startPoint;
-
sprite._height = (int16)stream->readUint16();
sprite._width = (int16)stream->readUint16();
diff --git a/engines/director/ink.cpp b/engines/director/ink.cpp
index 381944ec38..d7313b2c52 100644
--- a/engines/director/ink.cpp
+++ b/engines/director/ink.cpp
@@ -65,9 +65,9 @@ void Score::inkBasedBlit(Graphics::ManagedSurface *maskSurface, const Graphics::
}
void Score::drawBackgndTransSprite(const Graphics::Surface &sprite, Common::Rect &drawRect, int spriteId) {
- byte skipColor = _sprites[spriteId]->_backColor;
- if (_sprites[spriteId]->_castType == kCastText && _sprites[spriteId]->_cast) {
- skipColor = ((TextCast *)_sprites[spriteId]->_cast)->getBackColor();
+ byte skipColor = _channels[spriteId]->_sprite->_backColor;
+ if (_channels[spriteId]->_sprite->_castType == kCastText && _channels[spriteId]->_sprite->_cast) {
+ skipColor = ((TextCast *)_channels[spriteId]->_sprite->_cast)->getBackColor();
}
Common::Rect srcRect(sprite.w, sprite.h);
@@ -123,7 +123,7 @@ void Score::drawReverseSprite(const Graphics::Surface &sprite, Common::Rect &dra
byte srcColor = *src;
for (int j = 0; j < drawRect.width(); j++) {
- if (!_sprites[spriteId]->_cast || _sprites[spriteId]->_cast->_type == kCastShape)
+ if (!_channels[spriteId]->_sprite->_cast || _channels[spriteId]->_sprite->_cast->_type == kCastShape)
srcColor = 0x0;
else
srcColor = *src;
@@ -132,7 +132,7 @@ void Score::drawReverseSprite(const Graphics::Surface &sprite, Common::Rect &dra
// TODO: This entire reverse colour attempt needs a lot more testing on
// a lot more colour depths.
if (srcColor != skipColor) {
- if (!_sprites[targetSprite]->_cast || _sprites[targetSprite]->_cast->_type != kCastBitmap) {
+ if (!_channels[targetSprite]->_sprite->_cast || _channels[targetSprite]->_sprite->_cast->_type != kCastBitmap) {
if (*dst == 0 || *dst == 255) {
*dst = _vm->transformColor(*dst);
} else if (srcColor == 255 || srcColor == 0) {
@@ -142,7 +142,7 @@ void Score::drawReverseSprite(const Graphics::Surface &sprite, Common::Rect &dra
}
} else {
if (*dst == 0 && _vm->getVersion() == 3 &&
- ((BitmapCast*)_sprites[spriteId]->_cast)->_bitsPerPixel > 1) {
+ ((BitmapCast*)_channels[spriteId]->_sprite->_cast)->_bitsPerPixel > 1) {
*dst = _vm->transformColor(*src - 40);
} else {
*dst ^= _vm->transformColor(srcColor);
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 9ade91d604..dfef2c5cdb 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1483,8 +1483,8 @@ void LB::b_editableText(int nargs) {
if (nargs == 2) {
Datum state = g_lingo->pop();
Datum sprite = g_lingo->pop();
- if ((uint)sprite.asInt() < sc->_sprites.size()) {
- sc->_sprites[sprite.asInt()]->_editable = state.asInt();
+ if ((uint)sprite.asInt() < sc->_channels.size()) {
+ sc->getSpriteById(sprite.asInt())->_editable = state.asInt();
} else {
warning("b_editableText: sprite index out of bounds");
}
@@ -1495,7 +1495,7 @@ void LB::b_editableText(int nargs) {
warning("b_editableText: channel Id is missing");
return;
}
- sc->_sprites[g_lingo->_currentChannelId]->_editable = true;
+ sc->getSpriteById(g_lingo->_currentChannelId)->_editable = true;
} else {
warning("b_editableText: unexpectedly received %d arguments", nargs);
g_lingo->dropStack(nargs);
@@ -1724,8 +1724,8 @@ void LB::b_puppetSprite(int nargs) {
if (nargs == 2) {
Datum state = g_lingo->pop();
Datum sprite = g_lingo->pop();
- if ((uint)sprite.asInt() < sc->_sprites.size()) {
- sc->_sprites[sprite.asInt()]->_puppet = state.asInt();
+ if ((uint)sprite.asInt() < sc->_channels.size()) {
+ sc->getSpriteById(sprite.asInt())->_puppet = state.asInt();
} else {
warning("b_puppetSprite: sprite index out of bounds");
}
@@ -1736,7 +1736,7 @@ void LB::b_puppetSprite(int nargs) {
warning("b_puppetSprite: channel Id is missing");
return;
}
- sc->_sprites[g_lingo->_currentChannelId]->_puppet = true;
+ sc->getSpriteById(g_lingo->_currentChannelId)->_puppet = true;
} else {
warning("b_puppetSprite: unexpectedly received %d arguments", nargs);
g_lingo->dropStack(nargs);
@@ -1773,7 +1773,7 @@ void LB::b_rollOver(int nargs) {
return;
}
- if (arg >= (int32) score->_sprites.size()) {
+ if (arg >= (int32) score->_channels.size()) {
g_lingo->push(res);
return;
}
@@ -1827,33 +1827,32 @@ void LB::b_zoomBox(int nargs) {
Score *score = g_director->getCurrentScore();
uint16 curFrame = score->getCurrentFrame();
- Common::Rect *startRect = score->getSpriteRect(startSprite);
- if (!startRect) {
+ Common::Rect startRect = score->_channels[startSprite]->getBbox();
+ if (startRect.isEmpty()) {
warning("b_zoomBox: unknown start sprite #%d", startSprite);
return;
}
// Looks for endSprite in the current frame, otherwise
// Looks for endSprite in the next frame
- Common::Rect *endRect = score->getSpriteRect(endSprite);
- if (!endRect) {
+ Common::Rect endRect = score->_channels[endSprite]->getBbox();
+ if (endRect.isEmpty()) {
if ((uint)curFrame + 1 < score->_frames.size())
- endRect = &score->_frames[curFrame + 1]->_sprites[endSprite]->_currentBbox;
+ endRect = score->_frames[curFrame + 1]->_sprites[endSprite]->getDims();
}
- if (!endRect) {
+ if (endRect.isEmpty()) {
if ((uint)curFrame - 1 > 0)
- endRect = &score->_frames[curFrame - 1]->_sprites[endSprite]->_currentBbox;
+ endRect = score->_frames[curFrame - 1]->_sprites[endSprite]->getDims();
}
- if (!endRect) {
+ if (endRect.isEmpty()) {
warning("b_zoomBox: unknown end sprite #%d", endSprite);
return;
}
Graphics::ZoomBox *box = new Graphics::ZoomBox;
- box->start = *startRect;
- box->end = *endRect;
- // box->last = Common::Rect(0, 0);
+ box->start = startRect;
+ box->end = endRect;
box->delay = delayTicks;
box->step = 0;
box->startTime = g_system->getMillis();
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 278b4478f9..ac2449c7d3 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -790,8 +790,8 @@ void LC::c_intersects() {
Datum d1 = g_lingo->pop();
Score *score = g_director->getCurrentScore();
- Sprite *sprite1 = score->getSpriteById(d1.asInt());
- Sprite *sprite2 = score->getSpriteById(d2.asInt());
+ Channel *sprite1 = score->getChannelById(d1.asInt());
+ Channel *sprite2 = score->getChannelById(d2.asInt());
if (!sprite1 || !sprite2) {
g_lingo->push(Datum(0));
@@ -806,8 +806,8 @@ void LC::c_within() {
Datum d1 = g_lingo->pop();
Score *score = g_director->getCurrentScore();
- Sprite *sprite1 = score->getSpriteById(d1.asInt());
- Sprite *sprite2 = score->getSpriteById(d2.asInt());
+ Channel *sprite1 = score->getChannelById(d1.asInt());
+ Channel *sprite2 = score->getChannelById(d2.asInt());
if (!sprite1 || !sprite2) {
g_lingo->push(Datum(0));
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 96892ec659..29f3544eaa 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -469,7 +469,7 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
Score *sc = _vm->getCurrentScore();
uint16 spriteId = sc->getSpriteIDFromPos(pos);
d.type = INT;
- d.u.i = sc->_sprites[spriteId]->_castId;
+ d.u.i = sc->getSpriteById(spriteId)->_castId;
if (d.u.i == 0)
d.u.i = -1;
}
@@ -688,8 +688,8 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
return d;
}
- Sprite *sprite = score->getSpriteById(id);
- SpriteChannel *channel = score->getSpriteChannelById(id);
+ Channel *channel = score->getChannelById(id);
+ Sprite *sprite = channel->_sprite;
if (!sprite)
return d;
@@ -704,7 +704,7 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
d.u.i = sprite->_blend;
break;
case kTheBottom:
- d.u.i = sprite->_currentBbox.bottom;
+ d.u.i = sprite->getDims().bottom + channel->_currentPoint.y;
break;
case kTheCastNum:
d.u.i = sprite->_castId;
@@ -728,16 +728,16 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
d.u.i = sprite->_ink;
break;
case kTheLeft:
- d.u.i = sprite->_currentBbox.left;
+ d.u.i = sprite->getDims().left + channel->_currentPoint.x;
break;
case kTheLineSize:
d.u.i = sprite->_thickness & 0x3;
break;
case kTheLocH:
- d.u.i = sprite->_currentPoint.x;
+ d.u.i = channel->_currentPoint.x;
break;
case kTheLocV:
- d.u.i = sprite->_currentPoint.y;
+ d.u.i = channel->_currentPoint.y;
break;
case kTheMoveableSprite:
d.u.i = sprite->_moveable;
@@ -755,7 +755,7 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
d.u.i = sprite->_puppet;
break;
case kTheRight:
- d.u.i = sprite->_currentBbox.right;
+ d.u.i = sprite->getDims().right + channel->_currentPoint.x;
break;
case kTheStartTime:
d.u.i = sprite->_startTime;
@@ -767,7 +767,7 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
d.u.i = sprite->_stretch;
break;
case kTheTop:
- d.u.i = sprite->_currentBbox.top;
+ d.u.i = sprite->getDims().top + channel->_currentPoint.y;
break;
case kTheTrails:
d.u.i = sprite->_trails;
@@ -809,8 +809,8 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
return;
}
- Sprite *sprite = score->getSpriteById(id);
- SpriteChannel *channel = score->getSpriteChannelById(id);
+ Channel *channel = score->getChannelById(id);
+ Sprite *sprite = channel->_sprite;
if (!sprite)
return;
@@ -849,16 +849,15 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
sprite->_thickness = d.asInt();
break;
case kTheLocH:
- sprite->_currentPoint.x = d.asInt();
+ channel->addDelta(Common::Point(d.asInt() - channel->_currentPoint.x, 0));
break;
case kTheLocV:
- sprite->_currentPoint.y = d.asInt();
+ channel->addDelta(Common::Point(0, d.asInt() - channel->_currentPoint.y));
break;
case kTheMoveableSprite:
sprite->_moveable = d.asInt();
- if (!d.u.i) {
- sprite->_currentPoint = sprite->_startPoint;
- }
+ if (!d.u.i)
+ channel->resetPosition();
break;
case kTheMovieRate:
sprite->_movieRate = d.asInt();
@@ -872,7 +871,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
case kThePuppet:
sprite->_puppet = d.asInt();
if (!d.asInt()) {
- sprite->_currentPoint = sprite->_startPoint;
+ channel->resetPosition();
// TODO: Properly reset sprite properties after puppet disabled.
sprite->_moveable = false;
diff --git a/engines/director/score-loading.cpp b/engines/director/score-loading.cpp
index c367067a63..4151984369 100644
--- a/engines/director/score-loading.cpp
+++ b/engines/director/score-loading.cpp
@@ -259,10 +259,9 @@ bool Score::loadArchive(bool isSharedCast) {
}
copyCastStxts();
- setSpriteCasts();
loadSpriteImages(isSharedCast);
loadSpriteSounds(isSharedCast);
- setSpriteBboxes();
+ setSpriteCasts();
return true;
}
@@ -514,10 +513,6 @@ void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) {
warning("STUB: Score::loadFrames. unk1: %x unk2: %x unk3: %x unk4: %x unk5: %x unk6: %x", unk1, unk2, unk3, unk4, unk5, unk6);
}
- for (int i = 0; i < _numChannelsDisplayed + 1; i++) {
- _spriteChannels.push_back(new SpriteChannel());
- }
-
uint16 channelSize;
uint16 channelOffset;
@@ -691,20 +686,8 @@ void Score::setSpriteCasts() {
for (uint16 i = 0; i < _frames.size(); i++) {
for (uint16 j = 0; j < _frames[i]->_sprites.size(); j++) {
_frames[i]->_sprites[j]->setCast(_frames[i]->_sprites[j]->_castId);
- debugC(1, kDebugImages, "Score::setSpriteCasts(): Frame: %d Channel: %d castId: %d type: %d", i, j, _frames[i]->_sprites[j]->_castId, _frames[i]->_sprites[j]->_spriteType);
- }
- }
-}
-
-void Score::setSpriteBboxes() {
- // Initialise the sprite cache for all the initial bounding boxes
- for (uint16 i = 0; i < _frames.size(); i++) {
- for (uint16 j = 0; j < _frames[i]->_sprites.size(); j++) {
- Sprite *sp = _frames[i]->_sprites[j];
- sp->updateCast();
- sp->_startBbox = sp->getBbox();
- sp->_currentBbox = sp->_startBbox;
+ debugC(1, kDebugImages, "Score::setSpriteCasts(): Frame: %d Channel: %d castId: %d type: %d", i, j, _frames[i]->_sprites[j]->_castId, _frames[i]->_sprites[j]->_spriteType);
}
}
}
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index d69a88c346..7100db4795 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -38,6 +38,43 @@
namespace Director {
+Channel::Channel(Sprite *sp) {
+ _sprite = sp;
+ _currentPoint = sp->_startPoint;
+ _delta = Common::Point(0, 0);
+
+ _visible = true;
+
+ if (_sprite && _sprite->_castType != kCastTypeNull) {
+ _sprite->updateCast();
+ updateLocation();
+ }
+}
+
+Common::Rect Channel::getBbox() {
+ Common::Rect bbox = _sprite->getDims();
+ bbox.moveTo(_currentPoint);
+
+ return bbox;
+}
+
+void Channel::updateLocation() {
+ _currentPoint += _delta;
+ _delta = Common::Point(0, 0);
+
+ _sprite->translate(_currentPoint, true);
+}
+
+void Channel::addDelta(Common::Point pos) {
+ // This method is for easily implementing constraint of sprite
+
+ _delta += pos;
+}
+
+void Channel::resetPosition() {
+ _delta = _sprite->_startPoint;
+}
+
Score::Score(DirectorEngine *vm) {
_vm = vm;
_surface = nullptr;
@@ -109,8 +146,8 @@ Score::~Score() {
for (uint i = 0; i < _frames.size(); i++)
delete _frames[i];
- for (uint i = 0; i < _spriteChannels.size(); i++)
- delete _spriteChannels[i];
+ for (uint i = 0; i < _channels.size(); i++)
+ delete _channels[i];
if (_loadedStxts)
for (Common::HashMap<int, const Stxt *>::iterator it = _loadedStxts->begin(); it != _loadedStxts->end(); ++it)
@@ -328,16 +365,18 @@ void Score::startLoop() {
_stopPlay = false;
_nextFrameTime = 0;
- _sprites = _frames[_currentFrame]->_sprites;
- _lingo->processEvent(kEventStartMovie);
-
- renderFrame(_currentFrame, true);
-
if (_frames.size() <= 1) { // We added one empty sprite
warning("Score::startLoop(): Movie has no frames");
_stopPlay = true;
}
+ // All frames in the same movie have the same number of channels
+ for (int i = _frames[1]->_sprites.size() - 1; i >= 0; i--) {
+ _channels.push_back(new Channel(_frames[1]->_sprites[i]));
+ }
+
+ _lingo->processEvent(kEventStartMovie);
+
while (!_stopPlay) {
if (_currentFrame >= _frames.size()) {
if (debugChannelSet(-1, kDebugNoLoop))
@@ -488,8 +527,9 @@ void Score::renderFrame(uint16 frameId, bool forceUpdate, bool updateStageOnly)
Frame *currentFrame = _frames[frameId];
- for (uint16 i = 0; i < _sprites.size(); i++) {
- Sprite *currentSprite = _sprites[i];
+ for (uint16 i = 0; i < _channels.size(); i++) {
+ Channel *channel = _channels[i];
+ Sprite *currentSprite = channel->_sprite;
Sprite *nextSprite;
if (currentSprite->_puppet)
@@ -502,38 +542,53 @@ void Score::renderFrame(uint16 frameId, bool forceUpdate, bool updateStageOnly)
// - The cast member ID of the sprite has changed (_dirty flag set)
// - The sprite slot from the current frame is different (cast member ID or bounding box) from the cached sprite slot
// (maybe we have to compare all the sprite attributes, not just these two?)
- bool needsUpdate = currentSprite->isDirty() || currentSprite->_castId != nextSprite->_castId || currentSprite->_currentBbox != nextSprite->_currentBbox;
+ bool needsUpdate = currentSprite->isDirty() ||
+ currentSprite->_castId != nextSprite->_castId ||
+ channel->_delta != Common::Point(0, 0) ||
+ currentSprite->_startPoint != nextSprite->_startPoint ||
+ currentSprite->getDims() != nextSprite->getDims() ||
+ (channel->_currentPoint != nextSprite->_startPoint &&
+ currentSprite != nextSprite);
+
if (needsUpdate || forceUpdate) {
if (!currentSprite->_trails) {
- _maskSurface->fillRect(currentSprite->_currentBbox, 1);
- _surface->fillRect(currentSprite->_currentBbox, _stageColor);
+ Common::Rect currentBbox = channel->getBbox();
+ _maskSurface->fillRect(currentBbox, 1);
+ _surface->fillRect(currentBbox, _stageColor);
}
-
- currentSprite->_currentBbox = currentSprite->getBbox();
}
- _maskSurface->fillRect(nextSprite->_currentBbox, 1);
- _sprites[i] = nextSprite;
+ channel->_sprite = nextSprite;
+ channel->updateLocation();
}
- for (uint id = 0; id < _sprites.size(); id++) {
- Sprite *sprite = _sprites[id];
+ for (uint id = 0; id < _channels.size(); id++) {
+ Channel *channel = _channels[id];
+ Sprite *sprite = channel->_sprite;
if (!sprite || !sprite->_enabled || !sprite->_castType)
continue;
sprite->updateCast();
+ // Sprites marked moveable are constrained to the same bounding box until
+ // the moveable is disabled
+ if (!sprite->_moveable)
+ channel->_currentPoint = sprite->_startPoint;
+
+ Common::Rect currentBbox = channel->getBbox();
+ _maskSurface->fillRect(currentBbox, 1);
+
debugC(1, kDebugImages, "Score::renderSprite(): channel: %d, castType: %d, castId: %d", id, sprite->_castType, sprite->_castId);
if (sprite->_castType == kCastShape) {
renderShape(id);
} else {
- Cast *cast = _sprites[id]->_cast;
+ Cast *cast = sprite->_cast;
if (cast && cast->_widget) {
cast->_widget->_priority = id;
cast->_widget->draw();
- inkBasedBlit(cast->_widget->getMask(), cast->_widget->getSurface()->rawSurface(), _sprites[id]->_ink, _sprites[id]->_currentBbox, id);
+ inkBasedBlit(cast->_widget->getMask(), cast->_widget->getSurface()->rawSurface(), channel->_sprite->_ink, currentBbox, id);
} else {
warning("Score::renderSprite: No widget for channel ID %d", id);
}
@@ -562,7 +617,7 @@ void Score::renderFrame(uint16 frameId, bool forceUpdate, bool updateStageOnly)
}
void Score::renderShape(uint16 spriteId) {
- Sprite *sp = _sprites[spriteId];
+ Sprite *sp = _channels[spriteId]->_sprite;
InkType ink = sp->_ink;
byte spriteType = sp->_spriteType;
@@ -617,7 +672,7 @@ void Score::renderShape(uint16 spriteId) {
// for outlined shapes, line thickness of 1 means invisible.
lineSize -= 1;
- Common::Rect shapeRect = sp->_currentBbox;
+ Common::Rect shapeRect = _channels[spriteId]->getBbox();
Graphics::ManagedSurface tmpSurface, maskSurface;
tmpSurface.create(shapeRect.width(), shapeRect.height(), Graphics::PixelFormat::createFormatCLUT8());
@@ -698,46 +753,37 @@ const Stxt *Score::getStxt(int castId) {
}
uint16 Score::getSpriteIDFromPos(Common::Point pos) {
- for (int i = _sprites.size() - 1; i >= 0; i--)
- if (_sprites[i]->_currentBbox.contains(pos))
+ for (int i = _channels.size() - 1; i >= 0; i--)
+ if (_channels[i]->getBbox().contains(pos))
return i;
return 0;
}
bool Score::checkSpriteIntersection(uint16 spriteId, Common::Point pos) {
- if (_sprites[spriteId]->_currentBbox.contains(pos))
+ if (_channels[spriteId]->getBbox().contains(pos))
return true;
return false;
}
-Common::Rect *Score::getSpriteRect(uint16 spriteId) {
- if (!_sprites[spriteId]->_currentBbox.isEmpty())
- return &_sprites[spriteId]->_currentBbox;
-
- return nullptr;
-}
-
Sprite *Score::getSpriteById(uint16 id) {
- if (id >= _sprites.size()) {
- warning("Score::getSpriteById(%d): out of bounds. frame: %d", id, _currentFrame);
- return nullptr;
- }
- if (_sprites[id]) {
- return _sprites[id];
+ Channel *channel = getChannelById(id);
+
+ if (channel) {
+ return channel->_sprite;
} else {
- warning("Sprite on frame %d width id %d not found", _currentFrame, id);
+ warning("Score::getSpriteById: sprite on frame %d with id %d not found", _currentFrame, id);
return nullptr;
}
}
-SpriteChannel *Score::getSpriteChannelById(uint16 id) {
- if (id >= _spriteChannels.size()) {
+Channel *Score::getChannelById(uint16 id) {
+ if (id >= _channels.size()) {
warning("Score::getSpriteChannelById(%d): out of bounds", id);
return nullptr;
}
- return _spriteChannels[id];
+ return _channels[id];
}
void Score::playSoundChannel(uint16 frameId) {
diff --git a/engines/director/score.h b/engines/director/score.h
index 1eb98aafaf..08fb1a5a68 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -48,8 +48,8 @@ class Frame;
struct Label;
class Lingo;
struct Resource;
+class Channel;
class Sprite;
-class SpriteChannel;
class Stxt;
class BitmapCast;
class ScriptCast;
@@ -86,6 +86,20 @@ struct TransParams {
}
};
+struct Channel {
+ Sprite *_sprite;
+
+ bool _visible;
+ Common::Point _currentPoint;
+ Common::Point _delta;
+
+ Channel(Sprite *sp);
+ Common::Rect getBbox();
+ void updateLocation();
+ void addDelta(Common::Point pos);
+ void resetPosition();
+};
+
class Score {
public:
Score(DirectorEngine *vm);
@@ -110,10 +124,9 @@ public:
void setCurrentFrame(uint16 frameId) { _nextFrame = frameId; }
uint16 getCurrentFrame() { return _currentFrame; }
Common::String getMacName() const { return _macName; }
+ Channel *getChannelById(uint16 id);
Sprite *getSpriteById(uint16 id);
- SpriteChannel *getSpriteChannelById(uint16 id);
void setSpriteCasts();
- void setSpriteBboxes();
void loadSpriteImages(bool isSharedCast);
void loadSpriteSounds(bool isSharedCast);
void copyCastStxts();
@@ -128,7 +141,6 @@ public:
uint16 getSpriteIDFromPos(Common::Point pos);
bool checkSpriteIntersection(uint16 spriteId, Common::Point pos);
- Common::Rect *getSpriteRect(uint16 spriteId);
Cast *getCastMember(int castId);
const Stxt *getStxt(int castId);
@@ -171,9 +183,8 @@ private:
bool processImmediateFrameScript(Common::String s, int id);
public:
+ Common::Array<Channel *> _channels;
Common::Array<Frame *> _frames;
- Common::Array<Sprite *> _sprites;
- Common::Array<SpriteChannel *> _spriteChannels;
Common::HashMap<uint16, CastInfo *> _castsInfo;
Common::HashMap<Common::String, int, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _castsNames;
Common::SortedArray<Label *> *_labels;
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 0d59887ae2..dcdcb6a951 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -30,13 +30,6 @@
namespace Director {
-SpriteChannel::SpriteChannel() {
- _visible = true;
-}
-
-SpriteChannel::~SpriteChannel() {
-}
-
Sprite::Sprite() {
_scriptId = 0;
_scriptCastIndex = 0;
@@ -95,35 +88,23 @@ void Sprite::updateCast() {
_cast->createWidget();
}
- int offsetx = 0, offsety = 0;
- if (_cast->_type == kCastBitmap) {
- BitmapCast *bc = (BitmapCast *)_cast;
- offsety = bc->_initialRect.top - bc->_regY;
- offsetx = bc->_initialRect.left - bc->_regX;
- }
-
- if (_cast && _cast->_widget)
- _cast->_widget->_dims.moveTo(_currentPoint.x + offsetx, _currentPoint.y + offsety);
-
if (_cast->isEditable() != _editable && !_puppet)
_cast->setEditable(_editable);
}
void Sprite::translate(Common::Point delta, bool moveTo) {
- _currentPoint += delta;
-
if (_cast && _cast->_widget) {
if (moveTo)
- _cast->_widget->_dims.translate(delta.x, delta.y);
- else
_cast->_widget->_dims.moveTo(delta.x, delta.y);
+ else
+ _cast->_widget->_dims.translate(delta.x, delta.y);
}
_dirty = true;
}
bool Sprite::isDirty() {
- return _dirty || (_cast && _cast->isModified());
+ return _castType != kCastTypeNull && (_dirty || (_cast && _cast->isModified()));
}
void Sprite::setClean() {
@@ -246,11 +227,16 @@ void Sprite::setCast(uint16 castId) {
}
}
+ if (_castType == kCastBitmap && _cast) {
+ BitmapCast *bc = (BitmapCast *)_cast;
+
+ _startPoint += Common::Point(bc->_initialRect.left - bc->_regX, bc->_initialRect.top - bc->_regY);
+ }
_dirty = true;
}
-Common::Rect Sprite::getBbox() {
+Common::Rect Sprite::getDims() {
Common::Rect result;
if (_castId == 0) {
return result;
@@ -258,18 +244,18 @@ Common::Rect Sprite::getBbox() {
if (_castType == kCastShape) {
// WORKAROUND: Shape widgets not fully implemented.
- result = Common::Rect(_currentPoint.x, _currentPoint.y, _currentPoint.x + _width, _currentPoint.y + _height);
+ result = Common::Rect(_width, _height);
} else {
- result = _cast && _cast->_widget ? _cast->_widget->getDimensions() : Common::Rect(0, 0, _width, _height);
- }
-
- result.moveTo(_currentPoint.x, _currentPoint.y);
-
- if (_cast && _castType == kCastBitmap) {
- BitmapCast *bc = (BitmapCast *)_cast;
- int offsety = bc->_initialRect.top - bc->_regY;
- int offsetx = bc->_initialRect.left - bc->_regX;
- result.translate(offsetx, offsety);
+ if (_cast && _cast->_widget) {
+ result = Common::Rect(_cast->_widget->_dims.width(), _cast->_widget->_dims.height());
+
+ if (_castType == kCastBitmap) {
+ BitmapCast *bc = (BitmapCast *)_cast;
+ int offsety = bc->_initialRect.top - bc->_regY;
+ int offsetx = bc->_initialRect.left - bc->_regX;
+ result.translate(offsetx, offsety);
+ }
+ }
}
if (_puppet && _stretch) {
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index 204a12ca25..f7f601941d 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -56,14 +56,6 @@ enum MainChannelsPosition {
kPalettePosition = 15
};
-class SpriteChannel {
-public:
- SpriteChannel();
- ~SpriteChannel();
-
- bool _visible;
-};
-
class Sprite {
public:
Sprite();
@@ -78,7 +70,7 @@ public:
void setCast(uint16 castid);
- Common::Rect getBbox();
+ Common::Rect getDims();
uint16 _scriptId;
uint16 _scriptCastIndex;
@@ -100,9 +92,6 @@ public:
byte _thickness;
bool _dirty;
Common::Point _startPoint;
- Common::Point _currentPoint;
- Common::Rect _startBbox;
- Common::Rect _currentBbox;
int16 _width;
int16 _height;
// TODO: default constraint = 0, if turned on, sprite is constrainted to the bounding rect
Commit: c7714d3882343ef4322a93b8e5c7b8a05fd126d2
https://github.com/scummvm/scummvm/commit/c7714d3882343ef4322a93b8e5c7b8a05fd126d2
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-06-17T09:07:35-04:00
Commit Message:
DIRECTOR: Work around flashing reverse sprites
Changed paths:
engines/director/score.cpp
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 7100db4795..8deac6ff55 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -550,6 +550,8 @@ void Score::renderFrame(uint16 frameId, bool forceUpdate, bool updateStageOnly)
(channel->_currentPoint != nextSprite->_startPoint &&
currentSprite != nextSprite);
+ // WORKAROUND, HACK: Redraw reverse ink sprites each time to prevent flickering
+ needsUpdate = needsUpdate || (currentSprite->_ink == kInkTypeReverse);
if (needsUpdate || forceUpdate) {
if (!currentSprite->_trails) {
More information about the Scummvm-git-logs
mailing list