diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp index 6ca2a8d397..bfb58b3d0f 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -878,7 +878,7 @@ void OpenGLDrawingContext::DrawSprite(RenderTarget& rt, const ImageId imageId, c if (rt.zoom_level > ZoomLevel{ 0 }) { - if (g1Element->flags & G1_FLAG_HAS_ZOOM_SPRITE) + if (g1Element->flags.has(G1Flag::hasZoomSprite)) { RenderTarget zoomedRT; zoomedRT.bits = rt.bits; @@ -891,7 +891,7 @@ void OpenGLDrawingContext::DrawSprite(RenderTarget& rt, const ImageId imageId, c DrawSprite(zoomedRT, imageId.WithIndex(imageId.GetIndex() - g1Element->zoomedOffset), x >> 1, y >> 1); return; } - if (g1Element->flags & G1_FLAG_NO_ZOOM_DRAW) + if (g1Element->flags.has(G1Flag::noZoomDraw)) { return; } diff --git a/src/openrct2-ui/scripting/CustomImages.cpp b/src/openrct2-ui/scripting/CustomImages.cpp index c736cb146b..83be3269b8 100644 --- a/src/openrct2-ui/scripting/CustomImages.cpp +++ b/src/openrct2-ui/scripting/CustomImages.cpp @@ -155,12 +155,12 @@ namespace OpenRCT2::Scripting obj.Set("width", g1->width); obj.Set("height", g1->height); - obj.Set("hasTransparent", (g1->flags & G1_FLAG_HAS_TRANSPARENCY) != 0); - obj.Set("isRLE", (g1->flags & G1_FLAG_RLE_COMPRESSION) != 0); - obj.Set("isPalette", (g1->flags & G1_FLAG_PALETTE) != 0); - obj.Set("noZoom", (g1->flags & G1_FLAG_NO_ZOOM_DRAW) != 0); + obj.Set("hasTransparent", g1->flags.has(G1Flag::hasTransparency)); + obj.Set("isRLE", g1->flags.has(G1Flag::hasRLECompression)); + obj.Set("isPalette", g1->flags.has(G1Flag::isPalette)); + obj.Set("noZoom", g1->flags.has(G1Flag::noZoomDraw)); - if (g1->flags & G1_FLAG_HAS_ZOOM_SPRITE) + if (g1->flags.has(G1Flag::hasZoomSprite)) { obj.Set("nextZoomId", id - g1->zoomedOffset); } @@ -173,9 +173,9 @@ namespace OpenRCT2::Scripting static const char* GetPixelDataTypeForG1(const G1Element& g1) { - if (g1.flags & G1_FLAG_RLE_COMPRESSION) + if (g1.flags.has(G1Flag::hasRLECompression)) return "rle"; - else if (g1.flags & G1_FLAG_PALETTE) + else if (g1.flags.has(G1Flag::isPalette)) return "palette"; return "raw"; } @@ -405,10 +405,10 @@ namespace OpenRCT2::Scripting el.offset = newData; el.width = pixelData.Width; el.height = pixelData.Height; - el.flags = 0; + el.flags = {}; if (pixelData.Type == PixelDataKind::Rle) { - el.flags |= G1_FLAG_RLE_COMPRESSION; + el.flags.set(G1Flag::hasRLECompression); } GfxSetG1Element(id, &el); DrawingEngineInvalidateImage(id); @@ -441,7 +441,7 @@ namespace OpenRCT2::Scripting auto createNewImage = false; auto g1 = GfxGetG1Element(id); - if (g1 == nullptr || g1->width != size.width || g1->height != size.height || (g1->flags & G1_FLAG_RLE_COMPRESSION)) + if (g1 == nullptr || g1->width != size.width || g1->height != size.height || g1->flags.has(G1Flag::hasRLECompression)) { createNewImage = true; } @@ -478,7 +478,7 @@ namespace OpenRCT2::Scripting newg1.offset = rt.bits; newg1.width = size.width; newg1.height = size.height; - newg1.flags = 0; + newg1.flags = {}; GfxSetG1Element(id, &newg1); } diff --git a/src/openrct2-ui/windows/InstallTrack.cpp b/src/openrct2-ui/windows/InstallTrack.cpp index c968f3deb9..57d43db79b 100644 --- a/src/openrct2-ui/windows/InstallTrack.cpp +++ b/src/openrct2-ui/windows/InstallTrack.cpp @@ -163,7 +163,7 @@ namespace OpenRCT2::Ui::Windows g1temp.offset = _trackDesignPreviewPixels.data() + (_currentTrackPieceDirection * kTrackPreviewImageSize); g1temp.width = 370; g1temp.height = 217; - g1temp.flags = G1_FLAG_HAS_TRANSPARENCY; + g1temp.flags = { G1Flag::hasTransparency }; GfxSetG1Element(SPR_TEMP, &g1temp); DrawingEngineInvalidateImage(SPR_TEMP); GfxDrawSprite(rt, ImageId(SPR_TEMP), screenPos); diff --git a/src/openrct2-ui/windows/TrackList.cpp b/src/openrct2-ui/windows/TrackList.cpp index 4c5691bf24..9783599eae 100644 --- a/src/openrct2-ui/windows/TrackList.cpp +++ b/src/openrct2-ui/windows/TrackList.cpp @@ -511,7 +511,7 @@ namespace OpenRCT2::Ui::Windows g1temp.offset = _trackDesignPreviewPixels.data() + (_currentTrackPieceDirection * kTrackPreviewImageSize); g1temp.width = 370; g1temp.height = 217; - g1temp.flags = G1_FLAG_HAS_TRANSPARENCY; + g1temp.flags = { G1Flag::hasTransparency }; GfxSetG1Element(SPR_TEMP, &g1temp); DrawingEngineInvalidateImage(SPR_TEMP); GfxDrawSprite(rt, ImageId(SPR_TEMP), trackPreview); diff --git a/src/openrct2/command_line/sprite/SpriteCombine.cpp b/src/openrct2/command_line/sprite/SpriteCombine.cpp index 6b51873220..cbbbe17c15 100644 --- a/src/openrct2/command_line/sprite/SpriteCombine.cpp +++ b/src/openrct2/command_line/sprite/SpriteCombine.cpp @@ -45,7 +45,7 @@ namespace OpenRCT2::CommandLine::Sprite for (uint32_t i = 0; i < numEntries; i++) { // RCT1 used zoomed offsets that counted from the beginning of the file, rather than from the current sprite. - if (g1Elements32[i].flags & G1_FLAG_HAS_ZOOM_SPRITE) + if (g1Elements32[i].flags.has(G1Flag::hasZoomSprite)) { g1Elements32[i].zoomed_offset = i - g1Elements32[i].zoomed_offset; } diff --git a/src/openrct2/drawing/Drawing.Sprite.BMP.cpp b/src/openrct2/drawing/Drawing.Sprite.BMP.cpp index 4988fb2970..4bb0a322a1 100644 --- a/src/openrct2/drawing/Drawing.Sprite.BMP.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.BMP.cpp @@ -106,7 +106,7 @@ void FASTCALL GfxBmpSpriteToBuffer(RenderTarget& rt, const DrawSpriteArgs& args) // Used for glass. DrawBMPSprite(rt, args); } - else if (!(args.SourceImage.flags & G1_FLAG_HAS_TRANSPARENCY)) + else if (!args.SourceImage.flags.has(G1Flag::hasTransparency)) { // Copy raw bitmap data to target DrawBMPSprite(rt, args); diff --git a/src/openrct2/drawing/Drawing.Sprite.cpp b/src/openrct2/drawing/Drawing.Sprite.cpp index 71f443ea06..4f5500ad9c 100644 --- a/src/openrct2/drawing/Drawing.Sprite.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.cpp @@ -345,7 +345,7 @@ static void ReadAndConvertGxDat(IStream* stream, size_t count, bool is_rctc, G1E elements[i].yOffset = src.y_offset; elements[i].flags = src.flags; - if (src.flags & G1_FLAG_HAS_ZOOM_SPRITE) + if (src.flags.has(G1Flag::hasZoomSprite)) { elements[i].zoomedOffset = static_cast(i - rctc_to_rct2_index(rctc - src.zoomed_offset)); } @@ -650,7 +650,7 @@ bool GfxLoadCsg() _csg.elements[i].offset += reinterpret_cast(_csg.data.get()); } // RCT1 used zoomed offsets that counted from the beginning of the file, rather than from the current sprite. - if (_csg.elements[i].flags & G1_FLAG_HAS_ZOOM_SPRITE) + if (_csg.elements[i].flags.has(G1Flag::hasZoomSprite)) { _csg.elements[i].zoomedOffset = i - _csg.elements[i].zoomedOffset; } @@ -768,7 +768,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( return; } - if (zoomLevel > ZoomLevel{ 0 } && (g1->flags & G1_FLAG_HAS_ZOOM_SPRITE)) + if (zoomLevel > ZoomLevel{ 0 } && g1->flags.has(G1Flag::hasZoomSprite)) { RenderTarget zoomedRT = rt; zoomedRT.bits = rt.bits; @@ -785,7 +785,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( return; } - if (zoomLevel > ZoomLevel{ 0 } && (g1->flags & G1_FLAG_NO_ZOOM_DRAW)) + if (zoomLevel > ZoomLevel{ 0 } && g1->flags.has(G1Flag::noZoomDraw)) { return; } @@ -820,7 +820,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( const int32_t zoom_mask = zoomLevel > ZoomLevel{ 0 } ? zoomLevel.ApplyTo(0xFFFFFFFF) : 0xFFFFFFFF; - if (zoomLevel > ZoomLevel{ 0 } && g1->flags & G1_FLAG_RLE_COMPRESSION) + if (zoomLevel > ZoomLevel{ 0 } && g1->flags.has(G1Flag::hasRLECompression)) { x -= ~zoom_mask; y -= ~zoom_mask; @@ -834,7 +834,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( // For whatever reason the RLE version does not use // the zoom mask on the y coordinate but does on x. - if (g1->flags & G1_FLAG_RLE_COMPRESSION) + if (g1->flags.has(G1Flag::hasRLECompression)) { dest_start_y -= rt.WorldY(); } @@ -862,7 +862,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( } else { - if ((g1->flags & G1_FLAG_RLE_COMPRESSION) && zoomLevel > ZoomLevel{ 0 }) + if (g1->flags.has(G1Flag::hasRLECompression) && zoomLevel > ZoomLevel{ 0 }) { source_start_y -= dest_start_y & ~zoom_mask; height += dest_start_y & ~zoom_mask; @@ -908,7 +908,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( } else { - if ((g1->flags & G1_FLAG_RLE_COMPRESSION) && zoomLevel > ZoomLevel{ 0 }) + if (g1->flags.has(G1Flag::hasRLECompression) && zoomLevel > ZoomLevel{ 0 }) { source_start_x -= dest_start_x & ~zoom_mask; } @@ -938,11 +938,11 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware( void FASTCALL GfxSpriteToBuffer(RenderTarget& rt, const DrawSpriteArgs& args) { - if (args.SourceImage.flags & G1_FLAG_RLE_COMPRESSION) + if (args.SourceImage.flags.has(G1Flag::hasRLECompression)) { GfxRleSpriteToBuffer(rt, args); } - else if (!(args.SourceImage.flags & G1_FLAG_1)) + else if (!args.SourceImage.flags.has(G1Flag::one)) { GfxBmpSpriteToBuffer(rt, args); } @@ -966,7 +966,7 @@ void FASTCALL GfxDrawSpriteRawMaskedSoftware( } // Must have transparency in order to pass check - if (!(imgMask->flags & G1_FLAG_HAS_TRANSPARENCY) || !(imgColour->flags & G1_FLAG_HAS_TRANSPARENCY)) + if (!imgMask->flags.has(G1Flag::hasTransparency) || !imgColour->flags.has(G1Flag::hasTransparency)) { GfxDrawSpriteSoftware(rt, colourImage, scrCoords); return; @@ -1161,12 +1161,12 @@ bool IsCsgLoaded() size_t G1CalculateDataSize(const G1Element* g1) { - if (g1->flags & G1_FLAG_PALETTE) + if (g1->flags.has(G1Flag::isPalette)) { return g1->numColours * 3; } - if (g1->flags & G1_FLAG_RLE_COMPRESSION) + if (g1->flags.has(G1Flag::hasRLECompression)) { if (g1->offset == nullptr) { diff --git a/src/openrct2/drawing/Drawing.h b/src/openrct2/drawing/Drawing.h index f6a26fd07c..a5cbd8b658 100644 --- a/src/openrct2/drawing/Drawing.h +++ b/src/openrct2/drawing/Drawing.h @@ -10,6 +10,7 @@ #pragma once #include "../core/CallingConventions.h" +#include "../core/FlagHolder.hpp" #include "../core/StringTypes.h" #include "../interface/Colour.h" #include "../interface/ZoomLevel.h" @@ -45,23 +46,34 @@ namespace OpenRCT2::Drawing struct IDrawingEngine; } +enum class G1Flag : uint8_t +{ + hasTransparency, // Image data contains transparent pixels (0XFF) which will not be rendered + one, + hasRLECompression, // Image data is encoded using RCT2's form of run length encoding + isPalette, // Image data is a sequence of palette entries R8G8B8 + hasZoomSprite, // Use a different sprite for higher zoom levels + noZoomDraw, // Does not get drawn at higher zoom levels (only zoom 0) +}; +using G1Flags = FlagHolder; + struct G1Element { uint8_t* offset = nullptr; // 0x00 union { int16_t width = 0; // 0x04 - int16_t numColours; // If G1_FLAG_PALETTE is set + int16_t numColours; // If G1Flag::isPalette is set }; int16_t height = 0; // 0x06 union { int16_t xOffset = 0; // 0x08 - int16_t startIndex; // If G1_FLAG_PALETTE is set + int16_t startIndex; // If G1Flag::isPalette is set }; - int16_t yOffset = 0; // 0x0A - uint16_t flags = 0; // 0x0C - int32_t zoomedOffset = 0; // 0x0E + int16_t yOffset = 0; // 0x0A + G1Flags flags = {}; // 0x0C + int32_t zoomedOffset = 0; // 0x0E }; #pragma pack(push, 1) @@ -87,21 +99,11 @@ struct RCTG1Element int16_t height; // 0x06 int16_t x_offset; // 0x08 int16_t y_offset; // 0x0A - uint16_t flags; // 0x0C + G1Flags flags; // 0x0C uint16_t zoomed_offset; // 0x0E }; static_assert(sizeof(RCTG1Element) == 0x10); -enum -{ - G1_FLAG_HAS_TRANSPARENCY = (1 << 0), // Image data contains transparent pixels (0XFF) which will not be rendered - G1_FLAG_1 = (1 << 1), - G1_FLAG_RLE_COMPRESSION = (1 << 2), // Image data is encoded using RCT2's form of run length encoding - G1_FLAG_PALETTE = (1 << 3), // Image data is a sequence of palette entries R8G8B8 - G1_FLAG_HAS_ZOOM_SPRITE = (1 << 4), // Use a different sprite for higher zoom levels - G1_FLAG_NO_ZOOM_DRAW = (1 << 5), // Does not get drawn at higher zoom levels (only zoom 0) -}; - using DrawBlendOp = uint8_t; constexpr DrawBlendOp kBlendNone = 0; diff --git a/src/openrct2/drawing/ImageImporter.cpp b/src/openrct2/drawing/ImageImporter.cpp index a97690c4bb..717d10ab2a 100644 --- a/src/openrct2/drawing/ImageImporter.cpp +++ b/src/openrct2/drawing/ImageImporter.cpp @@ -45,12 +45,12 @@ namespace OpenRCT2::Drawing G1Element outElement; outElement.width = meta.srcSize.width; outElement.height = meta.srcSize.height; - outElement.flags = isRLE ? G1_FLAG_RLE_COMPRESSION : G1_FLAG_HAS_TRANSPARENCY; + outElement.flags = { isRLE ? G1Flag::hasRLECompression : G1Flag::hasTransparency }; outElement.xOffset = meta.offset.x; outElement.yOffset = meta.offset.y; outElement.zoomedOffset = meta.zoomedOffset; if (HasFlag(meta.importFlags, ImportFlags::NoDrawOnZoom)) - outElement.flags |= G1_FLAG_NO_ZOOM_DRAW; + outElement.flags.set(G1Flag::noZoomDraw); ImageImporter::ImportResult result; result.Element = outElement; diff --git a/src/openrct2/drawing/ScrollingText.cpp b/src/openrct2/drawing/ScrollingText.cpp index 0b8d309c99..eda4eaf831 100644 --- a/src/openrct2/drawing/ScrollingText.cpp +++ b/src/openrct2/drawing/ScrollingText.cpp @@ -91,7 +91,7 @@ namespace OpenRCT2::Drawing::ScrollingText g1.offset = _drawScrollTextList[i].bitmap; g1.xOffset = -32; g1.yOffset = 0; - g1.flags = G1_FLAG_HAS_TRANSPARENCY; + g1.flags = { G1Flag::hasTransparency }; g1.width = 64; g1.height = 40; g1.offset[0] = 0xFF; diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index b105ca2b87..4a80ed11c7 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -1498,7 +1498,7 @@ namespace OpenRCT2 uint8_t* index = g1->offset + (y * g1->width) + x; // Needs investigation as it has no consideration for pure BMP maps. - if (!(g1->flags & G1_FLAG_HAS_TRANSPARENCY)) + if (!g1->flags.has(G1Flag::hasTransparency)) { return false; } @@ -1560,16 +1560,16 @@ namespace OpenRCT2 if (rt.zoom_level > ZoomLevel{ 0 }) { - if (g1->flags & G1_FLAG_NO_ZOOM_DRAW) + if (g1->flags.has(G1Flag::noZoomDraw)) { return false; } - while (g1->flags & G1_FLAG_HAS_ZOOM_SPRITE && zoomLevel > ZoomLevel{ 0 }) + while (g1->flags.has(G1Flag::hasZoomSprite) && zoomLevel > ZoomLevel{ 0 }) { imageId = imageId.WithIndex(imageId.GetIndex() - g1->zoomedOffset); g1 = GfxGetG1Element(imageId); - if (g1 == nullptr || g1->flags & G1_FLAG_NO_ZOOM_DRAW) + if (g1 == nullptr || g1->flags.has(G1Flag::noZoomDraw)) { return false; } @@ -1591,12 +1591,12 @@ namespace OpenRCT2 return false; } - if (g1->flags & G1_FLAG_RLE_COMPRESSION) + if (g1->flags.has(G1Flag::hasRLECompression)) { return IsPixelPresentRLE(g1->offset, interactionPoint.x, interactionPoint.y); } - if (!(g1->flags & G1_FLAG_1)) + if (!g1->flags.has(G1Flag::one)) { return IsPixelPresentBMP(imageType, g1, interactionPoint.x, interactionPoint.y, paletteMap); } diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index 3323289cfd..3181e4a3f9 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -51,7 +51,7 @@ namespace OpenRCT2 g1 = orig; g1.offset = new uint8_t[length]; std::memcpy(g1.offset, orig.offset, length); - g1.flags &= ~G1_FLAG_HAS_ZOOM_SPRITE; + g1.flags.unset(G1Flag::hasZoomSprite); } RequiredImage(uint32_t idx, std::function getter) @@ -63,14 +63,14 @@ namespace OpenRCT2 g1 = *orig; g1.offset = new uint8_t[length]; std::memcpy(g1.offset, orig->offset, length); - if ((g1.flags & G1_FLAG_HAS_ZOOM_SPRITE) && g1.zoomedOffset != 0) + if (g1.flags.has(G1Flag::hasZoomSprite) && g1.zoomedOffset != 0) { // Fetch image for next zoom level next_zoom = std::make_unique(static_cast(idx - g1.zoomedOffset), getter); if (!next_zoom->HasData()) { next_zoom = nullptr; - g1.flags &= ~G1_FLAG_HAS_ZOOM_SPRITE; + g1.flags.unset(G1Flag::hasZoomSprite); } } } @@ -471,7 +471,7 @@ namespace OpenRCT2 g1Element.height = stream->ReadValue(); g1Element.xOffset = stream->ReadValue(); g1Element.yOffset = stream->ReadValue(); - g1Element.flags = stream->ReadValue(); + g1Element.flags = stream->ReadValue(); g1Element.zoomedOffset = stream->ReadValue(); newEntries.push_back(std::move(g1Element)); diff --git a/src/openrct2/object/WaterObject.cpp b/src/openrct2/object/WaterObject.cpp index dad717dd6a..5e5c11df79 100644 --- a/src/openrct2/object/WaterObject.cpp +++ b/src/openrct2/object/WaterObject.cpp @@ -125,7 +125,7 @@ namespace OpenRCT2 g1.offset = data.get(); g1.numColours = static_cast(numColours); g1.startIndex = Json::GetNumber(jPalette["index"]); - g1.flags = G1_FLAG_PALETTE; + g1.flags = { G1Flag::isPalette }; auto& imageTable = GetImageTable(); imageTable.AddImage(&g1);