aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/draci/animation.cpp91
-rw-r--r--engines/draci/animation.h40
-rw-r--r--engines/draci/game.cpp22
-rw-r--r--engines/draci/game.h6
-rw-r--r--engines/draci/script.cpp28
-rw-r--r--engines/draci/script.h2
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> &params) {
_vm->_game->setVariable(var, value);
}
+void Script::mark(Common::Queue<int> &params) {
+ _vm->_game->setMarkedAnimationIndex(_vm->_anims->getLastIndex());
+}
+
+void Script::release(Common::Queue<int> &params) {
+ 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> &params);
void load(Common::Queue<int> &params);
void start(Common::Queue<int> &params);
+ void mark(Common::Queue<int> &params);
+ void release(Common::Queue<int> &params);
int operAnd(int op1, int op2);
int operOr(int op1, int op2);