diff --git a/config/SOME01/splits.txt b/config/SOME01/splits.txt index 6f672e2..abb8413 100644 --- a/config/SOME01/splits.txt +++ b/config/SOME01/splits.txt @@ -3032,6 +3032,7 @@ GameUtil/FaderFlash.cpp: GameUtil/Layout.cpp: .text start:0x801D85BC end:0x801D9E40 .ctors start:0x801F7568 end:0x801F756C + .rodata start:0x802E4C20 end:0x802E4C38 .data start:0x803162F8 end:0x803163E0 .sbss start:0x80320FA0 end:0x80320FA8 .sdata2 start:0x80329590 end:0x803295A8 diff --git a/config/SOME01/symbols.txt b/config/SOME01/symbols.txt index d6c8062..52bf50d 100644 --- a/config/SOME01/symbols.txt +++ b/config/SOME01/symbols.txt @@ -6522,7 +6522,7 @@ __dt__Q34nw4r3lyt4PaneFv = .text:0x8019B890; // type:function size:0x13C AppendChild__Q34nw4r3lyt4PaneFPQ34nw4r3lyt4Pane = .text:0x8019B9D0; // type:function size:0x50 PrependChild__Q34nw4r3lyt4PaneFPQ34nw4r3lyt4Pane = .text:0x8019BA20; // type:function size:0x50 RemoveChild__Q34nw4r3lyt4PaneFPQ34nw4r3lyt4Pane = .text:0x8019BA70; // type:function size:0x3C -GetPaneRect__Q34nw4r3lyt4PaneCFv = .text:0x8019BAB0; // type:function size:0x110 +GetPaneRect__Q34nw4r3lyt4PaneCFRCQ34nw4r3lyt8DrawInfo = .text:0x8019BAB0; // type:function size:0x110 GetVtxColor__Q34nw4r3lyt4PaneCFUl = .text:0x8019BBC0; // type:function size:0xC SetVtxColor__Q34nw4r3lyt4PaneFUlQ34nw4r2ut5Color = .text:0x8019BBD0; // type:function size:0x4 GetColorElement__Q34nw4r3lyt4PaneCFUl = .text:0x8019BBE0; // type:function size:0x24 @@ -7875,14 +7875,14 @@ fn_801D8578__6CSceneFv = .text:0x801D8578; // type:function size:0x1C _24__6CSceneFv = .text:0x801D8594; // type:function size:0x8 fn_801D859C__11CFaderFlashFv = .text:0x801D859C; // type:function size:0x20 fn_801D85BC__8CBtnPaneFPQ34nw4r3lyt4PanePQ34nw4r3lyt8DrawInfo = .text:0x801D85BC; // type:function size:0x114 -fn_801D86D0 = .text:0x801D86D0; // type:function size:0x1AC -fn_801D887C = .text:0x801D887C; // type:function size:0x1E0 -fn_801D8A5C = .text:0x801D8A5C; // type:function size:0x5A0 -fn_801D8FFC = .text:0x801D8FFC; // type:function size:0x94 -fn_801D9090 = .text:0x801D9090; // type:function size:0x610 -fn_801D96A0 = .text:0x801D96A0; // type:function size:0x26C -fn_801D990C = .text:0x801D990C; // type:function size:0x68 -fn_801D9974 = .text:0x801D9974; // type:function size:0xB8 +fn_801D86D0__8CBtnPaneFPQ34nw4r3lyt4PanePQ34nw4r3lyt8DrawInfo = .text:0x801D86D0; // type:function size:0x1AC +fn_801D887C__8CBtnPaneFPQ34nw4r3lyt4PanePQ34nw4r3lyt8DrawInfo = .text:0x801D887C; // type:function size:0x1E0 +fn_801D8A5C__FPQ34nw4r3lyt7TextBoxff = .text:0x801D8A5C; // type:function size:0x5A0 +fn_801D8FFC__10CExBtnPaneFPQ34nw4r3lyt4Pane = .text:0x801D8FFC; // type:function size:0x94 +fn_801D9090__10CExBtnPaneFPQ34nw4r4math4VEC2bPQ34nw4r3lyt8DrawInfo = .text:0x801D9090; // type:function size:0x610 +_10__10CExBtnPaneF9EBtnStateb = .text:0x801D96A0; // type:function size:0x26C +_14__10CExBtnPaneFv = .text:0x801D990C; // type:function size:0x68 +fn_801D9974__10CExBtnPaneFv = .text:0x801D9974; // type:function size:0xB8 __ct__7CLayoutFv = .text:0x801D9A2C; // type:function size:0x20 _0C__7CLayoutFv = .text:0x801D9A4C; // type:function size:0x84 __dt__16CLayoutAnimationFv = .text:0x801D9AD0; // type:function size:0x40 diff --git a/include/nw4r/lyt/pane.h b/include/nw4r/lyt/pane.h index 70d99b1..97e400e 100644 --- a/include/nw4r/lyt/pane.h +++ b/include/nw4r/lyt/pane.h @@ -65,6 +65,9 @@ class Pane : public detail::PaneBase { virtual Material *GetMaterial() const; virtual Material *GetMaterial(u32 idx) const; + ut::Rect GetPaneRect() const; + ut::Rect GetPaneRect(const DrawInfo &) const; + bool IsVisible() const { return detail::TestBit(mFlag, 0); } @@ -100,6 +103,10 @@ class Pane : public detail::PaneBase { mScale = value; } + const Size &GetSize() const { + return mSize; + } + void SetSize(const Size &value) { mSize = value; } @@ -107,6 +114,10 @@ class Pane : public detail::PaneBase { Pane *GetParent() const { return mpParent; } + + ut::LinkList &GetChildList() { + return mChildList; + } protected: virtual void LoadMtx(const DrawInfo &drawInfo); diff --git a/include/nw4r/ut/LinkList.h b/include/nw4r/ut/LinkList.h index 02cb13c..d4a9f2b 100644 --- a/include/nw4r/ut/LinkList.h +++ b/include/nw4r/ut/LinkList.h @@ -435,6 +435,7 @@ namespace nw4r { namespace ut static LinkListNode *GetNodeFromPointer(T *p) { + NW4R_ASSERT_PTR_NULL(p, 563); return reinterpret_cast(reinterpret_cast(p) + I); } diff --git a/include/nw4r/ut/TextWriterBase.h b/include/nw4r/ut/TextWriterBase.h index acf131a..37950f3 100644 --- a/include/nw4r/ut/TextWriterBase.h +++ b/include/nw4r/ut/TextWriterBase.h @@ -112,6 +112,12 @@ template class TextWriterBase : public CharWriter { f32 CalcStringWidth(const T* pStr, int len) const; void CalcStringRect(Rect* pRect, const T* pStr, int len) const; + f32 CalcStringWidth(const T* str) const { + NW4R_ASSERT_PTR(this, 212); + NW4R_ASSERT_PTR(str, 213); + return CalcStringWidth(str, StrLen(str)); + } + void CalcStringRect(Rect* pRect, const T* str) const { NW4R_ASSERT_PTR(this, 233); NW4R_ASSERT_PTR(pRect, 234); diff --git a/src/Game/CursorLayout.cpp b/src/Game/CursorLayout.cpp index 6c0f476..5d453f6 100644 --- a/src/Game/CursorLayout.cpp +++ b/src/Game/CursorLayout.cpp @@ -50,8 +50,6 @@ void CCursorLayout::_10(void) { } } -extern Vec2 lbl_80320FA0; - void CCursorLayout::_18(nw4r::lyt::DrawInfo *drawInfo) { for (s32 i = 0; i < CURSOR_COUNT; i++) { if (mPaneTrans[i]->IsVisible()) { @@ -65,9 +63,7 @@ void CCursorLayout::_18(nw4r::lyt::DrawInfo *drawInfo) { )); } else { - mPaneTrans[i]->SetTranslate(nw4r::math::VEC2( - lbl_80320FA0.x, lbl_80320FA0.y - )); + mPaneTrans[i]->SetTranslate(lbl_80320FA0); } } diff --git a/src/Game/Epilogue/MyLayout.cpp b/src/Game/Epilogue/MyLayout.cpp index c5e4a25..d236e80 100644 --- a/src/Game/Epilogue/MyLayout.cpp +++ b/src/Game/Epilogue/MyLayout.cpp @@ -10,9 +10,6 @@ #include -// TODO -extern "C" void fn_801D8A5C(nw4r::lyt::TextBox *, f32, f32); - static const char layoutFile_epilogue[] = "epilogue.brlyt"; DECL_SECTION(".sdata") static const char *layoutFileTable[] = { layoutFile_epilogue, NULL }; diff --git a/src/Game/Error/MyLayout.cpp b/src/Game/Error/MyLayout.cpp index 9b3fc2d..edbf4a4 100644 --- a/src/Game/Error/MyLayout.cpp +++ b/src/Game/Error/MyLayout.cpp @@ -208,17 +208,15 @@ void Error::CMyLayout::_10(void) { mUnkF8 = false; } -extern Vec2 lbl_80320FA0; - void Error::CMyLayout::_18(nw4r::lyt::DrawInfo *drawInfo) { CController *controller = gControllerManager->fn_801D5FF0(0); - Vec2 vec = (Vec2) { + nw4r::math::VEC2 vec ( controller->fn_801D523C(this).x, controller->fn_801D523C(this).y - }; + ); - if (!mUnkF8 || !controller->fn_801D52D4()) { + if (mUnkF8 || !controller->fn_801D52D4()) { vec.x = lbl_80320FA0.x; vec.y = lbl_80320FA0.y; } diff --git a/src/Game/Perfect/MyLayout.cpp b/src/Game/Perfect/MyLayout.cpp index 9b480ce..4702648 100644 --- a/src/Game/Perfect/MyLayout.cpp +++ b/src/Game/Perfect/MyLayout.cpp @@ -9,9 +9,6 @@ #include "GameTable.hpp" #include "GiftTable.hpp" -// TODO -extern "C" void fn_801D8A5C(nw4r::lyt::TextBox *, f32, f32); - const char layoutFile_perfect[] = "perfect.brlyt"; diff --git a/src/GameUtil/Layout.cpp b/src/GameUtil/Layout.cpp index 46d51ad..c94cc2a 100644 --- a/src/GameUtil/Layout.cpp +++ b/src/GameUtil/Layout.cpp @@ -4,25 +4,248 @@ #include "LayoutManager.hpp" -// TODO: match https://decomp.me/scratch/EEu7e +#include "Controller.hpp" + +#include "Sound.hpp" + +nw4r::math::VEC2 lbl_80320FA0 (-9999.0f, -9999.0f); + bool CBtnPane::fn_801D85BC(nw4r::lyt::Pane *pane, nw4r::lyt::DrawInfo *drawInfo) { if (!drawInfo->IsLocationAdjust()) { return false; } - else { + + nw4r::lyt::Pane *parent = pane->GetParent(); + if (parent == NULL) { + return pane->IsLocationAdjust(); + } + + return (pane->IsLocationAdjust() || fn_801D85BC(parent, drawInfo)); +} + +nw4r::math::VEC2 CBtnPane::fn_801D86D0(nw4r::lyt::Pane *pane, nw4r::lyt::DrawInfo *drawInfo) { + nw4r::math::VEC2 vec (0.0f, 0.0f); + + for (pane; pane != NULL; pane = pane->GetParent()) { nw4r::lyt::Pane *parent = pane->GetParent(); - if (parent == NULL) { - return pane->IsLocationAdjust(); - } - else { - if (!pane->IsLocationAdjust()) { - return fn_801D85BC(parent, drawInfo); + if (parent != NULL) { + if (fn_801D85BC(parent, drawInfo)) { + vec.x += pane->GetTranslate().x * drawInfo->GetLocationAdjustScale().x; + vec.y += pane->GetTranslate().y; + continue; } - return false; } + vec.x += pane->GetTranslate().x; + vec.y += pane->GetTranslate().y; + } + + return vec; +} + +nw4r::math::VEC3 CBtnPane::fn_801D887C(nw4r::lyt::Pane *pane, nw4r::lyt::DrawInfo *drawInfo) { + nw4r::math::VEC2 tmp (fn_801D86D0(pane, drawInfo)); + + return nw4r::math::VEC3(tmp.x, tmp.y, 0.0f); +} + +f32 fn_801D8A5C(nw4r::lyt::TextBox *textBox, f32 fontWidth, f32 fontHeight) { + nw4r::ut::WideTextWriter textWriter; + + textWriter.SetFont(*textBox->GetFont()); + textWriter.SetFontSize(fontWidth, fontHeight); + textWriter.SetLineSpace(textBox->GetLineSpace()); + textWriter.SetCharSpace(textBox->GetCharSpace()); + + f32 strWidth = textWriter.CalcStringWidth(textBox->GetString()); + f32 strWidthR; + if (strWidth > textBox->GetSize().width) { + strWidthR = (textBox->GetSize().width * 0.95f) / strWidth; + } else { + strWidthR = 1.0f; } + fontWidth *= strWidthR; + textBox->SetFontSize(nw4r::lyt::Size(fontWidth, fontHeight)); + + return strWidthR; } + +void CExBtnPane::fn_801D8FFC(nw4r::lyt::Pane *pane) { + mPane = pane; + mDefaultAnime = NULL; + mFocusAnime = NULL; + mActionAnime = NULL; + mEnabled = true; + mUnk25 = false; + mUnk28 = true; + _10(eBtnState_Default, true); + mUnk18 = 0; + mVibrateOnHover = true; + mSelectSfxID = -1; + mActionSfxID = -1; + mControllerChan = 0; + mUnk26 = false; + mUnk27 = false; +} + +// not matching (stack swaps) +EBtnState CExBtnPane::fn_801D9090(nw4r::math::VEC2 *arg0, bool arg1, nw4r::lyt::DrawInfo *drawInfo) { + mUnk26 = false; + mUnk27 = false; + if (!mEnabled) { + return eBtnState_Default; + } + + arg0 = (arg0) ? arg0 : &nw4r::math::VEC2(-9999.0f, -9999.0f); + + nw4r::lyt::Pane *pane = mPane; + nw4r::math::VEC2 posVec = *arg0; + nw4r::ut::Rect paneRect = pane->GetPaneRect(*drawInfo); + if (fn_801D85BC(pane, drawInfo)) { + paneRect.left *= drawInfo->GetLocationAdjustScale().x; + paneRect.right *= drawInfo->GetLocationAdjustScale().x; + } + + nw4r::math::VEC2 vec = fn_801D86D0(pane, drawInfo); + paneRect.left += vec.x; + paneRect.right += vec.x; + paneRect.top += vec.y; + paneRect.bottom += vec.y; + bool temp = ((paneRect.left <= posVec.x) && (posVec.x <= paneRect.right) && + (paneRect.bottom <= posVec.y) && (posVec.y <= paneRect.top)); + + switch (mState) { + case eBtnState_Default: + if (temp && !isFocusPlaying()) { + _10(eBtnState_Selected, true); + return eBtnState_Selected; + } + + if ((mDefaultAnime != NULL) && (!mDefaultAnime->getIsPlaying())) { + if (!isFocusPlaying()) { + mDefaultAnime->playFromBeginning(); + } + } + break; + + case eBtnState_Selected: + if (!temp && !isFocusPlaying()) { + _10(eBtnState_Default, true); + break; + } + + if (temp && arg1 && !isActionPlaying()) { + _10(eBtnState_Active, true); + mUnk26 = true; + return eBtnState_Active; + } + break; + + case eBtnState_Active: + if (!isActionPlaying()) { + _10(eBtnState_Unk03, true); + mUnk27 = true; + return eBtnState_Unk03; + } + break; + + case eBtnState_Unk03: + if (temp && mUnk25) { + s32 selectSfxTemp; + bool vibrateTemp; + + vibrateTemp = mVibrateOnHover; + selectSfxTemp = mSelectSfxID; + + mVibrateOnHover = false; + mSelectSfxID = -1; + _10(eBtnState_Selected, true); + mVibrateOnHover = vibrateTemp; + mSelectSfxID = selectSfxTemp; + return eBtnState_Selected; + } + _10(eBtnState_Default, true); + break; + } + return eBtnState_Default; +} + +void CExBtnPane::_10(EBtnState state, bool arg1) { + if (!mEnabled) { + return; + } + + if (!arg1 && (mState == state)) { + return; + } + + EBtnState prevState = mState; + mState = state; + + switch (state) { + case eBtnState_Default: + if ((prevState == eBtnState_Selected) && (mFocusAnime != NULL)) { + if (!mFocusAnime->getIsPlaying()) { + mFocusAnime->playFromBeginReverse(); + } else { + mFocusAnime->fn_801DA09C(TRUE); + mFocusAnime->setIsPlaying(true); + } + } + break; + + case eBtnState_Selected: + if ( + ((prevState == eBtnState_Default) || ((prevState == eBtnState_Unk03) && mUnk28)) && + (mFocusAnime != NULL)) { + if (mDefaultAnime != NULL) { + mDefaultAnime->setIsPlaying(false); + } + mFocusAnime->playFromBeginForward(); + fn_801D9974(); + } + if (mVibrateOnHover) { + gControllerManager->fn_801D5FF0(mControllerChan)->_40("****--------", false); + } + if (mSelectSfxID != -1) { + gSoundManager->play(mSelectSfxID); + } + break; + + case eBtnState_Active: + if (mActionAnime != NULL) { + mActionAnime->playFromBeginForward(); + } + if (mActionSfxID != -1) { + gSoundManager->play(mActionSfxID); + } + break; + } +} + +CW_FORCE_STRINGS(GameUtil_Layout_cpp, "LYT_ANIM"); + +void CExBtnPane::_14(void) { + _10(eBtnState_Default, true); + if (mFocusAnime != NULL) { + mFocusAnime->fn_801DA094(FALSE); + mFocusAnime->setIsPlaying(false); + mFocusAnime->fn_801DA20C(); + } +} + +void CExBtnPane::fn_801D9974(void) { + nw4r::lyt::Pane *pane = mPane; + s32 unk18 = mUnk18; + for (pane; (unk18 > 0) && (pane != NULL); pane = pane->GetParent()) { + nw4r::ut::LinkList &parentChildList = pane->GetParent()->GetChildList(); + parentChildList.Erase(pane); + parentChildList.PushBack(pane); + unk18--; + } +} + + CLayout::CLayout(void) { mAnimationCount = 0; mLayout = NULL; diff --git a/src/GameUtil/Layout.hpp b/src/GameUtil/Layout.hpp index 14e5c7e..6cfd70f 100644 --- a/src/GameUtil/Layout.hpp +++ b/src/GameUtil/Layout.hpp @@ -14,14 +14,20 @@ enum EBtnState { eBtnState_Unk03 }; +extern nw4r::math::VEC2 lbl_80320FA0; + class CBtnPane { public: CBtnPane() {} protected: static bool fn_801D85BC(nw4r::lyt::Pane *pane, nw4r::lyt::DrawInfo *drawInfo); + static nw4r::math::VEC2 fn_801D86D0(nw4r::lyt::Pane *pane, nw4r::lyt::DrawInfo *drawInfo); + static nw4r::math::VEC3 fn_801D887C(nw4r::lyt::Pane *pane, nw4r::lyt::DrawInfo *drawInfo); }; +f32 fn_801D8A5C(nw4r::lyt::TextBox *textBox, f32 fontWidth, f32 fontHeight); + class CExBtnPaneManager; class CExBtnPane : public CBtnPane { @@ -34,6 +40,10 @@ class CExBtnPane : public CBtnPane { CExBtnPane(void) {} + void fn_801D8FFC(nw4r::lyt::Pane *pane); + EBtnState fn_801D9090(nw4r::math::VEC2 *, bool, nw4r::lyt::DrawInfo *); + void fn_801D9974(void); + nw4r::lyt::Pane *getPane(void) const { return mPane; } @@ -57,6 +67,13 @@ class CExBtnPane : public CBtnPane { mActionSfxID = soundID; } + bool isFocusPlaying(void) { + return (mFocusAnime && mFocusAnime->getIsPlaying()); + } + bool isActionPlaying(void) { + return (mActionAnime && mActionAnime->getIsPlaying()); + } + private: nw4r::lyt::Pane *mPane; EBtnState mState; @@ -101,7 +118,7 @@ class CExBtnPaneManager { public: virtual ~CExBtnPaneManager(void); - virtual void _0C(Vec2 *, bool, nw4r::lyt::DrawInfo *drawInfo); // TODO typing + virtual void _0C(nw4r::math::VEC2 *, bool, nw4r::lyt::DrawInfo *drawInfo); CExBtnPaneManager(u8 buttonCount);