Browse Source

Store graphics: Scale sprites only once

Prepare downscaled sprites once instead of doing it on every frame.

Note that we do this lazily in `StartStore` rather than
`SetupTownStores` because we need the palette blending table to be
available when downscaling.
pull/5704/head
Gleb Mazovetskiy 3 years ago
parent
commit
c5369f4b2b
  1. 41
      Source/cursor.cpp
  2. 4
      Source/cursor.h
  3. 24
      Source/stores.cpp

41
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<size_t>(CURSOR_FIRSTITEM);
StaticVector<OwnedClxSpriteList, NumInvItems> *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<OwnedClxSpriteList, NumInvItems>;
for (size_t i = 0; i < NumInvItems; ++i) {
const ClxSprite itemSprite = GetInvItemSprite(static_cast<int>(CURSOR_FIRSTITEM) + static_cast<int>(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;

4
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);

24
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<int>(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;

Loading…
Cancel
Save