diff options
| author | Luke Street <luke@street.dev> | 2026-03-01 15:35:36 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-01 14:35:36 -0800 |
| commit | 9649319ec4926457ef85e6094f8207474c977c2d (patch) | |
| tree | 1c5cd4c7cc4c1aee03f28921213da47f2775444d /libs/JSystem/src/J2DGraph/J2DTextBox.cpp | |
| parent | 6e149819e13b1f70ecbf8a4c66b030c17ffed2bb (diff) | |
Reorganize library code into `libs/` (#3119)
* Reorganize files into libs/{dolphin,JSystem,PowerPC_EABI_Support,revolution,TRK_MINNOW_DOLPHIN}
* Update configure.py and project.py for new libs structure
* Refactor `#include <dolphin/x.h>` -> `<x.h>`
* Remove `__REVOLUTION_SDK__` forwards from dolphin
* Fix dolphin/ references in revolution
* Wrap `#include <dolphin.h>` in `!__REVOLUTION_SDK__`
* Always build TRK against dolphin headers
* Resolve revolution SDK header resolution issues
Diffstat (limited to 'libs/JSystem/src/J2DGraph/J2DTextBox.cpp')
| -rw-r--r-- | libs/JSystem/src/J2DGraph/J2DTextBox.cpp | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/libs/JSystem/src/J2DGraph/J2DTextBox.cpp b/libs/JSystem/src/J2DGraph/J2DTextBox.cpp new file mode 100644 index 0000000000..8f8a168104 --- /dev/null +++ b/libs/JSystem/src/J2DGraph/J2DTextBox.cpp @@ -0,0 +1,449 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/J2DGraph/J2DTextBox.h" +#include "JSystem/J2DGraph/J2DPrint.h" +#include "JSystem/JSupport/JSURandomInputStream.h" +#include "JSystem/JUtility/JUTResFont.h" +#include "JSystem/JUtility/JUTResource.h" +#include <cstring> + +J2DTextBox::J2DTextBox() + : mFont(NULL), mCharColor(), mGradientColor(), mStringPtr(NULL), mWhiteColor(), mBlackColor() { + initiate(NULL, NULL, 0, HBIND_LEFT, VBIND_TOP); +} + +J2DTextBox::J2DTextBox(J2DPane* p_pane, JSURandomInputStream* p_stream, JKRArchive* p_archive) + : mFont(NULL), mCharColor(), mGradientColor(), mStringPtr(NULL), mWhiteColor(), mBlackColor() { + private_readStream(p_pane, p_stream, p_archive); +} + +J2DTextBox::J2DTextBox(J2DPane* p_pane, JSURandomInputStream* p_stream, u32 param_2, + J2DMaterial* p_material) + : mFont(NULL), mCharColor(), mGradientColor(), mStringPtr(NULL), mWhiteColor(), mBlackColor() { + J2DTextBoxInfo info; + + int startPos = p_stream->getPosition(); + + J2DTbxBlockHeader header; + p_stream->read(&header, 8); + mKind = 'TBX1'; + + int panHeaderPos = p_stream->getPosition(); + J2DTbxBlockHeader panHeader; + p_stream->peek(&panHeader, 8); + makePaneExStream(p_pane, p_stream); + p_stream->seek(panHeaderPos + panHeader.mSize, JSUStreamSeekFrom_SET); + + p_stream->read(&info, 0x20); + J2DMaterial* mat = NULL; + + if (info.mMaterialNum != 0xFFFF) { + mat = &p_material[info.mMaterialNum]; + + if (mat != NULL) { + if (mat->getTevBlock() != NULL) { + JUTFont* font = mat->getTevBlock()->getFont(); + + if (font != NULL) { + mFont = font; + mat->getTevBlock()->setFontUndeleteFlag(); + } + } + mAlpha = mat->getColorBlock()->getMatColor(0)->a; + } + } + + mCharSpacing = info.mCharSpace; + mLineSpacing = info.mLineSpace; + mFontSizeX = info.mFontSizeX; + mFontSizeY = info.mFontSizeY; + mFlags = (info.mHBind << 2) | info.mVBind; + mCharColor = JUtility::TColor(info.mCharColor); + mGradientColor = JUtility::TColor(info.mGradColor); + setConnectParent(info.mConnected); + + u16 strLength = 0; + if (!(param_2 & 0x2000000)) { + strLength = info.field_0x1c; + if ((s16)info.field_0x1c == -1) { + strLength = info.field_0x1e + 1; + } + } + + mStringLength = 0; + mStringPtr = NULL; + + if (strLength != 0) { + mStringPtr = new char[strLength]; + } + + if (mStringPtr != NULL) { + mStringLength = strLength; + + u16 var_r26_2 = strLength - 1 < info.field_0x1e ? u16(strLength - 1) : info.field_0x1e; + + p_stream->peek(mStringPtr, var_r26_2); + mStringPtr[var_r26_2] = 0; + } + + p_stream->skip(info.field_0x1e); + p_stream->seek(startPos + header.mSize, JSUStreamSeekFrom_SET); + mBlackColor = JUtility::TColor(0); + mWhiteColor = JUtility::TColor(0xFFFFFFFF); + + if (mat != NULL && mat->getTevBlock() != NULL) { + u8 tevStageNum = u32(mat->getTevBlock()->getTevStageNum()); + if (tevStageNum != 1) { + J2DGXColorS10 color0(*mat->getTevBlock()->getTevColor(0)); + + J2DGXColorS10 color1(*mat->getTevBlock()->getTevColor(1)); + + mBlackColor = JUtility::TColor(((u8)color0.r << 0x18) | ((u8)color0.g << 0x10) | + ((u8)color0.b << 8) | (u8)color0.a); + mWhiteColor = JUtility::TColor(((u8)color1.r << 0x18) | ((u8)color1.g << 0x10) | + ((u8)color1.b << 8) | (u8)color1.a); + } + } + + field_0x10c = 0.0f; + field_0x110 = 0.0f; + mTextFontOwned = true; +} + +J2DTextBox::J2DTextBox(u64 tag, JGeometry::TBox2<f32> const& bounds, ResFONT const* p_font, + char const* string, s16 strLength, J2DTextBoxHBinding hBind, + J2DTextBoxVBinding vBind) + : J2DPane(tag, bounds), mFont(NULL), mCharColor(), mGradientColor(), mStringPtr(NULL), + mWhiteColor(), mBlackColor() { + initiate(p_font, string, strLength, hBind, vBind); +} + +void J2DTextBox::initiate(ResFONT const* p_font, char const* string, s16 length, + J2DTextBoxHBinding hBind, J2DTextBoxVBinding vBind) { + if (p_font != NULL) { + mFont = new JUTResFont(p_font, NULL); + } + + mCharColor.set(0xFFFFFFFF); + mGradientColor.set(0xFFFFFFFF); + mBlackColor = JUtility::TColor(0); + mWhiteColor = JUtility::TColor(0xFFFFFFFF); + + mFlags = (hBind << 2) | vBind; + mStringLength = 0; + mStringPtr = NULL; + + if (string != NULL && length != 0) { + u32 len = strlen(string); + u16 stringLen = length; + + if (length == -1) { + if (len >= 0xFFFF) { + len = 0xFFFF - 1; + } + stringLen = len + 1; + } + + mStringPtr = new char[stringLen]; + + if (stringLen != 0 && mStringPtr != NULL) { + strncpy(mStringPtr, string, stringLen - 1); + mStringPtr[stringLen - 1] = 0; + mStringLength = stringLen; + } + } + + field_0x10c = 0.0f; + field_0x110 = 0.0f; + mCharSpacing = 0.0f; + + if (mFont == NULL) { + mLineSpacing = 0.0f; + mFontSizeX = 0.0f; + mFontSizeY = 0.0f; + } else { + mLineSpacing = mFont->getLeading(); + mFontSizeX = mFont->getWidth(); + mFontSizeY = mFont->getHeight(); + } + + mKind = 'TBX1'; + mTextFontOwned = true; +} + +void J2DTextBox::private_readStream(J2DPane* p_pane, JSURandomInputStream* p_stream, + JKRArchive* p_archive) { + int position = p_stream->getPosition(); + + J2DTbxBlockHeader header; + p_stream->read(&header, 8); + mKind = header.mTag; + + makePaneStream(p_pane, p_stream); + {JUTResReference ref;} + u8 spA = p_stream->readU8(); + + ResFONT* fontPtr = (ResFONT*)getPointer(p_stream, 'FONT', p_archive); + if (fontPtr != NULL) { + mFont = new JUTResFont(fontPtr, NULL); + } + + mCharColor.set(p_stream->read32b()); + mGradientColor.set(p_stream->read32b()); + u8 tmp = p_stream->read8b(); + mFlags = tmp; + mCharSpacing = p_stream->readS16(); + mLineSpacing = p_stream->readS16(); + mFontSizeX = p_stream->read16b(); + mFontSizeY = p_stream->read16b(); + + s16 stringLen = p_stream->read16b(); + mStringPtr = new char[stringLen + 1]; + + if (mStringPtr != NULL) { + p_stream->read(mStringPtr, stringLen); + mStringPtr[stringLen] = 0; + mStringLength = stringLen + 1; + } else { + p_stream->skip(stringLen); + mStringLength = 0; + } + + spA -= 10; + if (spA != 0) { + tmp = p_stream->read8b(); + if (tmp != 0) { + setConnectParent(true); + } + + spA--; + } + + mBlackColor = JUtility::TColor(0); + mWhiteColor = JUtility::TColor(0xFFFFFFFF); + + if (spA != 0) { + mBlackColor.set(p_stream->read32b()); + spA--; + } + + if (spA != 0) { + mWhiteColor.set(p_stream->read32b()); + spA--; + } + + field_0x10c = 0.0f; + field_0x110 = 0.0f; + p_stream->seek(position + header.mSize, JSUStreamSeekFrom_SET); + mTextFontOwned = true; +} + +J2DTextBox::~J2DTextBox() { + if (mTextFontOwned) { + delete mFont; + } + + delete[] mStringPtr; +} + +void J2DTextBox::setFont(JUTFont* p_font) { + if (p_font) { + if (mTextFontOwned) { + delete mFont; + } + mFont = p_font; + mTextFontOwned = false; + } +} + +void J2DTextBox::draw(f32 posX, f32 posY) { + Mtx m; + + if (isVisible()) { + J2DPrint print(mFont, mCharSpacing, mLineSpacing, mCharColor, mGradientColor, mBlackColor, + mWhiteColor); + print.setFontSize(mFontSizeX, mFontSizeY); + makeMatrix(posX, posY, 0.0f, 0.0f); + + GXLoadPosMtxImm(mPositionMtx, GX_PNMTX0); + GXSetCurrentMtx(0); + GXSetNumIndStages(0); + for (int i = 0; i < 16; i++) { + GXSetTevDirect((GXTevStageID)i); + } + GXSetNumTexGens(1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 60); + + if (mStringPtr != NULL) { + print.print(0.0f, 0.0f, mAlpha, "%s", mStringPtr); + } + MTXIdentity(m); + GXLoadPosMtxImm(m, 0); + } +} + +void J2DTextBox::draw(f32 posX, f32 posY, f32 param_2, J2DTextBoxHBinding hBind) { + Mtx m; + + if (isVisible()) { + J2DPrint print(mFont, mCharSpacing, mLineSpacing, mCharColor, mGradientColor, mBlackColor, + mWhiteColor); + print.setFontSize(mFontSizeX, mFontSizeY); + makeMatrix(posX, posY, 0.0f, 0.0f); + + GXLoadPosMtxImm(mPositionMtx, GX_PNMTX0); + GXSetCurrentMtx(0); + GXSetNumIndStages(0); + for (int i = 0; i < 16; i++) { + GXSetTevDirect((GXTevStageID)i); + } + GXSetNumTexGens(1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 60); + + if (mStringPtr != NULL) { + print.printReturn(mStringPtr, param_2, 0.0f, hBind, VBIND_TOP, 0.0f, -mFontSizeY, + mAlpha); + } + MTXIdentity(m); + GXLoadPosMtxImm(m, 0); + } +} + +char* J2DTextBox::getStringPtr() const { + return mStringPtr; +} + +s32 J2DTextBox::setString(char const* string, ...) { + va_list args; + va_start(args, string); + + delete[] mStringPtr; + + u32 len = strlen(string); + + if (len >= 0xFFFF) { + len = 0xFFFF - 1; + } + + mStringLength = 0; + mStringPtr = new char[len + 1]; + + if (mStringPtr) { + mStringLength = len + 1; + strcpy(mStringPtr, string); + } + + va_end(args); + return len; +} + +s32 J2DTextBox::setString(s16 length, char const* string, ...) { + va_list args; + va_start(args, string); + + delete[] mStringPtr; + mStringPtr = NULL; + + u32 len = strlen(string); + u16 stringLen = length; + + if (length == -1) { + if (len >= 0xFFFF) { + len = 0xFFFF - 1; + } + stringLen = len + 1; + } + + mStringLength = 0; + + if (stringLen != 0) { + mStringPtr = new char[stringLen]; + } + + if (mStringPtr != NULL) { + strncpy(mStringPtr, string, stringLen - 1); + mStringPtr[stringLen - 1] = 0; + mStringLength = stringLen; + } + + va_end(args); + return len; +} + +bool J2DTextBox::setConnectParent(bool connected) { + if (getPaneTree()->getParent() == NULL) { + return false; + } + + if (getPaneTree()->getParent()->getObject()->getTypeID() != 0x11) { + return false; + } + + mConnected = connected; + return connected; +} + +void J2DTextBox::drawSelf(f32 param_0, f32 param_1) { + Mtx identity; + MTXIdentity(identity); + + drawSelf(param_0, param_1, &identity); +} + +void J2DTextBox::drawSelf(f32 param_0, f32 param_1, Mtx* p_mtx) { + Mtx m; + + J2DPrint print(mFont, mCharSpacing, mLineSpacing, mCharColor, mGradientColor, mBlackColor, + mWhiteColor); + print.setFontSize(mFontSizeX, mFontSizeY); + MTXConcat(*p_mtx, mGlobalMtx, m); + + GXLoadPosMtxImm(m, GX_PNMTX0); + GXSetNumIndStages(0); + for (int i = 0; i < 16; i++) { + GXSetTevDirect((GXTevStageID)i); + } + GXSetNumTexGens(1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 60); + + print.locate(param_0 + mBounds.i.x, param_1 + mBounds.i.y); + if (mStringPtr != NULL) { + print.printReturn(mStringPtr, mBounds.getWidth() + 0.0001f, mBounds.getHeight(), + getHBinding(), getVBinding(), field_0x10c, field_0x110, mColorAlpha); + } +} + +void J2DTextBox::resize(f32 x, f32 y) { + if (mConnected && getPaneTree() != NULL && getPaneTree()->getParent() != NULL) { + J2DPane* obj = getPaneTree()->getParent()->getObject(); + + if (obj->getTypeID() == 0x11) { + f32 obj_x = obj->getWidth() + (x - getWidth()); + f32 obj_y = obj->getHeight() + (y - getHeight()); + obj->resize(obj_x, obj_y); + return; + } + } + + J2DPane::resize(x, y); +} + +bool J2DTextBox::isUsed(ResFONT const* p_font) { + if (mFont != NULL && mFont->getResFont() == p_font) { + return true; + } + + return J2DPane::isUsed(p_font); +} + +u16 J2DTextBox::getTypeID() const { + return 19; +} + +bool J2DTextBox::isUsed(ResTIMG const* p_timg) { + return J2DPane::isUsed(p_timg); +} + +void J2DTextBox::rewriteAlpha() { + /* empty function */ +} |
