#include "d/lyt/msg_window/d_lyt_msg_window_sword.h" #include "common.h" #include "d/d_gfx.h" #include "d/d_tag_processor.h" #include "d/d_lyt_hio.h" #include "d/d_textwindow_unk.h" #include "d/lyt/d2d.h" #include "d/lyt/d_textbox.h" #include "m/m_vec.h" #include "nw4r/lyt/lyt_group.h" #include "nw4r/lyt/lyt_pane.h" #include "nw4r/lyt/lyt_types.h" #include "nw4r/math/math_types.h" #include "s/s_State.hpp" STATE_DEFINE(dLytMsgWindowSword_c, Invisible); STATE_DEFINE(dLytMsgWindowSword_c, In); STATE_DEFINE(dLytMsgWindowSword_c, Wait); STATE_DEFINE(dLytMsgWindowSword_c, Visible); STATE_DEFINE(dLytMsgWindowSword_c, Out); static const d2d::LytBrlanMapping brlanMap[] = { { "messageWindow_01_in.brlan", "G_inOut_00"}, { "messageWindow_01_out.brlan", "G_inOut_00"}, { "messageWindow_01_loop.brlan", "G_loop_00"}, { "messageWindow_01_color.brlan", "G_color_00"}, {"messageWindow_01_position.brlan", "G_position_00"}, }; #define SWORD_ANIM_IN 0 #define SWORD_ANIM_OUT 1 #define SWORD_ANIM_LOOP 2 #define SWORD_ANIM_COLOR 3 #define SWORD_ANIM_POSITION 4 #define SWORD_NUM_ANIMS 5 #define TRANSLATE_ORIGINAL 0 #define TRANSLATE_TO 1 #define TRANSLATE_FROM 2 static const char *sPanes[] = { "N_aBtn_00", "N_inOut_00", "N_position_00", }; static const char *sTextBoxes[] = { "T_message_00", "T_messageS_00", }; static const char *sGroupName = "G_ref_00"; bool dLytMsgWindowSword_c::build(d2d::ResAccIf_c *resAcc1, d2d::ResAccIf_c *resAcc, dTagProcessor_c *tagProcessor) { mLyt.setResAcc(resAcc); mLyt.build("messageWindow_01.brlyt", nullptr); mLyt.setPriority(0x8A); for (int i = 0; i < SWORD_NUM_ANIMS; i++) { mAnm[i].init(brlanMap[i].mFile, resAcc, mLyt.getLayout(), brlanMap[i].mName); mAnm[i].bind(false); mAnm[i].setAnimEnable(false); } mAnm[SWORD_ANIM_LOOP].setAnimEnable(true); mAnm[SWORD_ANIM_OUT].setAnimEnable(true); mAnm[SWORD_ANIM_OUT].setToEnd(); mLyt.calc(); mAnm[SWORD_ANIM_OUT].setAnimEnable(false); for (int i = 0; i < 3; i++) { mpPanes[i] = mLyt.findPane(sPanes[i]); } for (int i = 0; i < 2; i++) { mpTextboxes[i] = mLyt.getTextBox(sTextBoxes[i]); mpTextboxes[i]->SetTextPositionH(0); mpTextboxes[i]->SetTextPositionV(0); } mpTextboxes[1]->setIsShadow(1); for (int i = 0; i < 1; i++) { mNodes[i].mpLytPane = &mBtn; mBtn.build(resAcc); mSubpaneList.PushBack(&mNodes[i]); } if (mLyt.getLayout()->GetGroupContainer() != nullptr) { nw4r::lyt::Group *g = mLyt.getLayout()->GetGroupContainer()->FindGroupByName(sGroupName); if (g != nullptr) { d2d::dSubPane::linkMeters(g, &mSubpaneList); } } mSwordText.build(resAcc, mSwordType); for (int i = 0; i < TextWindowUnk::BUF_SIZE; i++) { mCharacterData[i].reset(); mTextBuf[i] = L'\0'; } mAnm[SWORD_ANIM_COLOR].setAnimEnable(true); mAnm[SWORD_ANIM_COLOR].setFrame(mSwordType); mpPanes[1]->SetVisible(true); mLyt.calc(); mpPanes[1]->SetVisible(false); mAnm[SWORD_ANIM_COLOR].setAnimEnable(false); mpTagProcessor = tagProcessor; mTranslationOrig.copyFrom(mpPanes[2]->GetTranslate()); mTranslationTo.copyFrom(mpPanes[2]->GetTranslate()); mTranslationFrom.copyFrom(mpPanes[2]->GetTranslate()); mParam = 0; mOffset.x = mOffset.y = 0.0f; mWaitDelay = 0; mHasDrawnThisTick = false; mStateMgr.changeState(StateID_Invisible); return true; } bool dLytMsgWindowSword_c::remove() { mSwordText.remove(); for (d2d::SubPaneList::Iterator it = mSubpaneList.GetBeginIter(); it != mSubpaneList.GetEndIter(); ++it) { d2d::dSubPane *subPane = it->mpLytPane; if (subPane != nullptr) { nw4r::lyt::Pane *parent = subPane->getPane()->GetParent(); parent->RemoveChild(subPane->getPane()); } } for (int i = 0; i < 1; i++) { mNodes[i].mpLytPane->remove(); } mBtn.remove(); for (int i = 0; i < SWORD_NUM_ANIMS; i++) { mAnm[i].remove(); } return true; } void dLytMsgWindowSword_c::initializeState_Invisible() { mBtn.resetToInvisble(); } void dLytMsgWindowSword_c::executeState_Invisible() { if (mShouldBeOpen) { mStateMgr.changeState(StateID_In); } } void dLytMsgWindowSword_c::finalizeState_Invisible() {} void dLytMsgWindowSword_c::initializeState_In() { mAnm[SWORD_ANIM_POSITION].setFrame(mParam); mAnm[SWORD_ANIM_POSITION].setAnimEnable(true); mLyt.calc(); mAnm[SWORD_ANIM_POSITION].setAnimEnable(false); mTranslationTo = mTranslationOrig; mTranslationTo.y = mpPanes[2]->GetTranslate().y; mTranslationFrom = mTranslationTo; mAnm[SWORD_ANIM_IN].setAnimEnable(true); mAnm[SWORD_ANIM_IN].setFrame(0.0f); mpPanes[2]->SetTranslate(mTranslationFrom); } void dLytMsgWindowSword_c::executeState_In() { if (mTranslationFrom != mTranslationTo) { mVec3_c v; if (mAnm[SWORD_ANIM_IN].isEndReached()) { v = mTranslationTo; } else { f32 ratio = mAnm[SWORD_ANIM_IN].getRatio(); if (ratio > 1.0f) { ratio = 1.0f; } v = mTranslationFrom + (mTranslationTo - mTranslationFrom) * ratio; } mpPanes[2]->SetTranslate(v); } if (mAnm[SWORD_ANIM_IN].isEndReached()) { mAnm[SWORD_ANIM_IN].setAnimEnable(false); mStateMgr.changeState(StateID_Wait); } } void dLytMsgWindowSword_c::finalizeState_In() {} void dLytMsgWindowSword_c::initializeState_Wait() { mWaitDelay = dLyt_HIO_c::getInstance()->getMsgWindowWaitDelay(); } void dLytMsgWindowSword_c::executeState_Wait() { if (--mWaitDelay > 0) { return; } mStateMgr.changeState(StateID_Visible); } void dLytMsgWindowSword_c::finalizeState_Wait() {} void dLytMsgWindowSword_c::initializeState_Visible() { nw4r::lyt::Size size = getTextBox()->GetSize(); nw4r::lyt::Size fontSize = getTextBox()->GetFontSize(); // unused nw4r::math::MTX34 transform = getTextBox()->GetGlobalMtx(); mOffset.x = transform._03 - size.width / 2; mOffset.y = transform._13 + size.height / 2; getTextBox()->GetTextDrawRect(); // unused } void dLytMsgWindowSword_c::executeState_Visible() { if (!mShouldBeOpen) { mStateMgr.changeState(StateID_Out); } } void dLytMsgWindowSword_c::finalizeState_Visible() {} void dLytMsgWindowSword_c::initializeState_Out() { mTranslationFrom = mTranslationTo; mAnm[SWORD_ANIM_OUT].setAnimEnable(true); mAnm[SWORD_ANIM_OUT].setFrame(0.0f); } void dLytMsgWindowSword_c::executeState_Out() { if (mTranslationFrom != mTranslationTo) { mVec3_c v; if (mAnm[SWORD_ANIM_OUT].isEndReached()) { v = mTranslationFrom; } else { v.copyFrom(mpPanes[2]->GetTranslate()); mVec3_c tmp = (mTranslationTo - v) / 2.0f; v += tmp; } mpPanes[2]->SetTranslate(v); } if (mAnm[SWORD_ANIM_OUT].isEndReached()) { mAnm[SWORD_ANIM_OUT].setAnimEnable(false); mStateMgr.changeState(StateID_Invisible); } } void dLytMsgWindowSword_c::finalizeState_Out() {} bool dLytMsgWindowSword_c::execute() { mStateMgr.executeState(); for (int i = 0; i < SWORD_NUM_ANIMS; i++) { if (mAnm[i].isEnabled()) { mAnm[i].play(); } } mLyt.calc(); mNodes[0].mpLytPane->execute(); mHasDrawnThisTick = false; return true; } void dLytMsgWindowSword_c::draw() { mLyt.draw(); for (int i = 0; i < TextWindowUnk::BUF_SIZE; i++) { if (mCharacterData[i].displayTimerMaybe >= 0) { if (!mHasDrawnThisTick) { mCharacterData[i].displayTimerMaybe += 1; } mVec3_c v( (mOffset.x + mCharacterData[i].posX) / dGfx_c::get16x9to4x3WidthScaleF(), mOffset.y + mCharacterData[i].posY, 0.0f ); wchar_t str[2]; str[0] = mCharacterData[i].character; str[1] = 0; mSwordText.draw(str, mCharacterData[i].displayTimerMaybe, v, mCharacterData[i].field_0x08); if (mCharacterData[i].displayTimerMaybe >= mSwordText.getAnimDuration()) { mCharacterData[i].displayTimerMaybe = -1; } } } if (!mHasDrawnThisTick) { mHasDrawnThisTick = true; } } void dLytMsgWindowSword_c::open(dAcObjBase_c *obj, u32 param) { mpActor = obj; mParam = param; mShouldBeOpen = true; } bool dLytMsgWindowSword_c::isDoneOpening() const { if (*mStateMgr.getStateID() == StateID_In || *mStateMgr.getStateID() == StateID_Wait) { return false; } return true; } void dLytMsgWindowSword_c::close() { mShouldBeOpen = false; } bool dLytMsgWindowSword_c::isDoneClosing() const { return !(*mStateMgr.getStateID() == StateID_Out); } bool dLytMsgWindowSword_c::setText(const wchar_t *text) { int foundIdx = TextWindowUnk::BUF_SIZE; for (int i = 0; i < TextWindowUnk::BUF_SIZE; i++) { if (mCharacterData[i].displayTimerMaybe >= 0 && foundIdx > mCharacterData[i].field_0x0C) { foundIdx = mCharacterData[i].field_0x0C; } } for (int i = 0; i < TextWindowUnk::BUF_SIZE; i++) { if (i < foundIdx) { mTextBuf[i] = text[i]; } else { mTextBuf[i] = L' '; } } mpTextboxes[0]->SetTagProcessor(mpTagProcessor); mpTextboxes[1]->SetTagProcessor(mpTagProcessor); mpTextboxes[0]->setTextWithTextProcessor(mTextBuf, mpTagProcessor, 0); mpTextboxes[1]->setTextWithTextProcessor(mTextBuf, mpTagProcessor, 0); return foundIdx == TextWindowUnk::BUF_SIZE; }