Browse Source

Improve DiabloMsg handling

1. Simplified implementation.
2. Now adjusts the box size to fit the content (e.g. when wrapping
   failed or when there are too many lines).
pull/6701/head
Gleb Mazovetskiy 2 years ago
parent
commit
88bbf4f913
  1. 2
      Source/control.cpp
  2. 2
      Source/debug.cpp
  3. 2
      Source/diablo.cpp
  4. 76
      Source/diablo_msg.cpp
  5. 4
      Source/engine/render/scrollrt.cpp
  6. 2
      Source/gamemenu.cpp
  7. 2
      Source/objects.cpp
  8. 4
      Source/panels/info_box.hpp
  9. 2
      Source/qol/chatlog.cpp

2
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"

2
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"

2
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"

76
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<MessageEntry> DiabloMessages;
uint32_t msgStartTime = 0;
uint32_t msgStartTime;
std::vector<std::string> 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<int>((TextLines.size() * LineHeight()) + 42));
msgStartTime = SDL_GetTicks();
LineHeight = GetLineHeight(text, GameFont12);
OuterHeight = static_cast<int>((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<int>(out.h(), OuterHeight);
const int outerWidth = std::min<int>(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<int>(TextLines.size())) / 2;
const int textX = innerXBegin + textPaddingX;
int textY = innerYBegin + (innerHeight - LineHeight * static_cast<int>(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();
}
}

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

2
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"

2
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"

4
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`.
*/

2
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"

Loading…
Cancel
Save