From c9c130eb872580b153c9d20f5c3135f62c9b68a8 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Fri, 21 Jun 2024 20:41:01 +0200 Subject: [PATCH] Implement AnimState (#1042) * Implement LegoAnim * fix: minor issues * fix ncc complaints * refactor: address review comments --------- Co-authored-by: jonschz --- .../legoomni/include/legoanimationmanager.h | 21 ++-- .../lego/legoomni/include/legonavcontroller.h | 1 + .../src/common/legoanimationmanager.cpp | 115 +++++++++++++----- .../legoomni/src/entity/legonavcontroller.cpp | 6 + 4 files changed, 102 insertions(+), 41 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index 5038ac47..0a658254 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -71,22 +71,23 @@ class AnimState : public LegoState { MxBool SetFlag() override; // vtable+0x18 MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c - void FUN_100651d0(MxU32, AnimInfo*, MxU32&); - void FUN_10065240(MxU32, AnimInfo*, MxU32); + void CopyToAnims(MxU32, AnimInfo* p_anims, MxU32& p_outExtraCharacterId); + void InitFromAnims(MxU32 p_animsLength, AnimInfo* p_anims, MxU32 p_extraCharacterId); // SYNTHETIC: LEGO1 0x10065130 // AnimState::`scalar deleting destructor' private: - undefined4 m_unk0x08; // 0x08 + MxU32 m_extraCharacterId; // 0x08 + // appears to store the length of m_unk0x10 - undefined4 m_unk0x0c; // 0x0c - // dynamically sized array of two-byte elements - undefined2* m_unk0x10; // 0x10 - // appears to store the length of m_unk0x18 - undefined4 m_unk0x14; // 0x14 - // dynamically sized array of one-byte elements - undefined* m_unk0x18; // 0x18 + MxU32 m_unk0x0c; // 0x0c + // dynamically sized array of MxU16, corresponding to AnimInfo::m_unk0x22 + MxU16* m_unk0x10; // 0x10 + + MxU32 m_locationsFlagsLength; // 0x14 + // dynamically sized array of bools, corresponding to LegoLocation.m_unk0x5c + MxBool* m_locationsFlags; // 0x18 }; // VTABLE: LEGO1 0x100d8c18 diff --git a/LEGO1/lego/legoomni/include/legonavcontroller.h b/LEGO1/lego/legoomni/include/legonavcontroller.h index 3e310dde..fb95762b 100644 --- a/LEGO1/lego/legoomni/include/legonavcontroller.h +++ b/LEGO1/lego/legoomni/include/legonavcontroller.h @@ -74,6 +74,7 @@ class LegoNavController : public MxCore { ); static MxResult UpdateLocation(MxU32 p_location); static MxResult UpdateLocation(const char* p_location); + static MxS32 GetNumLocations(); static LegoLocation* GetLocation(MxU32 p_location); inline void SetLinearVel(MxFloat p_linearVel) { m_linearVel = p_linearVel; } diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index ab48daef..f5abb3c8 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -416,7 +416,7 @@ void LegoAnimationManager::Suspend() } if (m_worldId == 0) { - m_animState->FUN_10065240(m_animCount, m_anims, m_lastExtraCharacterId); + m_animState->InitFromAnims(m_animCount, m_anims, m_lastExtraCharacterId); } if (!m_suspended) { @@ -615,7 +615,7 @@ MxResult LegoAnimationManager::LoadWorldInfo(MxS32 p_worldId) } if (m_worldId == 0) { - m_animState->FUN_10065240(m_animCount, m_anims, m_lastExtraCharacterId); + m_animState->InitFromAnims(m_animCount, m_anims, m_lastExtraCharacterId); } DeleteAnimations(); @@ -727,7 +727,7 @@ MxResult LegoAnimationManager::LoadWorldInfo(MxS32 p_worldId) } if (p_worldId == 0) { - m_animState->FUN_100651d0(m_animCount, m_anims, m_lastExtraCharacterId); + m_animState->CopyToAnims(m_animCount, m_anims, m_lastExtraCharacterId); } } @@ -2828,26 +2828,59 @@ AnimState::AnimState() { m_unk0x0c = 0; m_unk0x10 = NULL; - m_unk0x14 = 0; - m_unk0x18 = NULL; + m_locationsFlagsLength = 0; + m_locationsFlags = NULL; } -// STUB: LEGO1 0x10065150 +// FUNCTION: LEGO1 0x10065150 AnimState::~AnimState() { - // TODO + delete[] m_unk0x10; + delete[] m_locationsFlags; } -// STUB: LEGO1 0x100651d0 -void AnimState::FUN_100651d0(MxU32, AnimInfo*, MxU32&) +// FUNCTION: LEGO1 0x100651d0 +void AnimState::CopyToAnims(MxU32, AnimInfo* p_anims, MxU32& p_outExtraCharacterId) { - // TODO + if (m_unk0x10 != NULL) { + for (MxS32 i = 0; i < m_unk0x0c; i++) { + p_anims[i].m_unk0x22 = m_unk0x10[i]; + } + + p_outExtraCharacterId = m_extraCharacterId; + + for (MxS32 j = 0; j < m_locationsFlagsLength; j++) { + LegoLocation* location = LegoNavController::GetLocation(j); + if (location != NULL) { + location->m_unk0x5c = m_locationsFlags[j]; + } + } + } } -// STUB: LEGO1 0x10065240 -void AnimState::FUN_10065240(MxU32, AnimInfo*, MxU32) +// FUNCTION: LEGO1 0x10065240 +void AnimState::InitFromAnims(MxU32 p_animsLength, AnimInfo* p_anims, MxU32 p_extraCharacterId) { - // TODO + if (m_unk0x10 == NULL) { + m_unk0x0c = p_animsLength; + m_unk0x10 = new MxU16[p_animsLength]; + MxS32 numLocations = LegoNavController::GetNumLocations(); + m_locationsFlagsLength = numLocations; + m_locationsFlags = new MxBool[numLocations]; + } + + m_extraCharacterId = p_extraCharacterId; + + for (MxS32 i = 0; i < m_unk0x0c; i++) { + m_unk0x10[i] = p_anims[i].m_unk0x22; + } + + for (MxS32 j = 0; j < m_locationsFlagsLength; j++) { + LegoLocation* location = LegoNavController::GetLocation(j); + if (location != NULL) { + m_locationsFlags[j] = location->m_unk0x5c; + } + } } // FUNCTION: LEGO1 0x100652d0 @@ -2864,57 +2897,77 @@ MxResult AnimState::Serialize(LegoFile* p_file) } if (p_file->IsReadMode()) { - Read(p_file, &m_unk0x08); + Read(p_file, &m_extraCharacterId); - // m_unk0x10_len and m_unk0x10 if (m_unk0x10) { delete[] m_unk0x10; } + Read(p_file, &m_unk0x0c); if (m_unk0x0c != 0) { - m_unk0x10 = new undefined2[m_unk0x0c]; + m_unk0x10 = new MxU16[m_unk0x0c]; } else { m_unk0x10 = NULL; } + for (MxS32 i = 0; i < m_unk0x0c; i++) { Read(p_file, &m_unk0x10[i]); } - // m_unk0x18_len and m_unk0x18 // Note that here we read first and then free memory in contrast to above - Read(p_file, &m_unk0x14); - if (m_unk0x18) { - delete[] m_unk0x18; + Read(p_file, &m_locationsFlagsLength); + + if (m_locationsFlags) { + delete[] m_locationsFlags; } - if (m_unk0x14 != 0) { - m_unk0x18 = new undefined[m_unk0x14]; + + if (m_locationsFlagsLength != 0) { + m_locationsFlags = new MxBool[m_locationsFlagsLength]; } else { - m_unk0x18 = NULL; + m_locationsFlags = NULL; } - for (MxS32 j = 0; j < m_unk0x14; j++) { - Read(p_file, &m_unk0x18[j]); + + for (MxS32 j = 0; j < m_locationsFlagsLength; j++) { + Read(p_file, &m_locationsFlags[j]); } } else if (p_file->IsWriteMode()) { - Write(p_file, m_unk0x08); + Write(p_file, m_extraCharacterId); + Write(p_file, m_unk0x0c); for (MxS32 i = 0; i < m_unk0x0c; i++) { Write(p_file, m_unk0x10[i]); } - Write(p_file, m_unk0x14); - for (MxS32 j = 0; j < m_unk0x14; j++) { - Write(p_file, m_unk0x18[j]); + + Write(p_file, m_locationsFlagsLength); + for (MxS32 j = 0; j < m_locationsFlagsLength; j++) { + Write(p_file, m_locationsFlags[j]); } } return SUCCESS; } -// STUB: LEGO1 0x100654f0 +// FUNCTION: LEGO1 0x100654f0 MxBool AnimState::SetFlag() { - // TODO + if (m_unk0x10 != NULL) { + m_extraCharacterId = NULL; + + for (MxS32 i = 0; i < m_unk0x0c; i++) { + m_unk0x10[i] = 0; + } + + for (MxS32 j = 0; j < m_locationsFlagsLength; j++) { + if (LegoNavController::GetLocation(j) != NULL) { + m_locationsFlags[j] = 0; + } + } + + return TRUE; + } + return FALSE; } diff --git a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp index 69b9133d..01facf17 100644 --- a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp @@ -482,6 +482,12 @@ LegoLocation* LegoNavController::GetLocation(MxU32 p_location) return NULL; } +// FUNCTION: LEGO1 0x10055740 +MxS32 LegoNavController::GetNumLocations() +{ + return sizeOfArray(g_locations); +} + // FUNCTION: LEGO1 0x10055750 MxResult LegoNavController::ProcessJoystickInput(MxBool& p_und) {