mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-01-11 02:21:15 +00:00
Merge remote-tracking branch 'isle/master'
This commit is contained in:
commit
67a89f2d78
@ -157,7 +157,18 @@ class LegoGameState {
|
||||
MxS16 m_totalScore; // 0x00
|
||||
MxU8 m_scores[5][5]; // 0x02
|
||||
Username m_name; // 0x1c
|
||||
MxS16 m_unk0x2a; // 0x2a
|
||||
MxS16 m_playerId; // 0x2a
|
||||
|
||||
ScoreItem& operator=(const ScoreItem& p_other)
|
||||
{
|
||||
// MSVC auto-generates an operator=, but LegoGameState::WriteScoreHistory() has a much better match
|
||||
// with a manual implementation.
|
||||
m_totalScore = p_other.m_totalScore;
|
||||
memcpy(m_scores, p_other.m_scores, sizeof(m_scores));
|
||||
m_name = p_other.m_name;
|
||||
m_playerId = p_other.m_playerId;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
// SIZE 0x372
|
||||
@ -165,7 +176,7 @@ class LegoGameState {
|
||||
History();
|
||||
void WriteScoreHistory();
|
||||
MxResult Serialize(LegoStorage* p_storage);
|
||||
ScoreItem* FUN_1003cc90(Username* p_player, MxS16 p_unk0x24, MxS32& p_unk0x2c);
|
||||
ScoreItem* FindPlayerInScoreHistory(Username* p_player, MxS16 p_unk0x24, MxS32& p_unk0x2c);
|
||||
|
||||
// FUNCTION: BETA10 0x1002c2b0
|
||||
MxS16 GetCount() { return m_count; }
|
||||
@ -174,9 +185,12 @@ class LegoGameState {
|
||||
// FUNCTION: BETA10 0x1002c540
|
||||
ScoreItem* GetScore(MxS32 p_index) { return p_index >= m_count ? NULL : &m_scores[p_index]; }
|
||||
|
||||
MxS16 m_count; // 0x00
|
||||
ScoreItem m_scores[20]; // 0x02
|
||||
MxS16 m_unk0x372; // 0x372
|
||||
MxS16 m_count; // 0x00
|
||||
#ifdef BETA10
|
||||
MxS16 m_indices[20]; // 0x02
|
||||
#endif
|
||||
ScoreItem m_scores[20]; // 0x02 (0x22 for BETA10)
|
||||
MxS16 m_nextPlayerId; // 0x372 (0x392 for BETA10)
|
||||
};
|
||||
|
||||
LEGO1_EXPORT LegoGameState();
|
||||
@ -252,7 +266,7 @@ class LegoGameState {
|
||||
// TODO: Most likely getters/setters are not used according to BETA for the following members:
|
||||
|
||||
public:
|
||||
MxS16 m_unk0x24; // 0x24
|
||||
MxS16 m_currentPlayerId; // 0x24
|
||||
MxS16 m_playerCount; // 0x26
|
||||
Username m_players[9]; // 0x28
|
||||
History m_history; // 0xa6
|
||||
|
||||
@ -579,10 +579,10 @@ void LegoCarBuildAnimPresenter::RotateAroundYAxis(MxFloat p_angle)
|
||||
newRotation.EqualsHamiltonProduct(currentRotation, additionalRotation);
|
||||
|
||||
if (newRotation[3] < 0.9999) {
|
||||
rotationKey->FUN_100739a0(TRUE);
|
||||
rotationKey->SetActive(TRUE);
|
||||
}
|
||||
else {
|
||||
rotationKey->FUN_100739a0(FALSE);
|
||||
rotationKey->SetActive(FALSE);
|
||||
}
|
||||
|
||||
m_platformAnimNodeData->GetRotationKey(0)->SetX(newRotation[0]);
|
||||
|
||||
@ -290,7 +290,7 @@ MxResult LegoGameState::Save(MxULong p_slot)
|
||||
}
|
||||
|
||||
storage.WriteS32(0x1000c);
|
||||
storage.WriteS16(m_unk0x24);
|
||||
storage.WriteS16(m_currentPlayerId);
|
||||
storage.WriteU16(m_currentAct);
|
||||
storage.WriteU8(m_actorId);
|
||||
|
||||
@ -386,7 +386,7 @@ MxResult LegoGameState::Load(MxULong p_slot)
|
||||
goto done;
|
||||
}
|
||||
|
||||
storage.ReadS16(m_unk0x24);
|
||||
storage.ReadS16(m_currentPlayerId);
|
||||
storage.ReadS16(actArea);
|
||||
|
||||
SetCurrentAct((Act) actArea);
|
||||
@ -630,8 +630,8 @@ MxResult LegoGameState::AddPlayer(Username& p_player)
|
||||
|
||||
m_playerCount++;
|
||||
m_players[0].Set(p_player);
|
||||
m_unk0x24 = m_history.m_unk0x372;
|
||||
m_history.m_unk0x372 = m_unk0x24 + 1;
|
||||
m_currentPlayerId = m_history.m_nextPlayerId;
|
||||
m_history.m_nextPlayerId = m_currentPlayerId + 1;
|
||||
m_history.WriteScoreHistory();
|
||||
SetCurrentAct(e_act1);
|
||||
|
||||
@ -1422,7 +1422,7 @@ MxResult LegoGameState::ScoreItem::Serialize(LegoStorage* p_storage)
|
||||
}
|
||||
|
||||
m_name.Serialize(p_storage);
|
||||
p_storage->ReadS16(m_unk0x2a);
|
||||
p_storage->ReadS16(m_playerId);
|
||||
}
|
||||
else if (p_storage->IsWriteMode()) {
|
||||
p_storage->WriteS16(m_totalScore);
|
||||
@ -1434,7 +1434,7 @@ MxResult LegoGameState::ScoreItem::Serialize(LegoStorage* p_storage)
|
||||
}
|
||||
|
||||
m_name.Serialize(p_storage);
|
||||
p_storage->WriteS16(m_unk0x2a);
|
||||
p_storage->WriteS16(m_playerId);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
@ -1445,7 +1445,7 @@ MxResult LegoGameState::ScoreItem::Serialize(LegoStorage* p_storage)
|
||||
LegoGameState::History::History()
|
||||
{
|
||||
m_count = 0;
|
||||
m_unk0x372 = 0;
|
||||
m_nextPlayerId = 0;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1003c870
|
||||
@ -1456,83 +1456,130 @@ void LegoGameState::History::WriteScoreHistory()
|
||||
MxU8 scores[5][5];
|
||||
|
||||
InfocenterState* state = (InfocenterState*) GameState()->GetState("InfocenterState");
|
||||
if (state->m_letters[0]) {
|
||||
JetskiRaceState* jetskiRaceState = (JetskiRaceState*) GameState()->GetState("JetskiRaceState");
|
||||
CarRaceState* carRaceState = (CarRaceState*) GameState()->GetState("CarRaceState");
|
||||
TowTrackMissionState* towTrackMissionState =
|
||||
(TowTrackMissionState*) GameState()->GetState("TowTrackMissionState");
|
||||
PizzaMissionState* pizzaMissionState = (PizzaMissionState*) GameState()->GetState("PizzaMissionState");
|
||||
AmbulanceMissionState* ambulanceMissionState =
|
||||
(AmbulanceMissionState*) GameState()->GetState("AmbulanceMissionState");
|
||||
|
||||
for (MxS32 actor = 1; actor <= 5; actor++) {
|
||||
scores[0][actor - 1] = carRaceState ? carRaceState->GetState(actor)->GetHighScore() : 0;
|
||||
totalScore += scores[0][actor - 1];
|
||||
if (!state->m_letters[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
scores[1][actor - 1] = jetskiRaceState ? jetskiRaceState->GetState(actor)->GetHighScore() : 0;
|
||||
totalScore += scores[1][actor - 1];
|
||||
JetskiRaceState* jetskiRaceState = (JetskiRaceState*) GameState()->GetState("JetskiRaceState");
|
||||
CarRaceState* carRaceState = (CarRaceState*) GameState()->GetState("CarRaceState");
|
||||
TowTrackMissionState* towTrackMissionState = (TowTrackMissionState*) GameState()->GetState("TowTrackMissionState");
|
||||
PizzaMissionState* pizzaMissionState = (PizzaMissionState*) GameState()->GetState("PizzaMissionState");
|
||||
AmbulanceMissionState* ambulanceMissionState =
|
||||
(AmbulanceMissionState*) GameState()->GetState("AmbulanceMissionState");
|
||||
|
||||
scores[2][actor - 1] = pizzaMissionState ? pizzaMissionState->GetHighScore(actor) : 0;
|
||||
totalScore += scores[2][actor - 1];
|
||||
for (MxS32 actor = 1; actor <= 5; actor++) {
|
||||
scores[0][actor - 1] = carRaceState ? carRaceState->GetState(actor)->GetHighScore() : 0;
|
||||
totalScore += scores[0][actor - 1];
|
||||
|
||||
scores[3][actor - 1] = towTrackMissionState ? towTrackMissionState->GetHighScore(actor) : 0;
|
||||
totalScore += scores[3][actor - 1];
|
||||
#ifdef BETA10
|
||||
// likely a bug in BETA10
|
||||
scores[1][actor - 1] = carRaceState ? carRaceState->GetState(actor)->GetHighScore() : 0;
|
||||
#else
|
||||
scores[1][actor - 1] = jetskiRaceState ? jetskiRaceState->GetState(actor)->GetHighScore() : 0;
|
||||
#endif
|
||||
totalScore += scores[1][actor - 1];
|
||||
|
||||
scores[4][actor - 1] = ambulanceMissionState ? ambulanceMissionState->GetHighScore(actor) : 0;
|
||||
totalScore += scores[4][actor - 1];
|
||||
}
|
||||
scores[2][actor - 1] = pizzaMissionState ? pizzaMissionState->GetHighScore(actor) : 0;
|
||||
totalScore += scores[2][actor - 1];
|
||||
|
||||
MxS32 unk0x2c;
|
||||
ScoreItem* p_scorehist = FUN_1003cc90(&GameState()->m_players[0], GameState()->m_unk0x24, unk0x2c);
|
||||
scores[3][actor - 1] = towTrackMissionState ? towTrackMissionState->GetHighScore(actor) : 0;
|
||||
totalScore += scores[3][actor - 1];
|
||||
|
||||
if (p_scorehist != NULL) {
|
||||
p_scorehist->m_totalScore = totalScore;
|
||||
memcpy(p_scorehist->m_scores, scores, sizeof(p_scorehist->m_scores));
|
||||
}
|
||||
else {
|
||||
if (m_count < (MxS16) sizeOfArray(m_scores)) {
|
||||
m_scores[m_count].m_totalScore = totalScore;
|
||||
memcpy(m_scores[m_count].m_scores, scores, sizeof(m_scores[m_count].m_scores));
|
||||
m_scores[m_count].m_name = GameState()->m_players[0];
|
||||
m_scores[m_count].m_unk0x2a = GameState()->m_unk0x24;
|
||||
m_count++;
|
||||
}
|
||||
else if (m_scores[19].m_totalScore <= totalScore) {
|
||||
m_scores[19].m_totalScore = totalScore;
|
||||
memcpy(m_scores[19].m_scores, scores, sizeof(m_scores[19].m_scores));
|
||||
m_scores[19].m_name = GameState()->m_players[0];
|
||||
m_scores[19].m_unk0x2a = GameState()->m_unk0x24;
|
||||
scores[4][actor - 1] = ambulanceMissionState ? ambulanceMissionState->GetHighScore(actor) : 0;
|
||||
totalScore += scores[4][actor - 1];
|
||||
}
|
||||
|
||||
MxS32 playerScoreHistoryIndex;
|
||||
ScoreItem* p_scorehist =
|
||||
FindPlayerInScoreHistory(GameState()->m_players, GameState()->m_currentPlayerId, playerScoreHistoryIndex);
|
||||
|
||||
#ifdef BETA10
|
||||
if (!p_scorehist) {
|
||||
MxS32 playerScoreRank;
|
||||
// LINE: BETA10 0x100870ee
|
||||
for (playerScoreRank = 0; playerScoreRank < m_count; playerScoreRank++) {
|
||||
if (totalScore > m_scores[m_indices[playerScoreRank]].m_totalScore) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// LINE: BETA10 0x1008713f
|
||||
if (playerScoreRank < m_count) {
|
||||
if (m_count < 20) {
|
||||
playerScoreHistoryIndex = m_count++;
|
||||
}
|
||||
else {
|
||||
playerScoreHistoryIndex = m_indices[19];
|
||||
}
|
||||
|
||||
MxU8 tmpScores[5][5];
|
||||
Username tmpPlayer;
|
||||
MxS16 tmpUnk0x2a;
|
||||
MxS32 max = m_count - 1;
|
||||
for (MxS32 j = max; playerScoreRank < j; j--) {
|
||||
m_indices[j - 1] = m_indices[j - 2];
|
||||
}
|
||||
|
||||
// TODO: Match bubble sort loops
|
||||
for (MxS32 i = m_count - 1; i > 0; i--) {
|
||||
for (MxS32 j = 1; j <= i; j++) {
|
||||
if (m_scores[j - 1].m_totalScore < m_scores[j].m_totalScore) {
|
||||
memcpy(tmpScores, m_scores[j - 1].m_scores, sizeof(tmpScores));
|
||||
tmpPlayer = m_scores[j - 1].m_name;
|
||||
tmpUnk0x2a = m_scores[j - 1].m_unk0x2a;
|
||||
m_indices[playerScoreRank] = playerScoreHistoryIndex;
|
||||
p_scorehist = &m_scores[playerScoreHistoryIndex];
|
||||
}
|
||||
else if (playerScoreRank < 20) {
|
||||
m_indices[m_count] = m_count;
|
||||
p_scorehist = &m_scores[m_count++];
|
||||
}
|
||||
}
|
||||
else if (p_scorehist->m_totalScore != totalScore) {
|
||||
assert(totalScore > p_scorehist->m_totalScore);
|
||||
|
||||
memcpy(m_scores[j - 1].m_scores, m_scores[j].m_scores, sizeof(m_scores[j - 1].m_scores));
|
||||
m_scores[j - 1].m_name = m_scores[j].m_name;
|
||||
m_scores[j - 1].m_unk0x2a = m_scores[j].m_unk0x2a;
|
||||
for (MxS32 i = playerScoreHistoryIndex; i > 0 && m_indices[i - 1] < m_indices[i]; i--) {
|
||||
MxU8 tmp = m_indices[i - 1];
|
||||
m_indices[i - 1] = m_indices[i];
|
||||
m_indices[i] = tmp;
|
||||
}
|
||||
}
|
||||
if (p_scorehist) {
|
||||
p_scorehist->m_totalScore = totalScore;
|
||||
memcpy(p_scorehist->m_scores[0], scores[0], sizeof(scores));
|
||||
p_scorehist->m_name = GameState()->m_players[0];
|
||||
p_scorehist->m_playerId = GameState()->m_currentPlayerId;
|
||||
}
|
||||
#else
|
||||
if (p_scorehist != NULL) {
|
||||
p_scorehist->m_totalScore = totalScore;
|
||||
memcpy(p_scorehist->m_scores, scores, sizeof(p_scorehist->m_scores));
|
||||
}
|
||||
else {
|
||||
if (m_count < (MxS16) sizeOfArray(m_scores)) {
|
||||
assert(totalScore > p_scorehist->m_totalScore);
|
||||
|
||||
memcpy(m_scores[j].m_scores, tmpScores, sizeof(m_scores[j].m_scores));
|
||||
m_scores[j].m_name = tmpPlayer;
|
||||
m_scores[j].m_unk0x2a = tmpUnk0x2a;
|
||||
}
|
||||
m_scores[m_count].m_totalScore = totalScore;
|
||||
memcpy(m_scores[m_count].m_scores, scores, sizeof(m_scores[m_count].m_scores));
|
||||
m_scores[m_count].m_name = GameState()->m_players[0];
|
||||
m_scores[m_count].m_playerId = GameState()->m_currentPlayerId;
|
||||
m_count++;
|
||||
}
|
||||
else if (m_scores[19].m_totalScore <= totalScore) {
|
||||
m_scores[19].m_totalScore = totalScore;
|
||||
memcpy(m_scores[19].m_scores, scores, sizeof(m_scores[19].m_scores));
|
||||
m_scores[19].m_name = GameState()->m_players[0];
|
||||
m_scores[19].m_playerId = GameState()->m_currentPlayerId;
|
||||
}
|
||||
}
|
||||
|
||||
ScoreItem tmpItem;
|
||||
|
||||
for (MxS32 i = m_count - 1; i >= 0; i--) {
|
||||
for (MxS32 j = 1; j <= i; j++) {
|
||||
if (m_scores[j].m_totalScore > m_scores[j - 1].m_totalScore) {
|
||||
tmpItem = m_scores[j - 1];
|
||||
m_scores[j - 1] = m_scores[j];
|
||||
m_scores[j] = tmpItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1003cc90
|
||||
// FUNCTION: BETA10 0x1008732a
|
||||
LegoGameState::ScoreItem* LegoGameState::History::FUN_1003cc90(
|
||||
LegoGameState::ScoreItem* LegoGameState::History::FindPlayerInScoreHistory(
|
||||
LegoGameState::Username* p_player,
|
||||
MxS16 p_unk0x24,
|
||||
MxS32& p_unk0x2c
|
||||
@ -1540,7 +1587,7 @@ LegoGameState::ScoreItem* LegoGameState::History::FUN_1003cc90(
|
||||
{
|
||||
MxS32 i = 0;
|
||||
for (; i < m_count; i++) {
|
||||
if (!memcmp(p_player, &m_scores[i].m_name, sizeof(*p_player)) && m_scores[i].m_unk0x2a == p_unk0x24) {
|
||||
if (!memcmp(p_player, &m_scores[i].m_name, sizeof(*p_player)) && m_scores[i].m_playerId == p_unk0x24) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1559,7 +1606,7 @@ LegoGameState::ScoreItem* LegoGameState::History::FUN_1003cc90(
|
||||
MxResult LegoGameState::History::Serialize(LegoStorage* p_storage)
|
||||
{
|
||||
if (p_storage->IsReadMode()) {
|
||||
p_storage->ReadS16(m_unk0x372);
|
||||
p_storage->ReadS16(m_nextPlayerId);
|
||||
p_storage->ReadS16(m_count);
|
||||
|
||||
for (MxS16 i = 0; i < m_count; i++) {
|
||||
@ -1569,7 +1616,7 @@ MxResult LegoGameState::History::Serialize(LegoStorage* p_storage)
|
||||
}
|
||||
}
|
||||
else if (p_storage->IsWriteMode()) {
|
||||
p_storage->WriteS16(m_unk0x372);
|
||||
p_storage->WriteS16(m_nextPlayerId);
|
||||
p_storage->WriteS16(m_count);
|
||||
|
||||
for (MxS16 i = 0; i < m_count; i++) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "legovariables.h"
|
||||
|
||||
#include "3dmanager/lego3dmanager.h"
|
||||
#include "legoactor.h"
|
||||
#include "legogamestate.h"
|
||||
#include "legonavcontroller.h"
|
||||
#include "legovideomanager.h"
|
||||
@ -159,18 +160,18 @@ void WhoAmIVariable::SetValue(const char* p_value)
|
||||
MxVariable::SetValue(p_value);
|
||||
|
||||
if (!SDL_strcasecmp(p_value, g_papa)) {
|
||||
GameState()->SetActorId(3);
|
||||
GameState()->SetActorId(LegoActor::c_papa);
|
||||
}
|
||||
else if (!SDL_strcasecmp(p_value, g_mama)) {
|
||||
GameState()->SetActorId(2);
|
||||
GameState()->SetActorId(LegoActor::c_mama);
|
||||
}
|
||||
else if (!SDL_strcasecmp(p_value, g_pepper)) {
|
||||
GameState()->SetActorId(1);
|
||||
GameState()->SetActorId(LegoActor::c_pepper);
|
||||
}
|
||||
else if (!SDL_strcasecmp(p_value, g_nick)) {
|
||||
GameState()->SetActorId(4);
|
||||
GameState()->SetActorId(LegoActor::c_nick);
|
||||
}
|
||||
else if (!SDL_strcasecmp(p_value, g_laura)) {
|
||||
GameState()->SetActorId(5);
|
||||
GameState()->SetActorId(LegoActor::c_laura);
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,10 +224,10 @@ void LegoAnimPresenter::FUN_100692b0()
|
||||
|
||||
for (LegoU32 i = 0; i < numActors; i++) {
|
||||
LegoChar* str = GetVariableOrIdentity(m_anim->GetActorName(i), NULL);
|
||||
undefined4 unk0x04 = m_anim->GetActorUnknown0x04(i);
|
||||
LegoU32 actorType = m_anim->GetActorType(i);
|
||||
LegoROI* roi = NULL;
|
||||
|
||||
if (unk0x04 == 2) {
|
||||
if (actorType == LegoAnimActorEntry::e_actorType2) {
|
||||
LegoChar* src;
|
||||
if (str[0] == '*') {
|
||||
src = str + 1;
|
||||
@ -242,7 +242,7 @@ void LegoAnimPresenter::FUN_100692b0()
|
||||
roi->SetVisibility(FALSE);
|
||||
}
|
||||
}
|
||||
else if (unk0x04 == 4) {
|
||||
else if (actorType == LegoAnimActorEntry::e_actorType4) {
|
||||
LegoChar* baseName = new LegoChar[strlen(str)];
|
||||
strcpy(baseName, str + 1);
|
||||
SDL_strlwr(baseName);
|
||||
@ -257,7 +257,7 @@ void LegoAnimPresenter::FUN_100692b0()
|
||||
delete[] baseName;
|
||||
delete[] und;
|
||||
}
|
||||
else if (unk0x04 == 3) {
|
||||
else if (actorType == LegoAnimActorEntry::e_actorType3) {
|
||||
LegoChar* lodName = new LegoChar[strlen(str)];
|
||||
strcpy(lodName, str + 1);
|
||||
|
||||
@ -303,9 +303,9 @@ void LegoAnimPresenter::FUN_100695c0()
|
||||
|
||||
for (LegoU32 i = 0; i < numActors; i++) {
|
||||
if (FUN_100698b0(rois, m_anim->GetActorName(i)) == FALSE) {
|
||||
undefined4 unk0x04 = m_anim->GetActorUnknown0x04(i);
|
||||
LegoU32 actorType = m_anim->GetActorType(i);
|
||||
|
||||
if (unk0x04 == 5 || unk0x04 == 6) {
|
||||
if (actorType == LegoAnimActorEntry::e_actorType5 || actorType == LegoAnimActorEntry::e_actorType6) {
|
||||
LegoChar lodName[256];
|
||||
const LegoChar* actorName = m_anim->GetActorName(i);
|
||||
|
||||
|
||||
@ -725,6 +725,7 @@ void LegoAnimNodeData::SetName(LegoChar* p_name)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a03c0
|
||||
// FUNCTION: BETA10 0x1017f254
|
||||
LegoResult LegoAnimNodeData::CreateLocalTransform(LegoFloat p_time, Matrix4& p_matrix)
|
||||
{
|
||||
LegoU32 index;
|
||||
@ -1062,7 +1063,7 @@ LegoResult LegoAnim::Read(LegoStorage* p_storage, LegoS32 p_parseScene)
|
||||
|
||||
m_modelList[i].m_name[length] = '\0';
|
||||
|
||||
if (p_storage->Read(&m_modelList[i].m_unk0x04, sizeof(undefined4)) != SUCCESS) {
|
||||
if (p_storage->Read(&m_modelList[i].m_type, sizeof(LegoU32)) != SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -1123,7 +1124,7 @@ LegoResult LegoAnim::Write(LegoStorage* p_storage)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (p_storage->Write(&m_modelList[i].m_unk0x04, sizeof(m_modelList[i].m_unk0x04)) != SUCCESS) {
|
||||
if (p_storage->Write(&m_modelList[i].m_type, sizeof(m_modelList[i].m_type)) != SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -1158,10 +1159,10 @@ const LegoChar* LegoAnim::GetActorName(LegoU32 p_index)
|
||||
|
||||
// FUNCTION: LEGO1 0x100a0f40
|
||||
// FUNCTION: BETA10 0x1018023c
|
||||
undefined4 LegoAnim::GetActorUnknown0x04(LegoU32 p_index)
|
||||
LegoU32 LegoAnim::GetActorType(LegoU32 p_index)
|
||||
{
|
||||
if (p_index < m_numActors) {
|
||||
return m_modelList[p_index].m_unk0x04;
|
||||
return m_modelList[p_index].m_type;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -30,9 +30,9 @@ class LegoAnimKey {
|
||||
LegoU32 ShouldSkipInterpolation() { return m_flags & c_skipInterpolation; }
|
||||
|
||||
// FUNCTION: BETA10 0x100739a0
|
||||
void FUN_100739a0(MxS32 p_param)
|
||||
void SetActive(MxS32 p_active)
|
||||
{
|
||||
if (p_param) {
|
||||
if (p_active) {
|
||||
m_flags |= c_active;
|
||||
}
|
||||
else {
|
||||
@ -289,8 +289,16 @@ class LegoAnimNodeData : public LegoTreeNodeData {
|
||||
|
||||
// SIZE 0x08
|
||||
struct LegoAnimActorEntry {
|
||||
LegoChar* m_name; // 0x00
|
||||
undefined4 m_unk0x04; // 0x04
|
||||
enum {
|
||||
e_actorType2 = 2,
|
||||
e_actorType3 = 3,
|
||||
e_actorType4 = 4,
|
||||
e_actorType5 = 5,
|
||||
e_actorType6 = 6,
|
||||
};
|
||||
|
||||
LegoChar* m_name; // 0x00
|
||||
LegoU32 m_type; // 0x04
|
||||
};
|
||||
|
||||
// TODO: Possibly called `LegoCameraAnim(ation)`?
|
||||
@ -338,7 +346,7 @@ class LegoAnim : public LegoTree {
|
||||
virtual LegoResult Read(LegoStorage* p_storage, LegoS32 p_parseScene); // vtable+0x10
|
||||
|
||||
const LegoChar* GetActorName(LegoU32 p_index);
|
||||
undefined4 GetActorUnknown0x04(LegoU32 p_index);
|
||||
LegoU32 GetActorType(LegoU32 p_index);
|
||||
|
||||
// FUNCTION: BETA10 0x1005abf0
|
||||
LegoAnimScene* GetCamAnim() { return m_camAnim; }
|
||||
|
||||
@ -59,8 +59,12 @@ ColorOverride g_colorOverride = NULL;
|
||||
TextureHandler g_textureHandler = NULL;
|
||||
|
||||
// FUNCTION: LEGO1 0x100a81b0
|
||||
void LegoROI::FUN_100a81b0(const LegoChar* p_error, const LegoChar* p_name)
|
||||
// FUNCTION: BETA10 0x101898c0
|
||||
// FUNCTION: ALPHA 0x100bb1c0
|
||||
void LegoROI::FUN_100a81b0(const LegoChar* p_error, ...)
|
||||
{
|
||||
// Probably a printf-like debug function that was removed early.
|
||||
// No known implementation in any of the binaries.
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a81c0
|
||||
@ -70,6 +74,7 @@ void LegoROI::configureLegoROI(int p_roiConfig)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a81d0
|
||||
// FUNCTION: BETA10 0x101898e8
|
||||
LegoROI::LegoROI(Tgl::Renderer* p_renderer) : ViewROI(p_renderer, NULL)
|
||||
{
|
||||
m_parentROI = NULL;
|
||||
@ -78,6 +83,7 @@ LegoROI::LegoROI(Tgl::Renderer* p_renderer) : ViewROI(p_renderer, NULL)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a82d0
|
||||
// FUNCTION: BETA10 0x10189994
|
||||
LegoROI::LegoROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList) : ViewROI(p_renderer, p_lodList)
|
||||
{
|
||||
m_parentROI = NULL;
|
||||
@ -86,6 +92,7 @@ LegoROI::LegoROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList) : ViewROI(p_
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a83c0
|
||||
// FUNCTION: BETA10 0x10189a42
|
||||
LegoROI::~LegoROI()
|
||||
{
|
||||
if (comp) {
|
||||
@ -106,6 +113,7 @@ LegoROI::~LegoROI()
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a84a0
|
||||
// FUNCTION: BETA10 0x10189b99
|
||||
LegoResult LegoROI::Read(
|
||||
OrientableROI* p_unk0xd4,
|
||||
Tgl::Renderer* p_renderer,
|
||||
@ -338,6 +346,7 @@ LegoResult LegoROI::Read(
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a8cb0
|
||||
// FUNCTION: BETA10 0x1018a7e8
|
||||
LegoResult LegoROI::CreateLocalTransform(LegoAnimNodeData* p_data, LegoTime p_time, Matrix4& p_matrix)
|
||||
{
|
||||
p_matrix.SetIdentity();
|
||||
@ -380,6 +389,7 @@ LegoROI* LegoROI::FindChildROI(const LegoChar* p_name, LegoROI* p_roi)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a8da0
|
||||
// FUNCTION: BETA10 0x1018a9fb
|
||||
LegoResult LegoROI::ApplyAnimationTransformation(
|
||||
LegoTreeNode* p_node,
|
||||
const Matrix4& p_matrix,
|
||||
@ -474,6 +484,7 @@ void LegoROI::FUN_100a8fd0(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_t
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a90f0
|
||||
// FUNCTION: BETA10 0x1018ada8
|
||||
LegoResult LegoROI::SetFrame(LegoAnim* p_anim, LegoTime p_time)
|
||||
{
|
||||
LegoTreeNode* root = p_anim->GetRoot();
|
||||
@ -513,6 +524,7 @@ LegoResult LegoROI::SetLodColor(LegoFloat p_red, LegoFloat p_green, LegoFloat p_
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a9210
|
||||
// FUNCTION: BETA10 0x1018af25
|
||||
LegoResult LegoROI::SetTextureInfo(LegoTextureInfo* p_textureInfo)
|
||||
{
|
||||
LegoResult result = SUCCESS;
|
||||
@ -736,6 +748,7 @@ LegoU32 LegoROI::FUN_100a9410(
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a9a50
|
||||
// FUNCTION: BETA10 0x1018bb6b
|
||||
TimeROI::TimeROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, LegoTime p_time) : LegoROI(p_renderer, p_lodList)
|
||||
{
|
||||
m_time = p_time;
|
||||
@ -761,6 +774,7 @@ void TimeROI::FUN_100a9b40(Matrix4& p_matrix, LegoTime p_time)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a9bf0
|
||||
// FUNCTION: BETA10 0x1018bc93
|
||||
LegoBool LegoROI::GetRGBAColor(const LegoChar* p_name, float& p_red, float& p_green, float& p_blue, float& p_alpha)
|
||||
{
|
||||
if (p_name == NULL) {
|
||||
@ -851,12 +865,14 @@ void LegoROI::SetDisplayBB(int p_displayBB)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aa340
|
||||
// FUNCTION: BETA10 0x1018cca0
|
||||
float LegoROI::IntrinsicImportance() const
|
||||
{
|
||||
return .5;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aa350
|
||||
// FUNCTION: BETA10 0x1018ccc0
|
||||
void LegoROI::UpdateWorldBoundingVolumes()
|
||||
{
|
||||
CalcWorldBoundingVolumes(m_sphere, m_local2world, m_world_bounding_box, m_world_bounding_sphere);
|
||||
|
||||
@ -18,6 +18,7 @@ class LegoTreeNode;
|
||||
struct LegoAnimActorEntry;
|
||||
|
||||
// VTABLE: LEGO1 0x100dbe38
|
||||
// VTABLE: BETA10 0x101c3898
|
||||
// SIZE 0x108
|
||||
class LegoROI : public ViewROI {
|
||||
public:
|
||||
@ -58,7 +59,7 @@ class LegoROI : public ViewROI {
|
||||
void SetDisplayBB(int p_displayBB);
|
||||
|
||||
static LegoResult CreateLocalTransform(LegoAnimNodeData* p_data, LegoTime p_time, Matrix4& p_matrix);
|
||||
static void FUN_100a81b0(const LegoChar* p_error, const LegoChar* p_name);
|
||||
static void FUN_100a81b0(const LegoChar* p_error, ...);
|
||||
LEGO1_EXPORT static void configureLegoROI(int p_roi);
|
||||
static void SetColorOverride(ColorOverride p_colorOverride);
|
||||
static LegoBool GetRGBAColor(const LegoChar* p_name, float& p_red, float& p_green, float& p_blue, float& p_alpha);
|
||||
@ -87,6 +88,7 @@ class LegoROI : public ViewROI {
|
||||
void SetBoundingBox(const BoundingBox& p_box) { m_bounding_box = p_box; }
|
||||
|
||||
// SYNTHETIC: LEGO1 0x100a82b0
|
||||
// SYNTHETIC: BETA10 0x1018c490
|
||||
// LegoROI::`scalar deleting destructor'
|
||||
|
||||
private:
|
||||
@ -99,15 +101,20 @@ class LegoROI : public ViewROI {
|
||||
};
|
||||
|
||||
// VTABLE: LEGO1 0x100dbea8
|
||||
// VTABLE: BETA10 0x101c38d0
|
||||
// SIZE 0x10c
|
||||
class TimeROI : public LegoROI {
|
||||
public:
|
||||
TimeROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, LegoTime p_time);
|
||||
|
||||
void FUN_100a9b40(Matrix4& p_matrix, LegoTime p_time);
|
||||
|
||||
// SYNTHETIC: LEGO1 0x100a9ad0
|
||||
// SYNTHETIC: BETA10 0x1018c540
|
||||
// TimeROI::`scalar deleting destructor'
|
||||
|
||||
void FUN_100a9b40(Matrix4& p_matrix, LegoTime p_time);
|
||||
// SYNTHETIC: BETA10 0x1018c580
|
||||
// TimeROI::~TimeROI
|
||||
|
||||
private:
|
||||
LegoTime m_time; // 0x108
|
||||
|
||||
@ -289,7 +289,7 @@ void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_da
|
||||
while (--line >= 0) {
|
||||
short column = 0;
|
||||
data++;
|
||||
char count = 0;
|
||||
signed char count = 0;
|
||||
while ((column += count) < width2) {
|
||||
count = *data++;
|
||||
|
||||
@ -332,7 +332,7 @@ void DecodeLC(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data
|
||||
|
||||
while (packets > 0) {
|
||||
column += *data++; // skip byte
|
||||
char type = *((char*) data++);
|
||||
signed char type = *((signed char*) data++);
|
||||
|
||||
if (type < 0) {
|
||||
type = -type;
|
||||
@ -418,7 +418,7 @@ void DecodeSS2(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_dat
|
||||
// LINE: BETA10 0x1013e726
|
||||
column += *data.byte++;
|
||||
// LINE: BETA10 0x1013e73a
|
||||
short type = *(char*) data.byte++;
|
||||
short type = *(signed char*) data.byte++;
|
||||
type += type;
|
||||
|
||||
if (type >= 0) {
|
||||
|
||||
@ -108,6 +108,7 @@ void OrientableROI::SetLocal2World(const Matrix4& p_local2world)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a5910
|
||||
// FUNCTION: BETA10 0x10167bac
|
||||
void OrientableROI::UpdateWorldData()
|
||||
{
|
||||
UpdateWorldBoundingVolumes();
|
||||
@ -115,6 +116,7 @@ void OrientableROI::UpdateWorldData()
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a5930
|
||||
// FUNCTION: BETA10 0x10167bd8
|
||||
void OrientableROI::SetLocal2WorldWithWorldDataUpdate(const Matrix4& p_transform)
|
||||
{
|
||||
m_local2world = p_transform;
|
||||
@ -123,6 +125,7 @@ void OrientableROI::SetLocal2WorldWithWorldDataUpdate(const Matrix4& p_transform
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a5960
|
||||
// FUNCTION: BETA10 0x10167c19
|
||||
void OrientableROI::UpdateWorldDataWithTransform(const Matrix4& p_transform)
|
||||
{
|
||||
MxMatrix l_matrix(m_local2world);
|
||||
@ -132,6 +135,7 @@ void OrientableROI::UpdateWorldDataWithTransform(const Matrix4& p_transform)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a59b0
|
||||
// FUNCTION: BETA10 0x10167c6d
|
||||
void OrientableROI::UpdateWorldDataWithTransformAndChildren(const Matrix4& p_transform)
|
||||
{
|
||||
MxMatrix l_matrix(m_local2world);
|
||||
@ -155,11 +159,13 @@ void OrientableROI::SetWorldVelocity(const Vector3& p_world_velocity)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a5a50
|
||||
// FUNCTION: BETA10 0x10167d65
|
||||
void OrientableROI::UpdateWorldVelocity()
|
||||
{
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a5a60
|
||||
// FUNCTION: BETA10 0x10167d7b
|
||||
void CalcWorldBoundingVolumes(
|
||||
const BoundingSphere& modelling_sphere,
|
||||
const Matrix4& local2world,
|
||||
@ -186,18 +192,21 @@ void CalcWorldBoundingVolumes(
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a5d80
|
||||
// FUNCTION: BETA10 0x10168760
|
||||
const float* OrientableROI::GetWorldVelocity() const
|
||||
{
|
||||
return m_world_velocity.GetData();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a5d90
|
||||
// FUNCTION: BETA10 0x10168790
|
||||
const BoundingBox& OrientableROI::GetWorldBoundingBox() const
|
||||
{
|
||||
return m_world_bounding_box;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a5da0
|
||||
// FUNCTION: BETA10 0x101687b0
|
||||
const BoundingSphere& OrientableROI::GetWorldBoundingSphere() const
|
||||
{
|
||||
return m_world_bounding_sphere;
|
||||
|
||||
@ -27,6 +27,7 @@ class OrientableROI : public ROI {
|
||||
const BoundingSphere& GetWorldBoundingSphere() const override; // vtable+0x10
|
||||
|
||||
// FUNCTION: LEGO1 0x100a5db0
|
||||
// FUNCTION: BETA10 0x101687d0
|
||||
virtual void WrappedUpdateWorldData() { UpdateWorldData(); } // vtable+0x14
|
||||
|
||||
virtual void UpdateWorldBoundingVolumes() = 0; // vtable+0x18
|
||||
@ -85,6 +86,7 @@ class OrientableROI : public ROI {
|
||||
// OrientableROI::`scalar deleting destructor'
|
||||
|
||||
// SYNTHETIC: LEGO1 0x100aa2f0
|
||||
// SYNTHETIC: BETA10 0x10168600
|
||||
// OrientableROI::~OrientableROI
|
||||
|
||||
#endif // ORIENTABLEROI_H
|
||||
|
||||
@ -15,9 +15,16 @@
|
||||
// SIZE 0x28
|
||||
class BoundingBox {
|
||||
public:
|
||||
// The BETA10 matches may reference the wrong version
|
||||
|
||||
// FUNCTION: BETA10 0x1004a7a0
|
||||
const Vector3& Min() const { return min; }
|
||||
|
||||
Vector3& Min() { return min; }
|
||||
|
||||
// FUNCTION: BETA10 0x1004a7c0
|
||||
const Vector3& Max() const { return max; }
|
||||
|
||||
Vector3& Max() { return max; }
|
||||
|
||||
private:
|
||||
@ -31,14 +38,26 @@ class BoundingBox {
|
||||
// SIZE 0x18
|
||||
class BoundingSphere {
|
||||
public:
|
||||
// The BETA10 matches may reference the wrong version
|
||||
|
||||
// FUNCTION: BETA10 0x1001fac0
|
||||
const Vector3& Center() const { return center; }
|
||||
|
||||
// FUNCTION: BETA10 0x100d55a0
|
||||
Vector3& Center() { return center; }
|
||||
|
||||
// FUNCTION: BETA10 0x1001fd30
|
||||
const float& Radius() const { return radius; }
|
||||
|
||||
// FUNCTION: BETA10 0x1001fae0
|
||||
float& Radius() { return radius; }
|
||||
|
||||
// SYNTHETIC: BETA10 0x1001fb90
|
||||
// BoundingSphere::operator=
|
||||
|
||||
// SYNTHETIC: BETA10 0x1001fc50
|
||||
// BoundingSphere::BoundingSphere
|
||||
|
||||
private:
|
||||
Mx3DPointFloat center; // 0x00
|
||||
float radius; // 0x14
|
||||
@ -136,6 +155,7 @@ class ROI {
|
||||
// list<ROI *,allocator<ROI *> >::~list<ROI *,allocator<ROI *> >
|
||||
|
||||
// SYNTHETIC: LEGO1 0x100a5d50
|
||||
// SYNTHETIC: BETA10 0x101686a0
|
||||
// ROI::~ROI
|
||||
|
||||
#endif // ROI_H
|
||||
|
||||
@ -16,65 +16,60 @@ float ViewROI::IntrinsicImportance() const
|
||||
} // for now
|
||||
|
||||
// FUNCTION: LEGO1 0x100a9ec0
|
||||
// FUNCTION: BETA10 0x1018c740
|
||||
Tgl::Group* ViewROI::GetGeometry()
|
||||
{
|
||||
return geometry;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a9ed0
|
||||
// FUNCTION: BETA10 0x1018c760
|
||||
const Tgl::Group* ViewROI::GetGeometry() const
|
||||
{
|
||||
return geometry;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a9ee0
|
||||
// FUNCTION: BETA10 0x1018c780
|
||||
void ViewROI::UpdateWorldDataWithTransformAndChildren(const Matrix4& parent2world)
|
||||
{
|
||||
OrientableROI::UpdateWorldDataWithTransformAndChildren(parent2world);
|
||||
SetGeometryTransformation();
|
||||
}
|
||||
|
||||
// FUNCTION: BETA10 0x1018c7b0
|
||||
inline void ViewROI::SetGeometryTransformation()
|
||||
{
|
||||
if (geometry) {
|
||||
Tgl::FloatMatrix4 matrix;
|
||||
Matrix4 in(matrix);
|
||||
SETMAT4(in, m_local2world);
|
||||
Tgl::Result result = geometry->SetTransformation(matrix);
|
||||
// assert(Tgl::Succeeded(result));
|
||||
geometry->SetTransformation(matrix);
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a9fc0
|
||||
// FUNCTION: BETA10 0x1018cad0
|
||||
void ViewROI::UpdateWorldDataWithTransform(const Matrix4& p_transform)
|
||||
{
|
||||
OrientableROI::UpdateWorldDataWithTransform(p_transform);
|
||||
if (geometry) {
|
||||
Tgl::FloatMatrix4 matrix;
|
||||
Matrix4 in(matrix);
|
||||
SETMAT4(in, m_local2world);
|
||||
geometry->SetTransformation(matrix);
|
||||
}
|
||||
SetGeometryTransformation();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aa0a0
|
||||
// FUNCTION: BETA10 0x1018cb00
|
||||
void ViewROI::SetLocal2WorldWithWorldDataUpdate(const Matrix4& p_transform)
|
||||
{
|
||||
OrientableROI::SetLocal2WorldWithWorldDataUpdate(p_transform);
|
||||
if (geometry) {
|
||||
Tgl::FloatMatrix4 matrix;
|
||||
Matrix4 in(matrix);
|
||||
SETMAT4(in, m_local2world);
|
||||
geometry->SetTransformation(matrix);
|
||||
}
|
||||
SetGeometryTransformation();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aa180
|
||||
// FUNCTION: BETA10 0x1018cb30
|
||||
void ViewROI::UpdateWorldData()
|
||||
{
|
||||
OrientableROI::UpdateWorldData();
|
||||
if (geometry) {
|
||||
Tgl::FloatMatrix4 matrix;
|
||||
Matrix4 in(matrix);
|
||||
SETMAT4(in, m_local2world);
|
||||
geometry->SetTransformation(matrix);
|
||||
}
|
||||
SetGeometryTransformation();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100aa500
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
// VTABLE: LEGO1 0x100dbe70
|
||||
// VTABLE: BETA10 0x101c3908
|
||||
// SIZE 0xe4
|
||||
class ViewROI : public OrientableROI {
|
||||
public:
|
||||
@ -21,6 +22,7 @@ class ViewROI : public OrientableROI {
|
||||
c_lodLevelInvisible = -2,
|
||||
};
|
||||
|
||||
// FUNCTION: BETA10 0x1018c5e0
|
||||
ViewROI(Tgl::Renderer* pRenderer, ViewLODList* lodList)
|
||||
{
|
||||
SetLODList(lodList);
|
||||
@ -29,6 +31,7 @@ class ViewROI : public OrientableROI {
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100a9e20
|
||||
// FUNCTION: BETA10 0x1018c680
|
||||
~ViewROI() override
|
||||
{
|
||||
// SetLODList() will decrease refCount of LODList
|
||||
@ -36,6 +39,7 @@ class ViewROI : public OrientableROI {
|
||||
delete geometry;
|
||||
}
|
||||
|
||||
// FUNCTION: BETA10 0x1007b540
|
||||
void SetLODList(ViewLODList* lodList)
|
||||
{
|
||||
// ??? inherently type unsafe - kind of... because, now, ROI
|
||||
@ -69,6 +73,8 @@ class ViewROI : public OrientableROI {
|
||||
protected:
|
||||
void UpdateWorldDataWithTransformAndChildren(const Matrix4& parent2world) override; // vtable+0x28
|
||||
|
||||
void SetGeometryTransformation();
|
||||
|
||||
Tgl::Group* geometry; // 0xdc
|
||||
int m_lodLevel; // 0xe0
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user