diff options
author | Paul Gilbert | 2016-07-09 11:32:15 -0400 |
---|---|---|
committer | Paul Gilbert | 2016-07-15 19:27:33 -0400 |
commit | cc9bf88ed56a4c5fbb14c05d30395b1688f5ebe7 (patch) | |
tree | 7a3a9a9fb8f0ce6fa15ab71a12c1144893c45811 /engines/titanic/support | |
parent | 341cf1866168a8e270ed08b38cd43aa83387ea5a (diff) | |
download | scummvm-rg350-cc9bf88ed56a4c5fbb14c05d30395b1688f5ebe7.tar.gz scummvm-rg350-cc9bf88ed56a4c5fbb14c05d30395b1688f5ebe7.tar.bz2 scummvm-rg350-cc9bf88ed56a4c5fbb14c05d30395b1688f5ebe7.zip |
TITANIC: Major implementation of OSMovie and AVISurface classes
Diffstat (limited to 'engines/titanic/support')
-rw-r--r-- | engines/titanic/support/avi_surface.cpp | 185 | ||||
-rw-r--r-- | engines/titanic/support/avi_surface.h | 110 | ||||
-rw-r--r-- | engines/titanic/support/mouse_cursor.cpp | 12 | ||||
-rw-r--r-- | engines/titanic/support/mouse_cursor.h | 2 | ||||
-rw-r--r-- | engines/titanic/support/movie.cpp | 245 | ||||
-rw-r--r-- | engines/titanic/support/movie.h | 132 | ||||
-rw-r--r-- | engines/titanic/support/movie_event.cpp | 33 | ||||
-rw-r--r-- | engines/titanic/support/movie_event.h | 18 | ||||
-rw-r--r-- | engines/titanic/support/movie_range_info.cpp | 42 | ||||
-rw-r--r-- | engines/titanic/support/movie_range_info.h | 20 | ||||
-rw-r--r-- | engines/titanic/support/video_surface.cpp | 23 | ||||
-rw-r--r-- | engines/titanic/support/video_surface.h | 58 |
12 files changed, 608 insertions, 272 deletions
diff --git a/engines/titanic/support/avi_surface.cpp b/engines/titanic/support/avi_surface.cpp index f6f63a7f1d..47127fe83b 100644 --- a/engines/titanic/support/avi_surface.cpp +++ b/engines/titanic/support/avi_surface.cpp @@ -21,12 +21,197 @@ */ #include "titanic/support/avi_surface.h" +#include "titanic/support/video_surface.h" #include "video/avi_decoder.h" namespace Titanic { AVISurface::AVISurface(const CResourceKey &key) { + // TODO +/* +Video::AVIDecoder *decoder = new Video::AVIDecoder(); +decoder->ignoreSecondaryVideoTracks(); +_video = decoder; +_field14 = 1; + +if (!_video->loadFile(name.getString())) +error("Could not open video - %s", name.getString().c_str()); +*/ +} + +AVISurface::~AVISurface() { + if (_videoSurface) + _videoSurface->_blitStyleFlag = false; + delete _frameInfo; +} + +bool AVISurface::play(uint flags, CGameObject *obj) { + if (flags & MOVIE_REVERSE) + return play(_decoder->getFrameCount() - 1, 0, flags, obj); + else + return play(0, _decoder->getFrameCount() - 1, flags, obj); +} + +bool AVISurface::play(int startFrame, int endFrame, uint flags, CGameObject *obj) { + if (flags & MOVIE_STOP_PREVIOUS) + stop(); + + return play(startFrame, endFrame, -1, flags, obj); +} + +bool AVISurface::play(int startFrame, int endFrame, int initialFrame, uint flags, CGameObject *obj) { + CMovieRangeInfo *info = new CMovieRangeInfo(); + info->_startFrame = startFrame; + info->_endFrame = endFrame; + info->_isReversed = endFrame < startFrame; + info->_isFlag1 = flags & MOVIE_1; + + if (obj) { + CMovieEvent *me = new CMovieEvent(); + me->_type = MET_MOVIE_END; + me->_startFrame = startFrame; + me->_endFrame = endFrame; + me->_initialFrame = 0; + me->_gameObject = obj; + + info->addEvent(me); + } + + _movieRangeInfo.push_back(info); + + if (_movieRangeInfo.size() == 1) { + changeFrame(initialFrame); + } else { + return true; + } +} + +void AVISurface::stop() { + _isPlaying = false; + _decoder->stop(); + _movieRangeInfo.destroyContents(); +} + +bool AVISurface::changeFrame(int frameNumber) { + if (_isPlaying) + return false; + + if (frameNumber == -1) + // Default to starting frame of first movie range + frameNumber = _movieRangeInfo.front()->_startFrame; + + seekToFrame(frameNumber); + renderFrame(); + + _isPlaying = true; + return true; +} + +void AVISurface::seekToFrame(uint frameNumber) { + _decoder->seekToFrame(frameNumber); + _priorFrame = frameNumber; +} + +bool AVISurface::handleEvents(CMovieEventList &events) { + if (!_isPlaying) + return true; + + CMovieRangeInfo *info = _movieRangeInfo.front(); + _currentPos += info->_isReversed ? -1 : 1; + if ((info->_isReversed && _currentPos < info->_endFrame) || + (!info->_isReversed && _currentPos > info->_endFrame)) { + if (info->_isFlag1) { + info->getMovieEnd(events); + _movieRangeInfo.remove(info); + delete info; + + if (_movieRangeInfo.empty()) { + // NO more ranges, so stop playback + stop(); + } else { + // Not empty, so move onto new first one + info = _movieRangeInfo.front(); + _currentPos = info->_startFrame; + } + } else { + _currentPos = info->_startFrame; + } + } + + if (_isPlaying) { + // SInce movie ranges can change the position in the movie, + // ensure the decoder is kept in sync + seekToFrame(_currentPos); + + info->getMovieFrame(events, _currentPos); + return renderFrame(); + } else { + return false; + } +} + +void AVISurface::setVideoSurface(CVideoSurface *surface) { + _videoSurface = surface; + + warning("TODO: Get video track list from video decoder"); +} + +uint AVISurface::getWidth() const { + return _decoder->getWidth(); +} + +uint AVISurface::getHeight() const { + return _decoder->getHeight(); +} + +void AVISurface::setFrame(int frameNumber) { + // If playback was in process, stop it + if (_isPlaying) + stop(); + + // Ensure the frame number is valid + if (frameNumber >= _decoder->getFrameCount()) + frameNumber = _decoder->getFrameCount() - 1; + + seekToFrame(frameNumber); + renderFrame(); +} + +int AVISurface::getFrame() const { + return _decoder->getCurFrame(); +} + +bool AVISurface::renderFrame() { + // Check there's a frame ready for + assert(_videoSurface); + if (!_decoder->needsUpdate()) + return false; + + // Get the frame to render, and draw it on the surface + const Graphics::Surface *frame = _decoder->decodeNextFrame(); + _videoSurface->blitFrom(Point(0, 0), frame); + return false; +} + +bool AVISurface::addEvent(int frameNumber, CGameObject *obj) { + if (!_movieRangeInfo.empty()) { + CMovieRangeInfo *tail = _movieRangeInfo.back(); + if (frameNumber == -1) + frameNumber = tail->_startFrame; + + CMovieEvent *me = new CMovieEvent(); + me->_type = MET_FRAME; + me->_startFrame = 0; + me->_endFrame = 0; + me->_initialFrame = frameNumber; + me->_gameObject = obj; + tail->addEvent(me); + + return _movieRangeInfo.size() == 1 && frameNumber == _priorFrame; + } + + return false; } } // End of namespace Titanic diff --git a/engines/titanic/support/avi_surface.h b/engines/titanic/support/avi_surface.h index 248f2c5ab3..48c8169e78 100644 --- a/engines/titanic/support/avi_surface.h +++ b/engines/titanic/support/avi_surface.h @@ -23,33 +23,121 @@ #ifndef TITANIC_AVI_SURFACE_H #define TITANIC_AVI_SURFACE_H -#include "video/video_decoder.h" +#include "video/avi_decoder.h" #include "titanic/core/resource_key.h" #include "titanic/support/movie_range_info.h" namespace Titanic { class CSoundManager; +class CVideoSurface; + +enum MovieFlag { + MOVIE_1 = 1, MOVIE_STOP_PREVIOUS = 2, MOVIE_NO_OBJECT = 4, + MOVIE_REVERSE = 8, MOVIE_GAMESTATE = 0x10 +}; class AVISurface { private: + Video::AVIDecoder *_decoder; + CVideoSurface *_videoSurface; int _field4; int _field8; - int _fieldC; - int _field10; - int _frame; + int _currentPos; + int _priorFrame; CMovieRangeInfoList _movieRangeInfo; - int _field28; - int _field2C; - int _field30; - int _field34; - int _field38; + int _streamCount; + void *_frameInfo; +private: + /** + * Render a frame to the video surface + */ + bool renderFrame(); +protected: + /** + * Change the frame with ??? checking + */ + virtual bool changeFrame(int frameNumber); + + /** + * Seeks to a given frame number in the video + */ + virtual void seekToFrame(uint frameNumber); +public: CSoundManager *_soundManager; - // TODO: Lots more fields + bool _hasAudio; + bool _isPlaying; + double _frameRate; public: AVISurface(const CResourceKey &key); + ~AVISurface(); + + /** + * Start playing the loaded AVI video + */ + virtual bool play(uint flags, CGameObject *obj); + + /** + * Start playing the loaded AVI video + */ + virtual bool play(int startFrame, int endFrame, uint flags, CGameObject *obj); + + /** + * Start playing the loaded AVI video + */ + virtual bool play(int startFrame, int endFrame, int initialFrame, uint flags, CGameObject *obj); + + /** + * Stop the currently playing video + */ + virtual void stop(); + + /** + * Handle any movie events relevent for the frame + */ + virtual bool handleEvents(CMovieEventList &events); + + /** + * Set the video surface the AVI Surface will render on + */ + void setVideoSurface(CVideoSurface *surface); + + /** + * Get the width of the video + */ + uint getWidth() const; + + /** + * Get the height of the video + */ + uint getHeight() const; + + /** + * Set the current frame + */ + void setFrame(int frameNumber); + + /** + * Gets the current frame + */ + int getFrame() const; + + /** + * Add a movie event + */ + bool addEvent(int frameNumber, CGameObject *obj); + + const void *getFrameInfo() const { + return _streamCount <= 1 ? nullptr : _frameInfo; + } + + /** + * Get a reference to the movie range info list + */ + const CMovieRangeInfoList *getMovieRangeInfo() const { + return &_movieRangeInfo; + } - }; } // End of namespace Titanic diff --git a/engines/titanic/support/mouse_cursor.cpp b/engines/titanic/support/mouse_cursor.cpp index d87e7a499b..721088f086 100644 --- a/engines/titanic/support/mouse_cursor.cpp +++ b/engines/titanic/support/mouse_cursor.cpp @@ -91,15 +91,17 @@ void CMouseCursor::loadCursorImages() { // Create the surface CVideoSurface *surface = _screenManager->createSurface(64, 64); _cursors[idx]._videoSurface = surface; - +/* Common::SeekableReadStream *stream = new Common::MemoryReadStream( movieData, f.size(), DisposeAfterUse::NO); OSMovie movie(stream, surface); movie.setFrame(idx); - - _cursors[idx]._ptrUnknown = movie.proc21(); - surface->set40(_cursors[idx]._ptrUnknown); - } + + int frameNum = movie.proc21(); + _cursors[idx]._frameNumber = frameNum; + surface->setMovieFrame(frameNum); +*/ + } } void CMouseCursor::show() { diff --git a/engines/titanic/support/mouse_cursor.h b/engines/titanic/support/mouse_cursor.h index 55e0cb4da5..168a7be539 100644 --- a/engines/titanic/support/mouse_cursor.h +++ b/engines/titanic/support/mouse_cursor.h @@ -54,7 +54,7 @@ class CVideoSurface; class CMouseCursor { struct CursorEntry { CVideoSurface *_videoSurface; - void *_ptrUnknown; + int _frameNumber; Common::Point _centroid; }; private: diff --git a/engines/titanic/support/movie.cpp b/engines/titanic/support/movie.cpp index 6a79c02a3e..338396ff96 100644 --- a/engines/titanic/support/movie.cpp +++ b/engines/titanic/support/movie.cpp @@ -20,42 +20,51 @@ * */ -#include "video/avi_decoder.h" -#include "titanic/sound/sound_manager.h" #include "titanic/support/movie.h" +#include "titanic/support/avi_surface.h" +#include "titanic/sound/sound_manager.h" +#include "titanic/messages/messages.h" #include "titanic/titanic.h" namespace Titanic { -CMovieList *CMovie::_activeMovies; +#define CLIP_WIDTH 600 +#define CLIP_WIDTH_REDUCED (CLIP_WIDTH / 2) +#define CLIP_HEIGHT 340 +#define CLIP_HEIGHT_REDUCED (CLIP_HEIGHT / 2) + +CMovieList *CMovie::_playingMovies; +CVideoSurface *CMovie::_movieSurface; -CMovie::CMovie() : ListItem(), _state(MOVIE_STOPPED), _field10(0), +CMovie::CMovie() : ListItem(), _state(MSTATE_0), _field10(0), _field14(0) { } CMovie::~CMovie() { - removeFromActiveMovies(); + removeFromPlayingMovies(); } void CMovie::init() { - _activeMovies = new CMovieList(); + _playingMovies = new CMovieList(); + _movieSurface = nullptr; } void CMovie::deinit() { - delete _activeMovies; + delete _playingMovies; + delete _movieSurface; } -void CMovie::addToActiveMovies() { +void CMovie::addToPlayingMovies() { if (!isActive()) - _activeMovies->push_back(this); + _playingMovies->push_back(this); } -void CMovie::removeFromActiveMovies() { - _activeMovies->remove(this); +void CMovie::removeFromPlayingMovies() { + _playingMovies->remove(this); } bool CMovie::isActive() const { - return _activeMovies->contains(this); + return _playingMovies->contains(this); } bool CMovie::get10() { @@ -70,156 +79,148 @@ bool CMovie::get10() { /*------------------------------------------------------------------------*/ OSMovie::OSMovie(const CResourceKey &name, CVideoSurface *surface) : - _videoSurface(surface), _gameObject(nullptr), _endFrame(-1) { - Video::AVIDecoder *decoder = new Video::AVIDecoder(); - _video = decoder; - _field14 = 1; - - if (!_video->loadFile(name.getString())) - error("Could not open video - %s", name.getString().c_str()); -} + _aviSurface(name), _videoSurface(surface) { + _field18 = 0; + _field24 = 0; + _field28 = 0; + _field2C = 0; + _ticksStart = 0; + _frameTime1 = 0; + _frameTime2 = 17066; -OSMovie::OSMovie(Common::SeekableReadStream *stream, CVideoSurface *surface) : - _videoSurface(surface), _gameObject(nullptr), _endFrame(-1) { - _video = new Video::AVIDecoder(); - if (!_video->loadStream(stream)) - error("Could not parse movie stream"); + surface->resize(_aviSurface.getWidth(), _aviSurface.getHeight()); + _aviSurface.setVideoSurface(surface); } OSMovie::~OSMovie() { - delete _video; } -void OSMovie::play(uint flags, CVideoSurface *surface) { - uint endFrame = _video->getFrameCount(); - play(0, endFrame, 0, 0); -} +void OSMovie::play(uint flags, CGameObject *obj) { + _aviSurface.play(flags, obj); -void OSMovie::play(uint startFrame, uint endFrame, int v3, bool v4) { - warning("TODO: OSMovie::play properly"); + if (_aviSurface._isPlaying) + movieStarted(); +} - _video->start(); - _video->seekToFrame(startFrame); - _endFrame = endFrame; +void OSMovie::play(uint startFrame, uint endFrame, uint flags, CGameObject *obj) { + _aviSurface.play(startFrame, endFrame, flags, obj); - addToActiveMovies(); - _state = MOVIE_NONE; + if (_aviSurface._isPlaying) + movieStarted(); } -void OSMovie::play(const Rect &rect, int v1, int v2) { - warning("TODO: OSMovie::play 3"); -} +void OSMovie::play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) { + _aviSurface.play(startFrame, endFrame, initialFrame, flags, obj); -void OSMovie::playClip(const Rect &rect, uint startFrame, uint endFrame) { - warning("TODO: OSMovie::playClip"); + if (_aviSurface._isPlaying) + movieStarted(); } -void OSMovie::proc11() { - warning("TODO: OSMovie::proc11"); -} +void OSMovie::playClip(const Point &drawPos, uint startFrame, uint endFrame) { + if (!_movieSurface) + _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340); + + bool widthLess = _videoSurface->getWidth() < 600; + bool heightLess = _videoSurface->getHeight() < 340; + Rect r(drawPos.x, drawPos.y, + drawPos.x + widthLess ? CLIP_WIDTH_REDUCED : CLIP_WIDTH, + drawPos.y + heightLess ? CLIP_HEIGHT_REDUCED : CLIP_HEIGHT + ); -void OSMovie::proc12(int v1, int v2, int frameNumber, int flags, CGameObject *obj) { - warning("TODO: OSMovie::proc12"); + uint timePerFrame = 1000 / _aviSurface._frameRate; + + for (; endFrame >= startFrame; ++startFrame) { + // Set the frame + _aviSurface.setFrame(startFrame); + + // TODO: See if we need to do anything further here. The original had a bunch + // of calls and using of the _movieSurface; perhaps to allow scaling down + // videos to half-size + if (widthLess || heightLess) + warning("Not properly reducing clip size: %d %d", r.width(), r.height()); + + // Wait for the next frame, unless the user interrupts the clip + if (g_vm->_events->waitForPress(timePerFrame)) + break; + } } void OSMovie::stop() { - _video->stop(); - _state = MOVIE_STOPPED; + _aviSurface.stop(); + removeFromPlayingMovies(); } -void OSMovie::proc14() { - warning("TODO: OSMovie::proc14"); +void OSMovie::addEvent(int frameNumber, CGameObject *obj) { + if (_aviSurface.addEvent(frameNumber, obj)) { + CMovieFrameMsg frameMsg(frameNumber, 0); + frameMsg.execute(obj); + } } void OSMovie::setFrame(uint frameNumber) { - _video->seekToFrame(frameNumber); - decodeFrame(); + _aviSurface.setFrame(frameNumber); + _videoSurface->setMovieFrame(frameNumber); } -void OSMovie::proc16() { - warning("TODO: OSMovie::proc16"); -} +bool OSMovie::handleEvents(CMovieEventList &events) { + if (!_aviSurface._isPlaying) + return false; -const Common::List<CMovieRangeInfo *> OSMovie::getMovieRangeInfo() const { - warning("TODO: OSMovie::getMovieRangeInfo"); - return Common::List<CMovieRangeInfo *>(); -} + int time = (g_vm->_events->getTicksCount() + ((_ticksStart << 24) - _ticksStart)) << 8; + if (time < _frameTime1) + return _aviSurface._isPlaying; -void OSMovie::setSoundManager(CSoundManager *soundManager) { -// if (_aviSurface) -// _aviSurface->_field3C = soundManager; + if (!_field14 && (time - _frameTime1) > (_frameTime2 * 2)) + _frameTime1 = time; - warning("TODO: OSMovie::proc18"); -} + _frameTime1 += _frameTime2; + _aviSurface.handleEvents(events); + _videoSurface->setMovieFrameInfo(_aviSurface.getFrameInfo()); -int OSMovie::getFrame() { - assert(_video); - return _video->getCurFrame(); -} + if (_field14) { + while (_frameTime1 >= time && events.empty()) { + _aviSurface.handleEvents(events); + _videoSurface->setMovieFrameInfo(_aviSurface.getFrameInfo()); -void OSMovie::proc20() { - warning("TODO: OSMovie::proc20"); -} - -void *OSMovie::proc21() { - warning("TODO: OSMovie::proc21"); - return nullptr; -} - -MovieState OSMovie::getState() { - if (!_video) - _state = MOVIE_STOPPED; - return _state; -} - -void OSMovie::update() { - if (_state != MOVIE_STOPPED) { - if (_video->isPlaying()) { - if (_video->getCurFrame() >= _endFrame) { - _video->stop(); - _state = MOVIE_FINISHED; - } else if (_video->needsUpdate()) { - decodeFrame(); - _state = MOVIE_FRAME; - } else { - _state = MOVIE_NONE; - } - } else { - _state = MOVIE_STOPPED; + _frameTime1 += _frameTime2; } } + + return _aviSurface._isPlaying; +} + +const CMovieRangeInfoList *OSMovie::getMovieRangeInfo() const { + return _aviSurface.getMovieRangeInfo(); } -void OSMovie::decodeFrame() { - const Graphics::Surface *frame = _video->decodeNextFrame(); - OSVideoSurface *videoSurface = static_cast<OSVideoSurface *>(_videoSurface); - assert(videoSurface); +void OSMovie::setSoundManager(CSoundManager *soundManager) { + _aviSurface._soundManager = soundManager; +} - // If the video surface doesn't yet have an underlying surface, create it - if (!videoSurface->hasSurface()) - videoSurface->recreate(frame->w, frame->h); +int OSMovie::getFrame() const { + return _aviSurface.getFrame(); +} - // Lock access to the surface - videoSurface->lock(); - assert(videoSurface->_rawSurface); +void OSMovie::movieStarted() { + _frameTime1 = _frameTime2 = 256000.0 / _aviSurface._frameRate; + _ticksStart = g_vm->_events->getTicksCount(); - if (frame->format == videoSurface->_rawSurface->format) { - // Matching format, so we can copy straight from the video frame - videoSurface->_rawSurface->blitFrom(*frame); - } else { - // Different formats so we have to convert it first - Graphics::Surface *s = frame->convertTo(videoSurface->_rawSurface->format); - videoSurface->_rawSurface->blitFrom(*s); + if (_aviSurface._hasAudio) + _aviSurface._soundManager->movieStarted(); - s->free(); - delete s; - } + // Register the movie in the playing list + addToPlayingMovies(); + _field10 = 1; +} - // Unlock the surface - videoSurface->unlock(); +void OSMovie::proc20() { + // TODO +} - if (_gameObject) - _gameObject->makeDirty(); +int OSMovie::proc21() { + // TODO + return 0; } + } // End of namespace Titanic diff --git a/engines/titanic/support/movie.h b/engines/titanic/support/movie.h index 7abca6bbc0..c839c882ca 100644 --- a/engines/titanic/support/movie.h +++ b/engines/titanic/support/movie.h @@ -27,12 +27,13 @@ #include "video/video_decoder.h" #include "titanic/core/list.h" #include "titanic/core/resource_key.h" +#include "titanic/support/avi_surface.h" #include "titanic/support/movie_range_info.h" namespace Titanic { enum MovieState { - MOVIE_STOPPED = -1, MOVIE_NONE = 0, MOVIE_FINISHED = 1, MOVIE_FRAME = 2 + MSTATE_0 = 0, MSTATE_1 = 1 }; class CGameObject; @@ -46,22 +47,17 @@ public: class CMovie : public ListItem { protected: - MovieState _state; - int _field10; -protected: - /** - * Adds the movie to the active movies list - */ - void addToActiveMovies(); - /** - * Removes the movie from the active movies list + * Adds the movie to the list of currently playing movies */ - void removeFromActiveMovies(); + void addToPlayingMovies(); public: + MovieState _state; + int _field10; int _field14; public: - static CMovieList *_activeMovies; + static CMovieList *_playingMovies; + static CVideoSurface *_movieSurface; /** * Initializes statics @@ -77,41 +73,49 @@ public: virtual ~CMovie(); /** - * Plays the movie + * Starts playing the movie */ - virtual void play(uint flags, CVideoSurface *surface) = 0; + virtual void play(uint flags, CGameObject *obj) = 0; /** - * Plays the movie + * Starts playing the movie */ - virtual void play(uint startFrame, uint endFrame, int v3, bool v4) = 0; + virtual void play(uint startFrame, uint endFrame, uint flags, CGameObject *obj) = 0; /** - * Plays the movie + * Starts playing the movie */ - virtual void play(const Rect &rect, int v1, int v2) = 0; + virtual void play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) = 0; /** * Plays a sub-section of a movie */ - virtual void playClip(const Rect &rect, uint startFrame, uint endFrame) = 0; + virtual void playClip(const Point &drawPos, uint startFrame, uint endFrame) = 0; - virtual void proc11() = 0; - virtual void proc12(int v1, int v2, int frameNumber, int flags, CGameObject *obj) = 0; - /** * Stops the movie */ virtual void stop() = 0; - virtual void proc14() = 0; + /** + * Add a playback event + */ + virtual void addEvent(int frameNumber, CGameObject *obj) = 0; + + /** + * Set the current frame number + */ virtual void setFrame(uint frameNumber) = 0; - virtual void proc16() = 0; + + /** + * Handle any pending movie events + */ + virtual bool handleEvents(CMovieEventList &events) = 0; /** * Return any movie range info associated with the movie */ - virtual const Common::List<CMovieRangeInfo *> getMovieRangeInfo() const = 0; + virtual const CMovieRangeInfoList *getMovieRangeInfo() const = 0; /** * Set the sound manager reference @@ -121,94 +125,102 @@ public: /** * Get the current movie frame */ - virtual int getFrame() = 0; + virtual int getFrame() const = 0; virtual void proc20() = 0; - virtual void *proc21() = 0; + virtual int proc21() = 0; + + /** + * Removes the movie from the list of currently playing movies + */ + void removeFromPlayingMovies(); + /** + * Returns true if the movie is currently active + */ bool isActive() const; bool get10(); - - virtual MovieState getState() = 0; - virtual void update() = 0; }; class OSMovie : public CMovie { private: - Video::VideoDecoder *_video; + AVISurface _aviSurface; CVideoSurface *_videoSurface; - int _endFrame; - + int _field18; + int _field24; + int _field28; + int _field2C; + int _ticksStart; + int _frameTime1; + int _frameTime2; +private: /** - * Decodes the next frame + * Called when a movie is started playing */ - void decodeFrame(); -public: - CGameObject *_gameObject; + void movieStarted(); public: OSMovie(const CResourceKey &name, CVideoSurface *surface); - OSMovie(Common::SeekableReadStream *stream, CVideoSurface *surface); virtual ~OSMovie(); /** - * Plays the movie + * Starts playing the movie */ - virtual void play(uint flags, CVideoSurface *surface); + virtual void play(uint flags, CGameObject *obj); /** - * Plays the movie + * Starts playing the movie */ - virtual void play(uint startFrame, uint endFrame, int v3, bool v4); + virtual void play(uint startFrame, uint endFrame, uint flags, CGameObject *obj); /** - * Plays the movie + * Starts playing the movie */ - virtual void play(const Rect &rect, int v1, int v2); + virtual void play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj); /** * Plays a sub-section of a movie */ - virtual void playClip(const Rect &rect, uint startFrame, uint endFrame); - - virtual void proc11(); - virtual void proc12(int v1, int v2, int frameNumber, int flags, CGameObject *obj); + virtual void playClip(const Point &drawPos, uint startFrame, uint endFrame); /** * Stops the movie */ virtual void stop(); - virtual void proc14(); + /** + * Add a playback event + */ + virtual void addEvent(int eventId, CGameObject *obj); /** * Set the current frame number */ virtual void setFrame(uint frameNumber); - virtual void proc16(); + /** + * Handle any pending movie events + */ + virtual bool handleEvents(CMovieEventList &events); /** - * Return any movie range info associated with the movie + * Get the current frame number */ - virtual const Common::List<CMovieRangeInfo *> getMovieRangeInfo() const; + virtual int getFrame() const; /** - * Set the sound manager reference + * Return any movie range info associated with the movie */ - virtual void setSoundManager(CSoundManager *soundManager); + virtual const CMovieRangeInfoList *getMovieRangeInfo() const; /** - * Get the current movie frame + * Set the sound manager reference */ - virtual int getFrame(); + virtual void setSoundManager(CSoundManager *soundManager); virtual void proc20(); - virtual void *proc21(); - + virtual int proc21(); - virtual MovieState getState(); - virtual void update(); }; } // End of namespace Titanic diff --git a/engines/titanic/support/movie_event.cpp b/engines/titanic/support/movie_event.cpp index 870a06fe6f..5f8a6da019 100644 --- a/engines/titanic/support/movie_event.cpp +++ b/engines/titanic/support/movie_event.cpp @@ -21,27 +21,29 @@ */ #include "titanic/support/movie_event.h" +#include "titanic/core/game_object.h" namespace Titanic { -CMovieEvent::CMovieEvent() : ListItem(), _fieldC(0), _field10(0), - _field14(0), _field1C(0) { +CMovieEvent::CMovieEvent() : ListItem(), _type(MET_PLAY), _startFrame(0), + _endFrame(0), _initialFrame(0), _gameObject(nullptr) { } CMovieEvent::CMovieEvent(const CMovieEvent *src) { - _fieldC = src->_fieldC; - _field10 = src->_field10; - _field14 = src->_field14; - _field18 = src->_field18; - _field1C = src->_field1C; + _type = src->_type; + _startFrame = src->_startFrame; + _endFrame = src->_endFrame; + _initialFrame = src->_initialFrame; + _gameObject = src->_gameObject; } void CMovieEvent::save(SimpleFile *file, int indent) { file->writeNumberLine(0, indent); - file->writeNumberLine(_fieldC, indent + 1); - file->writeNumberLine(_field10, indent + 1); - file->writeNumberLine(_field14, indent + 1); - file->writeNumberLine(_field1C, indent + 1); + file->writeNumberLine(_startFrame, indent + 1); + file->writeNumberLine(_endFrame, indent + 1); + error("FIXME: Original save/loaded object pointer"); + // file->writeNumberLine(_gameObject, indent + 1); + file->writeNumberLine(_initialFrame, indent + 1); ListItem::save(file, indent); } @@ -49,10 +51,11 @@ void CMovieEvent::save(SimpleFile *file, int indent) { void CMovieEvent::load(SimpleFile *file) { int val = file->readNumber(); if (!val) { - _fieldC = file->readNumber(); - _field10 = file->readNumber(); - _field14 = file->readNumber(); - _field1C = file->readNumber(); + _startFrame = file->readNumber(); + _endFrame = file->readNumber(); + file->readNumber(); + error("FIXME: Original save/loaded object pointer"); + _initialFrame = file->readNumber(); } ListItem::load(file); diff --git a/engines/titanic/support/movie_event.h b/engines/titanic/support/movie_event.h index ed72e2d349..af93c76a31 100644 --- a/engines/titanic/support/movie_event.h +++ b/engines/titanic/support/movie_event.h @@ -27,13 +27,17 @@ namespace Titanic { +enum MovieEventType { MET_PLAY = 0, MET_MOVIE_END = 1, MET_FRAME = 2 }; + +class CGameObject; + class CMovieEvent : public ListItem { public: - int _fieldC; - int _field10; - int _field14; - int _field18; - int _field1C; + MovieEventType _type; + int _startFrame; + int _endFrame; + CGameObject *_gameObject; + int _initialFrame; public: CMovieEvent(); CMovieEvent(const CMovieEvent *src); @@ -53,6 +57,10 @@ public: class CMovieEventList : public List<CMovieEvent> { }; +class CSharedMovieEventList : public Common::List<CMovieEvent> { +}; + + } // End of namespace Titanic #endif /* TITANIC_MOVIE_EVENT_H */ diff --git a/engines/titanic/support/movie_range_info.cpp b/engines/titanic/support/movie_range_info.cpp index e6b28ce4e8..4c62539864 100644 --- a/engines/titanic/support/movie_range_info.cpp +++ b/engines/titanic/support/movie_range_info.cpp @@ -34,11 +34,11 @@ CMovieRangeInfo::~CMovieRangeInfo() { } CMovieRangeInfo::CMovieRangeInfo(const CMovieRangeInfo *src) : ListItem() { - _fieldC = src->_fieldC; - _field10 = src->_field10; - _frameNumber = src->_frameNumber; _startFrame = src->_startFrame; _endFrame = src->_endFrame; + _initialFrame = src->_initialFrame; + _isReversed = src->_isReversed; + _isFlag1 = src->_isFlag1; // Duplicate the events list for (CMovieEventList::const_iterator i = _events.begin(); @@ -49,38 +49,38 @@ CMovieRangeInfo::CMovieRangeInfo(const CMovieRangeInfo *src) : ListItem() { void CMovieRangeInfo::save(SimpleFile *file, int indent) { file->writeNumberLine(0, indent); - file->writeNumberLine(_fieldC, indent + 1); - file->writeNumberLine(_field10, indent + 1); - file->writeNumberLine(_frameNumber, indent + 1); - file->writeNumberLine(_endFrame, indent + 1); file->writeNumberLine(_startFrame, indent + 1); + file->writeNumberLine(_endFrame, indent + 1); + file->writeNumberLine(_initialFrame, indent + 1); + file->writeNumberLine(_isFlag1, indent + 1); + file->writeNumberLine(_isReversed, indent + 1); _events.save(file, indent + 1); } void CMovieRangeInfo::load(SimpleFile *file) { int val = file->readNumber(); if (!val) { - _fieldC = file->readNumber(); - _field10 = file->readNumber(); - _frameNumber = file->readNumber(); - _endFrame = file->readNumber(); _startFrame = file->readNumber(); + _endFrame = file->readNumber(); + _initialFrame = file->readNumber(); + _isFlag1 = file->readNumber(); + _isReversed = file->readNumber(); _events.load(file); } } -void CMovieRangeInfo::get1(CMovieEventList &list) { +void CMovieRangeInfo::getMovieEnd(CMovieEventList &list) { for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { CMovieEvent *movieEvent = *i; - if (movieEvent->_fieldC == 1) + if (movieEvent->_type == MET_MOVIE_END) list.push_back(new CMovieEvent(movieEvent)); } } -void CMovieRangeInfo::get2(CMovieEventList &list, int val) { +void CMovieRangeInfo::getMovieFrame(CMovieEventList &list, int frameNumber) { for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { CMovieEvent *movieEvent = *i; - if (movieEvent->_fieldC == 2 && movieEvent->_field1C == val) + if (movieEvent->_type == MET_FRAME && movieEvent->_initialFrame == frameNumber) list.push_back(new CMovieEvent(movieEvent)); } } @@ -88,24 +88,24 @@ void CMovieRangeInfo::get2(CMovieEventList &list, int val) { void CMovieRangeInfo::process(CGameObject *owner) { int flags = 0; if (_endFrame) - flags |= CLIPFLAG_HAS_END_FRAME; + flags |= MOVIE_1; if (_startFrame) - flags |= CLIPFLAG_HAS_START_FRAME; + flags |= MOVIE_REVERSE; for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { CMovieEvent *movieEvent = *i; - if (!movieEvent->_fieldC) { + if (!movieEvent->_type == MET_PLAY) { flags |= CLIPFLAG_PLAY; break; } } - owner->checkPlayMovie(_fieldC, _field10, _frameNumber, flags); + owner->playMovie(_startFrame, _endFrame, _initialFrame, flags); for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { CMovieEvent *movieEvent = *i; - if (!movieEvent->_fieldC) - owner->surface38(movieEvent->_field1C); + if (movieEvent->_type == MET_PLAY) + owner->movieEvent(movieEvent->_initialFrame); } } diff --git a/engines/titanic/support/movie_range_info.h b/engines/titanic/support/movie_range_info.h index be04975cbf..b8186e6f7e 100644 --- a/engines/titanic/support/movie_range_info.h +++ b/engines/titanic/support/movie_range_info.h @@ -34,11 +34,11 @@ class CGameObject; class CMovieRangeInfo : public ListItem { public: - int _fieldC; - int _field10; - int _frameNumber; - uint _startFrame; - uint _endFrame; + int _startFrame; + int _endFrame; + int _initialFrame; + bool _isReversed; + bool _isFlag1; CMovieEventList _events; public: CMovieRangeInfo(); @@ -60,9 +60,15 @@ public: */ void addEvent(CMovieEvent *movieEvent) { _events.push_back(movieEvent); } - void get1(CMovieEventList &list); + /** + * Get any movie end events for the range + */ + void getMovieEnd(CMovieEventList &list); - void get2(CMovieEventList &list, int val); + /** + * Get any movie frame events for a specified frame number + */ + void getMovieFrame(CMovieEventList &list, int frameNumber); void process(CGameObject *owner); }; diff --git a/engines/titanic/support/video_surface.cpp b/engines/titanic/support/video_surface.cpp index 0335e7d9b1..fc7db30391 100644 --- a/engines/titanic/support/video_surface.cpp +++ b/engines/titanic/support/video_surface.cpp @@ -32,7 +32,7 @@ int CVideoSurface::_videoSurfaceCounter = 0; CVideoSurface::CVideoSurface(CScreenManager *screenManager) : _screenManager(screenManager), _rawSurface(nullptr), _movie(nullptr), _pendingLoad(false), _blitStyleFlag(false), _blitFlag(false), - _field40(nullptr), _field44(4), _field48(0), _field50(1) { + _movieFrameInfo(nullptr), _transparencyMode(TRANS_DEFAULT), _field48(0), _field50(1) { _videoSurfaceNum = _videoSurfaceCounter++; } @@ -427,22 +427,22 @@ void OSVideoSurface::clear() { } -void OSVideoSurface::playMovie(uint flags, CVideoSurface *surface) { +void OSVideoSurface::playMovie(uint flags, CGameObject *obj) { if (loadIfReady() && _movie) - _movie->play(flags, surface); + _movie->play(flags, obj); _ddSurface->fill(nullptr, 0); } -void OSVideoSurface::playMovie(uint startFrame, uint endFrame, int v3, bool v4) { +void OSVideoSurface::playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj) { if (loadIfReady() && _movie) { - _movie->play(startFrame, endFrame, v3, v4); + _movie->play(startFrame, endFrame, flags, obj); } } -void OSVideoSurface::proc35(int v1, int v2, int frameNumber, int flags, CGameObject *owner) { +void OSVideoSurface::playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) { if (loadIfReady() && _movie) { - _movie->proc12(v1, v2, frameNumber, flags, owner); + _movie->play(startFrame, endFrame, initialFrame, flags, obj); } } @@ -456,16 +456,17 @@ void OSVideoSurface::setMovieFrame(uint frameNumber) { _movie->setFrame(frameNumber); } -void OSVideoSurface::proc38(int v1, int v2) { - warning("OSVideoSurface::proc38"); +void OSVideoSurface::addMovieEvent(int frameNumber, CGameObject *obj) { + if (_movie) + _movie->addEvent(frameNumber, obj); } void OSVideoSurface::proc39(int v1, int v2) { warning("OSVideoSurface::proc39"); } -const Common::List<CMovieRangeInfo *> OSVideoSurface::getMovieRangeInfo() const { - return _movie ? _movie->getMovieRangeInfo() : Common::List<CMovieRangeInfo *>(); +const CMovieRangeInfoList *OSVideoSurface::getMovieRangeInfo() const { + return _movie ? _movie->getMovieRangeInfo() : nullptr; } bool OSVideoSurface::loadIfReady() { diff --git a/engines/titanic/support/video_surface.h b/engines/titanic/support/video_surface.h index 37afccf9e1..3521be6336 100644 --- a/engines/titanic/support/video_surface.h +++ b/engines/titanic/support/video_surface.h @@ -35,6 +35,11 @@ namespace Titanic { +enum TransparencyMode { + TRANS_MASK0 = 0, TRANS_MASK255 = 1, TRANS_ALPHA0 = 2, + TRANS_ALPHA255 = 3, TRANS_DEFAULT = 4 +}; + class CScreenManager; class CJPEGDecode; class CTargaDecode; @@ -57,8 +62,7 @@ protected: CScreenManager *_screenManager; Graphics::ManagedSurface *_rawSurface; bool _pendingLoad; - void *_field40; - int _field44; + const void *_movieFrameInfo; int _field48; int _videoSurfaceNum; int _field50; @@ -69,6 +73,7 @@ public: bool _blitFlag; bool _blitStyleFlag; CResourceKey _resourceKey; + TransparencyMode _transparencyMode; public: CVideoSurface(CScreenManager *screenManager); virtual ~CVideoSurface(); @@ -190,15 +195,19 @@ public: * Plays a movie, loading it from the specified _resource * if not already loaded */ - virtual void playMovie(uint flags, CVideoSurface *surface) = 0; + virtual void playMovie(uint flags, CGameObject *obj) = 0; /** * Plays a movie, loading it from the specified _resource * if not already loaded */ - virtual void playMovie(uint startFrame, uint endFrame, int v3, bool v4) = 0; + virtual void playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj) = 0; - virtual void proc35(int v1, int v2, int frameNumber, int flags, CGameObject *owner) = 0; + /** + * Plays a movie, loading it from the specified _resource + * if not already loaded + */ + virtual void playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) = 0; /** * Stops any movie currently attached to the surface @@ -206,18 +215,21 @@ public: virtual void stopMovie() = 0; /** - * Sets the movie to the specified frame number + * Set the current movie frame number */ virtual void setMovieFrame(uint frameNumber) = 0; - virtual void proc38(int v1, int v2) = 0; + /** + * Adds a movie playback event + */ + virtual void addMovieEvent(int eventId, CGameObject *obj) = 0; virtual void proc39(int v1, int v2) = 0; /** * Return any movie range info associated with the surface's movie */ - virtual const Common::List<CMovieRangeInfo *> getMovieRangeInfo() const = 0; + virtual const CMovieRangeInfoList *getMovieRangeInfo() const = 0; /** * Loads the surface's resource if there's one pending @@ -257,8 +269,19 @@ public: */ void blitFrom(const Point &destPos, const Graphics::Surface *src); - void set40(void *v) { _field40 = v; } + /** + * + */ + void setMovieFrameInfo(const void *frameInfo) { _movieFrameInfo = frameInfo; } + + /** + */ + const void *getMovieFrameInfo() const { return _movieFrameInfo; } + /** + * Get the pixels associated with the surface. Only valid when the + * surface has been locked for access + */ uint16 *getPixels() { return (uint16 *)_rawSurface->getPixels(); } /** @@ -400,15 +423,19 @@ public: * Plays a movie, loading it from the specified _resource * if not already loaded */ - virtual void playMovie(uint flags, CVideoSurface *surface); + virtual void playMovie(uint flags, CGameObject *obj); /** * Plays a movie, loading it from the specified _resource * if not already loaded */ - virtual void playMovie(uint startFrame, uint endFrame, int v3, bool v4); + virtual void playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj); - virtual void proc35(int v1, int v2, int frameNumber, int flags, CGameObject *owner); + /** + * Plays a movie, loading it from the specified _resource + * if not already loaded + */ + virtual void playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj); /** * Stops any movie currently attached to the surface @@ -420,14 +447,17 @@ public: */ virtual void setMovieFrame(uint frameNumber); - virtual void proc38(int v1, int v2); + /** + * Adds a movie playback event + */ + virtual void addMovieEvent(int frameNumber, CGameObject *obj); virtual void proc39(int v1, int v2); /** * Return any movie range info associated with the surface's movie */ - virtual const Common::List<CMovieRangeInfo *> getMovieRangeInfo() const; + virtual const CMovieRangeInfoList *getMovieRangeInfo() const; /** * Loads the surface's resource if there's one pending |