diff options
author | Colin Snover | 2016-08-20 21:02:07 -0500 |
---|---|---|
committer | Colin Snover | 2016-09-29 19:39:16 -0500 |
commit | 44dd029cb17160316b2015321a0a53f8854b6dd3 (patch) | |
tree | b6975dd6bf0f1bc7723345273abdecf034a667a5 /engines/sci | |
parent | 2be2629a3b2b43a0c86cfb7ea26cf979b91251bd (diff) | |
download | scummvm-rg350-44dd029cb17160316b2015321a0a53f8854b6dd3.tar.gz scummvm-rg350-44dd029cb17160316b2015321a0a53f8854b6dd3.tar.bz2 scummvm-rg350-44dd029cb17160316b2015321a0a53f8854b6dd3.zip |
SCI32: Implement kSetHotRectangles
Used only by chapter 7 of Phant1.
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/engine/kernel.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/kernel_tables.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/kevent.cpp | 24 | ||||
-rw-r--r-- | engines/sci/event.cpp | 64 | ||||
-rw-r--r-- | engines/sci/event.h | 16 | ||||
-rw-r--r-- | engines/sci/graphics/video32.cpp | 40 |
6 files changed, 116 insertions, 30 deletions
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index bd9d1bb770..6cacb5f839 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -483,6 +483,7 @@ reg_t kShowMovieWinGetDuration(EngineState *s, int argc, reg_t *argv); reg_t kShowMovieWinPlayUntilEvent(EngineState *s, int argc, reg_t *argv); reg_t kShowMovieWinInitDouble(EngineState *s, int argc, reg_t *argv); +reg_t kSetHotRectangles(EngineState *s, int argc, reg_t *argv); reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv); reg_t kListAt(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 201afb66e2..b8d8450bc1 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -969,6 +969,7 @@ static SciKernelMapEntry s_kernelMap[] = { // SetHotRectangles - used by Phantasmagoria 1, script 64981 (used in the chase scene) // <lskovlun> The idea, if I understand correctly, is that the engine generates events // of a special HotRect type continuously when the mouse is on that rectangle + { MAP_CALL(SetHotRectangles), SIG_SINCE_SCI21MID, SIGFOR_ALL, "i(r)", NULL, NULL }, // Used by SQ6 to scroll through the inventory via the up/down buttons { MAP_CALL(MovePlaneItems), SIG_SINCE_SCI21, SIGFOR_ALL, "oii(i)", NULL, NULL }, diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index 600dce3014..8dcafe0f38 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -369,6 +369,30 @@ reg_t kLocalToGlobal32(EngineState *s, int argc, reg_t *argv) { return make_reg(0, visible); } + +reg_t kSetHotRectangles(EngineState *s, int argc, reg_t *argv) { + if (argc == 1) { + g_sci->getEventManager()->setHotRectanglesActive((bool)argv[0].toUint16()); + return s->r_acc; + } + + const int16 numRects = argv[0].toSint16(); + SciArray &hotRects = *s->_segMan->lookupArray(argv[1]); + + Common::Array<Common::Rect> rects; + rects.resize(numRects); + + for (int16 i = 0; i < numRects; ++i) { + rects[i].left = hotRects.int16At(i * 4); + rects[i].top = hotRects.int16At(i * 4 + 1); + rects[i].right = hotRects.int16At(i * 4 + 2) + 1; + rects[i].bottom = hotRects.int16At(i * 4 + 3) + 1; + } + + g_sci->getEventManager()->setHotRectanglesActive(true); + g_sci->getEventManager()->setHotRectangles(rects); + return s->r_acc; +} #endif } // End of namespace Sci diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index 43db00c566..345b380a48 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -109,8 +109,12 @@ static const MouseEventConversion mouseEventMappings[] = { { Common::EVENT_MBUTTONUP, SCI_EVENT_MOUSE_RELEASE } }; -EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended) { -} +EventManager::EventManager(bool fontIsExtended) : + _fontIsExtended(fontIsExtended) +#ifdef ENABLE_SCI32 + , _hotRectanglesActive(false) +#endif + {} EventManager::~EventManager() { } @@ -138,8 +142,8 @@ static int altify(int ch) { SciEvent EventManager::getScummVMEvent() { #ifdef ENABLE_SCI32 - SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() }; - SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() }; + SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point(), -1 }; + SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point(), -1 }; #else SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point() }; SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point() }; @@ -169,17 +173,20 @@ SciEvent EventManager::getScummVMEvent() { if (getSciVersion() >= SCI_VERSION_2) { const Buffer &screen = g_sci->_gfxFrameout->getCurrentBuffer(); + Common::Point mousePosSci = mousePos; + mulru(mousePosSci, Ratio(screen.scriptWidth, screen.screenWidth), Ratio(screen.scriptHeight, screen.screenHeight)); + noEvent.mousePosSci = input.mousePosSci = mousePosSci; + if (ev.type == Common::EVENT_MOUSEMOVE) { // This will clamp `mousePos` according to the restricted zone, // so any cursor or screen item associated with the mouse position // does not bounce when it hits the edge (or ignore the edge) g_sci->_gfxCursor32->deviceMoved(mousePos); + if (_hotRectanglesActive) { + checkHotRectangles(mousePosSci); + } } - Common::Point mousePosSci = mousePos; - mulru(mousePosSci, Ratio(screen.scriptWidth, screen.screenWidth), Ratio(screen.scriptHeight, screen.screenHeight)); - noEvent.mousePosSci = input.mousePosSci = mousePosSci; - } else { #endif g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x); @@ -365,7 +372,7 @@ void EventManager::updateScreen() { SciEvent EventManager::getSciEvent(uint32 mask) { #ifdef ENABLE_SCI32 - SciEvent event = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() }; + SciEvent event = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point(), -1 }; #else SciEvent event = { SCI_EVENT_NONE, 0, 0, Common::Point() }; #endif @@ -402,4 +409,43 @@ SciEvent EventManager::getSciEvent(uint32 mask) { return event; } + +#ifdef ENABLE_SCI32 +void EventManager::setHotRectanglesActive(const bool active) { + _hotRectanglesActive = active; +} + +void EventManager::setHotRectangles(const Common::Array<Common::Rect> &rects) { + _hotRects = rects; +} + +void EventManager::checkHotRectangles(const Common::Point &mousePosition) { + int lastActiveRectIndex = _activeRectIndex; + _activeRectIndex = -1; + + for (int16 i = 0; i < (int16)_hotRects.size(); ++i) { + if (_hotRects[i].contains(mousePosition)) { + _activeRectIndex = i; + if (i != lastActiveRectIndex) { + SciEvent hotRectEvent; + hotRectEvent.type = SCI_EVENT_HOT_RECTANGLE; + hotRectEvent.hotRectangleIndex = i; + _events.push_front(hotRectEvent); + break; + } + + lastActiveRectIndex = _activeRectIndex; + } + } + + if (lastActiveRectIndex != _activeRectIndex && lastActiveRectIndex != -1) { + _activeRectIndex = -1; + SciEvent hotRectEvent; + hotRectEvent.type = SCI_EVENT_HOT_RECTANGLE; + hotRectEvent.hotRectangleIndex = -1; + _events.push_front(hotRectEvent); + } +} +#endif + } // End of namespace Sci diff --git a/engines/sci/event.h b/engines/sci/event.h index 15a94b3e73..23b59f964a 100644 --- a/engines/sci/event.h +++ b/engines/sci/event.h @@ -50,6 +50,8 @@ struct SciEvent { * in script coordinates. */ Common::Point mousePosSci; + + int16 hotRectangleIndex; #endif }; @@ -60,6 +62,9 @@ struct SciEvent { #define SCI_EVENT_KEYBOARD (1 << 2) #define SCI_EVENT_DIRECTION (1 << 6) #define SCI_EVENT_SAID (1 << 7) +#ifdef ENABLE_SCI32 +#define SCI_EVENT_HOT_RECTANGLE (1 << 8) +#endif /*Fake values for other events*/ #define SCI_EVENT_QUIT (1 << 11) #define SCI_EVENT_PEEK (1 << 15) @@ -138,6 +143,17 @@ private: const bool _fontIsExtended; Common::List<SciEvent> _events; +#ifdef ENABLE_SCI32 +public: + void setHotRectanglesActive(const bool active); + void setHotRectangles(const Common::Array<Common::Rect> &rects); + void checkHotRectangles(const Common::Point &mousePosition); + +private: + bool _hotRectanglesActive; + Common::Array<Common::Rect> _hotRects; + int16 _activeRectIndex; +#endif }; } // End of namespace Sci diff --git a/engines/sci/graphics/video32.cpp b/engines/sci/graphics/video32.cpp index 506cde7b17..84c07d32f5 100644 --- a/engines/sci/graphics/video32.cpp +++ b/engines/sci/graphics/video32.cpp @@ -485,13 +485,6 @@ AVIPlayer::EventFlags AVIPlayer::playUntilEvent(EventFlags flags) { break; } } - - // TODO: Hot rectangles - if ((flags & kEventFlagHotRectangle) /* && event.type == SCI_EVENT_HOT_RECTANGLE */) { - warning("Hot rectangles not implemented in VMD player"); - stopFlag = kEventFlagHotRectangle; - break; - } } return stopFlag; @@ -655,11 +648,11 @@ VMDPlayer::EventFlags VMDPlayer::kernelPlayUntilEvent(const EventFlags flags, co } VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { - // Flushing all the keyboard and mouse events out of the event manager to - // avoid letting any events queued from before the video started from - // accidentally activating an event callback + // Flushing all the keyboard and mouse events out of the event manager + // keeps events queued from before the start of playback from accidentally + // activating a video stop flag for (;;) { - const SciEvent event = _eventMan->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_MOUSE_PRESS | SCI_EVENT_MOUSE_RELEASE | SCI_EVENT_QUIT); + const SciEvent event = _eventMan->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_MOUSE_PRESS | SCI_EVENT_MOUSE_RELEASE | SCI_EVENT_HOT_RECTANGLE | SCI_EVENT_QUIT); if (event.type == SCI_EVENT_NONE) { break; } else if (event.type == SCI_EVENT_QUIT) { @@ -667,8 +660,6 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { } } - _decoder->pauseVideo(false); - if (flags & kEventFlagReverse) { // NOTE: This flag may not work properly since SSCI does not care // if a video has audio, but the VMD decoder does. @@ -748,6 +739,14 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { g_sci->_gfxFrameout->addScreenItem(*_screenItem); + // HACK: When VMD playback is allowed to yield back to the VM, this + // causes the VMD decoder to freak out for some reason and video output + // starts jittering horribly. This problem does not happen if audio sync + // is disabled, but this causes some audible clicking between frames + // of audio (and, presumably, will cause some AV sync problems). Still, + // that's better than really bad jitter. + _decoder->setAudioSync(!(flags & kEventFlagYieldToVM)); + _decoder->start(); } @@ -758,9 +757,11 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { break; } - g_sci->getEngineState()->speedThrottler(_decoder->getTimeToNextFrame()); - g_sci->getEngineState()->_throttleTrigger = true; - if (_decoder->needsUpdate()) { + // Sleeping any more than 1/60th of a second will make the mouse feel + // very sluggish during VMD action sequences because the frame rate of + // VMDs is usually only 15fps + g_sci->sleep(MIN<uint32>(10, _decoder->getTimeToNextFrame())); + while (_decoder->needsUpdate()) { renderFrame(); } @@ -802,15 +803,13 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { } } - // TODO: Hot rectangles - if ((flags & kEventFlagHotRectangle) /* && event.type == SCI_EVENT_HOT_RECTANGLE */) { - warning("Hot rectangles not implemented in VMD player"); + event = _eventMan->getSciEvent(SCI_EVENT_HOT_RECTANGLE | SCI_EVENT_PEEK); + if ((flags & kEventFlagHotRectangle) && event.type == SCI_EVENT_HOT_RECTANGLE) { stopFlag = kEventFlagHotRectangle; break; } } - _decoder->pauseVideo(true); return stopFlag; } @@ -859,7 +858,6 @@ void VMDPlayer::renderFrame() const { g_sci->_gfxFrameout->updateScreenItem(*_screenItem); g_sci->getSciDebugger()->onFrame(); g_sci->_gfxFrameout->frameOut(true); - g_sci->_gfxFrameout->throttle(); } } |