[Scummvm-git-logs] scummvm master -> 713f9f2624f048d725c2389d6aeae9747c2ad032
npjg
nathanael.gentrydb8 at gmail.com
Tue Jun 30 16:39:03 UTC 2020
This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
d04934a54f DIRECTOR: Move rendering to a Stage class
30bd4de3a7 Revert "GRAPHICS: MACGUI: Add QuickDraw class"
1ddc4bf6bd GRAPHICS: MACGUI: MacButton: Properly mark dirty button states
93a5c39381 DIRECTOR: Cache widgets for all loaded cast
487dcec139 DIRECTOR: Remove shape cast hack
713f9f2624 DIRECTOR: Unify sprite and channel internal rendering methods
Commit: d04934a54fdc05c92f4bb71ba9a6d2ba1a60da53
https://github.com/scummvm/scummvm/commit/d04934a54fdc05c92f4bb71ba9a6d2ba1a60da53
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-06-30T12:38:46-04:00
Commit Message:
DIRECTOR: Move rendering to a Stage class
This commit introduces several changes to the rendering pipeline.
- Rather than having a window for each score that is played, there is a Stage
in g_director that is only cleared when the upcoming stage has a different
size. This permits transitions still clean transitions between movies.
- Rather than relying upon general surface blitting functions, there is
progress toward a custom blitter than makes working with inks much easier. A
pixelwise function, inkDrawPixel, has been introduced.
- The mask-based approach to incremental rendering has been abandoned, as it
caused performance issues and strange rendering bugs. Now the renderer
operates on a traditional list of dirty rects that must be redrawn.
- QuickDraw shapes are more closely integrated with the renderer, and they do
not require a temporary surface to draw.
Changed paths:
A engines/director/stage.cpp
A engines/director/stage.h
R engines/director/ink.cpp
engines/director/cast.cpp
engines/director/director.cpp
engines/director/director.h
engines/director/graphics.cpp
engines/director/lingo/lingo-builtins.cpp
engines/director/lingo/lingo-the.cpp
engines/director/module.mk
engines/director/score-loading.cpp
engines/director/score.cpp
engines/director/score.h
engines/director/sprite.cpp
engines/director/transitions.cpp
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 74b0627f4c..21f8fcf035 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -138,7 +138,7 @@ void BitmapCast::createWidget() {
return;
}
- _widget = new Graphics::MacWidget(g_director->getCurrentScore()->_window, 0, 0, _initialRect.width(), _initialRect.height(), g_director->_wm, false);
+ _widget = new Graphics::MacWidget(g_director->getStage(), 0, 0, _initialRect.width(), _initialRect.height(), g_director->_wm, false);
_widget->getSurface()->blitFrom(*_img->getSurface());
}
@@ -394,13 +394,13 @@ void TextCast::createWidget() {
switch (_type) {
case kCastText:
- _widget = new Graphics::MacText(g_director->getCurrentScore()->_window, 0, 0, _initialRect.width(), _initialRect.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), _initialRect.width(), getAlignment(), 1, _borderSize, _gutterSize, _boxShadow, _textShadow);
+ _widget = new Graphics::MacText(g_director->getStage(), 0, 0, _initialRect.width(), _initialRect.height(), g_director->_wm, _ftext, macFont, getForeColor(), getBackColor(), _initialRect.width(), getAlignment(), 1, _borderSize, _gutterSize, _boxShadow, _textShadow);
((Graphics::MacText *)_widget)->draw();
break;
case kCastButton:
- _widget = new Graphics::MacButton(Graphics::MacButtonType(_buttonType), getAlignment(), g_director->getCurrentScore()->_window, 0, 0, _initialRect.width(), _initialRect.height(), g_director->_wm, _ftext, macFont, getForeColor(), 0xff);
+ _widget = new Graphics::MacButton(Graphics::MacButtonType(_buttonType), getAlignment(), g_director->getStage(), 0, 0, _initialRect.width(), _initialRect.height(), g_director->_wm, _ftext, macFont, getForeColor(), 0xff);
((Graphics::MacButton *)_widget)->draw();
_widget->_focusable = true;
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index 169ec2d9e8..6014ececc5 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -32,6 +32,7 @@
#include "graphics/macgui/macwindowmanager.h"
#include "director/director.h"
+#include "director/stage.h"
#include "director/archive.h"
#include "director/score.h"
#include "director/sound.h"
@@ -120,6 +121,8 @@ DirectorEngine::~DirectorEngine() {
delete _sharedScore;
delete _currentScore;
+ _wm->removeWindow(_currentStage);
+
if (_macBinary) {
delete _macBinary;
_macBinary = nullptr;
@@ -145,6 +148,11 @@ Common::Error DirectorEngine::run() {
_wm = new Graphics::MacWindowManager(wmMode, &_director3QuickDrawPatterns);
_wm->setEngine(this);
+ _currentStage = new Stage(_wm->getNextId(), false, false, false, _wm);
+ _currentStage->disableBorder();
+ _wm->addWindowInitialized(_currentStage);
+ _wm->setScreen(_currentStage->getSurface());
+
_lingo = new Lingo(this);
_soundManager = new DirectorSound(this);
@@ -274,13 +282,7 @@ Common::Error DirectorEngine::run() {
// If a loop was requested, do it
if (!_nextMovie.movie.empty()) {
- // Persist screen between the movies
- // TODO: this is a workaround until the rendering pipeline is reworked
- if (_currentScore && _currentScore->_surface) {
- _backSurface.copyFrom(*_currentScore->_surface);
-
- _newMovieStarted = true;
- }
+ _newMovieStarted = true;
delete _currentScore;
_currentScore = nullptr;
diff --git a/engines/director/director.h b/engines/director/director.h
index dabfbd498f..e0d41d28d0 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -41,6 +41,7 @@ class SeekableSubReadStreamEndian;
namespace Graphics {
class MacWindowManager;
+struct MacPlotData;
typedef Common::Array<byte *> MacPatterns;
}
@@ -56,6 +57,7 @@ class Archive;
struct DirectorGameDescription;
class DirectorSound;
class Lingo;
+class Stage;
class Score;
class Cast;
class Stxt;
@@ -92,6 +94,28 @@ struct PaletteV4 {
int length;
};
+// An extension of MacPlotData for interfacing with inks and patterns without
+// needing extra surfaces.
+struct DirectorPlotData {
+ Graphics::ManagedSurface *src;
+ Graphics::ManagedSurface *dst;
+ Graphics::MacPlotData *macPlot;
+ Common::Rect destRect;
+ Common::Point srcPoint;
+
+ InkType ink;
+ int numColors;
+ uint backColor;
+
+ Graphics::MacWindowManager *_wm;
+
+ DirectorPlotData(Graphics::MacWindowManager *wm, Graphics::ManagedSurface *s, Graphics::ManagedSurface *d, InkType i, uint b, uint n) :
+ src(s), dst(d), ink(i), backColor(b), macPlot(nullptr), numColors(n), _wm(wm) {
+ }
+};
+
+void inkDrawPixel(int x, int y, int color, void *data);
+
class DirectorEngine : public ::Engine {
public:
DirectorEngine(OSystem *syst, const DirectorGameDescription *gameDesc);
@@ -109,6 +133,7 @@ public:
Graphics::MacWindowManager *getMacWindowManager() const { return _wm; }
Archive *getMainArchive() const { return _mainArchive; }
Lingo *getLingo() const { return _lingo; }
+ Stage *getStage() const { return _currentStage; }
Score *getCurrentScore() const { return _currentScore; }
Score *getSharedScore() const { return _sharedScore; }
Common::String getCurrentPath() const { return _currentPath; }
@@ -126,6 +151,7 @@ public:
uint32 transformColor(uint32 color);
Graphics::MacPatterns &getPatterns();
void setCursor(int type); // graphics.cpp
+
void loadKeyCodes();
void loadInitialMovie(const Common::String movie);
@@ -157,7 +183,6 @@ public:
MovieReference _nextMovie;
Common::List<MovieReference> _movieStack;
- Graphics::ManagedSurface _backSurface;
bool _newMovieStarted;
protected:
@@ -184,6 +209,7 @@ private:
uint16 _currentPaletteLength;
Lingo *_lingo;
+ Stage *_currentStage;
Score *_currentScore;
Common::String _currentPath;
@@ -201,7 +227,7 @@ private:
Common::StringArray _movieQueue;
- // tests.cpp
+// tests.cpp
private:
void testFontScaling();
void testFonts();
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index 5f0a193d7e..b85c69adc4 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -793,4 +793,115 @@ void DirectorEngine::setCursor(int type) {
}
}
+void inkDrawPixel(int x, int y, int color, void *data) {
+ DirectorPlotData *p = (DirectorPlotData *)data;
+
+ if (!p->destRect.contains(x, y))
+ return;
+
+ byte rSrc, gSrc, bSrc;
+ byte rDst, gDst, bDst;
+
+ const byte *src;
+ byte *dst;
+
+ byte tmpSrc, tmpDst;
+
+ dst = (byte *)p->dst->getBasePtr(x, y);
+
+ if (p->macPlot) {
+ // Get the pixel that macDrawPixel will give us, but store it to apply the
+ // ink later.
+ tmpDst = *dst;
+ Graphics::macDrawPixel(x, y, color, p->macPlot);
+ tmpSrc = *dst;
+
+ *dst = tmpDst;
+ src = &tmpSrc;
+ } else {
+ if (!p->src)
+ error("Director::inkDrawPixel(): No source surface");
+
+ src = (const byte *)p->src->getBasePtr(p->srcPoint.x, p->srcPoint.y);
+ }
+
+ g_director->_wm->decomposeColor(*src, rSrc, gSrc, bSrc);
+ g_director->_wm->decomposeColor(*dst, rDst, gDst, bDst);
+
+ switch (p->ink) {
+ case kInkTypeBackgndTrans:
+ if (*src == p->backColor)
+ break;
+ // fall through
+ case kInkTypeCopy:
+ *dst = *src;
+ case kInkTypeMask:
+ // TODO: Migrate from Stage to here
+ break;
+ case kInkTypeTransparent:
+ // FIXME: Is colour to ignore always white (last entry in pallette)?
+ if (*src != p->numColors - 1)
+ *dst &= *src;
+ break;
+ case kInkTypeReverse:
+ // TODO: Migrate from Stage to here
+ *dst ^= *src;
+ break;
+ case kInkTypeGhost:
+ if (*src != p->numColors - 1)
+ *dst = *dst | ~(*src);
+ break;
+ case kInkTypeNotCopy:
+ if (*src != p->numColors - 1)
+ *dst = ~(*src);
+ break;
+ case kInkTypeNotTrans:
+ if (*src != p->numColors - 1)
+ *dst = *dst & ~(*src);
+ break;
+ case kInkTypeNotReverse:
+ if (*src != p->numColors - 1)
+ *dst = *dst ^ *src;
+ break;
+ case kInkTypeNotGhost:
+ if (*src != p->numColors - 1)
+ *dst = *dst | *src;
+ break;
+ case kInkTypeMatte:
+ // TODO: Migrate from Stage to here.
+ break;
+ // Arithmetic ink types
+ case kInkTypeBlend:
+ if (*src != p->numColors - 1)
+ *dst = p->_wm->findBestColor((rSrc + rDst) / 2, (gSrc + gDst) / 2, (bSrc + bDst) / 2);
+ break;
+ case kInkTypeAddPin:
+ if (*src != p->numColors - 1)
+ *dst = p->_wm->findBestColor(MIN((rSrc + rDst), p->numColors - 1), MIN((gSrc + gDst), p->numColors - 1), MIN((bSrc + bDst), p->numColors - 1));
+ break;
+ case kInkTypeAdd:
+ if (*src != p->numColors - 1)
+ *dst = p->_wm->findBestColor(abs(rSrc + rDst) % p->numColors, abs(gSrc + gDst) % p->numColors, abs(bSrc + bDst) % p->numColors);
+ break;
+ case kInkTypeSubPin:
+ if (*src != p->numColors - 1)
+ *dst = p->_wm->findBestColor(MAX(rSrc - rDst, 0), MAX(gSrc - gDst, 0), MAX(bSrc - bDst, 0));
+ break;
+ case kInkTypeLight:
+ if (*src != p->numColors - 1)
+ *dst = p->_wm->findBestColor(MAX(rSrc, rDst), MAX(gSrc, gDst), MAX(bSrc, bDst));
+ break;
+ case kInkTypeSub:
+ if (*src != p->numColors - 1)
+ *dst = p->_wm->findBestColor(abs(rSrc - rDst) % p->numColors, abs(gSrc - gDst) % p->numColors, abs(bSrc - bDst) % p->numColors);
+ break;
+ case kInkTypeDark:
+ if (*src != p->numColors - 1)
+ *dst = p->_wm->findBestColor(MIN(rSrc, rDst), MIN(gSrc, gDst), MIN(bSrc, bDst));
+ break;
+ default:
+ warning("Stage::inkBlitFrom: Drawing not implemented yet");
+ }
+}
+
}
diff --git a/engines/director/ink.cpp b/engines/director/ink.cpp
deleted file mode 100644
index fe47037589..0000000000
--- a/engines/director/ink.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "director/director.h"
-#include "director/cast.h"
-#include "director/score.h"
-#include "director/sprite.h"
-
-namespace Director {
-
-void Score::inkBasedBlit(Graphics::ManagedSurface *destSurface, Graphics::ManagedSurface *maskSurface, const Graphics::Surface &spriteSurface, InkType ink, Common::Rect drawRect, uint spriteId) {
-
- byte rSrc, gSrc, bSrc;
- byte rDst, gDst, bDst;
- int numColors = _vm->getPaletteColorCount();
-
- Common::Rect t = Common::Rect(spriteSurface.w, spriteSurface.h);
- t.moveTo(drawRect.left, drawRect.top);
-
- Common::Point maskOrigin(MAX(0, -drawRect.left), MAX(0, -drawRect.top));
- drawRect.clip(Common::Rect(_maskSurface->w, _maskSurface->h));
-
- Graphics::ManagedSurface *castMask = nullptr;
- if (ink == kInkTypeMask) {
- Cast *member = g_director->getCastMember(_channels[spriteId]->_sprite->_castId + 1);
-
- if (!member->_widget)
- member->createWidget();
-
- if (member->_initialRect == _channels[spriteId]->_sprite->_cast->_initialRect)
- castMask = member->_widget->getSurface();
- }
-
- // HACK: A custom blitter is needed for the logical AND necessary here;
- // surface class doesn't provide it.
- for (int ii = 0; ii < drawRect.height(); ii++) {
- const byte *msk = castMask ? (const byte *)castMask->getBasePtr(maskOrigin.x, maskOrigin.y + ii) : nullptr;
- const byte *src = (const byte *)maskSurface->getBasePtr(maskOrigin.x, maskOrigin.y + ii);
- byte *dst = (byte *)_maskSurface->getBasePtr(t.left + maskOrigin.x, t.top + maskOrigin.y + ii);
-
- for (int j = 0; j < drawRect.width(); j++, src++, dst++) {
- *dst &= *src;
-
- if (msk)
- *dst = (*(msk++) ? 0 : *dst);
- }
- }
-
- // TODO: Merge these two into the switch logic that is below
- if (ink == kInkTypeMatte) {
- Common::Rect spriteRect(spriteSurface.w, spriteSurface.h);
- drawMatteSprite(destSurface, spriteSurface, t);
- return;
- } else if (ink == kInkTypeReverse) {
- drawReverseSprite(destSurface, spriteSurface, t, spriteId);
- return;
- }
-
- for (int ii = 0; ii < drawRect.height(); ii++) {
- const byte *msk = (const byte *)_maskSurface->getBasePtr(t.left + maskOrigin.x, t.top + maskOrigin.y + ii);
- const byte *src = (const byte *)spriteSurface.getBasePtr(maskOrigin.x, ii + maskOrigin.y);
- byte *dst = (byte *)destSurface->getBasePtr(t.left + maskOrigin.x, t.top + maskOrigin.y + ii);
-
- for (int j = 0; j < drawRect.width(); j++, msk++, src++, dst++) {
- if (*msk) {
- _vm->_wm->decomposeColor(*src, rSrc, gSrc, bSrc);
- _vm->_wm->decomposeColor(*dst, rDst, gDst, bDst);
-
- switch (ink) {
- case kInkTypeBackgndTrans:
- if (*src == _channels[spriteId]->_sprite->_backColor)
- break;
- // fall through
- case kInkTypeCopy:
- case kInkTypeMask:
- *dst = *src;
- break;
- case kInkTypeTransparent:
- // FIXME: Is colour to ignore always white (last entry in pallette)?
- if (*src != numColors - 1)
- *dst &= *src;
- break;
- case kInkTypeReverse:
- if (*src != numColors - 1)
- *dst ^= *src;
- break;
- case kInkTypeGhost:
- if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0) && *src != numColors - 1)
- *dst = *dst | ~(*src);
- break;
- case kInkTypeNotCopy:
- if (*src != numColors - 1)
- *dst = ~(*src);
- break;
- case kInkTypeNotTrans:
- if (*src != numColors - 1)
- *dst = *dst & ~(*src);
- break;
- case kInkTypeNotReverse:
- if (*src != numColors - 1)
- *dst = *dst ^ *src;
- break;
- case kInkTypeNotGhost:
- if (*src != numColors - 1)
- *dst = *dst | *src;
- break;
- case kInkTypeMatte:
- break;
- // Arithmetic ink types
- case kInkTypeBlend:
- if (*src != numColors - 1)
- *dst = _vm->_wm->findBestColor((rSrc + rDst) / 2, (gSrc + gDst) / 2, (bSrc + bDst) / 2);
- break;
- case kInkTypeAddPin:
- if (*src != numColors - 1)
- *dst = _vm->_wm->findBestColor(MIN((rSrc + rDst), numColors - 1), MIN((gSrc + gDst), numColors - 1), MIN((bSrc + bDst), numColors - 1));
- break;
- case kInkTypeAdd:
- if (*src != numColors - 1)
- *dst = _vm->_wm->findBestColor(abs(rSrc + rDst) % numColors, abs(gSrc + gDst) % numColors, abs(bSrc + bDst) % numColors);
- break;
- case kInkTypeSubPin:
- if (*src != numColors - 1)
- *dst = _vm->_wm->findBestColor(MAX(rSrc - rDst, 0), MAX(gSrc - gDst, 0), MAX(bSrc - bDst, 0));
- break;
- case kInkTypeLight:
- if (*src != numColors - 1)
- *dst = _vm->_wm->findBestColor(MAX(rSrc, rDst), MAX(gSrc, gDst), MAX(bSrc, bDst));
- break;
- case kInkTypeSub:
- if (*src != numColors - 1)
- *dst = _vm->_wm->findBestColor(abs(rSrc - rDst) % numColors, abs(gSrc - gDst) % numColors, abs(bSrc - bDst) % numColors);
- break;
- case kInkTypeDark:
- if (*src != numColors - 1)
- *dst = _vm->_wm->findBestColor(MIN(rSrc, rDst), MIN(gSrc, gDst), MIN(bSrc, bDst));
- break;
- }
- }
- }
- }
-}
-
-void Score::drawReverseSprite(Graphics::ManagedSurface *destSurface, const Graphics::Surface &sprite, Common::Rect &drawRect, uint16 spriteId) {
- Common::Rect srcRect(sprite.w, sprite.h);
-
- if (!_surface->clip(srcRect, drawRect))
- return; // Out of screen
-
- uint8 skipColor = _vm->getPaletteColorCount() - 1;
- for (int ii = 0; ii < drawRect.height(); ii++) {
- const byte *msk = (const byte *)_maskSurface->getBasePtr(drawRect.left, drawRect.top + ii);
- const byte *src = (const byte *)sprite.getBasePtr(srcRect.left, srcRect.top + ii);
- byte *dst = (byte *)destSurface->getBasePtr(drawRect.left, drawRect.top + ii);
- byte srcColor = *src;
-
- for (int j = 0; j < drawRect.width(); j++, msk++, src++, dst++) {
- if (*msk != 0) {
- if (!_channels[spriteId]->_sprite->_cast || _channels[spriteId]->_sprite->_cast->_type == kCastShape)
- srcColor = 0x0;
- else
- srcColor = *src;
- uint16 targetSprite = getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii));
- if ((targetSprite != 0)) {
- // TODO: This entire reverse colour attempt needs a lot more testing on
- // a lot more colour depths.
- if (srcColor != skipColor) {
- 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) {
- *dst = _vm->transformColor(*dst - 40);
- } else {
- *dst = _vm->transformColor(*src - 40);
- }
- } else {
- if (*dst == 0 && _vm->getVersion() == 3 &&
- _channels[spriteId]->_sprite->_cast->_type == kCastBitmap &&
- ((BitmapCast*)_channels[spriteId]->_sprite->_cast)->_bitsPerPixel > 1) {
- *dst = _vm->transformColor(*src - 40);
- } else {
- *dst ^= _vm->transformColor(srcColor);
- }
- }
- }
- } else if (srcColor != skipColor) {
- *dst = _vm->transformColor(srcColor);
- }
- }
- }
- }
-}
-
- void Score::drawMatteSprite(Graphics::ManagedSurface *destSurface, const Graphics::Surface &sprite, Common::Rect &drawRect) {
- // Like background trans, but all white pixels NOT ENCLOSED by coloured pixels are transparent
- Graphics::Surface tmp;
- tmp.copyFrom(sprite);
- Common::Rect srcRect(sprite.w, sprite.h);
-
- if (!_surface->clip(srcRect, drawRect))
- return; // Out of screen
-
- // Searching white color in the corners
- int whiteColor = -1;
-
- for (int y = 0; y < tmp.h; y++) {
- for (int x = 0; x < tmp.w; x++) {
- byte color = *(byte *)tmp.getBasePtr(x, y);
-
- if (_vm->getPalette()[color * 3 + 0] == 0xff &&
- _vm->getPalette()[color * 3 + 1] == 0xff &&
- _vm->getPalette()[color * 3 + 2] == 0xff) {
- whiteColor = color;
- break;
- }
- }
- }
-
- if (whiteColor == -1) {
- debugC(1, kDebugImages, "Score::drawMatteSprite(): No white color for Matte image");
-
- for (int yy = 0; yy < drawRect.height(); yy++) {
- const byte *msk = (const byte *)_maskSurface->getBasePtr(drawRect.left, drawRect.top + yy);
- const byte *src = (const byte *)tmp.getBasePtr(srcRect.left, srcRect.top + yy);
- byte *dst = (byte *)destSurface->getBasePtr(drawRect.left, drawRect.top + yy);
-
- for (int xx = 0; xx < drawRect.width(); xx++, src++, dst++, msk++)
- if (*msk != 0)
- *dst = *src;
- }
- } else {
- Graphics::FloodFill ff(&tmp, whiteColor, 0, true);
-
- for (int yy = 0; yy < tmp.h; yy++) {
- ff.addSeed(0, yy);
- ff.addSeed(tmp.w - 1, yy);
- }
-
- for (int xx = 0; xx < tmp.w; xx++) {
- ff.addSeed(xx, 0);
- ff.addSeed(xx, tmp.h - 1);
- }
- ff.fillMask();
-
- for (int yy = 0; yy < drawRect.height(); yy++) {
- const byte *src = (const byte *)tmp.getBasePtr(srcRect.left, srcRect.top + yy);
- const byte *mask = (const byte *)ff.getMask()->getBasePtr(srcRect.left, srcRect.top + yy);
- byte *dst = (byte *)destSurface->getBasePtr(drawRect.left, drawRect.top + yy);
-
- for (int xx = 0; xx < drawRect.width(); xx++, src++, dst++, mask++)
- if (*mask == 0)
- *dst = *src;
- }
- }
-
- tmp.free();
-}
-
-} // End of namespace Director
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 2222d22102..ed9e282bf4 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1744,6 +1744,7 @@ void LB::b_puppetTempo(int nargs) {
void LB::b_puppetTransition(int nargs) {
// puppetTransition whichTransition [, time] [, chunkSize] [, changeArea]
Score *score = g_director->getCurrentScore();
+ Stage *stage = g_director->getStage();
uint16 duration = 250, area = 1, chunkSize = 1, type = 0;
if (nargs == 4) {
area = g_lingo->pop().asInt();
@@ -1766,7 +1767,7 @@ void LB::b_puppetTransition(int nargs) {
ARGNUMCHECK(1);
}
- score->playTransition(duration, area, chunkSize, ((TransitionType)type));
+ stage->playTransition(duration, area, chunkSize, ((TransitionType)type), score->getCurrentFrame());
}
void LB::b_ramNeeded(int nargs) {
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 430f049397..6f3d25f0b8 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -649,16 +649,8 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
}
}
break;
- case kTheStageColor: {
- Score *score = _vm->getCurrentScore();
- score->_stageColor = _vm->transformColor(d.asInt());
- if (score->_surface) {
- score->_surface->clear(score->_stageColor);
- score->renderFrame(score->getCurrentFrame(), kRenderForceUpdate);
- } else {
- warning("setStageColor: score has no surface, skipping");
- }
- }
+ case kTheStageColor:
+ g_director->getStage()->setStageColor(d.asInt());
break;
case kTheSprite:
setTheSprite(id, field, d);
@@ -866,7 +858,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
break;
case kTheHeight:
if (sprite->_puppet && sprite->_stretch) {
- score->markDirtyRect(channel->getBbox());
+ g_director->getStage()->addDirtyRect(channel->getBbox());
sprite->_height = d.asInt();
}
break;
@@ -928,7 +920,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
break;
case kTheWidth:
if (sprite->_puppet && sprite->_stretch) {
- score->markDirtyRect(channel->getBbox());
+ g_director->getStage()->addDirtyRect(channel->getBbox());
sprite->_width = d.asInt();
}
break;
diff --git a/engines/director/module.mk b/engines/director/module.mk
index ad04ef32e7..196a030656 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -9,9 +9,9 @@ MODULE_OBJS = \
frame.o \
graphics.o \
images.o \
- ink.o \
movie.o \
resource.o \
+ stage.o \
score-loading.o \
score.o \
sound.o \
diff --git a/engines/director/score-loading.cpp b/engines/director/score-loading.cpp
index d108cb63c8..175ccf982a 100644
--- a/engines/director/score-loading.cpp
+++ b/engines/director/score-loading.cpp
@@ -126,9 +126,15 @@ bool Score::loadArchive(bool isSharedCast) {
}
if (!isSharedCast) {
- _window = _vm->_wm->addWindow(false, false, false);
- _window->disableBorder();
- _window->resize(_movieRect.width(), _movieRect.height());
+ Stage *stage = g_director->getStage();
+
+ // If the stage dimensions are different, delete it and start again.
+ // Otherwise, do not clear it so there can be a nice transition.
+ if (stage->getSurface()->w != _movieRect.width() || stage->getSurface()->h != _movieRect.height()) {
+ stage->resize(_movieRect.width(), _movieRect.height());
+ }
+
+ stage->setStageColor(_stageColor);
}
// Cast Information Array
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index dba19a86bc..2fd6e41301 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -59,6 +59,14 @@ Channel::Channel(Sprite *sp) {
}
}
+Graphics::ManagedSurface *Channel::getSurface() {
+ if (_sprite->_cast && _sprite->_cast->_widget) {
+ return _sprite->_cast->_widget->getSurface();
+ } else {
+ return nullptr;
+ }
+}
+
Common::Rect Channel::getBbox() {
Common::Rect bbox = _sprite->getDims();
bbox.moveTo(getPosition());
@@ -111,10 +119,65 @@ void Channel::resetPosition() {
_delta = _sprite->_startPoint;
}
+MacShape *Channel::getShape() {
+ MacShape *shape = new MacShape();
+
+ if (_sprite->_castType != kCastShape)
+ return nullptr;
+
+ shape->ink = _sprite->_ink;
+ shape->spriteType = _sprite->_spriteType;
+ shape->foreColor = _sprite->_foreColor;
+ shape->backColor = _sprite->_backColor;
+ shape->lineSize = _sprite->_thickness & 0x3;
+
+ if (g_director->getVersion() >= 3 && shape->spriteType == kCastMemberSprite) {
+ if (!_sprite->_cast) {
+ warning("Channel::getShape(): kCastMemberSprite has no cast defined");
+ return nullptr;
+ }
+ switch (_sprite->_cast->_type) {
+ case kCastShape:
+ {
+ ShapeCast *sc = (ShapeCast *)_sprite->_cast;
+ switch (sc->_shapeType) {
+ case kShapeRectangle:
+ shape->spriteType = sc->_fillType ? kRectangleSprite : kOutlinedRectangleSprite;
+ break;
+ case kShapeRoundRect:
+ shape->spriteType = sc->_fillType ? kRoundedRectangleSprite : kOutlinedRoundedRectangleSprite;
+ break;
+ case kShapeOval:
+ shape->spriteType = sc->_fillType ? kOvalSprite : kOutlinedOvalSprite;
+ break;
+ case kShapeLine:
+ shape->spriteType = sc->_lineDirection == 6 ? kLineBottomTopSprite : kLineTopBottomSprite;
+ break;
+ default:
+ break;
+ }
+ if (g_director->getVersion() > 3) {
+ shape->foreColor = sc->_fgCol;
+ shape->backColor = sc->_bgCol;
+ shape->lineSize = sc->_lineThickness;
+ shape->ink = sc->_ink;
+ }
+ }
+ break;
+ default:
+ warning("Channel::getShape(): Unhandled cast type: %d", _sprite->_cast->_type);
+ break;
+ }
+ }
+
+ // for outlined shapes, line thickness of 1 means invisible.
+ shape->lineSize -= 1;
+
+ return shape;
+}
+
Score::Score(DirectorEngine *vm) {
_vm = vm;
- _surface = nullptr;
- _maskSurface = nullptr;
_lingo = _vm->getLingo();
_lingoArchive = kArchMain;
_soundManager = _vm->getSoundManager();
@@ -155,21 +218,9 @@ Score::Score(DirectorEngine *vm) {
_numChannelsDisplayed = 0;
_framesRan = 0; // used by kDebugFewFramesOnly and kDebugScreenshot
-
- _window = nullptr;
-
- _stageColor = 0;
}
Score::~Score() {
- if (_maskSurface && _maskSurface->w)
- _maskSurface->free();
-
- delete _maskSurface;
-
- if (_window)
- _vm->_wm->removeWindow(_window);
-
for (uint i = 0; i < _frames.size(); i++)
delete _frames[i];
@@ -363,14 +414,6 @@ void Score::startLoop() {
initGraphics(_movieRect.width(), _movieRect.height());
- _surface = _window->getWindowSurface();
- _vm->_wm->setScreen(_surface);
-
- _maskSurface = new Graphics::ManagedSurface;
- _maskSurface->create(_movieRect.width(), _movieRect.height());
-
- _surface->clear(_stageColor);
-
_currentFrame = 0;
_stopPlay = false;
_nextFrameTime = 0;
@@ -388,7 +431,6 @@ void Score::startLoop() {
if (_vm->getVersion() >= 3)
_lingo->processEvent(kEventStartMovie);
- _maskSurface->clear(1);
while (!_stopPlay) {
if (_currentFrame >= _frames.size()) {
if (debugChannelSet(-1, kDebugNoLoop))
@@ -398,7 +440,6 @@ void Score::startLoop() {
}
update();
- _maskSurface->clear(0);
if (_currentFrame < _frames.size())
_vm->processEvents();
@@ -482,7 +523,6 @@ void Score::update() {
}
debugC(1, kDebugImages, "****************************** Current frame: %d", _currentFrame);
- _vm->_newMovieStarted = false;
_lingo->executeImmediateScripts(_frames[_currentFrame]);
@@ -493,8 +533,9 @@ void Score::update() {
// TODO: Director 6 step: send prepareFrame event to all sprites and the script channel in upcoming frame
}
- renderFrame(_currentFrame);
// Stage is drawn between the prepareFrame and enterFrame events (Lingo in a Nutshell, p.100)
+ renderFrame(_currentFrame);
+ _vm->_newMovieStarted = false;
// Enter and exit from previous frame
if (!_vm->_playbackPaused) {
@@ -547,37 +588,31 @@ void Score::update() {
void Score::renderFrame(uint16 frameId, RenderMode mode) {
Frame *currentFrame = _frames[frameId];
- // When a transition is played, the next frame is rendered as a part of it.
if (currentFrame->_transType != 0 && mode != kRenderUpdateStageOnly) {
// TODO Handle changing area case
- playTransition(currentFrame->_transDuration, currentFrame->_transArea, currentFrame->_transChunkSize, currentFrame->_transType);
+ g_director->getStage()->playTransition(currentFrame->_transDuration, currentFrame->_transArea, currentFrame->_transChunkSize, currentFrame->_transType, frameId);
} else {
- renderSprites(frameId, _surface, mode);
+ renderSprites(frameId, mode);
}
- _vm->_wm->renderZoomBox();
- _vm->_wm->draw();
-
- if (currentFrame->_sound1 != 0 || currentFrame->_sound2 != 0)
- playSoundChannel(frameId);
+ _vm->_wm->renderZoomBox();
+ g_director->getStage()->render();
+ _vm->_wm->draw();
- g_system->copyRectToScreen(_surface->getPixels(), _surface->pitch, 0, 0, _surface->getBounds().width(), _surface->getBounds().height());
+ if (currentFrame->_sound1 != 0 || currentFrame->_sound2 != 0)
+ playSoundChannel(frameId);
}
-void Score::renderSprites(uint16 frameId, Graphics::ManagedSurface *surface, RenderMode mode) {
- // HACK: Determine a batter way to do this.
- if (mode == kRenderNoUnrender)
- _maskSurface->clear(1);
+void Score::renderSprites(uint16 frameId, RenderMode mode) {
+ if (_vm->_newMovieStarted) {
+ // g_director->getStage()->reset();
+ mode = kRenderForceUpdate;
+ }
for (uint16 i = 0; i < _channels.size(); i++) {
Channel *channel = _channels[i];
Sprite *currentSprite = channel->_sprite;
- Sprite *nextSprite;
-
- if (currentSprite->_puppet)
- nextSprite = currentSprite;
- else
- nextSprite = _frames[frameId]->_sprites[i];
+ Sprite *nextSprite = _frames[frameId]->_sprites[i];
// A sprite needs to be updated if one of the following happens:
// - The dimensions/bounding box of the sprite has changed (_dirty flag set)
@@ -588,63 +623,40 @@ void Score::renderSprites(uint16 frameId, Graphics::ManagedSurface *surface, Ren
currentSprite->_castId != nextSprite->_castId ||
channel->_delta != Common::Point(0, 0) ||
currentSprite->getDims() != nextSprite->getDims() ||
- channel->_currentPoint != nextSprite->_startPoint;
-
- if (mode != kRenderNoUnrender &&
- (needsUpdate || mode == kRenderForceUpdate) &&
- !currentSprite->_trails)
- markDirtyRect(channel->getBbox());
+ currentSprite->_ink != nextSprite->_ink ||
+ (channel->_currentPoint != nextSprite->_startPoint &&
+ !currentSprite->_puppet && !currentSprite->_moveable);
- channel->_sprite = nextSprite;
- channel->_sprite->updateCast();
+ if ((needsUpdate || mode == kRenderForceUpdate) && !currentSprite->_trails)
+ g_director->getStage()->addDirtyRect(channel->getBbox());
- // Sprites marked moveable are constrained to the same bounding box until
- // the moveable is disabled
- if (!nextSprite->_puppet && !nextSprite->_moveable)
- channel->_currentPoint = nextSprite->_startPoint;
+ currentSprite->setClean();
- channel->updateLocation();
-
- // TODO: Understand why conditioning this causes so many problems
- if (mode != kRenderNoUnrender)
- markDirtyRect(channel->getBbox());
- }
+ if (!currentSprite->_puppet) {
+ channel->_sprite = nextSprite;
+ channel->_sprite->updateCast();
- for (uint id = 0; id < _channels.size(); id++) {
- Channel *channel = _channels[id];
- Sprite *sprite = channel->_sprite;
-
- if (!sprite || !sprite->_enabled || !sprite->_castId)
- continue;
-
- Common::Rect currentBbox = channel->getBbox();
+ // Sprites marked moveable are constrained to the same bounding box until
+ // the moveable is disabled
+ if (!channel->_sprite->_moveable)
+ channel->_currentPoint = channel->_sprite->_startPoint;
+ }
- debugC(1, kDebugImages, "Score::renderFrame(): channel: %d, castType: %d, castId: %d", id, sprite->_castType, sprite->_castId);
+ channel->updateLocation();
- if (sprite->_castType == kCastShape) {
- renderShape(id, surface);
- } else {
- Cast *cast = sprite->_cast;
- if (cast && cast->_widget) {
- cast->_widget->_priority = id;
- cast->_widget->draw();
- inkBasedBlit(surface, cast->_widget->getMask(), cast->_widget->getSurface()->rawSurface(), channel->_sprite->_ink, currentBbox, id);
- } else {
- warning("Score::renderFrame(): No widget for channel ID %d", id);
- }
+ if (channel->_sprite->_cast && channel->_sprite->_cast->_widget) {
+ channel->_sprite->_cast->_widget->_priority = i;
+ channel->_sprite->_cast->_widget->draw();
+ channel->_sprite->_cast->_widget->_contentIsDirty = false;
}
- sprite->setClean();
+ if (needsUpdate || mode == kRenderForceUpdate)
+ g_director->getStage()->addDirtyRect(channel->getBbox());
}
}
-void Score::markDirtyRect(Common::Rect dirty) {
- _maskSurface->fillRect(dirty, 1);
- _surface->fillRect(dirty, _stageColor);
-}
-
void Score::screenShot() {
- Graphics::Surface rawSurface = _surface->rawSurface();
+ Graphics::Surface rawSurface = g_director->getStage()->getSurface()->rawSurface();
const Graphics::PixelFormat requiredFormat_4byte(4, 8, 8, 8, 8, 0, 8, 16, 24);
Graphics::Surface *newSurface = rawSurface.convertTo(requiredFormat_4byte, _vm->getPalette());
Common::String currentPath = _vm->getCurrentPath().c_str();
@@ -664,118 +676,6 @@ void Score::screenShot() {
newSurface->free();
}
-void Score::renderShape(uint16 spriteId, Graphics::ManagedSurface *surface) {
- Sprite *sp = _channels[spriteId]->_sprite;
-
- InkType ink = sp->_ink;
- byte spriteType = sp->_spriteType;
- byte foreColor = sp->_foreColor;
- byte backColor = sp->_backColor;
- int lineSize = sp->_thickness & 0x3;
-
- if (_vm->getVersion() >= 3 && spriteType == kCastMemberSprite) {
- if (!sp->_cast) {
- warning("Score::renderShape(): kCastMemberSprite has no cast defined");
- return;
- }
- switch (sp->_cast->_type) {
- case kCastShape:
- {
- ShapeCast *sc = (ShapeCast *)sp->_cast;
- switch (sc->_shapeType) {
- case kShapeRectangle:
- spriteType = sc->_fillType ? kRectangleSprite : kOutlinedRectangleSprite;
- break;
- case kShapeRoundRect:
- spriteType = sc->_fillType ? kRoundedRectangleSprite : kOutlinedRoundedRectangleSprite;
- break;
- case kShapeOval:
- spriteType = sc->_fillType ? kOvalSprite : kOutlinedOvalSprite;
- break;
- case kShapeLine:
- spriteType = sc->_lineDirection == 6 ? kLineBottomTopSprite : kLineTopBottomSprite;
- break;
- default:
- break;
- }
- if (_vm->getVersion() > 3) {
- foreColor = sc->_fgCol;
- backColor = sc->_bgCol;
- lineSize = sc->_lineThickness;
- ink = sc->_ink;
- }
- }
- break;
- default:
- warning("Score::renderShape(): Unhandled cast type: %d", sp->_cast->_type);
- break;
- }
- }
-
- // for outlined shapes, line thickness of 1 means invisible.
- lineSize -= 1;
-
- Common::Rect shapeRect = _channels[spriteId]->getBbox();
-
- Graphics::ManagedSurface tmpSurface, maskSurface;
- tmpSurface.create(shapeRect.width(), shapeRect.height(), Graphics::PixelFormat::createFormatCLUT8());
- tmpSurface.clear(backColor);
-
- maskSurface.create(shapeRect.width(), shapeRect.height(), Graphics::PixelFormat::createFormatCLUT8());
- maskSurface.clear(0);
-
- // Draw fill
- Common::Rect fillRect((int)shapeRect.width(), (int)shapeRect.height());
- Graphics::MacPlotData plotFill(&tmpSurface, &maskSurface, &_vm->getPatterns(), sp->getPattern(), -shapeRect.left, -shapeRect.top, 1, backColor);
- switch (spriteType) {
- case kRectangleSprite:
- Graphics::drawFilledRect(fillRect, foreColor, Graphics::macDrawPixel, &plotFill);
- break;
- case kRoundedRectangleSprite:
- Graphics::drawRoundRect(fillRect, 12, foreColor, true, Graphics::macDrawPixel, &plotFill);
- break;
- case kOvalSprite:
- Graphics::drawEllipse(fillRect.left, fillRect.top, fillRect.right, fillRect.bottom, foreColor, true, Graphics::macDrawPixel, &plotFill);
- break;
- case kCastMemberSprite: // Face kit D3
- Graphics::drawFilledRect(fillRect, foreColor, Graphics::macDrawPixel, &plotFill);
- break;
- default:
- break;
- }
-
- // Draw stroke
- Common::Rect strokeRect(MAX((int)shapeRect.width() - lineSize, 0), MAX((int)shapeRect.height() - lineSize, 0));
- Graphics::MacPlotData plotStroke(&tmpSurface, &maskSurface, &_vm->getPatterns(), 1, -shapeRect.left, -shapeRect.top, lineSize, backColor);
- switch (spriteType) {
- case kLineTopBottomSprite:
- Graphics::drawLine(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, foreColor, Graphics::macDrawPixel, &plotStroke);
- break;
- case kLineBottomTopSprite:
- Graphics::drawLine(strokeRect.left, strokeRect.bottom, strokeRect.right, strokeRect.top, foreColor, Graphics::macDrawPixel, &plotStroke);
- break;
- case kRectangleSprite:
- // fall through
- case kOutlinedRectangleSprite: // this is actually a mouse-over shape? I don't think it's a real button.
- Graphics::drawRect(strokeRect, foreColor, Graphics::macDrawPixel, &plotStroke);
- break;
- case kRoundedRectangleSprite:
- // fall through
- case kOutlinedRoundedRectangleSprite:
- Graphics::drawRoundRect(strokeRect, 12, foreColor, false, Graphics::macDrawPixel, &plotStroke);
- break;
- case kOvalSprite:
- // fall through
- case kOutlinedOvalSprite:
- Graphics::drawEllipse(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, foreColor, false, Graphics::macDrawPixel, &plotStroke);
- break;
- default:
- break;
- }
-
- inkBasedBlit(surface, &maskSurface, tmpSurface, ink, shapeRect, spriteId);
-}
-
Cast *Score::getCastMember(int castId) {
Cast *result = nullptr;
@@ -809,6 +709,16 @@ bool Score::checkSpriteIntersection(uint16 spriteId, Common::Point pos) {
return false;
}
+Common::List<Channel *> Score::getSpriteIntersections(const Common::Rect &r) {
+ Common::List<Channel *>intersections;
+
+ for (uint i = 0; i < _channels.size(); i++)
+ if (!r.findIntersectingRect(_channels[i]->getBbox()).isEmpty())
+ intersections.push_back(_channels[i]);
+
+ return intersections;
+}
+
Sprite *Score::getSpriteById(uint16 id) {
Channel *channel = getChannelById(id);
diff --git a/engines/director/score.h b/engines/director/score.h
index 2b50328bbe..6d3143fec1 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -25,6 +25,7 @@
#include "common/hash-str.h"
#include "graphics/macgui/macwindowmanager.h"
+#include "director/stage.h"
namespace Graphics {
class ManagedSurface;
@@ -40,6 +41,7 @@ namespace Common {
namespace Director {
+class Stage;
class Archive;
struct CastInfo;
class DirectorEngine;
@@ -51,6 +53,7 @@ struct Resource;
struct Channel;
class Sprite;
class Stxt;
+class Cast;
class BitmapCast;
class ScriptCast;
class ShapeCast;
@@ -63,34 +66,12 @@ enum RenderMode {
kRenderNoUnrender
};
-struct TransParams {
- TransitionType type;
- uint duration;
- uint chunkSize;
- uint area;
-
- int steps;
- int stepDuration;
-
- int xStepSize;
- int yStepSize;
-
- int xpos, ypos;
-
- int stripSize;
-
- TransParams() {
- type = kTransNone;
- duration = 250;
- chunkSize = 1;
- area = 0;
- steps = 0;
- stepDuration = 0;
- stripSize = 0;
-
- xStepSize = yStepSize = 0;
- xpos = ypos = 0;
- }
+struct MacShape {
+ InkType ink;
+ byte spriteType;
+ byte foreColor;
+ byte backColor;
+ int lineSize;
};
struct Channel {
@@ -104,6 +85,10 @@ struct Channel {
Channel(Sprite *sp);
Common::Rect getBbox();
Common::Point getPosition();
+ MacShape *getShape();
+ Graphics::ManagedSurface *getSurface();
+ Graphics::ManagedSurface *getMask();
+
void updateLocation();
void addDelta(Common::Point pos);
void resetPosition();
@@ -139,7 +124,6 @@ public:
void loadSpriteImages(bool isSharedCast);
void loadSpriteSounds(bool isSharedCast);
void copyCastStxts();
- Graphics::ManagedSurface *getSurface() { return _surface; }
Common::Rect getCastMemberInitialRect(int castId);
void setCastMemberModified(int castId);
@@ -150,33 +134,16 @@ public:
uint16 getSpriteIDFromPos(Common::Point pos, bool onlyActive = false);
bool checkSpriteIntersection(uint16 spriteId, Common::Point pos);
+ Common::List<Channel *> getSpriteIntersections(const Common::Rect &r);
Cast *getCastMember(int castId);
const Stxt *getStxt(int castId);
void renderFrame(uint16 frameId, RenderMode mode = kRenderModeNormal);
- void renderSprites(uint16 frameId, Graphics::ManagedSurface *surface, RenderMode mode = kRenderModeNormal);
- void markDirtyRect(Common::Rect dirty);
-
- // transition.cpp
- void playTransition(uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType);
+ void renderSprites(uint16 frameId, RenderMode mode = kRenderModeNormal);
private:
void update();
- void renderShape(uint16 spriteId, Graphics::ManagedSurface *surface);
-
- // ink.cpp
- void inkBasedBlit(Graphics::ManagedSurface *destSurface, Graphics::ManagedSurface *maskSurface, const Graphics::Surface &spriteSurface, InkType ink, Common::Rect drawRect, uint spriteId);
- void drawMatteSprite(Graphics::ManagedSurface *destSurface, const Graphics::Surface &sprite, Common::Rect &drawRect);
- void drawReverseSprite(Graphics::ManagedSurface *destSurface, const Graphics::Surface &sprite, Common::Rect &drawRect, uint16 spriteId);
- // transitions.cpp
- void initTransParams(TransParams &t, Common::Rect &clipRect);
- void dissolveTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);
- void dissolvePatternsTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);
- void transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);
- void transZoom(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);
-
- // score.cpp
void playSoundChannel(uint16 frameId);
void readVersion(uint32 rid);
@@ -203,10 +170,6 @@ public:
Common::HashMap<uint16, Common::String> _actions;
Common::HashMap<uint16, bool> _immediateActions;
Common::HashMap<uint16, Common::String> _fontMap;
- Graphics::ManagedSurface *_surface;
- Graphics::ManagedSurface *_maskSurface;
- Graphics::ManagedSurface *_backSurface;
- Graphics::ManagedSurface *_backSurface2;
Graphics::Font *_font;
Archive *_movieArchive;
Common::Rect _movieRect;
@@ -231,8 +194,6 @@ public:
int _numChannelsDisplayed;
- Graphics::MacWindow *_window;
-
uint16 _framesRan; // used by kDebugFewFramesOnly
int _lingoArchive;
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index da120cff5d..9e3a16ca35 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -93,13 +93,13 @@ void Sprite::updateCast() {
}
bool Sprite::isDirty() {
- return _castType != kCastTypeNull && (_dirty || (_cast && _cast->isModified()));
+ return _castType != kCastTypeNull && (_cast && _cast->isModified());
}
bool Sprite::isActive() {
if (_moveable || _puppet || _scriptId)
return true;
-
+
if (g_lingo->getScriptContext(kArchMain, kCastScript, _castId)
|| g_lingo->getScriptContext(kArchShared, kCastScript, _castId))
return true;
diff --git a/engines/director/stage.cpp b/engines/director/stage.cpp
new file mode 100644
index 0000000000..30f442caff
--- /dev/null
+++ b/engines/director/stage.cpp
@@ -0,0 +1,309 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "graphics/primitives.h"
+
+#include "director/director.h"
+#include "director/stage.h"
+#include "director/score.h"
+#include "director/cast.h"
+#include "director/sprite.h"
+
+#include "common/file.h"
+
+namespace Director {
+
+Stage::Stage(int id, bool scrollable, bool resizable, bool editable, Graphics::MacWindowManager *wm)
+ : MacWindow(id, scrollable, resizable, editable, wm) {
+ _stageColor = 0;
+}
+
+bool Stage::render(bool forceRedraw, Graphics::ManagedSurface *blitTo) {
+ if (!blitTo)
+ blitTo = &_surface;
+
+ if (forceRedraw) {
+ blitTo->clear(_stageColor);
+ _dirtyRects.clear();
+ _dirtyRects.push_back(Common::Rect(_surface.w, _surface.h));
+ } else {
+ if (_dirtyRects.size() == 0)
+ return true;
+
+ mergeDirtyRects();
+ }
+
+ for (Common::List<Common::Rect>::iterator i = _dirtyRects.begin(); i != _dirtyRects.end(); i++) {
+ const Common::Rect &r = *i;
+ blitTo->fillRect(r, _stageColor);
+
+ _dirtyChannels = g_director->getCurrentScore()->getSpriteIntersections(r);
+ for (Common::List<Channel *>::iterator j = _dirtyChannels.begin(); j != _dirtyChannels.end(); j++)
+ inkBlitFrom(*j, r, blitTo);
+ }
+
+ _dirtyRects.clear();
+ _contentIsDirty = true;
+
+ return true;
+}
+
+void Stage::setStageColor(uint stageColor) {
+ if (stageColor != _stageColor) {
+ _stageColor = stageColor;
+ reset();
+ }
+}
+
+void Stage::reset() {
+ _surface.clear(_stageColor);
+ _contentIsDirty = true;
+}
+
+void Stage::addDirtyRect(const Common::Rect &r) {
+ Common::Rect bounds = r;
+ bounds.clip(_dims);
+
+ if (bounds.width() > 0 && bounds.height() > 0)
+ _dirtyRects.push_back(bounds);
+}
+
+void Stage::mergeDirtyRects() {
+ Common::List<Common::Rect>::iterator rOuter, rInner;
+
+ // Process the dirty rect list to find any rects to merge
+ for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
+ rInner = rOuter;
+ while (++rInner != _dirtyRects.end()) {
+
+ if ((*rOuter).intersects(*rInner)) {
+ // These two rectangles overlap, so merge them
+ unionRectangle(*rOuter, *rOuter, *rInner);
+
+ // remove the inner rect from the list
+ _dirtyRects.erase(rInner);
+
+ // move back to beginning of list
+ rInner = rOuter;
+ }
+ }
+ }
+}
+
+bool Stage::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
+ destRect = src1;
+ destRect.extend(src2);
+
+ return !destRect.isEmpty();
+}
+
+void Stage::inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::ManagedSurface *blitTo) {
+ Common::Rect srcRect = channel->getBbox();
+ destRect.clip(srcRect);
+
+ Sprite *sprite = channel->_sprite;
+ MacShape *ms = channel->getShape();
+ DirectorPlotData pd(_wm, channel->getSurface(), blitTo, sprite->_ink, sprite->_backColor, g_director->getPaletteColorCount());
+ pd.destRect = destRect;
+
+ // Shapes do not have surfaces of their own, so draw the shape directly upon
+ // stage surface.
+ if (ms) {
+ if (ms->foreColor == ms->backColor)
+ return;
+
+ Common::Rect fillRect((int)srcRect.width(), (int)srcRect.height());
+ fillRect.moveTo(srcRect.left, srcRect.top);
+ Graphics::MacPlotData plotFill(blitTo, nullptr, &g_director->getPatterns(), sprite->getPattern(), srcRect.left, srcRect.top, 1, ms->backColor);
+
+ Common::Rect strokeRect(MAX((int)srcRect.width() - ms->lineSize, 0), MAX((int)srcRect.height() - ms->lineSize, 0));
+ strokeRect.moveTo(srcRect.left, srcRect.top);
+ Graphics::MacPlotData plotStroke(blitTo, nullptr, &g_director->getPatterns(), 1, strokeRect.left, strokeRect.top, ms->lineSize, ms->backColor);
+
+ switch (ms->spriteType) {
+ case kRectangleSprite:
+ pd.macPlot = &plotFill;
+ Graphics::drawFilledRect(fillRect, ms->foreColor, inkDrawPixel, &pd);
+ // fall through
+ case kOutlinedRectangleSprite:
+ pd.macPlot = &plotStroke;
+ Graphics::drawRect(strokeRect, ms->foreColor, inkDrawPixel, &pd);
+ break;
+ case kRoundedRectangleSprite:
+ pd.macPlot = &plotFill;
+ Graphics::drawRoundRect(fillRect, 12, ms->foreColor, true, inkDrawPixel, &pd);
+ // fall through
+ case kOutlinedRoundedRectangleSprite:
+ pd.macPlot = &plotStroke;
+ Graphics::drawRoundRect(strokeRect, 12, ms->foreColor, false, inkDrawPixel, &pd);
+ break;
+ case kOvalSprite:
+ pd.macPlot = &plotFill;
+ Graphics::drawEllipse(fillRect.left, fillRect.top, fillRect.right, fillRect.bottom, ms->foreColor, true, inkDrawPixel, &plotFill);
+ // fall through
+ case kOutlinedOvalSprite:
+ pd.macPlot = &plotStroke;
+ Graphics::drawEllipse(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, ms->foreColor, false, inkDrawPixel, &plotStroke);
+ break;
+ case kLineTopBottomSprite:
+ pd.macPlot = &plotStroke;
+ Graphics::drawLine(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, ms->foreColor, inkDrawPixel, &plotStroke);
+ break;
+ case kLineBottomTopSprite:
+ pd.macPlot = &plotStroke;
+ Graphics::drawLine(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, ms->foreColor, inkDrawPixel, &plotStroke);
+ break;
+ default:
+ warning("Stage::inkBlitFrom: Expected shape type but got type %d", ms->spriteType);
+ }
+
+ delete ms;
+ return;
+ }
+
+ // Otherwise, we are drawing a cast type that does have a built-in surface, so
+ // blit from that.
+ // TODO: Work these ink types into inkDrawPixel.
+ if (sprite->_ink == kInkTypeMatte) {
+ drawMatteSprite(channel, srcRect, destRect, blitTo);
+ return;
+ } else if (sprite->_ink == kInkTypeReverse) {
+ drawReverseSprite(channel, srcRect, destRect, blitTo);
+ return;
+ }
+ // Otherwise, fall through to inkDrawPixel
+
+ pd.srcPoint.y = MAX(abs(srcRect.top - destRect.top), 0);
+ for (int i = 0; i < destRect.height(); i++, pd.srcPoint.y++) {
+ pd.srcPoint.x = MAX(abs(srcRect.left - destRect.left), 0);
+
+ for (int j = 0; j < destRect.width(); j++, pd.srcPoint.x++)
+ inkDrawPixel(destRect.left + j, destRect.top + i, 0, &pd);
+ }
+}
+
+void Stage::drawMatteSprite(Channel *channel, Common::Rect &srcRect, Common::Rect &destRect, Graphics::ManagedSurface *blitTo) {
+ // Like background trans, but all white pixels NOT ENCLOSED by coloured pixels are transparent
+ Graphics::Surface tmp;
+ tmp.create(destRect.width(), destRect.height(), Graphics::PixelFormat::createFormatCLUT8());
+ tmp.copyFrom(channel->getSurface()->rawSurface());
+
+ if (!blitTo->clip(srcRect, destRect))
+ return; // Out of screen
+
+ // Searching white color in the corners
+ int whiteColor = -1;
+
+ for (int y = 0; y < tmp.h; y++) {
+ for (int x = 0; x < tmp.w; x++) {
+ byte color = *(byte *)tmp.getBasePtr(x, y);
+
+ if (g_director->getPalette()[color * 3 + 0] == 0xff &&
+ g_director->getPalette()[color * 3 + 1] == 0xff &&
+ g_director->getPalette()[color * 3 + 2] == 0xff) {
+ whiteColor = color;
+ break;
+ }
+ }
+ }
+
+ if (whiteColor == -1) {
+ debugC(1, kDebugImages, "Score::drawMatteSprite(): No white color for Matte image");
+
+ for (int yy = 0; yy < destRect.height(); yy++) {
+ const byte *src = (const byte *)channel->getSurface()->getBasePtr(MAX(abs(srcRect.left - destRect.left), 0), MAX(abs(srcRect.top - destRect.top + yy), 0));
+ byte *dst = (byte *)blitTo->getBasePtr(destRect.left, destRect.top + yy);
+
+ for (int xx = 0; xx < destRect.width(); xx++, src++, dst++)
+ *dst = *src;
+ }
+ } else {
+ Graphics::FloodFill ff(&tmp, whiteColor, 0, true);
+
+ for (int yy = 0; yy < tmp.h; yy++) {
+ ff.addSeed(0, yy);
+ ff.addSeed(tmp.w - 1, yy);
+ }
+
+ for (int xx = 0; xx < tmp.w; xx++) {
+ ff.addSeed(xx, 0);
+ ff.addSeed(xx, tmp.h - 1);
+ }
+ ff.fillMask();
+
+ for (int yy = 0; yy < destRect.height(); yy++) {
+ const byte *mask = (const byte *)ff.getMask()->getBasePtr(MAX(abs(srcRect.left - destRect.left), 0), MAX(abs(srcRect.top - destRect.top - yy), 0));
+ const byte *src = (const byte *)channel->getSurface()->getBasePtr(MAX(abs(srcRect.left - destRect.left), 0), MAX(abs(srcRect.top - destRect.top - yy), 0));
+ byte *dst = (byte *)blitTo->getBasePtr(destRect.left, destRect.top + yy);
+
+ for (int xx = 0; xx < destRect.width(); xx++, src++, dst++, mask++)
+ if (*mask == 0)
+ *dst = *src;
+ }
+ }
+
+ tmp.free();
+}
+
+void Stage::drawReverseSprite(Channel *channel, Common::Rect &srcRect, Common::Rect &destRect, Graphics::ManagedSurface *blitTo) {
+ uint8 skipColor = g_director->getPaletteColorCount() - 1;
+ for (int ii = 0; ii < destRect.height(); ii++) {
+ const byte *src = (const byte *)channel->getSurface()->getBasePtr(MAX(abs(srcRect.left - destRect.left), 0), MAX(abs(srcRect.top - destRect.top - ii), 0));
+ byte *dst = (byte *)blitTo->getBasePtr(destRect.left, destRect.top + ii);
+ byte srcColor = *src;
+
+ for (int j = 0; j < destRect.width(); j++, src++, dst++) {
+ if (!channel->_sprite->_cast || channel->_sprite->_cast->_type == kCastShape)
+ srcColor = 0x0;
+ else
+ srcColor = *src;
+ uint16 targetSprite = g_director->getCurrentScore()->getSpriteIDFromPos(Common::Point(destRect.left + j, destRect.top + ii));
+ if ((targetSprite != 0)) {
+ // TODO: This entire reverse colour attempt needs a lot more testing on
+ // a lot more colour depths.
+ if (srcColor != skipColor) {
+ if (!g_director->getCurrentScore()->_channels[targetSprite]->_sprite->_cast || g_director->getCurrentScore()->_channels[targetSprite]->_sprite->_cast->_type != kCastBitmap) {
+ if (*dst == 0 || *dst == 255) {
+ *dst = g_director->transformColor(*dst);
+ } else if (srcColor == 255 || srcColor == 0) {
+ *dst = g_director->transformColor(*dst - 40);
+ } else {
+ *dst = g_director->transformColor(*src - 40);
+ }
+ } else {
+ if (*dst == 0 && g_director->getVersion() == 3 &&
+ g_director->getCurrentScore()->_channels[targetSprite]->_sprite->_cast->_type == kCastBitmap &&
+ ((BitmapCast*)g_director->getCurrentScore()->_channels[targetSprite]->_sprite->_cast)->_bitsPerPixel > 1) {
+ *dst = g_director->transformColor(*src - 40);
+ } else {
+ *dst ^= g_director->transformColor(srcColor);
+ }
+ }
+ }
+ } else if (srcColor != skipColor) {
+ *dst = g_director->transformColor(srcColor);
+ }
+ }
+ }
+}
+
+} // end of namespace Director
diff --git a/engines/director/stage.h b/engines/director/stage.h
new file mode 100644
index 0000000000..9495afbabc
--- /dev/null
+++ b/engines/director/stage.h
@@ -0,0 +1,107 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef DIRECTOR_STAGE_H
+#define DIRECTOR_STAGE_H
+
+#include "graphics/macgui/macwindowmanager.h"
+#include "graphics/macgui/macwindow.h"
+
+#include "director/types.h"
+
+namespace Graphics {
+class ManagedSurface;
+class MacWindow;
+class MacWindowManager;
+}
+
+namespace Director {
+
+struct Channel;
+
+struct TransParams {
+ TransitionType type;
+ uint frame;
+ uint duration;
+ uint chunkSize;
+ uint area;
+
+ int steps;
+ int stepDuration;
+
+ int xStepSize;
+ int yStepSize;
+
+ int xpos, ypos;
+
+ int stripSize;
+
+ TransParams() {
+ type = kTransNone;
+ frame = 0;
+ duration = 250;
+ chunkSize = 1;
+ area = 0;
+ steps = 0;
+ stepDuration = 0;
+ stripSize = 0;
+
+ xStepSize = yStepSize = 0;
+ xpos = ypos = 0;
+ }
+};
+
+class Stage : public Graphics::MacWindow {
+ public:
+ Stage(int id, bool scrollable, bool resizable, bool editable, Graphics::MacWindowManager *wm);
+ // ~Stage();
+
+ bool render(bool forceRedraw = false, Graphics::ManagedSurface *blitTo = nullptr);
+
+ bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
+ void setStageColor(uint stageColor);
+ void addDirtyRect(const Common::Rect &r);
+ void mergeDirtyRects();
+ void reset();
+
+ // transitions.cpp
+ void playTransition(uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType, uint frame);
+ void initTransParams(TransParams &t, Common::Rect &clipRect);
+ void dissolveTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);
+ void dissolvePatternsTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);
+ void transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);
+ void transZoom(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);
+
+public:
+ Common::List<Common::Rect> _dirtyRects;
+ Common::List<Channel *> _dirtyChannels;
+
+private:
+ uint _stageColor;
+ void inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::ManagedSurface *blitTo = nullptr);
+ void drawReverseSprite(Channel *channel, Common::Rect &srcRect, Common::Rect &destRect, Graphics::ManagedSurface *blitTo);
+ void drawMatteSprite(Channel *channel, Common::Rect &srcRect, Common::Rect &destRect, Graphics::ManagedSurface *blitTo);
+};
+
+} // end of namespace Director
+
+#endif
diff --git a/engines/director/transitions.cpp b/engines/director/transitions.cpp
index 0f9a417db7..ea20975d40 100644
--- a/engines/director/transitions.cpp
+++ b/engines/director/transitions.cpp
@@ -131,16 +131,13 @@ struct {
TRANS(kTransDissolveBits, kTransAlgoDissolve, kTransDirNone)
};
-void Score::playTransition(uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType) {
+void Stage::playTransition(uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType, uint frame) {
// Play a transition and return the number of subframes rendered
-
- if (!_surface)
- return;
-
TransParams t;
t.type = transType;
t.duration = MAX<uint16>(250, transDuration); // When duration is < 1/4s, make it 1/4
+ t.frame = frame;
t.chunkSize = MAX<uint>(1, transChunkSize);
t.area = MAX<uint>(0, transArea);
@@ -149,18 +146,18 @@ void Score::playTransition(uint16 transDuration, uint8 transArea, uint8 transChu
t.duration = 250;
// Cache a copy of the frame before the transition.
- Graphics::ManagedSurface *currentFrame = new Graphics::ManagedSurface(_movieRect.width(), _movieRect.height());
- currentFrame->copyFrom(*_surface);
+ Graphics::ManagedSurface *currentFrame = new Graphics::ManagedSurface(_surface.w, _surface.h);
+ currentFrame->copyFrom(_surface);
// If a transition is being played, render the frame after the transition.
- Graphics::ManagedSurface *nextFrame = new Graphics::ManagedSurface(_movieRect.width(), _movieRect.height());
- nextFrame->clear(_stageColor);
- renderSprites(_currentFrame, nextFrame, kRenderNoUnrender);
+ Graphics::ManagedSurface *nextFrame = new Graphics::ManagedSurface(_surface.w, _surface.h);
+ g_director->getCurrentScore()->renderSprites(t.frame, kRenderForceUpdate);
+ render(true, nextFrame);
if (t.area)
warning("STUB: Transition over changed area transition");
- Common::Rect clipRect(_movieRect);
+ Common::Rect clipRect(_dims);
clipRect.moveTo(0, 0);
Common::Rect rfrom, rto;
@@ -216,7 +213,7 @@ void Score::playTransition(uint16 transDuration, uint8 transArea, uint8 transChu
if (transProps[t.type].algo == kTransAlgoReveal ||
transProps[t.type].algo == kTransAlgoEdgesIn) {
- _surface->copyFrom(*nextFrame);
+ _surface.copyFrom(*nextFrame);
}
switch (t.type) {
@@ -286,7 +283,7 @@ void Score::playTransition(uint16 transDuration, uint8 transArea, uint8 transChu
case kTransPushLeft: // 11
rto.moveTo(w - t.xStepSize * i, 0);
- _surface->blitFrom(*nextFrame, rfrom, Common::Point(rto.left, rto.top));
+ _surface.blitFrom(*nextFrame, rfrom, Common::Point(rto.left, rto.top));
rfrom.moveTo(t.xStepSize * i, 0);
rfrom.setWidth(w - t.xStepSize * i);
@@ -296,7 +293,7 @@ void Score::playTransition(uint16 transDuration, uint8 transArea, uint8 transChu
case kTransPushRight: // 12
rfrom.moveTo(w - t.xStepSize * i, 0);
rfrom.setWidth(t.xStepSize * i);
- _surface->blitFrom(*nextFrame, rfrom, Common::Point(rto.left, rto.top));
+ _surface.blitFrom(*nextFrame, rfrom, Common::Point(rto.left, rto.top));
rto.setWidth(w - t.xStepSize * i);
rto.moveTo(t.xStepSize * i, 0);
@@ -307,7 +304,7 @@ void Score::playTransition(uint16 transDuration, uint8 transArea, uint8 transChu
case kTransPushDown: // 13
rfrom.moveTo(0, h - t.yStepSize * i);
rfrom.setHeight(t.yStepSize * i);
- _surface->blitFrom(*nextFrame, rfrom, Common::Point(rto.left, rto.top));
+ _surface.blitFrom(*nextFrame, rfrom, Common::Point(rto.left, rto.top));
rto.setHeight(h - t.yStepSize * i);
rto.moveTo(0, t.yStepSize * i);
@@ -317,7 +314,7 @@ void Score::playTransition(uint16 transDuration, uint8 transArea, uint8 transChu
case kTransPushUp: // 14
rto.moveTo(0, h - t.yStepSize * i);
- _backSurface->blitFrom(*nextFrame, rfrom, Common::Point(rto.left, rto.top));
+ _surface.blitFrom(*nextFrame, rfrom, Common::Point(rto.left, rto.top));
rfrom.moveTo(0, t.yStepSize * i);
rfrom.setHeight(h - t.yStepSize * i);
@@ -435,25 +432,24 @@ void Score::playTransition(uint16 transDuration, uint8 transArea, uint8 transChu
if (stop)
break;
- _surface->blitFrom(*blitFrom, rfrom, Common::Point(rto.left, rto.top));
+ _surface.blitFrom(*blitFrom, rfrom, Common::Point(rto.left, rto.top));
g_system->delayMillis(t.stepDuration);
if (processQuitEvent(true))
break;
if (fullredraw) {
- g_system->copyRectToScreen(_surface->getPixels(), _surface->pitch, 0, 0, w, h);
+ g_system->copyRectToScreen(_surface.getPixels(), _surface.pitch, 0, 0, w, h);
} else {
rto.clip(clipRect);
if (rto.height() > 0 && rto.width() > 0) {
- g_system->copyRectToScreen(_surface->getBasePtr(rto.left, rto.top), _surface->pitch, rto.left, rto.top, rto.width(), rto.height());
+ g_system->copyRectToScreen(_surface.getBasePtr(rto.left, rto.top), _surface.pitch, rto.left, rto.top, rto.width(), rto.height());
}
}
g_system->updateScreen();
-
- g_lingo->executePerFrameHook(_currentFrame, i);
+ g_lingo->executePerFrameHook(t.frame, i);
}
delete currentFrame;
@@ -481,7 +477,7 @@ static uint32 randomSeed[33] = {
0x14000000UL, 0x32800000UL, 0x48000000UL, 0xa3000000UL
};
-void Score::dissolveTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *nextFrame) {
+void Stage::dissolveTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *nextFrame) {
uint w = clipRect.width();
uint h = clipRect.height();
uint realw = w, realh = h;
@@ -603,13 +599,13 @@ void Score::dissolveTrans(TransParams &t, Common::Rect &clipRect, Graphics::Mana
if (x < realw && y < realh) {
r.moveTo(x, y);
r.clip(clipRect);
- _surface->copyRectToSurface(*nextFrame, x, y, r);
+ _surface.copyRectToSurface(*nextFrame, x, y, r);
}
} else {
mask = pixmask[x % -t.xStepSize];
x = x / -t.xStepSize;
- byte *color1 = (byte *)_surface->getBasePtr(x, y);
+ byte *color1 = (byte *)_surface.getBasePtr(x, y);
byte *color2 = (byte *)nextFrame->getBasePtr(x, y);
*color1 = ((*color1 & ~mask) | (*color2 & mask)) & 0xff;
@@ -625,10 +621,10 @@ void Score::dissolveTrans(TransParams &t, Common::Rect &clipRect, Graphics::Mana
}
} while (rnd != seed);
- g_system->copyRectToScreen(_surface->getPixels(), _surface->pitch, 0, 0, realw, realh);
+ g_system->copyRectToScreen(_surface.getPixels(), _surface.pitch, 0, 0, realw, realh);
g_system->updateScreen();
- g_lingo->executePerFrameHook(_currentFrame, i + 1);
+ g_lingo->executePerFrameHook(t.frame, i + 1);
if (processQuitEvent(true))
break;
@@ -704,7 +700,7 @@ static byte dissolvePatterns[][8] = {
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
};
-void Score::dissolvePatternsTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *nextFrame) {
+void Stage::dissolvePatternsTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *nextFrame) {
uint w = clipRect.width();
uint h = clipRect.height();
@@ -714,7 +710,7 @@ void Score::dissolvePatternsTrans(TransParams &t, Common::Rect &clipRect, Graphi
for (int i = 0; i < t.steps; i++) {
for (uint y = 0; y < h; y++) {
byte pat = dissolvePatterns[i][y % 8];
- byte *dst = (byte *)_surface->getBasePtr(0, y);
+ byte *dst = (byte *)_surface.getBasePtr(0, y);
byte *src = (byte *)nextFrame->getBasePtr(0, y);
for (uint x = 0; x < w;) {
@@ -730,10 +726,10 @@ void Score::dissolvePatternsTrans(TransParams &t, Common::Rect &clipRect, Graphi
}
}
- g_system->copyRectToScreen(_surface->getPixels(), _surface->pitch, 0, 0, w, h);
+ g_system->copyRectToScreen(_surface.getPixels(), _surface.pitch, 0, 0, w, h);
g_system->updateScreen();
- g_lingo->executePerFrameHook(_currentFrame, i + 1);
+ g_lingo->executePerFrameHook(t.frame, i + 1);
if (processQuitEvent(true))
break;
@@ -742,7 +738,7 @@ void Score::dissolvePatternsTrans(TransParams &t, Common::Rect &clipRect, Graphi
}
}
-void Score::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *nextFrame) {
+void Stage::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *nextFrame) {
Common::Rect rto;
uint w = clipRect.width();
uint h = clipRect.height();
@@ -897,15 +893,15 @@ void Score::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::Man
rto.clip(clipRect);
if (rto.height() > 0 && rto.width() > 0) {
- _surface->blitFrom(*nextFrame, rto, Common::Point(rto.left, rto.top));
- g_system->copyRectToScreen(_surface->getBasePtr(rto.left, rto.top), _surface->pitch, rto.left, rto.top, rto.width(), rto.height());
+ _surface.blitFrom(*nextFrame, rto, Common::Point(rto.left, rto.top));
+ g_system->copyRectToScreen(_surface.getBasePtr(rto.left, rto.top), _surface.pitch, rto.left, rto.top, rto.width(), rto.height());
}
}
rects.clear();
g_system->updateScreen();
- g_lingo->executePerFrameHook(_currentFrame, i);
+ g_lingo->executePerFrameHook(t.frame, i);
g_system->delayMillis(t.stepDuration);
if (processQuitEvent(true))
@@ -914,14 +910,14 @@ void Score::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::Man
}
}
-void Score::transZoom(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *nextFrame) {
+void Stage::transZoom(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *nextFrame) {
Common::Rect r = clipRect;
uint w = clipRect.width();
uint h = clipRect.height();
t.steps += 2;
- Graphics::MacPlotData pd(_surface, nullptr, &g_director->_wm->getPatterns(), Graphics::kPatternCheckers, 0, 0, 1, 0);
+ Graphics::MacPlotData pd(&_surface, nullptr, &g_director->_wm->getPatterns(), Graphics::kPatternCheckers, 0, 0, 1, 0);
for (uint16 i = 1; i < t.steps; i++) {
@@ -949,10 +945,10 @@ void Score::transZoom(TransParams &t, Common::Rect &clipRect, Graphics::ManagedS
r.setWidth(t.xStepSize * i * 2);
r.moveTo(w / 2 - t.xStepSize * i, h / 2 - t.yStepSize * i);
- g_system->copyRectToScreen(_surface->getPixels(), _surface->pitch, 0, 0, w, h);
+ g_system->copyRectToScreen(_surface.getPixels(), _surface.pitch, 0, 0, w, h);
g_system->updateScreen();
- g_lingo->executePerFrameHook(_currentFrame, i);
+ g_lingo->executePerFrameHook(t.frame, i);
g_system->delayMillis(t.stepDuration);
if (processQuitEvent(true))
@@ -960,7 +956,7 @@ void Score::transZoom(TransParams &t, Common::Rect &clipRect, Graphics::ManagedS
}
}
-void Score::initTransParams(TransParams &t, Common::Rect &clipRect) {
+void Stage::initTransParams(TransParams &t, Common::Rect &clipRect) {
int w = clipRect.width();
int h = clipRect.height();
int m = MIN(w, h);
Commit: 30bd4de3a7b8d6e06886acad0a90083330ae091a
https://github.com/scummvm/scummvm/commit/30bd4de3a7b8d6e06886acad0a90083330ae091a
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-06-30T12:38:46-04:00
Commit Message:
Revert "GRAPHICS: MACGUI: Add QuickDraw class"
This reverts commit 3469ed858c47a8a0ce3c1eb192d2a494bdf5ba02.
Changed paths:
R graphics/macgui/macshape.cpp
R graphics/macgui/macshape.h
graphics/module.mk
diff --git a/graphics/macgui/macshape.cpp b/graphics/macgui/macshape.cpp
deleted file mode 100644
index ad74fba90d..0000000000
--- a/graphics/macgui/macshape.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "graphics/macgui/macwindowmanager.h"
-#include "graphics/macgui/macshape.h"
-#include "graphics/primitives.h"
-
-namespace Graphics {
-
-MacShape::MacShape(MacShapeType shapeType, MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, uint fgcolor, uint bgcolor, uint thickness, uint fillType) : _shapeType(shapeType), _thickness(thickness), _fillType(fillType), MacWidget(parent, x, y, w, h, wm, false, 0, 0, 0, fgcolor, bgcolor) {
- _contentIsDirty = true;
- render();
- }
-
-void MacShape::setStyle(MacShapeType shapeType, uint fgcolor, uint bgcolor, uint thickness, uint fillType) {
- _contentIsDirty = true;
-
- _shapeType = shapeType;
- _fgcolor = fgcolor;
- _bgcolor = bgcolor;
- _thickness = thickness;
- _fillType = fillType;
-}
-
-void MacShape::render() {
- if (!_contentIsDirty)
- return;
-
- _maskSurface->clear(0);
- _composeSurface->clear(_bgcolor);
-
- Common::Rect fillRect((int)_dims.width(), (int)_dims.height());
- Graphics::MacPlotData plotFill(_composeSurface, _maskSurface, &_wm->getPatterns(), _fillType, -_dims.left, -_dims.top, 1, _bgcolor);
-
- Common::Rect strokeRect(MAX((int)_dims.width() - _thickness, 0), MAX((int)_dims.height() - _thickness, 0));
- Graphics::MacPlotData plotStroke(_composeSurface, _maskSurface, &_wm->getPatterns(), 1, -_dims.left, -_dims.top, _thickness, _bgcolor);
-
- switch (_shapeType) {
- case kShapeRectangle:
- if (_fillType)
- Graphics::drawFilledRect(fillRect, _fgcolor, Graphics::macDrawPixel, &plotFill);
-
- Graphics::drawRect(strokeRect, _fgcolor, Graphics::macDrawPixel, &plotStroke);
- break;
-
- case kShapeRoundRect:
- if (_fillType)
- Graphics::drawRoundRect(fillRect, 12, _fgcolor, true, Graphics::macDrawPixel, &plotFill);
-
- Graphics::drawRoundRect(strokeRect, 12, _fgcolor, false, Graphics::macDrawPixel, &plotStroke);
- break;
-
- case kShapeOval:
- if (_fillType)
- Graphics::drawEllipse(fillRect.left, fillRect.top, fillRect.right, fillRect.bottom, _fgcolor, true, Graphics::macDrawPixel, &plotFill);
-
- Graphics::drawEllipse(strokeRect.left, strokeRect.top, strokeRect.right, strokeRect.bottom, _fgcolor, false, Graphics::macDrawPixel, &plotStroke);
- break;
-
- case kShapeLine:
- warning("MacShape::render(): Line drawing not yet implemented");
- break;
- }
-
- _contentIsDirty = true;
-}
-
-} // end of namespace Graphics
diff --git a/graphics/macgui/macshape.h b/graphics/macgui/macshape.h
deleted file mode 100644
index a47d69a99d..0000000000
--- a/graphics/macgui/macshape.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef GRAPHICS_MACGUI_MACSHAPE_H
-#define GRAPHICS_MACGUI_MACSHAPE_H
-
-#include "graphics/macgui/macwidget.h"
-
-namespace Graphics {
-
-enum MacShapeType {
- kShapeRectangle,
- kShapeRoundRect,
- kShapeOval,
- kShapeLine
-};
-
-class MacShape : public MacWidget {
-public:
- MacShape(MacShapeType shapeType, MacWidget *parent, int x, int y, int w, int h, MacWindowManager *wm, uint fgcolor, uint bgcolor, uint thickness, uint fillType);
-
- void setStyle(MacShapeType shapeType, uint fgcolor, uint bgcolor, uint thickness, uint fillType);
- void render();
-
-private:
- MacShapeType _shapeType;
- int _thickness;
- uint _fillType;
-};
-
-} // end of namespace Graphics
-
-#endif
diff --git a/graphics/module.mk b/graphics/module.mk
index 4a8ba148a7..142a2aab21 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -19,7 +19,6 @@ MODULE_OBJS := \
macgui/macmenu.o \
macgui/mactext.o \
macgui/mactextwindow.o \
- macgui/macshape.o \
macgui/macwidget.o \
macgui/macwindow.o \
macgui/macwindowborder.o \
Commit: 1ddc4bf6bde5f791a14261b91e15eab09cb024ce
https://github.com/scummvm/scummvm/commit/1ddc4bf6bde5f791a14261b91e15eab09cb024ce
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-06-30T12:38:46-04:00
Commit Message:
GRAPHICS: MACGUI: MacButton: Properly mark dirty button states
Changed paths:
graphics/macgui/macbutton.cpp
diff --git a/graphics/macgui/macbutton.cpp b/graphics/macgui/macbutton.cpp
index 6b413dece3..9b32f096d1 100644
--- a/graphics/macgui/macbutton.cpp
+++ b/graphics/macgui/macbutton.cpp
@@ -85,6 +85,8 @@ void MacButton::invertOuter() {
Graphics::drawEllipse(r.left + 1, r.top + 3, r.left + 10, r.top + 12, 0, false, Graphics::macInvertPixel, _composeSurface);
break;
}
+
+ _contentIsDirty = true;
}
void MacButton::invertInner() {
@@ -102,10 +104,12 @@ void MacButton::invertInner() {
Graphics::drawEllipse(r.left + 3, r.top + 5, r.left + 8, r.top + 10, 0, true, Graphics::macInvertPixel, _composeSurface);
break;
}
+
+ _contentIsDirty = true;
}
bool MacButton::draw(bool forceRedraw) {
- if (!_contentIsDirty && !forceRedraw)
+ if ((!_contentIsDirty && !forceRedraw) || _active)
return false;
_maskSurface->clear(1);
Commit: 93a5c39381ca71b0f2b3e69e2a43c607b0150628
https://github.com/scummvm/scummvm/commit/93a5c39381ca71b0f2b3e69e2a43c607b0150628
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-06-30T12:38:46-04:00
Commit Message:
DIRECTOR: Cache widgets for all loaded cast
Changed paths:
engines/director/cast.cpp
engines/director/cast.h
engines/director/score-loading.cpp
engines/director/score.h
engines/director/sprite.cpp
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 21f8fcf035..677bb58f78 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -44,11 +44,6 @@ Cast::Cast() {
_modified = true;
}
-void Cast::createWidget() {
- if (_widget)
- error("TextCast::createWidget: Attempted to create widget twice");
-}
-
BitmapCast::BitmapCast(Common::ReadStreamEndian &stream, uint32 castTag, uint16 version) {
_type = kCastBitmap;
_img = nullptr;
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 2b9a0120e4..061ae35fee 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -57,7 +57,7 @@ public:
virtual bool isEditable() { return false; }
virtual bool setEditable(bool editable) { return false; }
virtual bool isModified() { return _modified; }
- virtual void createWidget();
+ virtual void createWidget() {}
virtual void setColors(int *fgcolor, int *bgcolor) { return; }
virtual void getColors(int *fgcolor, int *bgcolor) { return; }
diff --git a/engines/director/score-loading.cpp b/engines/director/score-loading.cpp
index 175ccf982a..a2fb75083a 100644
--- a/engines/director/score-loading.cpp
+++ b/engines/director/score-loading.cpp
@@ -267,6 +267,7 @@ bool Score::loadArchive(bool isSharedCast) {
loadSpriteImages(isSharedCast);
loadSpriteSounds(isSharedCast);
+ createCastWidgets();
setSpriteCasts();
return true;
@@ -292,6 +293,15 @@ void Score::copyCastStxts() {
}
}
+void Score::createCastWidgets() {
+ for (Common::HashMap<int, Cast *>::iterator c = _loadedCast->begin(); c != _loadedCast->end(); ++c) {
+ if (!c->_value)
+ continue;
+
+ c->_value->createWidget();
+ }
+}
+
void Score::loadSpriteImages(bool isSharedCast) {
debugC(1, kDebugLoading, "****** Preloading sprite images");
diff --git a/engines/director/score.h b/engines/director/score.h
index 6d3143fec1..9b16890aa1 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -124,6 +124,7 @@ public:
void loadSpriteImages(bool isSharedCast);
void loadSpriteSounds(bool isSharedCast);
void copyCastStxts();
+ void createCastWidgets();
Common::Rect getCastMemberInitialRect(int castId);
void setCastMemberModified(int castId);
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 9e3a16ca35..84e3c54aed 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -76,18 +76,6 @@ void Sprite::updateCast() {
if (!_cast)
return;
- if (!_cast->_widget) {
- if (_cast->_type == kCastText && (_spriteType == kButtonSprite || _spriteType == kCheckboxSprite || _spriteType == kRadioButtonSprite)) {
- // WORKAROUND: In D2/D3 there can be text casts that have button
- // information set in the sprite.
- warning("Sprite::updateCast: Working around D2/3 button glitch");
- _cast->_type = kCastButton;
- ((TextCast *)_cast)->_buttonType = (ButtonType)(_spriteType - 8);
- }
-
- _cast->createWidget();
- }
-
if (_cast->isEditable() != _editable && !_puppet)
_cast->setEditable(_editable);
}
@@ -171,9 +159,21 @@ void Sprite::setCast(uint16 castId) {
if (castId == 0)
return;
- if (member)
+ if (member) {
_cast = member;
- else {
+
+ if (_cast->_type == kCastText &&
+ (_spriteType == kButtonSprite || _spriteType == kCheckboxSprite || _spriteType == kRadioButtonSprite)) {
+ // WORKAROUND: In D2/D3 there can be text casts that have button
+ // information set in the sprite.
+ warning("Sprite::updateCast: Working around D2/3 button glitch");
+
+ delete _cast->_widget;
+ _cast->_type = kCastButton;
+ ((TextCast *)_cast)->_buttonType = (ButtonType)(_spriteType - 8);
+ ((TextCast *)_cast)->createWidget();
+ }
+ } else {
warning("Sprite::setCast: Cast id %d has null member", castId);
}
Commit: 487dcec139c22354b6d4185e4bab49480f3b9d54
https://github.com/scummvm/scummvm/commit/487dcec139c22354b6d4185e4bab49480f3b9d54
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-06-30T12:38:46-04:00
Commit Message:
DIRECTOR: Remove shape cast hack
Changed paths:
engines/director/sprite.cpp
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 84e3c54aed..1bcb88529c 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -202,8 +202,6 @@ void Sprite::setCast(uint16 castId) {
}
} else {
_castType = kCastShape;
-
- g_director->getCurrentScore()->_loadedCast->setVal(_castId, new ShapeCast());
}
break;
case kTextSprite:
Commit: 713f9f2624f048d725c2389d6aeae9747c2ad032
https://github.com/scummvm/scummvm/commit/713f9f2624f048d725c2389d6aeae9747c2ad032
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-06-30T12:38:46-04:00
Commit Message:
DIRECTOR: Unify sprite and channel internal rendering methods
Now we only need to check with the channel to see if its contents need to be
re-rendered, and the channel takes care of updating its internal locations, as
well as those of the widgets.
Changed paths:
engines/director/lingo/lingo-the.cpp
engines/director/score.cpp
engines/director/score.h
engines/director/sprite.cpp
engines/director/sprite.h
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 6f3d25f0b8..acdbcc952e 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -927,7 +927,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
default:
warning("Lingo::setTheSprite(): Unprocessed setting field \"%s\" of sprite", field2str(field));
}
- sprite->_dirty = true;
+ channel->_dirty = true;
}
Datum Lingo::getTheCast(Datum &id1, int field) {
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 2fd6e41301..f5ce27f522 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -53,6 +53,7 @@ Channel::Channel(Sprite *sp) {
_constraint = 0;
_visible = true;
+ _dirty = true;
if (_sprite && _sprite->_castType != kCastTypeNull) {
_sprite->updateCast();
@@ -67,6 +68,25 @@ Graphics::ManagedSurface *Channel::getSurface() {
}
}
+bool Channel::isDirty(Sprite *nextSprite) {
+ // When a sprite is puppeted setTheSprite ensures that the dirty flag here is
+ // set. Otherwise, we need to rerender when the position, bounding box, or
+ // cast of the sprite changes.
+ bool isDirty = _dirty ||
+ _delta != Common::Point(0, 0) ||
+ ((_sprite->_castType != kCastTypeNull) &&
+ (_sprite->_cast && _sprite->_cast->isModified()));
+
+ if (nextSprite) {
+ isDirty |= _sprite->_castId != nextSprite->_castId ||
+ _sprite->getDims() != nextSprite->getDims() ||
+ (_currentPoint != nextSprite->_startPoint &&
+ !_sprite->_puppet && !_sprite->_moveable);
+ }
+
+ return isDirty;
+}
+
Common::Rect Channel::getBbox() {
Common::Rect bbox = _sprite->getDims();
bbox.moveTo(getPosition());
@@ -74,13 +94,30 @@ Common::Rect Channel::getBbox() {
return bbox;
}
-void Channel::updateLocation() {
+void Channel::setClean(Sprite *nextSprite, int spriteId) {
+ _dirty = false;
+
+ if (!_sprite->_puppet) {
+ _sprite = nextSprite;
+ _sprite->updateCast();
+
+ // Sprites marked moveable are constrained to the same bounding box until
+ // the moveable is disabled
+ if (!_sprite->_moveable)
+ _currentPoint = _sprite->_startPoint;
+ }
+
_currentPoint += _delta;
_delta = Common::Point(0, 0);
if (_sprite->_cast && _sprite->_cast->_widget) {
Common::Point p(getPosition());
+ _sprite->_cast->_modified = false;
_sprite->_cast->_widget->_dims.moveTo(p.x, p.y);
+
+ _sprite->_cast->_widget->_priority = spriteId;
+ _sprite->_cast->_widget->draw();
+ _sprite->_cast->_widget->_contentIsDirty = false;
}
}
@@ -115,10 +152,6 @@ Common::Point Channel::getPosition() {
return res;
}
-void Channel::resetPosition() {
- _delta = _sprite->_startPoint;
-}
-
MacShape *Channel::getShape() {
MacShape *shape = new MacShape();
@@ -604,53 +637,22 @@ void Score::renderFrame(uint16 frameId, RenderMode mode) {
}
void Score::renderSprites(uint16 frameId, RenderMode mode) {
- if (_vm->_newMovieStarted) {
- // g_director->getStage()->reset();
+ if (_vm->_newMovieStarted)
mode = kRenderForceUpdate;
- }
for (uint16 i = 0; i < _channels.size(); i++) {
Channel *channel = _channels[i];
Sprite *currentSprite = channel->_sprite;
Sprite *nextSprite = _frames[frameId]->_sprites[i];
- // A sprite needs to be updated if one of the following happens:
- // - The dimensions/bounding box of the sprite has changed (_dirty flag set)
- // - 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 ||
- channel->_delta != Common::Point(0, 0) ||
- currentSprite->getDims() != nextSprite->getDims() ||
- currentSprite->_ink != nextSprite->_ink ||
- (channel->_currentPoint != nextSprite->_startPoint &&
- !currentSprite->_puppet && !currentSprite->_moveable);
-
- if ((needsUpdate || mode == kRenderForceUpdate) && !currentSprite->_trails)
- g_director->getStage()->addDirtyRect(channel->getBbox());
-
- currentSprite->setClean();
+ bool needsUpdate = channel->isDirty(nextSprite) || mode == kRenderForceUpdate;
- if (!currentSprite->_puppet) {
- channel->_sprite = nextSprite;
- channel->_sprite->updateCast();
-
- // Sprites marked moveable are constrained to the same bounding box until
- // the moveable is disabled
- if (!channel->_sprite->_moveable)
- channel->_currentPoint = channel->_sprite->_startPoint;
- }
-
- channel->updateLocation();
+ if (needsUpdate && !currentSprite->_trails)
+ g_director->getStage()->addDirtyRect(channel->getBbox());
- if (channel->_sprite->_cast && channel->_sprite->_cast->_widget) {
- channel->_sprite->_cast->_widget->_priority = i;
- channel->_sprite->_cast->_widget->draw();
- channel->_sprite->_cast->_widget->_contentIsDirty = false;
- }
+ channel->setClean(nextSprite, i);
- if (needsUpdate || mode == kRenderForceUpdate)
+ if (needsUpdate)
g_director->getStage()->addDirtyRect(channel->getBbox());
}
}
diff --git a/engines/director/score.h b/engines/director/score.h
index 9b16890aa1..1ce09b715e 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -77,21 +77,21 @@ struct MacShape {
struct Channel {
Sprite *_sprite;
+ bool _dirty;
bool _visible;
uint _constraint;
Common::Point _currentPoint;
Common::Point _delta;
Channel(Sprite *sp);
+ bool isDirty(Sprite *nextSprite = nullptr);
Common::Rect getBbox();
Common::Point getPosition();
MacShape *getShape();
Graphics::ManagedSurface *getSurface();
- Graphics::ManagedSurface *getMask();
- void updateLocation();
+ void setClean(Sprite *nextSprite, int spriteId);
void addDelta(Common::Point pos);
- void resetPosition();
};
class Score {
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index 1bcb88529c..2e30a38893 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -50,7 +50,6 @@ Sprite::Sprite() {
_cast = nullptr;
_thickness = 0;
- _dirty = false;
_width = 0;
_height = 0;
_moveable = false;
@@ -80,10 +79,6 @@ void Sprite::updateCast() {
_cast->setEditable(_editable);
}
-bool Sprite::isDirty() {
- return _castType != kCastTypeNull && (_cast && _cast->isModified());
-}
-
bool Sprite::isActive() {
if (_moveable || _puppet || _scriptId)
return true;
@@ -95,12 +90,6 @@ bool Sprite::isActive() {
return false;
}
-void Sprite::setClean() {
- _dirty = false;
- if (_cast)
- _cast->_modified = false;
-}
-
uint16 Sprite::getPattern() {
switch (_spriteType) {
case kRectangleSprite:
@@ -224,8 +213,6 @@ void Sprite::setCast(uint16 castId) {
_castType = member->_type;
}
}
-
- _dirty = true;
}
Common::Rect Sprite::getDims() {
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
index b390d860b4..c36df70689 100644
--- a/engines/director/sprite.h
+++ b/engines/director/sprite.h
@@ -62,9 +62,7 @@ public:
~Sprite();
void updateCast();
- bool isDirty();
bool isActive();
- void setClean();
uint16 getPattern();
void setPattern(uint16 pattern);
@@ -90,7 +88,6 @@ public:
Cast *_cast;
byte _thickness;
- bool _dirty;
Common::Point _startPoint;
int16 _width;
int16 _height;
More information about the Scummvm-git-logs
mailing list