1#include "Library/Play/Layout/RollParts.h"
2
3#include "Library/Base/StringUtil.h"
4#include "Library/Layout/LayoutActionFunction.h"
5#include "Library/Layout/LayoutActorUtil.h"
6#include "Library/Layout/LayoutInitInfo.h"
7#include "Library/Nerve/NerveSetupUtil.h"
8#include "Library/Nerve/NerveUtil.h"
9
10namespace {
11using namespace al;
12
13NERVE_IMPL(RollParts, Deactive)
14NERVE_IMPL(RollParts, Active)
15NERVE_IMPL(RollParts, RollIn)
16NERVE_IMPL(RollParts, RollOut)
17
18NERVES_MAKE_STRUCT(RollParts, Deactive, Active, RollIn, RollOut)
19} // namespace
20
21namespace al {
22RollParts::RollParts(LayoutActor* parent, const LayoutInitInfo& info, const char* archiveName)
23 : LayoutActor("ロールパーツ") {
24 initLayoutPartsActor(this, parent, info, archiveName, nullptr);
25 initNerve(&NrvRollParts.Deactive, 0);
26}
27
28void RollParts::startLoopAction(const char* actionName, const char* paneName) {
29 startAction(layout: this, actionName, paneName);
30}
31
32void RollParts::setData(const char16** messages, s32 messageCount, bool isLoop, s32 selectedIdx,
33 const char* paneName) {
34 mIsLoop = isLoop;
35 mMessages = messages;
36 mMessageCount = messageCount;
37 mPaneName = paneName;
38 mCurrentActionType = ActionType::Active;
39 mNextActionType = ActionType::Active;
40
41 if (selectedIdx >= 0)
42 mSelectedIdx = selectedIdx;
43
44 setPaneString(this, mPaneName, mMessages[mSelectedIdx], 0);
45 updateHeaderText();
46
47 if (!mHasStatePane)
48 return;
49
50 if (messageCount == 1) {
51 if (isExistAction(layout: this, actionName: "Off", paneName: "State"))
52 startAction(layout: this, actionName: "Off", paneName: "State");
53 } else {
54 if (isExistAction(layout: this, actionName: "On", paneName: "State"))
55 startAction(layout: this, actionName: "On", paneName: "State");
56 }
57}
58
59void RollParts::updateHeaderText() {
60 if (!mHeaderPaneName)
61 return;
62
63 WStringTmp<0x20> text;
64 text.clear();
65
66 if (mMessageCount > 1) {
67 for (s32 i = 0; i < mMessageCount; i++)
68 if (i == mSelectedIdx)
69 text.append(str: u"1");
70 else
71 text.append(str: u"0");
72 }
73
74 setPaneString(this, mHeaderPaneName, text.cstr(), 0);
75}
76
77void RollParts::setSelectedIdx(s32 idx) {
78 mSelectedIdx = idx;
79 setPaneString(this, mPaneName, mMessages[mSelectedIdx], 0);
80}
81
82void RollParts::activate() {
83 if (isNerve(user: this, nerve: &NrvRollParts.Active))
84 return;
85
86 if (mMessages)
87 setPaneString(this, mPaneName, mMessages[mSelectedIdx], 0);
88
89 setNerve(user: this, nerve: &NrvRollParts.Active);
90}
91
92void RollParts::activate(s32 selectedIdx) {
93 if (isNerve(user: this, nerve: &NrvRollParts.Active))
94 return;
95
96 mSelectedIdx = selectedIdx;
97 activate();
98}
99
100void RollParts::deactivate() {
101 if (isNerve(user: this, nerve: &NrvRollParts.Active)) {
102 setNerve(user: this, nerve: &NrvRollParts.Deactive);
103
104 return;
105 }
106
107 if (isRoll())
108 mNextActionType = ActionType::Deactive;
109}
110
111void RollParts::rollRight() {
112 if ((!mIsLoop && mSelectedIdx + 1 >= mMessageCount) || mMessageCount <= 1)
113 return;
114
115 if (isNerve(user: this, nerve: &NrvRollParts.Active)) {
116 mCurrentActionType = ActionType::RollRight;
117 setNerve(user: this, nerve: &NrvRollParts.RollOut);
118
119 return;
120 }
121
122 if (isNerve(user: this, nerve: &NrvRollParts.RollOut) || isNerve(user: this, nerve: &NrvRollParts.RollIn))
123 mNextActionType = ActionType::RollRight;
124}
125
126void RollParts::rollLeft() {
127 if ((!mIsLoop && mSelectedIdx <= 0) || mMessageCount <= 1)
128 return;
129
130 if (isNerve(user: this, nerve: &NrvRollParts.Active)) {
131 mCurrentActionType = ActionType::RollLeft;
132 setNerve(user: this, nerve: &NrvRollParts.RollOut);
133
134 return;
135 }
136
137 if (isNerve(user: this, nerve: &NrvRollParts.RollOut) || isNerve(user: this, nerve: &NrvRollParts.RollIn))
138 mNextActionType = ActionType::RollLeft;
139}
140
141void RollParts::calcCursorTrans(sead::Vector2f* outCursorTrans) const {
142 calcPaneTrans(outCursorTrans, this, "Cursor");
143}
144
145bool RollParts::isJustChangeRoll() const {
146 return isNerve(user: this, nerve: &NrvRollParts.RollIn) && getNerveStep(user: this) == 1;
147}
148
149bool RollParts::isRoll() const {
150 return isNerve(user: this, nerve: &NrvRollParts.RollIn) || isNerve(user: this, nerve: &NrvRollParts.RollOut);
151}
152
153void RollParts::exeDeactive() {
154 if (isFirstStep(user: this) && mDeactiveAction)
155 startAction(layout: this, actionName: mDeactiveAction, paneName: nullptr);
156}
157
158void RollParts::exeActive() {
159 if (isFirstStep(user: this) && mActiveAction)
160 startAction(layout: this, actionName: mActiveAction, paneName: nullptr);
161}
162
163void RollParts::exeRollOut() {
164 if (isFirstStep(user: this)) {
165 startAction(layout: this,
166 actionName: mCurrentActionType == ActionType::RollLeft ? mRollLeftOutAction :
167 mRollRightOutAction,
168 paneName: mRollPaneName);
169
170 if (mCurrentActionType == ActionType::RollLeft) {
171 startHitReaction(this, "左ロール", nullptr);
172 mSelectedIdx--;
173
174 if (mSelectedIdx < 0)
175 mSelectedIdx = mIsLoop ? mMessageCount - 1 : 0;
176 } else {
177 startHitReaction(this, "右ロール", nullptr);
178 mSelectedIdx++;
179
180 if (mSelectedIdx >= mMessageCount)
181 mSelectedIdx = mIsLoop ? 0 : mMessageCount - 1;
182 }
183
184 updateHeaderText();
185 }
186
187 if (isActionEnd(layout: this, paneName: mRollPaneName))
188 setNerve(user: this, nerve: &NrvRollParts.RollIn);
189}
190
191void RollParts::exeRollIn() {
192 if (isFirstStep(user: this)) {
193 startAction(layout: this,
194 actionName: mCurrentActionType == ActionType::RollLeft ? mRollLeftInAction :
195 mRollRightInAction,
196 paneName: mRollPaneName);
197 setPaneString(this, mPaneName, mMessages[mSelectedIdx], 0);
198 }
199
200 if (isActionEnd(layout: this, paneName: mRollPaneName)) {
201 mCurrentActionType = mNextActionType;
202 mNextActionType = ActionType::Active;
203
204 switch (mCurrentActionType) {
205 case ActionType::RollRight:
206 case ActionType::RollLeft:
207 setNerve(user: this, nerve: &NrvRollParts.RollOut);
208 break;
209 case ActionType::Deactive:
210 setNerve(user: this, nerve: &NrvRollParts.Deactive);
211 break;
212 default:
213 setNerve(user: this, nerve: &NrvRollParts.Active);
214 break;
215 }
216 }
217}
218} // namespace al
219