2015-03-15 21:25:07 -04:00
|
|
|
/* 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.
|
2015-05-09 18:04:13 +02:00
|
|
|
*
|
2015-03-15 21:25:07 -04:00
|
|
|
* 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.
|
2015-05-09 18:04:13 +02:00
|
|
|
*
|
2015-03-15 21:25:07 -04:00
|
|
|
* 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 "sherlock/animation.h"
|
|
|
|
#include "sherlock/sherlock.h"
|
|
|
|
#include "common/algorithm.h"
|
|
|
|
|
|
|
|
namespace Sherlock {
|
|
|
|
|
|
|
|
static const int NO_FRAMES = FRAMES_END;
|
|
|
|
|
2015-05-18 18:20:54 +01:00
|
|
|
Animation::Animation(SherlockEngine *vm) : _vm(vm) {
|
2015-03-15 21:25:07 -04:00
|
|
|
}
|
|
|
|
|
2015-05-07 19:33:44 +02:00
|
|
|
bool Animation::play(const Common::String &filename, int minDelay, int fade,
|
2015-03-15 21:25:07 -04:00
|
|
|
bool setPalette, int speed) {
|
2015-03-21 20:25:15 -04:00
|
|
|
Events &events = *_vm->_events;
|
2015-03-16 08:07:24 -04:00
|
|
|
Screen &screen = *_vm->_screen;
|
2015-03-16 22:42:19 -04:00
|
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
int soundNumber = 0;
|
2015-03-16 08:07:24 -04:00
|
|
|
|
2015-03-15 21:25:07 -04:00
|
|
|
// Check for any any sound frames for the given animation
|
|
|
|
const int *soundFrames = checkForSoundFrames(filename);
|
|
|
|
|
2015-05-09 08:41:13 -04:00
|
|
|
// Add on the VDX extension
|
|
|
|
Common::String vdxName = filename + ".vdx";
|
2015-03-15 21:25:07 -04:00
|
|
|
|
|
|
|
// Load the animation
|
|
|
|
Common::SeekableReadStream *stream;
|
2015-05-18 19:53:49 -04:00
|
|
|
if (!_gfxLibraryFilename.empty())
|
|
|
|
stream = _vm->_res->load(vdxName, _gfxLibraryFilename);
|
2015-03-15 23:16:38 -04:00
|
|
|
else if (_vm->_useEpilogue2)
|
2015-03-15 21:25:07 -04:00
|
|
|
stream = _vm->_res->load(vdxName, "epilog2.lib");
|
|
|
|
else
|
2015-04-30 15:20:48 -10:00
|
|
|
stream = _vm->_res->load(vdxName, "epilogue.lib");
|
2015-03-15 21:25:07 -04:00
|
|
|
|
|
|
|
// Load initial image
|
2015-05-09 08:41:13 -04:00
|
|
|
Common::String vdaName = filename + ".vda";
|
2015-05-01 12:29:40 -10:00
|
|
|
ImageFile images(vdaName, true, true);
|
2015-05-07 19:33:44 +02:00
|
|
|
|
2015-03-17 23:09:04 -04:00
|
|
|
events.wait(minDelay);
|
2015-03-16 08:07:24 -04:00
|
|
|
if (fade != 0 && fade != 255)
|
|
|
|
screen.fadeToBlack();
|
2015-03-16 23:38:58 -04:00
|
|
|
|
2015-03-16 08:07:24 -04:00
|
|
|
if (setPalette) {
|
|
|
|
if (fade != 255)
|
2015-03-19 19:49:42 -04:00
|
|
|
screen.setPalette(images._palette);
|
2015-03-16 08:07:24 -04:00
|
|
|
}
|
|
|
|
|
2015-03-16 22:42:19 -04:00
|
|
|
int frameNumber = 0;
|
|
|
|
Common::Point pt;
|
|
|
|
bool skipped = false;
|
|
|
|
while (!_vm->shouldQuit()) {
|
2015-03-16 23:38:58 -04:00
|
|
|
// Get the next sprite to display
|
2015-05-07 18:21:25 +02:00
|
|
|
int imageFrame = stream->readSint16LE();
|
2015-03-16 23:38:58 -04:00
|
|
|
|
2015-03-19 19:49:42 -04:00
|
|
|
if (imageFrame == -2) {
|
2015-03-16 23:38:58 -04:00
|
|
|
// End of animation reached
|
|
|
|
break;
|
2015-03-19 19:49:42 -04:00
|
|
|
} else if (imageFrame != -1) {
|
2015-03-16 23:38:58 -04:00
|
|
|
// Read position from either animation stream or the sprite frame itself
|
2015-03-19 19:49:42 -04:00
|
|
|
if (imageFrame < 0) {
|
2015-05-01 12:29:40 -10:00
|
|
|
imageFrame += 32768;
|
2015-03-16 22:42:19 -04:00
|
|
|
pt.x = stream->readUint16LE();
|
|
|
|
pt.y = stream->readUint16LE();
|
|
|
|
} else {
|
2015-03-21 20:25:15 -04:00
|
|
|
pt = images[imageFrame]._offset;
|
2015-03-16 22:42:19 -04:00
|
|
|
}
|
|
|
|
|
2015-05-01 12:29:40 -10:00
|
|
|
// Draw the sprite. Note that we explicitly use the raw frame below, rather than the ImageFrame,
|
|
|
|
// since we don't want the offsets in the image file to be used, just the explicit position we specify
|
|
|
|
screen.transBlitFrom(images[imageFrame]._frame, pt);
|
2015-03-16 22:42:19 -04:00
|
|
|
} else {
|
2015-05-09 08:56:12 -04:00
|
|
|
// At this point, either the sprites for the frame has been complete, or there weren't any sprites
|
|
|
|
// at all to draw for the frame
|
2015-03-16 22:42:19 -04:00
|
|
|
if (fade == 255) {
|
|
|
|
// Gradual fade in
|
2015-03-19 19:49:42 -04:00
|
|
|
if (screen.equalizePalette(images._palette) == 0)
|
2015-03-16 22:42:19 -04:00
|
|
|
fade = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we've reached a frame with sound
|
|
|
|
if (frameNumber++ == *soundFrames) {
|
|
|
|
++soundNumber;
|
|
|
|
++soundFrames;
|
2015-05-18 19:53:49 -04:00
|
|
|
Common::String fname = _soundLibraryFilename.empty() ?
|
2015-05-09 08:41:13 -04:00
|
|
|
Common::String::format("%s%01d", filename.c_str(), soundNumber) :
|
|
|
|
Common::String::format("%s%02d", filename.c_str(), soundNumber);
|
2015-03-16 22:42:19 -04:00
|
|
|
|
2015-04-10 23:35:26 -05:00
|
|
|
if (sound._voices)
|
2015-05-18 19:53:49 -04:00
|
|
|
sound.playSound(fname, WAIT_RETURN_IMMEDIATELY, 100, _soundLibraryFilename.c_str());
|
2015-03-16 22:42:19 -04:00
|
|
|
}
|
|
|
|
|
2015-05-12 20:40:47 -04:00
|
|
|
events.wait(speed * 3);
|
2015-03-16 22:42:19 -04:00
|
|
|
}
|
2015-03-15 21:25:07 -04:00
|
|
|
|
2015-03-23 20:34:34 -04:00
|
|
|
if (events.kbHit()) {
|
2015-03-16 22:42:19 -04:00
|
|
|
Common::KeyState keyState = events.getKey();
|
|
|
|
if (keyState.keycode == Common::KEYCODE_ESCAPE ||
|
|
|
|
keyState.keycode == Common::KEYCODE_SPACE) {
|
|
|
|
skipped = true;
|
|
|
|
break;
|
|
|
|
}
|
2015-03-23 20:34:34 -04:00
|
|
|
} else if (events._pressed) {
|
2015-03-16 22:42:19 -04:00
|
|
|
skipped = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-05-07 19:33:44 +02:00
|
|
|
|
2015-03-16 22:42:19 -04:00
|
|
|
events.clearEvents();
|
|
|
|
sound.stopSound();
|
2015-03-15 21:25:07 -04:00
|
|
|
delete stream;
|
2015-03-16 22:42:19 -04:00
|
|
|
|
|
|
|
return !skipped && !_vm->shouldQuit();
|
2015-03-15 21:25:07 -04:00
|
|
|
}
|
|
|
|
|
2015-05-12 00:42:57 +01:00
|
|
|
void Animation::setPrologueNames(const char *const *names, int count) {
|
2015-05-18 18:30:31 -04:00
|
|
|
for (int idx = 0; idx < count; ++idx, ++names) {
|
2015-05-12 00:42:57 +01:00
|
|
|
_prologueNames.push_back(*names);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Animation::setPrologueFrames(const int *frames, int count, int maxFrames) {
|
|
|
|
_prologueFrames.resize(count);
|
|
|
|
|
2015-05-12 18:00:35 +01:00
|
|
|
for (int idx = 0; idx < count; ++idx, frames += maxFrames) {
|
2015-05-12 00:42:57 +01:00
|
|
|
_prologueFrames[idx].resize(maxFrames);
|
|
|
|
Common::copy(frames, frames + maxFrames, &_prologueFrames[idx][0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Animation::setTitleNames(const char *const *names, int count) {
|
2015-05-18 18:30:31 -04:00
|
|
|
for (int idx = 0; idx < count; ++idx, ++names) {
|
2015-05-12 00:42:57 +01:00
|
|
|
_titleNames.push_back(*names);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Animation::setTitleFrames(const int *frames, int count, int maxFrames) {
|
|
|
|
_titleFrames.resize(count);
|
|
|
|
|
2015-05-12 18:00:35 +01:00
|
|
|
for (int idx = 0; idx < count; ++idx, frames += maxFrames) {
|
2015-05-12 00:42:57 +01:00
|
|
|
_titleFrames[idx].resize(maxFrames);
|
|
|
|
Common::copy(frames, frames + maxFrames, &_titleFrames[idx][0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-15 21:25:07 -04:00
|
|
|
const int *Animation::checkForSoundFrames(const Common::String &filename) {
|
|
|
|
const int *frames = &NO_FRAMES;
|
|
|
|
|
2015-05-18 19:53:49 -04:00
|
|
|
if (_soundLibraryFilename.empty()) {
|
2015-05-18 18:30:31 -04:00
|
|
|
for (uint idx = 0; idx < _prologueNames.size(); ++idx) {
|
2015-05-12 00:42:57 +01:00
|
|
|
if (filename.equalsIgnoreCase(_prologueNames[idx])) {
|
|
|
|
frames = &_prologueFrames[idx][0];
|
2015-03-15 21:25:07 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2015-05-18 18:30:31 -04:00
|
|
|
for (uint idx = 0; idx < _titleNames.size(); ++idx) {
|
2015-05-12 00:42:57 +01:00
|
|
|
if (filename.equalsIgnoreCase(_titleNames[idx])) {
|
|
|
|
frames = &_titleFrames[idx][0];
|
2015-03-15 21:25:07 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return frames;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // End of namespace Sherlock
|