Implement LegoCarBuildAnimPresenter::FUN_10079160() and others (#1111)

* Implement `LegoCarBuildAnimPresenter::FUN_10079160()` and others

* Address review comments

---------

Co-authored-by: jonschz <jonschz@users.noreply.github.com>
This commit is contained in:
jonschz
2024-10-11 20:21:33 +02:00
committed by GitHub
parent 85ce10ab50
commit 974cd7ce7c
11 changed files with 360 additions and 52 deletions

View File

@@ -1,12 +1,16 @@
#include "legocarbuildpresenter.h"
#include "3dmanager/lego3dmanager.h"
#include "legocarbuild.h"
#include "legoentity.h"
#include "legogamestate.h"
#include "legomain.h"
#include "legoutils.h"
#include "legovideomanager.h"
#include "legoworld.h"
#include "misc.h"
#include "mxautolock.h"
#include "mxcompositepresenter.h"
#include "realtime/realtime.h"
DECOMP_SIZE_ASSERT(LegoCarBuildAnimPresenter::UnknownListEntry, 0x0c)
@@ -17,9 +21,9 @@ DECOMP_SIZE_ASSERT(LegoCarBuildAnimPresenter, 0x150)
LegoCarBuildAnimPresenter::LegoCarBuildAnimPresenter()
{
m_unk0xbc = 0;
m_unk0xbe = 0;
m_unk0xc0 = 0;
m_unk0x128 = NULL;
m_numberOfParts = 0;
m_placedPartCount = 0;
m_parts = NULL;
m_unk0xc4 = NULL;
m_unk0x130 = 0;
m_unk0x12c = 0;
@@ -42,12 +46,12 @@ void LegoCarBuildAnimPresenter::RepeatingTickle()
// FUNCTION: BETA10 0x1007091e
LegoCarBuildAnimPresenter::~LegoCarBuildAnimPresenter()
{
if (m_unk0x128) {
for (MxS16 i = 0; i < m_unk0xbe; i++) {
delete m_unk0x128[i].m_unk0x00;
delete m_unk0x128[i].m_unk0x04;
if (m_parts) {
for (MxS16 i = 0; i < m_numberOfParts; i++) {
delete m_parts[i].m_name;
delete m_parts[i].m_wiredName;
}
delete[] m_unk0x128;
delete[] m_parts;
}
m_unk0xc8.GetRoot()->SetNumChildren(0);
@@ -64,11 +68,52 @@ void LegoCarBuildAnimPresenter::PutFrame()
// TODO
}
// STUB: LEGO1 0x100788c0
// STUB: BETA10 0x10070b56
// FUNCTION: LEGO1 0x100788c0
// FUNCTION: BETA10 0x10070b56
void LegoCarBuildAnimPresenter::ReadyTickle()
{
// TODO
if (!m_anim) {
LegoAnimPresenter::ReadyTickle();
if (!m_currentWorld) {
return;
}
#ifdef NDEBUG
if (!m_anim) {
return;
}
#else
assert(m_anim);
#endif
}
m_unk0x140 = (LegoEntity*) m_currentWorld->Find("MxEntity", "Dunebld");
if (!m_unk0x140) {
m_unk0x140 = (LegoEntity*) m_currentWorld->Find("MxEntity", "Chptrbld");
}
if (!m_unk0x140) {
m_unk0x140 = (LegoEntity*) m_currentWorld->Find("MxEntity", "Jetbld");
}
if (!m_unk0x140) {
m_unk0x140 = (LegoEntity*) m_currentWorld->Find("MxEntity", "bldrace");
}
if (m_unk0x140) {
((LegoCarBuild*) m_currentWorld)->SetUnknown0x258(this);
m_placedPartCount = ((LegoCarBuild*) m_currentWorld)->GetPlacedPartCount();
SetUnknown0xbc(1);
m_previousTickleStates |= 1 << m_currentTickleState;
m_currentTickleState = e_starting;
m_compositePresenter->SendToCompositePresenter(Lego());
}
else {
m_previousTickleStates |= 1 << m_currentTickleState;
m_currentTickleState = e_ready;
}
}
// FUNCTION: LEGO1 0x100789e0
@@ -88,25 +133,25 @@ void LegoCarBuildAnimPresenter::StreamingTickle()
FUN_10079160();
if (GameState()->GetCurrentAct() == LegoGameState::e_act2) {
m_unk0xc0 = 10;
m_placedPartCount = 10;
}
MxS16 i;
for (i = 0; i < m_unk0xbe; i++) {
if (m_unk0xc0 == i) {
FUN_10079680(m_unk0x128[i].m_unk0x04);
for (i = 0; i < m_numberOfParts; i++) {
if (m_placedPartCount == i) {
FUN_10079680(m_parts[i].m_wiredName);
}
else {
FUN_100795d0(m_unk0x128[i].m_unk0x04);
FUN_100795d0(m_parts[i].m_wiredName);
}
if (i < m_unk0xc0) {
if (i < m_placedPartCount) {
FUN_10079050(i);
FUN_10079680(m_unk0x128[i].m_unk0x00);
FUN_10079680(m_parts[i].m_name);
}
LegoChar* name = m_unk0x128[i].m_unk0x04;
LegoChar* name = m_parts[i].m_wiredName;
if (name) {
for (MxS32 j = 0; j <= m_roiMapSize; j++) {
@@ -185,23 +230,125 @@ void LegoCarBuildAnimPresenter::EndAction()
// FUNCTION: BETA10 0x1007151e
void LegoCarBuildAnimPresenter::FUN_10079050(MxS16 p_index)
{
FUN_10079090(m_unk0x128[p_index].m_unk0x04, m_unk0x128[p_index].m_unk0x00);
FUN_100795d0(m_unk0x128[p_index].m_unk0x04);
SwapNodesByName(m_parts[p_index].m_wiredName, m_parts[p_index].m_name);
FUN_100795d0(m_parts[p_index].m_wiredName);
}
// STUB: LEGO1 0x10079090
// STUB: BETA10 0x10071584
void LegoCarBuildAnimPresenter::FUN_10079090(LegoChar* p_param1, LegoChar* p_param2)
// FUNCTION: LEGO1 0x10079090
// FUNCTION: BETA10 0x10071584
void LegoCarBuildAnimPresenter::SwapNodesByName(LegoChar* p_name1, LegoChar* p_name2)
{
// TODO
char buffer[40];
if (stricmp(p_name1, p_name2) != 0) {
LegoAnimNodeData* node1 = FindNodeDataByName(m_anim->GetRoot(), p_name1);
LegoAnimNodeData* node2 = FindNodeDataByName(m_anim->GetRoot(), p_name2);
strcpy(buffer, node1->GetName());
strcpy(node1->GetName(), node2->GetName());
strcpy(node2->GetName(), buffer);
LegoU16 val1 = node1->GetUnknown0x20();
node1->SetUnknown0x20(node2->GetUnknown0x20());
node2->SetUnknown0x20(val1);
}
}
// STUB: LEGO1 0x10079160
// STUB: BETA10 0x1007165d
// FUNCTION: LEGO1 0x10079160
// FUNCTION: BETA10 0x1007165d
void LegoCarBuildAnimPresenter::FUN_10079160()
{
// called from LegoCarBuildAnimPresenter::StreamingTickle()
// TODO
LegoTreeNode* root;
LegoAnimNodeData* data2;
MxS16 i;
MxS16 totalNodes = CountTotalTreeNodes(m_anim->GetRoot());
LegoChar* name;
LegoTreeNode* destNode;
LegoAnimNodeData* destData;
LegoTreeNode** children;
for (i = 0; i < totalNodes; i++) {
LegoAnimNodeData* data = (LegoAnimNodeData*) GetTreeNode(m_anim->GetRoot(), i)->GetData();
name = data->GetName();
if (StringEqualsPlatform(name)) {
m_unk0xc4 = data;
if (m_unk0xc4->GetNumRotationKeys() == 0) {
LegoRotationKey* key = new LegoRotationKey();
m_unk0xc4->SetNumRotationKeys(1);
m_unk0xc4->SetRotationKeys(key);
}
}
else {
if (StringEndsOnYOrN(name)) {
m_numberOfParts++;
}
else {
if (m_unk0x134 == 0.0f && StringEqualsShelf(name)) {
m_unk0x134 = m_anim->GetDuration();
m_unk0x138 = m_unk0x134 / (data->GetNumTranslationKeys() - 1);
}
}
}
}
assert(m_numberOfParts);
m_parts = new UnknownListEntry[m_numberOfParts];
assert(m_parts);
for (i = 0; i < totalNodes; i++) {
name = ((LegoAnimNodeData*) GetTreeNode(m_anim->GetRoot(), i)->GetData())->GetName();
strupr(name);
if (StringEndsOnW(name)) {
m_parts[name[strlen(name) - 1] - 'A'].m_wiredName = new LegoChar[strlen(name) + 1];
// clang-format off
assert(m_parts[name[strlen(name)-1] - 'A'].m_wiredName);
// clang-format on
strcpy(m_parts[name[strlen(name) - 1] - 'A'].m_wiredName, name);
}
}
MxS16 counter = 0;
for (i = 0; i < totalNodes; i++) {
name = ((LegoAnimNodeData*) GetTreeNode(m_anim->GetRoot(), i)->GetData())->GetName();
if (StringEndsOnYOrN(name)) {
for (MxS16 ii = 0; ii < m_numberOfParts; ii++) {
if (strnicmp(m_parts[ii].m_wiredName, name, strlen(name) - 2) == 0) {
m_parts[ii].m_name = new LegoChar[strlen(name) + 1];
assert(m_parts[ii].m_name);
strcpy(m_parts[ii].m_name, name);
counter++;
if (m_numberOfParts == counter) {
break;
}
}
}
}
}
destNode = new LegoTreeNode();
assert(destNode);
destData = new LegoAnimNodeData();
assert(destData);
destNode->SetData(destData);
root = m_anim->GetRoot();
data2 = (LegoAnimNodeData*) root->GetData();
destData->FUN_100a0360(data2->GetName());
destNode->SetNumChildren(1);
children = new LegoTreeNode*;
assert(children);
*children = FindNodeByName(m_anim->GetRoot(), "PLATFORM");
destNode->SetChildren(children);
m_unk0xc8.SetRoot(destNode);
}
// STUB: LEGO1 0x100795d0
@@ -218,6 +365,57 @@ void LegoCarBuildAnimPresenter::FUN_10079680(LegoChar* p_param)
// TODO
}
// FUNCTION: LEGO1 0x100796b0
// FUNCTION: BETA10 0x10071f3c
LegoAnimNodeData* LegoCarBuildAnimPresenter::FindNodeDataByName(LegoTreeNode* p_treeNode, const LegoChar* p_name)
{
LegoAnimNodeData* data = NULL;
if (p_treeNode) {
data = (LegoAnimNodeData*) p_treeNode->GetData();
if (stricmp(data->GetName(), p_name) == 0) {
return data;
}
for (MxS32 i = 0; i < p_treeNode->GetNumChildren(); i++) {
data = FindNodeDataByName(p_treeNode->GetChildren()[i], p_name);
if (data) {
return data;
}
}
}
return NULL;
}
// FUNCTION: LEGO1 0x10079720
// FUNCTION: BETA10 0x10071fec
LegoTreeNode* LegoCarBuildAnimPresenter::FindNodeByName(LegoTreeNode* p_treeNode, const LegoChar* p_name)
{
LegoAnimNodeData* data = NULL;
LegoTreeNode* node = NULL;
if (p_treeNode) {
data = (LegoAnimNodeData*) p_treeNode->GetData();
if (stricmp(data->GetName(), p_name) == 0) {
return p_treeNode;
}
for (MxS32 i = 0; i < p_treeNode->GetNumChildren(); i++) {
node = FindNodeByName(p_treeNode->GetChildren()[i], p_name);
if (node) {
return node;
}
}
}
return NULL;
}
// FUNCTION: LEGO1 0x10079920
// FUNCTION: BETA10 0x1007225d
void LegoCarBuildAnimPresenter::RotateAroundYAxis(MxFloat p_angle)
@@ -251,6 +449,20 @@ void LegoCarBuildAnimPresenter::RotateAroundYAxis(MxFloat p_angle)
}
}
// FUNCTION: LEGO1 0x10079b20
// FUNCTION: BETA10 0x100724fa
MxBool LegoCarBuildAnimPresenter::StringEqualsPlatform(const LegoChar* p_string)
{
return stricmp(p_string, "PLATFORM") == 0;
}
// FUNCTION: LEGO1 0x10079b40
// FUNCTION: BETA10 0x10072534
MxBool LegoCarBuildAnimPresenter::StringEndsOnW(LegoChar* p_param)
{
return (p_param[strlen(p_param) - 2] == 'W') || (p_param[strlen(p_param) - 2] == 'w');
}
// FUNCTION: LEGO1 0x10079b80
// FUNCTION: BETA10 0x1007258f
MxBool LegoCarBuildAnimPresenter::StringEndsOnYOrN(const LegoChar* p_string)
@@ -259,6 +471,13 @@ MxBool LegoCarBuildAnimPresenter::StringEndsOnYOrN(const LegoChar* p_string)
(p_string[strlen(p_string) - 2] == 'Y') || (p_string[strlen(p_string) - 2] == 'y');
}
// FUNCTION: LEGO1 0x10079bf0
// FUNCTION: BETA10 0x10072624
MxBool LegoCarBuildAnimPresenter::StringEqualsShelf(const LegoChar* p_string)
{
return strnicmp(p_string, "SHELF", strlen("SHELF")) == 0;
}
// STUB: LEGO1 0x10079c30
// STUB: BETA10 0x100726a6
MxBool LegoCarBuildAnimPresenter::FUN_10079c30(const LegoChar* p_name)
@@ -271,8 +490,8 @@ MxBool LegoCarBuildAnimPresenter::FUN_10079c30(const LegoChar* p_name)
// FUNCTION: BETA10 0x10072740
MxBool LegoCarBuildAnimPresenter::FUN_10079ca0(const LegoChar* p_name)
{
for (MxS16 i = 0; i < m_unk0xc0; i++) {
if (strcmpi(p_name, m_unk0x128[i].m_unk0x00) == 0) {
for (MxS16 i = 0; i < m_placedPartCount; i++) {
if (strcmpi(p_name, m_parts[i].m_name) == 0) {
return TRUE;
}
}
@@ -292,5 +511,5 @@ MxBool LegoCarBuildAnimPresenter::FUN_10079cf0(const LegoChar* p_string)
const BoundingSphere& LegoCarBuildAnimPresenter::FUN_10079e20()
{
LegoROI* roi = m_unk0x140->GetROI();
return roi->FindChildROI(m_unk0x128[m_unk0xc0].m_unk0x04, roi)->GetWorldBoundingSphere();
return roi->FindChildROI(m_parts[m_placedPartCount].m_wiredName, roi)->GetWorldBoundingSphere();
}