diff --git a/Source/control.cpp b/Source/control.cpp index a9dabb437..5ecc19555 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -18,13 +18,13 @@ #include "controls/modifier_hints.h" #include "controls/plrctrls.h" #include "cursor.h" +#include "diablo_msg.hpp" #include "engine/backbuffer_state.hpp" #include "engine/clx_sprite.hpp" #include "engine/load_cel.hpp" #include "engine/render/clx_render.hpp" #include "engine/render/text_render.hpp" #include "engine/trn.hpp" -#include "diablo_msg.hpp" #include "gamemenu.h" #include "init.h" #include "inv.h" diff --git a/Source/debug.cpp b/Source/debug.cpp index 772a1a6c4..cd37f188a 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -15,11 +15,11 @@ #include "automap.h" #include "control.h" #include "cursor.h" +#include "diablo_msg.hpp" #include "engine/backbuffer_state.hpp" #include "engine/events.hpp" #include "engine/load_cel.hpp" #include "engine/point.hpp" -#include "diablo_msg.hpp" #include "inv.h" #include "levels/setmaps.h" #include "lighting.h" diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 92af2e511..9bfe6743f 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -23,6 +23,7 @@ #include "controls/plrctrls.h" #include "controls/remap_keyboard.h" #include "diablo.h" +#include "diablo_msg.hpp" #include "discord/discord.h" #include "doom.h" #include "encrypt.h" @@ -35,7 +36,6 @@ #include "engine/load_file.hpp" #include "engine/random.hpp" #include "engine/sound.h" -#include "diablo_msg.hpp" #include "gamemenu.h" #include "gmenu.h" #include "help.h" diff --git a/Source/diablo_msg.cpp b/Source/diablo_msg.cpp index bf8e537a4..2bee54a39 100644 --- a/Source/diablo_msg.cpp +++ b/Source/diablo_msg.cpp @@ -11,14 +11,13 @@ #include "diablo_msg.hpp" #include "DiabloUI/ui_flags.hpp" -#include "control.h" #include "engine/clx_sprite.hpp" #include "engine/render/clx_render.hpp" #include "engine/render/text_render.hpp" #include "panels/info_box.hpp" #include "utils/algorithm/container.hpp" #include "utils/language.h" -#include "utils/timer.hpp" +#include "utils/str_split.hpp" namespace devilution { @@ -30,32 +29,29 @@ struct MessageEntry { }; std::deque DiabloMessages; -uint32_t msgStartTime = 0; +uint32_t msgStartTime; std::vector TextLines; -int OuterHeight = 54; -const int LineWidth = 418; +int OuterHeight; +int LineWidth; +int LineHeight; -int LineHeight() -{ - return IsSmallFontTall() ? 18 : 12; -} - -void InitNextLines() +void InitDiabloMsg() { TextLines.clear(); + if (DiabloMessages.empty()) + return; - const std::string paragraphs = WordWrapString(DiabloMessages.front().text, LineWidth, GameFont12, 1); - - size_t previous = 0; - while (true) { - const size_t next = paragraphs.find('\n', previous); - TextLines.emplace_back(paragraphs.substr(previous, next - previous)); - if (next == std::string::npos) - break; - previous = next + 1; + LineWidth = 418; + const std::string_view text = DiabloMessages.front().text; + const std::string wrapped = WordWrapString(text, LineWidth, GameFont12); + for (const std::string_view line : SplitByChar(wrapped, '\n')) { + LineWidth = std::max(LineWidth, GetLineWidth(text, GameFont12)); + TextLines.emplace_back(line); } - OuterHeight = std::max(54, static_cast((TextLines.size() * LineHeight()) + 42)); + msgStartTime = SDL_GetTicks(); + LineHeight = GetLineHeight(text, GameFont12); + OuterHeight = static_cast((TextLines.size()) * LineHeight) + 42; } } // namespace @@ -126,17 +122,13 @@ void InitDiabloMsg(diablo_message e, uint32_t duration /*= 3500*/) void InitDiabloMsg(std::string_view msg, uint32_t duration /*= 3500*/) { - if (DiabloMessages.size() >= MAX_SEND_STR_LEN) - return; - if (c_find_if(DiabloMessages, [&msg](const MessageEntry &entry) { return entry.text == msg; }) != DiabloMessages.end()) return; DiabloMessages.push_back({ std::string(msg), duration }); if (DiabloMessages.size() == 1) { - InitNextLines(); - msgStartTime = SDL_GetTicks(); + InitDiabloMsg(); } } @@ -149,10 +141,7 @@ void CancelCurrentDiabloMsg() { if (!DiabloMessages.empty()) { DiabloMessages.pop_front(); - if (!DiabloMessages.empty()) { - InitNextLines(); - msgStartTime = SDL_GetTicks(); - } + InitDiabloMsg(); } } @@ -176,14 +165,16 @@ void DrawDiabloMsg(const Surface &out) const int borderPartWidth = 12; const int borderPartHeight = 12; - const int outerHeight = OuterHeight; - const int outerWidth = 429; + const int textPaddingX = 5; const int borderThickness = 3; + + const int outerHeight = std::min(out.h(), OuterHeight); + const int outerWidth = std::min(out.w(), LineWidth + 2 * borderThickness + textPaddingX); const int innerWidth = outerWidth - 2 * borderThickness; + const int lineWidth = innerWidth - textPaddingX; const int innerHeight = outerHeight - 2 * borderThickness; - const Point uiRectanglePosition = GetUIRectangle().position; - const Point topLeft { uiRectanglePosition.x + 101, ((gnScreenHeight - GetMainPanel().size.height - outerHeight) / 2) - borderThickness }; + const Point topLeft { (out.w() - outerWidth) / 2, (out.h() - outerHeight) / 2 }; const int innerXBegin = topLeft.x + borderThickness; const int innerXEnd = innerXBegin + innerWidth; @@ -210,25 +201,20 @@ void DrawDiabloMsg(const Surface &out) } DrawHalfTransparentRectTo(out, innerXBegin, innerYBegin, innerWidth, innerHeight); - const int lineHeight = LineHeight(); - const int textX = innerXBegin + 5; - int textY = innerYBegin + (innerHeight - lineHeight * static_cast(TextLines.size())) / 2; + const int textX = innerXBegin + textPaddingX; + int textY = innerYBegin + (innerHeight - LineHeight * static_cast(TextLines.size())) / 2; for (const std::string &line : TextLines) { - DrawString(out, line, { { textX, textY }, { LineWidth, lineHeight } }, UiFlags::AlignCenter, 1, lineHeight); - textY += lineHeight; + DrawString(out, line, { { textX, textY }, { lineWidth, LineHeight } }, UiFlags::AlignCenter, 1, LineHeight); + textY += LineHeight; } // Calculate the time the current message has been displayed - const uint32_t currentTime = SDL_GetTicks(); - const uint32_t messageElapsedTime = currentTime - msgStartTime; + const uint32_t messageElapsedTime = SDL_GetTicks() - msgStartTime; // Check if the current message's duration has passed if (!DiabloMessages.empty() && messageElapsedTime >= DiabloMessages.front().duration) { DiabloMessages.pop_front(); - if (!DiabloMessages.empty()) { - InitNextLines(); - msgStartTime = currentTime; - } + InitDiabloMsg(); } } diff --git a/Source/engine/render/scrollrt.cpp b/Source/engine/render/scrollrt.cpp index bb6da5e89..cfc52f05e 100644 --- a/Source/engine/render/scrollrt.cpp +++ b/Source/engine/render/scrollrt.cpp @@ -13,6 +13,7 @@ #include "controls/plrctrls.h" #include "cursor.h" #include "dead.h" +#include "diablo_msg.hpp" #include "doom.h" #include "engine/backbuffer_state.hpp" #include "engine/dx.h" @@ -21,7 +22,6 @@ #include "engine/render/text_render.hpp" #include "engine/trn.hpp" #include "engine/world_tile.hpp" -#include "diablo_msg.hpp" #include "gmenu.h" #include "help.h" #include "hwcursor.hpp" @@ -1194,7 +1194,7 @@ void DrawView(const Surface &out, Point startPosition) DrawChatLog(out); } if (IsDiabloMsgAvailable()) { - DrawDiabloMsg(out); + DrawDiabloMsg(out.subregionY(0, out.h() - GetMainPanel().size.height)); } if (MyPlayerIsDead) { RedBack(out); diff --git a/Source/gamemenu.cpp b/Source/gamemenu.cpp index 5ef5dc87d..1f3f60ada 100644 --- a/Source/gamemenu.cpp +++ b/Source/gamemenu.cpp @@ -6,11 +6,11 @@ #include "gamemenu.h" #include "cursor.h" +#include "diablo_msg.hpp" #include "engine/backbuffer_state.hpp" #include "engine/events.hpp" #include "engine/sound.h" #include "engine/sound_defs.hpp" -#include "diablo_msg.hpp" #include "gmenu.h" #include "init.h" #include "loadsave.h" diff --git a/Source/objects.cpp b/Source/objects.cpp index 62cca4ec7..6dbed8763 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -18,12 +18,12 @@ #ifdef _DEBUG #include "debug.h" #endif +#include "diablo_msg.hpp" #include "engine/backbuffer_state.hpp" #include "engine/load_cel.hpp" #include "engine/load_file.hpp" #include "engine/points_in_rectangle_range.hpp" #include "engine/random.hpp" -#include "diablo_msg.hpp" #include "init.h" #include "inv.h" #include "inv_iterators.hpp" diff --git a/Source/panels/info_box.hpp b/Source/panels/info_box.hpp index 3fbf583c2..d74b93992 100644 --- a/Source/panels/info_box.hpp +++ b/Source/panels/info_box.hpp @@ -5,14 +5,14 @@ namespace devilution { /** - * @brief Info box frame + * @brief Fixed size info box frame * * Used in stores, the quest log, the help window, and the unique item info window. */ extern OptionalOwnedClxSpriteList pSTextBoxCels; /** - * @brief Info box scrollbar graphics. + * @brief Dynamic size info box frame and scrollbar graphics. * * Used in stores and `DrawDiabloMsg`. */ diff --git a/Source/qol/chatlog.cpp b/Source/qol/chatlog.cpp index cdf2cd5c1..064c801c3 100644 --- a/Source/qol/chatlog.cpp +++ b/Source/qol/chatlog.cpp @@ -14,9 +14,9 @@ #include "automap.h" #include "chatlog.h" #include "control.h" +#include "diablo_msg.hpp" #include "doom.h" #include "engine/render/text_render.hpp" -#include "diablo_msg.hpp" #include "gamemenu.h" #include "help.h" #include "init.h"