d_textbox almost

This commit is contained in:
robojumper
2025-04-02 18:35:21 +02:00
parent 010c0a9a3b
commit c890868bad
8 changed files with 538 additions and 31 deletions
+1
View File
@@ -243,6 +243,7 @@ d/lyt/d_textbox.cpp:
.text start:0x800AE960 end:0x800B1628
.data start:0x80510780 end:0x80510820
.sdata start:0x805722C0 end:0x805722D8
.sbss start:0x805753A8 end:0x805753B0
.sdata2 start:0x805797D0 end:0x805797F0
.bss start:0x805A6370 end:0x805A6F70
+9 -9
View File
@@ -3848,17 +3848,17 @@ setMessageWithGlobalTextProcessor__10dTextBox_cFPCcPvPve = .text:0x800AF720; //
setMessageWithGlobalTextProcessorV__10dTextBox_cFPCcPvPvP16__va_list_struct = .text:0x800AF7B0; // type:function size:0x84
setMessageWithGlobalTextProcessorAndMsbtInfo__10dTextBox_cFPC8MsbtInfoPCcPwUl = .text:0x800AF840; // type:function size:0xEC
setTextWithGlobalTextProcessor__10dTextBox_cFPCw = .text:0x800AF930; // type:function size:0x50
GetLineWidth__10dTextBox_cFPf = .text:0x800AF980; // type:function size:0x1E4
fn_800AFB70 = .text:0x800AFB70; // type:function size:0x1A4
fn_800AFD20 = .text:0x800AFD20; // type:function size:0x3C
fn_800AFD60__10dTextBox_cFf = .text:0x800AFD60; // type:function size:0xC8
GetLineWidth__10dTextBox_cCFPf = .text:0x800AF980; // type:function size:0x1E4
GetLinesHeight__10dTextBox_cCFv = .text:0x800AFB70; // type:function size:0x1A4
GetUnkWidthRatio__10dTextBox_cCFv = .text:0x800AFD20; // type:function size:0x3C
resizeTextToFit__10dTextBox_cFf = .text:0x800AFD60; // type:function size:0xC8
init__10dTextBox_cFv = .text:0x800AFE30; // type:function size:0x204
fn_800B0040 = .text:0x800B0040; // type:function size:0x278
fn_800B02C0 = .text:0x800B02C0; // type:function size:0x1EC
hasDynamicText__10dTextBox_cFv = .text:0x800B0040; // type:function size:0x278
someDebugCheckMaybe__10dTextBox_cFv = .text:0x800B02C0; // type:function size:0x1EC
DrawSelf__10dTextBox_cFRCQ34nw4r3lyt8DrawInfo = .text:0x800B04B0; // type:function size:0x930
fn_800B0DE0 = .text:0x800B0DE0; // type:function size:0x158
fn_800B0F40__10dTextBox_cFv = .text:0x800B0F40; // type:function size:0x240
fn_800B1180 = .text:0x800B1180; // type:function size:0x3F0
CalcLineStrNum__FPfPQ34nw4r2ut17TextWriterBase<w>PCwifPb = .text:0x800B0DE0; // type:function size:0x158
loadTextFormatVars__10dTextBox_cFv = .text:0x800B0F40; // type:function size:0x240
setupGX__10dTextBox_cCFv = .text:0x800B1180; // type:function size:0x3F0
MySetFontSize__10dTextBox_cFRCQ34nw4r3lyt4Size = .text:0x800B1570; // type:function size:0x14
MySetScale__10dTextBox_cFRCQ34nw4r3lyt4Size = .text:0x800B1590; // type:function size:0x14
GetRuntimeTypeInfo__Q34nw4r3lyt7TextBoxCFv = .text:0x800B15B0; // type:function size:0x8 scope:weak
+4
View File
@@ -70,6 +70,10 @@ public:
s32 tickPauseFrame();
s32 tick0x830();
void setTextbox(dTextBox_c *box) {
field_0x004 = box;
}
s32 getNumLinesMaybe() const {
return mCommandInsert;
}
+14
View File
@@ -21,6 +21,20 @@ public:
return 0.0f;
}
inline static f32 getField0x75C() {
if (sInstance != nullptr) {
return sInstance->field_0x75C;
}
return 0.0f;
}
inline static f32 getField0x760() {
if (sInstance != nullptr) {
return sInstance->field_0x760;
}
return 0.0f;
}
inline static f32 getField0x768() {
if (sInstance != nullptr) {
return sInstance->field_0x768;
+11 -9
View File
@@ -18,7 +18,9 @@ public:
dTextBox_c(const nw4r::lyt::res::TextBox *pBlock, const nw4r::lyt::ResBlockSet &resBlockSet);
virtual void DrawSelf(const nw4r::lyt::DrawInfo &drawInfo) override; // at 0x18
f32 GetLineWidth(f32 *pOutSpacing);
f32 GetLineWidth(f32 *pOutSpacing) const;
f32 GetLinesHeight() const;
f32 GetUnkWidthRatio() const;
void setLytBase(d2d::LytBase_c *lytBase) {
mpLytBase = lytBase;
@@ -58,7 +60,8 @@ public:
void setMessageWithGlobalTextProcessorAndMsbtInfo(const MsbtInfo *info, const char *labelId, wchar_t *destBuf, u32 maxLen);
void fn_800B0F40();
void loadTextFormatVars();
void setupGX() const;
// @bug: This does not implement UT's RTTI, so casts to dTextBox_c will
// succeed even if all you have is a lyt::TextBox
@@ -72,7 +75,9 @@ private:
nw4r::ut::Rect GetMyTextDrawRect(nw4r::ut::TextWriterBase<wchar_t> *pWriter, bool *pbWideScreenUnk) const;
void fn_800AFD60(f32);
f32 resizeTextToFit(f32 maxWidth);
bool hasDynamicText();
void someDebugCheckMaybe();
/* 0x104 */ d2d::LytBase_c *mpLytBase;
/* 0x108 */ f32 mFixedWidth;
@@ -81,19 +86,16 @@ private:
/* 0x118 */ nw4r::lyt::Size mMyTextScale;
/* 0x120 */ f32 mMyScale;
/* 0x124 */ nw4r::ut::TextWriterBase<wchar_t> mTextWriter;
/* 0x188 */ f32 field_0x188;
/* 0x18C */ f32 field_0x18C;
/* 0x190 */ f32 field_0x190;
/* 0x194 */ f32 field_0x194;
/* 0x188 */ nw4r::ut::Rect field_0x188;
/* 0x198 */ u32 field_0x198[10];
/* 0x1C0 */ u8 mFontIdx;
/* 0x1C1 */ u8 mWindowSubtype;
/* 0x1C4 */ f32 field_0x1C4[10];
/* 0x1EC */ u8 field_0x1EC[10];
/* 0x1EC */ bool field_0x1EC[10];
/* 0x1F6 */ u8 field_0x1F6;
/* 0x1F7 */ u8 field_0x1F7;
/* 0x1F8 */ u8 field_0x1F8;
/* 0x1F9 */ u8 field_0x1F9;
/* 0x1F9 */ bool field_0x1F9;
/* 0x1FA */ u8 field_0x1FA;
/* 0x1FC */ dTagProcessor_c *mpMyTagProcessor;
/* 0x200 */ bool mHasTextWriter;
-1
View File
@@ -985,7 +985,6 @@ f32 dTagProcessor_c::fn_800B8040(s8 factor, u32 windowType) {
case 2:
x = 1.1f;
break;
// @bug: No default, so uninitialized is possible
}
x *= UnkTextThing::getFn800B1F10();
return x * f1;
+1 -1
View File
@@ -455,7 +455,7 @@ void LytBase_c::setProperties(nw4r::lyt::Pane *pane, f32 posX, f32 posY, f32 sca
textBox->AllocStringBuffer(0x200);
textBox->setLytBase(this);
textBox->fn_800B0F40();
textBox->loadTextFormatVars();
if (posX != -9999.0f || posY != -9999.0f) {
if (posX == -9999.0f) {
+498 -11
View File
@@ -5,21 +5,25 @@
#include "d/d_tag_processor.h"
#include "d/d_textunk.h"
#include "libms/msgfile.h"
#include "m/m_color.h"
#include "nw4r/lyt/lyt_common.h"
#include "nw4r/lyt/lyt_drawInfo.h"
#include "nw4r/lyt/lyt_material.h"
#include "nw4r/lyt/lyt_resources.h"
#include "nw4r/lyt/lyt_textBox.h"
#include "nw4r/lyt/lyt_types.h"
#include "nw4r/ut/ut_CharWriter.h"
#include "nw4r/ut/ut_Font.h"
#include "nw4r/ut/ut_Rect.h"
#include "rvl/GX/GXPixel.h"
#include "rvl/GX/GXTev.h"
#include "rvl/GX/GXTypes.h"
#include <cstddef>
#include <cstring>
dTextBox_c::dTextBox_c(const nw4r::lyt::res::TextBox *pBlock, const nw4r::lyt::ResBlockSet &resBlockSet)
: nw4r::lyt::TextBox(pBlock, resBlockSet),
mMyFontSize(0.0f, 0.0f),
mMyTextScale(0.0f, 0.0f),
field_0x188(0.0f),
field_0x18C(0.0f),
field_0x190(0.0f),
field_0x194(0.0f) {
: nw4r::lyt::TextBox(pBlock, resBlockSet), mMyFontSize(0.0f, 0.0f), mMyTextScale(0.0f, 0.0f) {
const nw4r::lyt::res::Font *fonts = nw4r::lyt::detail::ConvertOffsToPtr<nw4r::lyt::res::Font>(
resBlockSet.pFontList, sizeof(nw4r::lyt::res::FontList)
);
@@ -67,6 +71,11 @@ static int CalcLineRectImpl(
bool *pbOver, bool *pbWideScreenUnk
);
static int CalcLineStrNum(
f32 *pWidth, nw4r::ut::TextWriterBase<wchar_t> *pTextWriter, const wchar_t *str, int length, f32 maxWidth,
bool *pbOver
);
nw4r::ut::Rect dTextBox_c::GetMyTextDrawRect(nw4r::ut::TextWriterBase<wchar_t> *pWriter, bool *pbWideScreenUnk) const {
nw4r::ut::Rect textRect;
pWriter->SetCursor(0.0f, 0.0f);
@@ -305,7 +314,7 @@ void dTextBox_c::setMessageWithGlobalTextProcessorV(const char *labelId, void *u
const wchar_t *text = getTextMessageByLabel(labelId, 1, 0, 0);
setTextWithGlobalTextProcessorV(text, unk, list);
if (GetFont() != nullptr) {
fn_800AFD60(GetSize().width);
resizeTextToFit(GetSize().width);
}
}
@@ -331,10 +340,139 @@ void dTextBox_c::setMessageWithGlobalTextProcessorAndMsbtInfo(
void dTextBox_c::setTextWithGlobalTextProcessor(const wchar_t *str) {
setTextWithGlobalTextProcessor(str, nullptr);
if (GetFont() != nullptr) {
fn_800AFD60(GetSize().width);
resizeTextToFit(GetSize().width);
}
}
f32 dTextBox_c::GetLineWidth(f32 *pOutSpacing) const {
if ((int)mTextLen <= 0) {
return 0.0f;
}
f32 widthThisLine = 0.0f;
int numCharsThisLine = 0;
int maxNumCharacters = 0;
const wchar_t *buf = GetString();
f32 maxWidth = widthThisLine;
const nw4r::ut::Font *f = GetFont();
f32 charBaseWidth = mFontSize.width / f->GetWidth();
wchar_t c;
while ((c = *buf, c != '\0')) {
if (c == L'\x0E') {
u8 commandLen = buf[3];
buf += commandLen / 2 + 4;
} else if (c == L'\x0F') {
buf += 3;
} else if (c == L'\n') {
if (widthThisLine > maxWidth) {
maxWidth = widthThisLine;
maxNumCharacters = numCharsThisLine;
}
widthThisLine = 0.0f;
numCharsThisLine = 0;
buf++;
} else {
if (mIsWidthFixed == true) {
widthThisLine += mFixedWidth;
} else {
int charWid = f->GetCharWidth(c);
widthThisLine += charBaseWidth * charWid;
}
numCharsThisLine++;
buf++;
}
}
if (widthThisLine > maxWidth) {
maxWidth = widthThisLine;
maxNumCharacters = numCharsThisLine;
}
f32 maxSpaceWidth = (maxNumCharacters - 1) * GetCharSpace();
maxWidth += maxSpaceWidth + 1.0f;
if (pOutSpacing != nullptr) {
*pOutSpacing = maxSpaceWidth;
}
return maxWidth;
}
f32 dTextBox_c::GetLinesHeight() const {
if ((int)mTextLen <= 0) {
return 0.0f;
}
const wchar_t *buf = GetString();
const nw4r::ut::Font *f = GetFont();
f32 assumedDefaultSize = 35.0f;
f32 f3 = UnkTextThing::getFn800B1F70();
nw4r::lyt::Size size = mMyFontSize;
int fontHeight = f->GetHeight();
f3 *= (size.height / assumedDefaultSize) * fontHeight;
f32 lineBaseHeight = f3;
f32 totalHeight = 0.0f;
wchar_t c;
while ((c = *buf, c != '\0')) {
if (c == L'\x0E') {
u8 commandLen = buf[3];
s32 skip = commandLen / 2 + 4;
u32 command = *((u32 *)(buf + 1));
if (command == 0x10008) {
f32 nullHeight = dTagProcessor_c::fn_800B8040(0, mWindowSubtype);
f32 cmdHeight = dTagProcessor_c::fn_800B8040(*((u8 *)(buf + 4)), mWindowSubtype);
lineBaseHeight = f3 * (cmdHeight / nullHeight);
}
buf += skip;
} else if (c == L'\x0F') {
buf += 3;
} else if (c == L'\n') {
totalHeight += lineBaseHeight + GetLineSpace();
buf++;
} else {
buf++;
}
}
totalHeight += lineBaseHeight;
return totalHeight;
}
extern "C" f32 lbl_805751A4;
f32 dTextBox_c::GetUnkWidthRatio() const {
f32 tmp = lbl_805751A4;
return GetLineWidth(nullptr) / tmp;
}
f32 dTextBox_c::resizeTextToFit(f32 maxWidth) {
if (!hasDynamicText()) {
return 0.0f;
}
nw4r::lyt::Size size;
size = GetFontSize();
f32 spacing = 0.0f;
f32 computedTextWidth = GetLineWidth(&spacing);
if (maxWidth >= computedTextWidth) {
return 0.0f;
}
if (spacing < 0.0f) {
spacing = 0.0f;
}
f32 resizeFactor = (maxWidth - spacing) / computedTextWidth;
size.width *= resizeFactor;
size.height = size.height;
SetFontSize(size);
return resizeFactor * 100.0f;
}
void dTextBox_c::init() {
mpLytBase = nullptr;
mIsWidthFixed = false;
@@ -342,7 +480,7 @@ void dTextBox_c::init() {
mHasTextWriter = true;
field_0x1F6 = 0;
field_0x1F7 = 0;
field_0x1F9 = 0;
field_0x1F9 = false;
field_0x1FA = 0;
field_0x1F8 = 2;
mpMyTagProcessor = nullptr;
@@ -371,13 +509,362 @@ void dTextBox_c::init() {
field_0x201 = 1;
}
bool dTextBox_c::hasDynamicText() {
u16 myNum = GetExtUserDataNum();
if (myNum == 0) {
return false;
}
const nw4r::lyt::res::ExtUserData *myList = GetExtUserData();
for (int i = 0; i < myNum; i++) {
SizedString<0x40> userDatName;
userDatName = myList->GetName();
if (userDatName == "embed" && myList->GetType() == nw4r::lyt::res::TYPE_INT) {
return true;
}
if (userDatName == "textScale" && myList->GetType() == nw4r::lyt::res::TYPE_INT) {
return true;
}
if (userDatName == "copy" && myList->GetType() == nw4r::lyt::res::TYPE_STRING) {
field_0x1F6 = true;
dTextBox_c *other = mpLytBase->getTextBox(myList->GetString());
if (other != nullptr) {
u16 otherNum = other->GetExtUserDataNum();
if (otherNum == 0) {
break;
}
const nw4r::lyt::res::ExtUserData *otherList = other->GetExtUserData();
for (int j = 0; j < otherNum; j++) {
userDatName = otherList->GetName();
if (userDatName == "embed") {
return true;
}
if (userDatName == "textScale") {
return true;
}
otherList++;
}
}
}
myList++;
}
return false;
}
void dTextBox_c::someDebugCheckMaybe() {
field_0x1F7 = 0;
// Everything below this is effectively no-ops, since
// we check and compare a bunch of things but don't actually
// do anything.
u16 myNum = GetExtUserDataNum();
if (!myNum) {
return;
}
const nw4r::lyt::res::ExtUserData *myList = GetExtUserData();
for (int i = 0; i < myNum; myList++, i++) {
SizedString<0x40> userDatName;
userDatName = myList->GetName();
if (userDatName == "copy" && myList->GetType() == nw4r::lyt::res::TYPE_STRING) {
dTextBox_c *other = mpLytBase->getTextBox(myList->GetString());
if (other != nullptr) {
u16 otherNum = other->GetExtUserDataNum();
if (otherNum == 0) {
continue;
}
const nw4r::lyt::res::ExtUserData *otherList = other->GetExtUserData();
for (int j = 0; j < otherNum; j++) {
SizedString<0x40> otherName;
otherName = otherList->GetName();
otherList++;
}
}
}
}
return;
}
// Also largely copied from nw4r::lyt::TextBox
void dTextBox_c::DrawSelf(const nw4r::lyt::DrawInfo &drawInfo) {
if (!mTextBuf || !mpFont || !mpMaterial) {
return;
}
LoadMtx(drawInfo);
nw4r::ut::TextWriterBase<wchar_t> writer;
// TODO
nw4r::ut::Rect textRect;
if (mHasTextWriter) {
field_0x1F9 = false;
someDebugCheckMaybe();
nw4r::ut::Rect resultRect = GetMyTextDrawRect(&writer, &field_0x1F9);
textRect = resultRect;
mTextWriter = writer;
field_0x188 = textRect;
} else {
writer = mTextWriter;
textRect = field_0x188;
}
if (mpMyTagProcessor != nullptr) {
mpMyTagProcessor->setMsgWindowSubtype(mWindowSubtype);
mpMyTagProcessor->setField_0xEE1(field_0x1F6);
mpMyTagProcessor->setField_0xEE2(0);
if (mAlpha != 0) {
mpMyTagProcessor->setField_0xEE3(1);
} else {
mpMyTagProcessor->setField_0xEE3(0);
}
}
bool unk1;
if (field_0x1F8 == 2) {
unk1 = field_0x1F9;
} else {
unk1 = field_0x1F8 == 1;
}
if (field_0x1F7 == 1 || (field_0x1F7 == 2 && unk1)) {
f32 f = GetFontSize().height * UnkTextThing::getField0x75C();
textRect.top -= f;
textRect.bottom -= f;
} else if (field_0x1F7 == 3 && unk1) {
f32 f = GetFontSize().height * UnkTextThing::getField0x760();
textRect.top -= f;
textRect.bottom -= f;
}
nw4r::ut::Color c1 = nw4r::lyt::detail::MultipleAlpha(GetTextColor(0), GetGlobalAlpha());
nw4r::ut::Color c2 = nw4r::lyt::detail::MultipleAlpha(GetTextColor(2), GetGlobalAlpha());
writer.SetGradationMode(c1 != c2 ? nw4r::ut::CharWriter::GRADMODE_V : nw4r::ut::CharWriter::GRADMODE_NONE);
writer.SetTextColor(c1, c2);
nw4r::ut::Color minCol = GetColor(mpMaterial->GetTevColor(0));
nw4r::ut::Color maxCol = GetColor(mpMaterial->GetTevColor(1));
writer.SetColorMapping(minCol, maxCol);
if (mFontIdx <= 3) {
setupGX();
if (mpMyTagProcessor != nullptr) {
mpMyTagProcessor->setTextbox(this);
}
} else {
writer.SetupGX();
}
GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
f32 hMag = GetTextAlignMag();
const wchar_t *strPos = mTextBuf;
writer.SetCursor(textRect.left, -textRect.top);
f32 texWidth = textRect.GetWidth();
int i = 0;
if (field_0x1FA != 0) {
// The original variant from nw4r::lyt
int remain = mTextLen;
while (remain > 0) {
bool bOver;
f32 lineWidth;
int lineStrNum = CalcLineStrNum(&lineWidth, &writer, strPos, remain, mSize.width, &bOver);
f32 textPosX = textRect.left + hMag * (texWidth - lineWidth);
writer.SetCursorX(textPosX);
writer.PrintMutable(strPos, lineStrNum);
if (bOver) {
writer.PrintMutable(L"\n", 1);
}
strPos += lineStrNum;
remain -= lineStrNum;
}
} else if (!mHasTextWriter && field_0x201 == 1) {
// Taking parameters from the three arrays, instead of calculating them
int remain = mTextLen;
while (remain > 0 && i < 10) {
bool bOver;
f32 lineWidth = field_0x1C4[i];
int lineStrNum = field_0x198[i];
bOver = field_0x1EC[i];
f32 textPosX = textRect.left + hMag * (texWidth - lineWidth);
writer.SetCursorX(textPosX);
writer.PrintMutable(strPos, lineStrNum);
if (bOver) {
writer.PrintMutable(L"\n", 1);
}
strPos += lineStrNum;
remain -= lineStrNum;
i++;
}
} else {
// Copying parameters to the three arrays
int remain = mTextLen;
while (remain > 0 && i < 10) {
bool bOver;
f32 lineWidth;
int lineStrNum = CalcLineStrNum(&lineWidth, &writer, strPos, remain, mSize.width, &bOver);
f32 textPosX = textRect.left + hMag * (texWidth - lineWidth);
writer.SetCursorX(textPosX);
writer.PrintMutable(strPos, lineStrNum);
if (mHasTextWriter && field_0x201 == 1 && i < 10) {
field_0x1C4[i] = lineWidth;
field_0x198[i] = lineStrNum;
field_0x1EC[i] = bOver;
}
if (bOver) {
writer.PrintMutable(L"\n", 1);
}
strPos += lineStrNum;
remain -= lineStrNum;
i++;
}
}
/*
const wchar_t *strPos = mTextBuf;
writer.SetCursor(textRect.left, -textRect.top);
f32 texWidth = textRect.GetWidth();
int remain = mTextLen;
while (remain > 0) {
bool bOver;
f32 lineWidth;
int lineStrNum = CalcLineStrNum(&lineWidth, &writer, strPos, remain, mSize.width, &bOver);
f32 textPosX = textRect.left + hMag * (texWidth - lineWidth);
writer.SetCursorX(textPosX);
writer.PrintMutable(strPos, lineStrNum);
if (bOver) {
writer.PrintMutable(L"\n", 1);
}
strPos += lineStrNum;
remain -= lineStrNum;
}
*/
mHasTextWriter = false;
}
void dTextBox_c::loadTextFormatVars() {
u16 myNum = GetExtUserDataNum();
if (myNum == 0) {
return;
}
const nw4r::lyt::res::ExtUserData *myList = GetExtUserData();
for (int i = 0; i < myNum; i++) {
SizedString<0x40> userDatName;
userDatName = myList->GetName();
if (userDatName == "fontWidth" && myList->GetType() == nw4r::lyt::res::TYPE_FLOAT) {
// If this text box has a "fontWidth" user datum of type float,
// we use that as a fixed font width.
mIsWidthFixed = true;
mFixedWidth = myList->GetFloat();
return;
}
// If this text box has a "copy" user datum, find a text box
// of the given name and use its font width, if any
if (userDatName == "copy") {
dTextBox_c *other = mpLytBase->getTextBox(myList->GetString());
if (other != nullptr) {
u16 otherNum = other->GetExtUserDataNum();
if (otherNum == 0) {
return;
}
const nw4r::lyt::res::ExtUserData *otherList = other->GetExtUserData();
for (int j = 0; j < otherNum; j++) {
userDatName = otherList->GetName();
if (userDatName == "fontWidth" && otherList->GetType() == nw4r::lyt::res::TYPE_FLOAT) {
mIsWidthFixed = true;
mFixedWidth = otherList->GetFloat();
break;
}
otherList++;
}
}
}
myList++;
}
}
void dTextBox_c::setupGX() const {
static mColor sFogColor = mColor(0);
GXSetFog(GX_FOG_NONE, sFogColor, 0.0f, 0.0f, 0.0f, 0.0f);
GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
GXSetZTexture(0, GX_TF_Z8, 0);
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0A0, false, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
GXSetChanCtrl(GX_COLOR1A1, false, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
GXSetNumTexGens(1);
GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c, 0, 0x7d);
GXSetNumIndStages(0);
GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
GXSetNumTevStages(2);
GXSetTevDirect(GX_TEVSTAGE0);
GXSetTevDirect(GX_TEVSTAGE1);
GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
// TODO the logic is wrong - what it should actually look like:
/*
GXColorS10 c1 = mpMaterial->GetTevColor(1);
GXColorS10 c0 = mpMaterial->GetTevColor(0);
GXColorS10 c2 = {-(c1.r / 2), -(c1.g / 2), -(c1.b / 2), -(c1.a / 2)};
GXSetTevColorS10(GX_TEVREG0, c0);
GXSetTevColorS10(GX_TEVREG1, c1);
GXSetTevColorS10(GX_TEVREG2, c2);
*/
// This makes the instruction patterns match best
GXColorS10 c0 = mpMaterial->GetTevColor(1);
GXColorS10 c1 = mpMaterial->GetTevColor(0);
GXColorS10 c2 = {-(c0.r / 2), -(c0.g / 2), -(c0.b / 2), -(c0.a / 2)};
GXSetTevColorS10(GX_TEVREG0, c0);
GXSetTevColorS10(GX_TEVREG1, c1);
GXSetTevColorS10(GX_TEVREG2, c2);
if ((mFontIdx == 1) || (mFontIdx == 3)) {
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C0, GX_CC_C1, GX_CC_TEXC, GX_CC_C2);
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_A0, GX_CA_A1, GX_CA_TEXA, GX_CA_ZERO);
} else if ((mFontIdx == 0) || (mFontIdx == 2)) {
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C0, GX_CC_C1, GX_CC_TEXC, GX_CC_C2);
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_A0, GX_CA_A1, GX_CA_TEXA, GX_CA_A2);
}
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, 1, GX_TEVPREV);
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, 1, GX_TEVPREV);
GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_CPREV, GX_CC_RASC, GX_CC_ZERO);
GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_APREV, GX_CA_RASA, GX_CA_ZERO);
GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBX8, 0xf);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
}
static int CalcLineStrNum(
f32 *pWidth, nw4r::ut::TextWriterBase<wchar_t> *pTextWriter, const wchar_t *str, int length, f32 maxWidth,
bool *pbOver
) {
nw4r::ut::Rect rect;
nw4r::ut::TextWriterBase<wchar_t> writerCpy(*pTextWriter);
writerCpy.SetCursor(0.0f, 0.0f);
int ret = CalcLineRectImpl(&rect, &writerCpy, str, length, maxWidth, pbOver, nullptr);
*pWidth = rect.right - rect.left;
return ret;
}
void dTextBox_c::MySetFontSize(const nw4r::lyt::Size &value) {