From 5f9d03e9df954688e12b9caf13cf7c835316eee9 Mon Sep 17 00:00:00 2001 From: Ted John Date: Fri, 3 Dec 2021 18:59:33 +0000 Subject: [PATCH] Refactor ImageId and use in more functions --- .../engines/opengl/OpenGLDrawingEngine.cpp | 39 ++- .../drawing/engines/opengl/TextureCache.cpp | 48 ++- .../drawing/engines/opengl/TextureCache.h | 23 +- .../windows/EditorObjectSelection.cpp | 6 +- src/openrct2-ui/windows/NewRide.cpp | 27 +- src/openrct2/drawing/Drawing.Sprite.cpp | 16 +- src/openrct2/drawing/Drawing.h | 195 +------------ src/openrct2/drawing/IDrawingContext.h | 4 +- src/openrct2/drawing/ImageId.hpp | 273 ++++++++++++++++++ src/openrct2/drawing/NewDrawing.cpp | 10 +- src/openrct2/drawing/X8DrawingEngine.cpp | 7 +- src/openrct2/drawing/X8DrawingEngine.h | 4 +- src/openrct2/interface/Colour.h | 1 + src/openrct2/object/RideObject.cpp | 11 + src/openrct2/object/RideObject.h | 3 + src/openrct2/paint/Paint.cpp | 100 ++++--- src/openrct2/paint/Paint.h | 14 +- src/openrct2/paint/Supports.cpp | 12 +- 18 files changed, 452 insertions(+), 341 deletions(-) create mode 100644 src/openrct2/drawing/ImageId.hpp diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp index 13281c0bff..0e2ba6dd99 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -105,8 +105,8 @@ public: void FilterRect( rct_drawpixelinfo* dpi, FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) override; void DrawLine(rct_drawpixelinfo* dpi, uint32_t colour, const ScreenLine& line) override; - void DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) override; - void DrawSpriteRawMasked(rct_drawpixelinfo* dpi, int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) override; + void DrawSprite(rct_drawpixelinfo* dpi, ImageId imageId, int32_t x, int32_t y) override; + void DrawSpriteRawMasked(rct_drawpixelinfo* dpi, int32_t x, int32_t y, ImageId maskImage, ImageId colourImage) override; void DrawSpriteSolid(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint8_t colour) override; void DrawGlyph(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, const PaletteMap& palette) override; void DrawBitmap( @@ -617,12 +617,11 @@ void OpenGLDrawingContext::DrawLine(rct_drawpixelinfo* dpi, uint32_t colour, con command.depth = _drawCount++; } -void OpenGLDrawingContext::DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) +void OpenGLDrawingContext::DrawSprite(rct_drawpixelinfo* dpi, ImageId imageId, int32_t x, int32_t y) { CalculcateClipping(dpi); - int32_t g1Id = image & 0x7FFFF; - auto g1Element = gfx_get_g1_element(g1Id); + auto g1Element = gfx_get_g1_element(imageId); if (g1Element == nullptr) { return; @@ -640,7 +639,7 @@ void OpenGLDrawingContext::DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, in zoomedDPI.width = dpi->width >> 1; zoomedDPI.pitch = dpi->pitch; zoomedDPI.zoom_level = dpi->zoom_level - 1; - DrawSprite(&zoomedDPI, (image & 0xFFF80000) | (g1Id - g1Element->zoomed_offset), x >> 1, y >> 1, tertiaryColour); + DrawSprite(&zoomedDPI, imageId.WithIndex(imageId.GetIndex() - g1Element->zoomed_offset), x >> 1, y >> 1); return; } if (g1Element->flags & G1_FLAG_NO_ZOOM_DRAW) @@ -702,29 +701,29 @@ void OpenGLDrawingContext::DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, in right += _spriteOffset.x; bottom += _spriteOffset.y; - const auto texture = _textureCache->GetOrLoadImageTexture(image); + const auto texture = _textureCache->GetOrLoadImageTexture(imageId); int paletteCount; ivec3 palettes{}; bool special = false; - if (image & IMAGE_TYPE_REMAP_2_PLUS) + if (imageId.HasSecondary()) { - palettes.x = TextureCache::PaletteToY(static_cast((image >> 19) & 0x1F)); - palettes.y = TextureCache::PaletteToY(static_cast((image >> 24) & 0x1F)); - if (image & IMAGE_TYPE_REMAP) + palettes.x = TextureCache::PaletteToY(static_cast(imageId.GetPrimary())); + palettes.y = TextureCache::PaletteToY(static_cast(imageId.GetSecondary())); + if (!imageId.HasTertiary()) { paletteCount = 2; } else { paletteCount = 3; - palettes.z = TextureCache::PaletteToY(static_cast(tertiaryColour & 0xFF)); + palettes.z = TextureCache::PaletteToY(static_cast(imageId.GetTertiary())); } } - else if ((image & IMAGE_TYPE_REMAP) || (image & IMAGE_TYPE_TRANSPARENT)) + else if (imageId.IsRemap() || imageId.IsBlended()) { paletteCount = 1; - FilterPaletteID palette = static_cast((image >> 19) & 0xFF); + FilterPaletteID palette = static_cast(imageId.GetRemap()); palettes.x = TextureCache::PaletteToY(palette); if (palette == FilterPaletteID::PaletteWater) { @@ -736,7 +735,7 @@ void OpenGLDrawingContext::DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, in paletteCount = 0; } - if (special || (image & IMAGE_TYPE_TRANSPARENT)) + if (special || imageId.IsBlended()) { DrawRectCommand& command = _commandBuffers.transparent.allocate(); @@ -769,12 +768,12 @@ void OpenGLDrawingContext::DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, in } void OpenGLDrawingContext::DrawSpriteRawMasked( - rct_drawpixelinfo* dpi, int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) + rct_drawpixelinfo* dpi, int32_t x, int32_t y, ImageId maskImage, ImageId colourImage) { CalculcateClipping(dpi); - auto g1ElementMask = gfx_get_g1_element(maskImage & 0x7FFFF); - auto g1ElementColour = gfx_get_g1_element(colourImage & 0x7FFFF); + auto g1ElementMask = gfx_get_g1_element(maskImage); + auto g1ElementColour = gfx_get_g1_element(colourImage); if (g1ElementMask == nullptr || g1ElementColour == nullptr) { return; @@ -844,7 +843,7 @@ void OpenGLDrawingContext::DrawSpriteSolid(rct_drawpixelinfo* dpi, uint32_t imag return; } - const auto texture = _textureCache->GetOrLoadImageTexture(image); + const auto texture = _textureCache->GetOrLoadImageTexture(ImageId::FromUInt32(image)); int32_t drawOffsetX = g1Element->x_offset; int32_t drawOffsetY = g1Element->y_offset; @@ -894,7 +893,7 @@ void OpenGLDrawingContext::DrawGlyph(rct_drawpixelinfo* dpi, uint32_t image, int return; } - const auto texture = _textureCache->GetOrLoadGlyphTexture(image, palette); + const auto texture = _textureCache->GetOrLoadGlyphTexture(ImageId::FromUInt32(image), palette); int32_t left = x + g1Element->x_offset; int32_t top = y + g1Element->y_offset; diff --git a/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp b/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp index 178ed50dd2..31265499de 100644 --- a/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp @@ -30,7 +30,7 @@ TextureCache::~TextureCache() FreeTextures(); } -void TextureCache::InvalidateImage(uint32_t image) +void TextureCache::InvalidateImage(ImageIndex image) { unique_lock lock(_mutex); @@ -64,17 +64,15 @@ void TextureCache::InvalidateImage(uint32_t image) } // Note: for performance reasons, this returns a BasicTextureInfo over an AtlasTextureInfo (also to not expose the cache) -BasicTextureInfo TextureCache::GetOrLoadImageTexture(uint32_t image) +BasicTextureInfo TextureCache::GetOrLoadImageTexture(ImageId imageId) { uint32_t index; - image &= 0x7FFFFUL; - // Try to read cached texture first. { shared_lock lock(_mutex); - index = _indexMap[image]; + index = _indexMap[imageId.GetIndex()]; if (index != UNUSED_INDEX) { const auto& info = _textureCache[index]; @@ -90,18 +88,18 @@ BasicTextureInfo TextureCache::GetOrLoadImageTexture(uint32_t image) index = static_cast(_textureCache.size()); - AtlasTextureInfo info = LoadImageTexture(image); + AtlasTextureInfo info = LoadImageTexture(imageId); _textureCache.push_back(info); - _indexMap[image] = index; + _indexMap[imageId.GetIndex()] = index; return info; } -BasicTextureInfo TextureCache::GetOrLoadGlyphTexture(uint32_t image, const PaletteMap& paletteMap) +BasicTextureInfo TextureCache::GetOrLoadGlyphTexture(ImageId imageId, const PaletteMap& paletteMap) { GlyphId glyphId{}; - glyphId.Image = image; + glyphId.Image = imageId.GetIndex(); // Try to read cached texture first. { @@ -128,18 +126,16 @@ BasicTextureInfo TextureCache::GetOrLoadGlyphTexture(uint32_t image, const Palet // Load new texture. unique_lock lock(_mutex); - auto cacheInfo = LoadGlyphTexture(image, paletteMap); + auto cacheInfo = LoadGlyphTexture(imageId, paletteMap); auto it = _glyphTextureMap.insert(std::make_pair(glyphId, cacheInfo)); return (*it.first).second; } -BasicTextureInfo TextureCache::GetOrLoadBitmapTexture(uint32_t image, const void* pixels, size_t width, size_t height) +BasicTextureInfo TextureCache::GetOrLoadBitmapTexture(ImageIndex image, const void* pixels, size_t width, size_t height) { uint32_t index; - image &= 0x7FFFF; - // Try to read cached texture first. { shared_lock lock(_mutex); @@ -270,12 +266,12 @@ void TextureCache::EnlargeAtlasesTexture(GLuint newEntries) _atlasesTextureIndices = newIndices; } -AtlasTextureInfo TextureCache::LoadImageTexture(uint32_t image) +AtlasTextureInfo TextureCache::LoadImageTexture(ImageId imageId) { - rct_drawpixelinfo dpi = GetImageAsDPI(image, 0); + rct_drawpixelinfo dpi = GetImageAsDPI(ImageId(imageId.GetIndex())); auto cacheInfo = AllocateImage(dpi.width, dpi.height); - cacheInfo.image = image; + cacheInfo.image = imageId.GetIndex(); glBindTexture(GL_TEXTURE_2D_ARRAY, _atlasesTexture); glTexSubImage3D( @@ -287,12 +283,12 @@ AtlasTextureInfo TextureCache::LoadImageTexture(uint32_t image) return cacheInfo; } -AtlasTextureInfo TextureCache::LoadGlyphTexture(uint32_t image, const PaletteMap& paletteMap) +AtlasTextureInfo TextureCache::LoadGlyphTexture(ImageId imageId, const PaletteMap& paletteMap) { - rct_drawpixelinfo dpi = GetGlyphAsDPI(image, paletteMap); + rct_drawpixelinfo dpi = GetGlyphAsDPI(imageId, paletteMap); auto cacheInfo = AllocateImage(dpi.width, dpi.height); - cacheInfo.image = image; + cacheInfo.image = imageId.GetIndex(); glBindTexture(GL_TEXTURE_2D_ARRAY, _atlasesTexture); glTexSubImage3D( @@ -304,7 +300,7 @@ AtlasTextureInfo TextureCache::LoadGlyphTexture(uint32_t image, const PaletteMap return cacheInfo; } -AtlasTextureInfo TextureCache::LoadBitmapTexture(uint32_t image, const void* pixels, size_t width, size_t height) +AtlasTextureInfo TextureCache::LoadBitmapTexture(ImageIndex image, const void* pixels, size_t width, size_t height) { auto cacheInfo = AllocateImage(int32_t(width), int32_t(height)); cacheInfo.image = image; @@ -351,27 +347,27 @@ AtlasTextureInfo TextureCache::AllocateImage(int32_t imageWidth, int32_t imageHe return _atlases.back().Allocate(imageWidth, imageHeight); } -rct_drawpixelinfo TextureCache::GetImageAsDPI(uint32_t image, uint32_t tertiaryColour) +rct_drawpixelinfo TextureCache::GetImageAsDPI(ImageId imageId) { - auto g1Element = gfx_get_g1_element(image & 0x7FFFFUL); + auto g1Element = gfx_get_g1_element(imageId); int32_t width = g1Element->width; int32_t height = g1Element->height; rct_drawpixelinfo dpi = CreateDPI(width, height); - gfx_draw_sprite_software(&dpi, ImageId::FromUInt32(image, tertiaryColour), { -g1Element->x_offset, -g1Element->y_offset }); + gfx_draw_sprite_software(&dpi, imageId, { -g1Element->x_offset, -g1Element->y_offset }); return dpi; } -rct_drawpixelinfo TextureCache::GetGlyphAsDPI(uint32_t image, const PaletteMap& palette) +rct_drawpixelinfo TextureCache::GetGlyphAsDPI(ImageId imageId, const PaletteMap& palette) { - auto g1Element = gfx_get_g1_element(image & 0x7FFFFUL); + auto g1Element = gfx_get_g1_element(imageId); int32_t width = g1Element->width; int32_t height = g1Element->height; rct_drawpixelinfo dpi = CreateDPI(width, height); const auto glyphCoords = ScreenCoordsXY{ -g1Element->x_offset, -g1Element->y_offset }; - gfx_draw_sprite_palette_set_software(&dpi, ImageId::FromUInt32(image), glyphCoords, palette); + gfx_draw_sprite_palette_set_software(&dpi, imageId, glyphCoords, palette); return dpi; } diff --git a/src/openrct2-ui/drawing/engines/opengl/TextureCache.h b/src/openrct2-ui/drawing/engines/opengl/TextureCache.h index 416a4a2ddd..adb0da2a0e 100644 --- a/src/openrct2-ui/drawing/engines/opengl/TextureCache.h +++ b/src/openrct2-ui/drawing/engines/opengl/TextureCache.h @@ -17,6 +17,7 @@ #include #include #include +#include #ifndef __MACOSX__ # include #endif @@ -29,7 +30,7 @@ enum class FilterPaletteID : int32_t; struct GlyphId { - uint32_t Image; + ImageIndex Image; uint64_t Palette; struct Hash @@ -71,7 +72,7 @@ struct AtlasTextureInfo : public BasicTextureInfo { GLuint slot; ivec4 bounds; - uint32_t image; + ImageIndex image; }; // Represents a texture atlas that images of a given maximum size can be allocated from @@ -218,10 +219,10 @@ private: public: TextureCache(); ~TextureCache(); - void InvalidateImage(uint32_t image); - BasicTextureInfo GetOrLoadImageTexture(uint32_t image); - BasicTextureInfo GetOrLoadGlyphTexture(uint32_t image, const PaletteMap& paletteMap); - BasicTextureInfo GetOrLoadBitmapTexture(uint32_t image, const void* pixels, size_t width, size_t height); + void InvalidateImage(ImageIndex image); + BasicTextureInfo GetOrLoadImageTexture(ImageId imageId); + BasicTextureInfo GetOrLoadGlyphTexture(ImageId imageId, const PaletteMap& paletteMap); + BasicTextureInfo GetOrLoadBitmapTexture(ImageIndex image, const void* pixels, size_t width, size_t height); GLuint GetAtlasesTexture(); GLuint GetPaletteTexture(); @@ -231,12 +232,12 @@ private: void CreateTextures(); void GeneratePaletteTexture(); void EnlargeAtlasesTexture(GLuint newEntries); - AtlasTextureInfo LoadImageTexture(uint32_t image); - AtlasTextureInfo LoadGlyphTexture(uint32_t image, const PaletteMap& paletteMap); + AtlasTextureInfo LoadImageTexture(ImageId image); + AtlasTextureInfo LoadGlyphTexture(ImageId image, const PaletteMap& paletteMap); AtlasTextureInfo AllocateImage(int32_t imageWidth, int32_t imageHeight); - AtlasTextureInfo LoadBitmapTexture(uint32_t image, const void* pixels, size_t width, size_t height); - static rct_drawpixelinfo GetImageAsDPI(uint32_t image, uint32_t tertiaryColour); - static rct_drawpixelinfo GetGlyphAsDPI(uint32_t image, const PaletteMap& paletteMap); + AtlasTextureInfo LoadBitmapTexture(ImageIndex image, const void* pixels, size_t width, size_t height); + static rct_drawpixelinfo GetImageAsDPI(ImageId imageId); + static rct_drawpixelinfo GetGlyphAsDPI(ImageId imageId, const PaletteMap& paletteMap); void FreeTextures(); static rct_drawpixelinfo CreateDPI(int32_t width, int32_t height); diff --git a/src/openrct2-ui/windows/EditorObjectSelection.cpp b/src/openrct2-ui/windows/EditorObjectSelection.cpp index 58f5807410..35a1828aca 100644 --- a/src/openrct2-ui/windows/EditorObjectSelection.cpp +++ b/src/openrct2-ui/windows/EditorObjectSelection.cpp @@ -957,10 +957,8 @@ public: } const int32_t ride_tabs[] = { - SPR_TAB_RIDE_16, IMAGE_TYPE_REMAP | SPR_TAB_RIDES_TRANSPORT_0, - SPR_TAB_RIDES_GENTLE_0, IMAGE_TYPE_REMAP | SPR_TAB_RIDES_ROLLER_COASTERS_0, - SPR_TAB_RIDES_THRILL_0, SPR_TAB_RIDES_WATER_0, - SPR_TAB_RIDES_SHOP_0, SPR_TAB_FINANCES_RESEARCH_0, + SPR_TAB_RIDE_16, SPR_TAB_RIDES_TRANSPORT_0, SPR_TAB_RIDES_GENTLE_0, SPR_TAB_RIDES_ROLLER_COASTERS_0, + SPR_TAB_RIDES_THRILL_0, SPR_TAB_RIDES_WATER_0, SPR_TAB_RIDES_SHOP_0, SPR_TAB_FINANCES_RESEARCH_0, }; const int32_t ThrillRidesTabAnimationSequence[] = { 5, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, diff --git a/src/openrct2-ui/windows/NewRide.cpp b/src/openrct2-ui/windows/NewRide.cpp index 7d469a4505..0939a88869 100644 --- a/src/openrct2-ui/windows/NewRide.cpp +++ b/src/openrct2-ui/windows/NewRide.cpp @@ -629,9 +629,9 @@ static void WindowNewRideDrawTabImage(rct_drawpixelinfo* dpi, rct_window* w, int static void WindowNewRideDrawTabImages(rct_drawpixelinfo* dpi, rct_window* w) { - WindowNewRideDrawTabImage(dpi, w, WINDOW_NEW_RIDE_PAGE_TRANSPORT, IMAGE_TYPE_REMAP | SPR_TAB_RIDES_TRANSPORT_0); + WindowNewRideDrawTabImage(dpi, w, WINDOW_NEW_RIDE_PAGE_TRANSPORT, SPR_TAB_RIDES_TRANSPORT_0); WindowNewRideDrawTabImage(dpi, w, WINDOW_NEW_RIDE_PAGE_GENTLE, SPR_TAB_RIDES_GENTLE_0); - WindowNewRideDrawTabImage(dpi, w, WINDOW_NEW_RIDE_PAGE_ROLLER_COASTER, IMAGE_TYPE_REMAP | SPR_TAB_RIDES_ROLLER_COASTERS_0); + WindowNewRideDrawTabImage(dpi, w, WINDOW_NEW_RIDE_PAGE_ROLLER_COASTER, SPR_TAB_RIDES_ROLLER_COASTERS_0); WindowNewRideDrawTabImage(dpi, w, WINDOW_NEW_RIDE_PAGE_THRILL, SPR_TAB_RIDES_THRILL_0); WindowNewRideDrawTabImage(dpi, w, WINDOW_NEW_RIDE_PAGE_WATER, SPR_TAB_RIDES_WATER_0); WindowNewRideDrawTabImage(dpi, w, WINDOW_NEW_RIDE_PAGE_SHOP, SPR_TAB_RIDES_SHOP_0); @@ -793,6 +793,13 @@ static void WindowNewRidePaint(rct_window* w, rct_drawpixelinfo* dpi) } } +static ImageIndex GetRideImage(RideSelection rideSelection) +{ + auto& objMgr = OpenRCT2::GetContext()->GetObjectManager(); + auto obj = static_cast(objMgr.GetLoadedObject(ObjectType::Ride, rideSelection.EntryIndex)); + return obj == nullptr ? ImageIndexUndefined : obj->GetPreviewImage(rideSelection.Type); +} + /** * * rct2: 0x006B6ABF @@ -808,7 +815,6 @@ static void WindowNewRideScrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int3 RideSelection* listItem = _windowNewRideListItems; while (listItem->Type != RIDE_TYPE_NULL || listItem->EntryIndex != OBJECT_ENTRY_INDEX_NULL) { - rct_ride_entry* rideEntry; // Draw flat button rectangle int32_t flags = 0; if (w->new_ride.SelectedRide == *listItem) @@ -818,18 +824,9 @@ static void WindowNewRideScrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int3 dpi, { coords, coords + ScreenCoordsXY{ 115, 115 } }, w->colours[1], INSET_RECT_FLAG_FILL_MID_LIGHT | flags); // Draw ride image with feathered border - rideEntry = get_ride_entry(listItem->EntryIndex); - int32_t imageId = rideEntry->images_offset; - - for (size_t i = 0; i < RCT2::ObjectLimits::MaxRideTypesPerRideEntry; i++) - { - if (rideEntry->ride_type[i] == listItem->Type) - break; - - imageId++; - } - - gfx_draw_sprite_raw_masked(dpi, coords + ScreenCoordsXY{ 2, 2 }, SPR_NEW_RIDE_MASK, imageId); + auto mask = ImageId(SPR_NEW_RIDE_MASK); + auto rideImage = ImageId(GetRideImage(*listItem)); + gfx_draw_sprite_raw_masked(dpi, coords + ScreenCoordsXY{ 2, 2 }, mask, rideImage); // Next position coords.x += 116; diff --git a/src/openrct2/drawing/Drawing.Sprite.cpp b/src/openrct2/drawing/Drawing.Sprite.cpp index 3de578058d..cbd8b0e6cd 100644 --- a/src/openrct2/drawing/Drawing.Sprite.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.cpp @@ -596,11 +596,11 @@ void FASTCALL gfx_sprite_to_buffer(rct_drawpixelinfo& dpi, const DrawSpriteArgs& * rct2: 0x00681DE2 */ void FASTCALL gfx_draw_sprite_raw_masked_software( - rct_drawpixelinfo* dpi, const ScreenCoordsXY& scrCoords, int32_t maskImage, int32_t colourImage) + rct_drawpixelinfo* dpi, const ScreenCoordsXY& scrCoords, ImageId maskImage, ImageId colourImage) { int32_t left, top, right, bottom, width, height; - auto imgMask = gfx_get_g1_element(maskImage & 0x7FFFF); - auto imgColour = gfx_get_g1_element(colourImage & 0x7FFFF); + auto imgMask = gfx_get_g1_element(maskImage); + auto imgColour = gfx_get_g1_element(colourImage); if (imgMask == nullptr || imgColour == nullptr) { return; @@ -609,7 +609,7 @@ void FASTCALL gfx_draw_sprite_raw_masked_software( // Only BMP format is supported for masking if (!(imgMask->flags & G1_FLAG_BMP) || !(imgColour->flags & G1_FLAG_BMP)) { - gfx_draw_sprite_software(dpi, ImageId::FromUInt32(colourImage), scrCoords); + gfx_draw_sprite_software(dpi, colourImage, scrCoords); return; } @@ -654,12 +654,12 @@ const rct_g1_element* gfx_get_g1_element(ImageId imageId) return gfx_get_g1_element(imageId.GetIndex()); } -const rct_g1_element* gfx_get_g1_element(int32_t image_id) +const rct_g1_element* gfx_get_g1_element(ImageIndex image_id) { openrct2_assert(!gOpenRCT2NoGraphics, "gfx_get_g1_element called on headless instance"); auto offset = static_cast(image_id); - if (offset == 0x7FFFF) + if (offset == 0x7FFFF || offset == ImageIndexUndefined) { return nullptr; } @@ -718,7 +718,7 @@ const rct_g1_element* gfx_get_g1_element(int32_t image_id) return nullptr; } -void gfx_set_g1_element(int32_t imageId, const rct_g1_element* g1) +void gfx_set_g1_element(ImageIndex imageId, const rct_g1_element* g1) { bool isTemp = imageId == SPR_TEMP; bool isValid = (imageId >= SPR_IMAGE_LIST_BEGIN && imageId < SPR_IMAGE_LIST_END) @@ -740,7 +740,7 @@ void gfx_set_g1_element(int32_t imageId, const rct_g1_element* g1) { if (imageId < SPR_RCTC_G1_END) { - if (imageId < static_cast(_g1.elements.size())) + if (imageId < static_cast(_g1.elements.size())) { _g1.elements[imageId] = *g1; } diff --git a/src/openrct2/drawing/Drawing.h b/src/openrct2/drawing/Drawing.h index 940aa7a8c3..89f4f43cba 100644 --- a/src/openrct2/drawing/Drawing.h +++ b/src/openrct2/drawing/Drawing.h @@ -14,6 +14,7 @@ #include "../interface/ZoomLevel.h" #include "../world/Location.hpp" #include "Font.h" +#include "ImageId.hpp" #include "Text.h" #include @@ -201,6 +202,7 @@ enum class FilterPaletteID : int32_t Palette34 = 34, + Palette44 = 44, // Construction marker Palette45 = 45, // Decolourise + lighten Palette46 = 46, @@ -317,188 +319,6 @@ struct rct_size16 int16_t height; }; -enum class ImageCatalogue -{ - UNKNOWN, - G1, - G2, - CSG, - OBJECT, - TEMPORARY, -}; - -/** - * Represents a specific image from a catalogue such as G1, G2, CSG etc. with remap - * colours and flags. - * - * This is currently all stored as a single 32-bit integer, but will allow easy - * extension to 64-bits or higher so that more images can be used. - */ -struct ImageId -{ -private: - // clang-format off - static constexpr uint32_t MASK_INDEX = 0b00000000000001111111111111111111; - static constexpr uint32_t MASK_REMAP = 0b00000111111110000000000000000000; - static constexpr uint32_t MASK_PRIMARY = 0b00000000111110000000000000000000; - static constexpr uint32_t MASK_SECONDARY = 0b00011111000000000000000000000000; - static constexpr uint32_t FLAG_PRIMARY = 0b00100000000000000000000000000000; - static constexpr uint32_t FLAG_BLEND = 0b01000000000000000000000000000000; - static constexpr uint32_t FLAG_SECONDARY = 0b10000000000000000000000000000000; - static constexpr uint32_t SHIFT_REMAP = 19; - static constexpr uint32_t SHIFT_PRIMARY = 19; - static constexpr uint32_t SHIFT_SECONDARY = 24; - static constexpr uint32_t INDEX_UNDEFINED = 0b00000000000001111111111111111111; - static constexpr uint32_t VALUE_UNDEFINED = INDEX_UNDEFINED; - // clang-format on - - uint32_t _value = VALUE_UNDEFINED; - uint8_t _tertiary = 0; - -public: - static ImageId FromUInt32(uint32_t value) - { - ImageId result; - result._value = value; - return result; - } - - static ImageId FromUInt32(uint32_t value, uint32_t tertiary) - { - ImageId result; - result._value = value; - result._tertiary = tertiary & 0xFF; - return result; - } - - ImageId() = default; - - explicit constexpr ImageId(uint32_t index) - : _value(index & MASK_INDEX) - { - } - - constexpr ImageId(uint32_t index, uint8_t primaryColourOrPalette) - : ImageId(ImageId(index).WithPrimary(primaryColourOrPalette)) - { - } - - constexpr ImageId(uint32_t index, colour_t primaryColour, colour_t secondaryColour) - : ImageId(ImageId(index).WithPrimary(primaryColour).WithSecondary(secondaryColour)) - { - } - - constexpr ImageId(uint32_t index, colour_t primaryColour, colour_t secondaryColour, colour_t tertiaryColour) - : ImageId(ImageId(index).WithPrimary(primaryColour).WithSecondary(secondaryColour).WithTertiary(tertiaryColour)) - { - } - - uint32_t ToUInt32() const - { - return _value; - } - - bool HasValue() const - { - return GetIndex() != INDEX_UNDEFINED; - } - - bool HasPrimary() const - { - return (_value & FLAG_PRIMARY) || (_value & FLAG_SECONDARY); - } - - bool HasSecondary() const - { - return _value & FLAG_SECONDARY; - } - - bool HasTertiary() const - { - return !(_value & FLAG_PRIMARY) && (_value & FLAG_SECONDARY); - } - - bool IsRemap() const - { - return (_value & FLAG_PRIMARY) && !(_value & FLAG_SECONDARY); - } - - bool IsBlended() const - { - return _value & FLAG_BLEND; - } - - uint32_t GetIndex() const - { - return _value & MASK_INDEX; - } - - uint8_t GetRemap() const - { - return (_value & MASK_REMAP) >> SHIFT_REMAP; - } - - colour_t GetPrimary() const - { - return (_value & MASK_PRIMARY) >> SHIFT_PRIMARY; - } - - colour_t GetSecondary() const - { - return (_value & MASK_SECONDARY) >> SHIFT_SECONDARY; - } - - colour_t GetTertiary() const - { - return _tertiary; - } - - ImageCatalogue GetCatalogue() const; - - constexpr ImageId WithIndex(uint32_t index) - { - ImageId result = *this; - result._value = (_value & ~MASK_INDEX) | (index & MASK_INDEX); - return result; - } - - constexpr ImageId WithRemap(uint8_t paletteId) - { - ImageId result = *this; - result._value = (_value & ~MASK_REMAP) | ((paletteId << SHIFT_REMAP) & MASK_REMAP) | FLAG_PRIMARY; - return result; - } - - constexpr ImageId WithPrimary(colour_t colour) - { - ImageId result = *this; - result._value = (_value & ~MASK_PRIMARY) | ((colour << SHIFT_PRIMARY) & MASK_PRIMARY) | FLAG_PRIMARY; - return result; - } - - constexpr ImageId WithSecondary(colour_t colour) - { - ImageId result = *this; - result._value = (_value & ~MASK_SECONDARY) | ((colour << SHIFT_SECONDARY) & MASK_SECONDARY) | FLAG_SECONDARY; - return result; - } - - constexpr ImageId WithTertiary(colour_t tertiary) - { - ImageId result = *this; - result._value &= ~FLAG_PRIMARY; - if (!(_value & FLAG_SECONDARY)) - { - // Tertiary implies primary and secondary, so if colour was remap (8-bit primary) then - // we need to zero the secondary colour. - result._value &= ~MASK_SECONDARY; - result._value |= FLAG_SECONDARY; - } - result._tertiary = tertiary; - return result; - } -}; - /** * Represents an 8-bit indexed map that maps from one palette index to another. */ @@ -702,8 +522,8 @@ void gfx_unload_g1(); void gfx_unload_g2(); void gfx_unload_csg(); const rct_g1_element* gfx_get_g1_element(ImageId imageId); -const rct_g1_element* gfx_get_g1_element(int32_t image_id); -void gfx_set_g1_element(int32_t imageId, const rct_g1_element* g1); +const rct_g1_element* gfx_get_g1_element(ImageIndex image_id); +void gfx_set_g1_element(ImageIndex imageId, const rct_g1_element* g1); bool is_csg_loaded(); uint32_t gfx_object_allocate_images(const rct_g1_element* images, uint32_t count); void gfx_object_free_images(uint32_t baseImageId, uint32_t count); @@ -717,15 +537,14 @@ void FASTCALL gfx_draw_sprite(rct_drawpixelinfo* dpi, ImageId image_id, const Sc void FASTCALL gfx_draw_sprite(rct_drawpixelinfo* dpi, int32_t image_id, const ScreenCoordsXY& coords, uint32_t tertiary_colour); void FASTCALL gfx_draw_glyph(rct_drawpixelinfo* dpi, int32_t image_id, const ScreenCoordsXY& coords, const PaletteMap& paletteMap); -void FASTCALL - gfx_draw_sprite_raw_masked(rct_drawpixelinfo* dpi, const ScreenCoordsXY& coords, int32_t maskImage, int32_t colourImage); void FASTCALL gfx_draw_sprite_solid(rct_drawpixelinfo* dpi, int32_t image, const ScreenCoordsXY& coords, uint8_t colour); - +void FASTCALL + gfx_draw_sprite_raw_masked(rct_drawpixelinfo* dpi, const ScreenCoordsXY& coords, ImageId maskImage, ImageId colourImage); void FASTCALL gfx_draw_sprite_software(rct_drawpixelinfo* dpi, ImageId imageId, const ScreenCoordsXY& spriteCoords); void FASTCALL gfx_draw_sprite_palette_set_software( rct_drawpixelinfo* dpi, ImageId imageId, const ScreenCoordsXY& coords, const PaletteMap& paletteMap); void FASTCALL gfx_draw_sprite_raw_masked_software( - rct_drawpixelinfo* dpi, const ScreenCoordsXY& scrCoords, int32_t maskImage, int32_t colourImage); + rct_drawpixelinfo* dpi, const ScreenCoordsXY& scrCoords, ImageId maskImage, ImageId colourImage); // string void gfx_draw_string(rct_drawpixelinfo* dpi, const ScreenCoordsXY& coords, const_utf8string buffer, TextPaint textPaint = {}); diff --git a/src/openrct2/drawing/IDrawingContext.h b/src/openrct2/drawing/IDrawingContext.h index adff81a6d6..59c08dc9e3 100644 --- a/src/openrct2/drawing/IDrawingContext.h +++ b/src/openrct2/drawing/IDrawingContext.h @@ -27,9 +27,9 @@ namespace OpenRCT2::Drawing virtual void FilterRect( rct_drawpixelinfo* dpi, FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) abstract; virtual void DrawLine(rct_drawpixelinfo* dpi, uint32_t colour, const ScreenLine& line) abstract; - virtual void DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) abstract; + virtual void DrawSprite(rct_drawpixelinfo* dpi, ImageId image, int32_t x, int32_t y) abstract; virtual void DrawSpriteRawMasked( - rct_drawpixelinfo* dpi, int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) abstract; + rct_drawpixelinfo* dpi, int32_t x, int32_t y, ImageId maskImage, ImageId colourImage) abstract; virtual void DrawSpriteSolid(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint8_t colour) abstract; virtual void DrawGlyph( rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, const PaletteMap& palette) abstract; diff --git a/src/openrct2/drawing/ImageId.hpp b/src/openrct2/drawing/ImageId.hpp new file mode 100644 index 0000000000..56c2609a80 --- /dev/null +++ b/src/openrct2/drawing/ImageId.hpp @@ -0,0 +1,273 @@ +/***************************************************************************** + * Copyright (c) 2014-2020 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include +#include +#include + +using colour_t = uint8_t; +enum class FilterPaletteID : int32_t; +typedef uint32_t ImageIndex; + +static constexpr ImageIndex ImageIndexUndefined = std::numeric_limits::max(); + +enum class ImageCatalogue +{ + UNKNOWN, + G1, + G2, + CSG, + OBJECT, + TEMPORARY, +}; + +/** + * Represents a specific image from a catalogue such as G1, G2, CSG etc. with remap + * colours and flags. + * + * This is currently all stored as a single 32-bit integer, but will allow easy + * extension to 64-bits or higher so that more images can be used. + */ +struct ImageId +{ +private: + // clang-format off + static constexpr uint32_t MASK_INDEX = 0b00000000000001111111111111111111; + static constexpr uint32_t MASK_REMAP = 0b00000111111110000000000000000000; + static constexpr uint32_t MASK_PRIMARY = 0b00000000111110000000000000000000; + static constexpr uint32_t MASK_SECONDARY = 0b00011111000000000000000000000000; + static constexpr uint32_t FLAG_PRIMARY = 0b00100000000000000000000000000000; + static constexpr uint32_t FLAG_BLEND = 0b01000000000000000000000000000000; + static constexpr uint32_t FLAG_SECONDARY = 0b10000000000000000000000000000000; + static constexpr uint32_t SHIFT_REMAP = 19; + static constexpr uint32_t SHIFT_PRIMARY = 19; + static constexpr uint32_t SHIFT_SECONDARY = 24; + static constexpr uint32_t INDEX_UNDEFINED = 0b00000000000001111111111111111111; + static constexpr uint32_t VALUE_UNDEFINED = INDEX_UNDEFINED; + + static constexpr uint8_t NEW_FLAG_PRIMARY = 1; + static constexpr uint8_t NEW_FLAG_BLEND = 2; + static constexpr uint8_t NEW_FLAG_SECONDARY = 4; + // clang-format on + + // NONE = No remap + // PRIMARY = Remap with palette id (first 32 are colour palettes) + // PRIMARY | SECONDARY = Remap with primary and secondary colours + // SECONDARY = Remap with primary, secondary and tertiary colours + + ImageIndex _index = ImageIndexUndefined; + uint8_t _primary = 0; + uint8_t _secondary = 0; + uint8_t _tertiary = 0; + uint8_t _flags = 0; + +public: + static ImageId FromUInt32(uint32_t value) + { + ImageId result; + result._index = value & MASK_INDEX; + if (value & FLAG_SECONDARY) + result._primary = (value & MASK_PRIMARY) >> SHIFT_PRIMARY; + else + result._primary = (value & MASK_REMAP) >> SHIFT_REMAP; + if (value & FLAG_SECONDARY) + result._secondary = (value & MASK_SECONDARY) >> SHIFT_SECONDARY; + if (value & FLAG_PRIMARY) + result._flags |= NEW_FLAG_PRIMARY; + if (value & FLAG_BLEND) + result._flags |= NEW_FLAG_BLEND; + if (value & FLAG_SECONDARY) + result._flags |= NEW_FLAG_SECONDARY; + assert(result.ToUInt32() == value); + return result; + } + + static ImageId FromUInt32(uint32_t value, uint32_t tertiary) + { + if (!(value & FLAG_PRIMARY) && (value & FLAG_SECONDARY)) + { + auto result = ImageId::FromUInt32(value).WithTertiary(tertiary); + assert(result.ToUInt32() == value); + return result; + } + else + { + return ImageId::FromUInt32(value); + } + } + + ImageId() = default; + + explicit constexpr ImageId(ImageIndex index) + : _index(index) + { + } + + constexpr ImageId(uint32_t index, uint8_t primaryColourOrPalette) + : ImageId(ImageId(index).WithPrimary(primaryColourOrPalette)) + { + } + + constexpr ImageId(uint32_t index, colour_t primaryColour, colour_t secondaryColour) + : ImageId(ImageId(index).WithPrimary(primaryColour).WithSecondary(secondaryColour)) + { + } + + constexpr ImageId(uint32_t index, colour_t primaryColour, colour_t secondaryColour, colour_t tertiaryColour) + : ImageId(ImageId(index).WithPrimary(primaryColour).WithSecondary(secondaryColour).WithTertiary(tertiaryColour)) + { + } + + uint32_t ToUInt32() const + { + auto result = (_index & MASK_INDEX); + result |= (_primary << SHIFT_REMAP) & MASK_REMAP; + if (_flags & NEW_FLAG_PRIMARY) + result |= FLAG_PRIMARY; + if (_flags & NEW_FLAG_SECONDARY) + { + result |= (_secondary << SHIFT_SECONDARY) & MASK_SECONDARY; + result |= FLAG_SECONDARY; + } + if (_flags & NEW_FLAG_BLEND) + result |= FLAG_BLEND; + return result; + } + + bool HasValue() const + { + return GetIndex() != INDEX_UNDEFINED; + } + + bool HasPrimary() const + { + return (_flags & NEW_FLAG_PRIMARY) || (_flags & NEW_FLAG_SECONDARY); + } + + bool HasSecondary() const + { + return _flags & NEW_FLAG_SECONDARY; + } + + bool HasTertiary() const + { + return !(_flags & NEW_FLAG_PRIMARY) && (_flags & NEW_FLAG_SECONDARY); + } + + bool IsRemap() const + { + return (_flags & NEW_FLAG_PRIMARY) && !(_flags & NEW_FLAG_SECONDARY); + } + + bool IsBlended() const + { + return _flags & NEW_FLAG_BLEND; + } + + ImageIndex GetIndex() const + { + return _index; + } + + uint8_t GetRemap() const + { + return _primary; + } + + colour_t GetPrimary() const + { + return _primary; + } + + colour_t GetSecondary() const + { + return _secondary; + } + + colour_t GetTertiary() const + { + return _tertiary; + } + + ImageCatalogue GetCatalogue() const; + + constexpr ImageId WithIndex(ImageIndex index) const + { + ImageId result = *this; + result._index = index; + return result; + } + + constexpr ImageId WithIndexOffset(ImageIndex offset) const + { + ImageId result = *this; + result._index += offset; + return result; + } + + constexpr ImageId WithRemap(FilterPaletteID paletteId) const + { + return WithRemap(static_cast(paletteId)); + } + + constexpr ImageId WithRemap(uint8_t paletteId) const + { + ImageId result = *this; + result._primary = paletteId; + result._secondary = 0; + result._tertiary = 0; + result._flags |= NEW_FLAG_PRIMARY; + result._flags &= ~NEW_FLAG_SECONDARY; + return result; + } + + constexpr ImageId WithPrimary(colour_t colour) const + { + ImageId result = *this; + result._primary = colour; + result._flags |= NEW_FLAG_PRIMARY; + return result; + } + + constexpr ImageId WithSecondary(colour_t colour) const + { + ImageId result = *this; + result._secondary = colour; + result._flags |= NEW_FLAG_SECONDARY; + return result; + } + + constexpr ImageId WithTertiary(colour_t tertiary) const + { + ImageId result = *this; + result._tertiary = tertiary; + result._flags &= ~NEW_FLAG_PRIMARY; + result._flags |= NEW_FLAG_SECONDARY; + if (!(_flags & NEW_FLAG_SECONDARY)) + { + // Tertiary implies primary and secondary, so if colour was remap (8-bit primary) then + // we need to zero the secondary colour. + result._secondary = 0; + } + return result; + } + + constexpr ImageId WithBlended(bool value) const + { + ImageId result = *this; + if (value) + result._flags |= NEW_FLAG_BLEND; + else + result._flags &= ~NEW_FLAG_BLEND; + return result; + } +}; +static_assert(sizeof(ImageId) == 8); diff --git a/src/openrct2/drawing/NewDrawing.cpp b/src/openrct2/drawing/NewDrawing.cpp index 01bb3b7bcf..462b62ae5c 100644 --- a/src/openrct2/drawing/NewDrawing.cpp +++ b/src/openrct2/drawing/NewDrawing.cpp @@ -233,18 +233,18 @@ void gfx_draw_dashed_line( } } -void FASTCALL gfx_draw_sprite(rct_drawpixelinfo* dpi, ImageId image_id, const ScreenCoordsXY& coords) +void FASTCALL gfx_draw_sprite(rct_drawpixelinfo* dpi, int32_t image, const ScreenCoordsXY& coords, uint32_t tertiary_colour) { - gfx_draw_sprite(dpi, image_id.ToUInt32(), coords, image_id.GetTertiary()); + gfx_draw_sprite(dpi, ImageId::FromUInt32(image, tertiary_colour), coords); } -void FASTCALL gfx_draw_sprite(rct_drawpixelinfo* dpi, int32_t image, const ScreenCoordsXY& coords, uint32_t tertiary_colour) +void FASTCALL gfx_draw_sprite(rct_drawpixelinfo* dpi, ImageId imageId, const ScreenCoordsXY& coords) { auto drawingEngine = dpi->DrawingEngine; if (drawingEngine != nullptr) { IDrawingContext* dc = drawingEngine->GetDrawingContext(); - dc->DrawSprite(dpi, image, coords.x, coords.y, tertiary_colour); + dc->DrawSprite(dpi, imageId, coords.x, coords.y); } } @@ -259,7 +259,7 @@ void FASTCALL gfx_draw_glyph(rct_drawpixelinfo* dpi, int32_t image, const Screen } void FASTCALL - gfx_draw_sprite_raw_masked(rct_drawpixelinfo* dpi, const ScreenCoordsXY& coords, int32_t maskImage, int32_t colourImage) + gfx_draw_sprite_raw_masked(rct_drawpixelinfo* dpi, const ScreenCoordsXY& coords, ImageId maskImage, ImageId colourImage) { auto drawingEngine = dpi->DrawingEngine; if (drawingEngine != nullptr) diff --git a/src/openrct2/drawing/X8DrawingEngine.cpp b/src/openrct2/drawing/X8DrawingEngine.cpp index f5266c836e..e5890ef1a6 100644 --- a/src/openrct2/drawing/X8DrawingEngine.cpp +++ b/src/openrct2/drawing/X8DrawingEngine.cpp @@ -718,13 +718,12 @@ void X8DrawingContext::DrawLine(rct_drawpixelinfo* dpi, uint32_t colour, const S gfx_draw_line_software(dpi, line, colour); } -void X8DrawingContext::DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) +void X8DrawingContext::DrawSprite(rct_drawpixelinfo* dpi, ImageId imageId, int32_t x, int32_t y) { - gfx_draw_sprite_software(dpi, ImageId::FromUInt32(image, tertiaryColour), { x, y }); + gfx_draw_sprite_software(dpi, imageId, { x, y }); } -void X8DrawingContext::DrawSpriteRawMasked( - rct_drawpixelinfo* dpi, int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) +void X8DrawingContext::DrawSpriteRawMasked(rct_drawpixelinfo* dpi, int32_t x, int32_t y, ImageId maskImage, ImageId colourImage) { gfx_draw_sprite_raw_masked_software(dpi, { x, y }, maskImage, colourImage); } diff --git a/src/openrct2/drawing/X8DrawingEngine.h b/src/openrct2/drawing/X8DrawingEngine.h index d97f1a34ec..b10262381a 100644 --- a/src/openrct2/drawing/X8DrawingEngine.h +++ b/src/openrct2/drawing/X8DrawingEngine.h @@ -145,9 +145,9 @@ namespace OpenRCT2 rct_drawpixelinfo* dpi, FilterPaletteID palette, int32_t left, int32_t top, int32_t right, int32_t bottom) override; void DrawLine(rct_drawpixelinfo* dpi, uint32_t colour, const ScreenLine& line) override; - void DrawSprite(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) override; + void DrawSprite(rct_drawpixelinfo* dpi, ImageId imageId, int32_t x, int32_t y) override; void DrawSpriteRawMasked( - rct_drawpixelinfo* dpi, int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) override; + rct_drawpixelinfo* dpi, int32_t x, int32_t y, ImageId maskImage, ImageId colourImage) override; void DrawSpriteSolid(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, uint8_t colour) override; void DrawGlyph(rct_drawpixelinfo* dpi, uint32_t image, int32_t x, int32_t y, const PaletteMap& paletteMap) override; void DrawBitmap( diff --git a/src/openrct2/interface/Colour.h b/src/openrct2/interface/Colour.h index 39e208e7b9..0ae29c6492 100644 --- a/src/openrct2/interface/Colour.h +++ b/src/openrct2/interface/Colour.h @@ -79,6 +79,7 @@ enum : uint8_t PALETTE_INDEX_21 = 21, // Dark grey (11), White (lighter-11) PALETTE_INDEX_40 = 40, // PALETTE_INDEX_42 = 42, // Light Brown (lighter), Saturated brown (11) + PALETTE_INDEX_44 = 44, // Construction marker PALETTE_INDEX_46 = 46, // Tertiary remap 0 / Yellow (darkest) PALETTE_INDEX_47 = 47, // Tertiary remap 1 / Yellow PALETTE_INDEX_48 = 48, // Tertiary remap 2 / Yellow diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 7529327077..74b022a3ea 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -405,6 +405,17 @@ std::string RideObject::GetCapacity() const return GetString(ObjectStringID::CAPACITY); } +ImageIndex RideObject::GetPreviewImage(ride_type_t type) +{ + auto it = std::find(std::begin(_legacyType.ride_type), std::end(_legacyType.ride_type), type); + if (it == std::end(_legacyType.ride_type)) + { + return ImageIndexUndefined; + } + + return _legacyType.images_offset + std::distance(std::begin(_legacyType.ride_type), it); +} + void RideObject::SetRepositoryItem(ObjectRepositoryItem* item) const { // Find the first non-null ride type, to be used when checking the ride group and determining the category. diff --git a/src/openrct2/object/RideObject.h b/src/openrct2/object/RideObject.h index 55fb71002f..1e8d15cec0 100644 --- a/src/openrct2/object/RideObject.h +++ b/src/openrct2/object/RideObject.h @@ -10,7 +10,9 @@ #pragma once #include "../core/IStream.hpp" +#include "../drawing/ImageId.hpp" #include "../ride/RideEntry.h" +#include "../ride/RideTypes.h" #include "Object.h" #include @@ -38,6 +40,7 @@ public: std::string GetDescription() const; std::string GetCapacity() const; + ImageIndex GetPreviewImage(ride_type_t type); void SetRepositoryItem(ObjectRepositoryItem* item) const override; diff --git a/src/openrct2/paint/Paint.cpp b/src/openrct2/paint/Paint.cpp index ba4db50bb1..676e239666 100644 --- a/src/openrct2/paint/Paint.cpp +++ b/src/openrct2/paint/Paint.cpp @@ -53,9 +53,9 @@ bool gPaintBoundingBoxes; bool gPaintBlockedTiles; static void PaintAttachedPS(rct_drawpixelinfo* dpi, paint_struct* ps, uint32_t viewFlags); -static void PaintPSImageWithBoundingBoxes(rct_drawpixelinfo* dpi, paint_struct* ps, uint32_t imageId, int32_t x, int32_t y); -static void PaintPSImage(rct_drawpixelinfo* dpi, paint_struct* ps, uint32_t imageId, int32_t x, int32_t y); -static uint32_t PaintPSColourifyImage(uint32_t imageId, ViewportInteractionItem spriteType, uint32_t viewFlags); +static void PaintPSImageWithBoundingBoxes(rct_drawpixelinfo* dpi, paint_struct* ps, ImageId imageId, int32_t x, int32_t y); +static void PaintPSImage(rct_drawpixelinfo* dpi, paint_struct* ps, ImageId imageId, int32_t x, int32_t y); +static ImageId PaintPSColourifyImage(ImageId imageId, ViewportInteractionItem spriteType, uint32_t viewFlags); static int32_t RemapPositionToQuadrant(const paint_struct& ps, uint8_t rotation) { @@ -147,10 +147,10 @@ static constexpr CoordsXYZ RotateBoundBoxSize(const CoordsXYZ& bbSize, const uin * Extracted from 0x0098196c, 0x0098197c, 0x0098198c, 0x0098199c */ static paint_struct* CreateNormalPaintStruct( - paint_session* session, const uint32_t image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize, + paint_session* session, ImageId image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize, const CoordsXYZ& boundBoxOffset) { - auto* const g1 = gfx_get_g1_element(image_id & 0x7FFFF); + auto* const g1 = gfx_get_g1_element(image_id); if (g1 == nullptr) { return nullptr; @@ -176,7 +176,7 @@ static paint_struct* CreateNormalPaintStruct( return nullptr; } - ps->image_id = image_id; + ps->image_id = image_id.ToUInt32(); ps->x = imagePos.x; ps->y = imagePos.y; ps->bounds.x_end = rotBoundBoxSize.x + rotBoundBoxOffset.x + session->SpritePosition.x; @@ -501,7 +501,8 @@ static void PaintDrawStruct(paint_session* session, paint_struct* ps) } } - uint32_t imageId = PaintPSColourifyImage(ps->image_id, ps->sprite_type, session->ViewFlags); + auto imageId = PaintPSColourifyImage( + ImageId::FromUInt32(ps->image_id, ps->tertiary_colour), ps->sprite_type, session->ViewFlags); if (gPaintBoundingBoxes && dpi->zoom_level == ZoomLevel{ 0 }) { PaintPSImageWithBoundingBoxes(dpi, ps, imageId, x, y); @@ -549,19 +550,20 @@ static void PaintAttachedPS(rct_drawpixelinfo* dpi, paint_struct* ps, uint32_t v { auto screenCoords = ScreenCoordsXY{ attached_ps->x + ps->x, attached_ps->y + ps->y }; - uint32_t imageId = PaintPSColourifyImage(attached_ps->image_id, ps->sprite_type, viewFlags); + auto imageId = PaintPSColourifyImage( + ImageId::FromUInt32(attached_ps->image_id, ps->tertiary_colour), ps->sprite_type, viewFlags); if (attached_ps->flags & PAINT_STRUCT_FLAG_IS_MASKED) { - gfx_draw_sprite_raw_masked(dpi, screenCoords, imageId, attached_ps->colour_image_id); + gfx_draw_sprite_raw_masked(dpi, screenCoords, imageId, ImageId::FromUInt32(attached_ps->colour_image_id)); } else { - gfx_draw_sprite(dpi, imageId, screenCoords, ps->tertiary_colour); + gfx_draw_sprite(dpi, imageId, screenCoords); } } } -static void PaintPSImageWithBoundingBoxes(rct_drawpixelinfo* dpi, paint_struct* ps, uint32_t imageId, int32_t x, int32_t y) +static void PaintPSImageWithBoundingBoxes(rct_drawpixelinfo* dpi, paint_struct* ps, ImageId imageId, int32_t x, int32_t y) { const uint8_t colour = BoundBoxDebugColours[EnumValue(ps->sprite_type)]; const uint8_t rotation = get_current_rotation(); @@ -647,36 +649,31 @@ static void PaintPSImageWithBoundingBoxes(rct_drawpixelinfo* dpi, paint_struct* gfx_draw_line(dpi, { screenCoordFrontTop, screenCoordRightTop }, colour); } -static void PaintPSImage(rct_drawpixelinfo* dpi, paint_struct* ps, uint32_t imageId, int32_t x, int32_t y) +static void PaintPSImage(rct_drawpixelinfo* dpi, paint_struct* ps, ImageId imageId, int32_t x, int32_t y) { if (ps->flags & PAINT_STRUCT_FLAG_IS_MASKED) { - return gfx_draw_sprite_raw_masked(dpi, { x, y }, imageId, ps->colour_image_id); + return gfx_draw_sprite_raw_masked(dpi, { x, y }, imageId, ImageId::FromUInt32(ps->colour_image_id)); } - gfx_draw_sprite(dpi, imageId, { x, y }, ps->tertiary_colour); + gfx_draw_sprite(dpi, imageId, { x, y }); } -static uint32_t PaintPSColourifyImage(uint32_t imageId, ViewportInteractionItem spriteType, uint32_t viewFlags) +static ImageId PaintPSColourifyImage(ImageId imageId, ViewportInteractionItem spriteType, uint32_t viewFlags) { - constexpr uint32_t primaryColour = COLOUR_BRIGHT_YELLOW; - constexpr uint32_t secondaryColour = COLOUR_GREY; - constexpr uint32_t seeThoughFlags = IMAGE_TYPE_TRANSPARENT | (primaryColour << 19) | (secondaryColour << 24); - + auto seeThrough = imageId.WithPrimary(COLOUR_BRIGHT_YELLOW).WithSecondary(COLOUR_GREY).WithBlended(true); if (viewFlags & VIEWPORT_FLAG_SEETHROUGH_RIDES) { if (spriteType == ViewportInteractionItem::Ride) { - imageId &= 0x7FFFF; - imageId |= seeThoughFlags; + return seeThrough; } } if (viewFlags & VIEWPORT_FLAG_UNDERGROUND_INSIDE) { if (spriteType == ViewportInteractionItem::Wall) { - imageId &= 0x7FFFF; - imageId |= seeThoughFlags; + return seeThrough; } } if (viewFlags & VIEWPORT_FLAG_SEETHROUGH_PATHS) @@ -686,9 +683,7 @@ static uint32_t PaintPSColourifyImage(uint32_t imageId, ViewportInteractionItem case ViewportInteractionItem::Footpath: case ViewportInteractionItem::FootpathItem: case ViewportInteractionItem::Banner: - imageId &= 0x7FFFF; - imageId |= seeThoughFlags; - break; + return seeThrough; default: break; } @@ -700,9 +695,7 @@ static uint32_t PaintPSColourifyImage(uint32_t imageId, ViewportInteractionItem case ViewportInteractionItem::Scenery: case ViewportInteractionItem::LargeScenery: case ViewportInteractionItem::Wall: - imageId &= 0x7FFFF; - imageId |= seeThoughFlags; - break; + return seeThrough; default: break; } @@ -735,7 +728,20 @@ void PaintSessionFree([[maybe_unused]] paint_session* session) paint_struct* PaintAddImageAsParent( paint_session* session, uint32_t image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize) { - return PaintAddImageAsParent(session, image_id, offset, boundBoxSize, offset); + return PaintAddImageAsParent(session, ImageId::FromUInt32(image_id), offset, boundBoxSize, offset); +} + +paint_struct* PaintAddImageAsParent( + paint_session* session, uint32_t image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize, + const CoordsXYZ& boundBoxOffset) +{ + return PaintAddImageAsParent(session, ImageId::FromUInt32(image_id), offset, boundBoxSize, boundBoxOffset); +} + +paint_struct* PaintAddImageAsParent( + paint_session* session, ImageId imageId, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize) +{ + return PaintAddImageAsParent(session, imageId, offset, boundBoxSize, offset); } /** @@ -755,7 +761,7 @@ paint_struct* PaintAddImageAsParent( */ // Track Pieces, Shops. paint_struct* PaintAddImageAsParent( - paint_session* session, uint32_t image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize, + paint_session* session, ImageId image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize, const CoordsXYZ& boundBoxOffset) { session->LastPS = nullptr; @@ -790,24 +796,19 @@ paint_struct* PaintAddImageAsParent( * Creates a paint struct but does not allocate to a paint quadrant. Result cannot be ignored! */ [[nodiscard]] paint_struct* PaintAddImageAsOrphan( - paint_session* session, uint32_t image_id, int32_t x_offset, int32_t y_offset, int32_t bound_box_length_x, - int32_t bound_box_length_y, int32_t bound_box_length_z, int32_t z_offset, int32_t bound_box_offset_x, - int32_t bound_box_offset_y, int32_t bound_box_offset_z) + paint_session* session, ImageId imageId, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize, + const CoordsXYZ& boundBoxOffset) { session->LastPS = nullptr; session->LastAttachedPS = nullptr; + return CreateNormalPaintStruct(session, imageId, offset, boundBoxSize, boundBoxOffset); +} - CoordsXYZ offset = { x_offset, y_offset, z_offset }; - CoordsXYZ boundBoxSize = { bound_box_length_x, bound_box_length_y, bound_box_length_z }; - CoordsXYZ boundBoxOffset = { bound_box_offset_x, bound_box_offset_y, bound_box_offset_z }; - - auto* ps = CreateNormalPaintStruct(session, image_id, offset, boundBoxSize, boundBoxOffset); - if (ps == nullptr) - { - return nullptr; - } - - return ps; +paint_struct* PaintAddImageAsChild( + paint_session* session, uint32_t image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxLength, + const CoordsXYZ& boundBoxOffset) +{ + return PaintAddImageAsChild(session, ImageId::FromUInt32(image_id), offset, boundBoxLength, boundBoxOffset); } /** @@ -828,7 +829,7 @@ paint_struct* PaintAddImageAsParent( * If there is no parent paint struct then image is added as a parent */ paint_struct* PaintAddImageAsChild( - paint_session* session, uint32_t image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxLength, + paint_session* session, ImageId image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxLength, const CoordsXYZ& boundBoxOffset) { paint_struct* parentPS = session->LastPS; @@ -900,6 +901,11 @@ bool PaintAttachToPreviousAttach(paint_session* session, uint32_t image_id, int3 * @return (!CF) success */ bool PaintAttachToPreviousPS(paint_session* session, uint32_t image_id, int32_t x, int32_t y) +{ + return PaintAttachToPreviousPS(session, ImageId::FromUInt32(image_id), x, y); +} + +bool PaintAttachToPreviousPS(paint_session* session, ImageId image_id, int32_t x, int32_t y) { auto* masterPs = session->LastPS; if (masterPs == nullptr) @@ -913,7 +919,7 @@ bool PaintAttachToPreviousPS(paint_session* session, uint32_t image_id, int32_t return false; } - ps->image_id = image_id; + ps->image_id = image_id.ToUInt32(); ps->x = x; ps->y = y; ps->flags = 0; diff --git a/src/openrct2/paint/Paint.h b/src/openrct2/paint/Paint.h index 0117d4b2ad..6d03b1971b 100644 --- a/src/openrct2/paint/Paint.h +++ b/src/openrct2/paint/Paint.h @@ -289,10 +289,14 @@ paint_struct* PaintAddImageAsParent( paint_struct* PaintAddImageAsParent( paint_session* session, uint32_t image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize, const CoordsXYZ& boundBoxOffset); +paint_struct* PaintAddImageAsParent( + paint_session* session, ImageId imageId, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize); +paint_struct* PaintAddImageAsParent( + paint_session* session, ImageId image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize, + const CoordsXYZ& boundBoxOffset); [[nodiscard]] paint_struct* PaintAddImageAsOrphan( - paint_session* session, uint32_t image_id, int32_t x_offset, int32_t y_offset, int32_t bound_box_length_x, - int32_t bound_box_length_y, int32_t bound_box_length_z, int32_t z_offset, int32_t bound_box_offset_x, - int32_t bound_box_offset_y, int32_t bound_box_offset_z); + paint_session* session, ImageId image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize, + const CoordsXYZ& boundBoxOffset); paint_struct* PaintAddImageAsChild( paint_session* session, uint32_t image_id, int32_t x_offset, int32_t y_offset, int32_t bound_box_length_x, int32_t bound_box_length_y, int32_t bound_box_length_z, int32_t z_offset, int32_t bound_box_offset_x, @@ -300,6 +304,9 @@ paint_struct* PaintAddImageAsChild( paint_struct* PaintAddImageAsChild( paint_session* session, uint32_t image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxLength, const CoordsXYZ& boundBoxOffset); +paint_struct* PaintAddImageAsChild( + paint_session* session, ImageId image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxLength, + const CoordsXYZ& boundBoxOffset); paint_struct* PaintAddImageAsParentRotated( paint_session* session, uint8_t direction, uint32_t image_id, int32_t x_offset, int32_t y_offset, @@ -325,6 +332,7 @@ paint_struct* PaintAddImageAsParentRotated( void paint_util_push_tunnel_rotated(paint_session* session, uint8_t direction, uint16_t height, uint8_t type); bool PaintAttachToPreviousAttach(paint_session* session, uint32_t image_id, int32_t x, int32_t y); +bool PaintAttachToPreviousPS(paint_session* session, ImageId image_id, int32_t x, int32_t y); bool PaintAttachToPreviousPS(paint_session* session, uint32_t image_id, int32_t x, int32_t y); void PaintFloatingMoneyEffect( paint_session* session, money64 amount, rct_string_id string_id, int32_t y, int32_t z, int8_t y_offsets[], int32_t offset_x, diff --git a/src/openrct2/paint/Supports.cpp b/src/openrct2/paint/Supports.cpp index d8b20b2c45..1cda6df9a1 100644 --- a/src/openrct2/paint/Supports.cpp +++ b/src/openrct2/paint/Supports.cpp @@ -595,8 +595,8 @@ bool wooden_a_supports_paint_setup( { hasSupports = true; paint_struct* ps = PaintAddImageAsOrphan( - session, imageId, 0, 0, bBox.length.x, bBox.length.y, bBox.length.z, z, bBox.offset.x, bBox.offset.y, - bBox.offset.z + z); + session, ImageId::FromUInt32(imageId), { 0, 0, z }, bBox.length, + { bBox.offset.x, bBox.offset.y, bBox.offset.z + z }); if (ps != nullptr) { session->WoodenSupportsPrependTo->children = ps; @@ -770,8 +770,8 @@ bool wooden_b_supports_paint_setup( else { paint_struct* paintStruct = PaintAddImageAsOrphan( - session, imageId | imageColourFlags, 0, 0, boundBox.length.x, boundBox.length.y, boundBox.length.z, - baseHeight, boundBox.offset.x, boundBox.offset.y, boundBox.offset.z + baseHeight); + session, ImageId::FromUInt32(imageId | imageColourFlags), { 0, 0, baseHeight }, boundBox.length, + { boundBox.offset.x, boundBox.offset.y, boundBox.offset.z + baseHeight }); _9E32B1 = true; if (paintStruct != nullptr) { @@ -1292,8 +1292,8 @@ bool path_a_supports_paint_setup( else { paint_struct* paintStruct = PaintAddImageAsOrphan( - session, imageId | imageColourFlags, 0, 0, boundBox.length.y, boundBox.length.x, boundBox.length.z, baseHeight, - boundBox.offset.x, boundBox.offset.y, baseHeight + boundBox.offset.z); + session, ImageId::FromUInt32(imageId | imageColourFlags), { 0, 0, baseHeight }, boundBox.length, + { boundBox.offset.x, boundBox.offset.y, baseHeight + boundBox.offset.z }); hasSupports = true; if (paintStruct != nullptr) {