NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
m_2d.cpp
1#include "egg/gfxe/eggFrustum.h"
2#include "egg/gfxe/eggScreen.h"
3#include "game/mLib/m_2d/animation.hpp"
4#include "game/mLib/m_2d/simple.hpp"
5#include "game/mLib/m_mtx.hpp"
6#include "nw4r/lyt/lyt_group.h"
7#include "nw4r/lyt/lyt_pane.h"
8#include "revolution/MTX/mtx.h"
9#include "revolution/SC/scapi.h"
10#include <game/mLib/m_2d.hpp>
11#include <lib/egg/core/eggExpHeap.h>
12#include <nw4r/ut.h>
13#include <revolution/GX.h>
14#include <constants/sjis_constants.h>
15
16nw4r::ut::List m2d::l_list;
17mAllocator_c *m2d::l_allocator;
18
19void m2d::reset() {
20 nw4r::ut::List_Init(&m2d::l_list, 0);
21}
22
23bool m2d::create(EGG::Heap *parentHeap, size_t size) {
24 nw4r::lyt::LytInit();
25 EGG::ExpHeap *heap = EGG::ExpHeap::create(size, parentHeap, 4);
26 heap->mpName = M2D_HEAP_NAME;
27 l_allocator = new(heap, 4) mAllocator_c();
28 l_allocator->attach(heap, 4);
29 nw4r::lyt::Layout::SetAllocator(l_allocator);
30 m2d::reset();
31 return true;
32}
33
34void m2d::defaultSet() {
35 GXSetCullMode(GX_CULL_NONE);
36 GXSetZMode(0, GX_ALWAYS, 0);
37 static const GXColor l_clearColor = { 0x00000000 };
38 GXSetFog(GX_FOG_NONE, l_clearColor, 0.0f, 0.0f, 0.0f, 0.0f);
39}
40
41void m2d::draw() {
42 defaultSet();
43
44 m2d::Base_c *next = (m2d::Base_c *) nw4r::ut::List_GetNext(&m2d::l_list, nullptr);
45 while (next != nullptr) {
46 next->draw();
47 next = (m2d::Base_c *) nw4r::ut::List_GetNext(&m2d::l_list, next);
48 }
49 m2d::reset();
50}
51
52void m2d::drawBefore(u8 maxDrawOrder) {
53 m2d::Base_c *next = (m2d::Base_c *) nw4r::ut::List_GetNext(&m2d::l_list, nullptr);
54 while (next != nullptr) {
55 if (next->mDrawOrder >= maxDrawOrder) {
56 break;
57 }
58 next->draw();
59 next = (m2d::Base_c *) nw4r::ut::List_GetNext(&m2d::l_list, next);
60 }
61}
62
63void m2d::drawAfter(u8 minDrawOrder) {
64 m2d::Base_c *next = (m2d::Base_c *) nw4r::ut::List_GetNext(&m2d::l_list, nullptr);
65 while (next != nullptr) {
66 if (next->mDrawOrder > minDrawOrder) {
67 next->draw();
68 }
69 next = (m2d::Base_c *) nw4r::ut::List_GetNext(&m2d::l_list, next);
70 }
71}
72
73void m2d::drawBtween(u8 minDrawOrder, u8 maxDrawOrder) {
74 m2d::Base_c *next = (m2d::Base_c *) nw4r::ut::List_GetNext(&m2d::l_list, nullptr);
75 while (next != nullptr) {
76 if (next->mDrawOrder > maxDrawOrder) {
77 break;
78 }
79 if (next->mDrawOrder >= minDrawOrder) {
80 next->draw();
81 }
82 next = (m2d::Base_c *) nw4r::ut::List_GetNext(&m2d::l_list, next);
83 }
84}
85
86mAllocator_c *m2d::getAllocator() {
87 return l_allocator;
88}
89
90// [There are a few float constants that must appear here.
91// Looking at ss, this might be m2d::Anm_c, which doesn't appear in NSMBW.]
92DECL_WEAK
93void DUMMY_ORDERING() {
94 float dummy_float = 1.0f;
95 float dummy_float2 = -1.0f;
96 u16 tmp = 1234;
97 float dummy_float3 = (float) tmp;
98}
99
100nw4r::lyt::AnimTransform *m2d::Layout_c::CreateAnimTransform(const void *binary, nw4r::lyt::ResourceAccessor *accessor) {
101 nw4r::lyt::AnimTransform *transform = nw4r::lyt::Layout::CreateAnimTransform(binary, accessor);
102 if (transform != nullptr) {
103 mAnimTransList.Erase(transform);
104 }
105 return transform;
106}
107
108bool m2d::Layout_c::bindAnimationAuto(const nw4r::lyt::AnimResource &res, nw4r::lyt::ResourceAccessor *resAccessor) {
109 u16 groupNum = res.GetGroupNum();
110 u16 shareInfoNum = res.GetAnimationShareInfoNum();
111 if (groupNum == 0 || shareInfoNum != 0) {
112 return BindAnimationAuto(res, resAccessor);
113 } else if (GetRootPane() == nullptr) {
114 return false;
115 } else if (res.GetResourceBlock() == nullptr) {
116 return false;
117 } else {
118 const nw4r::lyt::AnimationGroupRef *arr = res.GetGroupArray();
119 for (int i = 0; i < groupNum; i++) {
120 nw4r::lyt::Group *group = GetGroupContainer()->FindGroupByName(arr[i].GetName());
121 u16 animNum = res.CalcAnimationNum(group, res.IsDescendingBind());
122 nw4r::lyt::AnimTransform *animTransform = nw4r::lyt::Layout::CreateAnimTransform();
123 animTransform->SetResource(res.GetResourceBlock(), resAccessor, animNum);
124 nw4r::lyt::BindAnimation(group, animTransform, res.IsDescendingBind(), true);
125 }
126 return true;
127 }
128}
129
130bool m2d::ResAccIf_c::attach(void *resource, const char *rootDir) {
131 if (mpResource != nullptr) {
132 return false;
133 }
134 mpResource = resource;
135 return mpResAccessor->Attach(mpResource, rootDir);
136}
137
138void m2d::ResAccIf_c::detach() {
139 mpResource = nullptr;
140 mpResAccessor->Detach();
141}
142
143void *m2d::ResAccIf_c::getResource(ulong type, const char *name) {
144 return mpResAccessor->GetResource(type, name, nullptr);
145}
146
147void m2d::FrameCtrl_c::play() {
148 mPrevFrame = mCurrFrame;
149 float frame = mCurrFrame;
150 if (mFlags & REVERSE) {
151 if (frame >= mRate) {
152 frame -= mRate;
153 } else if (mFlags & NO_LOOP) {
154 frame = 0;
155 } else {
156 frame += mEndFrame - mRate;
157 }
158 } else {
159 frame += mRate;
160 if (mFlags & NO_LOOP) {
161 if (frame > getLastActiveFrame()) {
162 frame = getLastActiveFrame();
163 }
164 } else if (frame >= mEndFrame) {
165 frame -= mEndFrame;
166 }
167 }
168 mCurrFrame = frame;
169}
170
171void m2d::FrameCtrl_c::set(float endFrame, u8 flags, float rate, float currFrame) {
172 if (currFrame < 0.0f) {
173 currFrame = 0.0f;
174 }
175 mEndFrame = endFrame;
176 mCurrFrame = currFrame;
177 setRate(rate);
178 mFlags = flags;
179 mPrevFrame = mCurrFrame;
180}
181
182void m2d::FrameCtrl_c::setFrame(float frame) {
183 mCurrFrame = frame;
184 mPrevFrame = frame;
185}
186
187void m2d::FrameCtrl_c::setRate(float rate) {
188 mRate = rate;
189}
190
191bool m2d::FrameCtrl_c::isStop() const {
192 switch (mFlags) {
193 case NO_LOOP:
194 return mCurrFrame >= getLastActiveFrame();
195 case NO_LOOP | REVERSE:
196 return mCurrFrame <= 0.0f;
197 default:
198 return false;
199 }
200}
201
202void m2d::Base_c::entry() {
203 m2d::Base_c *next = (m2d::Base_c *) nw4r::ut::List_GetNext(&m2d::l_list, nullptr);
204 while (next != nullptr) {
205 if (next->mDrawOrder > mDrawOrder) {
206 nw4r::ut::List_Insert(&m2d::l_list, next, this);
207 return;
208 }
209 next = (m2d::Base_c *) nw4r::ut::List_GetNext(&m2d::l_list, next);
210 }
211 nw4r::ut::List_Append(&m2d::l_list, this);
212}
213
214m2d::Simple_c::Simple_c() {
215 mpResAcc = nullptr;
216 mPos.set(0.0f, 0.0f, 0.0f);
217 mFlags = 0;
218 if (SCGetAspectRatio() == SC_ASPECT_WIDE) {
219 mDrawInfo.SetLocationAdjustScale(nw4r::math::VEC2(19.0f / 26.0f, 1.0f));
220 mDrawInfo.SetLocationAdjust(true);
221 }
222}
223
224void m2d::Simple_c::calc() {
225 calcBefore();
226 mMtx_c mtx;
227 PSMTXIdentity(mtx);
228 mVec3_c pos = mPos;
229 PSMTXTransApply(mtx, mtx, pos.x, pos.y, pos.z);
230 mDrawInfo.SetViewMtx(mtx);
231 calcAfter();
232}
233
234void m2d::Simple_c::calcBefore() {
235 u32 option = 0;
236 if (mFlags & SKIP_INVISIBLE) {
237 option = nw4r::lyt::ANIMOPTION_SKIP_INVISIBLE;
238 }
239 mLayout.Animate(option);
240}
241
242void m2d::Simple_c::calcAfter() {
243 mDrawInfo.SetViewRect(mLayout.GetLayoutRect());
244 mLayout.CalculateMtx(mDrawInfo);
245}
246
247void m2d::Simple_c::draw() {
248 nw4r::ut::Rect rect = mLayout.GetLayoutRect();
249 float near = 0.0f;
250 float far = 500.0f;
251 EGG::Screen screen;
252 bool isWide = EGG::Screen::sTVMode == EGG::Screen::TV_MODE_16_9;
253 float width_16_9 = EGG::Screen::sTVModeInfo[EGG::Screen::TV_MODE_16_9].width;
254 float width_4_3 = EGG::Screen::sTVModeInfo[EGG::Screen::TV_MODE_4_3].width;
255 float left = isWide ? width_16_9 * rect.left / width_4_3 : rect.left;
256 float right = isWide ? width_16_9 * rect.right / width_4_3 : rect.right;
257 screen.mProjType = EGG::Frustum::PROJ_ORTHO;
258 screen.ResetOrthographic(rect.top, rect.bottom, left, right, near, far);
259 if (isWide) {
260 screen.mScale = nw4r::math::VEC3(width_4_3 / width_16_9, 1.0f, 1.0f);
261 }
262 screen.SetProjectionGX();
263 mLayout.Draw(mDrawInfo);
264}
265
266bool m2d::Simple_c::build(const char *lytName, m2d::ResAccIf_c *resAcc) {
267 if (mLayout.GetRootPane() != nullptr) {
268 return true;
269 }
270 if (resAcc == nullptr) {
271 resAcc = mpResAcc;
272 if (resAcc == nullptr) {
273 return false;
274 }
275 }
276 void *res = resAcc->getResource(0, lytName);
277 if (res == nullptr) {
278 return false;
279 }
280 bool result = mLayout.Build(res, resAcc->getResAccessor());
281 if (result) {
282 calc();
283 }
284 return result;
285}
286
287int m2d::Simple_c::patrolPane_local(nw4r::lyt::Pane *pane, patrolPaneFunc1 func1, patrolPaneFunc2 func2, void *arg) {
288 int ret = 0;
289 if (func2 == nullptr || func2(pane) == 1) {
290 if (ret = func1(pane, arg), ret != 0) {
291 return ret;
292 }
293 }
294 nw4r::lyt::PaneList &list = pane->GetChildList();
295 for (
296 nw4r::lyt::PaneList::RevIterator it = list.GetEndReverseIter();
297 it != list.GetBeginReverseIter();
298 ++it
299 ) {
300 ret = patrolPane_local(&*it, func1, func2, arg);
301 if (ret != 0) {
302 return ret;
303 }
304 }
305 return ret;
306}
307
308bool m2d::Simple_c::patrolPane(patrolPaneFunc1 func1, patrolPaneFunc2 func2, void *arg) {
309 nw4r::lyt::Pane *pane = mLayout.GetRootPane();
310 int ret = patrolPane_local(pane, func1, func2, arg);
311 return ret != 2;
312}
313
314bool m2d::AnmResV2_c::create(const char *name, m2d::ResAccIf_c *resAcc, m2d::Layout_c *layout, bool useOverride) {
315 mAnimResource.Set(resAcc->getResource(0, name));
316 if (useOverride) {
317 layout->bindAnimationAuto(mAnimResource, resAcc->getResAccessor());
318 } else {
319 layout->BindAnimationAuto(mAnimResource, resAcc->getResAccessor());
320 }
321 mGroupNum = mAnimResource.GetGroupNum();
322 mGroupAnim = new(getAllocator()->mpHeap, 4) GroupAnimTransform_s[mGroupNum];
323 const nw4r::lyt::AnimationGroupRef *groupArray = mAnimResource.GetGroupArray();
324 for (int i = 0; i < mGroupNum; i++) {
325 nw4r::lyt::AnimTransform *transform = nullptr;
326 nw4r::lyt::Group *group = layout->GetGroupContainer()->FindGroupByName(groupArray->GetName());
327 mGroupAnim[i].mpGroup = group;
328 nw4r::lyt::detail::PaneLinkList &list = group->GetPaneList();
329 for (
330 nw4r::lyt::detail::PaneLinkList::Iterator it = list.GetBeginIter();
331 it != list.GetEndIter();
332 ++it
333 ) {
334 nw4r::lyt::AnimationLink *link = findAnmLink(it->mTarget, false);
335 if (link != nullptr) {
336 transform = link->GetAnimTransform();
337 break;
338 }
339 }
340 mGroupAnim[i].mpAnimTransform = transform;
341 groupArray++;
342 }
343 return true;
344}
345
346bool m2d::AnmResV2_c::remove() {
347 delete[] mGroupAnim;
348 mGroupAnim = nullptr;
349 return true;
350}
351
352m2d::GroupAnimTransform_s *m2d::AnmResV2_c::getGroupAnimTransform(const char *name) {
353 GroupAnimTransform_s *res = nullptr;
354 for (int i = 0; i < mGroupNum; i++) {
355 if (strcmp(name, mGroupAnim[i].mpGroup->GetName()) == 0) {
356 res = &mGroupAnim[i];
357 break;
358 }
359 }
360 return res;
361}
362
363void m2d::AnmResV2_c::setAnmEnable(nw4r::lyt::Group *group, bool enable) {
364 for (
365 nw4r::lyt::detail::PaneLinkList::Iterator it = group->GetPaneList().GetBeginIter();
366 it != group->GetPaneList().GetEndIter();
367 ++it
368 ) {
369 nw4r::lyt::AnimationLink *link = findAnmLink(it->mTarget, false);
370 if (link != nullptr) {
371 it->mTarget->SetAnimationEnable(link->GetAnimTransform(), enable, false);
372 }
373 }
374}
375
376void m2d::AnmResV2_c::updateFrame(nw4r::lyt::Group *group, float frame) {
377 for (
378 nw4r::lyt::detail::PaneLinkList::Iterator it = group->GetPaneList().GetBeginIter();
379 it != group->GetPaneList().GetEndIter();
380 ++it
381 ) {
382 nw4r::lyt::Pane *pane = it->mTarget;
383 nw4r::lyt::AnimationLink *link = findAnmLink(pane, false);
384 if (link != nullptr) {
385 setAnmFrame(pane, frame);
386 }
387 }
388}
389
390nw4r::lyt::AnimationLink *m2d::AnmResV2_c::findAnmLink(nw4r::lyt::Pane *pane, bool recursive) {
391 nw4r::lyt::AnimationLink *res = pane->FindAnimationLinkSelf(mAnimResource);
392 if (res != nullptr) {
393 return res;
394 }
395 u8 matNum = pane->GetMaterialNum();
396 for (u8 i = 0; i < matNum; i++) {
397 res = pane->GetMaterial(i)->FindAnimationLink(mAnimResource);
398 if (res != nullptr) {
399 return res;
400 }
401 }
402 if (recursive) {
403 for (
404 nw4r::lyt::PaneList::Iterator it = pane->GetChildList().GetBeginIter();
405 it != pane->GetChildList().GetEndIter();
406 ++it
407 ) {
408 res = findAnmLink(&*it, true);
409 if (res != nullptr) {
410 return res;
411 }
412 }
413 }
414 return nullptr;
415}
416
417void m2d::AnmResV2_c::setAnmFrame(nw4r::lyt::Pane *pane, float frame) {
418 nw4r::lyt::AnimationLink *res = pane->FindAnimationLinkSelf(mAnimResource);
419 if (res != nullptr) {
420 res->GetAnimTransform()->SetFrame(frame);
421 }
422 u8 matNum = pane->GetMaterialNum();
423 for (u8 i = 0; i < matNum; i++) {
424 res = pane->GetMaterial(i)->FindAnimationLink(mAnimResource);
425 if (res != nullptr) {
426 res->GetAnimTransform()->SetFrame(frame);
427 }
428 }
429}
430
431bool m2d::AnmGroupBase_c::create(AnmResV2_c *anmRes, const char *name) {
432 mpAnmRes = anmRes;
433 mpGroupAnim = mpAnmRes->getGroupAnimTransform(name);
434 if (mpGroupAnim != nullptr) {
435 u8 flags = FrameCtrl_c::NO_LOOP;
436 if (mpGroupAnim->mpAnimTransform->IsLoopData()) {
437 flags &= ~FrameCtrl_c::NO_LOOP;
438 }
439 mpFrameCtrl->set(mpGroupAnim->mpAnimTransform->GetFrameSize(), flags, 1.0f, -1.0f);
440 updateFrame();
441 }
442 return true;
443}
444
445void m2d::AnmGroupBase_c::setAnmEnable(bool enable) {
446 mpAnmRes->setAnmEnable(mpGroupAnim->mpGroup, enable);
447 if (enable) {
448 mFlags |= FLAG_ENABLED;
449 } else {
450 mFlags &= ~FLAG_ENABLED;
451 }
452}
453
454void m2d::AnmGroupBase_c::updateFrame() {
455 mpAnmRes->updateFrame(mpGroupAnim->mpGroup, mpFrameCtrl->getFrame());
456}
An allocator class that wraps an EGG:Allocator .