diff options
author | Colin Snover | 2016-06-18 20:48:10 -0500 |
---|---|---|
committer | Colin Snover | 2016-06-21 08:14:12 -0500 |
commit | a613a27b44eae68650eb9150ea146dff9befea28 (patch) | |
tree | 0aacbadabc6013a1ed45b234e14d71d9f6ea09f1 /engines/sci/graphics | |
parent | 94328f0ec8baa96947c5b82c63bdd298ba44981d (diff) | |
download | scummvm-rg350-a613a27b44eae68650eb9150ea146dff9befea28.tar.gz scummvm-rg350-a613a27b44eae68650eb9150ea146dff9befea28.tar.bz2 scummvm-rg350-a613a27b44eae68650eb9150ea146dff9befea28.zip |
SCI32: Implement line drawing (kAddLine/kUpdateLine/kRemoveLine)
This line drawing code lives in a remodelled GfxPaint32 class
that is totally separate from GfxPaint16.
Diffstat (limited to 'engines/sci/graphics')
-rw-r--r-- | engines/sci/graphics/frameout.cpp | 25 | ||||
-rw-r--r-- | engines/sci/graphics/frameout.h | 11 | ||||
-rw-r--r-- | engines/sci/graphics/paint.cpp | 44 | ||||
-rw-r--r-- | engines/sci/graphics/paint.h | 39 | ||||
-rw-r--r-- | engines/sci/graphics/paint16.h | 4 | ||||
-rw-r--r-- | engines/sci/graphics/paint32.cpp | 167 | ||||
-rw-r--r-- | engines/sci/graphics/paint32.h | 44 | ||||
-rw-r--r-- | engines/sci/graphics/screen_item32.cpp | 12 | ||||
-rw-r--r-- | engines/sci/graphics/screen_item32.h | 6 | ||||
-rw-r--r-- | engines/sci/graphics/text32.h | 1 |
10 files changed, 218 insertions, 135 deletions
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 2d44e38390..51a666e83e 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -259,6 +259,22 @@ void GfxFrameout::syncWithScripts(bool addElements) { #pragma mark - #pragma mark Screen items +void GfxFrameout::deleteScreenItem(ScreenItem *screenItem, Plane *plane) { + if (screenItem->_created == 0) { + screenItem->_created = 0; + screenItem->_updated = 0; + screenItem->_deleted = getScreenCount(); + } else { + plane->_screenItemList.erase(screenItem); + plane->_screenItemList.pack(); + } +} + +void GfxFrameout::deleteScreenItem(ScreenItem *screenItem, const reg_t planeObject) { + Plane *plane = _planes.findByObject(planeObject); + deleteScreenItem(screenItem, plane); +} + void GfxFrameout::kernelAddScreenItem(const reg_t object) { // The "fred" object is used to test graphics performance; // it is impacted by framerate throttling, so disable the @@ -335,14 +351,7 @@ void GfxFrameout::kernelDeleteScreenItem(const reg_t object) { return; } - if (screenItem->_created == 0) { - screenItem->_created = 0; - screenItem->_updated = 0; - screenItem->_deleted = getScreenCount(); - } else { - plane->_screenItemList.erase(screenItem); - plane->_screenItemList.pack(); - } + deleteScreenItem(screenItem, plane); } #pragma mark - diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 0f06ee1c85..4ebb754ba7 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -197,10 +197,19 @@ private: #pragma mark - #pragma mark Screen items private: - void deleteScreenItem(ScreenItem *screenItem, const reg_t plane); void remapMarkRedraw(); public: + /** + * Deletes a screen item from the given plane. + */ + void deleteScreenItem(ScreenItem *screenItem, Plane *plane); + + /** + * Deletes a screen item from the given plane. + */ + void deleteScreenItem(ScreenItem *screenItem, const reg_t plane); + void kernelAddScreenItem(const reg_t object); void kernelUpdateScreenItem(const reg_t object); void kernelDeleteScreenItem(const reg_t object); diff --git a/engines/sci/graphics/paint.cpp b/engines/sci/graphics/paint.cpp deleted file mode 100644 index 482b81aff1..0000000000 --- a/engines/sci/graphics/paint.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "graphics/primitives.h" - -#include "sci/sci.h" -#include "sci/engine/state.h" -#include "sci/engine/selector.h" -#include "sci/graphics/paint.h" - -namespace Sci { - -GfxPaint::GfxPaint() { -} - -GfxPaint::~GfxPaint() { -} - -void GfxPaint::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo) { -} - -void GfxPaint::kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control) { -} - -} // End of namespace Sci diff --git a/engines/sci/graphics/paint.h b/engines/sci/graphics/paint.h deleted file mode 100644 index b2277131d5..0000000000 --- a/engines/sci/graphics/paint.h +++ /dev/null @@ -1,39 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef SCI_GRAPHICS_PAINT_H -#define SCI_GRAPHICS_PAINT_H - -namespace Sci { - -class GfxPaint { -public: - GfxPaint(); - virtual ~GfxPaint(); - - virtual void kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo); - virtual void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control); -}; - -} // End of namespace Sci - -#endif diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h index 955cfdec8f..317388b2df 100644 --- a/engines/sci/graphics/paint16.h +++ b/engines/sci/graphics/paint16.h @@ -23,8 +23,6 @@ #ifndef SCI_GRAPHICS_PAINT16_H #define SCI_GRAPHICS_PAINT16_H -#include "sci/graphics/paint.h" - namespace Sci { class GfxPorts; @@ -36,7 +34,7 @@ class GfxView; /** * Paint16 class, handles painting/drawing for SCI16 (SCI0-SCI1.1) games */ -class GfxPaint16 : public GfxPaint { +class GfxPaint16 { public: GfxPaint16(ResourceManager *resMan, SegManager *segMan, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio); ~GfxPaint16(); diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp index a210a469f1..bfd46484e9 100644 --- a/engines/sci/graphics/paint32.cpp +++ b/engines/sci/graphics/paint32.cpp @@ -20,49 +20,162 @@ * */ -#include "sci/sci.h" -#include "sci/engine/state.h" -#include "sci/engine/selector.h" -#include "sci/graphics/coordadjuster.h" -#include "sci/graphics/cache.h" +#include "graphics/primitives.h" +#include "sci/engine/seg_manager.h" #include "sci/graphics/paint32.h" -#include "sci/graphics/font.h" -#include "sci/graphics/picture.h" -#include "sci/graphics/view.h" -#include "sci/graphics/screen.h" -#include "sci/graphics/palette.h" +#include "sci/graphics/text32.h" namespace Sci { -GfxPaint32::GfxPaint32(ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette) - : _resMan(resMan), _coordAdjuster(coordAdjuster), _screen(screen), _palette(palette) { +GfxPaint32::GfxPaint32(SegManager *segMan) : + _segMan(segMan) {} + +reg_t GfxPaint32::kernelAddLine(const reg_t planeObject, const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, const uint16 pattern, const uint8 thickness) { + Plane *plane = g_sci->_gfxFrameout->getPlanes().findByObject(planeObject); + if (plane == nullptr) { + error("kAddLine: Plane %04x:%04x not found", PRINT_REG(planeObject)); + } + + Common::Rect gameRect; + BitmapResource bitmap = makeLineBitmap(startPoint, endPoint, priority, color, style, pattern, thickness, gameRect); + + CelInfo32 celInfo; + celInfo.type = kCelTypeMem; + celInfo.bitmap = bitmap.getObject(); + // SSCI stores the line color on `celInfo`, even though + // this is not a `kCelTypeColor`, as a hack so that + // `kUpdateLine` can get the originally used color + celInfo.color = color; + + ScreenItem *screenItem = new ScreenItem(planeObject, celInfo, Common::Rect(startPoint.x, startPoint.y, startPoint.x + bitmap.getWidth(), startPoint.y + bitmap.getHeight())); + screenItem->_priority = priority; + screenItem->_fixedPriority = true; + + plane->_screenItemList.add(screenItem); + + return screenItem->_object; +} + +void GfxPaint32::kernelUpdateLine(ScreenItem *screenItem, Plane *plane, const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, const uint16 pattern, const uint8 thickness) { + + Common::Rect gameRect; + BitmapResource bitmap = makeLineBitmap(startPoint, endPoint, priority, color, style, pattern, thickness, gameRect); + + _segMan->freeHunkEntry(screenItem->_celInfo.bitmap); + screenItem->_celInfo.bitmap = bitmap.getObject(); + screenItem->_celInfo.color = color; + screenItem->_position = startPoint; + screenItem->_priority = priority; + screenItem->update(); } -GfxPaint32::~GfxPaint32() { +void GfxPaint32::kernelDeleteLine(const reg_t screenItemObject, const reg_t planeObject) { + Plane *plane = g_sci->_gfxFrameout->getPlanes().findByObject(planeObject); + if (plane == nullptr) { + return; + } + + ScreenItem *screenItem = plane->_screenItemList.findByObject(screenItemObject); + if (screenItem == nullptr) { + return; + } + + _segMan->freeHunkEntry(screenItem->_celInfo.bitmap); + g_sci->_gfxFrameout->deleteScreenItem(screenItem, plane); } -void GfxPaint32::fillRect(Common::Rect rect, byte color) { - int16 y, x; - Common::Rect clipRect = rect; +void GfxPaint32::plotter(int x, int y, int color, void *data) { + LineProperties &properties = *static_cast<LineProperties *>(data); + byte *pixels = properties.bitmap->getPixels(); + + const uint32 index = properties.bitmap->getWidth() * y + x; + + if (index < properties.bitmap->getDataSize()) { + if (properties.solid) { + pixels[index] = (uint8)color; + return; + } + + if (properties.horizontal && x != properties.lastAddress) { + properties.lastAddress = x; + ++properties.patternIndex; + } else if (!properties.horizontal && y != properties.lastAddress) { + properties.lastAddress = y; + ++properties.patternIndex; + } - clipRect.clip(_screen->getWidth(), _screen->getHeight()); + if (properties.pattern[properties.patternIndex]) { + pixels[index] = (uint8)color; + } - for (y = clipRect.top; y < clipRect.bottom; y++) { - for (x = clipRect.left; x < clipRect.right; x++) { - _screen->putPixel(x, y, GFX_SCREEN_MASK_VISUAL, color, 0, 0); + if (properties.patternIndex == ARRAYSIZE(properties.pattern)) { + properties.patternIndex = 0; } + } else { + warning("GfxPaint32::plotter: Attempted to write out of bounds (%u >= %u)", index, properties.bitmap->getDataSize()); } } -void GfxPaint32::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo) { - GfxPicture *picture = new GfxPicture(_resMan, _coordAdjuster, 0, _screen, _palette, pictureId, false); +BitmapResource GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, uint16 pattern, uint8 thickness, Common::Rect &outRect) { + const uint8 skipColor = color != 250 ? 250 : 0; - picture->draw(animationNr, mirroredFlag, addToFlag, EGApaletteNo); - delete picture; -} + // Thickness is expected to be 2n+1 + thickness = ((MAX((uint8)1, thickness) - 1) | 1); + const uint8 halfThickness = thickness >> 1; + + outRect.left = (startPoint.x < endPoint.x ? startPoint.x : endPoint.x) - halfThickness; + outRect.top = (startPoint.y < endPoint.y ? startPoint.y : endPoint.y) - halfThickness; + outRect.right = (startPoint.x > endPoint.x ? startPoint.x : endPoint.x) + halfThickness + 1; + outRect.bottom = (startPoint.y > endPoint.y ? startPoint.y : endPoint.y) + halfThickness + 1; + + BitmapResource bitmap(_segMan, outRect.width(), outRect.height(), skipColor, 0, 0, g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth, g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight, 0, false); + + byte *pixels = bitmap.getPixels(); + memset(pixels, skipColor, bitmap.getWidth() * bitmap.getHeight()); + + LineProperties properties; + properties.bitmap = &bitmap; + + switch (style) { + case kLineStyleSolid: + pattern = 0xFFFF; + properties.solid = true; + break; + case kLineStyleDashed: + pattern = 0xFF00; + properties.solid = false; + break; + case kLineStylePattern: + properties.solid = pattern == 0xFFFF; + break; + } + + const Common::Rect drawRect( + startPoint.x - outRect.left, + startPoint.y - outRect.top, + endPoint.x - outRect.left, + endPoint.y - outRect.top + ); -void GfxPaint32::kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control) { - _screen->drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, color, priority, control); + if (!properties.solid) { + for (int i = 0; i < ARRAYSIZE(properties.pattern); ++i) { + properties.pattern[i] = (pattern & 0x8000); + pattern <<= 1; + } + + properties.patternIndex = 0; + properties.horizontal = ABS(drawRect.right - drawRect.left) > ABS(drawRect.bottom - drawRect.top); + properties.lastAddress = properties.horizontal ? drawRect.left : drawRect.top; + } + + if (thickness <= 1) { + Graphics::drawLine(drawRect.left, drawRect.top, drawRect.right, drawRect.bottom, color, plotter, &properties); + } else { + Graphics::drawThickLine2(drawRect.left, drawRect.top, drawRect.right, drawRect.bottom, thickness, color, plotter, &properties); + } + + return bitmap; } + } // End of namespace Sci diff --git a/engines/sci/graphics/paint32.h b/engines/sci/graphics/paint32.h index e7a3ec256d..6d5a957fcd 100644 --- a/engines/sci/graphics/paint32.h +++ b/engines/sci/graphics/paint32.h @@ -23,30 +23,48 @@ #ifndef SCI_GRAPHICS_PAINT32_H #define SCI_GRAPHICS_PAINT32_H -#include "sci/graphics/paint.h" - namespace Sci { +class BitmapResource; +class Plane; +class ScreenItem; +class SegManager; -class GfxPorts; +enum LineStyle { + kLineStyleSolid, + kLineStyleDashed, + kLineStylePattern +}; /** * Paint32 class, handles painting/drawing for SCI32 (SCI2+) games */ -class GfxPaint32 : public GfxPaint { +class GfxPaint32 { public: - GfxPaint32(ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette); - ~GfxPaint32(); + GfxPaint32(SegManager *segMan); - void fillRect(Common::Rect rect, byte color); +private: + SegManager *_segMan; - void kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo); - void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control); +#pragma mark - +#pragma mark Line drawing +public: + reg_t kernelAddLine(const reg_t planeObject, const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, const uint16 pattern, const uint8 thickness); + void kernelUpdateLine(ScreenItem *screenItem, Plane *plane, const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, const uint16 pattern, const uint8 thickness); + void kernelDeleteLine(const reg_t screenItemObject, const reg_t planeObject); private: - ResourceManager *_resMan; - GfxCoordAdjuster *_coordAdjuster; - GfxScreen *_screen; - GfxPalette *_palette; + typedef struct { + BitmapResource *bitmap; + bool pattern[16]; + uint8 patternIndex; + bool solid; + bool horizontal; + int lastAddress; + } LineProperties; + + static void plotter(int x, int y, int color, void *data); + + BitmapResource makeLineBitmap(const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, const uint16 pattern, const uint8 thickness, Common::Rect &outRect); }; } // End of namespace Sci diff --git a/engines/sci/graphics/screen_item32.cpp b/engines/sci/graphics/screen_item32.cpp index fba0fa0422..a3728d9ce2 100644 --- a/engines/sci/graphics/screen_item32.cpp +++ b/engines/sci/graphics/screen_item32.cpp @@ -515,6 +515,18 @@ void ScreenItem::update(const reg_t object) { _deleted = 0; } +void ScreenItem::update() { + // TODO: error out if we're not contained in our plane's ScreenItemList + + if (!_created) { + _updated = g_sci->_gfxFrameout->getScreenCount(); + } + _deleted = 0; + + delete _celObj; + _celObj = nullptr; +} + // TODO: This code is quite similar to calcRects, so try to deduplicate // if possible Common::Rect ScreenItem::getNowSeenRect(const Plane &plane) const { diff --git a/engines/sci/graphics/screen_item32.h b/engines/sci/graphics/screen_item32.h index 91f54b48e9..eef2f488a5 100644 --- a/engines/sci/graphics/screen_item32.h +++ b/engines/sci/graphics/screen_item32.h @@ -261,6 +261,12 @@ public: void update(const reg_t object); /** + * Updates the properties of the screen item for one not belonging + * to a VM object. Originally GraphicsMgr::UpdateScreenItem. + */ + void update(); + + /** * 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. diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h index 905e88baf4..c28629871f 100644 --- a/engines/sci/graphics/text32.h +++ b/engines/sci/graphics/text32.h @@ -23,6 +23,7 @@ #ifndef SCI_GRAPHICS_TEXT32_H #define SCI_GRAPHICS_TEXT32_H +#include "sci/engine/state.h" #include "sci/graphics/celobj32.h" #include "sci/graphics/frameout.h" |