diff options
author | Matthew Hoops | 2012-07-05 20:36:34 -0400 |
---|---|---|
committer | Matthew Hoops | 2012-07-05 20:36:34 -0400 |
commit | 3860f341365a59ff96ec41e61e3952be01915b40 (patch) | |
tree | b0342b8131d54b629c893ae150bb505c9198a2af | |
parent | 91efe792d5b231752dd16888729a94f323363fa0 (diff) | |
download | scummvm-rg350-3860f341365a59ff96ec41e61e3952be01915b40.tar.gz scummvm-rg350-3860f341365a59ff96ec41e61e3952be01915b40.tar.bz2 scummvm-rg350-3860f341365a59ff96ec41e61e3952be01915b40.zip |
PEGASUS: Implement screen fading
This does linear instead of gamma for speed and complexity reasons.
-rw-r--r-- | engines/pegasus/graphics.cpp | 35 | ||||
-rw-r--r-- | engines/pegasus/graphics.h | 6 | ||||
-rw-r--r-- | engines/pegasus/menu.cpp | 5 | ||||
-rw-r--r-- | engines/pegasus/neighborhood/caldoria/caldoria.cpp | 21 | ||||
-rw-r--r-- | engines/pegasus/pegasus.cpp | 1 | ||||
-rw-r--r-- | engines/pegasus/transition.cpp | 65 | ||||
-rw-r--r-- | engines/pegasus/transition.h | 19 |
7 files changed, 112 insertions, 40 deletions
diff --git a/engines/pegasus/graphics.cpp b/engines/pegasus/graphics.cpp index 175f15e91d..8d0347ebc4 100644 --- a/engines/pegasus/graphics.cpp +++ b/engines/pegasus/graphics.cpp @@ -30,6 +30,7 @@ #include "pegasus/elements.h" #include "pegasus/graphics.h" +#include "pegasus/transition.h" namespace Pegasus { @@ -46,10 +47,13 @@ GraphicsManager::GraphicsManager(PegasusEngine *vm) : _vm(vm) { _modifiedScreen = false; _curSurface = &_workArea; _erase = false; + _updatesEnabled = true; + _screenFader = new ScreenFader(); } GraphicsManager::~GraphicsManager() { _workArea.free(); + delete _screenFader; } void GraphicsManager::invalRect(const Common::Rect &rect) { @@ -175,7 +179,7 @@ void GraphicsManager::updateDisplay() { _dirtyRect = Common::Rect(); } - if (screenDirty || _modifiedScreen) + if (_updatesEnabled && (screenDirty || _modifiedScreen)) g_system->updateScreen(); _modifiedScreen = false; @@ -200,19 +204,14 @@ DisplayElement *GraphicsManager::findDisplayElement(const DisplayElementID id) { return 0; } -void GraphicsManager::doFadeOutSync(const TimeValue, const TimeValue, uint32 color) { - if (color == 0) - color = g_system->getScreenFormat().RGBToColor(0, 0, 0); - - // HACK: Until fading out is done, white-out the screen here - Graphics::Surface *screen = g_system->lockScreen(); - screen->fillRect(Common::Rect(0, 0, 640, 480), color); - g_system->unlockScreen(); - g_system->updateScreen(); +void GraphicsManager::doFadeOutSync(const TimeValue time, const TimeScale scale, uint32 color) { + _updatesEnabled = false; + _screenFader->doFadeOutSync(time, scale, color == 0); } -void GraphicsManager::doFadeInSync(const TimeValue, const TimeValue, uint32) { - // TODO +void GraphicsManager::doFadeInSync(const TimeValue time, const TimeScale scale, uint32 color) { + _screenFader->doFadeInSync(time, scale, color == 0); + _updatesEnabled = true; } void GraphicsManager::markCursorAsDirty() { @@ -333,5 +332,15 @@ void GraphicsManager::enableErase() { void GraphicsManager::disableErase() { _erase = false; } - + +void GraphicsManager::enableUpdates() { + _updatesEnabled = true; + _screenFader->setFaderValue(100); +} + +void GraphicsManager::disableUpdates() { + _updatesEnabled = false; + _screenFader->setFaderValue(0); +} + } // End of namespace Pegasus diff --git a/engines/pegasus/graphics.h b/engines/pegasus/graphics.h index 502304409a..2d66cd9aaa 100644 --- a/engines/pegasus/graphics.h +++ b/engines/pegasus/graphics.h @@ -40,6 +40,7 @@ namespace Pegasus { class Cursor; class DisplayElement; class PegasusEngine; +class ScreenFader; class GraphicsManager { friend class Cursor; @@ -61,6 +62,8 @@ public: void shakeTheWorld(TimeValue time, TimeScale scale); void enableErase(); void disableErase(); + void enableUpdates(); + void disableUpdates(); // These default to black void doFadeOutSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, uint32 color = 0); @@ -82,6 +85,9 @@ private: static const int kMaxShakeOffsets = 17; Common::Point _shakeOffsets[kMaxShakeOffsets]; void newShakePoint(int32 index1, int32 index2, int32 maxRadius); + + bool _updatesEnabled; + ScreenFader *_screenFader; }; } // End of namespace Pegasus diff --git a/engines/pegasus/menu.cpp b/engines/pegasus/menu.cpp index 5d90f62b14..5076abdaa6 100644 --- a/engines/pegasus/menu.cpp +++ b/engines/pegasus/menu.cpp @@ -237,10 +237,7 @@ void MainMenu::startMainMenuLoop() { _menuLoop.loopSound(); spec.makeTwoKnotFaderSpec(30, 0, 0, 30, 255); - - // FIXME: Should be sync, but it's a pain to use the main menu right now - // with this one. - _menuFader.startFader(spec); + _menuFader.startFaderSync(spec); } void MainMenu::stopMainMenuLoop() { diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.cpp b/engines/pegasus/neighborhood/caldoria/caldoria.cpp index 0e5868cb7d..817a24a162 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoria.cpp +++ b/engines/pegasus/neighborhood/caldoria/caldoria.cpp @@ -204,17 +204,24 @@ void Caldoria::start() { if (!pullbackMovie->loadFile("Images/Caldoria/Pullback.movie")) error("Could not load pullback movie"); - bool skipped = false; - Input input; - + // Draw the first frame so we can fade to it + pullbackMovie->pauseVideo(true); + const Graphics::Surface *frame = pullbackMovie->decodeNextFrame(); + assert(frame); + assert(frame->format == g_system->getScreenFormat()); + g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 64, 112, frame->w, frame->h); _vm->_gfx->doFadeInSync(kTwoSeconds * kFifteenTicksPerSecond, kFifteenTicksPerSecond); + pullbackMovie->pauseVideo(false); bool saveAllowed = _vm->swapSaveAllowed(false); bool openAllowed = _vm->swapLoadAllowed(false); + bool skipped = false; + Input input; + while (!_vm->shouldQuit() && !pullbackMovie->endOfVideo()) { if (pullbackMovie->needsUpdate()) { - const Graphics::Surface *frame = pullbackMovie->decodeNextFrame(); + frame = pullbackMovie->decodeNextFrame(); if (frame) { g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 64, 112, frame->w, frame->h); @@ -233,6 +240,9 @@ void Caldoria::start() { delete pullbackMovie; + if (_vm->shouldQuit()) + return; + _vm->swapSaveAllowed(saveAllowed); _vm->swapLoadAllowed(openAllowed); @@ -240,11 +250,8 @@ void Caldoria::start() { if (!skipped) { uint32 white = g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff); - _vm->_gfx->doFadeOutSync(kThreeSeconds * kFifteenTicksPerSecond, kFifteenTicksPerSecond, white); - g_system->delayMillis(3 * 1000 / 2); - getExtraEntry(kCaldoria00WakeUp1, entry); _navMovie.setTime(entry.movieStart); _navMovie.redrawMovieWorld(); diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp index 401a922c74..04b6f36428 100644 --- a/engines/pegasus/pegasus.cpp +++ b/engines/pegasus/pegasus.cpp @@ -1479,6 +1479,7 @@ void PegasusEngine::startNewGame() { _gfx->doFadeOutSync(); useMenu(0); _gfx->updateDisplay(); + _gfx->enableUpdates(); createInterface(); diff --git a/engines/pegasus/transition.cpp b/engines/pegasus/transition.cpp index 24e9aaf4a2..0de63d6080 100644 --- a/engines/pegasus/transition.cpp +++ b/engines/pegasus/transition.cpp @@ -24,43 +24,92 @@ */ #include "common/system.h" +#include "graphics/surface.h" #include "pegasus/transition.h" namespace Pegasus { ScreenFader::ScreenFader() { - _fadeTarget = getBlack(); + _isBlack = true; // Initially, assume screens are on at full brightness. Fader::setFaderValue(100); + _screen = new Graphics::Surface(); } -void ScreenFader::doFadeOutSync(const TimeValue duration, const TimeValue scale, const uint32 fadeTarget) { - _fadeTarget = fadeTarget; +ScreenFader::~ScreenFader() { + _screen->free(); + delete _screen; +} + +void ScreenFader::doFadeOutSync(const TimeValue duration, const TimeValue scale, bool isBlack) { + _isBlack = isBlack; + _screen->copyFrom(*g_system->lockScreen()); + g_system->unlockScreen(); FaderMoveSpec spec; spec.makeTwoKnotFaderSpec(scale, 0, getFaderValue(), duration, 0); startFaderSync(spec); + + _screen->free(); } -void ScreenFader::doFadeInSync(const TimeValue duration, const TimeValue scale, const uint32 fadeTarget) { - _fadeTarget = fadeTarget; +void ScreenFader::doFadeInSync(const TimeValue duration, const TimeValue scale, bool isBlack) { + _isBlack = isBlack; + _screen->copyFrom(*g_system->lockScreen()); + g_system->unlockScreen(); FaderMoveSpec spec; spec.makeTwoKnotFaderSpec(scale, 0, getFaderValue(), duration, 100); startFaderSync(spec); + + _screen->free(); } void ScreenFader::setFaderValue(const int32 value) { if (value != getFaderValue()) { Fader::setFaderValue(value); - // TODO: Gamma fading + if (_screen->pixels) { + // The original game does a gamma fade here using the Mac API. In order to do + // that, it would require an immense amount of CPU processing. This does a + // linear fade instead, which looks fairly well, IMO. + Graphics::Surface *screen = g_system->lockScreen(); + + for (uint y = 0; y < _screen->h; y++) { + for (uint x = 0; x < _screen->w; x++) { + if (_screen->format.bytesPerPixel == 2) + WRITE_UINT16(screen->getBasePtr(x, y), fadePixel(READ_UINT16(_screen->getBasePtr(x, y)), value)); + else + WRITE_UINT32(screen->getBasePtr(x, y), fadePixel(READ_UINT32(_screen->getBasePtr(x, y)), value)); + } + } + + g_system->unlockScreen(); + g_system->updateScreen(); + } } } -uint32 ScreenFader::getBlack() { - return g_system->getScreenFormat().RGBToColor(0, 0, 0); +static inline byte fadeComponent(byte comp, int32 percent) { + return comp * percent / 100; +} + +uint32 ScreenFader::fadePixel(uint32 color, int32 percent) const { + byte r, g, b; + g_system->getScreenFormat().colorToRGB(color, r, g, b); + + if (_isBlack) { + r = fadeComponent(r, percent); + g = fadeComponent(g, percent); + b = fadeComponent(b, percent); + } else { + r = 0xFF - fadeComponent(0xFF - r, percent); + g = 0xFF - fadeComponent(0xFF - g, percent); + b = 0xFF - fadeComponent(0xFF - b, percent); + } + + return g_system->getScreenFormat().RGBToColor(r, g, b); } Transition::Transition(const DisplayElementID id) : FaderAnimation(id) { diff --git a/engines/pegasus/transition.h b/engines/pegasus/transition.h index 5f2b797d88..a516d58e20 100644 --- a/engines/pegasus/transition.h +++ b/engines/pegasus/transition.h @@ -28,23 +28,26 @@ #include "pegasus/fader.h" +namespace Graphics { +struct Surface; +} + namespace Pegasus { class ScreenFader : public Fader { public: ScreenFader(); - virtual ~ScreenFader() {} + virtual ~ScreenFader(); - void doFadeOutSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, const uint32 = getBlack()); - void doFadeInSync(const TimeValue = kHalfSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, const uint32 = getBlack()); - - void setFaderValue(const int32); + void doFadeOutSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, bool isBlack = true); + void doFadeInSync(const TimeValue = kHalfSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, bool isBlack = true); -protected: - uint32 _fadeTarget; + void setFaderValue(const int32); private: - static uint32 getBlack(); + bool _isBlack; + uint32 fadePixel(uint32 color, int32 percent) const; + Graphics::Surface *_screen; }; // Transitions are faders that range over [0,1000], which makes their |