Decompile 7 functions in Source/UI/Text/NavigationLink.cpp, Source/UI/Text/CreateLineInfo.h, ...
Batch #7455 by gordaoprogramas: 0 byte-identical, 7 confirmed by peer review. - fn_10433 CCreateLineInfo::CCreateLineInfo: logic confirmed by peer review - fn_10451 CCreateLineInfo::LayoutEmotion: logic confirmed by peer review - fn_10452 CCreateLineInfo::LayoutLink: logic confirmed by peer review - fn_10453 CCreateLineInfo::LayoutItemImage: logic confirmed by peer review - fn_10454 CCreateLineInfo::LayoutText: logic confirmed by peer review - fn_10455 CCreateLineInfo::BuildWindows: logic confirmed by peer review - fn_10467 CCreateLineInfo::CreateTextWindow: logic confirmed by peer review Peer-reviewed-by: eAthena, aDw Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes).
This commit is contained in:
parent
86a77882dc
commit
f8ccc7e2e0
3 changed files with 305 additions and 0 deletions
|
|
@ -16,6 +16,7 @@ class UITextButton : public UIButton {
|
|||
friend class UIEditCtrl3;
|
||||
friend class UIAchTracingWnd;
|
||||
friend class UIAchSummaryWnd;
|
||||
friend class CCreateLineInfo;
|
||||
|
||||
public:
|
||||
friend void OpenTextButtonLink(UITextButton* button);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
class FontCache;
|
||||
class UIWindow;
|
||||
class UITextButton;
|
||||
struct TextLocale;
|
||||
struct tagSIZE;
|
||||
|
||||
|
|
@ -47,6 +48,11 @@ struct LineTextSegment {
|
|||
/* 002C */ int unknown_002C;
|
||||
};
|
||||
|
||||
struct LineFontFlags {
|
||||
/* 0000 */ bool bold;
|
||||
/* 0001 */ bool italic;
|
||||
};
|
||||
|
||||
struct LineFontState {
|
||||
/* 0000 */ int fontHeight;
|
||||
/* 0004 */ std::uint32_t color;
|
||||
|
|
@ -88,6 +94,10 @@ public:
|
|||
/* 0070 */ std::vector<std::vector<UIWindow*>> m_lines;
|
||||
/* 007C */ int m_height;
|
||||
|
||||
CCreateLineInfo(
|
||||
UIWindow* parent, const char* text, int width, int lineSpacing, std::uint32_t color, int fontHeight, LineFontFlags flags, bool unknown0028,
|
||||
int unknown002C, bool unknown0030, int unknown0034, unsigned char align
|
||||
);
|
||||
virtual ~CCreateLineInfo();
|
||||
|
||||
void AppendText(const std::string& text);
|
||||
|
|
@ -105,6 +115,14 @@ public:
|
|||
int ParseChar(int index);
|
||||
int ParseTag(int index);
|
||||
void ArrangeLines();
|
||||
void BuildWindows();
|
||||
void Rebuild();
|
||||
int LayoutEmotion(int x, const std::string& text);
|
||||
int LayoutLink(int x, std::string text, int type, LineTextStyle style);
|
||||
int LayoutItemImage(int x, const std::string& text);
|
||||
int LayoutText(int x, std::string text, LineTextStyle style);
|
||||
UITextButton* CreateLinkWindow(const std::string& text, const std::vector<std::string>& parts, int type, LineTextStyle style);
|
||||
UIWindow* CreateTextWindow(std::string text, const LineTextStyle& style);
|
||||
|
||||
private:
|
||||
void CloseFont(std::string tag);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "Client/Input/InputCharset.h"
|
||||
#include "Client/Mode/ModeTooltip.h"
|
||||
#include "Client/Session.h"
|
||||
#include "Contents/CashEmotionMgr.h"
|
||||
#include "Contents/Configuration/ServiceConfiguration.h"
|
||||
#include "Contents/Items/ItemDescription.h"
|
||||
#include "Contents/Items/ItemInfo.h"
|
||||
|
|
@ -40,14 +41,23 @@
|
|||
#include "UI/Dialogs/UITipboxWnd.h"
|
||||
#include "UI/Text/ColoredText.h"
|
||||
#include "UI/Text/CreateLineInfo.h"
|
||||
#include "UI/Text/TextMarkup.h"
|
||||
#include "UI/Window/UINewSelectCharWnd.h"
|
||||
#include "UI/Window/UIWindow.h"
|
||||
#include "UI/Window/UIWindowMgr.h"
|
||||
#include "Utility/Text/StringUtil.h"
|
||||
#include "Utility/Text/TextEscapes.h"
|
||||
#include "Utility/Text/TextTokens.h"
|
||||
|
||||
namespace LineCutter {
|
||||
class UIText : public UIWindow {
|
||||
public:
|
||||
// INLINED
|
||||
explicit UIText(UIWindowContext& windows)
|
||||
: UIWindow(windows, 0), m_color(0), m_fontHeight(12), m_bold(0), m_italic(0), m_outlined(0), m_outlineColor(0xFFFFFF), m_shadowed(0),
|
||||
m_shadowColor(0xFFFFFF) {
|
||||
}
|
||||
|
||||
void Paint() override;
|
||||
void Slot25(int x, int y) override;
|
||||
void Slot26(int x, int y) override;
|
||||
|
|
@ -72,6 +82,13 @@ namespace LineCutter {
|
|||
|
||||
class UIEmotion : public UIWindow {
|
||||
public:
|
||||
// INLINED
|
||||
UIEmotion(UIWindowContext& windows, const char* sprite, const char* action, unsigned animation, unsigned maxLoops)
|
||||
: UIWindow(windows, 0), m_animation(animation), m_frame(0), m_maxLoops(maxLoops),
|
||||
m_sprite(static_cast<CSprRes*>(ResourceMgr::Instance().Load(sprite))), m_action(static_cast<CActRes*>(ResourceMgr::Instance().Load(action))),
|
||||
m_startTime(timeGetTime()), m_loops(1) {
|
||||
}
|
||||
|
||||
void Slot19() override;
|
||||
void Paint() override;
|
||||
|
||||
|
|
@ -87,6 +104,11 @@ protected:
|
|||
|
||||
class UIItemImage : public UIWindow {
|
||||
public:
|
||||
// INLINED
|
||||
UIItemImage(UIWindowContext& windows, const std::string& itemId) : UIWindow(windows, 0), m_itemId(itemId) {
|
||||
this->m_clip = 1;
|
||||
}
|
||||
|
||||
void Paint() override;
|
||||
void Slot28(int x, int y) override;
|
||||
void Slot32(int x, int y) override;
|
||||
|
|
@ -640,6 +662,36 @@ void UIItemImage::Paint() {
|
|||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00836970
|
||||
// FUNCTION: fn_10433
|
||||
CCreateLineInfo::CCreateLineInfo(
|
||||
UIWindow* parent, const char* text, int width, int lineSpacing, std::uint32_t color, int fontHeight, LineFontFlags flags, bool unknown0028,
|
||||
int unknown002C, bool unknown0030, int unknown0034, unsigned char align
|
||||
)
|
||||
: m_align(align), m_newSegment(true), m_height(0) {
|
||||
if (parent && (this->m_parent = parent, text)) {
|
||||
this->m_text.assign(text, std::strlen(text));
|
||||
this->m_width = width;
|
||||
this->m_lineSpacing = lineSpacing;
|
||||
this->m_defaultColor = color;
|
||||
this->m_color = color;
|
||||
this->m_defaultFontHeight = fontHeight;
|
||||
this->m_fontHeight = fontHeight;
|
||||
this->m_bold = flags.bold;
|
||||
this->m_italic = flags.italic;
|
||||
this->unknown_0030 = unknown0030;
|
||||
this->unknown_0034 = unknown0034;
|
||||
this->unknown_0028 = unknown0028;
|
||||
this->unknown_002C = unknown002C;
|
||||
|
||||
if (!s_fontStackCache.empty()) {
|
||||
this->m_fontStack.swap(s_fontStackCache);
|
||||
}
|
||||
|
||||
this->Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00837390
|
||||
// FUNCTION: fn_10441
|
||||
CCreateLineInfo::~CCreateLineInfo() {
|
||||
|
|
@ -685,6 +737,209 @@ void CCreateLineInfo::AddWindow(UIWindow* window) {
|
|||
this->m_lines.back().push_back(window);
|
||||
}
|
||||
|
||||
// OFFSET: 0x00837BC0
|
||||
// FUNCTION: fn_10451
|
||||
int CCreateLineInfo::LayoutEmotion(int x, const std::string& text) {
|
||||
int group = 0;
|
||||
int id = -1;
|
||||
std::cmatch match;
|
||||
|
||||
if (!std::regex_search(text.c_str(), text.c_str() + text.size(), match, std::regex("^\\^e\\[(\\d{1,3})\\](\\[\\d\\])*"))) {
|
||||
if (!std::regex_search(text.c_str(), text.c_str() + text.size(), match, std::regex("^\\^e\\[(\\d{1,3}\\s*,\\s*\\d{1,3})\\](\\[\\d\\])*"))) {
|
||||
return x;
|
||||
}
|
||||
|
||||
const std::vector<std::string> parts = Split(match[1].str(), ",");
|
||||
if (parts.size() == 2) {
|
||||
group = std::stoi(parts[0]);
|
||||
id = std::stoi(parts[1]);
|
||||
}
|
||||
} else {
|
||||
id = std::stoi(match[1].str());
|
||||
}
|
||||
|
||||
if (id >= 0) {
|
||||
int loops = 0;
|
||||
if (match.size() > 2 && match[2].matched) {
|
||||
const std::string tail = match[2].str();
|
||||
std::cmatch loopMatch;
|
||||
if (std::regex_search(tail.c_str(), tail.c_str() + tail.size(), loopMatch, std::regex("^\\[(\\d)\\]"))) {
|
||||
loops = std::atoi(loopMatch[1].str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
CashEmotionData* data = g_cashEmotionMgr->GetEmotionData(group, id);
|
||||
if (data) {
|
||||
const char* sprite = g_cashEmotionMgr->GetSprFileName(data->actId);
|
||||
if (sprite) {
|
||||
const char* action = g_cashEmotionMgr->GetPackName(data->sprId);
|
||||
if (action) {
|
||||
UIEmotion* emotion = new UIEmotion(*reinterpret_cast<UIWindowContext*>(nullptr), sprite, action, data->unknown_0020, loops);
|
||||
emotion->SetSize(50, 50);
|
||||
emotion->Invalidate();
|
||||
if (this->m_width < emotion->geometry.width + x) {
|
||||
this->NewLine();
|
||||
this->AddWindow(emotion);
|
||||
x = emotion->geometry.width;
|
||||
} else {
|
||||
this->AddWindow(emotion);
|
||||
x += emotion->geometry.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00838130
|
||||
// FUNCTION: fn_10452
|
||||
int CCreateLineInfo::LayoutLink(int x, std::string text, int type, LineTextStyle style) {
|
||||
const std::tuple<bool, std::string, std::string> info = SplitLinkInfo(text, type);
|
||||
if (std::get<0>(info)) {
|
||||
std::string display = std::get<1>(info);
|
||||
if (this->m_parent) {
|
||||
display = RemoveTextColors(display.c_str(), 0);
|
||||
}
|
||||
|
||||
const std::vector<std::string> parts = SplitString(std::get<2>(info), ",");
|
||||
const int width = MeasureText(this->m_parent, display, style).cx;
|
||||
if (width > this->m_width) {
|
||||
const std::vector<std::string> lines = SplitLines(this->m_parent, display, style, this->m_width);
|
||||
for (auto line = lines.begin(); line != lines.end(); ++line) {
|
||||
this->NewLine();
|
||||
x = 0;
|
||||
UITextButton* button = this->CreateLinkWindow(*line, parts, type, style);
|
||||
if (button) {
|
||||
this->AddWindow(button);
|
||||
x = button->geometry.width;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (x + width > this->m_width) {
|
||||
this->NewLine();
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (!display.empty() && !parts.empty()) {
|
||||
UITextButton* button = this->CreateLinkWindow(display, parts, type, style);
|
||||
this->AddWindow(button);
|
||||
x += button->geometry.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00838780
|
||||
// FUNCTION: fn_10453
|
||||
int CCreateLineInfo::LayoutItemImage(int x, const std::string& text) {
|
||||
std::cmatch match;
|
||||
|
||||
if (std::regex_search(text.c_str(), text.c_str() + text.size(), match, std::regex("^\\^i\\[(\\d{1,7})\\]*"))) {
|
||||
const std::string itemId = match[1].str();
|
||||
UIItemImage* image = new (std::nothrow) UIItemImage(*reinterpret_cast<UIWindowContext*>(nullptr), itemId);
|
||||
if (image) {
|
||||
image->SetSize(25, 25);
|
||||
image->Invalidate();
|
||||
if (this->m_width < image->geometry.width + x) {
|
||||
this->NewLine();
|
||||
this->AddWindow(image);
|
||||
x = image->geometry.width;
|
||||
} else {
|
||||
this->AddWindow(image);
|
||||
x += image->geometry.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// OFFSET: 0x008389A0
|
||||
// FUNCTION: fn_10454
|
||||
int CCreateLineInfo::LayoutText(int x, std::string text, LineTextStyle style) {
|
||||
const int width = MeasureText(this->m_parent, text, style).cx;
|
||||
if (this->m_width < width) {
|
||||
const std::string first = FitText(this->m_parent, text, style, this->m_width - x);
|
||||
UIWindow* last = this->CreateTextWindow(first, style);
|
||||
if (last) {
|
||||
this->AddWindow(last);
|
||||
}
|
||||
|
||||
const std::string rest = text.substr(first.size(), text.size() - first.size());
|
||||
const std::vector<std::string> lines = SplitLines(this->m_parent, rest, style, this->m_width);
|
||||
if (!lines.empty()) {
|
||||
x = 0;
|
||||
}
|
||||
|
||||
for (auto line = lines.begin(); line != lines.end(); ++line) {
|
||||
this->NewLine();
|
||||
last = this->CreateTextWindow(*line, style);
|
||||
if (last) {
|
||||
this->AddWindow(last);
|
||||
}
|
||||
}
|
||||
|
||||
if (last) {
|
||||
x += last->geometry.width;
|
||||
}
|
||||
} else {
|
||||
if (this->m_width < x + width) {
|
||||
this->NewLine();
|
||||
x = 0;
|
||||
}
|
||||
|
||||
UIWindow* window = this->CreateTextWindow(text, style);
|
||||
if (window) {
|
||||
this->AddWindow(window);
|
||||
x += window->geometry.width;
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00838D40
|
||||
// FUNCTION: fn_10455
|
||||
void CCreateLineInfo::BuildWindows() {
|
||||
int x = 0;
|
||||
|
||||
for (auto segment = this->m_segments.begin(); segment != this->m_segments.end(); ++segment) {
|
||||
const std::string text = segment->text;
|
||||
switch (segment->type) {
|
||||
case LINE_SEGMENT_URL:
|
||||
case LINE_SEGMENT_NAVI:
|
||||
case LINE_SEGMENT_ITEM:
|
||||
case LINE_SEGMENT_TIPBOX:
|
||||
case LINE_SEGMENT_QUEST:
|
||||
x = this->LayoutLink(x, text, segment->type, segment->style);
|
||||
break;
|
||||
case LINE_SEGMENT_MESSAGE:
|
||||
x = this->LayoutText(x, g_navigationLinkParser->ExpandMessages(text), segment->style);
|
||||
break;
|
||||
case LINE_SEGMENT_EMOTION:
|
||||
x = this->LayoutEmotion(x, text);
|
||||
break;
|
||||
case LINE_SEGMENT_ITEM_IMAGE:
|
||||
x = this->LayoutItemImage(x, text);
|
||||
break;
|
||||
case LINE_SEGMENT_TEXT:
|
||||
if (text == "\n") {
|
||||
this->NewLine();
|
||||
x = 0;
|
||||
} else {
|
||||
x = this->LayoutText(x, text, segment->style);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x008392C0
|
||||
|
||||
// OFFSET: 0x00839310
|
||||
// FUNCTION: fn_10457
|
||||
std::size_t CCreateLineInfo::FindTag(std::string text, std::string keyword, bool caseSensitive) {
|
||||
|
|
@ -830,6 +1085,37 @@ int CCreateLineInfo::AddLink(int index, int type) {
|
|||
return index;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0083A5F0
|
||||
|
||||
// OFFSET: 0x0083ACF0
|
||||
// FUNCTION: fn_10467
|
||||
UIWindow* CCreateLineInfo::CreateTextWindow(std::string text, const LineTextStyle& style) {
|
||||
if (text.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const tagSIZE size = MeasureText(this->m_parent, text, style);
|
||||
LineCutter::UIText* window = new LineCutter::UIText(*reinterpret_cast<UIWindowContext*>(nullptr));
|
||||
window->SetSize(size.cx, size.cy);
|
||||
window->m_text = text;
|
||||
window->m_outlineColor = this->unknown_002C;
|
||||
window->m_shadowed = this->unknown_0030;
|
||||
window->m_color = style.color;
|
||||
window->m_fontHeight = style.fontHeight;
|
||||
window->m_bold = style.bold;
|
||||
window->m_italic = style.italic;
|
||||
window->m_outlined = this->unknown_0028;
|
||||
window->m_shadowColor = this->unknown_0034;
|
||||
if (window->m_outlined == 1) {
|
||||
const TextLocale locale = {};
|
||||
const int textWidth = window->TextWidth(g_fontCache, locale, window->m_text.c_str(), 0, 0, style.fontHeight, style.bold, style.italic);
|
||||
window->Resize(textWidth + 2, style.fontHeight + 2);
|
||||
}
|
||||
|
||||
window->Invalidate();
|
||||
return window;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0083AA40
|
||||
// FUNCTION: fn_10465
|
||||
void CCreateLineInfo::NewLine() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue