ASYLUM: Convert Video to new event handling

- Change Text::LoadFont to return the previous font
- Fix AsylumEngine::processDelayedEvents not working properly for scenes
- Add two params to AsylumEvent (needed by video subtitle handling)

git-svn-id: http://asylumengine.googlecode.com/svn/trunk@681 0bfb4aae-4ea4-11de-8d8d-752d95cf3e3c
This commit is contained in:
Julien Templier 2010-12-08 06:51:15 +00:00 committed by Eugene Sandulenko
parent 26eacef2fc
commit ae4d75e6a0
No known key found for this signature in database
GPG key ID: 014D387312D34F08
13 changed files with 245 additions and 256 deletions

View file

@ -82,6 +82,10 @@ AsylumEngine::AsylumEngine(OSystem *system, const ADGameDescription *gd) : Engin
_introPlayed = false; _introPlayed = false;
_tickOffset = 0; _tickOffset = 0;
// Debug
_delayedSceneIndex = kResourcePackInvalid;
_delayedVideoIndex = -1;
// Add default search directories // Add default search directories
const Common::FSNode gameDataDir(ConfMan.get("path")); const Common::FSNode gameDataDir(ConfMan.get("path"));
SearchMan.addSubDirectoryMatching(gameDataDir, "data"); SearchMan.addSubDirectoryMatching(gameDataDir, "data");
@ -271,7 +275,7 @@ void AsylumEngine::playIntro() {
_sound->playMusic(kResourceNone, 0); _sound->playMusic(kResourceNone, 0);
// TODO convert to new event handling // TODO convert to new event handling
_video->playVideo(1); _video->play(1, _mainMenu);
if (_scene->worldstats()->musicCurrentResourceIndex != kMusicStopped) if (_scene->worldstats()->musicCurrentResourceIndex != kMusicStopped)
_sound->playMusic(MAKE_RESOURCE(kResourcePackMusic, _scene->worldstats()->musicCurrentResourceIndex)); _sound->playMusic(MAKE_RESOURCE(kResourcePackMusic, _scene->worldstats()->musicCurrentResourceIndex));
@ -356,7 +360,7 @@ void AsylumEngine::handleEvents() {
if (_handler) if (_handler)
_handler->handleEvent(updateEvt); _handler->handleEvent(updateEvt);
// TODO replace by original game code based on switchEventHandler // Handle debug events
processDelayedEvents(); processDelayedEvents();
} }
@ -364,30 +368,32 @@ void AsylumEngine::processDelayedEvents() {
if (!_video || !_sound || !_mainMenu) if (!_video || !_sound || !_mainMenu)
error("[AsylumEngine::processDelayedEvents] Subsystems not initialized properly!"); error("[AsylumEngine::processDelayedEvents] Subsystems not initialized properly!");
// check for a delayed video // check for a delayed scene change
int videoIdx = _script->getDelayedVideoIndex(); if (_delayedSceneIndex != kResourcePackInvalid && isGameFlagNotSet(kGameFlagScriptProcessing)) {
if (videoIdx >= 0) { ResourcePackId sceneIndex = _delayedSceneIndex;
_sound->stopMusic();
_sound->stopAll();
_video->playVideo(videoIdx);
_script->setDelayedVideoIndex(-1);
}
// check for a delayed scene change
ResourcePackId packId = _script->getDelayedSceneIndex();
if (packId != kResourcePackInvalid && isGameFlagNotSet(kGameFlagScriptProcessing)) {
// Reset delayed scene // Reset delayed scene
_script->setDelayedSceneIndex(kResourcePackInvalid); _delayedSceneIndex = kResourcePackInvalid;
_sound->stopMusic(); _sound->stopMusic();
_sound->stopAll(); _sound->stopAll();
switchEventHandler(NULL);
delete _scene; delete _scene;
_scene = new Scene(this); _scene = new Scene(this);
_scene->enter(packId); _scene->enter(sceneIndex);
switchEventHandler(_scene); switchEventHandler(_scene);
} }
// Check for delayed video
if (_delayedVideoIndex != -1 && isGameFlagNotSet(kGameFlagScriptProcessing)) {
int32 index = _delayedVideoIndex;
_delayedVideoIndex = -1;
_video->play(index, _handler);
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -412,11 +418,11 @@ void AsylumEngine::switchEventHandler(EventHandler *handler) {
_handler->handleEvent(init); _handler->handleEvent(init);
} }
void AsylumEngine::notify(AsylumEventType type) { void AsylumEngine::notify(AsylumEventType type, int32 param1, int32 param2) {
if (_handler == NULL) if (_handler == NULL)
error("[AsylumEngine::notify] Invalid handler parameter (cannot be NULL)!"); error("[AsylumEngine::notify] Invalid handler parameter (cannot be NULL)!");
AsylumEvent evt(type); AsylumEvent evt(type, param1, param2);
_handler->handleEvent(evt); _handler->handleEvent(evt);
} }

View file

@ -109,6 +109,11 @@ public:
*/ */
void restart(); void restart();
/**
* Run event loop
*/
void handleEvents();
/** /**
* Switch to a new scene * Switch to a new scene
* *
@ -185,7 +190,7 @@ public:
* *
* @param type The event type. * @param type The event type.
*/ */
void notify(AsylumEventType type); void notify(AsylumEventType type, int32 param1 = 0, int32 param2 = 0);
/** /**
* Gets a message handler. * Gets a message handler.
@ -248,7 +253,6 @@ private:
bool _introPlayed; bool _introPlayed;
int32 _tickOffset; int32 _tickOffset;
void handleEvents();
void updateMouseCursor(); void updateMouseCursor();
void processDelayedEvents(); void processDelayedEvents();
@ -276,7 +280,11 @@ private:
*/ */
int32 computeSinCosOffset(int32 val); int32 computeSinCosOffset(int32 val);
// Debug
friend class Console; friend class Console;
ResourcePackId _delayedSceneIndex;
int32 _delayedVideoIndex;
}; };
} // namespace Asylum } // namespace Asylum

View file

@ -36,6 +36,7 @@
#include "asylum/system/screen.h" #include "asylum/system/screen.h"
#include "asylum/views/scene.h" #include "asylum/views/scene.h"
#include "asylum/views/video.h"
#include "asylum/asylum.h" #include "asylum/asylum.h"
#include "asylum/respack.h" #include "asylum/respack.h"
@ -328,8 +329,7 @@ bool Console::cmdPlayVideo(int32 argc, const char **argv) {
return true; return true;
} }
getScreen()->clear(); _vm->_delayedVideoIndex = index;
getScript()->setDelayedVideoIndex(index);
return false; return false;
} }
@ -374,7 +374,7 @@ bool Console::cmdChangeScene(int32 argc, const char **argv) {
return true; return true;
} }
getScript()->setDelayedSceneIndex(index); _vm->_delayedSceneIndex = index;
return false; return false;
} }

View file

@ -45,13 +45,21 @@ enum AsylumEventType {
}; };
struct AsylumEvent : public Common::Event { struct AsylumEvent : public Common::Event {
AsylumEvent() : Event() {} AsylumEvent() : Event() {
param1 = 0;
param2 = 0;
}
// Since we don't feed any custom message into the event manager, // Since we don't feed any custom message into the event manager,
// we can safely use our own custom event type. // we can safely use our own custom event type.
AsylumEvent(AsylumEventType msgType) : Event() { AsylumEvent(AsylumEventType msgType, int32 p1 = 0, int32 p2 = 0) : Event() {
type = (Common::EventType)msgType; type = (Common::EventType)msgType;
param1 = p1;
param2 = p2;
} }
int32 param1;
int32 param2;
}; };
class EventHandler { class EventHandler {

View file

@ -37,6 +37,7 @@
#include "asylum/system/text.h" #include "asylum/system/text.h"
#include "asylum/views/scene.h" #include "asylum/views/scene.h"
#include "asylum/views/video.h"
#include "asylum/asylum.h" #include "asylum/asylum.h"
#include "asylum/respack.h" #include "asylum/respack.h"
@ -1549,7 +1550,7 @@ void Encounter::runScript() {
if (!getSharedData()->getMatteBarHeight()) { if (!getSharedData()->getMatteBarHeight()) {
getScreen()->makeGreyPalette(); getScreen()->makeGreyPalette();
getSharedData()->setMatteBarHeight(1); getSharedData()->setMatteBarHeight(1);
getScript()->setDelayedVideoIndex(getVariableInv(entry.param2)); getVideo()->play(getVariableInv(entry.param2), this);
getSharedData()->setMatteVar1(1); getSharedData()->setMatteVar1(1);
getSharedData()->setMattePlaySound(true); getSharedData()->setMattePlaySound(true);
getSharedData()->setMatteInitialized(true); getSharedData()->setMatteInitialized(true);

View file

@ -160,12 +160,6 @@ public:
*/ */
void resetQueue(); void resetQueue();
// Accessors
int32 getDelayedVideoIndex() const { return _delayedVideoIndex; }
void setDelayedVideoIndex(int32 val) { _delayedVideoIndex = val; }
ResourcePackId getDelayedSceneIndex() const { return _delayedSceneIndex; }
void setDelayedSceneIndex(ResourcePackId id) { _delayedSceneIndex = id; }
bool isProcessingSkipped() { return _skipProcessing; } bool isProcessingSkipped() { return _skipProcessing; }
// Serializable // Serializable

View file

@ -141,8 +141,7 @@ void Screen::drawWideScreenBars(int16 barSize) const {
} }
void Screen::fillRect(int32 x, int32 y, int32 width, int32 height, int32 color) { void Screen::fillRect(int32 x, int32 y, int32 width, int32 height, int32 color) {
_vm->_system->lockScreen()->fillRect(Common::Rect(x, y, x + width, y + height), color); _backBuffer.fillRect(Common::Rect(x, y, x + width, y + height), color);
_vm->_system->unlockScreen();
} }
void Screen::copyBackBufferToScreen() { void Screen::copyBackBufferToScreen() {
@ -239,6 +238,10 @@ void Screen::makeGreyPalette() {
warning("[Screen::makeGreyPalette] Not implemented!"); warning("[Screen::makeGreyPalette] Not implemented!");
} }
void Screen::setupPalette(byte *buffer, int start, int count) {
warning("[Screen::setupPalette] Not implemented!");
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Gamma // Gamma
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View file

@ -95,6 +95,7 @@ public:
void startPaletteFade(ResourceId resourceId, int32 milliseconds, int32 param); void startPaletteFade(ResourceId resourceId, int32 milliseconds, int32 param);
void updatePalette(int32 param); void updatePalette(int32 param);
void makeGreyPalette(); void makeGreyPalette();
void setupPalette(byte *buffer, int start, int count);
// Gamma // Gamma
void setGammaLevel(ResourceId id, int32 val); void setGammaLevel(ResourceId id, int32 val);
@ -114,6 +115,9 @@ public:
void clearGraphicsInQueue(); void clearGraphicsInQueue();
void deleteGraphicFromQueue(ResourceId resourceId); void deleteGraphicFromQueue(ResourceId resourceId);
// Used by Video
void copyToBackBuffer(byte *buffer, int32 pitch, int32 x, int32 y, uint32 width, uint32 height);
// Debug // Debug
void copyToBackBufferClipped(Graphics::Surface *surface, int x, int y); void copyToBackBufferClipped(Graphics::Surface *surface, int x, int y);
@ -146,8 +150,6 @@ private:
void blt(Common::Rect *dest, GraphicFrame* frame, Common::Rect *source, int32 flags, bool useColorKey); void blt(Common::Rect *dest, GraphicFrame* frame, Common::Rect *source, int32 flags, bool useColorKey);
void bltFast(int32 dX, int32 dY, GraphicFrame* frame, Common::Rect *source, bool useColorKey); void bltFast(int32 dX, int32 dY, GraphicFrame* frame, Common::Rect *source, bool useColorKey);
void copyToBackBuffer(byte *buffer, int32 pitch, int32 x, int32 y, uint32 width, uint32 height);
void copyToBackBufferWithTransparency(byte *buffer, int32 pitch, int32 x, int32 y, int32 width, int32 height); void copyToBackBufferWithTransparency(byte *buffer, int32 pitch, int32 x, int32 y, int32 width, int32 height);
}; };

View file

@ -51,17 +51,21 @@ Text::~Text() {
_vm = NULL; _vm = NULL;
} }
void Text::loadFont(ResourceId resourceId) { ResourceId Text::loadFont(ResourceId resourceId) {
if (_fontResource && resourceId == _fontResource->getResourceId()) if (_fontResource && resourceId == _fontResource->getResourceId())
return; return resourceId;
ResourceId previousFont = _fontResource ? _fontResource->getResourceId() : kResourceNone;
delete _fontResource; delete _fontResource;
_fontResource = new GraphicResource(_vm, resourceId); _fontResource = NULL;
if (resourceId != kResourceNone) { if (resourceId != kResourceNone) {
// load font flag data _fontResource = new GraphicResource(_vm, resourceId);
_curFontFlags = Common::Rational(_fontResource->getData().flags, 16).toInt() & 0x0F; _curFontFlags = Common::Rational(_fontResource->getData().flags, 16).toInt() & 0x0F;
} }
return previousFont;
} }
void Text::setPosition(int32 x, int32 y) { void Text::setPosition(int32 x, int32 y) {

View file

@ -47,7 +47,7 @@ public:
Text(AsylumEngine *engine); Text(AsylumEngine *engine);
~Text(); ~Text();
void loadFont(ResourceId resourceId); ResourceId loadFont(ResourceId resourceId);
void setPosition(int32 x, int32 y); void setPosition(int32 x, int32 y);
int32 getWidth(char c); int32 getWidth(char c);

View file

@ -354,7 +354,7 @@ bool MainMenu::init() {
_needEyeCursorInit = true; _needEyeCursorInit = true;
// Play start video // Play start video
getVideo()->playVideo(0); getVideo()->play(0, this);
// If no savegame is present, start the game directly // If no savegame is present, start the game directly
if (!getSaveLoad()->hasSavegames()) { if (!getSaveLoad()->hasSavegames()) {

View file

@ -26,8 +26,11 @@
#include "asylum/views/video.h" #include "asylum/views/video.h"
#include "asylum/system/config.h" #include "asylum/system/config.h"
#include "asylum/system/cursor.h"
#include "asylum/system/graphics.h" #include "asylum/system/graphics.h"
#include "asylum/system/savegame.h" #include "asylum/system/savegame.h"
#include "asylum/system/screen.h"
#include "asylum/system/sound.h"
#include "asylum/system/text.h" #include "asylum/system/text.h"
#include "asylum/asylum.h" #include "asylum/asylum.h"
@ -36,98 +39,176 @@
namespace Asylum { namespace Asylum {
Video::Video(AsylumEngine *engine, Audio::Mixer *mixer) : _vm(engine), _skipVideo(false) { Video::Video(AsylumEngine *engine, Audio::Mixer *mixer) : _vm(engine),
Common::Event stopEvent; _currentMovie(0), _subtitleIndex(0), _subtitleCounter(0), _previousFont(kResourceNone), _done(false) {
_stopEvents.clear();
stopEvent.type = Common::EVENT_KEYDOWN;
stopEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
_stopEvents.push_back(stopEvent);
_smkDecoder = new Graphics::SmackerDecoder(mixer); _smkDecoder = new Graphics::SmackerDecoder(mixer);
_text = new VideoText(engine);
_text->loadFont(MAKE_RESOURCE(kResourcePackShared, 57)); // video font
} }
Video::~Video() { Video::~Video() {
delete _smkDecoder; delete _smkDecoder;
delete _text;
// Zero-out passed pointers // Zero-out passed pointers
_vm = NULL; _vm = NULL;
} }
void Video::playVideo(int32 videoNumber) { //////////////////////////////////////////////////////////////////////////
char filename[20]; // Event Handler
sprintf(filename, "mov%03d.smk", videoNumber); //////////////////////////////////////////////////////////////////////////
bool Video::handleEvent(const AsylumEvent &evt) {
switch ((uint32)evt.type) {
default:
break;
getSaveLoad()->setMovieViewed(videoNumber); case EVENT_ASYLUM_INIT:
_previousFont = getText()->loadFont(MAKE_RESOURCE(kResourcePackShared, 57));
_subtitleCounter = 0;
_subtitleIndex = -1;
break;
if (!_smkDecoder->loadFile(filename)) { case EVENT_ASYLUM_DEINIT:
_smkDecoder->close(); getScreen()->clear();
getText()->loadFont(_previousFont);
break;
error("[Video::playVideo] Invalid video index (%d)", videoNumber); case EVENT_ASYLUM_SUBTITLE: {
int32 newIndex = (evt.param2 == 1) ? evt.param1 : -1;
if (_subtitleIndex != newIndex) {
_subtitleIndex = newIndex;
_subtitleCounter = 2;
}
if (_subtitleCounter > 0) {
getScreen()->fillRect(0, 400, 640, 80, 0);
if (_subtitleIndex >= 0) {
char *text1 = getText()->get((ResourceId)_currentMovie);
int32 y = 10 * (44 - getText()->draw(0, 99, kTextCalculate, 10, 400, 20, 620, text1));
if (y <= 400)
y = 405;
char *text = getText()->get(_subtitles[_subtitleIndex].resourceId);
getText()->draw(0, 99, kTextCenter, 10, y, 20, 620, text);
}
--_subtitleCounter;
}
return true;
}
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_KEYDOWN:
_done = true;
getScreen()->clear();
// Original set a value that does not seems to be used anywhere
return true;
} }
bool lastMouseState = g_system->showMouse(false); return false;
_skipVideo = false; }
if (Config.showMovieSubtitles) //////////////////////////////////////////////////////////////////////////
loadSubtitles(videoNumber); // Playing
//////////////////////////////////////////////////////////////////////////
void Video::play(int32 videoNumber, EventHandler *handler) {
getSaveLoad()->setMovieViewed(videoNumber);
_currentMovie = videoNumber;
// Prepare
getCursor()->hide();
getSharedData()->setFlag(kFlag1, true);
getScreen()->paletteFade(0, 25, 10);
getSound()->stopAll();
// Play movie
_vm->switchEventHandler(this);
play(Common::String::format("mov%03d.smk", videoNumber), Config.showMovieSubtitles);
// Cleanup and switch to previous event handler
getCursor()->show();
getSharedData()->setFlag(kFlag1, false);
_vm->switchEventHandler(handler);
}
void Video::play(Common::String filename, bool showSubtitles) {
if (!_smkDecoder->loadFile(filename))
error("[Video::playVideo] Invalid video index (%d)", _currentMovie);
int32 x = Common::Rational(g_system->getWidth() - _smkDecoder->getWidth(), 2).toInt(); int32 x = Common::Rational(g_system->getWidth() - _smkDecoder->getWidth(), 2).toInt();
int32 y = Common::Rational(g_system->getHeight() - _smkDecoder->getHeight(), 2).toInt(); int32 y = Common::Rational(g_system->getHeight() - _smkDecoder->getHeight(), 2).toInt();
while (!_smkDecoder->endOfVideo() && !_skipVideo) { getScreen()->clear();
processVideoEvents();
// TODO check flags and setup volume panning
// Load subtitles
if (showSubtitles)
loadSubtitles();
// Setup playing
_done = false;
uint32 index = 0;
int32 frameStart = 0;
int32 frameEnd = 0;
int32 currentSubtitle = 0;
while (!_done && !_vm->shouldQuit() && !_smkDecoder->endOfVideo()) {
_vm->handleEvents();
if (_smkDecoder->needsUpdate()) { if (_smkDecoder->needsUpdate()) {
Graphics::Surface *frame = _smkDecoder->decodeNextFrame(); Graphics::Surface *frame = _smkDecoder->decodeNextFrame();
if (!frame)
continue;
if (frame) { if (_smkDecoder->hasDirtyPalette())
g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); setupPalette();
if(Config.showMovieSubtitles) { getScreen()->copyToBackBuffer((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
Graphics::Surface *screen = g_system->lockScreen();
performPostProcessing((byte *)screen->pixels); if (showSubtitles) {
g_system->unlockScreen(); int32 currentFrame = _smkDecoder->getCurFrame() + 1;
// Check for next frame
if (currentFrame > frameEnd) {
if (index < _subtitles.size()) {
frameStart = _subtitles[index].frameStart;
frameEnd = _subtitles[index].frameEnd;
currentSubtitle = index;
++index;
}
} }
if (_smkDecoder->hasDirtyPalette()) if (currentFrame < frameStart || currentFrame > frameEnd)
_smkDecoder->setSystemPalette(); _vm->notify(EVENT_ASYLUM_SUBTITLE, 0, 0);
else
g_system->updateScreen(); _vm->notify(EVENT_ASYLUM_SUBTITLE, currentSubtitle, 1);
} }
getScreen()->copyBackBufferToScreen();
g_system->updateScreen();
} }
g_system->delayMillis(10); g_system->delayMillis(10);
} }
_smkDecoder->close(); _smkDecoder->close();
_subtitles.clear(); _subtitles.clear();
g_system->showMouse(lastMouseState);
} }
void Video::performPostProcessing(byte *screen) { void Video::setupPalette() {
int32 curFrame = _smkDecoder->getCurFrame(); _smkDecoder->setSystemPalette();
// Reset subtitle area, by filling it with zeroes warning("[Video::setupPalette] Video palette setup not implemented!");
memset(screen + 640 * 400, 0, 640 * 80); //getScreen()->setupPalette(0, 0, 0);
for (uint32 i = 0; i < _subtitles.size(); i++) {
VideoSubtitle curSubtitle = _subtitles[i];
if (curFrame >= curSubtitle.frameStart &&
curFrame <= curSubtitle.frameEnd) {
_text->drawMovieSubtitle(screen, curSubtitle.textResourceId);
break;
}
}
} }
void Video::loadSubtitles(int32 videoNumber) { void Video::loadSubtitles() {
// Read vids.cap
char movieToken[10]; char movieToken[10];
sprintf(movieToken, "[MOV%03d]", videoNumber); sprintf(movieToken, "[MOV%03d]", _currentMovie);
Common::File subsFile; Common::File subsFile;
subsFile.open("vids.cap"); subsFile.open("vids.cap");
@ -163,7 +244,7 @@ void Video::loadSubtitles(int32 videoNumber) {
if (!tok) if (!tok)
error("[Video::loadSubtitles] Invalid subtitle (resource id missing)!"); error("[Video::loadSubtitles] Invalid subtitle (resource id missing)!");
newSubtitle.textResourceId = (ResourceId)(atoi(tok) + video_subtitle_resourceIds[videoNumber]); newSubtitle.resourceId = (ResourceId)(atoi(tok) + video_subtitle_resourceIds[_currentMovie]);
tok = strtok(NULL, " "); tok = strtok(NULL, " ");
@ -176,131 +257,4 @@ void Video::loadSubtitles(int32 videoNumber) {
delete [] buffer; delete [] buffer;
} }
void Video::processVideoEvents() {
Common::Event curEvent;
while (g_system->getEventManager()->pollEvent(curEvent)) {
if (curEvent.type == Common::EVENT_RTL || curEvent.type == Common::EVENT_QUIT) {
_skipVideo = true;
}
for (Common::List<Common::Event>::const_iterator iter = _stopEvents.begin(); iter != _stopEvents.end(); ++iter) {
if (curEvent.type == iter->type) {
if (iter->type == Common::EVENT_KEYDOWN || iter->type == Common::EVENT_KEYUP) {
if (curEvent.kbd.keycode == iter->kbd.keycode) {
_skipVideo = true;
break;
}
} else {
_skipVideo = true;
break;
}
}
}
}
}
VideoText::VideoText(AsylumEngine *engine) : _vm(engine) {
_curFontFlags = 0;
_fontResource = NULL;
}
VideoText::~VideoText() {
delete _fontResource;
// Zero-out passed pointers
_vm = NULL;
}
void VideoText::loadFont(ResourceId resourceId) {
delete _fontResource;
_fontResource = new GraphicResource(_vm, resourceId);
if (resourceId != kResourceNone) {
// load font flag data
_curFontFlags = Common::Rational(_fontResource->getData().flags, 16).toInt() & 0x0F;
}
}
void VideoText::drawMovieSubtitle(byte *screenBuffer, ResourceId resourceId) {
Common::String textLine[4];
Common::String tmpLine;
int32 curLine = 0;
ResourceEntry *textRes = getResource()->get(resourceId);
char *text = strdup((const char *)textRes->data); // for strtok
char *tok = strtok(text, " ");
int32 startY = 420; // starting y for up to 2 subtitles
int32 spacing = 30; // spacing for up to 2 subtitles
// Videos can have up to 4 lines of text
while (tok) {
tmpLine += tok;
tmpLine += " ";
if (getTextWidth(tmpLine.c_str()) > 640) {
tmpLine = tok;
curLine++;
if (curLine >= 2) {
startY = 410; // starting Y for 3 subtitles
spacing = 20; // spacing for 3-4 subtitles
}
if (curLine >= 3) {
startY = 402; // starting Y for 4 subtitles
}
}
textLine[curLine] += tok;
textLine[curLine] += " ";
tok = strtok(NULL, " ");
}
for (int32 i = 0; i < curLine + 1; i++) {
int32 textWidth = getTextWidth(textLine[i].c_str());
drawText(screenBuffer, (int16)Common::Rational(640 - textWidth, 2).toInt(), (int16)(startY + i * spacing), textLine[i].c_str());
}
free(text);
}
int32 VideoText::getTextWidth(const char *text) {
if (!_fontResource)
error("[VideoText::getTextWidth] Video text resources not initialized properly!");
int32 width = 0;
while (*text) {
GraphicFrame *font = _fontResource->getFrame((uint8)*text);
width += font->surface.w + font->x - _curFontFlags;
text++;
}
return width;
}
void VideoText::drawText(byte *screenBuffer, int16 x, int16 y, const char *text) {
if (!_fontResource)
error("[VideoText::drawText] Video text resources not initialized properly!");
while (*text) {
GraphicFrame *fontLetter = _fontResource->getFrame((uint8)*text);
copyToVideoFrame(screenBuffer, fontLetter, x, y + fontLetter->y);
x += (int16)(fontLetter->surface.w + fontLetter->x - _curFontFlags);
text++;
}
}
void VideoText::copyToVideoFrame(byte *screenBuffer, GraphicFrame *frame, int32 x, int32 y) const {
uint16 h = frame->surface.h;
uint16 w = frame->surface.w;
int32 screenBufferPitch = 640;
byte *buffer = (byte *)frame->surface.pixels;
byte *dest = screenBuffer + y * screenBufferPitch + x;
while (h--) {
memcpy(dest, buffer, w);
dest += screenBufferPitch;
buffer += frame->surface.w;
}
}
} // end of namespace Asylum } // end of namespace Asylum

View file

@ -26,6 +26,7 @@
#ifndef ASYLUM_VIDEO_H #ifndef ASYLUM_VIDEO_H
#define ASYLUM_VIDEO_H #define ASYLUM_VIDEO_H
#include "asylum/eventhandler.h"
#include "asylum/shared.h" #include "asylum/shared.h"
#include "common/array.h" #include "common/array.h"
@ -48,54 +49,62 @@ struct GraphicFrame;
struct VideoSubtitle { struct VideoSubtitle {
int frameStart; int frameStart;
int frameEnd; int frameEnd;
ResourceId textResourceId; ResourceId resourceId;
}; };
class Video { class Video : public EventHandler {
public: public:
Video(AsylumEngine *engine, Audio::Mixer *mixer); Video(AsylumEngine *engine, Audio::Mixer *mixer);
virtual ~Video(); virtual ~Video();
void playVideo(int32 videoNumber); /**
* Plays a video.
*
* @param videoNumber The video number.
* @param handler The previous event handler.
*/
void play(int32 videoNumber, EventHandler *handler);
/**
* Handle event.
*
* @param evt The event.
*
* @return true if it succeeds, false if it fails.
*/
bool handleEvent(const AsylumEvent &evt);
private: private:
AsylumEngine *_vm; AsylumEngine *_vm;
void performPostProcessing(byte *screen);
void loadSubtitles(int32 videoNumber);
void processVideoEvents();
bool _skipVideo;
VideoText *_text;
Graphics::SmackerDecoder *_smkDecoder; Graphics::SmackerDecoder *_smkDecoder;
Common::List<Common::Event> _stopEvents; Common::Array<VideoSubtitle> _subtitles;
Common::Array<VideoSubtitle> _subtitles;
}; // end of class Video
// The VideoText class has some methods from the Text class, int32 _currentMovie;
// but it differs from the text class: this class draws text int32 _subtitleIndex;
// to a predefined screen buffer, whereas the Text class draws int32 _subtitleCounter;
// text directly to the screen ResourceId _previousFont;
class VideoText { bool _done;
public:
VideoText(AsylumEngine *engine);
~VideoText();
void loadFont(ResourceId resourceId);
void drawMovieSubtitle(byte *screenBuffer, ResourceId resourceId); /**
* Plays the given file.
*
* @param filename Filename of the file.
* @param showSubtitles true to show, false to hide the subtitles.
*/
void play(Common::String filename, bool showSubtitles);
private: /**
AsylumEngine *_vm; * Sets up the palette.
*/
void setupPalette();
int32 getTextWidth(const char *text); /**
* Loads the subtitles (vids.cap)
void drawText(byte *screenBuffer, int16 x, int16 y, const char *text); */
void copyToVideoFrame(byte *screenBuffer, GraphicFrame *frame, int x, int y) const; void loadSubtitles();
};
GraphicResource *_fontResource;
uint8 _curFontFlags;
}; // end of class VideoText
} // end of namespace Asylum } // end of namespace Asylum