mirror of
https://github.com/zeldaret/ss
synced 2026-08-20 14:14:40 -04:00
d_textbox almost
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -70,6 +70,10 @@ public:
|
||||
s32 tickPauseFrame();
|
||||
s32 tick0x830();
|
||||
|
||||
void setTextbox(dTextBox_c *box) {
|
||||
field_0x004 = box;
|
||||
}
|
||||
|
||||
s32 getNumLinesMaybe() const {
|
||||
return mCommandInsert;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user