mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2025-12-12 19:22:30 +00:00
chore: initial commit
This commit is contained in:
commit
70b00c5c38
965 changed files with 264882 additions and 0 deletions
919
src/ui/CSimpleFontString.cpp
Normal file
919
src/ui/CSimpleFontString.cpp
Normal file
|
|
@ -0,0 +1,919 @@
|
|||
#include "ui/CSimpleFontString.hpp"
|
||||
#include "gx/Coordinate.hpp"
|
||||
#include "math/Utils.hpp"
|
||||
#include "ui/CFramePoint.hpp"
|
||||
#include "ui/CRenderBatch.hpp"
|
||||
#include "ui/CSimpleFont.hpp"
|
||||
#include "ui/CSimpleFontStringScript.hpp"
|
||||
#include "ui/CSimpleFrame.hpp"
|
||||
#include "ui/CSimpleTop.hpp"
|
||||
#include "ui/FrameXML.hpp"
|
||||
#include "ui/LoadXML.hpp"
|
||||
#include "ui/Types.hpp"
|
||||
#include "ui/Util.hpp"
|
||||
#include "util/CStatus.hpp"
|
||||
#include "util/StringTo.hpp"
|
||||
#include <common/XML.hpp>
|
||||
#include <storm/String.hpp>
|
||||
|
||||
int32_t CSimpleFontString::s_count;
|
||||
int32_t CSimpleFontString::s_metatable;
|
||||
int32_t CSimpleFontString::s_objectType;
|
||||
|
||||
void CSimpleFontString::CreateScriptMetaTable() {
|
||||
lua_State* L = FrameScript_GetContext();
|
||||
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleFontString::RegisterScriptMethods);
|
||||
CSimpleFontString::s_metatable = ref;
|
||||
}
|
||||
|
||||
int32_t CSimpleFontString::GetObjectType() {
|
||||
if (!CSimpleFontString::s_objectType) {
|
||||
CSimpleFontString::s_objectType = ++FrameScript_Object::s_objectTypes;
|
||||
}
|
||||
|
||||
return CSimpleFontString::s_objectType;
|
||||
}
|
||||
|
||||
void CSimpleFontString::RegisterScriptMethods(lua_State* L) {
|
||||
CScriptRegion::RegisterScriptMethods(L);
|
||||
FrameScript_Object::FillScriptMethodTable(L, SimpleFontStringMethods, NUM_SIMPLE_FONT_STRING_SCRIPT_METHODS);
|
||||
}
|
||||
|
||||
CSimpleFontString::CSimpleFontString(CSimpleFrame* frame, uint32_t drawlayer, int32_t show) : CSimpleRegion(frame, drawlayer, show) {
|
||||
this->m_maxLines = 0;
|
||||
this->m_unk12b = 1;
|
||||
|
||||
// TODO
|
||||
|
||||
CSimpleFontString::s_count++;
|
||||
}
|
||||
|
||||
CSimpleFontString::~CSimpleFontString() {
|
||||
this->FreeEmbeddedTextures();
|
||||
|
||||
if (this->m_text) {
|
||||
SMemFree(this->m_text, __FILE__, __LINE__, 0x0);
|
||||
this->m_text = nullptr;
|
||||
}
|
||||
|
||||
this->m_fontHeight = 0.0f;
|
||||
|
||||
if (this->m_string) {
|
||||
HandleClose(this->m_string);
|
||||
this->m_string = nullptr;
|
||||
}
|
||||
|
||||
if (this->m_font) {
|
||||
HandleClose(this->m_font);
|
||||
this->m_font = nullptr;
|
||||
}
|
||||
|
||||
CSimpleFontString::s_count--;
|
||||
}
|
||||
|
||||
void CSimpleFontString::AddShadow(const CImVector& shadowColor, const C2Vector& shadowOffset) {
|
||||
auto styleFlags = this->m_styleFlags;
|
||||
|
||||
if (
|
||||
!(styleFlags & 0x100)
|
||||
|| shadowColor != this->m_shadowColor
|
||||
|| this->m_shadowOffset.x != shadowOffset.x
|
||||
|| this->m_shadowOffset.y != shadowOffset.y
|
||||
) {
|
||||
this->m_styleFlags = styleFlags | 0x100;
|
||||
this->m_shadowColor = shadowColor;
|
||||
this->m_shadowOffset = shadowOffset;
|
||||
|
||||
if (this->m_string) {
|
||||
auto shadowColor = this->m_shadowColor;
|
||||
// TODO alpha manipulation
|
||||
|
||||
auto shadowOffset = this->m_shadowOffset;
|
||||
shadowOffset.x *= this->m_layoutScale;
|
||||
shadowOffset.y *= this->m_layoutScale;
|
||||
|
||||
TextBlockAddShadow(this->m_string, shadowColor, shadowOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSimpleFontString::ClearString() {
|
||||
this->m_cachedWidth = 0.0f;
|
||||
this->m_cachedHeight = 0.0f;
|
||||
|
||||
if (this->m_string) {
|
||||
HandleClose(this->m_string);
|
||||
this->m_string = nullptr;
|
||||
}
|
||||
|
||||
this->m_flags &= ~0x1;
|
||||
this->Resize(0);
|
||||
}
|
||||
|
||||
void CSimpleFontString::Draw(CRenderBatch* batch) {
|
||||
if (this->m_font && this->m_text && *this->m_text) {
|
||||
batch->QueueFontString(this);
|
||||
this->DrawEmbeddedTextures(batch);
|
||||
}
|
||||
}
|
||||
|
||||
void CSimpleFontString::DrawEmbeddedTextures(CRenderBatch* batch) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
bool CSimpleFontString::IsA(int32_t type) {
|
||||
return type == CSimpleFontString::s_objectType
|
||||
|| type == CScriptRegion::s_objectType
|
||||
|| type == CScriptObject::s_objectType;
|
||||
}
|
||||
|
||||
void CSimpleFontString::FontObjectUpdated(CSimpleFontStringAttributes& attributes) {
|
||||
attributes.Update(this, this->m_fontableFlags);
|
||||
}
|
||||
|
||||
void CSimpleFontString::FreeEmbeddedTextures() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
const char* CSimpleFontString::GetDisplayText(float width, float height) {
|
||||
static char buffer[8192];
|
||||
|
||||
if (!this->m_text || !*this->m_text) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!this->m_font || width <= 0.0f || /* TODO */ height <= 0.0f) {
|
||||
return this->m_text;
|
||||
}
|
||||
|
||||
auto fontHeight = this->GetFontHeight(true);
|
||||
auto v5 = (CSimpleTop::RoundToPixelHeight(this->m_spacing) + fontHeight) * this->m_layoutScale;
|
||||
|
||||
// TODO
|
||||
|
||||
auto text = this->m_text;
|
||||
auto textLen = SStrLen(text);
|
||||
auto scaledSpacing = this->m_spacing * this->m_layoutScale;
|
||||
auto scaledShadowOffset = this->m_shadowOffset.x * this->m_layoutScale;
|
||||
auto scaledFontHeight = fontHeight * this->m_layoutScale;
|
||||
|
||||
auto maxChars = TextBlockGetMaxCharsWithinWidthAndHeight(
|
||||
this->m_font,
|
||||
text,
|
||||
scaledFontHeight,
|
||||
width,
|
||||
height,
|
||||
textLen,
|
||||
scaledShadowOffset,
|
||||
this->m_layoutScale,
|
||||
scaledSpacing,
|
||||
this->m_styleFlags
|
||||
);
|
||||
|
||||
if (maxChars >= textLen) {
|
||||
return text;
|
||||
}
|
||||
|
||||
SStrCopy(buffer, text, sizeof(buffer));
|
||||
auto end = std::min(textLen, sizeof(buffer) - 4);
|
||||
|
||||
do {
|
||||
if (end) {
|
||||
do {
|
||||
end--;
|
||||
} while (end && (buffer[end] & 0xC0) == 0x80);
|
||||
}
|
||||
|
||||
SStrCopy(&buffer[end], "...", STORM_MAX_STR);
|
||||
|
||||
maxChars = TextBlockGetMaxCharsWithinWidthAndHeight(
|
||||
this->m_font,
|
||||
buffer,
|
||||
scaledFontHeight,
|
||||
width,
|
||||
height,
|
||||
end + 3,
|
||||
scaledShadowOffset,
|
||||
this->m_layoutScale,
|
||||
scaledSpacing,
|
||||
this->m_styleFlags
|
||||
);
|
||||
} while (end && maxChars < end + 3);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
uint32_t CSimpleFontString::GetFontFlags() {
|
||||
if (this->m_font) {
|
||||
return TextBlockGetFontFlags(this->m_font);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float CSimpleFontString::GetFontHeight(bool a2) {
|
||||
float fontHeight = this->m_fontHeight;
|
||||
|
||||
if (a2 && this->m_font && this->m_styleFlags & 0x200) {
|
||||
auto font = TextBlockGetFontPtr(this->m_font);
|
||||
float ndcHeight = GxuFontGetOneToOneHeight(font) / this->m_layoutScale;
|
||||
NDCToDDC(0.0f, ndcHeight, nullptr, &fontHeight);
|
||||
}
|
||||
|
||||
return fontHeight;
|
||||
}
|
||||
|
||||
const char* CSimpleFontString::GetFontName() {
|
||||
return this->m_font
|
||||
? TextBlockGetFontName(this->m_font)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
float CSimpleFontString::GetHeight() {
|
||||
float v2 = CLayoutFrame::GetHeight();
|
||||
float v9 = v2 == 0.0f ? this->GetStringHeight() : v2;
|
||||
|
||||
float v3 = 1.0f / (CoordinateGetAspectCompensation() * 1024.0f);
|
||||
float v4 = NDCToDDCWidth(v3);
|
||||
|
||||
return v9 <= v4 ? v4 : v9;
|
||||
}
|
||||
|
||||
uint32_t CSimpleFontString::GetNumCharsWithinWidth(const char* text, uint32_t textBytes, float maxWidth) {
|
||||
if (!this->m_font) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (textBytes == 0) {
|
||||
textBytes = SStrLen(text);
|
||||
}
|
||||
|
||||
float fontHeight = this->GetFontHeight(true);
|
||||
float shadowWidth = this->m_shadowOffset.x;
|
||||
float extent[4];
|
||||
|
||||
return TextBlockGetMaxCharsWithinWidth(
|
||||
this->m_font,
|
||||
text,
|
||||
fontHeight * this->m_layoutScale,
|
||||
maxWidth * this->m_layoutScale,
|
||||
textBytes,
|
||||
extent,
|
||||
shadowWidth * this->m_layoutScale,
|
||||
this->m_layoutScale,
|
||||
0.0f,
|
||||
this->m_styleFlags
|
||||
);
|
||||
}
|
||||
|
||||
int32_t CSimpleFontString::GetScriptMetaTable() {
|
||||
return CSimpleFontString::s_metatable;
|
||||
}
|
||||
|
||||
float CSimpleFontString::GetStringHeight() {
|
||||
if (this->m_cachedHeight == 0.0f && this->m_font) {
|
||||
float width = CLayoutFrame::GetWidth() * this->m_layoutScale;
|
||||
float height = CLayoutFrame::GetHeight() * this->m_layoutScale;
|
||||
|
||||
const char* displayText = this->GetDisplayText(width, height);
|
||||
if (displayText && *displayText) {
|
||||
float fontHeight = this->GetFontHeight(1) * this->m_layoutScale;
|
||||
C2Vector shadowSize = {
|
||||
this->m_shadowOffset.x * this->m_layoutScale,
|
||||
this->m_shadowOffset.y * this->m_layoutScale
|
||||
};
|
||||
|
||||
this->m_cachedHeight = TextBlockGetWrappedTextHeight(
|
||||
this->m_font,
|
||||
displayText,
|
||||
fontHeight,
|
||||
this->GetWidth() * this->m_layoutScale,
|
||||
shadowSize,
|
||||
this->m_layoutScale,
|
||||
this->m_spacing * this->m_layoutScale,
|
||||
this->m_styleFlags
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return this->m_cachedHeight / this->m_layoutScale;
|
||||
}
|
||||
|
||||
float CSimpleFontString::GetStringWidth() {
|
||||
if (this->m_cachedWidth == 0.0f && this->m_font) {
|
||||
float width = CLayoutFrame::GetWidth() * this->m_layoutScale;
|
||||
float height = CLayoutFrame::GetHeight() * this->m_layoutScale;
|
||||
|
||||
const char* displayText = this->GetDisplayText(width, height);
|
||||
if (displayText && *displayText) {
|
||||
float fontHeight = this->GetFontHeight(1) * this->m_layoutScale;
|
||||
float shadowWidth = this->m_shadowOffset.x * this->m_layoutScale;
|
||||
size_t displayTextLength = SStrLen(displayText);
|
||||
|
||||
TextBlockGetTextExtent(
|
||||
this->m_font,
|
||||
displayText,
|
||||
displayTextLength,
|
||||
fontHeight,
|
||||
&this->m_cachedWidth,
|
||||
shadowWidth,
|
||||
this->m_layoutScale,
|
||||
0.0f,
|
||||
this->m_styleFlags
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return this->m_cachedWidth / this->m_layoutScale;
|
||||
}
|
||||
|
||||
const char* CSimpleFontString::GetText() {
|
||||
return this->m_text;
|
||||
}
|
||||
|
||||
float CSimpleFontString::GetTextWidth(const char* text, uint32_t textBytes) {
|
||||
if (!this->m_font) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (textBytes == 0) {
|
||||
textBytes = SStrLen(text);
|
||||
}
|
||||
|
||||
float fontHeight = this->GetFontHeight(true);
|
||||
float extent = 0.0f;
|
||||
|
||||
TextBlockGetTextExtent(
|
||||
this->m_font,
|
||||
text,
|
||||
textBytes,
|
||||
fontHeight * this->m_layoutScale,
|
||||
&extent,
|
||||
this->m_shadowOffset.x * this->m_layoutScale,
|
||||
this->m_layoutScale,
|
||||
0.0f,
|
||||
this->m_styleFlags
|
||||
);
|
||||
|
||||
float width = extent / this->m_layoutScale;
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
float CSimpleFontString::GetWidth() {
|
||||
float v2 = CLayoutFrame::GetWidth();
|
||||
float v9 = v2 == 0.0f ? this->GetStringWidth() : v2;
|
||||
|
||||
float v3 = 1.0f / (CoordinateGetAspectCompensation() * 1024.0f);
|
||||
float v4 = NDCToDDCWidth(v3);
|
||||
|
||||
return v9 <= v4 ? v4 : v9;
|
||||
}
|
||||
|
||||
void CSimpleFontString::LoadXML(XMLNode* node, CStatus* status) {
|
||||
const char* inheritsAttr = node->GetAttributeByName("inherits");
|
||||
if (inheritsAttr && *inheritsAttr) {
|
||||
auto font = CSimpleFont::GetFont(inheritsAttr, 0);
|
||||
|
||||
if (font) {
|
||||
if (this->m_unk12b) {
|
||||
this->SetFontObject(font);
|
||||
}
|
||||
} else {
|
||||
const char* tainted;
|
||||
bool locked;
|
||||
|
||||
XMLNode* inheritsNode = FrameXML_AcquireHashNode(inheritsAttr, tainted, locked);
|
||||
|
||||
if (inheritsNode) {
|
||||
if (locked) {
|
||||
status->Add(STATUS_WARNING, "Recursively inherited node: %s", inheritsAttr);
|
||||
} else {
|
||||
this->LoadXML(inheritsNode, status);
|
||||
FrameXML_ReleaseHashNode(inheritsAttr);
|
||||
}
|
||||
} else {
|
||||
status->Add(STATUS_WARNING, "Couldn't find inherited node: %s", inheritsAttr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CSimpleRegion::LoadXML(node, status);
|
||||
|
||||
const char* hiddenAttr = node->GetAttributeByName("hidden");
|
||||
if (hiddenAttr && *hiddenAttr) {
|
||||
bool hide = StringToBOOL(hiddenAttr);
|
||||
|
||||
if (hide) {
|
||||
this->Hide();
|
||||
} else {
|
||||
this->Show();
|
||||
}
|
||||
}
|
||||
|
||||
const char* textAttr = node->GetAttributeByName("text");
|
||||
if (textAttr && *textAttr) {
|
||||
const char* text = FrameScript_GetText(textAttr, -1, GENDER_NOT_APPLICABLE);
|
||||
this->SetText(text && *text ? text : textAttr, 1);
|
||||
}
|
||||
|
||||
const char* nonSpaceWrapAttr = node->GetAttributeByName("nonspacewrap");
|
||||
if (nonSpaceWrapAttr && *nonSpaceWrapAttr) {
|
||||
this->SetNonSpaceWrap(StringToBOOL(nonSpaceWrapAttr));
|
||||
}
|
||||
|
||||
const char* wordWrapAttr = node->GetAttributeByName("wordwrap");
|
||||
if (wordWrapAttr && *wordWrapAttr) {
|
||||
this->SetNonWordWrap(!StringToBOOL(wordWrapAttr));
|
||||
}
|
||||
|
||||
const char* bytesAttr = node->GetAttributeByName("bytes");
|
||||
if (bytesAttr && *bytesAttr) {
|
||||
uint32_t length = SStrToInt(bytesAttr);
|
||||
this->SetTextLength(length);
|
||||
}
|
||||
|
||||
if (!this->m_unk12b) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char* fontAttr = node->GetAttributeByName("font");
|
||||
if (fontAttr && *fontAttr) {
|
||||
auto font = CSimpleFont::GetFont(fontAttr, 0);
|
||||
|
||||
if (font) {
|
||||
this->SetFontObject(font);
|
||||
} else {
|
||||
float fontHeight = 0.0f;
|
||||
|
||||
XMLNode* fontHeightNode = node->GetChildByName("FontHeight");
|
||||
if (fontHeightNode) {
|
||||
LoadXML_Value(fontHeightNode, fontHeight, status);
|
||||
}
|
||||
|
||||
if (fontHeight == 0.0f) {
|
||||
status->Add(
|
||||
STATUS_WARNING,
|
||||
"FontString %s: invalid font height %f in %s element",
|
||||
this->GetDisplayName(),
|
||||
fontHeight,
|
||||
node->GetName()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t fontFlags = 0;
|
||||
|
||||
const char* outlineAttr = node->GetAttributeByName("outline");
|
||||
if (outlineAttr && *outlineAttr) {
|
||||
if (!SStrCmpI(outlineAttr, "NORMAL", STORM_MAX_STR)) {
|
||||
fontFlags |= FONT_OUTLINE;
|
||||
} else if (!SStrCmpI(outlineAttr, "THICK", STORM_MAX_STR)) {
|
||||
fontFlags |= (FONT_OUTLINE | FONT_THICKOUTLINE);
|
||||
}
|
||||
}
|
||||
|
||||
const char* monochromeAttr = node->GetAttributeByName("monochrome");
|
||||
if (monochromeAttr && *monochromeAttr && StringToBOOL(monochromeAttr)) {
|
||||
fontFlags |= FONT_MONOCHROME;
|
||||
}
|
||||
|
||||
if (this->SetFont(fontAttr, fontHeight, fontFlags, false)) {
|
||||
this->m_fontableFlags &= ~FLAG_FONT_UPDATE;
|
||||
} else {
|
||||
status->Add(
|
||||
STATUS_WARNING,
|
||||
"FontString %s: Unable to load font file %s",
|
||||
this->GetDisplayName(),
|
||||
fontAttr
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* spacingAttr = node->GetAttributeByName("spacing");
|
||||
if (spacingAttr && *spacingAttr) {
|
||||
float spacing = SStrToFloat(spacingAttr);
|
||||
float ndcSpacing = spacing / (CoordinateGetAspectCompensation() * 1024.0f);
|
||||
float ddcSpacing = NDCToDDCWidth(ndcSpacing);
|
||||
|
||||
this->SetSpacing(ddcSpacing);
|
||||
this->m_fontableFlags &= ~FLAG_SPACING_UPDATE;
|
||||
}
|
||||
|
||||
const char* justifyVAttr = node->GetAttributeByName("justifyV");
|
||||
if (justifyVAttr && *justifyVAttr) {
|
||||
uint32_t justify;
|
||||
|
||||
if (StringToJustify(justifyVAttr, justify)) {
|
||||
this->SetJustifyV(justify);
|
||||
this->m_fontableFlags &= ~FLAG_STYLE_UPDATE;
|
||||
}
|
||||
}
|
||||
|
||||
const char* justifyHAttr = node->GetAttributeByName("justifyH");
|
||||
if (justifyHAttr && *justifyHAttr) {
|
||||
uint32_t justify;
|
||||
|
||||
if (StringToJustify(justifyHAttr, justify)) {
|
||||
this->SetJustifyH(justify);
|
||||
this->m_fontableFlags &= ~FLAG_STYLE_UPDATE;
|
||||
}
|
||||
}
|
||||
|
||||
const char* indentedAttr = node->GetAttributeByName("indented");
|
||||
if (indentedAttr && *indentedAttr) {
|
||||
bool indented = StringToBOOL(indentedAttr);
|
||||
this->SetIndentedWordWrap(indented);
|
||||
}
|
||||
|
||||
for (XMLNode* child = node->m_child; child; child = child->m_next) {
|
||||
if (!SStrCmpI(child->GetName(), "Color", STORM_MAX_STR)) {
|
||||
CImVector color;
|
||||
LoadXML_Color(child, color);
|
||||
this->SetVertexColor(color);
|
||||
this->m_fontableFlags &= ~FLAG_COLOR_UPDATE;
|
||||
|
||||
} else if (!SStrCmpI(child->GetName(), "Shadow", STORM_MAX_STR)) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
// - alpha
|
||||
|
||||
// TODO
|
||||
// - children
|
||||
}
|
||||
|
||||
void CSimpleFontString::OnColorChanged(bool a2) {
|
||||
CSimpleRegion::OnColorChanged(a2);
|
||||
|
||||
if (this->m_string) {
|
||||
CImVector color = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
if (this->m_colorCount == 1) {
|
||||
color = this->m_color[0];
|
||||
}
|
||||
|
||||
TextBlockUpdateColor(this->m_string, color);
|
||||
|
||||
if (this->m_styleFlags & 0x100) {
|
||||
CImVector shadowColor = this->m_shadowColor;
|
||||
|
||||
C2Vector shadowOffset = {
|
||||
this->m_shadowOffset.x * this->m_layoutScale,
|
||||
this->m_shadowOffset.y * this->m_layoutScale
|
||||
};
|
||||
|
||||
// TODO
|
||||
// - shadow color alpha calculation
|
||||
|
||||
TextBlockAddShadow(this->m_string, shadowColor, shadowOffset);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
// - embedded texture color updates
|
||||
}
|
||||
|
||||
void CSimpleFontString::OnScreenSizeChanged() {
|
||||
this->m_cachedWidth = 0.0f;
|
||||
this->m_cachedHeight = 0.0f;
|
||||
this->Resize(0);
|
||||
}
|
||||
|
||||
void CSimpleFontString::OnFrameSizeChanged(const CRect& rect) {
|
||||
CLayoutFrame::OnFrameSizeChanged(rect);
|
||||
|
||||
if (
|
||||
this->m_string
|
||||
&& AreEqual(rect.maxX - rect.minX, this->m_rect.maxX - this->m_rect.minX, WHOA_EPSILON_2)
|
||||
&& AreEqual(rect.maxY - rect.minY, this->m_rect.maxY - this->m_rect.minY, WHOA_EPSILON_2)
|
||||
) {
|
||||
C3Vector pos = {
|
||||
this->m_justificationOffset.x * this->m_layoutScale + this->m_rect.minX,
|
||||
this->m_justificationOffset.y * this->m_layoutScale + this->m_rect.minY,
|
||||
this->m_layoutDepth
|
||||
};
|
||||
|
||||
TextBlockSetStringPos(this->m_string, pos);
|
||||
|
||||
if (rect.Sub4826D0() != this->m_rect.Sub4826D0()) {
|
||||
this->OnRegionChanged();
|
||||
}
|
||||
} else {
|
||||
this->UpdateString();
|
||||
}
|
||||
|
||||
// TODO logic if region flags & 0x40
|
||||
|
||||
if (this->m_parent) {
|
||||
this->m_parent->NotifyScrollParent();
|
||||
}
|
||||
}
|
||||
|
||||
void CSimpleFontString::PostLoadXML(XMLNode* node, CStatus* status) {
|
||||
if (this->m_parent) {
|
||||
int32_t hasPoint = 0;
|
||||
|
||||
for (int32_t i = 0; i < FRAMEPOINT_NUMPOINTS; i++) {
|
||||
auto point = this->m_points[i];
|
||||
|
||||
if (point && !(point->m_flags & 0x08)) {
|
||||
hasPoint = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasPoint) {
|
||||
float offsetX = 0.0f;
|
||||
float offsetY = 0.0f;
|
||||
|
||||
if (this->m_styleFlags & 0x01) {
|
||||
this->SetPoint(FRAMEPOINT_LEFT, this->m_parent, FRAMEPOINT_LEFT, offsetX, offsetY, 1);
|
||||
} else if (this->m_styleFlags & 0x04) {
|
||||
this->SetPoint(FRAMEPOINT_RIGHT, this->m_parent, FRAMEPOINT_RIGHT, offsetX, offsetY, 1);
|
||||
} else {
|
||||
this->SetPoint(FRAMEPOINT_CENTER, this->m_parent, FRAMEPOINT_CENTER, offsetX, offsetY, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSimpleFontString::RefreshEmbeddedTextures() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CSimpleFontString::RemoveShadow() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
int32_t CSimpleFontString::SetFont(const char* fontName, float fontHeight, uint32_t fontFlags, bool force) {
|
||||
if (!force) {
|
||||
const char* curFontName = this->GetFontName();
|
||||
|
||||
if (
|
||||
fontName
|
||||
&& curFontName
|
||||
&& !SStrCmpI(fontName, curFontName, STORM_MAX_STR)
|
||||
&& AreEqual(fontHeight, this->m_fontHeight, WHOA_EPSILON_1)
|
||||
&& fontFlags == this->GetFontFlags()
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
HTEXTFONT font = nullptr;
|
||||
|
||||
if (fontName && fontHeight != 0.0f) {
|
||||
font = TextBlockGenerateFont(fontName, fontFlags, fontHeight * this->m_layoutScale);
|
||||
|
||||
if (!font) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_fontHeight = fontHeight;
|
||||
|
||||
if (this->m_string) {
|
||||
HandleClose(this->m_string);
|
||||
this->m_string = nullptr;
|
||||
}
|
||||
|
||||
if (this->m_font) {
|
||||
HandleClose(this->m_font);
|
||||
}
|
||||
|
||||
this->m_font = font;
|
||||
|
||||
if (font) {
|
||||
this->m_cachedWidth = 0.0f;
|
||||
this->m_cachedHeight = 0.0f;
|
||||
}
|
||||
|
||||
this->m_flags &= ~0x1;
|
||||
this->Resize(0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CSimpleFontString::SetIndentedWordWrap(bool a2) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CSimpleFontString::SetJustificationOffset(float x, float y) {
|
||||
if (this->m_justificationOffset.x == x && this->m_justificationOffset.y == y) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->m_justificationOffset = { x, y };
|
||||
|
||||
if (this->m_string) {
|
||||
C3Vector pos = {
|
||||
this->m_rect.minX + (this->m_justificationOffset.x * this->m_layoutScale),
|
||||
this->m_rect.minY + (this->m_justificationOffset.y * this->m_layoutScale),
|
||||
this->m_layoutDepth
|
||||
};
|
||||
|
||||
TextBlockSetStringPos(this->m_string, pos);
|
||||
}
|
||||
}
|
||||
|
||||
void CSimpleFontString::SetJustifyV(uint8_t justify) {
|
||||
this->m_settableStyleFlags &= ~(0x8 | 0x10 | 0x20);
|
||||
uint32_t newStyleFlags = this->m_styleFlags ^ ((justify ^ this->m_styleFlags) & (0x8 | 0x10 | 0x20));
|
||||
|
||||
if (this->m_styleFlags != newStyleFlags) {
|
||||
this->m_styleFlags = newStyleFlags;
|
||||
|
||||
if (this->m_string) {
|
||||
this->UpdateString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSimpleFontString::SetJustifyH(uint8_t justify) {
|
||||
this->m_settableStyleFlags &= ~(0x1 | 0x2 | 0x4);
|
||||
uint32_t newStyleFlags = this->m_styleFlags ^ ((justify ^ this->m_styleFlags) & (0x1 | 0x2 | 0x4));
|
||||
|
||||
if (this->m_styleFlags != newStyleFlags) {
|
||||
this->m_styleFlags = newStyleFlags;
|
||||
|
||||
if (this->m_string) {
|
||||
this->UpdateString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSimpleFontString::SetNonSpaceWrap(int32_t a2) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CSimpleFontString::SetSpacing(float spacing) {
|
||||
if (spacing < 0.0f) {
|
||||
spacing = 0.0f;
|
||||
}
|
||||
|
||||
if (fabs(spacing - this->m_spacing) >= WHOA_EPSILON_1) {
|
||||
this->m_spacing = spacing;
|
||||
this->m_cachedHeight = 0.0f;
|
||||
|
||||
if (this->m_string) {
|
||||
this->UpdateString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSimpleFontString::SetStyleFlags(uint32_t styleFlags) {
|
||||
uint32_t newStyleFlags = (styleFlags & this->m_settableStyleFlags) | (this->m_styleFlags & ~this->m_settableStyleFlags);
|
||||
|
||||
if (this->m_styleFlags != newStyleFlags) {
|
||||
this->m_styleFlags = newStyleFlags;
|
||||
|
||||
if (this->m_string) {
|
||||
this->UpdateString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSimpleFontString::SetText(const char* text, int32_t a3) {
|
||||
if (text && a3) {
|
||||
text = LanguageProcess(text);
|
||||
}
|
||||
|
||||
if (text && *text) {
|
||||
if (this->m_text && !SStrCmp(text, this->m_text, STORM_MAX_STR)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->m_textMaxSize & 0xFFFF) {
|
||||
SStrCopy(this->m_text, text, this->m_textMaxSize & 0xFFFF);
|
||||
} else {
|
||||
size_t textSize = SStrLen(text);
|
||||
|
||||
if (textSize <= this->m_textCurSize) {
|
||||
SStrCopy(this->m_text, text, STORM_MAX_STR);
|
||||
} else {
|
||||
if (this->m_text) {
|
||||
SMemFree(this->m_text, __FILE__, __LINE__, 0x0);
|
||||
}
|
||||
|
||||
this->m_text = SStrDupA(text, __FILE__, __LINE__);
|
||||
this->m_textCurSize = textSize;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this->m_text) {
|
||||
*this->m_text = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
this->ClearString();
|
||||
}
|
||||
|
||||
int32_t CSimpleFontString::Sub482AC0() {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CSimpleFontString::SetTextLength(uint32_t a2) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CSimpleFontString::SetNonWordWrap(int32_t a2) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CSimpleFontString::UpdateString() {
|
||||
if (!(this->m_flags & 0x1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->m_string) {
|
||||
HandleClose(this->m_string);
|
||||
this->m_string = nullptr;
|
||||
}
|
||||
|
||||
this->FreeEmbeddedTextures();
|
||||
|
||||
if (this->m_rect.maxY <= this->m_rect.minY || this->m_rect.maxX <= this->m_rect.minX) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->m_font && this->m_text && *this->m_text) {
|
||||
C3Vector pos = {
|
||||
this->m_rect.minX + this->m_justificationOffset.x * this->m_layoutScale,
|
||||
this->m_rect.minY + this->m_justificationOffset.y * this->m_layoutScale,
|
||||
this->m_layoutDepth
|
||||
};
|
||||
|
||||
float width = this->GetWidth();
|
||||
float blockWidth = width == 0.0f ? this->m_cachedWidth : width * this->m_layoutScale;
|
||||
if (NotEqual(blockWidth, this->m_rect.maxX - this->m_rect.minX, WHOA_EPSILON_2)) {
|
||||
blockWidth = this->m_rect.maxX - this->m_rect.minX;
|
||||
}
|
||||
|
||||
float height = this->GetHeight();
|
||||
float blockHeight = height == 0.0f ? this->m_cachedHeight : height * this->m_layoutScale;
|
||||
if (NotEqual(blockHeight, this->m_rect.maxY - this->m_rect.minY, WHOA_EPSILON_2)) {
|
||||
blockHeight = this->m_rect.maxY - this->m_rect.minY;
|
||||
}
|
||||
|
||||
const char* displayText = this->GetDisplayText(blockWidth, blockHeight);
|
||||
|
||||
uint32_t styleFlags = this->m_styleFlags;
|
||||
|
||||
if (!(this->m_styleFlags & 0x400)) {
|
||||
// TODO
|
||||
|
||||
styleFlags |= 0x400;
|
||||
}
|
||||
|
||||
CImVector color = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
if (this->m_colorCount) {
|
||||
color = this->m_color[0];
|
||||
}
|
||||
|
||||
float scale = this->m_layoutScale;
|
||||
float lineSpacing = this->m_spacing * this->m_layoutScale;
|
||||
float fontHeight = this->GetFontHeight(true) * this->m_layoutScale;
|
||||
|
||||
this->m_string = TextBlockCreate(
|
||||
this->m_font,
|
||||
displayText,
|
||||
color,
|
||||
pos,
|
||||
fontHeight,
|
||||
blockWidth,
|
||||
blockHeight,
|
||||
styleFlags,
|
||||
0.0f,
|
||||
lineSpacing,
|
||||
scale
|
||||
);
|
||||
|
||||
if (this->m_styleFlags & 0x100) {
|
||||
auto shadowColor = this->m_shadowColor;
|
||||
// TODO alpha manipulation
|
||||
|
||||
auto shadowOffset = this->m_shadowOffset;
|
||||
shadowOffset.x *= this->m_layoutScale;
|
||||
shadowOffset.y *= this->m_layoutScale;
|
||||
|
||||
TextBlockAddShadow(this->m_string, shadowColor, shadowOffset);
|
||||
}
|
||||
|
||||
if (this->m_alphaGradientStart > 0) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
this->RefreshEmbeddedTextures();
|
||||
|
||||
// TODO
|
||||
// - logic if region flags & 0x40, CLayoutFrame::AnimData_HasActivePosition?
|
||||
}
|
||||
|
||||
this->OnRegionChanged();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue