diff options
author | Colin Snover | 2016-03-10 14:05:27 -0600 |
---|---|---|
committer | Colin Snover | 2016-03-10 14:16:56 -0600 |
commit | 4a16ebc970bfe1eae948b5d59accc321b092db8c (patch) | |
tree | e686fe900fe88ddd914cfaba18bbc49edd87c19b /engines/sci/graphics | |
parent | eac416f480ca5d08a6117b15e78ef906a0135c91 (diff) | |
download | scummvm-rg350-4a16ebc970bfe1eae948b5d59accc321b092db8c.tar.gz scummvm-rg350-4a16ebc970bfe1eae948b5d59accc321b092db8c.tar.bz2 scummvm-rg350-4a16ebc970bfe1eae948b5d59accc321b092db8c.zip |
SCI32: Implement kSetNowSeen
Diffstat (limited to 'engines/sci/graphics')
-rw-r--r-- | engines/sci/graphics/compare.cpp | 21 | ||||
-rw-r--r-- | engines/sci/graphics/frameout.cpp | 20 | ||||
-rw-r--r-- | engines/sci/graphics/frameout.h | 1 | ||||
-rw-r--r-- | engines/sci/graphics/screen_item32.cpp | 103 | ||||
-rw-r--r-- | engines/sci/graphics/screen_item32.h | 7 |
5 files changed, 131 insertions, 21 deletions
diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp index 698ad1baf1..2f83017915 100644 --- a/engines/sci/graphics/compare.cpp +++ b/engines/sci/graphics/compare.cpp @@ -122,9 +122,6 @@ uint16 GfxCompare::kernelOnControl(byte screenMask, const Common::Rect &rect) { void GfxCompare::kernelSetNowSeen(reg_t objectReference) { GfxView *view = NULL; Common::Rect celRect(0, 0); - // TODO/FIXME: Torin's menu code tries to draw special views with an ID of 0xFFFF, which - // are not currently handled properly and cause a crash. These might be text views that - // are not properly implemented. GuiResourceId viewId = (GuiResourceId)readSelectorValue(_segMan, objectReference, SELECTOR(view)); int16 loopNo = readSelectorValue(_segMan, objectReference, SELECTOR(loop)); int16 celNo = readSelectorValue(_segMan, objectReference, SELECTOR(cel)); @@ -135,26 +132,8 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) { z = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(z)); view = _cache->getView(viewId); - -#ifdef ENABLE_SCI32 - if (view->isSci2Hires()) - view->adjustToUpscaledCoordinates(y, x); - else if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE)) - _coordAdjuster->fromScriptToDisplay(y, x); -#endif - view->getCelRect(loopNo, celNo, x, y, z, celRect); -#ifdef ENABLE_SCI32 - if (view->isSci2Hires()) { - view->adjustBackUpscaledCoordinates(celRect.top, celRect.left); - view->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right); - } else if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE)) { - _coordAdjuster->fromDisplayToScript(celRect.top, celRect.left); - _coordAdjuster->fromDisplayToScript(celRect.bottom, celRect.right); - } -#endif - if (lookupSelector(_segMan, objectReference, SELECTOR(nsTop), NULL, NULL) == kSelectorVariable) { setNSRect(objectReference, celRect); } diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 655e59de00..78e61b9e34 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -2028,6 +2028,26 @@ bool GfxFrameout::isOnMe(const ScreenItem &screenItem, const Plane &plane, const return true; } +void GfxFrameout::kernelSetNowSeen(const reg_t screenItemObject) const { + const reg_t planeObject = readSelector(_segMan, screenItemObject, SELECTOR(plane)); + + Plane *plane = _planes.findByObject(planeObject); + if (plane == nullptr) { + error("Plane %04x:%04x not found", PRINT_REG(planeObject)); + } + + ScreenItem *screenItem = plane->_screenItemList.findByObject(screenItemObject); + if (screenItem == nullptr) { + error("Screen item %04x:%04x not found", PRINT_REG(screenItemObject)); + } + + Common::Rect result = screenItem->getNowSeenRect(*plane); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsLeft), result.left); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsTop), result.top); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsRight), result.right - 1); + writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsBottom), result.bottom - 1); +} + #pragma mark - #pragma mark Debugging diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index f864abc5bc..969123f4d3 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -245,6 +245,7 @@ public: void kernelAddScreenItem(const reg_t object); void kernelUpdateScreenItem(const reg_t object); void kernelDeleteScreenItem(const reg_t object); + void kernelSetNowSeen(const reg_t screenItemObject) const; #pragma mark - #pragma mark Planes diff --git a/engines/sci/graphics/screen_item32.cpp b/engines/sci/graphics/screen_item32.cpp index 4a42221875..9f6dc7a2a2 100644 --- a/engines/sci/graphics/screen_item32.cpp +++ b/engines/sci/graphics/screen_item32.cpp @@ -495,6 +495,109 @@ void ScreenItem::update(const reg_t object) { _deleted = 0; } +// TODO: This code is quite similar to calcRects, so try to deduplicate +// if possible +Common::Rect ScreenItem::getNowSeenRect(const Plane &plane) const { + CelObj &celObj = getCelObj(); + + Common::Rect celObjRect(celObj._width, celObj._height); + Common::Rect nsRect; + + if (_useInsetRect) { + // TODO: This is weird. Checking to see if the inset rect is + // fully inside the bounds of the celObjRect, and then + // clipping to the celObjRect, is pretty useless. + if (_insetRect.right > 0 && _insetRect.bottom > 0 && _insetRect.left < celObj._width && _insetRect.top < celObj._height) { + nsRect = _insetRect; + nsRect.clip(celObjRect); + } else { + nsRect = Common::Rect(); + } + } else { + nsRect = celObjRect; + } + + const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + + Ratio scaleX, scaleY; + if (_scale.signal & kScaleSignalDoScaling32) { + if (_scale.signal & kScaleSignalUseVanishingPoint) { + int num = _scale.max * (_position.y - plane._vanishingPoint.y) / (scriptWidth - plane._vanishingPoint.y); + scaleX = Ratio(num, 128); + scaleY = Ratio(num, 128); + } else { + scaleX = Ratio(_scale.x, 128); + scaleY = Ratio(_scale.y, 128); + } + } + + if (scaleX.getNumerator() == 0 || scaleY.getNumerator() == 0) { + return Common::Rect(); + } + + int16 displaceX = celObj._displace.x; + int16 displaceY = celObj._displace.y; + + if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) { + displaceX = celObj._width - displaceX - 1; + } + + if (celObj._scaledWidth != scriptWidth || celObj._scaledHeight != scriptHeight) { + if (_useInsetRect) { + Ratio scriptToScaledX(celObj._scaledWidth, scriptWidth); + Ratio scriptToScaledY(celObj._scaledHeight, scriptHeight); + mulru(nsRect, scriptToScaledX, scriptToScaledY, 0); + + // TODO: This is weird. Checking to see if the inset rect is + // fully inside the bounds of the celObjRect, and then + // clipping to the celObjRect, is pretty useless. + if (nsRect.right > 0 && nsRect.bottom > 0 && nsRect.left < celObj._width && nsRect.top < celObj._height) { + nsRect.clip(celObjRect); + } else { + nsRect = Common::Rect(); + } + } + + if (!scaleX.isOne() || !scaleY.isOne()) { + mulinc(nsRect, scaleX, scaleY); + // TODO: This was in the original code, baked into the + // multiplication though it is not immediately clear + // why this is the only one that reduces the BR corner + nsRect.right -= 1; + nsRect.bottom -= 1; + } + + Ratio scaledToScriptX(scriptWidth, celObj._scaledWidth); + Ratio scaledToScriptY(scriptHeight, celObj._scaledHeight); + + displaceX = (displaceX * scaleX * scaledToScriptX).toInt(); + displaceY = (displaceY * scaleY * scaledToScriptY).toInt(); + + mulinc(nsRect, scaledToScriptX, scaledToScriptY); + nsRect.translate(_position.x - displaceX, _position.y - displaceY); + } else { + if (!scaleX.isOne() || !scaleY.isOne()) { + mulinc(nsRect, scaleX, scaleY); + // TODO: This was in the original code, baked into the + // multiplication though it is not immediately clear + // why this is the only one that reduces the BR corner + nsRect.right -= 1; + nsRect.bottom -= 1; + } + + displaceX = (displaceX * scaleX).toInt(); + displaceY = (displaceY * scaleY).toInt(); + nsRect.translate(_position.x - displaceX, _position.y - displaceY); + + if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) { + nsRect.translate(plane._gameRect.width() - nsRect.width(), 0); + } + } + + return nsRect; +} + #pragma mark - #pragma mark ScreenItemList ScreenItem *ScreenItemList::findByObject(const reg_t object) const { diff --git a/engines/sci/graphics/screen_item32.h b/engines/sci/graphics/screen_item32.h index 52782acc56..977d80ebad 100644 --- a/engines/sci/graphics/screen_item32.h +++ b/engines/sci/graphics/screen_item32.h @@ -259,6 +259,13 @@ public: * VM object. */ void update(const reg_t object); + + /** + * Gets the "now seen" rect for the screen item, which + * represents the current size and position of the + * screen item on the screen in script coordinates. + */ + Common::Rect getNowSeenRect(const Plane &plane) const; }; #pragma mark - |