diff --git a/Source/cursor.cpp b/Source/cursor.cpp index ba2604c1f..35ee4129b 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -28,6 +28,9 @@ #include "track.h" #include "utils/attributes.h" #include "utils/language.h" +#include "utils/sdl_bilinear_scale.hpp" +#include "utils/static_vector.hpp" +#include "utils/surface_to_clx.hpp" #include "utils/utf8.hpp" namespace devilution { @@ -108,6 +111,9 @@ const uint16_t InvItemHeight2[InvItems2Size] = { // clang-format on }; +constexpr size_t NumInvItems = InvItems1Size + InvItems2Size - static_cast(CURSOR_FIRSTITEM); +StaticVector *HalfSizeItemSprites; + } // namespace /** Current highlighted monster */ @@ -153,6 +159,11 @@ ClxSprite GetInvItemSprite(int cursId) return (*pCursCels2)[cursId - InvItems1Size - 1]; } +size_t GetNumInvItems() +{ + return InvItems1Size + InvItems2Size; +} + Size GetInvItemSize(int cursId) { const int i = cursId - 1; @@ -161,6 +172,36 @@ Size GetInvItemSize(int cursId) return { InvItemWidth1[i], InvItemHeight1[i] }; } +ClxSprite GetHalfSizeItemSprite(int cursId) +{ + return (*HalfSizeItemSprites)[cursId][0]; +} + +void CreateHalfSizeItemSprites() +{ + if (HalfSizeItemSprites != nullptr) + return; + HalfSizeItemSprites = new StaticVector; + for (size_t i = 0; i < NumInvItems; ++i) { + const ClxSprite itemSprite = GetInvItemSprite(static_cast(CURSOR_FIRSTITEM) + static_cast(i)); + const OwnedSurface itemSurface(itemSprite.width(), itemSprite.height()); + SDL_FillRect(itemSurface.surface, nullptr, 1); + ClxDraw(itemSurface, { 0, itemSurface.h() }, itemSprite); + + const OwnedSurface halfSurface(itemSurface.w() / 2, itemSurface.h() / 2); + BilinearDownscaleByHalf8(itemSurface.surface, paletteTransparencyLookup, halfSurface.surface, 1); + HalfSizeItemSprites->emplace_back(SurfaceToClx(halfSurface, 1, 1)); + } +} + +void FreeHalfSizeItemSprites() +{ + if (HalfSizeItemSprites != nullptr) { + delete HalfSizeItemSprites; + HalfSizeItemSprites = nullptr; + } +} + void DrawItem(const Item &item, const Surface &out, Point position, ClxSprite clx) { const bool usable = item._iStatFlag; diff --git a/Source/cursor.h b/Source/cursor.h index 14d02f9c3..cf9264f97 100644 --- a/Source/cursor.h +++ b/Source/cursor.h @@ -67,6 +67,10 @@ void DrawItem(const Item &item, const Surface &out, Point position, ClxSprite cl /** Returns the sprite for the given inventory index. */ ClxSprite GetInvItemSprite(int cursId); +ClxSprite GetHalfSizeItemSprite(int cursId); +void CreateHalfSizeItemSprites(); +void FreeHalfSizeItemSprites(); + /** Returns the width and height for an inventory index. */ Size GetInvItemSize(int cursId); diff --git a/Source/stores.cpp b/Source/stores.cpp index d9a13a525..bcc03d639 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -24,10 +24,8 @@ #include "towners.h" #include "utils/format_int.hpp" #include "utils/language.h" -#include "utils/sdl_bilinear_scale.hpp" #include "utils/stdcompat/string_view.hpp" #include "utils/str_cat.hpp" -#include "utils/surface_to_clx.hpp" #include "utils/utf8.hpp" namespace devilution { @@ -2257,6 +2255,9 @@ void SetupTownStores() void FreeStoreMem() { + if (*sgOptions.Graphics.showItemGraphicsInStores) { + FreeHalfSizeItemSprites(); + } stextflag = STORE_NONE; for (STextStruct &entry : stext) { entry.text.clear(); @@ -2287,17 +2288,11 @@ void PrintSString(const Surface &out, int margin, int line, string_view text, Ui const int halfCursWidth = cursWidth / 2; if (*sgOptions.Graphics.showItemGraphicsInStores && cursId >= 0) { - const ClxSprite itemSprite = GetInvItemSprite(static_cast(CURSOR_FIRSTITEM) + cursId); - const OwnedSurface itemSurface(itemSprite.width(), itemSprite.height()); - SDL_FillRect(itemSurface.surface, nullptr, 1); - ClxDraw(itemSurface, { 0, itemSurface.h() }, itemSprite); - - const OwnedSurface halfSurface(itemSurface.w() / 2, itemSurface.h() / 2); - BilinearDownscaleByHalf8(itemSurface.surface, paletteTransparencyLookup, halfSurface.surface, 1); - - const Displacement spriteOffset { (halfCursWidth - halfSurface.w()) / 2, (TextHeight() * 3 + halfSurface.h()) / 2 }; - const OwnedClxSpriteList halfSprite = SurfaceToClx(halfSurface, 1, 1); - ClxDraw(out, rect.position + spriteOffset, halfSprite[0]); + const ClxSprite halfSprite = GetHalfSizeItemSprite(cursId); + ClxDraw(out, + { rect.position.x + (halfCursWidth - halfSprite.width()) / 2, + rect.position.y + (TextHeight() * 3 + halfSprite.height()) / 2 }, + halfSprite); } if (*sgOptions.Graphics.showItemGraphicsInStores && cursIndent) { @@ -2354,6 +2349,9 @@ void ClearSText(int s, int e) void StartStore(talk_id s) { + if (*sgOptions.Graphics.showItemGraphicsInStores) { + CreateHalfSizeItemSprites(); + } sbookflag = false; CloseInventory(); chrflag = false;