aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/director/frame.cpp760
-rw-r--r--engines/director/frame.h146
-rw-r--r--engines/director/lingo/lingo-the.cpp1
-rw-r--r--engines/director/module.mk2
-rw-r--r--engines/director/score.cpp784
-rw-r--r--engines/director/score.h217
-rw-r--r--engines/director/sprite.cpp85
-rw-r--r--engines/director/sprite.h137
8 files changed, 1135 insertions, 997 deletions
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
new file mode 100644
index 0000000000..abb880a6cf
--- /dev/null
+++ b/engines/director/frame.cpp
@@ -0,0 +1,760 @@
+/* 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 "common/system.h"
+#include "graphics/macgui/macwindowmanager.h"
+#include "image/bmp.h"
+
+#include "director/director.h"
+#include "director/frame.h"
+#include "director/images.h"
+#include "director/score.h"
+#include "director/sprite.h"
+
+namespace Director {
+
+Frame::Frame(DirectorEngine *vm) {
+ _vm = vm;
+ _transDuration = 0;
+ _transType = kTransNone;
+ _transArea = 0;
+ _transChunkSize = 0;
+ _tempo = 0;
+
+ _sound1 = 0;
+ _sound2 = 0;
+ _soundType1 = 0;
+ _soundType2 = 0;
+
+ _actionId = 0;
+ _skipFrameFlag = 0;
+ _blend = 0;
+
+ _sprites.resize(CHANNEL_COUNT);
+
+ for (uint16 i = 0; i < _sprites.size(); i++) {
+ Sprite *sp = new Sprite();
+ _sprites[i] = sp;
+ }
+}
+
+Frame::Frame(const Frame &frame) {
+ _vm = frame._vm;
+ _actionId = frame._actionId;
+ _transArea = frame._transArea;
+ _transDuration = frame._transDuration;
+ _transType = frame._transType;
+ _transChunkSize = frame._transChunkSize;
+ _tempo = frame._tempo;
+ _sound1 = frame._sound1;
+ _sound2 = frame._sound2;
+ _soundType1 = frame._soundType1;
+ _soundType2 = frame._soundType2;
+ _skipFrameFlag = frame._skipFrameFlag;
+ _blend = frame._blend;
+ _palette = new PaletteInfo();
+
+ _sprites.resize(CHANNEL_COUNT);
+
+ for (uint16 i = 0; i < CHANNEL_COUNT; i++) {
+ _sprites[i] = new Sprite(*frame._sprites[i]);
+ }
+}
+
+Frame::~Frame() {
+ delete _palette;
+}
+
+void Frame::readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
+ if (offset >= 32) {
+ if (size <= 16)
+ readSprite(stream, offset, size);
+ else {
+ //read > 1 sprites channel
+ while (size > 16) {
+ byte spritePosition = (offset - 32) / 16;
+ uint16 nextStart = (spritePosition + 1) * 16 + 32;
+ uint16 needSize = nextStart - offset;
+ readSprite(stream, offset, needSize);
+ offset += needSize;
+ size -= needSize;
+ }
+ readSprite(stream, offset, size);
+ }
+ } else {
+ readMainChannels(stream, offset, size);
+ }
+}
+
+void Frame::readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
+ uint16 finishPosition = offset + size;
+
+ while (offset < finishPosition) {
+ switch(offset) {
+ case kScriptIdPosition:
+ _actionId = stream.readByte();
+ offset++;
+ break;
+ case kSoundType1Position:
+ _soundType1 = stream.readByte();
+ offset++;
+ break;
+ case kTransFlagsPosition: {
+ uint8 transFlags = stream.readByte();
+ if (transFlags & 0x80)
+ _transArea = 1;
+ else
+ _transArea = 0;
+ _transDuration = transFlags & 0x7f;
+ offset++;
+ }
+ break;
+ case kTransChunkSizePosition:
+ _transChunkSize = stream.readByte();
+ offset++;
+ break;
+ case kTempoPosition:
+ _tempo = stream.readByte();
+ offset++;
+ break;
+ case kTransTypePosition:
+ _transType = static_cast<TransitionType>(stream.readByte());
+ offset++;
+ break;
+ case kSound1Position:
+ _sound1 = stream.readUint16();
+ offset+=2;
+ break;
+ case kSkipFrameFlagsPosition:
+ _skipFrameFlag = stream.readByte();
+ offset++;
+ break;
+ case kBlendPosition:
+ _blend = stream.readByte();
+ offset++;
+ break;
+ case kSound2Position:
+ _sound2 = stream.readUint16();
+ offset += 2;
+ break;
+ case kSound2TypePosition:
+ _soundType2 = stream.readByte();
+ offset += 1;
+ break;
+ case kPaletePosition:
+ if (stream.readUint16())
+ readPaletteInfo(stream);
+ offset += 16;
+ break;
+ default:
+ offset++;
+ stream.readByte();
+ debug("Field Position %d, Finish Position %d", offset, finishPosition);
+ break;
+ }
+ }
+}
+
+void Frame::readPaletteInfo(Common::SeekableSubReadStreamEndian &stream) {
+ _palette->firstColor = stream.readByte();
+ _palette->lastColor = stream.readByte();
+ _palette->flags = stream.readByte();
+ _palette->speed = stream.readByte();
+ _palette->frameCount = stream.readUint16();
+ stream.skip(8); //unknown
+}
+
+void Frame::readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
+ uint16 spritePosition = (offset - 32) / 16;
+ uint16 spriteStart = spritePosition * 16 + 32;
+
+ uint16 fieldPosition = offset - spriteStart;
+ uint16 finishPosition = fieldPosition + size;
+
+ Sprite &sprite = *_sprites[spritePosition];
+
+ while (fieldPosition < finishPosition) {
+ switch (fieldPosition) {
+ case kSpritePositionUnk1:
+ /*byte x1 = */ stream.readByte();
+ fieldPosition++;
+ break;
+ case kSpritePositionEnabled:
+ sprite._enabled = (stream.readByte() != 0);
+ fieldPosition++;
+ break;
+ case kSpritePositionUnk2:
+ /*byte x2 = */ stream.readUint16();
+ fieldPosition += 2;
+ break;
+ case kSpritePositionFlags:
+ sprite._flags = stream.readUint16();
+ sprite._ink = static_cast<InkType>(sprite._flags & 0x3f);
+
+ if (sprite._flags & 0x40)
+ sprite._trails = 1;
+ else
+ sprite._trails = 0;
+
+ fieldPosition += 2;
+ break;
+ case kSpritePositionCastId:
+ sprite._castId = stream.readUint16();
+ fieldPosition += 2;
+ break;
+ case kSpritePositionY:
+ sprite._startPoint.y = stream.readUint16();
+ fieldPosition += 2;
+ break;
+ case kSpritePositionX:
+ sprite._startPoint.x = stream.readUint16();
+ fieldPosition += 2;
+ break;
+ case kSpritePositionWidth:
+ sprite._width = stream.readUint16();
+ fieldPosition += 2;
+ break;
+ case kSpritePositionHeight:
+ sprite._height = stream.readUint16();
+ fieldPosition += 2;
+ break;
+ default:
+ //end cycle, go to next sprite channel
+ readSprite(stream, spriteStart + 16, finishPosition - fieldPosition);
+ fieldPosition = finishPosition;
+ break;
+ }
+ }
+}
+
+void Frame::prepareFrame(Score *score) {
+ renderSprites(*score->_surface, false);
+ renderSprites(*score->_trailSurface, true);
+
+ if (_transType != 0)
+ //TODO Handle changing area case
+ playTransition(score);
+
+ if (_sound1 != 0 || _sound2 != 0) {
+ playSoundChannel();
+ }
+
+ g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, score->_surface->getBounds().width(), score->_surface->getBounds().height());
+}
+
+void Frame::playSoundChannel() {
+ debug(0, "Sound2 %d", _sound2);
+ debug(0, "Sound1 %d", _sound1);
+}
+
+void Frame::playTransition(Score *score) {
+ uint16 duration = _transDuration * 250; // _transDuration in 1/4 of sec
+ duration = (duration == 0 ? 250 : duration); // director support transition duration = 0, but animation play like value = 1, idk.
+
+ if (_transChunkSize == 0)
+ _transChunkSize = 1; //equal 1 step
+
+ uint16 stepDuration = duration / _transChunkSize;
+ uint16 steps = duration / stepDuration;
+
+ switch (_transType) {
+ case kTransCoverDown:
+ {
+ uint16 stepSize = score->_movieRect.height() / steps;
+ Common::Rect r = score->_movieRect;
+
+ for (uint16 i = 1; i < steps; i++) {
+ r.setHeight(stepSize * i);
+
+ g_system->delayMillis(stepDuration);
+ score->processEvents();
+
+ g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
+ g_system->updateScreen();
+ }
+ }
+ break;
+ case kTransCoverUp:
+ {
+ uint16 stepSize = score->_movieRect.height() / steps;
+ Common::Rect r = score->_movieRect;
+
+ for (uint16 i = 1; i < steps; i++) {
+ r.setHeight(stepSize * i);
+
+ g_system->delayMillis(stepDuration);
+ score->processEvents();
+
+ g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height());
+ g_system->updateScreen();
+ }
+ }
+ break;
+ case kTransCoverRight: {
+ uint16 stepSize = score->_movieRect.width() / steps;
+ Common::Rect r = score->_movieRect;
+
+ for (uint16 i = 1; i < steps; i++) {
+ r.setWidth(stepSize * i);
+
+ g_system->delayMillis(stepDuration);
+ score->processEvents();
+
+ g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
+ g_system->updateScreen();
+ }
+ }
+ break;
+ case kTransCoverLeft: {
+ uint16 stepSize = score->_movieRect.width() / steps;
+ Common::Rect r = score->_movieRect;
+
+ for (uint16 i = 1; i < steps; i++) {
+ r.setWidth(stepSize * i);
+
+ g_system->delayMillis(stepDuration);
+ score->processEvents();
+
+ g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height());
+ g_system->updateScreen();
+ }
+ }
+ break;
+ case kTransCoverUpLeft: {
+ uint16 stepSize = score->_movieRect.width() / steps;
+ Common::Rect r = score->_movieRect;
+
+ for (uint16 i = 1; i < steps; i++) {
+ r.setWidth(stepSize * i);
+ r.setHeight(stepSize * i);
+
+ g_system->delayMillis(stepDuration);
+ score->processEvents();
+
+ g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, score->_movieRect.height() - stepSize * i, r.width(), r.height());
+ g_system->updateScreen();
+ }
+ }
+ break;
+ case kTransCoverUpRight: {
+ uint16 stepSize = score->_movieRect.width() / steps;
+ Common::Rect r = score->_movieRect;
+
+ for (uint16 i = 1; i < steps; i++) {
+ r.setWidth(stepSize * i);
+ r.setHeight(stepSize * i);
+
+ g_system->delayMillis(stepDuration);
+ score->processEvents();
+
+ g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height());
+ g_system->updateScreen();
+ }
+ }
+ break;
+ case kTransCoverDownLeft: {
+ uint16 stepSize = score->_movieRect.width() / steps;
+ Common::Rect r = score->_movieRect;
+
+ for (uint16 i = 1; i < steps; i++) {
+ r.setWidth(stepSize * i);
+ r.setHeight(stepSize * i);
+
+ g_system->delayMillis(stepDuration);
+ score->processEvents();
+
+ g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height());
+ g_system->updateScreen();
+ }
+ }
+ break;
+ case kTransCoverDownRight: {
+ uint16 stepSize = score->_movieRect.width() / steps;
+ Common::Rect r = score->_movieRect;
+
+ for (uint16 i = 1; i < steps; i++) {
+ r.setWidth(stepSize * i);
+ r.setHeight(stepSize * i);
+
+ g_system->delayMillis(stepDuration);
+ score->processEvents();
+
+ g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
+ g_system->updateScreen();
+ }
+ }
+ break;
+ default:
+ warning("Unhandled transition type %d %d %d", _transType, duration, _transChunkSize);
+ break;
+
+ }
+}
+
+void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) {
+ for (uint16 i = 0; i < CHANNEL_COUNT; i++) {
+ if (_sprites[i]->_enabled) {
+ if ((_sprites[i]->_trails == 0 && renderTrail) || (_sprites[i]->_trails == 1 && !renderTrail))
+ continue;
+
+ Cast *cast;
+ if (!_vm->_currentScore->_casts.contains(_sprites[i]->_castId)) {
+ if (!_vm->getSharedCasts()->contains(_sprites[i]->_castId)) {
+ warning("Cast id %d not found", _sprites[i]->_castId);
+ continue;
+ } else {
+ cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId);
+ }
+ } else {
+ cast = _vm->_currentScore->_casts[_sprites[i]->_castId];
+ }
+
+ if (cast->type == kCastText) {
+ renderText(surface, i);
+ continue;
+ }
+
+ Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId, _sprites[i]->_width, _sprites[i]->_height);
+
+ if (!img) {
+ warning("Image with id %d not found", _sprites[i]->_castId);
+ continue;
+ }
+
+ if (!img->getSurface()) {
+ //TODO
+ //BMPDecoder doesnt cover all BITD resources (not all have first two bytes 'BM')
+ //Some BITD's first two bytes 0x6 0x0
+ warning("Can not load image %d", _sprites[i]->_castId);
+ continue;
+ }
+
+ uint32 regX = static_cast<BitmapCast *>(_sprites[i]->_cast)->regX;
+ uint32 regY = static_cast<BitmapCast *>(_sprites[i]->_cast)->regY;
+ uint32 rectLeft = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.left;
+ uint32 rectTop = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.top;
+
+ int x = _sprites[i]->_startPoint.x - regX + rectLeft;
+ int y = _sprites[i]->_startPoint.y - regY + rectTop;
+ int height = _sprites[i]->_height;
+ int width = _sprites[i]->_width;
+
+ Common::Rect drawRect = Common::Rect(x, y, x + width, y + height);
+ _drawRects.push_back(drawRect);
+
+ switch (_sprites[i]->_ink) {
+ case kInkTypeCopy:
+ surface.blitFrom(*img->getSurface(), Common::Point(x, y));
+ break;
+ case kInkTypeBackgndTrans:
+ drawBackgndTransSprite(surface, *img->getSurface(), drawRect);
+ break;
+ case kInkTypeMatte:
+ drawMatteSprite(surface, *img->getSurface(), drawRect);
+ break;
+ case kInkTypeGhost:
+ drawGhostSprite(surface, *img->getSurface(), drawRect);
+ break;
+ case kInkTypeReverse:
+ drawReverseSprite(surface, *img->getSurface(), drawRect);
+ break;
+ default:
+ warning("Unhandled ink type %d", _sprites[i]->_ink);
+ surface.blitFrom(*img->getSurface(), Common::Point(x, y));
+ break;
+ }
+ }
+ }
+}
+
+void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) {
+ renderText(surface, spriteId);
+
+ uint16 castID = _sprites[spriteId]->_castId;
+ ButtonCast *button = static_cast<ButtonCast *>(_vm->_currentScore->_casts[castID]);
+
+ uint32 rectLeft = button->initialRect.left;
+ uint32 rectTop = button->initialRect.top;
+
+ int x = _sprites[spriteId]->_startPoint.x + rectLeft;
+ int y = _sprites[spriteId]->_startPoint.y + rectTop;
+ int height = _sprites[spriteId]->_height;
+ int width = _sprites[spriteId]->_width;
+
+ switch (button->buttonType) {
+ case kTypeCheckBox:
+ //Magic numbers: checkbox square need to move left about 5px from text and 12px side size (d4)
+ surface.frameRect(Common::Rect(x - 17, y, x + 12, y + 12), 0);
+ break;
+ case kTypeButton:
+ surface.frameRect(Common::Rect(x, y, x + width, y + height), 0);
+ break;
+ case kTypeRadio:
+ warning("STUB: renderButton: kTypeRadio");
+ break;
+ }
+}
+
+Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId, int w, int h) {
+ uint16 imgId = spriteId + 1024;
+ Image::ImageDecoder *img = NULL;
+
+ if (_vm->_currentScore->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) {
+ img = new DIBDecoder();
+ img->loadStream(*_vm->_currentScore->getArchive()->getResource(MKTAG('D', 'I', 'B', ' '), imgId));
+ return img;
+ }
+
+ if (_vm->getSharedDIB() != NULL && _vm->getSharedDIB()->contains(imgId)) {
+ img = new DIBDecoder();
+ img->loadStream(*_vm->getSharedDIB()->getVal(imgId));
+ return img;
+ }
+
+ if (_vm->_currentScore->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) {
+ if (_vm->getVersion() < 4) {
+ img = new BITDDecoder(w, h);
+ } else {
+ img = new Image::BitmapDecoder();
+ }
+
+ if (debugChannelSet(8, kDebugLoading)) {
+ Common::SeekableReadStream *s = _vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId);
+ byte buf[1024];
+ int n = s->read(buf, 1024);
+ Common::hexdump(buf, n);
+ }
+
+ img->loadStream(*_vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId));
+ return img;
+ }
+
+ if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(imgId)) {
+ img = new Image::BitmapDecoder();
+ img->loadStream(*_vm->getSharedBMP()->getVal(imgId));
+ return img;
+ }
+
+ warning("Image %d not found", spriteId);
+ return img;
+}
+
+
+void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) {
+ uint16 castID = _sprites[spriteID]->_castId;
+
+ TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castID]);
+ Common::SeekableSubReadStreamEndian *textStream;
+
+ if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S','T','X','T'), castID + 1024)) {
+ textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S','T','X','T'), castID + 1024);
+ } else {
+ textStream = _vm->getSharedSTXT()->getVal(spriteID + 1024);
+ }
+ /*uint32 unk1 = */ textStream->readUint32();
+ uint32 strLen = textStream->readUint32();
+ /*uin32 dataLen = */ textStream->readUint32();
+ Common::String text;
+
+ for (uint32 i = 0; i < strLen; i++) {
+ byte ch = textStream->readByte();
+ if (ch == 0x0d) {
+ ch = '\n';
+ }
+ text += ch;
+ }
+
+ uint32 rectLeft = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.left;
+ uint32 rectTop = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.top;
+
+ int x = _sprites[spriteID]->_startPoint.x + rectLeft;
+ int y = _sprites[spriteID]->_startPoint.y + rectTop;
+ int height = _sprites[spriteID]->_height;
+ int width = _sprites[spriteID]->_width;
+
+ const char *fontName;
+
+ if (_vm->_currentScore->_fontMap.contains(textCast->fontId)) {
+ fontName = _vm->_currentScore->_fontMap[textCast->fontId].c_str();
+ } else if ((fontName = _vm->_wm->getFontName(textCast->fontId, textCast->fontSize)) == NULL) {
+ warning("Unknown font id %d, falling back to default", textCast->fontId);
+ fontName = _vm->_wm->getFontName(0, 12);
+ }
+
+ const Graphics::Font *font = _vm->_wm->getFont(fontName, Graphics::FontManager::kBigGUIFont);
+
+ font->drawString(&surface, text, x, y, width, 0);
+
+ if (textCast->borderSize != kSizeNone) {
+ uint16 size = textCast->borderSize;
+
+ //Indent from borders, measured in d4
+ x -= 1;
+ y -= 4;
+
+ height += 4;
+ width += 1;
+
+ while (size) {
+ surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);
+ x--;
+ y--;
+ height += 2;
+ width += 2;
+ size--;
+ }
+ }
+
+ if (textCast->gutterSize != kSizeNone) {
+ x -= 1;
+ y -= 4;
+
+ height += 4;
+ width += 1;
+ uint16 size = textCast->gutterSize;
+
+ surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);
+
+ while (size) {
+ surface.drawLine(x + width, y, x + width, y + height, 0);
+ surface.drawLine(x, y + height, x + width, y + height, 0);
+ x++;
+ y++;
+ size--;
+ }
+ }
+}
+
+void Frame::drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
+ uint8 skipColor = _vm->getPaletteColorCount() - 1; //FIXME is it always white (last entry in pallette) ?
+
+ for (int ii = 0; ii < sprite.h; ii++) {
+ const byte *src = (const byte *)sprite.getBasePtr(0, ii);
+ byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
+
+ for (int j = 0; j < drawRect.width(); j++) {
+ if (*src != skipColor)
+ *dst = *src;
+
+ src++;
+ dst++;
+ }
+ }
+}
+
+void Frame::drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
+ uint8 skipColor = _vm->getPaletteColorCount() - 1;
+ for (int ii = 0; ii < sprite.h; ii++) {
+ const byte *src = (const byte *)sprite.getBasePtr(0, ii);
+ byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
+
+ for (int j = 0; j < drawRect.width(); j++) {
+ if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0) && (*src != skipColor))
+ *dst = (_vm->getPaletteColorCount() - 1) - *src; //Oposite color
+
+ src++;
+ dst++;
+ }
+ }
+}
+
+void Frame::drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
+ uint8 skipColor = _vm->getPaletteColorCount() - 1;
+ for (int ii = 0; ii < sprite.h; ii++) {
+ const byte *src = (const byte *)sprite.getBasePtr(0, ii);
+ byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
+
+ for (int j = 0; j < drawRect.width(); j++) {
+ if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0))
+ *dst = (_vm->getPaletteColorCount() - 1) - *src;
+ else if (*src != skipColor)
+ *dst = *src;
+ src++;
+ dst++;
+ }
+ }
+}
+
+void Frame::drawMatteSprite(Graphics::ManagedSurface &target, 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);
+
+ // Searching white color in the corners
+ int whiteColor = -1;
+
+ for (int corner = 0; corner < 4; corner++) {
+ int x = (corner & 0x1) ? tmp.w - 1 : 0;
+ int y = (corner & 0x2) ? tmp.h - 1 : 0;
+
+ 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) {
+ warning("No white color for Matte image");
+ whiteColor = *(byte *)tmp.getBasePtr(0, 0);
+ }
+
+ 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 < tmp.h; yy++) {
+ const byte *src = (const byte *)tmp.getBasePtr(0, yy);
+ const byte *mask = (const byte *)ff.getMask()->getBasePtr(0, yy);
+ byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + yy);
+
+ for (int xx = 0; xx < drawRect.width(); xx++, src++, dst++, mask++)
+ if (*mask == 0)
+ *dst = *src;
+ }
+
+ tmp.free();
+}
+
+uint16 Frame::getSpriteIDFromPos(Common::Point pos) {
+ //Find first from top to bottom
+ for (uint16 i = _drawRects.size() - 1; i > 0; i--) {
+ if (_drawRects[i].contains(pos))
+ return i;
+ }
+
+ return 0;
+}
+
+} //End of namespace Director
diff --git a/engines/director/frame.h b/engines/director/frame.h
new file mode 100644
index 0000000000..f9cef676cd
--- /dev/null
+++ b/engines/director/frame.h
@@ -0,0 +1,146 @@
+/* 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_FRAME_H
+#define DIRECTOR_FRAME_H
+
+#include "graphics/managed_surface.h"
+#include "image/image_decoder.h"
+
+namespace Director {
+
+class Sprite;
+
+#define CHANNEL_COUNT 24
+
+enum TransitionType {
+ kTransNone,
+ kTransWipeRight,
+ kTransWipeLeft,
+ kTransWipeDown,
+ kTransWipeUp,
+ kTransCenterOutHorizontal,
+ kTransEdgesInHorizontal,
+ kTransCenterOutVertical,
+ kTransEdgesInVertical,
+ kTransCenterOutSquare,
+ kTransEdgesInSquare,
+ kTransPushLeft,
+ kTransPushRight,
+ kTransPushDown,
+ kTransPushUp,
+ kTransRevealUp,
+ kTransRevealUpRight,
+ kTransRevealRight,
+ kTransRevealDown,
+ kTransRevealDownRight,
+ kTransRevealDownLeft,
+ kTransRevealLeft,
+ kTransRevealUpLeft,
+ kTransDissolvePixelsFast,
+ kTransDissolveBoxyRects,
+ kTransDissolveBoxySquares,
+ kTransDissolvePatterns,
+ kTransRandomRows,
+ kTransRandomColumns,
+ kTransCoverDown,
+ kTransCoverDownLeft,
+ kTransCoverDownRight,
+ kTransCoverLeft,
+ kTransCoverRight,
+ kTransCoverUp,
+ kTransCoverUpLeft,
+ kTransCoverUpRight,
+ kTransTypeVenitianBlind,
+ kTransTypeCheckerboard,
+ kTransTypeStripsBottomBuildLeft,
+ kTransTypeStripsBottomBuildRight,
+ kTransTypeStripsLeftBuildDown,
+ kTransTypeStripsLeftBuildUp,
+ kTransTypeStripsRightBuildDown,
+ kTransTypeStripsRightBuildUp,
+ kTransTypeStripsTopBuildLeft,
+ kTransTypeStripsTopBuildRight,
+ kTransZoomOpen,
+ kTransZoomClose,
+ kTransVerticalBinds,
+ kTransDissolveBitsTrans,
+ kTransDissolvePixels,
+ kTransDissolveBits
+};
+
+struct PaletteInfo {
+ uint8 firstColor;
+ uint8 lastColor;
+ uint8 flags;
+ uint8 speed;
+ uint16 frameCount;
+};
+
+
+class Frame {
+public:
+ Frame(DirectorEngine *vm);
+ Frame(const Frame &frame);
+ ~Frame();
+ void readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
+ void prepareFrame(Score *score);
+ uint16 getSpriteIDFromPos(Common::Point pos);
+
+private:
+ void playTransition(Score *score);
+ void playSoundChannel();
+ void renderSprites(Graphics::ManagedSurface &surface, bool renderTrail);
+ void renderText(Graphics::ManagedSurface &surface, uint16 spriteId);
+ void renderButton(Graphics::ManagedSurface &surface, uint16 spriteId);
+ void readPaletteInfo(Common::SeekableSubReadStreamEndian &stream);
+ void readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
+ void readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
+ Image::ImageDecoder *getImageFrom(uint16 spriteID, int w, int h);
+ void drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
+ void drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
+ void drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
+ void drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
+public:
+ uint8 _actionId;
+ uint8 _transDuration;
+ uint8 _transArea; //1 - Whole Stage, 0 - Changing Area
+ uint8 _transChunkSize;
+ TransitionType _transType;
+ PaletteInfo *_palette;
+ uint8 _tempo;
+
+ uint16 _sound1;
+ uint8 _soundType1;
+ uint16 _sound2;
+ uint8 _soundType2;
+
+ uint8 _skipFrameFlag;
+ uint8 _blend;
+ Common::Array<Sprite *> _sprites;
+ Common::Array<Common::Rect > _drawRects;
+ DirectorEngine *_vm;
+};
+
+} //End of namespace Director
+
+#endif
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index d868b8ab00..879ff4854d 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -21,6 +21,7 @@
*/
#include "engines/director/lingo/lingo.h"
+#include "director/sprite.h"
namespace Director {
diff --git a/engines/director/module.mk b/engines/director/module.mk
index 05e92b76e0..c37e9d9b9b 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -3,11 +3,13 @@ MODULE := engines/director
MODULE_OBJS = \
detection.o \
director.o \
+ frame.o \
images.o \
movie.o \
resource.o \
score.o \
sound.o \
+ sprite.o \
lingo/lingo-gr.o \
lingo/lingo.o \
lingo/lingo-builtins.o \
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index ccadac212c..2812f29919 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -32,11 +32,12 @@
#include "engines/util.h"
#include "graphics/managed_surface.h"
#include "graphics/macgui/macwindowmanager.h"
-#include "image/bmp.h"
#include "graphics/fontman.h"
#include "graphics/fonts/bdf.h"
#include "director/score.h"
+#include "director/frame.h"
+#include "director/sprite.h"
#include "director/images.h"
#include "director/resource.h"
#include "director/lingo/lingo.h"
@@ -839,785 +840,4 @@ Sprite *Score::getSpriteById(uint16 id) {
}
}
-Frame::Frame(DirectorEngine *vm) {
- _vm = vm;
- _transDuration = 0;
- _transType = kTransNone;
- _transArea = 0;
- _transChunkSize = 0;
- _tempo = 0;
-
- _sound1 = 0;
- _sound2 = 0;
- _soundType1 = 0;
- _soundType2 = 0;
-
- _actionId = 0;
- _skipFrameFlag = 0;
- _blend = 0;
-
- _sprites.resize(CHANNEL_COUNT);
-
- for (uint16 i = 0; i < _sprites.size(); i++) {
- Sprite *sp = new Sprite();
- _sprites[i] = sp;
- }
-}
-
-Frame::Frame(const Frame &frame) {
- _vm = frame._vm;
- _actionId = frame._actionId;
- _transArea = frame._transArea;
- _transDuration = frame._transDuration;
- _transType = frame._transType;
- _transChunkSize = frame._transChunkSize;
- _tempo = frame._tempo;
- _sound1 = frame._sound1;
- _sound2 = frame._sound2;
- _soundType1 = frame._soundType1;
- _soundType2 = frame._soundType2;
- _skipFrameFlag = frame._skipFrameFlag;
- _blend = frame._blend;
- _palette = new PaletteInfo();
-
- _sprites.resize(CHANNEL_COUNT);
-
- for (uint16 i = 0; i < CHANNEL_COUNT; i++) {
- _sprites[i] = new Sprite(*frame._sprites[i]);
- }
-}
-
-Frame::~Frame() {
- delete _palette;
-}
-
-void Frame::readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
- if (offset >= 32) {
- if (size <= 16)
- readSprite(stream, offset, size);
- else {
- //read > 1 sprites channel
- while (size > 16) {
- byte spritePosition = (offset - 32) / 16;
- uint16 nextStart = (spritePosition + 1) * 16 + 32;
- uint16 needSize = nextStart - offset;
- readSprite(stream, offset, needSize);
- offset += needSize;
- size -= needSize;
- }
- readSprite(stream, offset, size);
- }
- } else {
- readMainChannels(stream, offset, size);
- }
-}
-
-void Frame::readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
- uint16 finishPosition = offset + size;
-
- while (offset < finishPosition) {
- switch(offset) {
- case kScriptIdPosition:
- _actionId = stream.readByte();
- offset++;
- break;
- case kSoundType1Position:
- _soundType1 = stream.readByte();
- offset++;
- break;
- case kTransFlagsPosition: {
- uint8 transFlags = stream.readByte();
- if (transFlags & 0x80)
- _transArea = 1;
- else
- _transArea = 0;
- _transDuration = transFlags & 0x7f;
- offset++;
- }
- break;
- case kTransChunkSizePosition:
- _transChunkSize = stream.readByte();
- offset++;
- break;
- case kTempoPosition:
- _tempo = stream.readByte();
- offset++;
- break;
- case kTransTypePosition:
- _transType = static_cast<TransitionType>(stream.readByte());
- offset++;
- break;
- case kSound1Position:
- _sound1 = stream.readUint16();
- offset+=2;
- break;
- case kSkipFrameFlagsPosition:
- _skipFrameFlag = stream.readByte();
- offset++;
- break;
- case kBlendPosition:
- _blend = stream.readByte();
- offset++;
- break;
- case kSound2Position:
- _sound2 = stream.readUint16();
- offset += 2;
- break;
- case kSound2TypePosition:
- _soundType2 = stream.readByte();
- offset += 1;
- break;
- case kPaletePosition:
- if (stream.readUint16())
- readPaletteInfo(stream);
- offset += 16;
- break;
- default:
- offset++;
- stream.readByte();
- debug("Field Position %d, Finish Position %d", offset, finishPosition);
- break;
- }
- }
-}
-
-void Frame::readPaletteInfo(Common::SeekableSubReadStreamEndian &stream) {
- _palette->firstColor = stream.readByte();
- _palette->lastColor = stream.readByte();
- _palette->flags = stream.readByte();
- _palette->speed = stream.readByte();
- _palette->frameCount = stream.readUint16();
- stream.skip(8); //unknown
-}
-
-void Frame::readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
- uint16 spritePosition = (offset - 32) / 16;
- uint16 spriteStart = spritePosition * 16 + 32;
-
- uint16 fieldPosition = offset - spriteStart;
- uint16 finishPosition = fieldPosition + size;
-
- Sprite &sprite = *_sprites[spritePosition];
-
- while (fieldPosition < finishPosition) {
- switch (fieldPosition) {
- case kSpritePositionUnk1:
- /*byte x1 = */ stream.readByte();
- fieldPosition++;
- break;
- case kSpritePositionEnabled:
- sprite._enabled = (stream.readByte() != 0);
- fieldPosition++;
- break;
- case kSpritePositionUnk2:
- /*byte x2 = */ stream.readUint16();
- fieldPosition += 2;
- break;
- case kSpritePositionFlags:
- sprite._flags = stream.readUint16();
- sprite._ink = static_cast<InkType>(sprite._flags & 0x3f);
-
- if (sprite._flags & 0x40)
- sprite._trails = 1;
- else
- sprite._trails = 0;
-
- fieldPosition += 2;
- break;
- case kSpritePositionCastId:
- sprite._castId = stream.readUint16();
- fieldPosition += 2;
- break;
- case kSpritePositionY:
- sprite._startPoint.y = stream.readUint16();
- fieldPosition += 2;
- break;
- case kSpritePositionX:
- sprite._startPoint.x = stream.readUint16();
- fieldPosition += 2;
- break;
- case kSpritePositionWidth:
- sprite._width = stream.readUint16();
- fieldPosition += 2;
- break;
- case kSpritePositionHeight:
- sprite._height = stream.readUint16();
- fieldPosition += 2;
- break;
- default:
- //end cycle, go to next sprite channel
- readSprite(stream, spriteStart + 16, finishPosition - fieldPosition);
- fieldPosition = finishPosition;
- break;
- }
- }
-}
-
-void Frame::prepareFrame(Score *score) {
- renderSprites(*score->_surface, false);
- renderSprites(*score->_trailSurface, true);
-
- if (_transType != 0)
- //TODO Handle changing area case
- playTransition(score);
-
- if (_sound1 != 0 || _sound2 != 0) {
- playSoundChannel();
- }
-
- g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, score->_surface->getBounds().width(), score->_surface->getBounds().height());
-}
-
-void Frame::playSoundChannel() {
- debug(0, "Sound2 %d", _sound2);
- debug(0, "Sound1 %d", _sound1);
-}
-
-void Frame::playTransition(Score *score) {
- uint16 duration = _transDuration * 250; // _transDuration in 1/4 of sec
- duration = (duration == 0 ? 250 : duration); // director support transition duration = 0, but animation play like value = 1, idk.
-
- if (_transChunkSize == 0)
- _transChunkSize = 1; //equal 1 step
-
- uint16 stepDuration = duration / _transChunkSize;
- uint16 steps = duration / stepDuration;
-
- switch (_transType) {
- case kTransCoverDown:
- {
- uint16 stepSize = score->_movieRect.height() / steps;
- Common::Rect r = score->_movieRect;
-
- for (uint16 i = 1; i < steps; i++) {
- r.setHeight(stepSize * i);
-
- g_system->delayMillis(stepDuration);
- score->processEvents();
-
- g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
- g_system->updateScreen();
- }
- }
- break;
- case kTransCoverUp:
- {
- uint16 stepSize = score->_movieRect.height() / steps;
- Common::Rect r = score->_movieRect;
-
- for (uint16 i = 1; i < steps; i++) {
- r.setHeight(stepSize * i);
-
- g_system->delayMillis(stepDuration);
- score->processEvents();
-
- g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height());
- g_system->updateScreen();
- }
- }
- break;
- case kTransCoverRight: {
- uint16 stepSize = score->_movieRect.width() / steps;
- Common::Rect r = score->_movieRect;
-
- for (uint16 i = 1; i < steps; i++) {
- r.setWidth(stepSize * i);
-
- g_system->delayMillis(stepDuration);
- score->processEvents();
-
- g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
- g_system->updateScreen();
- }
- }
- break;
- case kTransCoverLeft: {
- uint16 stepSize = score->_movieRect.width() / steps;
- Common::Rect r = score->_movieRect;
-
- for (uint16 i = 1; i < steps; i++) {
- r.setWidth(stepSize * i);
-
- g_system->delayMillis(stepDuration);
- score->processEvents();
-
- g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height());
- g_system->updateScreen();
- }
- }
- break;
- case kTransCoverUpLeft: {
- uint16 stepSize = score->_movieRect.width() / steps;
- Common::Rect r = score->_movieRect;
-
- for (uint16 i = 1; i < steps; i++) {
- r.setWidth(stepSize * i);
- r.setHeight(stepSize * i);
-
- g_system->delayMillis(stepDuration);
- score->processEvents();
-
- g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, score->_movieRect.height() - stepSize * i, r.width(), r.height());
- g_system->updateScreen();
- }
- }
- break;
- case kTransCoverUpRight: {
- uint16 stepSize = score->_movieRect.width() / steps;
- Common::Rect r = score->_movieRect;
-
- for (uint16 i = 1; i < steps; i++) {
- r.setWidth(stepSize * i);
- r.setHeight(stepSize * i);
-
- g_system->delayMillis(stepDuration);
- score->processEvents();
-
- g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height());
- g_system->updateScreen();
- }
- }
- break;
- case kTransCoverDownLeft: {
- uint16 stepSize = score->_movieRect.width() / steps;
- Common::Rect r = score->_movieRect;
-
- for (uint16 i = 1; i < steps; i++) {
- r.setWidth(stepSize * i);
- r.setHeight(stepSize * i);
-
- g_system->delayMillis(stepDuration);
- score->processEvents();
-
- g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height());
- g_system->updateScreen();
- }
- }
- break;
- case kTransCoverDownRight: {
- uint16 stepSize = score->_movieRect.width() / steps;
- Common::Rect r = score->_movieRect;
-
- for (uint16 i = 1; i < steps; i++) {
- r.setWidth(stepSize * i);
- r.setHeight(stepSize * i);
-
- g_system->delayMillis(stepDuration);
- score->processEvents();
-
- g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height());
- g_system->updateScreen();
- }
- }
- break;
- default:
- warning("Unhandled transition type %d %d %d", _transType, duration, _transChunkSize);
- break;
-
- }
-}
-
-void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) {
- for (uint16 i = 0; i < CHANNEL_COUNT; i++) {
- if (_sprites[i]->_enabled) {
- if ((_sprites[i]->_trails == 0 && renderTrail) || (_sprites[i]->_trails == 1 && !renderTrail))
- continue;
-
- Cast *cast;
- if (!_vm->_currentScore->_casts.contains(_sprites[i]->_castId)) {
- if (!_vm->getSharedCasts()->contains(_sprites[i]->_castId)) {
- warning("Cast id %d not found", _sprites[i]->_castId);
- continue;
- } else {
- cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId);
- }
- } else {
- cast = _vm->_currentScore->_casts[_sprites[i]->_castId];
- }
-
- if (cast->type == kCastText) {
- renderText(surface, i);
- continue;
- }
-
- Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId, _sprites[i]->_width, _sprites[i]->_height);
-
- if (!img) {
- warning("Image with id %d not found", _sprites[i]->_castId);
- continue;
- }
-
- if (!img->getSurface()) {
- //TODO
- //BMPDecoder doesnt cover all BITD resources (not all have first two bytes 'BM')
- //Some BITD's first two bytes 0x6 0x0
- warning("Can not load image %d", _sprites[i]->_castId);
- continue;
- }
-
- uint32 regX = static_cast<BitmapCast *>(_sprites[i]->_cast)->regX;
- uint32 regY = static_cast<BitmapCast *>(_sprites[i]->_cast)->regY;
- uint32 rectLeft = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.left;
- uint32 rectTop = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.top;
-
- int x = _sprites[i]->_startPoint.x - regX + rectLeft;
- int y = _sprites[i]->_startPoint.y - regY + rectTop;
- int height = _sprites[i]->_height;
- int width = _sprites[i]->_width;
-
- Common::Rect drawRect = Common::Rect(x, y, x + width, y + height);
- _drawRects.push_back(drawRect);
-
- switch (_sprites[i]->_ink) {
- case kInkTypeCopy:
- surface.blitFrom(*img->getSurface(), Common::Point(x, y));
- break;
- case kInkTypeBackgndTrans:
- drawBackgndTransSprite(surface, *img->getSurface(), drawRect);
- break;
- case kInkTypeMatte:
- drawMatteSprite(surface, *img->getSurface(), drawRect);
- break;
- case kInkTypeGhost:
- drawGhostSprite(surface, *img->getSurface(), drawRect);
- break;
- case kInkTypeReverse:
- drawReverseSprite(surface, *img->getSurface(), drawRect);
- break;
- default:
- warning("Unhandled ink type %d", _sprites[i]->_ink);
- surface.blitFrom(*img->getSurface(), Common::Point(x, y));
- break;
- }
- }
- }
-}
-
-void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) {
- renderText(surface, spriteId);
-
- uint16 castID = _sprites[spriteId]->_castId;
- ButtonCast *button = static_cast<ButtonCast *>(_vm->_currentScore->_casts[castID]);
-
- uint32 rectLeft = button->initialRect.left;
- uint32 rectTop = button->initialRect.top;
-
- int x = _sprites[spriteId]->_startPoint.x + rectLeft;
- int y = _sprites[spriteId]->_startPoint.y + rectTop;
- int height = _sprites[spriteId]->_height;
- int width = _sprites[spriteId]->_width;
-
- switch (button->buttonType) {
- case kTypeCheckBox:
- //Magic numbers: checkbox square need to move left about 5px from text and 12px side size (d4)
- surface.frameRect(Common::Rect(x - 17, y, x + 12, y + 12), 0);
- break;
- case kTypeButton:
- surface.frameRect(Common::Rect(x, y, x + width, y + height), 0);
- break;
- case kTypeRadio:
- warning("STUB: renderButton: kTypeRadio");
- break;
- }
-}
-
-Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId, int w, int h) {
- uint16 imgId = spriteId + 1024;
- Image::ImageDecoder *img = NULL;
-
- if (_vm->_currentScore->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) {
- img = new DIBDecoder();
- img->loadStream(*_vm->_currentScore->getArchive()->getResource(MKTAG('D', 'I', 'B', ' '), imgId));
- return img;
- }
-
- if (_vm->getSharedDIB() != NULL && _vm->getSharedDIB()->contains(imgId)) {
- img = new DIBDecoder();
- img->loadStream(*_vm->getSharedDIB()->getVal(imgId));
- return img;
- }
-
- if (_vm->_currentScore->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) {
- if (_vm->getVersion() < 4) {
- img = new BITDDecoder(w, h);
- } else {
- img = new Image::BitmapDecoder();
- }
-
- if (debugChannelSet(8, kDebugLoading)) {
- Common::SeekableReadStream *s = _vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId);
- byte buf[1024];
- int n = s->read(buf, 1024);
- Common::hexdump(buf, n);
- }
-
- img->loadStream(*_vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId));
- return img;
- }
-
- if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(imgId)) {
- img = new Image::BitmapDecoder();
- img->loadStream(*_vm->getSharedBMP()->getVal(imgId));
- return img;
- }
-
- warning("Image %d not found", spriteId);
- return img;
-}
-
-
-void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) {
- uint16 castID = _sprites[spriteID]->_castId;
-
- TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castID]);
- Common::SeekableSubReadStreamEndian *textStream;
-
- if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S','T','X','T'), castID + 1024)) {
- textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S','T','X','T'), castID + 1024);
- } else {
- textStream = _vm->getSharedSTXT()->getVal(spriteID + 1024);
- }
- /*uint32 unk1 = */ textStream->readUint32();
- uint32 strLen = textStream->readUint32();
- /*uin32 dataLen = */ textStream->readUint32();
- Common::String text;
-
- for (uint32 i = 0; i < strLen; i++) {
- byte ch = textStream->readByte();
- if (ch == 0x0d) {
- ch = '\n';
- }
- text += ch;
- }
-
- uint32 rectLeft = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.left;
- uint32 rectTop = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.top;
-
- int x = _sprites[spriteID]->_startPoint.x + rectLeft;
- int y = _sprites[spriteID]->_startPoint.y + rectTop;
- int height = _sprites[spriteID]->_height;
- int width = _sprites[spriteID]->_width;
-
- const char *fontName;
-
- if (_vm->_currentScore->_fontMap.contains(textCast->fontId)) {
- fontName = _vm->_currentScore->_fontMap[textCast->fontId].c_str();
- } else if ((fontName = _vm->_wm->getFontName(textCast->fontId, textCast->fontSize)) == NULL) {
- warning("Unknown font id %d, falling back to default", textCast->fontId);
- fontName = _vm->_wm->getFontName(0, 12);
- }
-
- const Graphics::Font *font = _vm->_wm->getFont(fontName, Graphics::FontManager::kBigGUIFont);
-
- font->drawString(&surface, text, x, y, width, 0);
-
- if (textCast->borderSize != kSizeNone) {
- uint16 size = textCast->borderSize;
-
- //Indent from borders, measured in d4
- x -= 1;
- y -= 4;
-
- height += 4;
- width += 1;
-
- while (size) {
- surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);
- x--;
- y--;
- height += 2;
- width += 2;
- size--;
- }
- }
-
- if (textCast->gutterSize != kSizeNone) {
- x -= 1;
- y -= 4;
-
- height += 4;
- width += 1;
- uint16 size = textCast->gutterSize;
-
- surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);
-
- while (size) {
- surface.drawLine(x + width, y, x + width, y + height, 0);
- surface.drawLine(x, y + height, x + width, y + height, 0);
- x++;
- y++;
- size--;
- }
- }
-}
-
-void Frame::drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
- uint8 skipColor = _vm->getPaletteColorCount() - 1; //FIXME is it always white (last entry in pallette) ?
-
- for (int ii = 0; ii < sprite.h; ii++) {
- const byte *src = (const byte *)sprite.getBasePtr(0, ii);
- byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
-
- for (int j = 0; j < drawRect.width(); j++) {
- if (*src != skipColor)
- *dst = *src;
-
- src++;
- dst++;
- }
- }
-}
-
-void Frame::drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
- uint8 skipColor = _vm->getPaletteColorCount() - 1;
- for (int ii = 0; ii < sprite.h; ii++) {
- const byte *src = (const byte *)sprite.getBasePtr(0, ii);
- byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
-
- for (int j = 0; j < drawRect.width(); j++) {
- if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0) && (*src != skipColor))
- *dst = (_vm->getPaletteColorCount() - 1) - *src; //Oposite color
-
- src++;
- dst++;
- }
- }
-}
-
-void Frame::drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
- uint8 skipColor = _vm->getPaletteColorCount() - 1;
- for (int ii = 0; ii < sprite.h; ii++) {
- const byte *src = (const byte *)sprite.getBasePtr(0, ii);
- byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
-
- for (int j = 0; j < drawRect.width(); j++) {
- if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0))
- *dst = (_vm->getPaletteColorCount() - 1) - *src;
- else if (*src != skipColor)
- *dst = *src;
- src++;
- dst++;
- }
- }
-}
-
-void Frame::drawMatteSprite(Graphics::ManagedSurface &target, 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);
-
- // Searching white color in the corners
- int whiteColor = -1;
-
- for (int corner = 0; corner < 4; corner++) {
- int x = (corner & 0x1) ? tmp.w - 1 : 0;
- int y = (corner & 0x2) ? tmp.h - 1 : 0;
-
- 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) {
- warning("No white color for Matte image");
- whiteColor = *(byte *)tmp.getBasePtr(0, 0);
- }
-
- 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 < tmp.h; yy++) {
- const byte *src = (const byte *)tmp.getBasePtr(0, yy);
- const byte *mask = (const byte *)ff.getMask()->getBasePtr(0, yy);
- byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + yy);
-
- for (int xx = 0; xx < drawRect.width(); xx++, src++, dst++, mask++)
- if (*mask == 0)
- *dst = *src;
- }
-
- tmp.free();
-}
-
-uint16 Frame::getSpriteIDFromPos(Common::Point pos) {
- //Find first from top to bottom
- for (uint16 i = _drawRects.size() - 1; i > 0; i--) {
- if (_drawRects[i].contains(pos))
- return i;
- }
-
- return 0;
-}
-
-Sprite::Sprite() {
- _enabled = false;
- _trails = 0;
- _width = 0;
- _ink = kInkTypeCopy;
- _flags = 0;
- _height = 0;
- _castId = 0;
- _constraint = 0;
- _moveable = 0;
- _castId = 0;
- _backColor = 0;
- _foreColor = 0;
- _left = 0;
- _right = 0;
- _top = 0;
- _bottom = 0;
- _visible = false;
- _movieRate = 0;
- _movieTime = 0;
- _startTime = 0;
- _stopTime = 0;
- _volume = 0;
- _stretch = 0;
- _type = kInactiveSprite;
-}
-
-Sprite::Sprite(const Sprite &sprite) {
- _enabled = sprite._enabled;
- _castId = sprite._castId;
- _flags = sprite._flags;
- _trails = sprite._trails;
- _ink = sprite._ink;
- _width = sprite._width;
- _height = sprite._height;
- _startPoint.x = sprite._startPoint.x;
- _startPoint.y = sprite._startPoint.y;
- _backColor = sprite._backColor;
- _foreColor = sprite._foreColor;
- _left = sprite._left;
- _right = sprite._right;
- _top = sprite._top;
- _bottom = sprite._bottom;
- _visible = sprite._visible;
- _movieRate = sprite._movieRate;
- _movieTime = sprite._movieTime;
- _stopTime = sprite._stopTime;
- _volume = sprite._volume;
- _stretch = sprite._stretch;
- _type = sprite._type;
-}
-
-Sprite::~Sprite() {
- delete _cast;
-}
-
} //End of namespace Director
diff --git a/engines/director/score.h b/engines/director/score.h
index 929dae666f..9d92de9538 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -36,11 +36,11 @@ namespace Director {
class Lingo;
class DirectorSound;
+class Frame;
+class Sprite;
class Score;
class DirectorEngine;
-#define CHANNEL_COUNT 24
-
enum CastType {
kCastBitmap = 1,
kCastFilmLoop,
@@ -55,71 +55,6 @@ enum CastType {
kCastScript
};
-//Director v4
-enum SpriteType {
- kInactiveSprite, //turns the sprite off
- kBitmapSprite,
- kRectangleSprite,
- kRoundedRectangleSprite,
- kOvalSprite,
- kLineTopBottomSprite, //line from top left to bottom right
- kLineBottomTopSprite, //line from bottom left to top right
- kTextSprite,
- kButtonSprite,
- kCheckboxSprite,
- kRadioButtonSprite,
- kUndeterminedSprite = 16 //use castType property to examine the type of cast member associated with sprite
-};
-
-enum SpritePosition {
- kSpritePositionUnk1 = 0,
- kSpritePositionEnabled,
- kSpritePositionUnk2,
- kSpritePositionFlags = 4,
- kSpritePositionCastId = 6,
- kSpritePositionY = 8,
- kSpritePositionX = 10,
- kSpritePositionHeight = 12,
- kSpritePositionWidth = 14
-};
-
-enum MainChannelsPosition {
- kScriptIdPosition = 0,
- kSoundType1Position,
- kTransFlagsPosition,
- kTransChunkSizePosition,
- kTempoPosition,
- kTransTypePosition,
- kSound1Position,
- kSkipFrameFlagsPosition = 8,
- kBlendPosition,
- kSound2Position,
- kSound2TypePosition = 11,
- kPaletePosition = 15
-};
-
-enum InkType {
- kInkTypeCopy,
- kInkTypeTransparent,
- kInkTypeReverse,
- kInkTypeGhost,
- kInkTypeNotCopy,
- kInkTypeNotTrans,
- kInkTypeNotReverse,
- kInkTypeNotGhost,
- kInkTypeMatte,
- kInkTypeMask,
- //10-31 Not used (Lingo in a Nutshell)
- kInkTypeBlend = 32,
- kInkTypeAddPin,
- kInkTypeAdd,
- kInkTypeSubPin,
- kInkTypeBackgndTrans,
- kInkTypeLight,
- kInkTypeSub,
- kInkTypeDark
-};
-
enum ScriptType {
kMovieScript = 0,
kSpriteScript = 1,
@@ -127,62 +62,6 @@ enum ScriptType {
kMaxScriptType = 2
};
-enum TransitionType {
- kTransNone,
- kTransWipeRight,
- kTransWipeLeft,
- kTransWipeDown,
- kTransWipeUp,
- kTransCenterOutHorizontal,
- kTransEdgesInHorizontal,
- kTransCenterOutVertical,
- kTransEdgesInVertical,
- kTransCenterOutSquare,
- kTransEdgesInSquare,
- kTransPushLeft,
- kTransPushRight,
- kTransPushDown,
- kTransPushUp,
- kTransRevealUp,
- kTransRevealUpRight,
- kTransRevealRight,
- kTransRevealDown,
- kTransRevealDownRight,
- kTransRevealDownLeft,
- kTransRevealLeft,
- kTransRevealUpLeft,
- kTransDissolvePixelsFast,
- kTransDissolveBoxyRects,
- kTransDissolveBoxySquares,
- kTransDissolvePatterns,
- kTransRandomRows,
- kTransRandomColumns,
- kTransCoverDown,
- kTransCoverDownLeft,
- kTransCoverDownRight,
- kTransCoverLeft,
- kTransCoverRight,
- kTransCoverUp,
- kTransCoverUpLeft,
- kTransCoverUpRight,
- kTransTypeVenitianBlind,
- kTransTypeCheckerboard,
- kTransTypeStripsBottomBuildLeft,
- kTransTypeStripsBottomBuildRight,
- kTransTypeStripsLeftBuildDown,
- kTransTypeStripsLeftBuildUp,
- kTransTypeStripsRightBuildDown,
- kTransTypeStripsRightBuildUp,
- kTransTypeStripsTopBuildLeft,
- kTransTypeStripsTopBuildRight,
- kTransZoomOpen,
- kTransZoomClose,
- kTransVerticalBinds,
- kTransDissolveBitsTrans,
- kTransDissolvePixels,
- kTransDissolveBits
-};
-
struct Cast {
CastType type;
Common::Rect initialRect;
@@ -281,98 +160,6 @@ struct CastInfo {
Common::String type;
};
-struct PaletteInfo {
- uint8 firstColor;
- uint8 lastColor;
- uint8 flags;
- uint8 speed;
- uint16 frameCount;
-};
-
-class Sprite {
-public:
- Sprite();
- Sprite(const Sprite &sprite);
- ~Sprite();
- bool _enabled;
- byte _castId;
- InkType _ink;
- uint16 _trails;
- Cast *_cast;
- uint16 _flags;
- Common::Point _startPoint;
- uint16 _width;
- uint16 _height;
- //TODO: default constraint = 0, if turned on, sprite is constrainted to the bounding rect
- //As i know, constrainted != 0 only if sprite moveable
- byte _constraint;
- byte _moveable;
- byte _backColor;
- byte _foreColor;
- uint16 _left;
- uint16 _right;
- uint16 _top;
- uint16 _bottom;
- byte _blend;
- bool _visible;
- SpriteType _type;
- //Using in digital movie sprites
- byte _movieRate;
- uint16 _movieTime;
- uint16 _startTime;
- uint16 _stopTime;
- byte _volume;
- byte _stretch;
- //Using in shape sprites
- byte _lineSize;
- //Using in text sprites
- Common::String _editableText;
-};
-
-class Frame {
-public:
- Frame(DirectorEngine *vm);
- Frame(const Frame &frame);
- ~Frame();
- void readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
- void prepareFrame(Score *score);
- uint16 getSpriteIDFromPos(Common::Point pos);
-
-private:
- void playTransition(Score *score);
- void playSoundChannel();
- void renderSprites(Graphics::ManagedSurface &surface, bool renderTrail);
- void renderText(Graphics::ManagedSurface &surface, uint16 spriteId);
- void renderButton(Graphics::ManagedSurface &surface, uint16 spriteId);
- void readPaletteInfo(Common::SeekableSubReadStreamEndian &stream);
- void readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
- void readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size);
- Image::ImageDecoder *getImageFrom(uint16 spriteID, int w, int h);
- void drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
- void drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
- void drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
- void drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
-public:
- uint8 _actionId;
- uint8 _transDuration;
- uint8 _transArea; //1 - Whole Stage, 0 - Changing Area
- uint8 _transChunkSize;
- TransitionType _transType;
- PaletteInfo *_palette;
- uint8 _tempo;
-
- uint16 _sound1;
- uint8 _soundType1;
- uint16 _sound2;
- uint8 _soundType2;
-
- uint8 _skipFrameFlag;
- uint8 _blend;
- Common::Array<Sprite *> _sprites;
- Common::Array<Common::Rect > _drawRects;
- DirectorEngine *_vm;
-};
-
struct Label {
Common::String name;
uint16 number;
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
new file mode 100644
index 0000000000..7fd5b3d055
--- /dev/null
+++ b/engines/director/sprite.cpp
@@ -0,0 +1,85 @@
+/* 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/score.h"
+#include "director/sprite.h"
+
+namespace Director {
+
+Sprite::Sprite() {
+ _enabled = false;
+ _trails = 0;
+ _width = 0;
+ _ink = kInkTypeCopy;
+ _flags = 0;
+ _height = 0;
+ _castId = 0;
+ _constraint = 0;
+ _moveable = 0;
+ _castId = 0;
+ _backColor = 0;
+ _foreColor = 0;
+ _left = 0;
+ _right = 0;
+ _top = 0;
+ _bottom = 0;
+ _visible = false;
+ _movieRate = 0;
+ _movieTime = 0;
+ _startTime = 0;
+ _stopTime = 0;
+ _volume = 0;
+ _stretch = 0;
+ _type = kInactiveSprite;
+}
+
+Sprite::Sprite(const Sprite &sprite) {
+ _enabled = sprite._enabled;
+ _castId = sprite._castId;
+ _flags = sprite._flags;
+ _trails = sprite._trails;
+ _ink = sprite._ink;
+ _width = sprite._width;
+ _height = sprite._height;
+ _startPoint.x = sprite._startPoint.x;
+ _startPoint.y = sprite._startPoint.y;
+ _backColor = sprite._backColor;
+ _foreColor = sprite._foreColor;
+ _left = sprite._left;
+ _right = sprite._right;
+ _top = sprite._top;
+ _bottom = sprite._bottom;
+ _visible = sprite._visible;
+ _movieRate = sprite._movieRate;
+ _movieTime = sprite._movieTime;
+ _stopTime = sprite._stopTime;
+ _volume = sprite._volume;
+ _stretch = sprite._stretch;
+ _type = sprite._type;
+}
+
+Sprite::~Sprite() {
+ delete _cast;
+}
+
+} //End of namespace Director
diff --git a/engines/director/sprite.h b/engines/director/sprite.h
new file mode 100644
index 0000000000..c66c66d6e4
--- /dev/null
+++ b/engines/director/sprite.h
@@ -0,0 +1,137 @@
+/* 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_SPRITE_H
+#define DIRECTOR_SPRITE_H
+
+#include "common/rect.h"
+
+namespace Director {
+
+enum InkType {
+ kInkTypeCopy,
+ kInkTypeTransparent,
+ kInkTypeReverse,
+ kInkTypeGhost,
+ kInkTypeNotCopy,
+ kInkTypeNotTrans,
+ kInkTypeNotReverse,
+ kInkTypeNotGhost,
+ kInkTypeMatte,
+ kInkTypeMask,
+ //10-31 Not used (Lingo in a Nutshell)
+ kInkTypeBlend = 32,
+ kInkTypeAddPin,
+ kInkTypeAdd,
+ kInkTypeSubPin,
+ kInkTypeBackgndTrans,
+ kInkTypeLight,
+ kInkTypeSub,
+ kInkTypeDark
+};
+
+//Director v4
+enum SpriteType {
+ kInactiveSprite, //turns the sprite off
+ kBitmapSprite,
+ kRectangleSprite,
+ kRoundedRectangleSprite,
+ kOvalSprite,
+ kLineTopBottomSprite, //line from top left to bottom right
+ kLineBottomTopSprite, //line from bottom left to top right
+ kTextSprite,
+ kButtonSprite,
+ kCheckboxSprite,
+ kRadioButtonSprite,
+ kUndeterminedSprite = 16 //use castType property to examine the type of cast member associated with sprite
+};
+
+enum SpritePosition {
+ kSpritePositionUnk1 = 0,
+ kSpritePositionEnabled,
+ kSpritePositionUnk2,
+ kSpritePositionFlags = 4,
+ kSpritePositionCastId = 6,
+ kSpritePositionY = 8,
+ kSpritePositionX = 10,
+ kSpritePositionHeight = 12,
+ kSpritePositionWidth = 14
+};
+
+enum MainChannelsPosition {
+ kScriptIdPosition = 0,
+ kSoundType1Position,
+ kTransFlagsPosition,
+ kTransChunkSizePosition,
+ kTempoPosition,
+ kTransTypePosition,
+ kSound1Position,
+ kSkipFrameFlagsPosition = 8,
+ kBlendPosition,
+ kSound2Position,
+ kSound2TypePosition = 11,
+ kPaletePosition = 15
+};
+
+class Sprite {
+public:
+ Sprite();
+ Sprite(const Sprite &sprite);
+ ~Sprite();
+ bool _enabled;
+ byte _castId;
+ InkType _ink;
+ uint16 _trails;
+ Cast *_cast;
+ uint16 _flags;
+ Common::Point _startPoint;
+ uint16 _width;
+ uint16 _height;
+ //TODO: default constraint = 0, if turned on, sprite is constrainted to the bounding rect
+ //As i know, constrainted != 0 only if sprite moveable
+ byte _constraint;
+ byte _moveable;
+ byte _backColor;
+ byte _foreColor;
+ uint16 _left;
+ uint16 _right;
+ uint16 _top;
+ uint16 _bottom;
+ byte _blend;
+ bool _visible;
+ SpriteType _type;
+ //Using in digital movie sprites
+ byte _movieRate;
+ uint16 _movieTime;
+ uint16 _startTime;
+ uint16 _stopTime;
+ byte _volume;
+ byte _stretch;
+ //Using in shape sprites
+ byte _lineSize;
+ //Using in text sprites
+ Common::String _editableText;
+};
+
+} //End of namespace Director
+
+#endif