diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e55a645c..3dc625e51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -441,7 +441,6 @@ set(libdevilutionx_SRCS Source/DiabloUI/selok.cpp Source/DiabloUI/selyesno.cpp Source/DiabloUI/support_lines.cpp - Source/DiabloUI/text.cpp Source/DiabloUI/text_draw.cpp Source/DiabloUI/title.cpp Source/DiabloUI/ttf_render_wrapped.cpp diff --git a/Packaging/resources/devilutionx.mpq b/Packaging/resources/devilutionx.mpq index 61d425a17..69091ba96 100644 Binary files a/Packaging/resources/devilutionx.mpq and b/Packaging/resources/devilutionx.mpq differ diff --git a/Source/DiabloUI/art.h b/Source/DiabloUI/art.h index c339001ad..ee233792b 100644 --- a/Source/DiabloUI/art.h +++ b/Source/DiabloUI/art.h @@ -36,6 +36,12 @@ struct Art { { surface = nullptr; } + + ~Art() + { + if (surface != nullptr) + Unload(); + } }; void LoadArt(const char *pszFile, Art *art, int frames = 1, SDL_Color *pPalette = nullptr, const std::array *colorMapping = nullptr); diff --git a/Source/DiabloUI/art_draw.cpp b/Source/DiabloUI/art_draw.cpp index 7559792e8..fcc0913fb 100644 --- a/Source/DiabloUI/art_draw.cpp +++ b/Source/DiabloUI/art_draw.cpp @@ -3,9 +3,27 @@ #include "DiabloUI/diabloui.h" #include "utils/display.h" #include "utils/sdl_compat.h" +#include "palette.h" namespace devilution { +void UpdatePalette(Art *art, const SDL_Surface *output) +{ + if (art->surface->format->BitsPerPixel != 8) + return; + + if (art->palette_version == pal_surface_palette_version) + return; + + if (output == nullptr || output->format->BitsPerPixel != 8) + output = pal_surface; + + if (SDLC_SetSurfaceColors(art->surface.get(), output->format->palette) <= -1) + ErrSdl(); + + art->palette_version = pal_surface_palette_version; +} + void DrawArt(Point screenPosition, Art *art, int nFrame, Uint16 srcW, Uint16 srcH) { if (screenPosition.y >= gnScreenHeight || screenPosition.x >= gnScreenWidth || art->surface == nullptr) @@ -26,11 +44,7 @@ void DrawArt(Point screenPosition, Art *art, int nFrame, Uint16 srcW, Uint16 src SDL_Rect dstRect = MakeSdlRect(screenPosition.x, screenPosition.y, srcRect.w, srcRect.h); ScaleOutputRect(&dstRect); - if (art->surface->format->BitsPerPixel == 8 && art->palette_version != pal_surface_palette_version) { - if (SDLC_SetSurfaceColors(art->surface.get(), pal_surface->format->palette) <= -1) - ErrSdl(); - art->palette_version = pal_surface_palette_version; - } + UpdatePalette(art); if (SDL_BlitSurface(art->surface.get(), &srcRect, DiabloUiSurface(), &dstRect) < 0) ErrSdl(); @@ -51,13 +65,10 @@ void DrawArt(const Surface &out, Point screenPosition, Art *art, int nFrame, Uin srcRect.w = srcW; if (srcH != 0 && srcH < srcRect.h) srcRect.h = srcH; - SDL_Rect dstRect = MakeSdlRect(screenPosition.x, screenPosition.y, srcRect.w, srcRect.h); + out.Clip(&srcRect, &screenPosition); + SDL_Rect dstRect { screenPosition.x + out.region.x, screenPosition.y + out.region.y, 0, 0 }; - if (art->surface->format->BitsPerPixel == 8 && art->palette_version != pal_surface_palette_version) { - if (SDLC_SetSurfaceColors(art->surface.get(), out.surface->format->palette) <= -1) - ErrSdl(); - art->palette_version = pal_surface_palette_version; - } + UpdatePalette(art, out.surface); if (SDL_BlitSurface(art->surface.get(), &srcRect, out.surface, &dstRect) < 0) ErrSdl(); diff --git a/Source/DiabloUI/art_draw.h b/Source/DiabloUI/art_draw.h index daadc84f5..54a9f7051 100644 --- a/Source/DiabloUI/art_draw.h +++ b/Source/DiabloUI/art_draw.h @@ -5,6 +5,8 @@ namespace devilution { +void UpdatePalette(Art *art, const SDL_Surface *output = nullptr); + void DrawArt(Point screenPosition, Art *art, int nFrame = 0, Uint16 srcW = 0, Uint16 srcH = 0); void DrawArt(const Surface &out, Point screenPosition, Art *art, int nFrame = 0, Uint16 srcW = 0, Uint16 srcH = 0); diff --git a/Source/DiabloUI/diabloui.cpp b/Source/DiabloUI/diabloui.cpp index 2294698c0..399268d4a 100644 --- a/Source/DiabloUI/diabloui.cpp +++ b/Source/DiabloUI/diabloui.cpp @@ -12,6 +12,7 @@ #include "controls/controller.h" #include "controls/menu_controls.h" #include "dx.h" +#include "engine/render/text_render.hpp" #include "hwcursor.hpp" #include "palette.h" #include "storm/storm.h" @@ -21,6 +22,7 @@ #include "utils/sdl_wrap.h" #include "utils/stubs.h" #include "utils/utf8.h" +#include "utils/language.h" #ifdef __SWITCH__ // for virtual keyboard on Switch @@ -541,7 +543,15 @@ void UnloadUiGFX() void UiInitialize() { LoadUiGFX(); - LoadArtFonts(); + + LoadFont(GameFont12, ColorSilver, "fonts\\grayui.trn"); + LoadFont(GameFont12, ColorGold, "fonts\\goldui.trn"); + LoadFont(GameFont24, ColorSilver, "fonts\\grayui.trn"); + LoadFont(GameFont24, ColorGold, "fonts\\goldui.trn"); + LoadFont(GameFont30, ColorSilver, "fonts\\grayui.trn"); + LoadFont(GameFont30, ColorGold, "fonts\\goldui.trn"); + LoadFont(GameFont42, ColorGold, "fonts\\goldui.trn"); + if (ArtCursor.surface != nullptr) { if (SDL_ShowCursor(SDL_DISABLE) <= -1) { ErrSdl(); @@ -552,7 +562,7 @@ void UiInitialize() void UiDestroy() { UnloadTtfFont(); - UnloadArtFonts(); + UnloadFonts(); UnloadUiGFX(); } @@ -726,7 +736,10 @@ void Render(UiText *uiText) void Render(const UiArtText *uiArtText) { - DrawArtStr(uiArtText->text(), uiArtText->m_rect, uiArtText->m_iFlags); + Rectangle rect { { uiArtText->m_rect.x, uiArtText->m_rect.y }, { uiArtText->m_rect.w, uiArtText->m_rect.h } }; + + const Surface &out = Surface(DiabloUiSurface()); + DrawString(out, uiArtText->text(), rect, uiArtText->m_iFlags, uiArtText->spacing(), uiArtText->lineHeight()); } void Render(const UiImage *uiImage) @@ -745,17 +758,24 @@ void Render(const UiImage *uiImage) void Render(const UiArtTextButton *uiButton) { - DrawArtStr(uiButton->m_text, uiButton->m_rect, uiButton->m_iFlags); + Rectangle rect { { uiButton->m_rect.x, uiButton->m_rect.y }, { uiButton->m_rect.w, uiButton->m_rect.h } }; + + const Surface &out = Surface(DiabloUiSurface()); + DrawString(out, uiButton->m_text, rect, uiButton->m_iFlags); } void Render(const UiList *uiList) { + const Surface &out = Surface(DiabloUiSurface()); + for (std::size_t i = 0; i < uiList->m_vecItems.size(); ++i) { SDL_Rect rect = uiList->itemRect(i); const UiListItem *item = uiList->GetItem(i); if (i + (ListOffset == nullptr ? 0 : *ListOffset) == SelectedItem) DrawSelector(rect); - DrawArtStr(item->m_text, rect, uiList->m_iFlags); + + Rectangle rectangle { { rect.x, rect.y }, { rect.w, rect.h } }; + DrawString(out, item->m_text, rectangle, uiList->m_iFlags, uiList->spacing()); } } @@ -794,11 +814,11 @@ void Render(const UiScrollbar *uiSb) void Render(const UiEdit *uiEdit) { DrawSelector(uiEdit->m_rect); - SDL_Rect rect = uiEdit->m_rect; - rect.x += 43; - rect.y += 1; - rect.w -= 86; - DrawArtStr(uiEdit->m_value, rect, uiEdit->m_iFlags, /*drawTextCursor=*/true); + + Rectangle rect { { uiEdit->m_rect.x + 43, uiEdit->m_rect.y + 1 }, { uiEdit->m_rect.w - 86, uiEdit->m_rect.h } }; + + const Surface &out = Surface(DiabloUiSurface()); + DrawString(out, uiEdit->m_value, rect, uiEdit->m_iFlags | UiFlags::TextCursor); } void RenderItem(UiItemBase *item) diff --git a/Source/DiabloUI/fonts.cpp b/Source/DiabloUI/fonts.cpp index 88dbc324c..7d55aa437 100644 --- a/Source/DiabloUI/fonts.cpp +++ b/Source/DiabloUI/fonts.cpp @@ -9,50 +9,9 @@ namespace devilution { TTF_Font *font = nullptr; -std::unique_ptr FontTables[4]; -Art ArtFonts[4][2]; /** This is so we know ttf has been init when we get to the diablo_deinit() function */ bool was_fonts_init = false; -namespace { - -void LoadArtFont(const char *pszFile, int size, int color) -{ - LoadMaskedArt(pszFile, &ArtFonts[size][color], 256, 32); -} - -} // namespace - -void LoadArtFonts() -{ - FontTables[AFT_SMALL] = LoadFileInMem("ui_art\\font16.bin"); - FontTables[AFT_MED] = LoadFileInMem("ui_art\\font24.bin"); - FontTables[AFT_BIG] = LoadFileInMem("ui_art\\font30.bin"); - FontTables[AFT_HUGE] = LoadFileInMem("ui_art\\font42.bin"); - LoadArtFont("ui_art\\font16s.pcx", AFT_SMALL, AFC_SILVER); - LoadArtFont("ui_art\\font16g.pcx", AFT_SMALL, AFC_GOLD); - LoadArtFont("ui_art\\font24s.pcx", AFT_MED, AFC_SILVER); - LoadArtFont("ui_art\\font24g.pcx", AFT_MED, AFC_GOLD); - LoadArtFont("ui_art\\font30s.pcx", AFT_BIG, AFC_SILVER); - LoadArtFont("ui_art\\font30g.pcx", AFT_BIG, AFC_GOLD); - LoadArtFont("ui_art\\font42g.pcx", AFT_HUGE, AFC_GOLD); -} - -void UnloadArtFonts() -{ - ArtFonts[AFT_SMALL][AFC_SILVER].Unload(); - ArtFonts[AFT_SMALL][AFC_GOLD].Unload(); - ArtFonts[AFT_MED][AFC_SILVER].Unload(); - ArtFonts[AFT_MED][AFC_GOLD].Unload(); - ArtFonts[AFT_BIG][AFC_SILVER].Unload(); - ArtFonts[AFT_BIG][AFC_GOLD].Unload(); - ArtFonts[AFT_HUGE][AFC_GOLD].Unload(); - FontTables[AFT_SMALL] = nullptr; - FontTables[AFT_MED] = nullptr; - FontTables[AFT_BIG] = nullptr; - FontTables[AFT_HUGE] = nullptr; -} - void LoadTtfFont() { if (TTF_WasInit() == 0) { diff --git a/Source/DiabloUI/fonts.h b/Source/DiabloUI/fonts.h index ae6d4e82a..dce98207b 100644 --- a/Source/DiabloUI/fonts.h +++ b/Source/DiabloUI/fonts.h @@ -9,24 +9,7 @@ namespace devilution { -enum _artFontTables : uint8_t { - AFT_SMALL, - AFT_MED, - AFT_BIG, - AFT_HUGE, -}; - -enum _artFontColors : uint8_t { - AFC_SILVER, - AFC_GOLD, -}; - extern TTF_Font *font; -extern std::unique_ptr FontTables[4]; -extern Art ArtFonts[4][2]; - -void LoadArtFonts(); -void UnloadArtFonts(); void LoadTtfFont(); void UnloadTtfFont(); diff --git a/Source/DiabloUI/mainmenu.cpp b/Source/DiabloUI/mainmenu.cpp index 0e075cc11..f6940e051 100644 --- a/Source/DiabloUI/mainmenu.cpp +++ b/Source/DiabloUI/mainmenu.cpp @@ -51,10 +51,10 @@ void MainmenuLoad(const char *name, void (*fnSound)(const char *file)) UiAddBackground(&vecMainMenuDialog); UiAddLogo(&vecMainMenuDialog); - vecMainMenuDialog.push_back(std::make_unique(vecMenuItems, PANEL_LEFT + 64, (UI_OFFSET_Y + 192), 510, 43, UiFlags::FontHuge | UiFlags::ColorGold | UiFlags::AlignCenter)); + vecMainMenuDialog.push_back(std::make_unique(vecMenuItems, PANEL_LEFT + 64, (UI_OFFSET_Y + 192), 510, 43, UiFlags::FontSize42 | UiFlags::ColorGold | UiFlags::AlignCenter, 5)); SDL_Rect rect = { 17, (Sint16)(gnScreenHeight - 36), 605, 21 }; - vecMainMenuDialog.push_back(std::make_unique(name, rect, UiFlags::FontSmall)); + vecMainMenuDialog.push_back(std::make_unique(name, rect, UiFlags::FontSize12 | UiFlags::ColorSilver)); UiInitList(vecMenuItems.size(), nullptr, UiMainMenuSelect, MainmenuEsc, vecMainMenuDialog, true); } diff --git a/Source/DiabloUI/selconn.cpp b/Source/DiabloUI/selconn.cpp index 3a3072549..a8d82bde7 100644 --- a/Source/DiabloUI/selconn.cpp +++ b/Source/DiabloUI/selconn.cpp @@ -1,7 +1,6 @@ #include #include "DiabloUI/diabloui.h" -#include "DiabloUI/text.h" #include "stores.h" #include "storm/storm.h" #include "utils/language.h" @@ -45,36 +44,36 @@ void SelconnLoad() UiAddLogo(&vecSelConnDlg); SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 24), (Sint16)(Sint16)(UI_OFFSET_Y + 161), 590, 35 }; - vecSelConnDlg.push_back(std::make_unique(_("Multi Player Game"), rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelConnDlg.push_back(std::make_unique(_("Multi Player Game"), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 35), (Sint16)(UI_OFFSET_Y + 218), DESCRIPTION_WIDTH, 21 }; - vecSelConnDlg.push_back(std::make_unique(selconn_MaxPlayers, rect2)); + vecSelConnDlg.push_back(std::make_unique(selconn_MaxPlayers, rect2, UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 35), (Sint16)(UI_OFFSET_Y + 256), DESCRIPTION_WIDTH, 21 }; - vecSelConnDlg.push_back(std::make_unique(_("Requirements:"), rect3)); + vecSelConnDlg.push_back(std::make_unique(_("Requirements:"), rect3, UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 35), (Sint16)(UI_OFFSET_Y + 275), DESCRIPTION_WIDTH, 66 }; - vecSelConnDlg.push_back(std::make_unique(selconn_Description, rect4)); + vecSelConnDlg.push_back(std::make_unique(selconn_Description, rect4, UiFlags::FontSize12 | UiFlags::ColorSilver, 1, 16)); SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 30), (Sint16)(UI_OFFSET_Y + 356), 220, 31 }; - vecSelConnDlg.push_back(std::make_unique(_("no gateway needed"), rect5, UiFlags::AlignCenter | UiFlags::FontMedium)); + vecSelConnDlg.push_back(std::make_unique(_("no gateway needed"), rect5, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorSilver, 0)); SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 35), (Sint16)(UI_OFFSET_Y + 393), DESCRIPTION_WIDTH, 21 }; - vecSelConnDlg.push_back(std::make_unique(selconn_Gateway, rect6, UiFlags::AlignCenter)); + vecSelConnDlg.push_back(std::make_unique(selconn_Gateway, rect6, UiFlags::AlignCenter | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect7 = { (Sint16)(PANEL_LEFT + 300), (Sint16)(UI_OFFSET_Y + 211), 295, 33 }; - vecSelConnDlg.push_back(std::make_unique(_("Select Connection"), rect7, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelConnDlg.push_back(std::make_unique(_("Select Connection"), rect7, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect8 = { (Sint16)(PANEL_LEFT + 16), (Sint16)(UI_OFFSET_Y + 427), 250, 35 }; - vecSelConnDlg.push_back(std::make_unique(_("Change Gateway"), nullptr, rect8, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold | UiFlags::ElementHidden)); + vecSelConnDlg.push_back(std::make_unique(_("Change Gateway"), nullptr, rect8, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold | UiFlags::ElementHidden)); vecSelConnDlg.push_back(std::make_unique(vecConnItems, PANEL_LEFT + 305, (UI_OFFSET_Y + 256), 285, 26, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::ColorGold)); SDL_Rect rect9 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelConnDlg.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect9, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelConnDlg.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect9, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); SDL_Rect rect10 = { (Sint16)(PANEL_LEFT + 454), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelConnDlg.push_back(std::make_unique(_("Cancel"), &UiFocusNavigationEsc, rect10, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelConnDlg.push_back(std::make_unique(_("Cancel"), &UiFocusNavigationEsc, rect10, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); UiInitList(vecConnItems.size(), SelconnFocus, SelconnSelect, SelconnEsc, vecSelConnDlg, true); } @@ -113,7 +112,7 @@ void SelconnFocus(int value) } strncpy(selconn_MaxPlayers, fmt::format(_("Players Supported: {:d}"), players).c_str(), sizeof(selconn_MaxPlayers)); - WordWrapArtStr(selconn_Description, DESCRIPTION_WIDTH); + WordWrapString(selconn_Description, DESCRIPTION_WIDTH); } void SelconnSelect(int value) diff --git a/Source/DiabloUI/selgame.cpp b/Source/DiabloUI/selgame.cpp index 5f8659346..0eadfc6ed 100644 --- a/Source/DiabloUI/selgame.cpp +++ b/Source/DiabloUI/selgame.cpp @@ -6,7 +6,6 @@ #include "DiabloUI/dialogs.h" #include "DiabloUI/selhero.h" #include "DiabloUI/selok.h" -#include "DiabloUI/text.h" #include "config.h" #include "control.h" #include "menu.h" @@ -75,27 +74,27 @@ void selgame_GameSelection_Init() UiAddLogo(&vecSelGameDialog); SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 24), (Sint16)(UI_OFFSET_Y + 161), 590, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("Client-Server (TCP)"), rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelGameDialog.push_back(std::make_unique(_("Client-Server (TCP)"), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 35), (Sint16)(UI_OFFSET_Y + 211), 205, 192 }; - vecSelGameDialog.push_back(std::make_unique(_("Description:"), rect2, UiFlags::FontMedium)); + vecSelGameDialog.push_back(std::make_unique(_("Description:"), rect2, UiFlags::FontSize24 | UiFlags::ColorSilver)); SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 35), (Sint16)(UI_OFFSET_Y + 256), DESCRIPTION_WIDTH, 192 }; - vecSelGameDialog.push_back(std::make_unique(selgame_Description, rect3)); + vecSelGameDialog.push_back(std::make_unique(selgame_Description, rect3, UiFlags::FontSize12 | UiFlags::ColorSilver, 1, 16)); SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 300), (Sint16)(UI_OFFSET_Y + 211), 295, 33 }; - vecSelGameDialog.push_back(std::make_unique(_("Select Action"), rect4, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelGameDialog.push_back(std::make_unique(_("Select Action"), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); vecSelGameDlgItems.push_back(std::make_unique(_("Create Game"), 0)); vecSelGameDlgItems.push_back(std::make_unique(_("Join Game"), 1)); - vecSelGameDialog.push_back(std::make_unique(vecSelGameDlgItems, PANEL_LEFT + 305, (UI_OFFSET_Y + 255), 285, 26, UiFlags::AlignCenter | UiFlags::FontMedium | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(vecSelGameDlgItems, PANEL_LEFT + 305, (UI_OFFSET_Y + 255), 285, 26, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorGold)); SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect5, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect5, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 449), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("CANCEL"), &UiFocusNavigationEsc, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("CANCEL"), &UiFocusNavigationEsc, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); UiInitList(vecSelGameDlgItems.size(), selgame_GameSelection_Focus, selgame_GameSelection_Select, selgame_GameSelection_Esc, vecSelGameDialog, true); } @@ -110,7 +109,7 @@ void selgame_GameSelection_Focus(int value) strncpy(selgame_Description, _("Enter an IP or a hostname and join a game already in progress at that address."), sizeof(selgame_Description) - 1); break; } - WordWrapArtStr(selgame_Description, DESCRIPTION_WIDTH); + WordWrapString(selgame_Description, DESCRIPTION_WIDTH); } /** @@ -139,32 +138,32 @@ void selgame_GameSelection_Select(int value) UiAddLogo(&vecSelGameDialog); SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 24), (Sint16)(UI_OFFSET_Y + 161), 590, 35 }; - vecSelGameDialog.push_back(std::make_unique(&title, rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelGameDialog.push_back(std::make_unique(&title, rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 34), (Sint16)(UI_OFFSET_Y + 211), 205, 33 }; - vecSelGameDialog.push_back(std::make_unique(selgame_Label, rect2, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelGameDialog.push_back(std::make_unique(selgame_Label, rect2, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 35), (Sint16)(UI_OFFSET_Y + 256), DESCRIPTION_WIDTH, 192 }; - vecSelGameDialog.push_back(std::make_unique(selgame_Description, rect3)); + vecSelGameDialog.push_back(std::make_unique(selgame_Description, rect3, UiFlags::FontSize12 | UiFlags::ColorSilver, 1, 16)); switch (value) { case 0: { title = _("Create Game"); SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 211), 295, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("Select Difficulty"), rect4, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelGameDialog.push_back(std::make_unique(_("Select Difficulty"), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); vecSelGameDlgItems.push_back(std::make_unique(_("Normal"), DIFF_NORMAL)); vecSelGameDlgItems.push_back(std::make_unique(_("Nightmare"), DIFF_NIGHTMARE)); vecSelGameDlgItems.push_back(std::make_unique(_("Hell"), DIFF_HELL)); - vecSelGameDialog.push_back(std::make_unique(vecSelGameDlgItems, PANEL_LEFT + 300, (UI_OFFSET_Y + 282), 295, 26, UiFlags::AlignCenter | UiFlags::FontMedium | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(vecSelGameDlgItems, PANEL_LEFT + 300, (UI_OFFSET_Y + 282), 295, 26, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorGold)); SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect5, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect5, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 449), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("CANCEL"), &UiFocusNavigationEsc, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("CANCEL"), &UiFocusNavigationEsc, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); UiInitList(vecSelGameDlgItems.size(), selgame_Diff_Focus, selgame_Diff_Select, selgame_Diff_Esc, vecSelGameDialog, true); break; @@ -173,16 +172,16 @@ void selgame_GameSelection_Select(int value) title = _("Join TCP Games"); SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 305), (Sint16)(UI_OFFSET_Y + 211), 285, 33 }; - vecSelGameDialog.push_back(std::make_unique(_("Enter address"), rect4, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelGameDialog.push_back(std::make_unique(_("Enter address"), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 305), (Sint16)(UI_OFFSET_Y + 314), 285, 33 }; - vecSelGameDialog.push_back(std::make_unique(_("Enter address"), selgame_Ip, 128, rect5, UiFlags::FontMedium | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("Enter address"), selgame_Ip, 128, rect5, UiFlags::FontSize24 | UiFlags::ColorGold)); SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); SDL_Rect rect7 = { (Sint16)(PANEL_LEFT + 449), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("CANCEL"), &UiFocusNavigationEsc, rect7, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("CANCEL"), &UiFocusNavigationEsc, rect7, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); UiInitList(0, nullptr, selgame_Password_Init, selgame_GameSelection_Init, vecSelGameDialog); break; @@ -213,7 +212,7 @@ void selgame_Diff_Focus(int value) strncpy(selgame_Description, _("Hell Difficulty\nThe most powerful of the underworld's creatures lurk at the gateway into Hell. Only the most experienced characters should venture in this realm."), sizeof(selgame_Description) - 1); break; } - WordWrapArtStr(selgame_Description, DESCRIPTION_WIDTH); + WordWrapString(selgame_Description, DESCRIPTION_WIDTH); } bool IsDifficultyAllowed(int value) @@ -293,29 +292,29 @@ void selgame_GameSpeedSelection() UiAddLogo(&vecSelGameDialog); SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 24), (Sint16)(UI_OFFSET_Y + 161), 590, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("Create Game"), rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelGameDialog.push_back(std::make_unique(_("Create Game"), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 34), (Sint16)(UI_OFFSET_Y + 211), 205, 33 }; - vecSelGameDialog.push_back(std::make_unique(selgame_Label, rect2, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelGameDialog.push_back(std::make_unique(selgame_Label, rect2, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 35), (Sint16)(UI_OFFSET_Y + 256), DESCRIPTION_WIDTH, 192 }; - vecSelGameDialog.push_back(std::make_unique(selgame_Description, rect3)); + vecSelGameDialog.push_back(std::make_unique(selgame_Description, rect3, UiFlags::FontSize12 | UiFlags::ColorSilver, 1, 16)); SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 211), 295, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("Select Game Speed"), rect4, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelGameDialog.push_back(std::make_unique(_("Select Game Speed"), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); vecSelGameDlgItems.push_back(std::make_unique(_("Normal"), 20)); vecSelGameDlgItems.push_back(std::make_unique(_("Fast"), 30)); vecSelGameDlgItems.push_back(std::make_unique(_("Faster"), 40)); vecSelGameDlgItems.push_back(std::make_unique(_("Fastest"), 50)); - vecSelGameDialog.push_back(std::make_unique(vecSelGameDlgItems, PANEL_LEFT + 300, (UI_OFFSET_Y + 279), 295, 26, UiFlags::AlignCenter | UiFlags::FontMedium | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(vecSelGameDlgItems, PANEL_LEFT + 300, (UI_OFFSET_Y + 279), 295, 26, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorGold)); SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect5, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect5, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 449), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("CANCEL"), &UiFocusNavigationEsc, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("CANCEL"), &UiFocusNavigationEsc, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); UiInitList(vecSelGameDlgItems.size(), selgame_Speed_Focus, selgame_Speed_Select, selgame_Speed_Esc, vecSelGameDialog, true); } @@ -340,7 +339,7 @@ void selgame_Speed_Focus(int value) strncpy(selgame_Description, _("Fastest Speed\nThe minions of the underworld will rush to attack without hesitation. Only a true speed demon should enter at this pace."), sizeof(selgame_Description) - 1); break; } - WordWrapArtStr(selgame_Description, DESCRIPTION_WIDTH); + WordWrapString(selgame_Description, DESCRIPTION_WIDTH); } void selgame_Speed_Esc() @@ -370,25 +369,25 @@ void selgame_Password_Init(int /*value*/) UiAddLogo(&vecSelGameDialog); SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 24), (Sint16)(UI_OFFSET_Y + 161), 590, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("Client-Server (TCP)"), rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelGameDialog.push_back(std::make_unique(_("Client-Server (TCP)"), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 35), (Sint16)(UI_OFFSET_Y + 211), 205, 192 }; - vecSelGameDialog.push_back(std::make_unique(_("Description:"), rect2, UiFlags::FontMedium)); + vecSelGameDialog.push_back(std::make_unique(_("Description:"), rect2, UiFlags::FontSize24 | UiFlags::ColorSilver)); SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 35), (Sint16)(UI_OFFSET_Y + 256), DESCRIPTION_WIDTH, 192 }; - vecSelGameDialog.push_back(std::make_unique(selgame_Description, rect3)); + vecSelGameDialog.push_back(std::make_unique(selgame_Description, rect3, UiFlags::FontSize12 | UiFlags::ColorSilver, 1, 16)); SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 305), (Sint16)(UI_OFFSET_Y + 211), 285, 33 }; - vecSelGameDialog.push_back(std::make_unique(_("Enter Password"), rect4, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelGameDialog.push_back(std::make_unique(_("Enter Password"), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 305), (Sint16)(UI_OFFSET_Y + 314), 285, 33 }; - vecSelGameDialog.push_back(std::make_unique(_("Enter Password"), selgame_Password, 15, rect5, UiFlags::FontMedium | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("Enter Password"), selgame_Password, 15, rect5, UiFlags::FontSize24 | UiFlags::ColorGold)); SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); SDL_Rect rect7 = { (Sint16)(PANEL_LEFT + 449), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelGameDialog.push_back(std::make_unique(_("CANCEL"), &UiFocusNavigationEsc, rect7, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelGameDialog.push_back(std::make_unique(_("CANCEL"), &UiFocusNavigationEsc, rect7, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); UiInitList(0, nullptr, selgame_Password_Select, selgame_Password_Esc, vecSelGameDialog); } diff --git a/Source/DiabloUI/selhero.cpp b/Source/DiabloUI/selhero.cpp index 9c068463d..49ba245a1 100644 --- a/Source/DiabloUI/selhero.cpp +++ b/Source/DiabloUI/selhero.cpp @@ -127,7 +127,7 @@ void SelheroListFocus(int value) { const auto index = static_cast(value); SelheroScrollIntoView(index); - UiFlags baseFlags = UiFlags::AlignCenter | UiFlags::FontBig; + UiFlags baseFlags = UiFlags::AlignCenter | UiFlags::FontSize30; if (selhero_SaveCount != 0 && index < selhero_SaveCount) { memcpy(&selhero_heroInfo, &selhero_heros[index], sizeof(selhero_heroInfo)); SelheroSetStats(); @@ -143,7 +143,7 @@ void SelheroListFocus(int value) strncpy(textStats[3], "--", sizeof(textStats[3]) - 1); strncpy(textStats[4], "--", sizeof(textStats[4]) - 1); strncpy(textStats[5], "--", sizeof(textStats[5]) - 1); - SELLIST_DIALOG_DELETE_BUTTON->m_iFlags = baseFlags | UiFlags::ElementDisabled; + SELLIST_DIALOG_DELETE_BUTTON->m_iFlags = baseFlags | UiFlags::ColorSilver | UiFlags::ElementDisabled; selhero_deleteEnabled = false; } @@ -160,7 +160,7 @@ void SelheroListSelect(int value) vecSelDlgItems.clear(); SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 264), (Sint16)(UI_OFFSET_Y + 211), 320, 33 }; - vecSelDlgItems.push_back(std::make_unique(_("Choose Class"), rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelDlgItems.push_back(std::make_unique(_("Choose Class"), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); vecSelHeroDlgItems.clear(); int itemH = 33; @@ -179,13 +179,13 @@ void SelheroListSelect(int value) if (vecSelHeroDlgItems.size() > 4) itemH = 26; int itemY = 246 + (176 - vecSelHeroDlgItems.size() * itemH) / 2; - vecSelDlgItems.push_back(std::make_unique(vecSelHeroDlgItems, PANEL_LEFT + 264, (UI_OFFSET_Y + itemY), 320, itemH, UiFlags::AlignCenter | UiFlags::FontMedium | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(vecSelHeroDlgItems, PANEL_LEFT + 264, (UI_OFFSET_Y + itemY), 320, itemH, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorGold)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 279), (Sint16)(UI_OFFSET_Y + 429), 140, 35 }; - vecSelDlgItems.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect2, UiFlags::AlignCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect2, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 429), (Sint16)(UI_OFFSET_Y + 429), 140, 35 }; - vecSelDlgItems.push_back(std::make_unique(_("Cancel"), &UiFocusNavigationEsc, rect3, UiFlags::AlignCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(_("Cancel"), &UiFocusNavigationEsc, rect3, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); UiInitList(vecSelHeroDlgItems.size(), SelheroClassSelectorFocus, SelheroClassSelectorSelect, SelheroClassSelectorEsc, vecSelDlgItems, true); memset(&selhero_heroInfo.name, 0, sizeof(selhero_heroInfo.name)); @@ -199,18 +199,18 @@ void SelheroListSelect(int value) vecSelDlgItems.clear(); SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 264), (Sint16)(UI_OFFSET_Y + 211), 320, 33 }; - vecSelDlgItems.push_back(std::make_unique(_("Save File Exists"), rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelDlgItems.push_back(std::make_unique(_("Save File Exists"), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); vecSelHeroDlgItems.clear(); vecSelHeroDlgItems.push_back(std::make_unique(_("Load Game"), 0)); vecSelHeroDlgItems.push_back(std::make_unique(_("New Game"), 1)); - vecSelDlgItems.push_back(std::make_unique(vecSelHeroDlgItems, PANEL_LEFT + 265, (UI_OFFSET_Y + 285), 320, 33, UiFlags::AlignCenter | UiFlags::FontMedium | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(vecSelHeroDlgItems, PANEL_LEFT + 265, (UI_OFFSET_Y + 285), 320, 33, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorGold)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 279), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelDlgItems.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect2, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect2, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 429), (Sint16)(UI_OFFSET_Y + 427), 140, 35 }; - vecSelDlgItems.push_back(std::make_unique(_("Cancel"), &UiFocusNavigationEsc, rect3, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(_("Cancel"), &UiFocusNavigationEsc, rect3, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); UiInitList(vecSelHeroDlgItems.size(), SelheroLoadFocus, SelheroLoadSelect, selhero_List_Init, vecSelDlgItems, true); title = _("Single Player Characters"); @@ -271,16 +271,16 @@ void SelheroClassSelectorSelect(int value) strncpy(selhero_heroInfo.name, SelheroGenerateName(selhero_heroInfo.heroclass), sizeof(selhero_heroInfo.name) - 1); vecSelDlgItems.clear(); SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 264), (Sint16)(UI_OFFSET_Y + 211), 320, 33 }; - vecSelDlgItems.push_back(std::make_unique(_("Enter Name"), rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelDlgItems.push_back(std::make_unique(_("Enter Name"), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 265), (Sint16)(UI_OFFSET_Y + 317), 320, 33 }; - vecSelDlgItems.push_back(std::make_unique(_("Enter Name"), selhero_heroInfo.name, 15, rect2, UiFlags::FontMedium | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(_("Enter Name"), selhero_heroInfo.name, 15, rect2, UiFlags::FontSize24 | UiFlags::ColorGold)); SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 279), (Sint16)(UI_OFFSET_Y + 429), 140, 35 }; - vecSelDlgItems.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect3, UiFlags::AlignCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect3, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 429), (Sint16)(UI_OFFSET_Y + 429), 140, 35 }; - vecSelDlgItems.push_back(std::make_unique(_("Cancel"), &UiFocusNavigationEsc, rect4, UiFlags::AlignCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(_("Cancel"), &UiFocusNavigationEsc, rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); UiInitList(0, nullptr, SelheroNameSelect, SelheroNameEsc, vecSelDlgItems); } @@ -456,7 +456,7 @@ void selhero_Init() vecSelDlgItems.clear(); SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 24), (Sint16)(UI_OFFSET_Y + 161), 590, 35 }; - vecSelHeroDialog.push_back(std::make_unique(&title, rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelHeroDialog.push_back(std::make_unique(&title, rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 30), (Sint16)(UI_OFFSET_Y + 211), 180, 76 }; auto heroImg = std::make_unique(&ArtHero, rect2, UiFlags::None, /*bAnimated=*/false, static_cast(enum_size::value)); @@ -464,38 +464,38 @@ void selhero_Init() vecSelHeroDialog.push_back(std::move(heroImg)); SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 323), 110, 21 }; - vecSelHeroDialog.push_back(std::make_unique(_("Level:"), rect3, UiFlags::AlignRight)); + vecSelHeroDialog.push_back(std::make_unique(_("Level:"), rect3, UiFlags::AlignRight | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 323), 110, 21 }; - vecSelHeroDialog.push_back(std::make_unique(_("Level:"), rect4, UiFlags::AlignRight)); + vecSelHeroDialog.push_back(std::make_unique(_("Level:"), rect4, UiFlags::AlignRight | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 159), (Sint16)(UI_OFFSET_Y + 323), 40, 21 }; - vecSelHeroDialog.push_back(std::make_unique(textStats[0], rect5, UiFlags::AlignCenter)); + vecSelHeroDialog.push_back(std::make_unique(textStats[0], rect5, UiFlags::AlignCenter | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 358), 110, 21 }; - vecSelHeroDialog.push_back(std::make_unique(_("Strength:"), rect6, UiFlags::AlignRight)); + vecSelHeroDialog.push_back(std::make_unique(_("Strength:"), rect6, UiFlags::AlignRight | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect7 = { (Sint16)(PANEL_LEFT + 159), (Sint16)(UI_OFFSET_Y + 358), 40, 21 }; - vecSelHeroDialog.push_back(std::make_unique(textStats[1], rect7, UiFlags::AlignCenter)); + vecSelHeroDialog.push_back(std::make_unique(textStats[1], rect7, UiFlags::AlignCenter | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect8 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 380), 110, 21 }; - vecSelHeroDialog.push_back(std::make_unique(_("Magic:"), rect8, UiFlags::AlignRight)); + vecSelHeroDialog.push_back(std::make_unique(_("Magic:"), rect8, UiFlags::AlignRight | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect9 = { (Sint16)(PANEL_LEFT + 159), (Sint16)(UI_OFFSET_Y + 380), 40, 21 }; - vecSelHeroDialog.push_back(std::make_unique(textStats[2], rect9, UiFlags::AlignCenter)); + vecSelHeroDialog.push_back(std::make_unique(textStats[2], rect9, UiFlags::AlignCenter | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect10 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 401), 110, 21 }; - vecSelHeroDialog.push_back(std::make_unique(_("Dexterity:"), rect10, UiFlags::AlignRight)); + vecSelHeroDialog.push_back(std::make_unique(_("Dexterity:"), rect10, UiFlags::AlignRight | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect11 = { (Sint16)(PANEL_LEFT + 159), (Sint16)(UI_OFFSET_Y + 401), 40, 21 }; - vecSelHeroDialog.push_back(std::make_unique(textStats[3], rect11, UiFlags::AlignCenter)); + vecSelHeroDialog.push_back(std::make_unique(textStats[3], rect11, UiFlags::AlignCenter | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect12 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 422), 110, 21 }; - vecSelHeroDialog.push_back(std::make_unique(_("Vitality:"), rect12, UiFlags::AlignRight)); + vecSelHeroDialog.push_back(std::make_unique(_("Vitality:"), rect12, UiFlags::AlignRight | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect13 = { (Sint16)(PANEL_LEFT + 159), (Sint16)(UI_OFFSET_Y + 422), 40, 21 }; - vecSelHeroDialog.push_back(std::make_unique(textStats[4], rect13, UiFlags::AlignCenter)); + vecSelHeroDialog.push_back(std::make_unique(textStats[4], rect13, UiFlags::AlignCenter | UiFlags::FontSize12 | UiFlags::ColorSilver)); #if _DEBUG SDL_Rect rect14 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 443), 110, 21 }; - vecSelHeroDialog.push_back(std::make_unique(_("Savegame:"), rect14, UiFlags::AlignRight)); + vecSelHeroDialog.push_back(std::make_unique(_("Savegame:"), rect14, UiFlags::AlignRight | UiFlags::FontSize12 | UiFlags::ColorSilver)); SDL_Rect rect15 = { (Sint16)(PANEL_LEFT + 159), (Sint16)(UI_OFFSET_Y + 443), 40, 21 }; - vecSelHeroDialog.push_back(std::make_unique(textStats[5], rect15, UiFlags::AlignCenter)); + vecSelHeroDialog.push_back(std::make_unique(textStats[5], rect15, UiFlags::AlignCenter | UiFlags::FontSize12 | UiFlags::ColorSilver)); #endif } @@ -505,7 +505,7 @@ void selhero_List_Init() vecSelDlgItems.clear(); SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 264), (Sint16)(UI_OFFSET_Y + 211), 320, 33 }; - vecSelDlgItems.push_back(std::make_unique(_("Select Hero"), rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelDlgItems.push_back(std::make_unique(_("Select Hero"), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); vecSelHeroDlgItems.clear(); const size_t numViewportHeroes = std::min(selhero_SaveCount + 1, MaxViewportItems); @@ -514,7 +514,7 @@ void selhero_List_Init() } SelheroUpdateViewportItems(); - vecSelDlgItems.push_back(std::make_unique(vecSelHeroDlgItems, PANEL_LEFT + 265, (UI_OFFSET_Y + 256), 320, 26, UiFlags::AlignCenter | UiFlags::FontMedium | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(vecSelHeroDlgItems, PANEL_LEFT + 265, (UI_OFFSET_Y + 256), 320, 26, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorGold)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 585), (Sint16)(UI_OFFSET_Y + 244), 25, 178 }; auto pinnedScrollBar = std::make_unique(&ArtScrollBarBackground, &ArtScrollBarThumb, &ArtScrollBarArrow, rect2); @@ -522,15 +522,15 @@ void selhero_List_Init() vecSelDlgItems.push_back(std::move(pinnedScrollBar)); SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 239), (Sint16)(UI_OFFSET_Y + 429), 120, 35 }; - vecSelDlgItems.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect3, UiFlags::AlignCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(_("OK"), &UiFocusNavigationSelect, rect3, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 364), (Sint16)(UI_OFFSET_Y + 429), 120, 35 }; - auto setlistDialogDeleteButton = std::make_unique(_("Delete"), &SelheroUiFocusNavigationYesNo, rect4, UiFlags::AlignCenter | UiFlags::FontBig | UiFlags::ElementDisabled); + auto setlistDialogDeleteButton = std::make_unique(_("Delete"), &SelheroUiFocusNavigationYesNo, rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver | UiFlags::ElementDisabled); SELLIST_DIALOG_DELETE_BUTTON = setlistDialogDeleteButton.get(); vecSelDlgItems.push_back(std::move(setlistDialogDeleteButton)); SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 489), (Sint16)(UI_OFFSET_Y + 429), 120, 35 }; - vecSelDlgItems.push_back(std::make_unique(_("Cancel"), &UiFocusNavigationEsc, rect5, UiFlags::AlignCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelDlgItems.push_back(std::make_unique(_("Cancel"), &UiFocusNavigationEsc, rect5, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); UiInitList(selhero_SaveCount + 1, SelheroListFocus, SelheroListSelect, SelheroListEsc, vecSelDlgItems, false, SelheroListDeleteYesNo); UiInitScrollBar(scrollBar, MaxViewportItems, &listOffset); diff --git a/Source/DiabloUI/selok.cpp b/Source/DiabloUI/selok.cpp index bfc62f899..9ba77b89c 100644 --- a/Source/DiabloUI/selok.cpp +++ b/Source/DiabloUI/selok.cpp @@ -1,9 +1,9 @@ #include "DiabloUI/selok.h" #include "DiabloUI/diabloui.h" -#include "DiabloUI/text.h" #include "control.h" #include "utils/language.h" +#include "engine/render/text_render.hpp" namespace devilution { @@ -18,7 +18,7 @@ bool selok_endMenu; std::vector> vecSelOkDialogItems; std::vector> vecSelOkDialog; -#define MESSAGE_WIDTH 280 +#define MESSAGE_WIDTH 400 void selok_Free() { @@ -56,20 +56,20 @@ void UiSelOkDialog(const char *title, const char *body, bool background) if (title != nullptr) { SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 24), (Sint16)(UI_OFFSET_Y + 161), 590, 35 }; - vecSelOkDialog.push_back(std::make_unique(title, rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelOkDialog.push_back(std::make_unique(title, rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 140), (Sint16)(UI_OFFSET_Y + 210), 560, 168 }; - vecSelOkDialog.push_back(std::make_unique(dialogText, rect2, UiFlags::FontMedium)); + vecSelOkDialog.push_back(std::make_unique(dialogText, rect2, UiFlags::FontSize24 | UiFlags::ColorSilver)); } else { SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 140), (Sint16)(UI_OFFSET_Y + 197), 560, 168 }; - vecSelOkDialog.push_back(std::make_unique(dialogText, rect1, UiFlags::FontMedium)); + vecSelOkDialog.push_back(std::make_unique(dialogText, rect1, UiFlags::FontSize24 | UiFlags::ColorSilver)); } vecSelOkDialogItems.push_back(std::make_unique(_("OK"), 0)); - vecSelOkDialog.push_back(std::make_unique(vecSelOkDialogItems, PANEL_LEFT + 230, (UI_OFFSET_Y + 390), 180, 35, UiFlags::AlignCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelOkDialog.push_back(std::make_unique(vecSelOkDialogItems, PANEL_LEFT + 230, (UI_OFFSET_Y + 390), 180, 35, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); strncpy(dialogText, body, sizeof(dialogText) - 1); - WordWrapArtStr(dialogText, MESSAGE_WIDTH); + WordWrapString(dialogText, MESSAGE_WIDTH, GameFont24); UiInitList(0, nullptr, selok_Select, selok_Esc, vecSelOkDialog, false, nullptr); diff --git a/Source/DiabloUI/selyesno.cpp b/Source/DiabloUI/selyesno.cpp index 1f87ed2c2..91b751686 100644 --- a/Source/DiabloUI/selyesno.cpp +++ b/Source/DiabloUI/selyesno.cpp @@ -1,7 +1,6 @@ #include "selyesno.h" #include "DiabloUI/diabloui.h" -#include "DiabloUI/text.h" #include "control.h" #include "utils/language.h" @@ -15,7 +14,7 @@ char selyesno_confirmationMessage[256]; std::vector> vecSelYesNoDialogItems; std::vector> vecSelYesNoDialog; -#define MESSAGE_WIDTH 280 +#define MESSAGE_WIDTH 400 void SelyesnoFree() { @@ -47,17 +46,17 @@ bool UiSelHeroYesNoDialog(const char *title, const char *body) UiAddLogo(&vecSelYesNoDialog); SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 24), (Sint16)(UI_OFFSET_Y + 161), 590, 35 }; - vecSelYesNoDialog.push_back(std::make_unique(title, rect1, UiFlags::AlignCenter | UiFlags::FontBig)); + vecSelYesNoDialog.push_back(std::make_unique(title, rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorSilver, 3)); SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 120), (Sint16)(UI_OFFSET_Y + 236), MESSAGE_WIDTH, 168 }; - vecSelYesNoDialog.push_back(std::make_unique(selyesno_confirmationMessage, rect2, UiFlags::FontMedium)); + vecSelYesNoDialog.push_back(std::make_unique(selyesno_confirmationMessage, rect2, UiFlags::FontSize24 | UiFlags::ColorSilver)); vecSelYesNoDialogItems.push_back(std::make_unique(_("Yes"), 0)); vecSelYesNoDialogItems.push_back(std::make_unique(_("No"), 1)); - vecSelYesNoDialog.push_back(std::make_unique(vecSelYesNoDialogItems, PANEL_LEFT + 230, (UI_OFFSET_Y + 390), 180, 35, UiFlags::AlignCenter | UiFlags::FontBig | UiFlags::ColorGold)); + vecSelYesNoDialog.push_back(std::make_unique(vecSelYesNoDialogItems, PANEL_LEFT + 230, (UI_OFFSET_Y + 390), 180, 35, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorGold)); strncpy(selyesno_confirmationMessage, body, sizeof(selyesno_confirmationMessage) - 1); - WordWrapArtStr(selyesno_confirmationMessage, MESSAGE_WIDTH); + WordWrapString(selyesno_confirmationMessage, MESSAGE_WIDTH, GameFont24); UiInitList(vecSelYesNoDialogItems.size(), nullptr, SelyesnoSelect, SelyesnoEsc, vecSelYesNoDialog, true, nullptr); diff --git a/Source/DiabloUI/text.cpp b/Source/DiabloUI/text.cpp deleted file mode 100644 index 0a5b6b636..000000000 --- a/Source/DiabloUI/text.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "DiabloUI/text.h" - -namespace devilution { - -std::size_t GetArtStrWidth(const char *str, std::size_t size) -{ - int strWidth = 0; - - for (size_t i = 0, n = strlen(str); i < n; i++) { - uint8_t w = FontTables[size][(uint8_t)str[i] + 2]; - strWidth += (w != 0) ? w : FontTables[size][0]; - } - - return strWidth; -} - -void WordWrapArtStr(char *text, std::size_t width, std::size_t size) -{ - const std::size_t textLength = strlen(text); - std::size_t lineStart = 0; - std::size_t lineWidth = 0; - for (std::size_t i = 0; i < textLength; i++) { - if (text[i] == '\n') { // Existing line break, scan next line - lineStart = i + 1; - lineWidth = 0; - continue; - } - - uint8_t w = FontTables[size][(uint8_t)text[i] + 2]; - lineWidth += (w != 0) ? w : FontTables[size][0]; - - if (lineWidth <= width) { - continue; // String is still within the limit, continue to the next line - } - - std::size_t j; // Backtrack to the previous space - for (j = i; j >= lineStart; j--) { - if (text[j] == ' ') { - break; - } - } - - if (j == lineStart) { // Single word longer than width - if (i == textLength) - break; - j = i; - } - - // Break line and continue to next line - i = j; - text[i] = '\n'; - lineStart = i + 1; - lineWidth = 0; - } -} - -} // namespace devilution diff --git a/Source/DiabloUI/text.h b/Source/DiabloUI/text.h deleted file mode 100644 index 667a92311..000000000 --- a/Source/DiabloUI/text.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include - -#include "DiabloUI/fonts.h" - -namespace devilution { - -std::size_t GetArtStrWidth(const char *str, std::size_t size); -void WordWrapArtStr(char *text, std::size_t width, std::size_t size = AFT_SMALL); - -} // namespace devilution diff --git a/Source/DiabloUI/text_draw.cpp b/Source/DiabloUI/text_draw.cpp index 4d24a04a9..5f246bb0c 100644 --- a/Source/DiabloUI/text_draw.cpp +++ b/Source/DiabloUI/text_draw.cpp @@ -3,7 +3,6 @@ #include "DiabloUI/art_draw.h" #include "DiabloUI/diabloui.h" #include "DiabloUI/fonts.h" -#include "DiabloUI/text.h" #include "DiabloUI/ttf_render_wrapped.h" #include "DiabloUI/ui_item.h" #include "utils/display.h" @@ -65,37 +64,4 @@ void DrawTTF(const char *text, const SDL_Rect &rectIn, UiFlags flags, ErrSdl(); } -void DrawArtStr(const char *text, const SDL_Rect &rect, UiFlags flags, bool drawTextCursor) -{ - _artFontTables size = AFT_SMALL; - _artFontColors color = HasAnyOf(flags, UiFlags::ColorGold) ? AFC_GOLD : AFC_SILVER; - - if (HasAnyOf(flags, UiFlags::FontMedium)) - size = AFT_MED; - else if (HasAnyOf(flags, UiFlags::FontBig)) - size = AFT_BIG; - else if (HasAnyOf(flags, UiFlags::FontHuge)) - size = AFT_HUGE; - - const int x = rect.x + AlignXOffset(flags, rect, GetArtStrWidth(text, size)); - const int y = rect.y + (HasAnyOf(flags, UiFlags::VerticalCenter) ? (rect.h - ArtFonts[size][color].h()) / 2 : 0); - - int sx = x; - int sy = y; - for (size_t i = 0, n = strlen(text); i < n; i++) { - if (text[i] == '\n') { - sx = x; - sy += ArtFonts[size][color].h(); - continue; - } - uint8_t w = FontTables[size][static_cast(text[i]) + 2]; - w = (w != 0) ? w : FontTables[size][0]; - DrawArt({ sx, sy }, &ArtFonts[size][color], static_cast(text[i]), w); - sx += w; - } - if (drawTextCursor && GetAnimationFrame(2, 500) != 0) { - DrawArt({ sx, sy }, &ArtFonts[size][color], '|'); - } -} - } // namespace devilution diff --git a/Source/DiabloUI/text_draw.h b/Source/DiabloUI/text_draw.h index 2e946f519..fa2f4fd48 100644 --- a/Source/DiabloUI/text_draw.h +++ b/Source/DiabloUI/text_draw.h @@ -17,6 +17,4 @@ void DrawTTF(const char *text, const SDL_Rect &rect, UiFlags flags, const SDL_Color &textColor, const SDL_Color &shadowColor, TtfSurfaceCache &renderCache); -void DrawArtStr(const char *text, const SDL_Rect &rect, UiFlags flags, bool drawTextCursor = false); - } // namespace devilution diff --git a/Source/DiabloUI/title.cpp b/Source/DiabloUI/title.cpp index 6d52722b1..a512f3010 100644 --- a/Source/DiabloUI/title.cpp +++ b/Source/DiabloUI/title.cpp @@ -40,8 +40,8 @@ void UiTitleDialog() UiAddBackground(&vecTitleScreen); UiAddLogo(&vecTitleScreen, LOGO_BIG, 182); - SDL_Rect rect = { (Sint16)(PANEL_LEFT + 49), (Sint16)(UI_OFFSET_Y + 410), 550, 26 }; - vecTitleScreen.push_back(std::make_unique(_("Copyright © 1996-2001 Blizzard Entertainment"), rect, UiFlags::FontMedium | UiFlags::AlignCenter)); + SDL_Rect rect = { (Sint16)(PANEL_LEFT), (Sint16)(UI_OFFSET_Y + 410), 640, 26 }; + vecTitleScreen.push_back(std::make_unique(_("Copyright © 1996-2001 Blizzard Entertainment"), rect, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorSilver)); } TitleLoad(); diff --git a/Source/DiabloUI/ui_item.h b/Source/DiabloUI/ui_item.h index 5322b36c8..c6ebe7798 100644 --- a/Source/DiabloUI/ui_item.h +++ b/Source/DiabloUI/ui_item.h @@ -25,21 +25,30 @@ enum class UiType { enum class UiFlags { // clang-format off None = 0, - FontSmall = 1 << 0, - FontMedium = 1 << 1, - FontBig = 1 << 2, - FontHuge = 1 << 3, - AlignCenter = 1 << 4, - AlignRight = 1 << 5, - VerticalCenter = 1 << 6, - ColorSilver = 1 << 7, - ColorGold = 1 << 8, - ColorRed = 1 << 9, - ColorBlue = 1 << 10, - ColorBlack = 1 << 11, - ElementDisabled = 1 << 12, - ElementHidden = 1 << 13, - KerningFitSpacing = 1 << 14, + + FontSize12 = 1 << 0, + FontSize24 = 1 << 1, + FontSize30 = 1 << 2, + FontSize42 = 1 << 3, + FontSize46 = 1 << 4, + + ColorSilver = 1 << 5, + ColorGold = 1 << 6, + ColorRed = 1 << 7, + ColorBlue = 1 << 8, + ColorBlack = 1 << 9, + + AlignCenter = 1 << 10, + AlignRight = 1 << 11, + VerticalCenter = 1 << 12, + + KerningFitSpacing = 1 << 13, + + ElementDisabled = 1 << 14, + ElementHidden = 1 << 15, + + PentaCursor = 1 << 16, + TextCursor = 1 << 17, // clang-format on }; @@ -153,9 +162,11 @@ public: * @param rect screen region defining the area to draw the text * @param flags UiFlags controlling color/alignment/size */ - UiArtText(const char *text, SDL_Rect rect, UiFlags flags = UiFlags::None) + UiArtText(const char *text, SDL_Rect rect, UiFlags flags = UiFlags::None, int spacing = 1, int lineHeight = -1) : UiItemBase(UiType::ArtText, rect, flags) , m_text(text) + , m_spacing(spacing) + , m_lineHeight(lineHeight) { } @@ -165,9 +176,11 @@ public: * @param rect screen region defining the area to draw the text * @param flags UiFlags controlling color/alignment/size */ - UiArtText(const char **ptext, SDL_Rect rect, UiFlags flags = UiFlags::None) + UiArtText(const char **ptext, SDL_Rect rect, UiFlags flags = UiFlags::None, int spacing = 1, int lineHeight = -1) : UiItemBase(UiType::ArtText, rect, flags) , m_ptext(ptext) + , m_spacing(spacing) + , m_lineHeight(lineHeight) { } @@ -178,11 +191,23 @@ public: return *m_ptext; } + int spacing() const + { + return m_spacing; + } + + int lineHeight() const + { + return m_lineHeight; + } + ~UiArtText() {}; private: const char *m_text = nullptr; const char **m_ptext = nullptr; + int m_spacing = 1; + int m_lineHeight = -1; }; //============================================================================= @@ -280,7 +305,6 @@ public: enum FrameKey : uint8_t { DEFAULT, PRESSED, - DISABLED }; //private: @@ -315,12 +339,13 @@ typedef std::vector> vUiListItem; class UiList : public UiItemBase { public: - UiList(const vUiListItem &vItems, Sint16 x, Sint16 y, Uint16 item_width, Uint16 item_height, UiFlags flags = UiFlags::None) + UiList(const vUiListItem &vItems, Sint16 x, Sint16 y, Uint16 item_width, Uint16 item_height, UiFlags flags = UiFlags::None, int spacing = 1) : UiItemBase(UiType::List, { x, y, item_width, static_cast(item_height * vItems.size()) }, flags) , m_x(x) , m_y(y) , m_width(item_width) , m_height(item_height) + , m_spacing(spacing) { for (auto &item : vItems) m_vecItems.push_back(item.get()); @@ -352,9 +377,15 @@ public: return m_vecItems[i]; } + int spacing() const + { + return m_spacing; + } + //private: Sint16 m_x, m_y; Uint16 m_width, m_height; std::vector m_vecItems; + int m_spacing; }; } // namespace devilution diff --git a/Source/automap.cpp b/Source/automap.cpp index f5ca5540a..74b88cbd3 100644 --- a/Source/automap.cpp +++ b/Source/automap.cpp @@ -461,7 +461,7 @@ AutomapTile GetAutomapTypeView(Point map) void DrawAutomapText(const Surface &out) { char desc[256]; - Point linePosition { 8, 20 }; + Point linePosition { 8, 8 }; if (gbIsMultiplayer) { if (strcasecmp("0.0.0.0", szPlayerName) != 0) { diff --git a/Source/capture.cpp b/Source/capture.cpp index e4fe63c10..7b6179941 100644 --- a/Source/capture.cpp +++ b/Source/capture.cpp @@ -146,7 +146,7 @@ std::ofstream CaptureFile(std::string *dstPath) */ void RedPalette() { - for (int i = 0; i < 255; i++) { + for (int i = 0; i < 256; i++) { system_palette[i].g = 0; system_palette[i].b = 0; } diff --git a/Source/control.cpp b/Source/control.cpp index 1d04397cd..707d09f15 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -90,7 +90,6 @@ std::optional talkButtons; std::optional pDurIcons; std::optional multiButtons; std::optional pPanelButtons; -std::optional pChrPanel; std::optional pGBoxBuff; std::optional pSBkBtnCel; std::optional pSBkIconCels; @@ -109,19 +108,6 @@ bool WhisperList[MAX_PLRS]; char panelstr[4][64]; uint8_t SplTransTbl[256]; -/** - * Line start position for info box text when displaying 1, 2, 3, 4 and 5 lines respectivly - */ -const int LineOffsets[5][5] = { - { 82 }, - { 70, 94 }, - { 64, 82, 100 }, - { 60, 75, 89, 104 }, - { 58, 70, 82, 94, 105 }, -}; - -/* data */ - /** Maps from spell_id to spelicon.cel frame number. */ char SpellITbl[] = { 27, @@ -230,7 +216,7 @@ spell_id SpellPages[6][7] = { #define SPLROWICONLS 10 #define SPLICONLAST (gbIsHellfire ? 52 : 43) -void CalculatePanelAreas(void) +void CalculatePanelAreas() { MainPanel = { { (gnScreenWidth - PANEL_WIDTH) / 2, gnScreenHeight - PANEL_HEIGHT }, { PANEL_WIDTH, PANEL_HEIGHT } }; LeftPanel = { { 0, 0 }, { SPANEL_WIDTH, SPANEL_HEIGHT } }; @@ -320,7 +306,7 @@ void SetSpellTrans(spell_type t) void PrintSBookHotkey(const Surface &out, Point position, const std::string &text) { // Align the hot key text with the top-right corner of the spell icon - position += Displacement { SPLICONLENGTH - (GetLineWidth(text.c_str()) + 5), 17 - SPLICONLENGTH }; + position += Displacement { SPLICONLENGTH - (GetLineWidth(text.c_str()) + 5), 5 - SPLICONLENGTH }; // Draw a drop shadow below and to the left of the text DrawString(out, text, position + Displacement { -1, 1 }, UiFlags::ColorBlack); @@ -412,19 +398,19 @@ void PrintInfo(const Surface &out) if (talkflag) return; - Rectangle line { { PANEL_X + 177, PANEL_Y + LineOffsets[pnumlines][0] }, { 288, 0 } }; + const int LineStart[] = { 70, 58, 52, 48, 46 }; + const int LineHeights[] = { 30, 24, 18, 15, 12 }; + + Rectangle line { { PANEL_X + 177, PANEL_Y + LineStart[pnumlines] }, { 288, 12 } }; - int yo = 0; - int lo = 1; if (infostr[0] != '\0') { DrawString(out, infostr, line, InfoColor | UiFlags::AlignCenter | UiFlags::KerningFitSpacing, 2); - yo = 1; - lo = 0; + line.position.y += LineHeights[pnumlines]; } for (int i = 0; i < pnumlines; i++) { - line.position.y = PANEL_Y + LineOffsets[pnumlines - lo][i + yo]; DrawString(out, panelstr[i], line, InfoColor | UiFlags::AlignCenter | UiFlags::KerningFitSpacing, 2); + line.position.y += LineHeights[pnumlines]; } } @@ -918,7 +904,8 @@ void InitControlPan() pManaBuff.emplace(88, 88); pLifeBuff.emplace(88, 88); - pChrPanel = LoadCel("Data\\Char.CEL", SPANEL_WIDTH); + LoadCharPanel(); + if (!gbIsHellfire) pSpellCels = LoadCel("CtrlPan\\SpelIcon.CEL", SPLICONLENGTH); else @@ -1301,7 +1288,6 @@ void FreeControlPan() pBtmBuff = std::nullopt; pManaBuff = std::nullopt; pLifeBuff = std::nullopt; - pChrPanel = std::nullopt; pSpellCels = std::nullopt; pPanelButtons = std::nullopt; multiButtons = std::nullopt; @@ -1313,6 +1299,7 @@ void FreeControlPan() pSBkBtnCel = std::nullopt; pSBkIconCels = std::nullopt; pGBoxBuff = std::nullopt; + FreeCharPanel(); } void DrawInfoBox(const Surface &out) @@ -1397,7 +1384,7 @@ void DrawLevelUpIcon(const Surface &out) { if (stextflag == STORE_NONE) { int nCel = lvlbtndown ? 3 : 2; - DrawString(out, _("Level Up"), { { PANEL_LEFT + 0, PANEL_TOP - 49 }, { 120, 0 } }, UiFlags::ColorSilver | UiFlags::AlignCenter); + DrawString(out, _("Level Up"), { { PANEL_LEFT + 0, PANEL_TOP - 62 }, { 120, 0 } }, UiFlags::ColorSilver | UiFlags::AlignCenter); CelDrawTo(out, { 40 + PANEL_X, -17 + PANEL_Y }, *pChrButtons, nCel); } } @@ -1512,13 +1499,13 @@ void DrawSpellBook(const Surface &out) auto &myPlayer = Players[MyPlayerId]; uint64_t spl = myPlayer._pMemSpells | myPlayer._pISpells | myPlayer._pAblSpells; - int yp = 55; + int yp = 43; for (int i = 1; i < 8; i++) { spell_id sn = SpellPages[sbooktab][i - 1]; if (sn != SPL_INVALID && (spl & GetSpellBitmask(sn)) != 0) { spell_type st = GetSBookTrans(sn, true); SetSpellTrans(st); - const Point spellCellPosition = GetPanelPosition(UiPanels::Spell, { 11, yp }); + const Point spellCellPosition = GetPanelPosition(UiPanels::Spell, { 11, yp + 12 }); DrawSpellCel(out, spellCellPosition, *pSBkIconCels, SpellITbl[sn]); if (sn == myPlayer._pRSpell && st == myPlayer._pRSplType) { SetSpellTrans(RSPLTYPE_SKILL); @@ -1612,12 +1599,12 @@ void DrawGoldSplit(const Surface &out, int amount) tempstr[BufferSize - 1] = '\0'; // Pre-wrap the string at spaces, otherwise DrawString would hard wrap in the middle of words - WordWrapGameString(tempstr, 200); + WordWrapString(tempstr, 200); // The split gold dialog is roughly 4 lines high, but we need at least one line for the player to input an amount. // Using a clipping region 50 units high (approx 3 lines with a lineheight of 17) to ensure there is enough room left // for the text entered by the player. - DrawString(out, tempstr, { GetPanelPosition(UiPanels::Inventory, { dialogX + 31, 87 }), { 200, 50 } }, UiFlags::ColorGold | UiFlags::AlignCenter, 1, 17); + DrawString(out, tempstr, { GetPanelPosition(UiPanels::Inventory, { dialogX + 31, 75 }), { 200, 50 } }, UiFlags::ColorGold | UiFlags::AlignCenter, 1, 17); tempstr[0] = '\0'; if (amount > 0) { @@ -1626,7 +1613,7 @@ void DrawGoldSplit(const Surface &out, int amount) } // Even a ten digit amount of gold only takes up about half a line. There's no need to wrap or clip text here so we // use the Point form of DrawString. - DrawString(out, tempstr, GetPanelPosition(UiPanels::Inventory, { dialogX + 37, 140 }), UiFlags::ColorSilver, 1, -1, true); + DrawString(out, tempstr, GetPanelPosition(UiPanels::Inventory, { dialogX + 37, 128 }), UiFlags::ColorSilver | UiFlags::PentaCursor); } void control_drop_gold(char vkey) @@ -1683,9 +1670,9 @@ void DrawTalkPan(const Surface &out) char *msg = TalkMessage; int x = PANEL_LEFT + 200; - int y = PANEL_Y + 22; + int y = PANEL_Y + 10; - int idx = DrawString(out, msg, { { x, y }, { 250, 39 } }, UiFlags::ColorSilver, 1, 13, true); + int idx = DrawString(out, msg, { { x, y }, { 250, 27 } }, UiFlags::ColorSilver | UiFlags::PentaCursor, 1, 13); msg[idx] = '\0'; x += 46; diff --git a/Source/controls/modifier_hints.cpp b/Source/controls/modifier_hints.cpp index c44cde4c7..8ab376821 100644 --- a/Source/controls/modifier_hints.cpp +++ b/Source/controls/modifier_hints.cpp @@ -29,7 +29,7 @@ constexpr int LineHeight = 25; constexpr int CircleMarginX = 16; /** Distance between the panel top and the circle top. */ -constexpr int CircleTop = 76; +constexpr int CircleTop = 101; struct CircleMenuHint { CircleMenuHint(bool isDpad, const char *top, const char *right, const char *bottom, const char *left) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index e42776052..87164b478 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1006,6 +1006,7 @@ void DiabloDeinit() dx_cleanup(); // Cleanup SDL surfaces stuff, so we have to do it before SDL_Quit(). if (was_fonts_init) FontsCleanup(); + UnloadFonts(); if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_HAPTIC) != 0) SDL_Quit(); } @@ -1509,6 +1510,18 @@ void InitKeymapActions() }); } +void LoadGameFonts() +{ + LoadFont(GameFont12, ColorSilver, "fonts\\white.trn"); + LoadFont(GameFont12, ColorGold, "fonts\\whitegold.trn"); + LoadFont(GameFont12, ColorRed, "fonts\\red.trn"); + LoadFont(GameFont12, ColorBlue, "fonts\\blue.trn"); + LoadFont(GameFont12, ColorBlack, "fonts\\black.trn"); + LoadFont(GameFont30, ColorGold); + LoadFont(GameFont46, ColorGold); + LoadFont(GameFont46, ColorBlack, "fonts\\black.trn"); +} + } // namespace void FreeGameMem() @@ -1542,6 +1555,7 @@ bool StartGame(bool bNewGame, bool bSinglePlayer) // Save 2.8 MiB of RAM by freeing all main menu resources // before starting the game. UiDestroy(); + LoadGameFonts(); gbSelectProvider = false; @@ -1557,6 +1571,7 @@ bool StartGame(bool bNewGame, bool bSinglePlayer) } RunGameLoop(uMsg); NetClose(); + UnloadFonts(); // If the player left the game into the main menu, // initialize main menu resources. @@ -1825,7 +1840,6 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir) InitStores(); InitAutomapOnce(); InitHelp(); - InitText(); } SetRndSeed(glSeedTbl[currlevel]); diff --git a/Source/engine/render/text_render.cpp b/Source/engine/render/text_render.cpp index bd435b6b9..3579fb0e4 100644 --- a/Source/engine/render/text_render.cpp +++ b/Source/engine/render/text_render.cpp @@ -5,196 +5,60 @@ */ #include "text_render.hpp" +#include +#include +#include + +#include "DiabloUI/art_draw.h" +#include "DiabloUI/diabloui.h" #include "DiabloUI/ui_item.h" #include "cel_render.hpp" #include "engine.h" #include "engine/load_cel.hpp" +#include "engine/load_file.hpp" #include "engine/point.hpp" #include "palette.h" +#include "utils/display.h" +#include "utils/sdl_compat.h" namespace devilution { namespace { -/** - * Maps ASCII character code to font index, as used by the - * small, medium and large sized fonts; which corresponds to smaltext.cel, - * medtexts.cel and bigtgold.cel respectively. - */ -const uint8_t FontIndex[256] = { - // clang-format off - '\0', 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - ' ', '!', '\"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', - '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', - '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0x01, - 'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'i', 'i', 'i', 'A', 'A', - 'E', 'a', 'A', 'o', 'o', 'o', 'u', 'u', 'y', 'O', 'U', 'c', 'L', 'Y', 'P', 'f', - 'a', 'i', 'o', 'u', 'n', 'N', 'a', 'o', '?', 0x01, 0x01, 0x01, 0x01, '!', '<', '>', - 'o', '+', '2', '3', '\'', 'u', 'P', '.', ',', '1', '0', '>', 0x01, 0x01, 0x01, '?', - 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', - 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'X', '0', 'U', 'U', 'U', 'U', 'Y', 'b', 'B', - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', - 'o', 'n', 'o', 'o', 'o', 'o', 'o', '/', '0', 'u', 'u', 'u', 'u', 'y', 'b', 'y', - // clang-format on -}; - -/** Maps from font index to cel frame number. */ -const uint8_t FontFrame[3][128] = { - { - // clang-format off - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 54, 44, 57, 58, 56, 55, 47, 40, 41, 59, 39, 50, 37, 51, 52, - 36, 27, 28, 29, 30, 31, 32, 33, 34, 35, 48, 49, 60, 38, 61, 53, - 62, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 63, 43, 64, 65, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 40, 66, 41, 67, 0, - // clang-format on - }, - { - // clang-format off - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 37, 49, 38, 0, 39, 40, 47, 42, 43, 41, 45, 52, 44, 53, 55, - 36, 27, 28, 29, 30, 31, 32, 33, 34, 35, 51, 50, 48, 46, 49, 54, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 0, 43, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 48, 0, 49, 0, 0, - // clang-format on - }, - { - // clang-format off - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 37, 49, 38, 0, 39, 40, 47, 42, 43, 41, 45, 52, 44, 53, 55, - 36, 27, 28, 29, 30, 31, 32, 33, 34, 35, 51, 50, 0, 46, 0, 54, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 0, 43, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 20, 0, 21, 0, 0, - // clang-format on - }, -}; - -/** - * Maps from cel frame number to character width. Note, the character width - * may be distinct from the frame width, which is the same for every cel frame. - */ -const uint8_t FontKern[3][68] = { - { - // clang-format off - 8, 10, 7, 9, 8, 7, 6, 8, 8, 3, - 3, 8, 6, 11, 9, 10, 6, 9, 9, 6, - 9, 11, 10, 13, 10, 11, 7, 5, 7, 7, - 8, 7, 7, 7, 7, 7, 10, 4, 5, 6, - 3, 3, 4, 3, 6, 6, 3, 3, 3, 3, - 3, 2, 7, 6, 3, 10, 10, 6, 6, 7, - 4, 4, 9, 6, 6, 12, 3, 7 - // clang-format on - }, - { - // clang-format off - 5, 15, 10, 13, 14, 10, 9, 13, 11, 5, - 5, 11, 10, 16, 13, 16, 10, 15, 12, 10, - 14, 17, 17, 22, 17, 16, 11, 5, 11, 11, - 11, 10, 11, 11, 11, 11, 15, 5, 10, 18, - 15, 8, 6, 6, 7, 10, 9, 6, 10, 10, - 5, 5, 5, 5, 11, 12 - // clang-format on - }, - { - // clang-format off - 18, 33, 21, 26, 28, 19, 19, 26, 25, 11, - 12, 25, 19, 34, 28, 32, 20, 32, 28, 20, - 28, 36, 35, 46, 33, 33, 24, 11, 23, 22, - 22, 21, 22, 21, 21, 21, 32, 10, 20, 36, - 31, 17, 13, 12, 13, 18, 16, 11, 20, 21, - 11, 10, 12, 11, 21, 23 - // clang-format on - } -}; +std::unordered_map> Fonts; -enum text_color : uint8_t { - ColorWhite, - ColorBlue, - ColorRed, - ColorGold, - ColorBlack, -}; +std::array, 5> FontKerns; +std::array FontSizes = { 12, 24, 30, 42, 46 }; +std::array LineHeights = { 12, 26, 38, 42, 50 }; +std::array BaseLineOffset = { -3, -2, -3, -6, -7 }; -int LineHeights[3] = { 12, 38, 50 }; +} // namespace -/** Graphics for the fonts */ -std::array, 3> fonts; +void LoadFont(GameFontTables size, text_color color, const char *translationFile) +{ + auto font = std::make_unique(); -uint8_t fontColorTableGold[256]; -uint8_t fontColorTableBlue[256]; -uint8_t fontColorTableRed[256]; + char path[32]; + sprintf(path, "fonts\\%i-00.pcx", FontSizes[size]); -void DrawChar(const Surface &out, Point position, GameFontTables size, int nCel, text_color color) -{ - switch (color) { - case ColorWhite: - CelDrawTo(out, position, *fonts[size], nCel); - return; - case ColorBlue: - CelDrawLightTo(out, position, *fonts[size], nCel, fontColorTableBlue); - break; - case ColorRed: - CelDrawLightTo(out, position, *fonts[size], nCel, fontColorTableRed); - break; - case ColorGold: - CelDrawLightTo(out, position, *fonts[size], nCel, fontColorTableGold); - break; - case ColorBlack: - LightTableIndex = 15; - CelDrawLightTo(out, position, *fonts[size], nCel, nullptr); - return; + if (translationFile != nullptr) { + std::array colorMapping; + LoadFileInMem(translationFile, colorMapping); + LoadMaskedArt(path, font.get(), 256, 1, &colorMapping); + } else { + LoadMaskedArt(path, font.get(), 256, 1); } -} -} // namespace + uint32_t fontId = (color << 24) | (size << 16); + Fonts.insert(make_pair(fontId, move(font))); -std::optional pSPentSpn2Cels; + sprintf(path, "fonts\\%i-00.bin", FontSizes[size]); + LoadFileInMem(path, FontKerns[size]); +} -void InitText() +void UnloadFonts() { - fonts[GameFontSmall] = LoadCel("CtrlPan\\SmalText.CEL", 13); - fonts[GameFontMed] = LoadCel("Data\\MedTextS.CEL", 22); - fonts[GameFontBig] = LoadCel("Data\\BigTGold.CEL", 46); - - pSPentSpn2Cels = LoadCel("Data\\PentSpn2.CEL", 12); - - for (int i = 0; i < 256; i++) { - uint8_t pix = i; - if (pix >= PAL16_GRAY + 14) - pix = PAL16_BLUE + 15; - else if (pix >= PAL16_GRAY) - pix -= PAL16_GRAY - (PAL16_BLUE + 2); - fontColorTableBlue[i] = pix; - } - - for (int i = 0; i < 256; i++) { - uint8_t pix = i; - if (pix >= PAL16_GRAY) - pix -= PAL16_GRAY - PAL16_RED; - fontColorTableRed[i] = pix; - } - - for (int i = 0; i < 256; i++) { - uint8_t pix = i; - if (pix >= PAL16_GRAY + 14) - pix = PAL16_YELLOW + 15; - else if (pix >= PAL16_GRAY) - pix -= PAL16_GRAY - (PAL16_YELLOW + 2); - fontColorTableGold[i] = pix; - } + Fonts.clear(); } int GetLineWidth(string_view text, GameFontTables size, int spacing, int *charactersInLine) @@ -206,8 +70,8 @@ int GetLineWidth(string_view text, GameFontTables size, int spacing, int *charac if (text[i] == '\n') break; - uint8_t frame = FontFrame[size][FontIndex[static_cast(text[i])]]; - lineWidth += FontKern[size][frame] + spacing; + uint8_t frame = text[i] & 0xFF; + lineWidth += FontKerns[size][frame] + spacing; } if (charactersInLine != nullptr) @@ -227,7 +91,7 @@ int AdjustSpacingToFitHorizontally(int &lineWidth, int maxSpacing, int character return maxSpacing - spacingRedux; } -void WordWrapGameString(char *text, size_t width, GameFontTables size, int spacing) +void WordWrapString(char *text, size_t width, GameFontTables size, int spacing) { const size_t textLength = strlen(text); size_t lineStart = 0; @@ -239,8 +103,8 @@ void WordWrapGameString(char *text, size_t width, GameFontTables size, int spaci continue; } - uint8_t frame = FontFrame[size][FontIndex[static_cast(text[i])]]; - lineWidth += FontKern[size][frame] + spacing; + uint8_t frame = text[i] & 0xFF; + lineWidth += FontKerns[size][frame] + spacing; if (lineWidth - spacing <= width) { continue; // String is still within the limit, continue to the next line @@ -270,17 +134,21 @@ void WordWrapGameString(char *text, size_t width, GameFontTables size, int spaci /** * @todo replace Rectangle with cropped Surface */ -uint16_t DrawString(const Surface &out, string_view text, const Rectangle &rect, UiFlags flags, int spacing, int lineHeight, bool drawTextCursor) +uint32_t DrawString(const Surface &out, string_view text, const Rectangle &rect, UiFlags flags, int spacing, int lineHeight) { - GameFontTables size = GameFontSmall; - if (HasAnyOf(flags, UiFlags::FontMedium)) - size = GameFontMed; - else if (HasAnyOf(flags, UiFlags::FontHuge)) - size = GameFontBig; + GameFontTables size = GameFont12; + if (HasAnyOf(flags, UiFlags::FontSize24)) + size = GameFont24; + else if (HasAnyOf(flags, UiFlags::FontSize30)) + size = GameFont30; + else if (HasAnyOf(flags, UiFlags::FontSize42)) + size = GameFont42; + else if (HasAnyOf(flags, UiFlags::FontSize46)) + size = GameFont46; text_color color = ColorGold; if (HasAnyOf(flags, UiFlags::ColorSilver)) - color = ColorWhite; + color = ColorSilver; else if (HasAnyOf(flags, UiFlags::ColorBlue)) color = ColorBlue; else if (HasAnyOf(flags, UiFlags::ColorRed)) @@ -303,17 +171,31 @@ uint16_t DrawString(const Surface &out, string_view text, const Rectangle &rect, else if (HasAnyOf(flags, UiFlags::AlignRight)) characterPosition.x += rect.size.width - lineWidth; - int rightMargin = rect.position.x + rect.size.width; int bottomMargin = rect.size.height != 0 ? rect.position.y + rect.size.height : out.h(); if (lineHeight == -1) lineHeight = LineHeights[size]; - uint16_t i = 0; + if (HasAnyOf(flags, UiFlags::VerticalCenter)) { + int textHeight = (std::count(text.cbegin(), text.cend(), '\n') + 1) * lineHeight; + characterPosition.y += (rect.size.height - textHeight) / 2; + } + + characterPosition.y += BaseLineOffset[size]; + + uint32_t fontId = (color << 24) | (size << 16); + auto font = Fonts.find(fontId); + if (font == Fonts.end()) { + Log("Font: size {} and color {} not loaded ", size, color); + return 0; + } + + const auto &activeFont = font->second; + + uint32_t i = 0; for (; i < text.length(); i++) { - uint8_t frame = FontFrame[size][FontIndex[static_cast(text[i])]]; - int symbolWidth = FontKern[size][frame]; - if (text[i] == '\n' || characterPosition.x + symbolWidth > rightMargin) { + uint8_t frame = text[i] & 0xFF; + if (text[i] == '\n') { if (characterPosition.y + lineHeight >= bottomMargin) break; characterPosition.y += lineHeight; @@ -330,14 +212,14 @@ uint16_t DrawString(const Surface &out, string_view text, const Rectangle &rect, else if (HasAnyOf(flags, UiFlags::AlignRight)) characterPosition.x += rect.size.width - lineWidth; } - if (frame != 0) { - DrawChar(out, characterPosition, size, frame, color); - } + DrawArt(out, characterPosition, activeFont.get(), frame); if (text[i] != '\n') - characterPosition.x += symbolWidth + spacing; + characterPosition.x += FontKerns[size][frame] + spacing; } - if (drawTextCursor) { - CelDrawTo(out, characterPosition, *pSPentSpn2Cels, PentSpn2Spin()); + if (HasAnyOf(flags, UiFlags::PentaCursor)) { + CelDrawTo(out, characterPosition + Displacement { 0, lineHeight - BaseLineOffset[size] }, *pSPentSpn2Cels, PentSpn2Spin()); + } else if (HasAnyOf(flags, UiFlags::TextCursor) && GetAnimationFrame(2, 500) != 0) { + DrawArt(out, characterPosition, activeFont.get(), '|'); } return i; diff --git a/Source/engine/render/text_render.hpp b/Source/engine/render/text_render.hpp index d96337b66..9446c2dc5 100644 --- a/Source/engine/render/text_render.hpp +++ b/Source/engine/render/text_render.hpp @@ -19,14 +19,24 @@ namespace devilution { enum GameFontTables : uint8_t { - GameFontSmall, - GameFontMed, - GameFontBig, + GameFont12, + GameFont24, + GameFont30, + GameFont42, + GameFont46, +}; + +enum text_color : uint8_t { + ColorSilver, + ColorGold, + ColorRed, + ColorBlue, + ColorBlack, }; extern std::optional pSPentSpn2Cels; -void InitText(); +void LoadFont(GameFontTables size, text_color color, const char *translationFile = nullptr); /** * @brief Calculate pixel width of first line of text, respecting kerning @@ -36,8 +46,8 @@ void InitText(); * @param charactersInLine Receives characters read until newline or terminator * @return Line width in pixels */ -int GetLineWidth(string_view text, GameFontTables size = GameFontSmall, int spacing = 1, int *charactersInLine = nullptr); -void WordWrapGameString(char *text, size_t width, GameFontTables size = GameFontSmall, int spacing = 1); +int GetLineWidth(string_view text, GameFontTables size = GameFont12, int spacing = 1, int *charactersInLine = nullptr); +void WordWrapString(char *text, size_t width, GameFontTables size = GameFont12, int spacing = 1); /** * @brief Draws a line of text within a clipping rectangle (positioned relative to the origin of the output buffer). @@ -56,16 +66,14 @@ void WordWrapGameString(char *text, size_t width, GameFontTables size = GameFont * @param spacing Additional space to add between characters. * This value may be adjusted if the flag UIS_FIT_SPACING is passed in the flags parameter. * @param lineHeight Allows overriding the default line height, useful for multi-line strings. - * @param drawTextCursor Whether to draw an animated cursor sprite at the end of the text (default is to display nothing). * @return The number of characters rendered, including characters "drawn" outside the buffer. */ -uint16_t DrawString(const Surface &out, string_view text, const Rectangle &rect, UiFlags flags = UiFlags::None, int spacing = 1, int lineHeight = -1, bool drawTextCursor = false); +uint32_t DrawString(const Surface &out, string_view text, const Rectangle &rect, UiFlags flags = UiFlags::None, int spacing = 1, int lineHeight = -1); /** * @brief Draws a line of text at the given position relative to the origin of the output buffer. * * This method is provided as a convenience to pass through to DrawString(..., Rectangle, ...) when no explicit - * clipping/wrapping is requested. Note that this will still wrap the rendered string if it would end up being drawn * beyond the right edge of the output buffer and clip it if it would extend beyond the bottom edge of the buffer. * @@ -76,14 +84,13 @@ uint16_t DrawString(const Surface &out, string_view text, const Rectangle &rect, * @param spacing Additional space to add between characters. * This value may be adjusted if the flag UIS_FIT_SPACING is passed in the flags parameter. * @param lineHeight Allows overriding the default line height, useful for multi-line strings. - * @param drawTextCursor Whether to draw an animated cursor sprite at the end of the text (default is to display nothing). - * @return The number of characters rendered (could be less than the string length if it wrapped past the bottom of the buffer). */ -inline uint16_t DrawString(const Surface &out, string_view text, const Point &position, UiFlags flags = UiFlags::None, int spacing = 1, int lineHeight = -1, bool drawTextCursor = false) +inline void DrawString(const Surface &out, string_view text, const Point &position, UiFlags flags = UiFlags::None, int spacing = 1, int lineHeight = -1) { - return DrawString(out, text, { position, { out.w() - position.x, 0 } }, flags, spacing, lineHeight, drawTextCursor); + DrawString(out, text, { position, { out.w() - position.x, 0 } }, flags, spacing, lineHeight); } uint8_t PentSpn2Spin(); +void UnloadFonts(); } // namespace devilution diff --git a/Source/engine/size.hpp b/Source/engine/size.hpp index 61310862f..69421da30 100644 --- a/Source/engine/size.hpp +++ b/Source/engine/size.hpp @@ -16,6 +16,20 @@ struct Size { return !(*this == other); } + constexpr Size &operator*=(const int factor) + { + width *= factor; + height *= factor; + return *this; + } + + constexpr Size &operator*=(const float factor) + { + width = static_cast(width * factor); + height = static_cast(height * factor); + return *this; + } + constexpr Size &operator/=(const int factor) { width /= factor; diff --git a/Source/error.cpp b/Source/error.cpp index 075548cb2..5e05f422b 100644 --- a/Source/error.cpp +++ b/Source/error.cpp @@ -35,7 +35,7 @@ void InitNextLines() char tempstr[1536]; // Longest test is about 768 chars * 2 for unicode strcpy(tempstr, message.data()); - WordWrapGameString(tempstr, LineWidth, GameFontSmall, 1); + WordWrapString(tempstr, LineWidth, GameFont12, 1); const string_view paragraphs = tempstr; size_t previous = 0; @@ -172,7 +172,7 @@ void DrawDiabloMsg(const Surface &out) auto message = DiabloMessages.front(); int lineNumber = 0; for (auto &line : TextLines) { - DrawString(out, line.c_str(), { { PANEL_X + 109, dialogStartY + 24 + lineNumber * LineHeight }, { LineWidth, LineHeight } }, UiFlags::AlignCenter, 1, LineHeight); + DrawString(out, line.c_str(), { { PANEL_X + 109, dialogStartY + 12 + lineNumber * LineHeight }, { LineWidth, LineHeight } }, UiFlags::AlignCenter, 1, LineHeight); lineNumber += 1; } diff --git a/Source/gmenu.cpp b/Source/gmenu.cpp index 589ee1c49..b62e356fe 100644 --- a/Source/gmenu.cpp +++ b/Source/gmenu.cpp @@ -96,7 +96,7 @@ int GmenuGetLineWidth(TMenuItem *pItem) if ((pItem->dwFlags & GMENU_SLIDER) != 0) return 490; - return GetLineWidth(_(pItem->pszStr), GameFontBig, 2); + return GetLineWidth(_(pItem->pszStr), GameFont46, 2); } void GmenuDrawMenuItem(const Surface &out, TMenuItem *pItem, int y) @@ -104,20 +104,20 @@ void GmenuDrawMenuItem(const Surface &out, TMenuItem *pItem, int y) int w = GmenuGetLineWidth(pItem); if ((pItem->dwFlags & GMENU_SLIDER) != 0) { int x = 16 + w / 2; - CelDrawTo(out, { x + PANEL_LEFT, y - 10 }, *optbar_cel, 1); + CelDrawTo(out, { x + PANEL_LEFT, y + 40 }, *optbar_cel, 1); uint16_t step = pItem->dwFlags & 0xFFF; uint16_t steps = std::max((pItem->dwFlags & 0xFFF000) >> 12, 2); uint16_t pos = step * 256 / steps; - GmenuClearBuffer(out, x + 2 + PANEL_LEFT, y - 12, pos + 13, 28); - CelDrawTo(out, { x + 2 + pos + PANEL_LEFT, y - 12 }, *option_cel, 1); + GmenuClearBuffer(out, x + 2 + PANEL_LEFT, y + 38, pos + 13, 28); + CelDrawTo(out, { x + 2 + pos + PANEL_LEFT, y + 38 }, *option_cel, 1); } int x = (gnScreenWidth - w) / 2; - UiFlags style = (pItem->dwFlags & GMENU_ENABLED) != 0 ? UiFlags::ColorSilver : UiFlags::ColorBlack; - DrawString(out, _(pItem->pszStr), Point { x, y }, style | UiFlags::FontHuge, 2); + UiFlags style = (pItem->dwFlags & GMENU_ENABLED) != 0 ? UiFlags::ColorGold : UiFlags::ColorBlack; + DrawString(out, _(pItem->pszStr), Point { x, y }, style | UiFlags::FontSize46, 2); if (pItem == sgpCurrItem) { - CelDrawTo(out, { x - 54, y + 1 }, *PentSpin_cel, PentSpn2Spin()); - CelDrawTo(out, { x + 4 + w, y + 1 }, *PentSpin_cel, PentSpn2Spin()); + CelDrawTo(out, { x - 54, y + 51 }, *PentSpin_cel, PentSpn2Spin()); + CelDrawTo(out, { x + 4 + w, y + 51 }, *PentSpin_cel, PentSpn2Spin()); } } @@ -163,7 +163,7 @@ void gmenu_draw_pause(const Surface &out) RedBack(out); if (sgpCurrentMenu == nullptr) { LightTableIndex = 0; - DrawString(out, _("Pause"), Point { 0, PANEL_TOP / 2 }, UiFlags::FontHuge | UiFlags::AlignCenter, 2); + DrawString(out, _("Pause"), { { 0, 0 }, { gnScreenWidth, PANEL_TOP } }, UiFlags::FontSize46 | UiFlags::AlignCenter | UiFlags::VerticalCenter, 2); } } @@ -233,7 +233,7 @@ void gmenu_draw(const Surface &out) } } CelDrawTo(out, { (gnScreenWidth - sgpLogo->Width()) / 2, 102 + UI_OFFSET_Y }, *sgpLogo, LogoAnim_frame); - int y = 160 + UI_OFFSET_Y; + int y = 110 + UI_OFFSET_Y; TMenuItem *i = sgpCurrentMenu; if (sgpCurrentMenu->fnMenu != nullptr) { while (i->fnMenu != nullptr) { diff --git a/Source/help.cpp b/Source/help.cpp index 0ae81c0cf..3b302e548 100644 --- a/Source/help.cpp +++ b/Source/help.cpp @@ -106,7 +106,7 @@ void InitHelp() for (const auto *text : HelpText) { strcpy(tempString, _(text)); - WordWrapGameString(tempString, 577); + WordWrapString(tempString, 577); const string_view paragraph = tempString; size_t previous = 0; @@ -137,8 +137,8 @@ void DrawHelp(const Surface &out) const int sx = PANEL_X + 32; const int sy = UI_OFFSET_Y + 51; - for (int i = 7; i < 22; i++) { - const char *line = HelpTextLines[i - 7 + SkipLines].c_str(); + for (int i = 6; i < 21; i++) { + const char *line = HelpTextLines[i - 6 + SkipLines].c_str(); if (line[0] == '\0') { continue; } diff --git a/Source/inv.cpp b/Source/inv.cpp index d6d472c25..f27e93711 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -1248,7 +1248,7 @@ void DrawInvBelt(const Surface &out) && myPlayer.SpdList[i]._iStatFlag && myPlayer.SpdList[i]._itype != ITYPE_GOLD) { snprintf(tempstr, sizeof(tempstr) / sizeof(*tempstr), "%i", i + 1); - DrawString(out, tempstr, { position, InventorySlotSizeInPixels }, UiFlags::ColorSilver | UiFlags::AlignRight); + DrawString(out, tempstr, { position - Displacement { 0, 12 }, InventorySlotSizeInPixels }, UiFlags::ColorSilver | UiFlags::AlignRight); } } } diff --git a/Source/items.cpp b/Source/items.cpp index 44da1b2b3..84c0fdb1b 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1121,7 +1121,7 @@ int SaveItemPower(Item &item, const ItemPower &power) bool StringInPanel(const char *str) { - return GetLineWidth(str, GameFontSmall, 0) < 125; + return GetLineWidth(str, GameFont12, 0) < 125; } int PLVal(int pv, int p1, int p2, int minv, int maxv) @@ -4130,7 +4130,7 @@ void DrawUniqueInfo(const Surface &out) DrawUniqueInfoWindow(GlobalBackBuffer()); - Rectangle rect { { 32 + RightPanel.position.x - SPANEL_WIDTH, 44 + RightPanel.position.y + 2 * 12 }, { 257, 0 } }; + Rectangle rect { { 32 + RightPanel.position.x - SPANEL_WIDTH, 44 + RightPanel.position.y + 12 }, { 257, 0 } }; const UniqueItem &uitem = UniqueItems[curruitem._iUid]; DrawString(out, _(uitem.UIName), rect, UiFlags::AlignCenter); diff --git a/Source/minitext.cpp b/Source/minitext.cpp index 925a3f0f3..d52eb31ad 100644 --- a/Source/minitext.cpp +++ b/Source/minitext.cpp @@ -44,7 +44,7 @@ void LoadText(const char *text) char tempstr[1536]; // Longest test is about 768 chars * 2 for unicode strcpy(tempstr, text); - WordWrapGameString(tempstr, 543, GameFontMed, 2); + WordWrapString(tempstr, 543, GameFont30); const string_view paragraphs = tempstr; size_t previous = 0; @@ -102,7 +102,7 @@ void DrawQTextContent(const Surface &out) int y = CalculateTextPosition(); const int sx = PANEL_X + 48; - const int sy = LineHeight / 2 - (y % LineHeight); + const int sy = 0 - (y % LineHeight); const unsigned int skipLines = y / LineHeight; @@ -117,7 +117,7 @@ void DrawQTextContent(const Surface &out) continue; } - DrawString(out, line, { { sx, sy + i * LineHeight }, { 543, LineHeight } }, UiFlags::FontMedium, 2); + DrawString(out, line, { { sx, sy + i * LineHeight }, { 543, LineHeight } }, UiFlags::FontSize30); } } diff --git a/Source/palette.cpp b/Source/palette.cpp index e1f2f60fc..ffa7b9cde 100644 --- a/Source/palette.cpp +++ b/Source/palette.cpp @@ -160,10 +160,10 @@ void CycleColorsReverse(int from, int to) } // namespace -void palette_update() +void palette_update(int first, int ncolor) { assert(Palette); - if (SDLC_SetSurfaceAndPaletteColors(pal_surface, Palette, system_palette, 0, 256) < 0) { + if (SDLC_SetSurfaceAndPaletteColors(pal_surface, Palette, system_palette, first, ncolor) < 0) { ErrSdl(); } pal_surface_palette_version++; @@ -345,7 +345,7 @@ void PaletteFadeOut(int fr) void palette_update_caves() { CycleColors(1, 31); - palette_update(); + palette_update(1, 31); } void palette_update_crypt() @@ -361,7 +361,7 @@ void palette_update_crypt() } if (glowDelay > 0) { CycleColorsReverse(16, 31); - palette_update(); + palette_update(1, 31); glowDelay++; } else { glowDelay = 1; @@ -381,7 +381,7 @@ void palette_update_hive() } if (bubbleDelay == 2) { CycleColorsReverse(9, 15); - palette_update(); + palette_update(1, 31); bubbleDelay = 0; } else { bubbleDelay++; @@ -393,7 +393,7 @@ void palette_update_quest_palette(int n) int i = 32 - n; logical_palette[i] = orig_palette[i]; ApplyGamma(system_palette, logical_palette, 32); - palette_update(); + palette_update(0, 31); if (sgOptions.Graphics.bBlendedTransparancy) { // Update blended transparency, but only for the color that was updated for (int j = 0; j < 256; j++) { diff --git a/Source/palette.h b/Source/palette.h index a08da11ee..716806b2c 100644 --- a/Source/palette.h +++ b/Source/palette.h @@ -35,7 +35,7 @@ extern SDL_Color orig_palette[256]; /** Lookup table for transparency */ extern Uint8 paletteTransparencyLookup[256][256]; -void palette_update(); +void palette_update(int first = 0, int ncolor = 256); void palette_init(); void LoadPalette(const char *pszFileName, bool blend = true); void LoadRndLvlPal(dungeon_type l); diff --git a/Source/panels/charpanel.cpp b/Source/panels/charpanel.cpp index 6c8dd50be..765546dcf 100644 --- a/Source/panels/charpanel.cpp +++ b/Source/panels/charpanel.cpp @@ -7,6 +7,7 @@ #include "DiabloUI/art_draw.h" #include "control.h" +#include "utils/display.h" #include "engine/render/cel_render.hpp" #include "engine/render/text_render.hpp" #include "utils/language.h" @@ -36,17 +37,8 @@ struct PanelEntry { std::string label; Point position; int length; - Displacement labelOffset; // label's offset (end of the label vs the beginning of the stat box) - int labelLength; // max label's length - used for line wrapping - int labelSpacing; - int statSpacing; - bool centered; - /** - * Toggles whether the box should be using the 27px version or 26px. - * Must be set to true for stat boxes or they don't line up with the "spend stat" button - */ - bool high; - std::function statDisplayFunc; // function responsible for displaying stat + int labelLength; // max label's length - used for line wrapping + std::function statDisplayFunc = nullptr; // function responsible for displaying stat }; Player *MyPlayer = &Players[MyPlayerId]; @@ -120,112 +112,90 @@ StyledText GetResistInfo(int8_t resist) } PanelEntry panelEntries[] = { - { "", { 13, 14 }, 134, { 0, 0 }, 0, 0, 1, false, false, + { "", { 9, 14 }, 150, 0, []() { return StyledText { UiFlags::ColorSilver, MyPlayer->_pName }; } }, - { N_("Level"), { 57, 52 }, 45, { -3, 0 }, 0, 0, 1, false, false, - []() { return StyledText { UiFlags::ColorSilver, fmt::format("{:d}", MyPlayer->_pLevel) }; } }, + { "", { 161, 14 }, 149, 0, + []() { return StyledText { UiFlags::ColorSilver, _(ClassStrTbl[static_cast(MyPlayer->_pClass)]) }; } }, - { N_("Base"), { 88, 118 }, 33, { 39, 0 }, 0, 0, 0, false, false, - nullptr }, - { N_("Now"), { 135, 118 }, 33, { 39, 0 }, 0, 0, 0, false, false, - nullptr }, + { N_("Level"), { 57, 52 }, 57, 45, + []() { return StyledText { UiFlags::ColorSilver, fmt::format("{:d}", MyPlayer->_pLevel) }; } }, + { N_("Experience"), { 211, 52 }, 99, 91, + []() { return StyledText { UiFlags::ColorSilver, fmt::format("{:d}", MyPlayer->_pExperience) }; } }, + { N_("Next level"), { 211, 80 }, 99, 198, + []() { + if (MyPlayer->_pLevel == MAXCHARLEVEL - 1) { + return StyledText { UiFlags::ColorGold, _("None") }; + } else { + return StyledText { UiFlags::ColorSilver, fmt::format("{:d}", MyPlayer->_pNextExper) }; + } + } }, - { N_("Strength"), { 88, 137 }, 33, { -3, 0 }, 0, 0, 1, false, true, + { N_("Base"), { 88, 115 }, 0, 44 }, + { N_("Now"), { 135, 115 }, 0, 44 }, + { N_("Strength"), { 88, 135 }, 45, 76, []() { return StyledText { GetBaseStatColor(CharacterAttribute::Strength), fmt::format("{:d}", MyPlayer->_pBaseStr) }; } }, - { N_("Magic"), { 88, 165 }, 33, { -3, 0 }, 0, 0, 1, false, true, - []() { return StyledText { GetBaseStatColor(CharacterAttribute::Magic), fmt::format("{:d}", MyPlayer->_pBaseMag) }; } }, - { N_("Dexterity"), { 88, 193 }, 33, { -3, 0 }, 0, 0, 1, false, true, - []() { return StyledText { GetBaseStatColor(CharacterAttribute::Dexterity), fmt::format("{:d}", MyPlayer->_pBaseDex) }; } }, - { N_("Vitality"), { 88, 221 }, 33, { -3, 0 }, 0, 0, 1, false, true, - []() { return StyledText { GetBaseStatColor(CharacterAttribute::Vitality), fmt::format("{:d}", MyPlayer->_pBaseVit) }; } }, - - { "", { 135, 137 }, 33, { 0, 0 }, 0, 0, 1, false, true, + { "", { 135, 135 }, 45, 0, []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Strength), fmt::format("{:d}", MyPlayer->_pStrength) }; } }, - { "", { 135, 165 }, 33, { 0, 0 }, 0, 0, 1, false, true, + { N_("Magic"), { 88, 163 }, 45, 76, + []() { return StyledText { GetBaseStatColor(CharacterAttribute::Magic), fmt::format("{:d}", MyPlayer->_pBaseMag) }; } }, + { "", { 135, 163 }, 45, 0, []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Magic), fmt::format("{:d}", MyPlayer->_pMagic) }; } }, - { "", { 135, 193 }, 33, { 0, 0 }, 0, 0, 1, false, true, + { N_("Dexterity"), { 88, 191 }, 45, 76, []() { return StyledText { GetBaseStatColor(CharacterAttribute::Dexterity), fmt::format("{:d}", MyPlayer->_pBaseDex) }; } }, + { "", { 135, 191 }, 45, 0, []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Dexterity), fmt::format("{:d}", MyPlayer->_pDexterity) }; } }, - { "", { 135, 221 }, 33, { 0, 0 }, 0, 0, 1, false, true, + { N_("Vitality"), { 88, 219 }, 45, 76, []() { return StyledText { GetBaseStatColor(CharacterAttribute::Vitality), fmt::format("{:d}", MyPlayer->_pBaseVit) }; } }, + { "", { 135, 219 }, 45, 0, []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Vitality), fmt::format("{:d}", MyPlayer->_pVitality) }; } }, - - { N_("Points to distribute"), { 88, 250 }, 33, { -3, -5 }, 120, 0, 1, false, false, + { N_("Points to distribute"), { 88, 248 }, 45, 76, []() { MyPlayer->_pStatPts = std::min(CalcStatDiff(*MyPlayer), MyPlayer->_pStatPts); return StyledText { UiFlags::ColorRed, (MyPlayer->_pStatPts > 0 ? fmt::format("{:d}", MyPlayer->_pStatPts) : "") }; } }, - { N_("Life"), { 88, 287 }, 33, { -3, 0 }, 0, 0, 1, false, false, - []() { return StyledText { GetMaxHealthColor(), fmt::format("{:d}", MyPlayer->_pMaxHP >> 6) }; } }, - - { "", { 135, 287 }, 33, { 0, 0 }, 0, 0, 1, false, false, - []() { return StyledText { (MyPlayer->_pHitPoints != MyPlayer->_pMaxHP ? UiFlags::ColorRed : GetMaxHealthColor()), fmt::format("{:d}", MyPlayer->_pHitPoints >> 6) }; } }, - - { N_("Mana"), { 88, 315 }, 33, { -3, 0 }, 0, 0, 1, false, false, - []() { return StyledText { GetMaxManaColor(), fmt::format("{:d}", MyPlayer->_pMaxMana >> 6) }; } }, - - { "", { 135, 315 }, 33, { 0, 0 }, 0, 0, 1, false, false, - []() { return StyledText { (MyPlayer->_pMana != MyPlayer->_pMaxMana ? UiFlags::ColorRed : GetMaxManaColor()), fmt::format("{:d}", MyPlayer->_pMana >> 6) }; } }, - - { "", { 161, 14 }, 134, { 0, 0 }, 0, 0, 1, false, false, - []() { return StyledText { UiFlags::ColorSilver, _(ClassStrTbl[static_cast(MyPlayer->_pClass)]) }; } }, - - { N_("Experience"), { 208, 52 }, 87, { -3, 0 }, 0, 0, 1, false, false, - []() { return StyledText { UiFlags::ColorSilver, fmt::format("{:d}", MyPlayer->_pExperience) }; } }, - - { N_("Next level"), { 208, 80 }, 87, { -3, 0 }, 0, 0, 1, false, false, - []() { - if (MyPlayer->_pLevel == MAXCHARLEVEL - 1) { - return StyledText { UiFlags::ColorGold, _("None") }; - } else { - return StyledText { UiFlags::ColorSilver, fmt::format("{:d}", MyPlayer->_pNextExper) }; - } - } }, - - { N_("Gold"), { 208, 129 }, 87, { 0, -20 }, 0, 0, 1, true, false, + { N_("Gold"), { 211, 107 }, 0, 98 }, + { "", { 211, 127 }, 99, 0, []() { return StyledText { UiFlags::ColorSilver, fmt::format("{:d}", MyPlayer->_pGold) }; } }, - { N_("Armor class"), { 250, 166 }, 45, { -3, -5 }, 55, 0, 1, false, false, + { N_("Armor class"), { 253, 163 }, 57, 67, []() { return StyledText { GetValueColor(MyPlayer->_pIBonusAC), fmt::format("{:d}", MyPlayer->GetArmor()) }; } }, - - { N_("To hit"), { 250, 194 }, 45, { -3, 0 }, 0, 0, 1, false, false, + { N_("To hit"), { 253, 191 }, 57, 67, []() { return StyledText { GetValueColor(MyPlayer->_pIBonusToHit), fmt::format("{:d}%", (MyPlayer->InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_BOW ? MyPlayer->GetRangedToHit() : MyPlayer->GetMeleeToHit())) }; } }, - - { N_("Damage"), { 250, 222 }, 45, { -3, 0 }, 0, 0, 0, false, false, + { N_("Damage"), { 253, 219 }, 57, 67, []() { std::pair dmg = GetDamage(); return StyledText { GetValueColor(MyPlayer->_pIBonusDam), fmt::format("{:d}-{:d}", dmg.first, dmg.second) }; } }, - { N_("Resist magic"), { 250, 259 }, 45, { -3, -5 }, 46, 1, 1, false, false, - []() { return GetResistInfo(MyPlayer->_pMagResist); } }, + { N_("Life"), { 88, 284 }, 45, 76, + []() { return StyledText { GetMaxHealthColor(), fmt::format("{:d}", MyPlayer->_pMaxHP >> 6) }; } }, + { "", { 135, 284 }, 45, 0, + []() { return StyledText { (MyPlayer->_pHitPoints != MyPlayer->_pMaxHP ? UiFlags::ColorRed : GetMaxHealthColor()), fmt::format("{:d}", MyPlayer->_pHitPoints >> 6) }; } }, + { N_("Mana"), { 88, 312 }, 45, 76, + []() { return StyledText { GetMaxManaColor(), fmt::format("{:d}", MyPlayer->_pMaxMana >> 6) }; } }, + { "", { 135, 312 }, 45, 0, + []() { return StyledText { (MyPlayer->_pMana != MyPlayer->_pMaxMana ? UiFlags::ColorRed : GetMaxManaColor()), fmt::format("{:d}", MyPlayer->_pMana >> 6) }; } }, - { N_("Resist fire"), { 250, 287 }, 45, { -3, -5 }, 46, 1, 1, false, false, + { N_("Resist magic"), { 253, 256 }, 57, 67, + []() { return GetResistInfo(MyPlayer->_pMagResist); } }, + { N_("Resist fire"), { 253, 284 }, 57, 67, []() { return GetResistInfo(MyPlayer->_pFireResist); } }, - - { N_("Resist lightning"), { 250, 315 }, 45, { -3, -5 }, 76, 0, 1, false, false, + { N_("Resist lightning"), { 253, 313 }, 57, 67, []() { return GetResistInfo(MyPlayer->_pLghtResist); } }, - }; -Art PanelParts[6]; +Art PanelBoxLeft; +Art PanelBoxMiddle; +Art PanelBoxRight; Art PanelFull; -void DrawPanelFieldLow(const Surface &out, Point pos, int len) -{ - DrawArt(out, pos, &PanelParts[0]); - pos.x += PanelParts[0].w(); - DrawArt(out, pos, &PanelParts[1], 0, len); - pos.x += len; - DrawArt(out, pos, &PanelParts[2]); -} - -void DrawPanelFieldHigh(const Surface &out, Point pos, int len) +void DrawPanelField(const Surface &out, Point pos, int len) { - DrawArt(out, pos, &PanelParts[3]); - pos.x += PanelParts[3].w(); - DrawArt(out, pos, &PanelParts[4], 0, len); + DrawArt(out, pos, &PanelBoxLeft); + pos.x += PanelBoxLeft.w(); + len -= PanelBoxLeft.w() + PanelBoxRight.w(); + DrawArt(out, pos, &PanelBoxMiddle, 0, len); pos.x += len; - DrawArt(out, pos, &PanelParts[5]); + DrawArt(out, pos, &PanelBoxRight); } void DrawShadowString(const Surface &out, const PanelEntry &entry) @@ -235,87 +205,83 @@ void DrawShadowString(const Surface &out, const PanelEntry &entry) std::string text_tmp = _(entry.label.c_str()); char buffer[32]; - int spacing = entry.labelSpacing; + int spacing = 0; strcpy(buffer, text_tmp.c_str()); if (entry.labelLength > 0) - WordWrapGameString(buffer, entry.labelLength, GameFontSmall, spacing); + WordWrapString(buffer, entry.labelLength, GameFont12, spacing); std::string text(buffer); - int width = GetLineWidth(text, GameFontSmall, spacing); - Point finalPos = { entry.position + Displacement { 0, 17 } + entry.labelOffset }; - if (entry.centered) - width = entry.length; - else - finalPos.x -= width; - - UiFlags style = UiFlags::AlignRight; - if (entry.centered) { - style = UiFlags::AlignCenter; - finalPos += Displacement { 7, 0 }; // left border + + UiFlags style = UiFlags::VerticalCenter; + + Point labelPosition = entry.position; + + if (entry.length == 0) { + style |= UiFlags::AlignCenter; + } else { + style |= UiFlags::AlignRight; + labelPosition += Displacement { -entry.labelLength - 3, 0 }; } - DrawString(out, text, { finalPos + Displacement { -2, 2 }, { width, 0 } }, style | UiFlags::ColorBlack, spacing, 10); - DrawString(out, text, { finalPos, { width, 0 } }, style | UiFlags::ColorSilver, spacing, 10); + + DrawString(out, text, { labelPosition + Displacement { -2, 2 }, { entry.labelLength, 20 } }, style | UiFlags::ColorBlack, spacing, 10); + DrawString(out, text, { labelPosition, { entry.labelLength, 20 } }, style | UiFlags::ColorSilver, spacing, 10); } +void DrawStatButtons(const Surface &out) +{ + if (MyPlayer->_pStatPts > 0) { + if (MyPlayer->_pBaseStr < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Strength)) + CelDrawTo(out, GetPanelPosition(UiPanels::Character, { 137, 157 }), *pChrButtons, chrbtn[static_cast(CharacterAttribute::Strength)] ? 3 : 2); + if (MyPlayer->_pBaseMag < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Magic)) + CelDrawTo(out, GetPanelPosition(UiPanels::Character, { 137, 185 }), *pChrButtons, chrbtn[static_cast(CharacterAttribute::Magic)] ? 5 : 4); + if (MyPlayer->_pBaseDex < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Dexterity)) + CelDrawTo(out, GetPanelPosition(UiPanels::Character, { 137, 214 }), *pChrButtons, chrbtn[static_cast(CharacterAttribute::Dexterity)] ? 7 : 6); + if (MyPlayer->_pBaseVit < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Vitality)) + CelDrawTo(out, GetPanelPosition(UiPanels::Character, { 137, 242 }), *pChrButtons, chrbtn[static_cast(CharacterAttribute::Vitality)] ? 9 : 8); + } +} + +} // namespace + void LoadCharPanel() { LoadArt("data\\charbg.pcx", &PanelFull); - LoadArt("data\\boxleftend26.pcx", &PanelParts[0]); - LoadArt("data\\boxmiddle26.pcx", &PanelParts[1]); - LoadArt("data\\boxrightend26.pcx", &PanelParts[2]); - LoadArt("data\\boxleftend27.pcx", &PanelParts[3]); - LoadArt("data\\boxmiddle27.pcx", &PanelParts[4]); - LoadArt("data\\boxrightend27.pcx", &PanelParts[5]); + UpdatePalette(&PanelFull); // PanelFull is being used as a render target + LoadArt("data\\boxleftend.pcx", &PanelBoxLeft); + LoadArt("data\\boxmiddle.pcx", &PanelBoxMiddle); + LoadArt("data\\boxrightend.pcx", &PanelBoxRight); const Surface out(PanelFull.surface.get()); for (auto &entry : panelEntries) { if (entry.statDisplayFunc != nullptr) { - if (entry.high) - DrawPanelFieldHigh(out, entry.position, entry.length); - else - DrawPanelFieldLow(out, entry.position, entry.length); + DrawPanelField(out, entry.position, entry.length); } DrawShadowString(out, entry); } - for (auto &gfx : PanelParts) { - gfx.Unload(); - } + PanelBoxLeft.Unload(); + PanelBoxMiddle.Unload(); + PanelBoxRight.Unload(); } -bool CharPanelLoaded = false; - -void DrawStatButtons(const Surface &out) +void FreeCharPanel() { - if (MyPlayer->_pStatPts > 0) { - if (MyPlayer->_pBaseStr < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Strength)) - CelDrawTo(out, GetPanelPosition(UiPanels::Character, { 137, 159 }), *pChrButtons, chrbtn[static_cast(CharacterAttribute::Strength)] ? 3 : 2); - if (MyPlayer->_pBaseMag < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Magic)) - CelDrawTo(out, GetPanelPosition(UiPanels::Character, { 137, 187 }), *pChrButtons, chrbtn[static_cast(CharacterAttribute::Magic)] ? 5 : 4); - if (MyPlayer->_pBaseDex < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Dexterity)) - CelDrawTo(out, GetPanelPosition(UiPanels::Character, { 137, 216 }), *pChrButtons, chrbtn[static_cast(CharacterAttribute::Dexterity)] ? 7 : 6); - if (MyPlayer->_pBaseVit < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Vitality)) - CelDrawTo(out, GetPanelPosition(UiPanels::Character, { 137, 244 }), *pChrButtons, chrbtn[static_cast(CharacterAttribute::Vitality)] ? 9 : 8); - } + PanelFull.Unload(); } -} // namespace - void DrawChr(const Surface &out) { - if (!CharPanelLoaded) { - LoadCharPanel(); - CharPanelLoaded = true; - } Point pos = GetPanelPosition(UiPanels::Character, { 0, 0 }); DrawArt(out, pos, &PanelFull); for (auto &entry : panelEntries) { if (entry.statDisplayFunc != nullptr) { StyledText tmp = entry.statDisplayFunc(); - Displacement displacement = Displacement { pos.x + 7, pos.y + 17 }; - if (entry.high) - displacement += { 0, 1 }; - DrawString(out, tmp.text.c_str(), { entry.position + displacement, { entry.length, 0 } }, UiFlags::AlignCenter | tmp.style, entry.statSpacing); + DrawString( + out, + tmp.text.c_str(), + { entry.position + Displacement { pos.x, pos.y }, { entry.length, 27 } }, + UiFlags::AlignCenter | UiFlags::VerticalCenter | tmp.style, + 1); } } DrawStatButtons(out); diff --git a/Source/panels/charpanel.hpp b/Source/panels/charpanel.hpp index 388493432..e5e21605d 100644 --- a/Source/panels/charpanel.hpp +++ b/Source/panels/charpanel.hpp @@ -10,5 +10,7 @@ extern std::optional pChrButtons; extern const char *const ClassStrTbl[]; void DrawChr(const Surface &); +void LoadCharPanel(); +void FreeCharPanel(); } // namespace devilution diff --git a/Source/plrmsg.cpp b/Source/plrmsg.cpp index b39efbbe6..42352807b 100644 --- a/Source/plrmsg.cpp +++ b/Source/plrmsg.cpp @@ -31,7 +31,7 @@ void PrintChatMessage(const Surface &out, int x, int y, int width, char *text, U if (text[i] == '\n') text[i] = ' '; } - WordWrapGameString(text, width); + WordWrapString(text, width); DrawString(out, text, { { x, y }, { width, 0 } }, style, 1, 10); } @@ -109,7 +109,7 @@ void InitPlrMsg() void DrawPlrMsg(const Surface &out) { DWORD x = 10; - DWORD y = 70; + DWORD y = 58; DWORD width = gnScreenWidth - 20; _plrmsg *pMsg; diff --git a/Source/qol/itemlabels.cpp b/Source/qol/itemlabels.cpp index 9917aff59..d6c68e624 100644 --- a/Source/qol/itemlabels.cpp +++ b/Source/qol/itemlabels.cpp @@ -88,7 +88,7 @@ void AddItemToLabelQueue(int id, int x, int y) y *= 2; } x -= nameWidth / 2; - labelQueue.push_back(ItemLabel { id, nameWidth, { x, y }, textOnGround }); + labelQueue.push_back(ItemLabel { id, nameWidth, { x, y - Height }, textOnGround }); } bool IsMouseOverGameArea() @@ -148,7 +148,7 @@ void DrawItemNameLabels(const Surface &out) for (const ItemLabel &label : labelQueue) { Item &item = Items[label.id]; - if (MousePosition.x >= label.pos.x && MousePosition.x < label.pos.x + label.width && MousePosition.y >= label.pos.y - Height + MarginY && MousePosition.y < label.pos.y + MarginY) { + if (MousePosition.x >= label.pos.x && MousePosition.x < label.pos.x + label.width && MousePosition.y >= label.pos.y + MarginY && MousePosition.y < label.pos.y + MarginY + Height) { if (!gmenu_is_active() && PauseMode == 0 && !MyPlayerIsDead && IsMouseOverGameArea()) { isLabelHighlighted = true; cursPosition = item.position; @@ -156,9 +156,9 @@ void DrawItemNameLabels(const Surface &out) } } if (pcursitem == label.id) - FillRect(out, label.pos.x, label.pos.y - Height + MarginY, label.width, Height, PAL8_BLUE + 6); + FillRect(out, label.pos.x, label.pos.y + MarginY, label.width, Height, PAL8_BLUE + 6); else - DrawHalfTransparentRectTo(out, label.pos.x, label.pos.y - Height + MarginY, label.width, Height); + DrawHalfTransparentRectTo(out, label.pos.x, label.pos.y + MarginY, label.width, Height); DrawString(out, label.text, { { label.pos.x + MarginX, label.pos.y }, { label.width, Height } }, item.getTextColor()); } labelQueue.clear(); diff --git a/Source/qol/monhealthbar.cpp b/Source/qol/monhealthbar.cpp index c72247e25..36e67b43e 100644 --- a/Source/qol/monhealthbar.cpp +++ b/Source/qol/monhealthbar.cpp @@ -109,14 +109,16 @@ void DrawMonsterHealthBar(const Surface &out) UnsafeDrawVerticalLine(out, { position.x + width - border - 1, position.y + border + 1 }, borderHeight, borderColor); } - int barLabelY = position.y + 10 + (height - 11) / 2; - DrawString(out, monster.mName, { position.x - 1, barLabelY + 1, width, height }, UiFlags::AlignCenter | UiFlags::ColorBlack); - UiFlags style = UiFlags::ColorSilver; + int barLabelY = position.y; + UiFlags style = UiFlags::AlignCenter | UiFlags::VerticalCenter; + DrawString(out, monster.mName, { position + Displacement { -1, 1 }, width, height }, style | UiFlags::ColorBlack); if (monster._uniqtype != 0) - style = UiFlags::ColorGold; + style |= UiFlags::ColorGold; else if (monster.leader != 0) - style = UiFlags::ColorBlue; - DrawString(out, monster.mName, { position.x, barLabelY, width, height }, UiFlags::AlignCenter | style); + style |= UiFlags::ColorBlue; + else + style |= UiFlags::ColorSilver; + DrawString(out, monster.mName, { position, width, height }, style); if (monster._uniqtype != 0 || MonsterKillCounts[monster.MType->mtype] >= 15) { monster_resistance immunes[] = { IMMUNE_MAGIC, IMMUNE_FIRE, IMMUNE_LIGHTNING }; diff --git a/Source/quests.cpp b/Source/quests.cpp index b0f06d4ae..ce9f50b28 100644 --- a/Source/quests.cpp +++ b/Source/quests.cpp @@ -276,14 +276,13 @@ int QuestLogMouseToEntry() void PrintQLString(const Surface &out, int x, int y, const char *str, bool marked, bool disabled = false) { int width = GetLineWidth(str); - int sx = x + std::max((257 - width) / 2, 0); - int sy = y + lineHeight; //seems that DrawString y is the text base line -> so add a lines height + x += std::max((257 - width) / 2, 0); if (marked) { - CelDrawTo(out, GetPanelPosition(UiPanels::Quest, { sx - 20, sy + 1 }), *pSPentSpn2Cels, PentSpn2Spin()); + CelDrawTo(out, GetPanelPosition(UiPanels::Quest, { x - 20, y + 13 }), *pSPentSpn2Cels, PentSpn2Spin()); } - DrawString(out, str, { GetPanelPosition(UiPanels::Quest, { sx, sy }), { 257, 0 } }, disabled ? UiFlags::ColorGold : UiFlags::ColorSilver); + DrawString(out, str, { GetPanelPosition(UiPanels::Quest, { x, y }), { 257, 0 } }, disabled ? UiFlags::ColorGold : UiFlags::ColorSilver); if (marked) { - CelDrawTo(out, GetPanelPosition(UiPanels::Quest, { sx + width + 7, sy + 1 }), *pSPentSpn2Cels, PentSpn2Spin()); + CelDrawTo(out, GetPanelPosition(UiPanels::Quest, { x + width + 7, y + 13 }), *pSPentSpn2Cels, PentSpn2Spin()); } } diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index 99b0ff5cc..876c27f03 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -1206,21 +1206,15 @@ void DrawView(const Surface &out, Point startPosition) for (auto m : DebugCoordsMap) { Point dunCoords = { m.first % MAXDUNX, m.first / MAXDUNX }; Point pixelCoords = m.second; - Displacement ver = { 0, -TILE_HEIGHT / 2 }; - Displacement hor = { TILE_WIDTH / 2, 0 }; - if (!zoomflag) { + if (!zoomflag) pixelCoords *= 2; - hor *= 2; - ver *= 2; - } - Point center = pixelCoords + hor + ver; if (DebugCoords || (DebugCursorCoords && dunCoords == cursPosition)) { char coordstr[10]; sprintf(coordstr, "%d:%d", dunCoords.x, dunCoords.y); - int textWidth = GetLineWidth(coordstr); - int textHeight = 12; - Point position = center + Displacement { -textWidth / 2, textHeight / 2 }; - DrawString(out, coordstr, { position, { textWidth, textHeight } }, UiFlags::ColorRed); + Size tileSize = { TILE_WIDTH, TILE_HEIGHT }; + if (!zoomflag) + tileSize *= 2; + DrawString(out, coordstr, { pixelCoords - Displacement { 0, tileSize.height }, tileSize }, UiFlags::ColorRed | UiFlags::AlignCenter | UiFlags::VerticalCenter); } if (DebugGrid) { auto DrawLine = [&out](Point from, Point to, uint8_t col) { @@ -1236,11 +1230,19 @@ void DrawView(const Surface &out, Point startPosition) out.SetPixel({ (int)sx, (int)sy }, col); }; + Displacement hor = { TILE_WIDTH / 2, 0 }; + Displacement ver = { 0, TILE_HEIGHT / 2 }; + if (!zoomflag) { + hor *= 2; + ver *= 2; + } + Point center = pixelCoords + hor - ver; + uint8_t col = PAL16_BEIGE; - DrawLine(center - hor, center - ver, col); - DrawLine(center + hor, center - ver, col); DrawLine(center - hor, center + ver, col); DrawLine(center + hor, center + ver, col); + DrawLine(center - hor, center - ver, col); + DrawLine(center + hor, center - ver, col); } } } @@ -1321,7 +1323,7 @@ void DrawFPS(const Surface &out) frameend = 0; } snprintf(string, 12, "%i FPS", framerate); - DrawString(out, string, Point { 8, 65 }, UiFlags::ColorRed); + DrawString(out, string, Point { 8, 53 }, UiFlags::ColorRed); } /** diff --git a/Source/stores.cpp b/Source/stores.cpp index e0127653a..e9273712e 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -24,6 +24,7 @@ namespace devilution { Item golditem; +std::optional pSPentSpn2Cels; std::optional pSTextBoxCels; std::optional pSTextSlidCels; @@ -2163,13 +2164,13 @@ void DrawSelector(const Surface &out, const Rectangle &rect, const char *text, U if (HasAnyOf(flags, UiFlags::AlignCenter)) x1 += (rect.size.width - lineWidth) / 2; - CelDrawTo(out, { x1, rect.position.y + 1 }, *pSPentSpn2Cels, PentSpn2Spin()); + CelDrawTo(out, { x1, rect.position.y + 13 }, *pSPentSpn2Cels, PentSpn2Spin()); int x2 = rect.position.x + rect.size.width + 5; if (HasAnyOf(flags, UiFlags::AlignCenter)) x2 = rect.position.x + (rect.size.width - lineWidth) / 2 + lineWidth + 5; - CelDrawTo(out, { x2, rect.position.y + 1 }, *pSPentSpn2Cels, PentSpn2Spin()); + CelDrawTo(out, { x2, rect.position.y + 13 }, *pSPentSpn2Cels, PentSpn2Spin()); } } // namespace @@ -2199,6 +2200,7 @@ void AddStoreHoldRepair(Item *itm, int8_t i) void InitStores() { + pSPentSpn2Cels = LoadCel("Data\\PentSpn2.CEL", 12); pSTextBoxCels = LoadCel("Data\\TextBox2.CEL", 271); pSTextSlidCels = LoadCel("Data\\TextSlid.CEL", 12); ClearSText(0, STORE_LINES); @@ -2250,7 +2252,7 @@ void PrintSString(const Surface &out, int margin, int line, const char *text, Ui sx += 320; } - int sy = UI_OFFSET_Y + 44 + line * 12 + stext[line]._syoff; + int sy = UI_OFFSET_Y + 32 + line * 12 + stext[line]._syoff; int width = stextsize ? 575 : 255; if (stextscrl && line >= 4 && line <= 20) {