From 3cd4851474ae7d28bb0de627ac51b884c83965fb Mon Sep 17 00:00:00 2001 From: Archez Date: Tue, 4 Feb 2025 18:03:35 -0500 Subject: [PATCH] Defer scene DList resource loading to in-game and support alt pathing (#4986) * Defer scene dlist resource loading to in-game and support alt pathing * feedback --- .../importer/scenecommand/SetMeshFactory.cpp | 137 +++++++++++------- 1 file changed, 82 insertions(+), 55 deletions(-) diff --git a/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp b/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp index cdca68f34..b53a36b85 100644 --- a/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp @@ -36,30 +36,38 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, s for (int32_t i = 0; i < polyNum; i++) { if (setMesh->meshHeader.base.type == 0) { PolygonDlist dlist; + dlist.opa = nullptr; + dlist.xlu = nullptr; int32_t polyType = reader->ReadInt8(); // Unused std::string meshOpa = reader->ReadString(); std::string meshXlu = reader->ReadString(); - auto opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); - auto xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); - dlist.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; - dlist.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + // Enables alt-toggling support by setting maintained c_str references to DList resource after pushing to vector the first + // Defers resource loading later in game when the scene is drawn + if (meshOpa != "") { + meshOpa = "__OTR__" + meshOpa; + setMesh->opaPaths.push_back(meshOpa); + dlist.opa = (Gfx*)setMesh->opaPaths.back().c_str(); + } + if (meshXlu != "") { + meshXlu = "__OTR__" + meshXlu; + setMesh->xluPaths.push_back(meshXlu); + dlist.xlu = (Gfx*)setMesh->xluPaths.back().c_str(); + } - setMesh->opaPaths.push_back(meshOpa); - setMesh->xluPaths.push_back(meshXlu); setMesh->dlists.push_back(dlist); } else if (setMesh->meshHeader.base.type == 1) { PolygonDlist pType; + pType.opa = nullptr; + pType.xlu = nullptr; setMesh->meshHeader.polygon1.format = reader->ReadUByte(); - std::string imgOpa = reader->ReadString(); - std::string imgXlu = reader->ReadString(); - auto opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgOpa.c_str()); - auto xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgXlu.c_str()); - pType.opa = imgOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; - pType.xlu = imgXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + // These strings are the same that are read and used below. Not sure why they get exported twice from the exporter. + // We read and ignore these to advance the reader. + reader->ReadString(); + reader->ReadString(); int32_t bgImageCount = reader->ReadUInt32(); setMesh->images.reserve(bgImageCount); @@ -104,17 +112,24 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, s std::string meshOpa = reader->ReadString(); std::string meshXlu = reader->ReadString(); - opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); - xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); - pType.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; - pType.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + // Use long-lived maintained c_str references + if (meshOpa != "") { + meshOpa = "__OTR__" + meshOpa; + setMesh->opaPaths.push_back(meshOpa); + pType.opa = (Gfx*)setMesh->opaPaths.back().c_str(); + } + if (meshXlu != "") { + meshXlu = "__OTR__" + meshXlu; + setMesh->xluPaths.push_back(meshXlu); + pType.xlu = (Gfx*)setMesh->xluPaths.back().c_str(); + } - setMesh->opaPaths.push_back(meshOpa); - setMesh->xluPaths.push_back(meshXlu); setMesh->dlists.push_back(pType); } else if (setMesh->meshHeader.base.type == 2) { PolygonDlist2 dlist; - + dlist.opa = nullptr; + dlist.xlu = nullptr; + int32_t polyType = reader->ReadInt8(); // Unused dlist.pos.x = reader->ReadInt16(); dlist.pos.y = reader->ReadInt16(); @@ -124,13 +139,18 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, s std::string meshOpa = reader->ReadString(); std::string meshXlu = reader->ReadString(); - auto opaRes = meshOpa != "" ? Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()) : nullptr; - auto xluRes = meshXlu != "" ? Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()) : nullptr; - dlist.opa = (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr); - dlist.xlu = (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr); + // Use long-lived maintained c_str references + if (meshOpa != "") { + meshOpa = "__OTR__" + meshOpa; + setMesh->opaPaths.push_back(meshOpa); + dlist.opa = (Gfx*)setMesh->opaPaths.back().c_str(); + } + if (meshXlu != "") { + meshXlu = "__OTR__" + meshXlu; + setMesh->xluPaths.push_back(meshXlu); + dlist.xlu = (Gfx*)setMesh->xluPaths.back().c_str(); + } - setMesh->opaPaths.push_back(meshOpa); - setMesh->xluPaths.push_back(meshXlu); setMesh->dlists2.push_back(dlist); } else { SPDLOG_ERROR("Tried to load mesh in SetMesh scene header with type that doesn't exist: {}", setMesh->meshHeader.base.type); @@ -194,38 +214,33 @@ std::shared_ptr SetMeshFactoryXML::ReadResource(std::shared_ptr if (setMesh->meshHeader.base.type == 0) { PolygonDlist dlist; + dlist.opa = nullptr; + dlist.xlu = nullptr; int32_t polyType = child->IntAttribute("PolyType"); // Unused std::string meshOpa = child->Attribute("MeshOpa"); std::string meshXlu = child->Attribute("MeshXlu"); + + // Enables alt-toggling support by setting maintained c_str references to DList resource after pushing to vector the first + // Defers resource loading later in game when the scene is drawn if (meshOpa != "") { - auto opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); - dlist.opa = (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr); - } else { - dlist.opa = 0; + meshOpa = "__OTR__" + meshOpa; + setMesh->opaPaths.push_back(meshOpa); + dlist.opa = (Gfx*)setMesh->opaPaths.back().c_str(); } - if (meshXlu != "") { - auto xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); - dlist.xlu = (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr); - } else { - dlist.xlu = 0; + meshXlu = "__OTR__" + meshXlu; + setMesh->xluPaths.push_back(meshXlu); + dlist.xlu = (Gfx*)setMesh->xluPaths.back().c_str(); } - setMesh->opaPaths.push_back(meshOpa); - setMesh->xluPaths.push_back(meshXlu); setMesh->dlists.push_back(dlist); } else if (setMesh->meshHeader.base.type == 1) { PolygonDlist pType; + pType.opa = nullptr; + pType.xlu = nullptr; setMesh->meshHeader.polygon1.format = child->IntAttribute("Format"); - std::string imgOpa = child->Attribute("ImgOpa"); - std::string imgXlu = child->Attribute("ImgXlu"); - - auto opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgOpa.c_str()); - auto xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgXlu.c_str()); - pType.opa = imgOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; - pType.xlu = imgXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; int32_t bgImageCount = child->IntAttribute("BgImageCount"); setMesh->images.reserve(bgImageCount); @@ -279,16 +294,23 @@ std::shared_ptr SetMeshFactoryXML::ReadResource(std::shared_ptr std::string meshOpa = child->Attribute("MeshOpa"); std::string meshXlu = child->Attribute("MeshXlu"); - opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); - xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); - pType.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; - pType.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + // Use long-lived maintained c_str references + if (meshOpa != "") { + meshOpa = "__OTR__" + meshOpa; + setMesh->opaPaths.push_back(meshOpa); + pType.opa = (Gfx*)setMesh->opaPaths.back().c_str(); + } + if (meshXlu != "") { + meshXlu = "__OTR__" + meshXlu; + setMesh->xluPaths.push_back(meshXlu); + pType.xlu = (Gfx*)setMesh->xluPaths.back().c_str(); + } - setMesh->opaPaths.push_back(meshOpa); - setMesh->xluPaths.push_back(meshXlu); setMesh->dlists.push_back(pType); } else if (setMesh->meshHeader.base.type == 2) { PolygonDlist2 dlist; + dlist.opa = nullptr; + dlist.xlu = nullptr; int32_t polyType = child->IntAttribute("PolyType"); // Unused dlist.pos.x = child->IntAttribute("PosX"); @@ -299,13 +321,18 @@ std::shared_ptr SetMeshFactoryXML::ReadResource(std::shared_ptr std::string meshOpa = child->Attribute("MeshOpa"); std::string meshXlu = child->Attribute("MeshXlu"); - auto opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); - auto xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); - dlist.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; - dlist.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + // Use long-lived maintained c_str references + if (meshOpa != "") { + meshOpa = "__OTR__" + meshOpa; + setMesh->opaPaths.push_back(meshOpa); + dlist.opa = (Gfx*)setMesh->opaPaths.back().c_str(); + } + if (meshXlu != "") { + meshXlu = "__OTR__" + meshXlu; + setMesh->xluPaths.push_back(meshXlu); + dlist.xlu = (Gfx*)setMesh->xluPaths.back().c_str(); + } - setMesh->opaPaths.push_back(meshOpa); - setMesh->xluPaths.push_back(meshXlu); setMesh->dlists2.push_back(dlist); } else { SPDLOG_ERROR("Tried to load mesh in SetMesh scene header with type that doesn't exist: {}", setMesh->meshHeader.base.type);