isle/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp
Misha 277957f0d5
implement misc presenter functions (#695)
* implement misc presenter functions

* style/spacing

---------

Co-authored-by: Christian Semmler <mail@csemmler.com>
2024-03-19 16:07:11 +01:00

276 lines
5.9 KiB
C++

#include "legopartpresenter.h"
#include "legovideomanager.h"
#include "misc.h"
#include "misc/legocontainer.h"
#include "misc/legostorage.h"
#include "misc/legotexture.h"
#include "viewmanager/viewlodlist.h"
DECOMP_SIZE_ASSERT(LegoLODList, 0x18)
DECOMP_SIZE_ASSERT(LegoNamedPart, 0x14)
DECOMP_SIZE_ASSERT(LegoNamedPartList, 0x18)
// GLOBAL: LEGO1 0x100f7aa0
MxS32 g_partPresenterConfig1 = 1;
// GLOBAL: LEGO1 0x100f7aa4
MxS32 g_partPresenterConfig2 = 100;
// FUNCTION: LEGO1 0x1000cf60
void LegoPartPresenter::Destroy()
{
Destroy(FALSE);
}
// FUNCTION: LEGO1 0x1007c990
void LegoPartPresenter::configureLegoPartPresenter(MxS32 p_partPresenterConfig1, MxS32 p_partPresenterConfig2)
{
g_partPresenterConfig1 = p_partPresenterConfig1;
g_partPresenterConfig2 = p_partPresenterConfig2;
}
// FUNCTION: LEGO1 0x1007c9b0
MxResult LegoPartPresenter::AddToManager()
{
VideoManager()->RegisterPresenter(*this);
return SUCCESS;
}
// FUNCTION: LEGO1 0x1007c9d0
void LegoPartPresenter::Destroy(MxBool p_fromDestructor)
{
m_criticalSection.Enter();
VideoManager()->UnregisterPresenter(*this);
if (m_parts) {
delete m_parts;
m_parts = NULL;
}
m_parts = NULL;
m_criticalSection.Leave();
if (!p_fromDestructor) {
MxMediaPresenter::Destroy(FALSE);
}
}
// FUNCTION: LEGO1 0x1007ca30
MxResult LegoPartPresenter::Read(MxDSChunk& p_chunk)
{
MxResult result = FAILURE;
LegoU32 numROIs, numLODs;
LegoMemory storage(p_chunk.GetData());
LegoU32 textureInfoOffset, i, j, numTextures;
LegoU32 roiNameLength, roiInfoOffset, surplusLODs;
LegoLODList* lods;
LegoNamedPart* namedPart;
LegoChar* roiName = NULL;
LegoChar* textureName = NULL;
LegoTexture* texture = NULL;
LegoTextureInfo* textureInfo = NULL;
LegoS32 hardwareMode = VideoManager()->GetDirect3D()->AssignedDevice()->GetHardwareMode();
if (storage.Read(&textureInfoOffset, sizeof(textureInfoOffset)) != SUCCESS) {
goto done;
}
if (storage.SetPosition(textureInfoOffset) != SUCCESS) {
goto done;
}
if (storage.Read(&numTextures, sizeof(numTextures)) != SUCCESS) {
goto done;
}
for (i = 0; i < numTextures; i++) {
LegoU32 textureNameLength;
storage.Read(&textureNameLength, sizeof(textureNameLength));
textureName = new LegoChar[textureNameLength + 1];
storage.Read(textureName, textureNameLength);
textureName[textureNameLength] = '\0';
strlwr(textureName);
if (textureName[0] == '^') {
strcpy(textureName, textureName + 1);
if (g_partPresenterConfig1) {
texture = new LegoTexture();
if (texture->Read(&storage, hardwareMode) != SUCCESS) {
goto done;
}
LegoTexture* discardTexture = new LegoTexture();
if (discardTexture->Read(&storage, FALSE) != SUCCESS) {
goto done;
}
delete discardTexture;
}
else {
LegoTexture* discardTexture = new LegoTexture();
if (discardTexture->Read(&storage, FALSE) != SUCCESS) {
goto done;
}
delete discardTexture;
texture = new LegoTexture();
if (texture->Read(&storage, hardwareMode) != SUCCESS) {
goto done;
}
}
}
else {
texture = new LegoTexture();
if (texture->Read(&storage, hardwareMode) != SUCCESS) {
goto done;
}
}
if (TextureContainer()->Get(textureName) == NULL) {
textureInfo = LegoTextureInfo::Create(textureName, texture);
if (textureInfo == NULL) {
goto done;
}
TextureContainer()->Add(textureName, textureInfo);
}
delete[] textureName;
textureName = NULL;
delete texture;
texture = NULL;
}
if (storage.SetPosition(4) != SUCCESS) {
goto done;
}
m_parts = new LegoNamedPartList();
if (storage.Read(&numROIs, sizeof(numROIs)) != SUCCESS) {
goto done;
}
for (i = 0; i < numROIs; i++) {
if (storage.Read(&roiNameLength, sizeof(roiNameLength)) != SUCCESS) {
goto done;
}
roiName = new LegoChar[roiNameLength + 1];
if (storage.Read(roiName, roiNameLength) != SUCCESS) {
goto done;
}
roiName[roiNameLength] = '\0';
strlwr(roiName);
if (storage.Read(&numLODs, sizeof(numLODs)) != SUCCESS) {
goto done;
}
if (storage.Read(&roiInfoOffset, sizeof(roiInfoOffset)) != SUCCESS) {
goto done;
}
if (numLODs > g_partPresenterConfig2) {
surplusLODs = numLODs - g_partPresenterConfig2;
numLODs = g_partPresenterConfig2;
}
else {
surplusLODs = 0;
}
lods = new LegoLODList();
for (j = 0; j < numLODs; j++) {
LegoLOD* lod = new LegoLOD(VideoManager()->GetRenderer());
if (lod->Read(VideoManager()->GetRenderer(), TextureContainer(), &storage) != SUCCESS) {
goto done;
}
if (j == 0) {
if (surplusLODs != 0 && lod->GetUnknown0x08Test8()) {
numLODs++;
surplusLODs--;
}
}
lods->Append(lod);
}
storage.SetPosition(roiInfoOffset);
namedPart = new LegoNamedPart(roiName, lods);
m_parts->Append(namedPart);
delete[] roiName;
roiName = NULL;
}
result = SUCCESS;
done:
if (roiName != NULL) {
delete[] roiName;
}
if (result != SUCCESS && m_parts != NULL) {
delete m_parts;
m_parts = NULL;
}
return result;
}
// FUNCTION: LEGO1 0x1007deb0
void LegoPartPresenter::ReadyTickle()
{
MxStreamChunk* chunk = m_subscriber->PeekData();
if (chunk != NULL && chunk->GetTime() <= m_action->GetElapsedTime()) {
ParseExtra();
ProgressTickleState(e_starting);
chunk = m_subscriber->PopData();
MxResult result = Read(*chunk);
m_subscriber->FreeDataChunk(chunk);
if (result == SUCCESS) {
Store();
}
EndAction();
}
}
// FUNCTION: LEGO1 0x1007df20
void LegoPartPresenter::Store()
{
LegoNamedPartListCursor partCursor(m_parts);
LegoNamedPart* part;
while (partCursor.Next(part)) {
ViewLODList* lodList = GetViewLODListManager()->Lookup(part->GetName()->GetData());
if (lodList == NULL) {
lodList = GetViewLODListManager()->Create(part->GetName()->GetData(), part->GetList()->GetCount());
LegoLODListCursor lodCursor(part->GetList());
LegoLOD* lod;
while (lodCursor.First(lod)) {
lodCursor.Detach();
lodList->PushBack(lod);
}
}
else {
lodList->Release();
}
}
if (m_parts != NULL) {
delete m_parts;
}
m_parts = NULL;
}