From 53aa4e2efa0f5e2d662857ebdb593d33099b86bf Mon Sep 17 00:00:00 2001 From: elijah-thomas774 Date: Sun, 9 Jun 2024 21:04:42 -0400 Subject: [PATCH] lyt_animation *ALMOST* --- config/SOUE01/splits.txt | 2 + config/SOUE01/symbols.txt | 2 +- configure.py | 2 +- include/nw4r/lyt/lyt_animation.h | 35 +- include/nw4r/lyt/lyt_common.h | 5 + include/nw4r/lyt/lyt_material.h | 12 + include/nw4r/lyt/lyt_pane.h | 8 + include/nw4r/lyt/lyt_resources.h | 8 +- include/rvl/OS/OSFastCast.h | 16 + src/nw4r/lyt/lyt_animation.cpp | 584 ++++++++++++++++++++++++------- src/nw4r/lyt/lyt_layout.cpp | 6 +- 11 files changed, 544 insertions(+), 136 deletions(-) diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index 1f087339..5428e745 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -383,6 +383,8 @@ nw4r/lyt/lyt_drawInfo.cpp: nw4r/lyt/lyt_animation.cpp: .text start:0x80490A40 end:0x80491FF4 + .data start:0x8056E7B8 end:0x8056E7DC + .sdata2 start:0x8057F2C0 end:0x8057F2E0 nw4r/lyt/lyt_resourceAccessor.cpp: .text start:0x80492000 end:0x80492058 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 5ec068cc..f309f30a 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -37084,7 +37084,7 @@ __vt__Q34nw4r3lyt8Bounding = .data:0x8056E6C0; // type:object size:0x74 @LOCAL@SetupGX__Q34nw4r3lyt8MaterialFbUc@kAlpSels = .data:0x8056E758; // type:object size:0x20 data:4byte __vt__Q34nw4r3lyt8Material = .data:0x8056E778; // type:object size:0x30 __vt__Q34nw4r3lyt8DrawInfo = .data:0x8056E7A8; // type:object size:0xC -lbl_8056E7B8 = .data:0x8056E7B8; // type:object size:0x28 +__vt__Q34nw4r3lyt18AnimTransformBasic = .data:0x8056E7B8; // type:object size:0x24 __vt__Q34nw4r3lyt16ResourceAccessor = .data:0x8056E7E0; // type:object size:0x14 __vt__Q34nw4r3lyt24MultiArcResourceAccessor = .data:0x8056E7F8; // type:object size:0x14 __vt__Q34nw4r3lyt19ArcResourceAccessor = .data:0x8056E80C; // type:object size:0x14 diff --git a/configure.py b/configure.py index 88f585b2..80b5fc29 100644 --- a/configure.py +++ b/configure.py @@ -252,7 +252,7 @@ def EGGLib(lib_name, objects): def nw4rLib(lib_name, objects, extra_cflags=[]): return { "lib": lib_name, - "mw_version": "Wii/1.1", # most seem to be around 1.2, snd is 1.6 + "mw_version": "Wii/1.3", # most seem to be around 1.2, snd is 1.6 "cflags": cflags_nw4r + extra_cflags, "host": False, "objects": objects, diff --git a/include/nw4r/lyt/lyt_animation.h b/include/nw4r/lyt/lyt_animation.h index 4db537ea..64e6195c 100644 --- a/include/nw4r/lyt/lyt_animation.h +++ b/include/nw4r/lyt/lyt_animation.h @@ -25,14 +25,24 @@ public: virtual void Animate(u32 idx, Pane *pPane) = 0; // at 0x1C virtual void Animate(u32 idx, Material *pMaterial) = 0; // at 0x20 - res::AnimationBlock *GetAnimResource() const { + f32 GetFrameMax() const { + return mFrame; // TOOD + } + + const res::AnimationBlock *GetAnimResource() const { return mpRes; } + f32 GetFrame() const { + return mFrame; + } + void SetFrame(f32 frame) { + mFrame = frame; + } ut::LinkListNode mLink; // at 0x4 protected: - res::AnimationBlock *mpRes; // at 0xC - f32 mFrame; // at 0x10 + const res::AnimationBlock *mpRes; // at 0xC + f32 mFrame; // at 0x10 }; class AnimResource { @@ -44,10 +54,10 @@ public: void Set(const void *anmResBuf); void Init(); u16 GetGroupNum() const; - AnimationGroupRef *GetGroupArray() const; + const AnimationGroupRef *GetGroupArray() const; bool IsDescendingBind() const; u16 GetAnimationShareInfoNum() const; - AnimationShareInfo *GetAnimationShareInfoArray() const; + const AnimationShareInfo *GetAnimationShareInfoArray() const; u16 CalcAnimationNum(Pane *pPane, bool bRecursive) const; u16 CalcAnimationNum(Group *pGroup, bool bRecursive) const; @@ -71,7 +81,7 @@ private: class AnimTransformBasic : public AnimTransform { public: AnimTransformBasic(); - AnimationLink *FindUnbindLink(AnimationLink *pLink); + AnimationLink *FindUnbindLink(AnimationLink *pLink) const; virtual ~AnimTransformBasic(); // at 0x08 virtual void SetResource(const res::AnimationBlock *pRes, ResourceAccessor *pResAccessor); // at 0x0C @@ -84,8 +94,12 @@ public: template AnimationLink *Bind(T *pTarget, AnimationLink *pAnimLink, u16 idx, bool bDisable); -private: - void *mpFileResAry; // at 0x14 + AnimationLink *GetAnimLinkAry() const { + return mAnimLinkAry; + } + +protected: + void **mpFileResAry; // at 0x14 AnimationLink *mAnimLinkAry; // at 0x18 u16 mAnimLinkNum; // at 0x1C }; @@ -97,7 +111,10 @@ public: Init(); Set(pTargetPane, animRes); } - bool IsEnabled() const; + bool IsEnabled() const { + // TODO + return false; + } static u16 FindAnimContent(const res::AnimationBlock *pAnimBlock, const char *animContName, u8 animContType); void Init(); void Set(Pane *pTargetPane, const AnimResource &animRes); diff --git a/include/nw4r/lyt/lyt_common.h b/include/nw4r/lyt/lyt_common.h index bd09aae9..ffee8317 100644 --- a/include/nw4r/lyt/lyt_common.h +++ b/include/nw4r/lyt/lyt_common.h @@ -41,6 +41,11 @@ inline void SetVerticalPosition(u8 *pVar, u8 newVal) { *pVar = newVal * 3 + GetHorizontalPosition(*pVar); } +inline const char *GetStrTableStr(const void *pStrTable, int index) { + const u32 *offsets = (u32 *)pStrTable; + const char *stringPool = (char *)pStrTable; + return &stringPool[offsets[index]]; +} typedef math::VEC2 TexCoordData[TEXCOORD_VTX_COUNT]; class TexCoordAry { diff --git a/include/nw4r/lyt/lyt_material.h b/include/nw4r/lyt/lyt_material.h index 3a1d4dce..ec2c924e 100644 --- a/include/nw4r/lyt/lyt_material.h +++ b/include/nw4r/lyt/lyt_material.h @@ -78,8 +78,15 @@ public: } // SetTexSRTElement__Q34nw4r3lyt8MaterialFUlUlf + void SetTexSRTElement(u32 texSRTIdx, u32 eleIdx, f32 value) { + f32 *srtAry = (f32 *)&(GetTexSRTAry()[texSRTIdx]); + srtAry[eleIdx] = value; + } // GetTexturePtr__Q34nw4r3lyt8MaterialFUc + TexMap *GetTexturePtr(u8 idx) { + return &GetTexMapAry()[idx]; + } // GetTexSRTCap__Q34nw4r3lyt8MaterialCFv u8 GetTexSRTCap() const { @@ -90,7 +97,12 @@ public: u8 GetIndTexSRTCap() const { return mGXMemCap.indSRT; } + // SetIndTexSRTElement__Q34nw4r3lyt8MaterialFUlUlf + void SetIndTexSRTElement(u32 texSRTIdx, u32 eleIdx, f32 value) { + f32 *srtAry = (f32 *)&(GetIndTexSRTAry()[texSRTIdx]); + srtAry[eleIdx] = value; + } ut::LinkList *GetAnimationList() { return &mAnimList; diff --git a/include/nw4r/lyt/lyt_pane.h b/include/nw4r/lyt/lyt_pane.h index 54e16eea..b73d8d30 100644 --- a/include/nw4r/lyt/lyt_pane.h +++ b/include/nw4r/lyt/lyt_pane.h @@ -78,6 +78,10 @@ public: mSize = value; } + void SetSRTElement(u32 idx, f32 f) { + ((f32 *)&mTranslate)[idx] = f; + } + const res::ExtUserDataList *GetExtUserDataList() const { return mpExtUserDataList; } @@ -85,6 +89,10 @@ public: mpExtUserDataList = pBlock; } + const char *GetName() const { + return mName; + } + Pane(); Pane(const res::Pane *pBlock); void Init(); diff --git a/include/nw4r/lyt/lyt_resources.h b/include/nw4r/lyt/lyt_resources.h index b90e101f..dcdd27d4 100644 --- a/include/nw4r/lyt/lyt_resources.h +++ b/include/nw4r/lyt/lyt_resources.h @@ -30,8 +30,8 @@ struct BinaryFileHeader { }; struct DataBlockHeader { - u32 kind; // at 0x0 - u32 size; // at 0x4 + char kind[4]; // at 0x0 + u32 size; // at 0x4 }; struct TexSRT { @@ -250,7 +250,7 @@ struct WindowContent { struct AnimationBlock { DataBlockHeader blockHeader; // at 0x00 u16 frameSize; // at 0x08 - bool loop; // at 0x0A + u8 loop; // at 0x0A u8 padding1; // at 0x0B u16 fileNum; // at 0x0C u16 animContNum; // at 0x0E @@ -308,7 +308,7 @@ struct AnimationContent { char name[20]; // at 0x00 u8 num; // at 0x14 u8 type; // at 0x15 - u8 padding[2]; // at 0x17 + u8 padding[2]; // at 0x67 }; } // namespace res diff --git a/include/rvl/OS/OSFastCast.h b/include/rvl/OS/OSFastCast.h index 5791018a..8db17517 100644 --- a/include/rvl/OS/OSFastCast.h +++ b/include/rvl/OS/OSFastCast.h @@ -57,11 +57,27 @@ static inline u16 __OSf32tou16(register f32 arg) { r = *(u16 *)ptr; return r; } +static inline u8 __OSf32tou8(register f32 arg) { + f32 a; + register f32 *ptr = &a; + register u8 r; + // clang-format off + asm { + psq_st arg, 0(ptr), 1, 2 + lbz r, 0(ptr) + } + // clang-format on + + return r; +} static inline void OSf32tou16(const f32 *in, u16 *out) { *out = __OSf32tou16(*in); } +static inline void OSf32tou8(const f32 *in, u8 *out) { + *out = __OSf32tou8(*in); +} static inline f32 __OSs16tof32(register const s16 *arg) { register f32 ret; diff --git a/src/nw4r/lyt/lyt_animation.cpp b/src/nw4r/lyt/lyt_animation.cpp index 31c7e9ae..0767b4a9 100644 --- a/src/nw4r/lyt/lyt_animation.cpp +++ b/src/nw4r/lyt/lyt_animation.cpp @@ -1,110 +1,219 @@ #include #include +#include #include namespace nw4r { namespace lyt { namespace { -// GetStepCurveValue__27@unnamed@lyt_animation_cpp@FfPCQ44nw4r3lyt3res7StepKeyUl -// GetStepCurveValue__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FfPCQ44nw4r3lyt3res7StepKeyUl -u16 GetStepCurveValue(f32 frame, const res::StepKey *keyArray, u32 keySize) { - int ikeyL, ikeyR, ikeyCenter; - - const res::StepKey ¢erKey = keyArray[0]; -} - // RIsSame__27@unnamed@lyt_animation_cpp@Ffff // RIsSame__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@Ffff bool RIsSame(f32 a, f32 b, f32 tolerance) { - f32 c; + f32 c = a - b; + return (-tolerance < c && c < tolerance); +} + +// GetStepCurveValue__27@unnamed@lyt_animation_cpp@FfPCQ44nw4r3lyt3res7StepKeyUl +// GetStepCurveValue__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FfPCQ44nw4r3lyt3res7StepKeyUl +u16 GetStepCurveValue(f32 frame, const res::StepKey *keyArray, u32 keySize) { + if (keySize == 1 || frame <= keyArray[0].frame) { + return keyArray[0].value; + } + if (frame >= keyArray[keySize - 1].frame) { + return keyArray[keySize - 1].value; + } + + int ikeyL = 0; + int ikeyR = keySize - 1; + while (ikeyL != ikeyR - 1 && ikeyL != ikeyR) { + int ikeyCenter = (ikeyL + ikeyR) / 2; + const res::StepKey ¢erKey = keyArray[ikeyCenter]; + if (frame < centerKey.frame) { + ikeyR = ikeyCenter; + } else { + ikeyL = ikeyCenter; + } + } + + if (RIsSame(frame, keyArray[ikeyR].frame, 0.001f)) { + return keyArray[ikeyR].value; + } else { + return keyArray[ikeyL].value; + } } // GetHermiteCurveValue__27@unnamed@lyt_animation_cpp@FfPCQ44nw4r3lyt3res10HermiteKeyUl // GetHermiteCurveValue__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FfPCQ44nw4r3lyt3res10HermiteKeyUl f32 GetHermiteCurveValue(f32 frame, const res::HermiteKey *keyArray, u32 keySize) { - int ikeyL, ikeyR, ikeyCenter; - const res::HermiteKey &key0 = keyArray[0]; - const res::HermiteKey &key1 = keyArray[0]; - f32 t1, t2; - f32 v0, v1; - f32 s0, s1; - f32 t1t1t2; - f32 t1t1t2t2; - f32 t1t1t1t2t2; - f32 t1t1t1t2t2t2; + if (keySize == 1 || frame <= keyArray[0].frame) { + return keyArray[0].value; + } + if (frame >= keyArray[keySize - 1].frame) { + return keyArray[keySize - 1].value; + } + + int ikeyL = 0; + int ikeyR = keySize - 1; + while (ikeyL != ikeyR - 1 && ikeyL != ikeyR) { + int ikeyCenter = (ikeyL + ikeyR) / 2; + if (frame <= keyArray[ikeyCenter].frame) { + ikeyR = ikeyCenter; + } else { + ikeyL = ikeyCenter; + } + } + const res::HermiteKey &key0 = keyArray[ikeyL]; + const res::HermiteKey &key1 = keyArray[ikeyR]; + + if (RIsSame(frame, key1.frame, 0.001f)) { + if (ikeyR < keySize - 1 && key1.frame == keyArray[ikeyR + 1].frame) { + return keyArray[ikeyR + 1].value; + } else { + return key1.value; + } + } + + f32 t1 = frame - key0.frame; + f32 t2 = 1.0f / (key1.frame - key0.frame); + + f32 v0 = key0.value; + f32 v1 = key1.value; + f32 s0 = key0.slope; + f32 s1 = key1.slope; + + f32 t1t1t2 = t1 * t1 * t2; + f32 t1t1t2t2 = t1t1t2 * t2; + f32 t1t1t1t2t2 = t1 * t1t1t2t2; + f32 t1t1t1t2t2t2 = t1t1t1t2t2 * t2; + + return v0 * (2.0f * t1t1t1t2t2t2 - 3.0f * t1t1t2t2 + 1.0f) + v1 * (-2.0f * t1t1t1t2t2t2 + 3.0f * t1t1t2t2) + + s0 * (t1 + (t1t1t1t2t2 - 2.0f * t1t1t2)) + s1 * (t1t1t1t2t2 - t1t1t2); } // AnimatePainSRT__27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt4PanePCQ44nw4r3lyt3res13AnimationInfoPCUlf // AnimatePaneSRT__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt4PanePCQ44nw4r3lyt3res13AnimationInfoPCUlf void AnimatePaneSRT(Pane *pPane, const res::AnimationInfo *pAnimInfo, const u32 *animTargetOffsets, f32 frame) { - int i; - const res::AnimationTarget *pAnimTarget; - const res::HermiteKey *keys; + for (int i = 0; i < pAnimInfo->num; i++) { + const res::AnimationTarget *pAnimTarget = + detail::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); + const res::HermiteKey *keys = detail::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keyOffset); + pPane->SetSRTElement(pAnimTarget->target, GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum)); + } } // AnimateVisibility__27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt4PanePCQ44nw4r3lyt3res13AnimationInfoPCUlf // AnimateVisibility__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt4PanePCQ44nw4r3lyt3res13AnimationInfoPCUlf void AnimateVisibility(Pane *pPane, const res::AnimationInfo *pAnimInfo, const u32 *animTargetOffsets, f32 frame) { - int i; - const res::AnimationTarget *pAnimTarget; - const res::StepKey *keys; + for (int i = 0; i < pAnimInfo->num; i++) { + const res::AnimationTarget *pAnimTarget = + detail::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); + const res::StepKey *keys = detail::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keyOffset); + pPane->SetVisible(GetStepCurveValue(frame, keys, pAnimTarget->keyNum) != 0); + } } // AnimateVertexColor__27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt4PanePCQ44nw4r3lyt3res13AnimationInfoPCUlf // AnimateVertexColor__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt4PanePCQ44nw4r3lyt3res13AnimationInfoPCUlf void AnimateVertexColor(Pane *pPane, const res::AnimationInfo *pAnimInfo, const u32 *animTargetOffsets, f32 frame) { - int i; - const res::AnimationTarget *pAnimTarget; - const res::HermiteKey *keys; - f32 value; - u8 u8Val; + for (int i = 0; i < pAnimInfo->num; i++) { + const res::AnimationTarget *pAnimTarget = + detail::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); + const res::HermiteKey *keys = detail::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keyOffset); + f32 value = GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum); + value += 0.5f; + u8 u8Val; + OSf32tou8(&value, &u8Val); + pPane->SetColorElement(pAnimTarget->target, u8Val); + } } // AnimateMaterialColor__27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt8MaterialPCQ44nw4r3lyt3res13AnimationInfoPCUlf // AnimateMaterialColor__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt8MaterialPCQ44nw4r3lyt3res13AnimationInfoPCUlf void AnimateMaterialColor(Material *pMaterial, const res::AnimationInfo *pAnimInfo, const u32 *animTargetOffsets, f32 frame) { - int i; - const res::AnimationTarget *pAnimTarget; - const res::HermiteKey *keys; - f32 value; - s16 s16Val; + for (int i = 0; i < pAnimInfo->num; i++) { + const res::AnimationTarget *pAnimTarget = + detail::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); + const res::HermiteKey *keys = detail::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keyOffset); + f32 value = GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum); + value += 0.5f; + s16 s16Val; + OSf32tos16(&value, &s16Val); + s16Val = ut::Min(ut::Max(s16Val, -0x400), 1023); + pMaterial->SetColorElement(pAnimTarget->target, s16Val); + } } // AnimateTextureSRT__27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt8MaterialPCQ44nw4r3lyt3res13AnimationInfoPCUlf // AnimateTextureSRT__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt8MaterialPCQ44nw4r3lyt3res13AnimationInfoPCUlf void AnimateTextureSRT(Material *pMaterial, const res::AnimationInfo *pAnimInfo, const u32 *animTargetOffsets, f32 frame) { - int i; - const res::AnimationTarget *pAnimTarget; - const res::HermiteKey *keys; + for (int i = 0; i < pAnimInfo->num; i++) { + const res::AnimationTarget *pAnimTarget = + detail::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); + if (pAnimTarget->id < pMaterial->GetTexSRTCap()) { + const res::HermiteKey *keys = + detail::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keyOffset); + + pMaterial->SetTexSRTElement(pAnimTarget->id, pAnimTarget->target, + GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum)); + } + } } // AnimateTexturePattern__27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt8MaterialPCQ44nw4r3lyt3res13AnimationInfoPCUlfPPv // AnimateTexturePattern__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt8MaterialPCQ44nw4r3lyt3res13AnimationInfoPCUlfPPv void AnimateTexturePattern(Material *pMaterial, const res::AnimationInfo *pAnimInfo, const u32 *animTargetOffsets, f32 frame, void **tpls) { - int i; - const res::AnimationTarget *pAnimTarget; - const res::StepKey *keys; - u16 fileIdx; + for (int i = 0; i < pAnimInfo->num; i++) { + const res::AnimationTarget *pAnimTarget = + detail::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); + if (pAnimTarget->id < pMaterial->GetTextureNum()) { + const res::StepKey *keys = detail::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keyOffset); + u16 fileIdx = GetStepCurveValue(frame, keys, pAnimTarget->keyNum); + if (tpls[fileIdx] != nullptr) { + pMaterial->GetTexturePtr(pAnimTarget->id)->ReplaceImage((TPLPalette *)tpls[fileIdx], 0); + } + } + } } // AnimateIndTexSRT__27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt8MaterialPCQ44nw4r3lyt3res13AnimationInfoPCUlf // AnimateIndTexSRT__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt8MaterialPCQ44nw4r3lyt3res13AnimationInfoPCUlf void AnimateIndTexSRT(Material *pMaterial, const res::AnimationInfo *pAnimInfo, const u32 *animTargetOffsets, f32 frame) { - int i; - const res::AnimationTarget *pAnimTarget; - const res::HermiteKey *keys; + for (int i = 0; i < pAnimInfo->num; i++) { + const res::AnimationTarget *pAnimTarget = + detail::ConvertOffsToPtr(pAnimInfo, animTargetOffsets[i]); + if (pAnimTarget->id < pMaterial->GetIndTexSRTCap()) { + const res::HermiteKey *keys = + detail::ConvertOffsToPtr(pAnimTarget, pAnimTarget->keyOffset); + pMaterial->SetIndTexSRTElement(pAnimTarget->id, pAnimTarget->target, + GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum)); + } + } } // IsBindAnimation__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt8MaterialPQ34nw4r3lyt13AnimTransform -bool IsBindAnimation(Material *pMaterial, AnimTransform *pAnimTrans) {} +bool IsBindAnimation(Material *pMaterial, AnimTransform *pAnimTrans) { + return false; // Early return in release builds, no call to FindAnimationLink in SS, exists in tfp2 + + if (pMaterial->FindAnimationLink(pAnimTrans)) { + return true; + } + return false; +} // IsBindAnimation__Q34nw4r3lyt27@unnamed@lyt_animation_cpp@FPQ34nw4r3lyt4PanePQ34nw4r3lyt13AnimTransform -bool IsBindAnimation(Pane *pPane, AnimTransform *pAnimTrans) {} +bool IsBindAnimation(Pane *pPane, AnimTransform *pAnimTrans) { + return false; // Early return in release builds, no call to FindAnimationLink in SS, exists in tfp2 + + if (pPane->FindAnimationLinkSelf(pAnimTrans)) { + return true; + } + return false; +} } // namespace @@ -115,174 +224,413 @@ AnimTransform::AnimTransform() : mLink(), mpRes(NULL), mFrame(0.0f) {} AnimTransform::~AnimTransform() {} // GetFrameSize__Q34nw4r3lyt13AnimTransformCFv -u16 AnimTransform::GetFrameSize() const {} +u16 AnimTransform::GetFrameSize() const { + return mpRes->frameSize; +} // IsLoopData__Q34nw4r3lyt13AnimTransformCFv -bool AnimTransform::IsLoopData() const {} +bool AnimTransform::IsLoopData() const { + return mpRes->loop; +} // __ct__Q34nw4r3lyt18AnimTransformBasicFv -AnimTransformBasic::AnimTransformBasic() : AnimTransform() {} +AnimTransformBasic::AnimTransformBasic() : mpFileResAry(nullptr), mAnimLinkAry(nullptr), mAnimLinkNum(0) {} // __dt__Q34nw4r3lyt18AnimTransformBasicFv -AnimTransformBasic::~AnimTransformBasic() {} +AnimTransformBasic::~AnimTransformBasic() { + Layout::DeletePrimArray(mAnimLinkAry); + Layout::DeletePrimArray(mpFileResAry); +} // SetResource__Q34nw4r3lyt18AnimTransformBasicFPCQ44nw4r3lyt3res14AnimationBlockPQ34nw4r3lyt16ResourceAccessor -void AnimTransformBasic::SetResource(const res::AnimationBlock *pRes, ResourceAccessor *pResAccessor) {} +void AnimTransformBasic::SetResource(const res::AnimationBlock *pRes, ResourceAccessor *pResAccessor) { + SetResource(pRes, pResAccessor, pRes->animContNum); +} // SetResource__Q34nw4r3lyt18AnimTransformBasicFPCQ44nw4r3lyt3res14AnimationBlockPQ34nw4r3lyt16ResourceAccessorUs void AnimTransformBasic::SetResource(const res::AnimationBlock *pRes, ResourceAccessor *pResAccessor, u16 animNum) { - const u32 *fineNameOffsets; - int i; - const char *fileName; + mpRes = pRes; + mpFileResAry = nullptr; + if (mpRes->fileNum != 0) { + mpFileResAry = Layout::NewArray(mpRes->fileNum); + if (mpFileResAry) { + const u32 *fileNameOffsets = detail::ConvertOffsToPtr(mpRes, sizeof(*mpRes)); + for (int i = 0; i < mpRes->fileNum; i++) { + const char *fileName = detail::GetStrTableStr(fileNameOffsets, i); + mpFileResAry[i] = pResAccessor->GetResource('timg', fileName, nullptr); + } + } + } + + mAnimLinkAry = Layout::NewArray(animNum); + if (mAnimLinkAry) { + mAnimLinkNum = animNum; + } } // Bind__Q34nw4r3lyt18AnimTransformBasicFPQ34nw4r3lyt4Paneb // Bind__Q34nw4r3lyt18AnimTransformBasicFPQ34nw4r3lyt4Panebb void AnimTransformBasic::Bind(Pane *pPane, bool bRecursive, bool bDisable) { - AnimationLink *pCrAnimLink; - const u32 *animContOffsets; - u16 i; - // const res::AnimationContent &animCont; - Pane *pFindPane; - Material *pFindMat; + AnimationLink *pCrAnimLink = nullptr; + const u32 *animContOffsets = detail::ConvertOffsToPtr(mpRes, mpRes->animContOffsetsOffset); + for (u16 i = 0; i < mpRes->animContNum; i++) { + const res::AnimationContent &animCont = + *detail::ConvertOffsToPtr(mpRes, animContOffsets[i]); + if (animCont.type == 0) { + Pane *pFindPane = pPane->FindPaneByName(animCont.name, bRecursive); + if (pFindPane && !IsBindAnimation(pFindPane, this)) { + pCrAnimLink = Bind(pFindPane, pCrAnimLink, i, bDisable); + if (pCrAnimLink == nullptr) { + break; + } + } + } else { + Material *pFindMat = pPane->FindMaterialByName(animCont.name, bRecursive); + if (pFindMat && !IsBindAnimation(pFindMat, this)) { + pCrAnimLink = Bind(pFindMat, pCrAnimLink, i, bDisable); + if (pCrAnimLink == nullptr) { + break; + } + } + } + } } // Bind__Q34nw4r3lyt18AnimTransformBasicFPQ34nw4r3lyt8Material // Bind__Q34nw4r3lyt18AnimTransformBasicFPQ34nw4r3lyt8Materialb void AnimTransformBasic::Bind(Material *pMaterial, bool bDisable) { - AnimationLink *pCrAnimLink; - const u32 *animContOffsets; - u16 i; - // const res::AnimationContent &animCont; + AnimationLink *pCrAnimLink = nullptr; + const u32 *animContOffsets = detail::ConvertOffsToPtr(mpRes, mpRes->animContOffsetsOffset); + for (u16 i = 0; i < mpRes->animContNum; i++) { + const res::AnimationContent &animCont = + *detail::ConvertOffsToPtr(mpRes, animContOffsets[i]); + if (animCont.type == 1) { + if (detail::EqualsMaterialName(pMaterial->GetName(), animCont.name) && !IsBindAnimation(pMaterial, this)) { + pCrAnimLink = Bind(pMaterial, pCrAnimLink, i, bDisable); + if (pCrAnimLink == nullptr) { + break; + } + } + } + } } // Animate__Q34nw4r3lyt18AnimTransformBasicFUlPQ34nw4r3lyt4Pane void AnimTransformBasic::Animate(u32 idx, Pane *pPane) { - u32 animContOffsets; - res::AnimationContent *pAnimCont; - const u32 *animInfoOffsets; - int i; - res::AnimationInfo *pAnimInfo; - const u32 *animTargetOffsets; + u32 animContOffsets = detail::ConvertOffsToPtr(mpRes, mpRes->animContOffsetsOffset)[idx]; + const res::AnimationContent *pAnimCont = detail::ConvertOffsToPtr(mpRes, animContOffsets); + const u32 *animInfoOffsets = detail::ConvertOffsToPtr(pAnimCont, sizeof(res::AnimationContent)); + + for (int i = 0; i < pAnimCont->num; i++) { + const res::AnimationInfo *pAnimInfo = + detail::ConvertOffsToPtr(pAnimCont, animInfoOffsets[i]); + const u32 *animTargetOffsets = detail::ConvertOffsToPtr(pAnimInfo, sizeof(res::AnimationInfo)); + switch (pAnimInfo->kind) { + case 'RLPA': + AnimatePaneSRT(pPane, pAnimInfo, animTargetOffsets, mFrame); + break; + case 'RLVI': + AnimateVisibility(pPane, pAnimInfo, animTargetOffsets, mFrame); + break; + case 'RLVC': + AnimateVertexColor(pPane, pAnimInfo, animTargetOffsets, mFrame); + break; + } + } } // Animate__Q34nw4r3lyt18AnimTransformBasicFUlPQ34nw4r3lyt8Material void AnimTransformBasic::Animate(u32 idx, Material *pMaterial) { - u32 animContOffsets; - res::AnimationContent *pAnimCont; - const u32 *animInfoOffsets; - int i; - res::AnimationInfo *pAnimInfo; - const u32 *animTargetOffsets; + u32 animContOffsets = detail::ConvertOffsToPtr(mpRes, mpRes->animContOffsetsOffset)[idx]; + const res::AnimationContent *pAnimCont = detail::ConvertOffsToPtr(mpRes, animContOffsets); + const u32 *animInfoOffsets = detail::ConvertOffsToPtr(pAnimCont, sizeof(res::AnimationContent)); + + for (int i = 0; i < pAnimCont->num; i++) { + const res::AnimationInfo *pAnimInfo = + detail::ConvertOffsToPtr(pAnimCont, animInfoOffsets[i]); + const u32 *animTargetOffsets = detail::ConvertOffsToPtr(pAnimInfo, sizeof(res::AnimationInfo)); + switch (pAnimInfo->kind) { + case 'RLMC': + AnimateMaterialColor(pMaterial, pAnimInfo, animTargetOffsets, mFrame); + break; + case 'RLTS': + AnimateTextureSRT(pMaterial, pAnimInfo, animTargetOffsets, mFrame); + break; + case 'RLTP': + if (mpFileResAry) { + AnimateTexturePattern(pMaterial, pAnimInfo, animTargetOffsets, mFrame, mpFileResAry); + } + break; + case 'RLIM': + AnimateIndTexSRT(pMaterial, pAnimInfo, animTargetOffsets, mFrame); + break; + } + } } // FindUnbindLink__Q34nw4r3lyt18AnimTransformBasicCFPQ34nw4r3lyt13AnimationLink -AnimationLink *AnimTransformBasic::FindUnbindLink(AnimationLink *pLink) {} +AnimationLink *AnimTransformBasic::FindUnbindLink(AnimationLink *pLink) const { + if (pLink == nullptr) { + pLink = mAnimLinkAry; + } + + while (pLink < &mAnimLinkAry[mAnimLinkNum]) { + if (pLink->GetAnimTransform() == nullptr) { + return pLink; + } + pLink++; + } + + return nullptr; +} // Bind__Q34nw4r3lyt18AnimTransformBasicFPQ34nw4r3lyt4PanePQ34nw4r3lyt13AnimationLinkUsb_PQ34nw4r3lyt13AnimationLink // Bind__Q34nw4r3lyt18AnimTransformBasicFPQ34nw4r3lyt8MaterialPQ34nw4r3lyt13AnimationLinkUsb_PQ34nw4r3lyt13AnimationLink template -AnimationLink *AnimTransformBasic::Bind(T *pTarget, AnimationLink *pAnimLink, u16 idx, bool bDisable) {} +AnimationLink *AnimTransformBasic::Bind(T *pTarget, AnimationLink *pAnimLink, u16 idx, bool bDisable) { + pAnimLink = FindUnbindLink(pAnimLink); + if (!pAnimLink) { + return nullptr; + } + pAnimLink->Set(this, idx, bDisable); + pTarget->AddAnimationLink(pAnimLink); + pAnimLink++; + return pAnimLink; +} // __ct__Q34nw4r3lyt12AnimResourceFv -AnimResource::AnimResource() {} +AnimResource::AnimResource() { + Init(); +} // Set__Q34nw4r3lyt12AnimResourceFPCv void AnimResource::Set(const void *animResBuf) { - const res::BinaryFileHeader *pFileHeader; - const res::DataBlockHeader *pDataBlockHead; - int i; + Init(); + const res::BinaryFileHeader *pFileHeader = (res::BinaryFileHeader *)animResBuf; + if (detail::TestFileHeader(*pFileHeader, 'RLAN')) { + if (detail::TestFileVersion(*pFileHeader)) { + mpFileHeader = pFileHeader; + const res::DataBlockHeader *pDataBlockHead = + detail::ConvertOffsToPtr(mpFileHeader, mpFileHeader->headerSize); + for (int i = 0; i < mpFileHeader->dataBlocks; i++) { + switch (detail::GetSignatureInt(pDataBlockHead->kind)) { + case 'pat1': + mpTagBlock = (res::AnimationTagBlock *)pDataBlockHead; + break; + case 'pah1': + mpShareBlock = (res::AnimationShareBlock *)pDataBlockHead; + break; + case 'pai1': + mpResBlock = (res::AnimationBlock *)pDataBlockHead; + break; + } + pDataBlockHead = detail::ConvertOffsToPtr(pDataBlockHead, pDataBlockHead->size); + } + } + } } // Init__Q34nw4r3lyt12AnimResourceFv -void AnimResource::Init() {} +void AnimResource::Init() { + mpFileHeader = nullptr; + mpResBlock = nullptr; + mpTagBlock = nullptr; + mpShareBlock = nullptr; +} // GetGroupNum__Q34nw4r3lyt12AnimResourceCFv -u16 AnimResource::GetGroupNum() const {} +u16 AnimResource::GetGroupNum() const { + if (mpTagBlock) { + return mpTagBlock->groupNum; + } + return 0; +} // GetGroupArray__Q34nw4r3lyt12AnimResourceCFv -AnimationGroupRef *AnimResource::GetGroupArray() const { - const AnimationGroupRef *groups; +const AnimationGroupRef *AnimResource::GetGroupArray() const { + if (mpTagBlock) { + const AnimationGroupRef *groups = + detail::ConvertOffsToPtr(mpTagBlock, mpTagBlock->groupsOffset); + return groups; + } + return nullptr; } // IsDescendingBind__Q34nw4r3lyt12AnimResourceCFv -bool AnimResource::IsDescendingBind() const {} +bool AnimResource::IsDescendingBind() const { + if (mpTagBlock) { + return detail::TestBit(mpTagBlock->flag, 0); + } + return false; +} // GetAnimationShareInfoNum__Q34nw4r3lyt12AnimResourceCFv -u16 AnimResource::GetAnimationShareInfoNum() const {} +u16 AnimResource::GetAnimationShareInfoNum() const { + if (mpShareBlock) { + return mpShareBlock->shareNum; + } + return 0; +} // GetAnimationShareInfoArray__Q34nw4r3lyt12AnimResourceCFv -AnimationShareInfo *AnimResource::GetAnimationShareInfoArray() const {} +const AnimationShareInfo *AnimResource::GetAnimationShareInfoArray() const { + if (mpShareBlock) { + return detail::ConvertOffsToPtr(mpShareBlock, mpShareBlock->animShareInfoOffset); + } + return 0; +} // CalcAnimationNum__Q34nw4r3lyt12AnimResourceCFPQ34nw4r3lyt4Paneb u16 AnimResource::CalcAnimationNum(Pane *pPane, bool bRecursive) const { - u16 linkNum; - const u32 *animContOffsets; - u16 i; - // const res::AnimationContent &animCont; - Pane *pFindPane; - Material *pFindMat; + u16 linkNum = 0; + const u32 *animContOffsets = detail::ConvertOffsToPtr(mpResBlock, mpResBlock->animContOffsetsOffset); + for (u16 i = 0; i < mpResBlock->animContNum; i++) { + const res::AnimationContent &animCont = + *detail::ConvertOffsToPtr(mpResBlock, animContOffsets[i]); + if (animCont.type == 0) { + Pane *pFindPane = pPane->FindPaneByName(animCont.name, bRecursive); + if (pFindPane) { + linkNum++; + } + } else { + Material *pFindMat = pPane->FindMaterialByName(animCont.name, bRecursive); + if (pFindMat) { + linkNum++; + } + } + } + return linkNum; } // CalcAnimationNum__Q34nw4r3lyt12AnimResourceCFPQ34nw4r3lyt5Groupb u16 AnimResource::CalcAnimationNum(Group *pGroup, bool bRecursive) const { - u16 linkNum; - ut::LinkList paneList; - ut::LinkList::Iterator it; + u16 linkNum = 0; + ut::LinkList *paneList = pGroup->GetPaneList(); + for (ut::LinkList::Iterator it = paneList->GetBeginIter(); it != paneList->GetEndIter(); + it++) { + linkNum += CalcAnimationNum(it->mTarget, bRecursive); + } + return linkNum; } namespace detail { // FindAnimContent__Q44nw4r3lyt6detail12AnimPaneTreeFPCQ44nw4r3lyt3res14AnimationBlockPCcUc u16 AnimPaneTree::FindAnimContent(const res::AnimationBlock *pAnimBlock, const char *animContName, u8 animContType) { - const u32 *animContOffsets; - u16 i; - const res::AnimationContent *pAnimCont; + const u32 *animContOffsets = detail::ConvertOffsToPtr(pAnimBlock, pAnimBlock->animContOffsetsOffset); + for (u16 i = 0; i < pAnimBlock->animContNum; i++) { + const res::AnimationContent *pAnimCont = + detail::ConvertOffsToPtr(pAnimBlock, animContOffsets[i]); + if (pAnimCont->type == animContType && EqualsMaterialName(pAnimCont->name, animContName)) { + return i; + } + } + return -1; } // Init__Q44nw4r3lyt6detail12AnimPaneTreeFv void AnimPaneTree::Init() { - u8 i; + mLinkNum = 0; + mAnimPaneIdx = 0; + mAnimMatCnt = 0; + for (u8 i = 0; i < 9; i++) { + mAnimMatIdx[i] = 0; + } } // Set__Q44nw4r3lyt6detail12AnimPaneTreeFPQ34nw4r3lyt4PaneRCQ34nw4r3lyt12AnimResource void AnimPaneTree::Set(Pane *pTargetPane, const AnimResource &animRes) { - u16 linkNum; - const res::AnimationBlock *pAnimBlock; - u16 animContIdx; - u8 animMatCnt; + u16 linkNum = 0; + const res::AnimationBlock *pAnimBlock = animRes.GetResourceBlock(); + + u16 animContIdx = FindAnimContent(pAnimBlock, pTargetPane->GetName(), 0); + if (animContIdx != 0xFFFF) { + linkNum++; + } + + u8 animMatCnt = pTargetPane->GetMaterialNum(); u16 animMatIdxs[9]; - for (u8 i;;) {} - for (u8 i;;) {} + for (u8 i = 0; i < animMatCnt; i++) { + animMatIdxs[i] = FindAnimContent(pAnimBlock, pTargetPane->GetMaterial(i)->GetName(), 1); + if (animMatIdxs[i] != 0xFFFF) { + linkNum++; + } + } + if (linkNum != 0) { + mAnimRes = animRes; + mAnimPaneIdx = animContIdx; + mAnimMatCnt = animMatCnt; + for (u8 i = 0; i < animMatCnt; i++) { + mAnimMatIdx[i] = animMatIdxs[i]; + } + mLinkNum = linkNum; + } } // Bind__Q44nw4r3lyt6detail12AnimPaneTreeCFPQ34nw4r3lyt6LayoutPQ34nw4r3lyt4PanePQ34nw4r3lyt16ResourceAccessor AnimTransform *AnimPaneTree::Bind(Layout *pLayout, Pane *pTargetPane, ResourceAccessor *pResAccessor) const { - AnimTransform *pAnimTrans; - AnimationLink *pCrAnimLink; - u8 animMatMax; - u8 i; - Material *pMaterial; + AnimTransformBasic *pAnimTrans = (AnimTransformBasic *)pLayout->CreateAnimTransform(); + pAnimTrans->SetResource(mAnimRes.GetResourceBlock(), pResAccessor, mLinkNum); + + AnimationLink *pCrAnimLink = nullptr; + if (mAnimPaneIdx != 0xFFFF) { + pCrAnimLink = pAnimTrans->Bind(pTargetPane, nullptr, mAnimPaneIdx, true); + } + + u8 animMatMax = ut::Min(mAnimMatCnt, pTargetPane->GetMaterialNum()); + for (u8 i = 0; i < animMatMax; i++) { + if (mAnimMatIdx[i] != 0xFFFF) { + Material *pMaterial = pTargetPane->GetMaterial(i); + pCrAnimLink = pAnimTrans->Bind(pMaterial, pCrAnimLink, mAnimMatIdx[i], true); + } + } + + return pAnimTrans; } // FindAnimationLink__Q34nw4r3lyt6detailFPQ34nw4r2ut38LinkListPQ34nw4r3lyt13AnimTransform AnimationLink *FindAnimationLink(ut::LinkList *pAnimList, AnimTransform *pAnimTrans) { - // it + for (ut::LinkList::Iterator it = pAnimList->GetBeginIter(); it != pAnimList->GetEndIter(); it++) { + if (pAnimTrans == it->GetAnimTransform()) { + return &*it; + } + } + return nullptr; } // FindAnimationLink__Q34nw4r3lyt6detailFPQ34nw4r2ut38LinkListRCQ34nw4r3lyt12AnimResource AnimationLink *FindAnimationLink(ut::LinkList *pAnimList, const AnimResource &animRes) { - // it + for (ut::LinkList::Iterator it = pAnimList->GetBeginIter(); it != pAnimList->GetEndIter(); it++) { + if (animRes.GetResourceBlock() == it->GetAnimTransform()->GetAnimResource()) { + return &*it; + } + } + return nullptr; } // UnbindAnimationLink__Q34nw4r3lyt6detailFPQ34nw4r2ut38LinkListPQ34nw4r3lyt13AnimTransform void UnbindAnimationLink(ut::LinkList *pAnimList, AnimTransform *pAnimTrans) { - // it, currIt + ut::LinkList::Iterator it = pAnimList->GetBeginIter(); + while (it != pAnimList->GetEndIter()) { + ut::LinkList::Iterator currIt = it++; + if (pAnimTrans == nullptr || currIt->GetAnimTransform() == pAnimTrans) { + pAnimList->Erase(currIt); + currIt->Reset(); + } + } } +// Guess, Unused // UnbindAnimationLink__Q34nw4r3lyt6detailFPQ34nw4r2ut38LinkListRCQ34nw4r3lyt12AnimResource void UnbindAnimationLink(ut::LinkList *pAnimList, const AnimResource &animRes) { - // it, currIt + ut::LinkList::Iterator it = pAnimList->GetBeginIter(); + while (it != pAnimList->GetEndIter()) { + ut::LinkList::Iterator currIt = it++; + if (currIt->GetAnimTransform()->GetAnimResource() == animRes.GetResourceBlock()) { + pAnimList->Erase(currIt); + currIt->Reset(); + } + } } } // namespace detail diff --git a/src/nw4r/lyt/lyt_layout.cpp b/src/nw4r/lyt/lyt_layout.cpp index 71a78288..9897363f 100644 --- a/src/nw4r/lyt/lyt_layout.cpp +++ b/src/nw4r/lyt/lyt_layout.cpp @@ -93,7 +93,7 @@ bool Layout::Build(const void *lytResBuf, ResourceAccessor *pResAcsr) { const void *dataPtr = ((u8 *)lytResBuf + pFileHead->headerSize); for (int i = 0; i < pFileHead->dataBlocks; i++) { const res::DataBlockHeader *pDataBlockHead = (const res::DataBlockHeader *)dataPtr; - switch (pDataBlockHead->kind) { + switch (detail::GetSignatureInt(pDataBlockHead->kind)) { case 'lyt1': // Main Layout { const res::Layout *pResLyt = ((const res::Layout *)dataPtr); @@ -114,7 +114,7 @@ bool Layout::Build(const void *lytResBuf, ResourceAccessor *pResAcsr) { case 'txt1': // Text Box case 'bnd1': // Boundary Pane { - Pane *pPane = BuildPaneObj(pDataBlockHead->kind, dataPtr, resBlockSet); + Pane *pPane = BuildPaneObj(detail::GetSignatureInt(pDataBlockHead->kind), dataPtr, resBlockSet); if (pPane) { if (mpRootPane == nullptr) { mpRootPane = pPane; @@ -164,7 +164,7 @@ bool Layout::Build(const void *lytResBuf, ResourceAccessor *pResAcsr) { // CreateAnimTransform__Q34nw4r3lyt6LayoutFv AnimTransform *Layout::CreateAnimTransform() { - AnimTransform *pAnimTrans = NewObj(); + AnimTransformBasic *pAnimTrans = NewObj(); if (pAnimTrans) { mAnimTransList.PushBack(pAnimTrans); }