From c4e5cf96aca973297f463d1b327ffa35cf74b28c Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Mon, 18 Jul 2011 21:50:24 +0200 Subject: COMPOSER: Move graphics-related code into graphics.cpp. --- engines/composer/composer.cpp | 654 +-------------------------------------- engines/composer/composer.h | 45 +-- engines/composer/graphics.cpp | 696 ++++++++++++++++++++++++++++++++++++++++++ engines/composer/graphics.h | 74 +++++ engines/composer/module.mk | 1 + 5 files changed, 774 insertions(+), 696 deletions(-) create mode 100644 engines/composer/graphics.cpp create mode 100644 engines/composer/graphics.h (limited to 'engines/composer') diff --git a/engines/composer/composer.cpp b/engines/composer/composer.cpp index 4ec3c1e356..656030f1f1 100644 --- a/engines/composer/composer.cpp +++ b/engines/composer/composer.cpp @@ -37,28 +37,18 @@ #include "graphics/cursorman.h" #include "graphics/surface.h" #include "graphics/pixelformat.h" -#include "graphics/palette.h" #include "engines/util.h" #include "engines/advancedDetector.h" #include "audio/audiostream.h" -#include "audio/decoders/raw.h" #include "composer/composer.h" +#include "composer/graphics.h" #include "composer/resource.h" namespace Composer { -// bitmap compression types -enum { - kBitmapUncompressed = 0, - kBitmapSpp32 = 1, - kBitmapSLW8 = 3, - kBitmapRLESLWM = 4, - kBitmapSLWM = 5 -}; - // new script ops enum { kOpPlusPlus = 0x1, @@ -134,49 +124,6 @@ enum { kFuncGetSpriteSize = 35029 }; -bool Sprite::contains(const Common::Point &pos) const { - Common::Point adjustedPos = pos - _pos; - - if (adjustedPos.x < 0 || adjustedPos.x >= _surface.w) - return false; - if (adjustedPos.y < 0 || adjustedPos.y >= _surface.h) - return false; - byte *pixels = (byte *)_surface.pixels; - return (pixels[(_surface.h - adjustedPos.y - 1) * _surface.w + adjustedPos.x] != 0); -} - -Animation::Animation(Common::SeekableReadStream *stream, uint16 id, Common::Point basePos, uint32 eventParam) - : _stream(stream), _id(id), _basePos(basePos), _eventParam(eventParam) { - uint32 size = _stream->readUint32LE(); - _state = _stream->readUint32LE() + 1; - - // probably total size? - uint32 unknown = _stream->readUint32LE(); - - debug(8, "anim: size %d, state %08x, unknown %08x", size, _state, unknown); - - for (uint i = 0; i < size; i++) { - AnimationEntry entry; - entry.op = _stream->readUint16LE(); - entry.priority = _stream->readUint16LE(); - entry.state = _stream->readUint16LE(); - entry.counter = 0; - entry.prevValue = 0; - debug(8, "anim entry: %04x, %04x, %04x", entry.op, entry.priority, entry.state); - _entries.push_back(entry); - } - - _offset = _stream->pos(); -} - -Animation::~Animation() { - delete _stream; -} - -void Animation::seekToCurrPos() { - _stream->seek(_offset, SEEK_SET); -} - Pipe::Pipe(Common::SeekableReadStream *stream) { _offset = 0; _stream = stream; @@ -325,364 +272,6 @@ bool Button::contains(const Common::Point &pos) const { } } -void ComposerEngine::playAnimation(uint16 animId, int16 x, int16 y, int16 eventParam) { - // First, we check if this animation is already playing, - // and if it is, we sabotage that running one first. - for (Common::List::iterator i = _anims.begin(); i != _anims.end(); i++) { - Animation *anim = *i; - if (anim->_id != animId) - continue; - - stopAnimation(*i); - } - - Common::SeekableReadStream *stream = NULL; - Pipe *newPipe = NULL; - - // First, check the existing pipes. - for (Common::List::iterator j = _pipes.begin(); j != _pipes.end(); j++) { - Pipe *pipe = *j; - if (!pipe->hasResource(ID_ANIM, animId)) - continue; - stream = pipe->getResource(ID_ANIM, animId, false); - break; - } - - // If we didn't find it, try the libraries. - if (!stream) { - if (!hasResource(ID_ANIM, animId)) { - warning("ignoring attempt to play invalid anim %d", animId); - return; - } - stream = getResource(ID_ANIM, animId); - - uint32 type = 0; - for (Common::List::iterator i = _libraries.begin(); i != _libraries.end(); i++) - if (i->_archive->hasResource(ID_ANIM, animId)) { - type = i->_archive->getResourceFlags(ID_ANIM, animId); - break; - } - - // If the resource is a pipe itself, then load the pipe - // and then fish the requested animation out of it. - if (type != 1) { - newPipe = new Pipe(stream); - _pipes.push_front(newPipe); - stream = newPipe->getResource(ID_ANIM, animId, false); - } - } - - Animation *anim = new Animation(stream, animId, Common::Point(x, y), eventParam); - _anims.push_back(anim); - runEvent(1, animId, eventParam, 0); - if (newPipe) - newPipe->_anim = anim; -} - -void ComposerEngine::stopAnimation(Animation *anim, bool localOnly, bool pipesOnly) { - // disable the animation - anim->_state = 0; - - // stop any animations it may have spawned - for (uint j = 0; j < anim->_entries.size(); j++) { - AnimationEntry &entry = anim->_entries[j]; - if (!entry.prevValue) - continue; - if (localOnly) { - if (pipesOnly) - continue; - if (entry.op == kAnimOpDrawSprite) { - removeSprite(entry.prevValue, anim->_id); - } else if (entry.op == kAnimOpPlayWave) { - if (_currSoundPriority >= entry.priority) { - _mixer->stopAll(); - _audioStream = NULL; - } - } - } else { - if (entry.op != kAnimOpPlayAnim) - continue; - for (Common::List::iterator i = _anims.begin(); i != _anims.end(); i++) { - if ((*i)->_id == entry.prevValue) - stopAnimation(*i); - } - } - } - - // kill any pipe owned by the animation - for (Common::List::iterator j = _pipes.begin(); j != _pipes.end(); j++) { - Pipe *pipe = *j; - if (pipe->_anim != anim) - continue; - j = _pipes.reverse_erase(j); - delete pipe; - break; - } -} - -void ComposerEngine::playWaveForAnim(uint16 id, uint16 priority, bool bufferingOnly) { - if (_audioStream && _audioStream->numQueuedStreams() != 0) { - if (_currSoundPriority < priority) - return; - if (_currSoundPriority > priority) { - _mixer->stopAll(); - _audioStream = NULL; - } - } - Common::SeekableReadStream *stream = NULL; - if (!bufferingOnly && hasResource(ID_WAVE, id)) { - stream = getResource(ID_WAVE, id); - } else { - for (Common::List::iterator k = _pipes.begin(); k != _pipes.end(); k++) { - Pipe *pipe = *k; - if (!pipe->hasResource(ID_WAVE, id)) - continue; - stream = pipe->getResource(ID_WAVE, id, true); - break; - } - } - if (!stream) - return; - // FIXME: non-pipe buffers have fixed wav header (data at +44, size at +40) - byte *buffer = (byte *)malloc(stream->size()); - stream->read(buffer, stream->size()); - if (!_audioStream) - _audioStream = Audio::makeQueuingAudioStream(22050, false); - _audioStream->queueBuffer(buffer, stream->size(), DisposeAfterUse::YES, Audio::FLAG_UNSIGNED); - _currSoundPriority = priority; - delete stream; - if (!_mixer->isSoundHandleActive(_soundHandle)) - _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream); -} - -void ComposerEngine::processAnimFrame() { - for (Common::List::iterator i = _anims.begin(); i != _anims.end(); i++) { - Animation *anim = *i; - - anim->seekToCurrPos(); - - if (anim->_state <= 1) { - bool normalEnd = (anim->_state == 1); - if (normalEnd) { - runEvent(2, anim->_id, anim->_eventParam, 0); - } - stopAnimation(anim, true, normalEnd); - delete anim; - i = _anims.reverse_erase(i); - - continue; - } - - for (uint j = 0; j < anim->_entries.size(); j++) { - AnimationEntry &entry = anim->_entries[j]; - if (entry.op != kAnimOpEvent) - break; - if (entry.counter) { - entry.counter--; - } else { - if ((anim->_state > 1) && (anim->_stream->pos() + 2 > anim->_stream->size())) { - warning("anim with id %d ended too soon", anim->_id); - anim->_state = 0; - break; - } - - uint16 event = anim->_stream->readUint16LE(); - anim->_offset += 2; - if (event == 0xffff) { - entry.counter = anim->_stream->readUint16LE() - 1; - anim->_offset += 2; - } else { - debug(4, "anim: event %d", event); - runEvent(event, anim->_id, 0, 0); - } - } - } - } - - for (Common::List::iterator i = _anims.begin(); i != _anims.end(); i++) { - Animation *anim = *i; - - // did the anim get disabled? - if (anim->_state == 0) { - stopAnimation(anim, true, false); - delete anim; - i = _anims.reverse_erase(i); - continue; - } - - anim->_state--; - - bool foundWait = false; - for (uint j = 0; j < anim->_entries.size(); j++) { - AnimationEntry &entry = anim->_entries[j]; - - // only skip these at the start - if (!foundWait && (entry.op == kAnimOpEvent)) - continue; - foundWait = true; - - if (entry.counter) { - entry.counter--; - if ((entry.op == kAnimOpPlayWave) && entry.prevValue) { - debug(4, "anim: continue play wave %d", entry.prevValue); - playWaveForAnim(entry.prevValue, entry.priority, true); - } - } else { - anim->seekToCurrPos(); - if ((anim->_state > 1) && (anim->_stream->pos() + 2 > anim->_stream->size())) { - warning("anim with id %d ended too soon", anim->_id); - anim->_state = 0; - break; - } - - uint16 data = anim->_stream->readUint16LE(); - anim->_offset += 2; - if (data == 0xffff) { - entry.counter = anim->_stream->readUint16LE() - 1; - anim->_offset += 2; - } else { - switch (entry.op) { - case kAnimOpEvent: - debug(4, "anim: event %d", data); - runEvent(data, anim->_id, 0, 0); - break; - case kAnimOpPlayWave: - debug(4, "anim: play wave %d", data); - playWaveForAnim(data, entry.priority, false); - break; - case kAnimOpPlayAnim: - debug(4, "anim: play anim %d", data); - playAnimation(data, anim->_basePos.x, anim->_basePos.y, 1); - break; - case kAnimOpDrawSprite: - if (!data || (entry.prevValue && (data != entry.prevValue))) { - debug(4, "anim: erase sprite %d", entry.prevValue); - removeSprite(entry.prevValue, anim->_id); - } - if (data) { - int16 x = anim->_stream->readSint16LE(); - int16 y = anim->_stream->readSint16LE(); - Common::Point pos(x, y); - anim->_offset += 4; - uint16 animId = anim->_id; - if (anim->_state == entry.state) - animId = 0; - debug(4, "anim: draw sprite %d at (relative) %d,%d", data, x, y); - bool wasVisible = spriteVisible(data, animId); - addSprite(data, animId, entry.priority, anim->_basePos + pos); - if (wasVisible) { - // make sure modified sprite isn't removed by another entry - for (uint k = 0; k < anim->_entries.size(); k++) { - if (anim->_entries[k].op != kAnimOpDrawSprite) - continue; - if (anim->_entries[k].prevValue == data) - anim->_entries[k].prevValue = 1; - } - } - } - break; - default: - warning("unknown anim op %d", entry.op); - } - - entry.prevValue = data; - } - } - } - } - - for (Common::List::iterator j = _pipes.begin(); j != _pipes.end(); j++) { - Pipe *pipe = *j; - pipe->nextFrame(); - } -} - -bool ComposerEngine::spriteVisible(uint16 id, uint16 animId) { - for (Common::List::iterator i = _sprites.begin(); i != _sprites.end(); i++) { - if (i->_id != id) - continue; - if (i->_animId && animId && (i->_animId != animId)) - continue; - return true; - } - - return false; -} - -void ComposerEngine::addSprite(uint16 id, uint16 animId, uint16 zorder, const Common::Point &pos) { - Sprite sprite; - bool foundSprite = false; - - // re-use old sprite, if any (the BMAP for this id might well have - // changed in the meantime, but the scripts depend on that!) - for (Common::List::iterator i = _sprites.begin(); i != _sprites.end(); i++) { - if (i->_id != id) - continue; - if (i->_animId && animId && (i->_animId != animId)) - continue; - - // if the zordering is identical, modify it in-place - if (i->_zorder == zorder) { - i->_animId = animId; - i->_pos = pos; - return; - } - - // otherwise, take a copy and remove it from the list - sprite = *i; - foundSprite = true; - _sprites.erase(i); - break; - } - - sprite._animId = animId; - sprite._zorder = zorder; - sprite._pos = pos; - - if (!foundSprite) { - sprite._id = id; - if (!initSprite(sprite)) { - warning("ignoring addSprite on invalid sprite %d", id); - return; - } - } - - for (Common::List::iterator i = _sprites.begin(); i != _sprites.end(); i++) { - if (sprite._zorder <= i->_zorder) - continue; - // insert *before* this sprite - _sprites.insert(i, sprite); - return; - } - _sprites.push_back(sprite); -} - -void ComposerEngine::removeSprite(uint16 id, uint16 animId) { - for (Common::List::iterator i = _sprites.begin(); i != _sprites.end(); i++) { - if (id && i->_id != id) - continue; - if (i->_animId && animId && (i->_animId != animId)) - continue; - i->_surface.free(); - i = _sprites.reverse_erase(i); - if (id) - break; - } -} - -const Sprite *ComposerEngine::getSpriteAtPos(const Common::Point &pos) { - for (Common::List::iterator i = _sprites.reverse_begin(); i != _sprites.end(); --i) { - // avoid highest-level objects (e.g. the cursor) - if (!i->_zorder) - continue; - - if (i->contains(pos)) - return &(*i); - } - - return NULL; -} - const Button *ComposerEngine::getButtonFor(const Sprite *sprite, const Common::Point &pos) { for (Common::List