diff options
-rw-r--r-- | engines/draci/animation.cpp | 91 | ||||
-rw-r--r-- | engines/draci/animation.h | 40 | ||||
-rw-r--r-- | engines/draci/game.cpp | 22 | ||||
-rw-r--r-- | engines/draci/game.h | 6 | ||||
-rw-r--r-- | engines/draci/script.cpp | 28 | ||||
-rw-r--r-- | engines/draci/script.h | 2 |
6 files changed, 172 insertions, 17 deletions
diff --git a/engines/draci/animation.cpp b/engines/draci/animation.cpp index 74e876401d..83a21ee543 100644 --- a/engines/draci/animation.cpp +++ b/engines/draci/animation.cpp @@ -28,8 +28,9 @@ namespace Draci { -Animation::Animation(DraciEngine *vm) : _vm(vm) { +Animation::Animation(DraciEngine *vm, int index) : _vm(vm) { _id = kUnused; + _index = index; _z = 0; _relX = 0; _relY = 0; @@ -201,6 +202,11 @@ void Animation::setPlaying(bool playing) { } void Animation::setScaleFactors(double scaleX, double scaleY) { + + debugC(5, kDraciAnimationDebugLevel, + "Setting scaling factors on anim %d (scaleX: %.3f scaleY: %.3f)", + _id, scaleX, scaleY); + markDirtyRect(_vm->_screen->getSurface()); _scaleX = scaleX; @@ -211,6 +217,14 @@ void Animation::addFrame(Drawable *frame) { _frames.push_back(frame); } +int Animation::getIndex() { + return _index; +} + +void Animation::setIndex(int index) { + _index = index; +} + Drawable *Animation::getFrame(int frameNum) { // If no argument is passed, return the current frame @@ -235,7 +249,10 @@ void Animation::deleteFrames() { Animation *AnimationManager::addAnimation(int id, uint z, bool playing) { - Animation *anim = new Animation(_vm); + // Increment animation index + ++_lastIndex; + + Animation *anim = new Animation(_vm, _lastIndex); anim->setID(id); anim->setZ(z); @@ -249,26 +266,26 @@ Animation *AnimationManager::addAnimation(int id, uint z, bool playing) { void AnimationManager::play(int id) { Animation *anim = getAnimation(id); - // Mark the first frame dirty so it gets displayed - anim->markDirtyRect(_vm->_screen->getSurface()); - if (anim) { + // Mark the first frame dirty so it gets displayed + anim->markDirtyRect(_vm->_screen->getSurface()); + anim->setPlaying(true); - debugC(5, kDraciAnimationDebugLevel, "Playing animation %d...", id); + debugC(3, kDraciAnimationDebugLevel, "Playing animation %d...", id); } } void AnimationManager::stop(int id) { Animation *anim = getAnimation(id); - // Clean up the last frame that was drawn before stopping - anim->markDirtyRect(_vm->_screen->getSurface()); - if (anim) { + // Clean up the last frame that was drawn before stopping + anim->markDirtyRect(_vm->_screen->getSurface()); + anim->setPlaying(false); - debugC(5, kDraciAnimationDebugLevel, "Stopping animation %d...", id); + debugC(3, kDraciAnimationDebugLevel, "Stopping animation %d...", id); } } @@ -298,7 +315,11 @@ void AnimationManager::insertAnimation(Animation *animObj) { } void AnimationManager::addOverlay(Drawable *overlay, uint z) { - Animation *anim = new Animation(_vm); + // Since this is an overlay, we don't need it to be deleted + // when the GPL Release command is invoked so we pass the index + // as kIgnoreIndex + Animation *anim = new Animation(_vm, kIgnoreIndex); + anim->setID(kOverlayImage); anim->setZ(z); anim->setPlaying(true); @@ -362,17 +383,38 @@ void AnimationManager::deleteAnimation(int id) { Common::List<Animation *>::iterator it; + int index = -1; + + // Iterate for the first time to delete the animation for (it = _animations.begin(); it != _animations.end(); ++it) { if ((*it)->getID() == id) { (*it)->deleteFrames(); _animations.erase(it); + + // Remember index of the deleted animation + index = (*it)->getIndex(); + + debugC(3, kDraciAnimationDebugLevel, "Deleting animation %d...", id); + break; } } + + // Iterate the second time to decrease indexes greater than the deleted animation index + for (it = _animations.begin(); it != _animations.end(); ++it) { + if ((*it)->getIndex() == index && (*it)->getIndex() != kIgnoreIndex) { + (*it)->setIndex(index-1); + } + } + + // Decrement index of last animation + _lastIndex -= 1; } void AnimationManager::deleteOverlays() { + debugC(3, kDraciAnimationDebugLevel, "Deleting overlays..."); + Common::List<Animation *>::iterator it; for (it = _animations.begin(); it != _animations.end(); ++it) { @@ -384,7 +426,9 @@ void AnimationManager::deleteOverlays() { } void AnimationManager::deleteAll() { - + + debugC(3, kDraciAnimationDebugLevel, "Deleting all animations..."); + Common::List<Animation *>::iterator it; for (it = _animations.begin(); it != _animations.end(); ++it) { @@ -392,6 +436,29 @@ void AnimationManager::deleteAll() { } _animations.clear(); + + _lastIndex = -1; +} + +int AnimationManager::getLastIndex() { + return _lastIndex; +} + +void AnimationManager::deleteAfterIndex(int index) { + + Common::List<Animation *>::iterator it; + + for (it = _animations.begin(); it != _animations.end(); ++it) { + if ((*it)->getIndex() > index) { + + debugC(3, kDraciAnimationDebugLevel, "Deleting animation %d...", (*it)->getID()); + + (*it)->deleteFrames(); + _animations.erase(it); + } + } + + _lastIndex = index; } } diff --git a/engines/draci/animation.h b/engines/draci/animation.h index 683af7c812..5229972543 100644 --- a/engines/draci/animation.h +++ b/engines/draci/animation.h @@ -30,16 +30,30 @@ namespace Draci { +/** + * Animation IDs for those animations that don't have their IDs + * specified in the data files. + */ enum { kOverlayImage = -1, kWalkingMapOverlay = -2, kUnused = -3 }; +/** + * Default argument to Animation::getFrame() that makes it return + * the current frame instead of the user specifying it. + */ enum { kCurrentFrame = -1 }; +/** + * Used by overlays as a neutral index that won't get + * released with the GPL Release command. + */ +enum { kIgnoreIndex = -2 }; + class DraciEngine; class Animation { public: - Animation(DraciEngine *vm); + Animation(DraciEngine *v, int index); ~Animation(); uint getZ(); @@ -66,6 +80,9 @@ public: int getRelativeX(); int getRelativeY(); + int getIndex(); + void setIndex(int index); + void setScaleFactors(double scaleX, double scaleY); void markDirtyRect(Surface *surface); @@ -74,7 +91,16 @@ private: uint nextFrameNum(); - int _id; + /** Internal animation ID + * (as specified in the data files and the bytecode) + */ + int _id; + + /** The recency index of an animation, i.e. the most recently added animation has + * the highest index. Some script commands need this. + */ + int _index; + uint _currentFrame; uint _z; @@ -96,7 +122,7 @@ private: class AnimationManager { public: - AnimationManager(DraciEngine *vm) : _vm(vm) {}; + AnimationManager(DraciEngine *vm) : _vm(vm), _lastIndex(-1) {} ~AnimationManager() { deleteAll(); } Animation *addAnimation(int id, uint z, bool playing = false); @@ -113,12 +139,20 @@ public: Animation *getAnimation(int id); + int getLastIndex(); + void deleteAfterIndex(int index); + private: void sortAnimations(); void insertAnimation(Animation *anim); DraciEngine *_vm; Common::List<Animation *> _animations; + + /** The index of the most recently added animation. + * See Animation::_index for details. + */ + int _lastIndex; }; } diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index de925fe11f..e85a1780db 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -448,6 +448,10 @@ GameObject *Game::getObject(uint objNum) { return _objects + objNum; } +uint Game::getNumObjects() { + return _info._numObjects; +} + void Game::loadOverlays() { uint x, y, z, num; @@ -533,6 +537,24 @@ int Game::getIconStatus(int iconID) { return _iconStatus[iconID]; } +/** + * The GPL command Mark sets the animation index (which specifies the order in which + * animations were loaded in) which is then used by the Release command to delete + * all animations that have an index greater than the one marked. + */ + +int Game::getMarkedAnimationIndex() { + return _markedAnimationIndex; +} + +/** + * See Game::getMarkedAnimationIndex(). + */ + +void Game::setMarkedAnimationIndex(int index) { + _markedAnimationIndex = index; +} + Game::~Game() { delete[] _persons; delete[] _variables; diff --git a/engines/draci/game.h b/engines/draci/game.h index 511ce95e85..d4c9c256ee 100644 --- a/engines/draci/game.h +++ b/engines/draci/game.h @@ -177,6 +177,7 @@ public: void loadOverlays(); void loadObject(uint numObj); + uint getNumObjects(); GameObject *getObject(uint objNum); int getVariable(int varNum); @@ -184,6 +185,9 @@ public: int getIconStatus(int iconID); + int getMarkedAnimationIndex(); + void setMarkedAnimationIndex(int index); + private: DraciEngine *_vm; int *_variables; @@ -193,6 +197,8 @@ private: byte *_iconStatus; GameObject *_objects; Room _currentRoom; + + int _markedAnimationIndex; //!< Used by the Mark GPL command }; } // End of namespace Draci diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp index 2d0a33db86..2dd5d9288a 100644 --- a/engines/draci/script.cpp +++ b/engines/draci/script.cpp @@ -78,8 +78,8 @@ void Script::setupCommandList() { { 18, 3, "StopMusic", 0, { 0 }, NULL }, { 18, 4, "FadeOutMusic", 1, { 1 }, NULL }, { 18, 5, "FadeInMusic", 1, { 1 }, NULL }, - { 19, 1, "Mark", 0, { 0 }, NULL }, - { 19, 2, "Release", 0, { 0 }, NULL }, + { 19, 1, "Mark", 0, { 0 }, &Script::mark }, + { 19, 2, "Release", 0, { 0 }, &Script::release }, { 20, 1, "Play", 0, { 0 }, NULL }, { 21, 1, "LoadMap", 1, { 2 }, NULL }, { 21, 2, "RoomMap", 0, { 0 }, NULL }, @@ -307,6 +307,30 @@ void Script::c_Let(Common::Queue<int> ¶ms) { _vm->_game->setVariable(var, value); } +void Script::mark(Common::Queue<int> ¶ms) { + _vm->_game->setMarkedAnimationIndex(_vm->_anims->getLastIndex()); +} + +void Script::release(Common::Queue<int> ¶ms) { + int markedIndex = _vm->_game->getMarkedAnimationIndex(); + + // Also delete those animations from the game's objects + for (uint i = 0; i < _vm->_game->getNumObjects(); ++i) { + GameObject *obj = _vm->_game->getObject(i); + + for (uint j = 0; j < obj->_anims.size(); ++j) { + Animation *anim; + + anim = _vm->_anims->getAnimation(obj->_anims[j]); + if (anim != NULL && anim->getIndex() > markedIndex) + obj->_anims.remove_at(j); + } + } + + // Delete animations which have an index greater than the marked index + _vm->_anims->deleteAfterIndex(markedIndex); +} + /** * @brief Evaluates mathematical expressions * @param reader Stream reader set to the beginning of the expression diff --git a/engines/draci/script.h b/engines/draci/script.h index d8e9a2f49f..0cbb0b49fc 100644 --- a/engines/draci/script.h +++ b/engines/draci/script.h @@ -104,6 +104,8 @@ private: void c_Let(Common::Queue<int> ¶ms); void load(Common::Queue<int> ¶ms); void start(Common::Queue<int> ¶ms); + void mark(Common::Queue<int> ¶ms); + void release(Common::Queue<int> ¶ms); int operAnd(int op1, int op2); int operOr(int op1, int op2); |