diff options
Diffstat (limited to 'src/engine/editor/SceneManager.cpp')
| -rw-r--r-- | src/engine/editor/SceneManager.cpp | 179 |
1 files changed, 132 insertions, 47 deletions
diff --git a/src/engine/editor/SceneManager.cpp b/src/engine/editor/SceneManager.cpp index 0165f5c81..135079a57 100644 --- a/src/engine/editor/SceneManager.cpp +++ b/src/engine/editor/SceneManager.cpp @@ -7,6 +7,7 @@ #include <iostream> #include <fstream> +#include <memory> #include <optional> // Must be before json.hpp #include <nlohmann/json.hpp> #include "port/Engine.h" @@ -21,28 +22,23 @@ #include "engine/objects/Thwomp.h" #include "engine/objects/Snowman.h" #include "engine/cameras/TourCamera.h" +#include "port/resource/type/TrackPathPointData.h" extern "C" { #include "common_structs.h" #include "actors.h" #include "actor_types.h" +#include "code_80005FD0.h" } namespace Editor { - std::shared_ptr<Ship::Archive> CurrentArchive; - std::string SceneFile = ""; - - void SaveLevel() { - if ((!CurrentArchive) || (SceneFile.empty())) { - SPDLOG_INFO("[SceneManager] [SaveLevel] Could not save scene file, SceneFile or CurrentArchive not set"); - return; - } + void SaveLevel(Track* track) { nlohmann::json data; /** * Save track properties, static mesh actors, actors, and tour camera */ - data["Props"] = gWorldInstance.GetTrack()->Props.to_json(); + data["Props"] = track->Props.to_json(); nlohmann::json staticMesh; SaveStaticMeshActors(staticMesh); @@ -54,12 +50,17 @@ namespace Editor { data["Actors"] = actors; - if (gWorldInstance.GetTrack()->TourShots.size() != 0) { + if (track->TourShots.size() != 0) { nlohmann::json tour; - SaveTour(tour); + SaveTour(track, tour); data["Tour"] = tour; } + if (nullptr == track->Archive) { + SPDLOG_INFO("[SceneManager] [SaveLevel] Track archive nullptr"); + return; + } + /** * Write data to file */ @@ -68,11 +69,14 @@ namespace Editor { std::vector<uint8_t> bytes; // Turn the str into raw data bytes.assign(jsonStr.begin(), jsonStr.end()); + const TrackInfo* info = gTrackRegistry.GetInfo(track->ResourceName); + std::string sceneFile = info->Path + "/scene.json"; + // Write file to disk - bool wrote = GameEngine::Instance->context->GetResourceManager()->GetArchiveManager()->WriteFile(CurrentArchive, SceneFile, bytes); + bool wrote = GameEngine::Instance->context->GetResourceManager()->GetArchiveManager()->WriteFile(track->Archive, sceneFile, bytes); if (wrote) { // Tell the cache this file needs to be reloaded - auto resource = GameEngine::Instance->context->GetResourceManager()->GetCachedResource(SceneFile); + auto resource = GameEngine::Instance->context->GetResourceManager()->GetCachedResource(sceneFile); if (resource) { resource->Dirty(); } @@ -84,11 +88,18 @@ namespace Editor { } } - /** Do not use gWorldInstance.CurrentCourse during loading! The current track is not guaranteed! **/ - void LoadLevel(Track* track, std::string sceneFile) { - SceneFile = sceneFile; - if ((nullptr == track) || (nullptr == track->RootArchive)) { - SPDLOG_INFO("[SceneManager] [LoadLevel] Failed to load scenefile, track or rootarchive were null"); + /** Do not use GetWorld()->CurrentCourse during loading! The current track is not guaranteed! **/ + void LoadTrackDataFromJson(Track* track, const std::string& trackPath) { + SPDLOG_INFO("[SceneManager] [LoadTrackDataFromJson] Loading track scenefile..."); + + if (trackPath.empty()) { + SPDLOG_INFO(" Unable to load track. trackPath empty."); + return; + } + + std::string sceneFile = trackPath + "/scene.json"; + if ((nullptr == track) || (nullptr == track->Archive)) { + SPDLOG_INFO(" Failed to load scenefile, track or archive were null"); return; } @@ -97,7 +108,7 @@ namespace Editor { * the init data needs to be manually populated */ auto initData = std::make_shared<Ship::ResourceInitData>(); - initData->Parent = track->RootArchive; + initData->Parent = track->Archive; initData->Format = RESOURCE_FORMAT_BINARY; initData->ByteOrder = Ship::Endianness::Little; initData->Type = static_cast<uint32_t>(Ship::ResourceType::Json); @@ -109,56 +120,80 @@ namespace Editor { // Check that the data is valid if (data.is_null() || !data.is_object() || data.empty()) { - SPDLOG_INFO("[SceneManager] [LoadLevel] Scenefile corrupted or contained no data"); + SPDLOG_INFO(" Scenefile corrupted or contained no data"); return; } - SPDLOG_INFO("[SceneManager] [LoadLevel] Loading track scenefile..."); + SPDLOG_INFO(" Loading Props, Actors, Static Mesh Actors, and Tour..."); // Load the Props, and populate actors LoadProps(track, data); + LoadPaths(track, trackPath); + LoadMinimap(track, trackPath); LoadActors(track, data); LoadStaticMeshActors(track, data); LoadTour(track, data); - SPDLOG_INFO("[SceneManager] [LoadLevel] Scene File Loaded!"); + SPDLOG_INFO("[SceneManager] [LoadTrackDataFromJson] Scene File Loaded!"); + } + + void LoadTrackInfo(TrackInfo& info, std::shared_ptr<Ship::Archive> archive, std::string sceneFile) { + if (nullptr == archive) { + SPDLOG_INFO("[SceneManager] [LoadTrackDataFromJson] Failed to load scenefile, track or rootarchive were null"); + return; + } + + /* + * Manually loading a custom asset file (scene.json) with no extractor class means that + * the init data needs to be manually populated + */ + auto initData = std::make_shared<Ship::ResourceInitData>(); + initData->Parent = archive; + initData->Format = RESOURCE_FORMAT_BINARY; + initData->ByteOrder = Ship::Endianness::Little; + initData->Type = static_cast<uint32_t>(Ship::ResourceType::Json); + initData->ResourceVersion = 0; + + // Load the scene file and return the json data + nlohmann::json data = std::static_pointer_cast<Ship::Json>( + GameEngine::Instance->context->GetResourceManager()->LoadResource(sceneFile, true, initData))->Data; + + // Check that the data is valid + if (data.is_null() || !data.is_object() || data.empty()) { + SPDLOG_INFO("[SceneManager] [LoadTrackInfo] Scenefile corrupted or contained no data"); + return; + } + + LoadTrackInfoData(info, data); + + SPDLOG_INFO("[SceneManager] [LoadTrackInfo] Loaded track info!"); } void Load_AddStaticMeshActor(const nlohmann::json& actorJson) { - gWorldInstance.StaticMeshActors.push_back(new StaticMeshActor("", FVector(0, 0, 0), IRotator(0, 0, 0), FVector(1, 1, 1), "", nullptr)); - auto actor = gWorldInstance.StaticMeshActors.back(); + GetWorld()->StaticMeshActors.push_back(std::make_unique<StaticMeshActor>("", FVector(0, 0, 0), IRotator(0, 0, 0), FVector(1, 1, 1), "", nullptr)); + auto& actor = GetWorld()->StaticMeshActors.back(); actor->from_json(actorJson); printf("After from_json: Pos(%f, %f, %f), Name: %s, Model: %s\n", actor->Pos.x, actor->Pos.y, actor->Pos.z, actor->Name.c_str(), actor->Model.c_str()); } - void SetSceneFile(std::shared_ptr<Ship::Archive> archive, std::string sceneFile) { - CurrentArchive = archive; - SceneFile = sceneFile; - } - - // Called from ContentBrowser.cpp void LoadMinimap(Track* track, std::string filePath) { + std::string minimapPath = filePath + "/minimap.png"; SPDLOG_INFO(" Loading {} minimap...", filePath); - if (nullptr == track->RootArchive) { - SPDLOG_INFO("[SceneManager] [LoadMinimap] Root archive is nullptr"); - SetDefaultMinimap(track); - return; - } /* * Manually loading a custom asset file with no extractor class means that * the init data needs to be manually populated */ auto initData = std::make_shared<Ship::ResourceInitData>(); - initData->Parent = track->RootArchive; + initData->Parent = track->Archive; initData->Format = RESOURCE_FORMAT_BINARY; initData->ByteOrder = Ship::Endianness::Little; initData->Type = static_cast<uint32_t>(MK64::ResourceType::Minimap); initData->ResourceVersion = 0; std::shared_ptr<MK64::Minimap> ptr = std::static_pointer_cast<MK64::Minimap>( - GameEngine::Instance->context->GetResourceManager()->LoadResource(filePath, true, initData)); + GameEngine::Instance->context->GetResourceManager()->LoadResource(minimapPath, true, initData)); if (ptr) { SPDLOG_INFO(" Minimap Loaded!"); @@ -180,7 +215,7 @@ namespace Editor { } void SaveActors(nlohmann::json& actorList) { - for (const auto& actor : gWorldInstance.Actors) { + for (const auto& actor : GetWorld()->Actors) { SpawnParams params{}; bool alreadyProcessed = false; @@ -234,7 +269,7 @@ namespace Editor { } } - for (const auto& object : gWorldInstance.Objects) { + for (const auto& object : GetWorld()->Objects) { SpawnParams params; object->SetSpawnParams(params); @@ -247,17 +282,17 @@ namespace Editor { } void SaveStaticMeshActors(nlohmann::json& actorList) { - for (const auto& mesh : gWorldInstance.StaticMeshActors) { + for (const auto& mesh : GetWorld()->StaticMeshActors) { actorList.push_back(mesh->to_json()); } } - void SaveTour(nlohmann::json& tour) { - tour["Enabled"] = gWorldInstance.GetTrack()->bTourEnabled; + void SaveTour(Track* track, nlohmann::json& tour) { + tour["Enabled"] = track->bTourEnabled; // Camera shots tour["Shots"] = nlohmann::json::array(); - for (const auto& shot : gWorldInstance.GetTrack()->TourShots) { + for (const auto& shot : track->TourShots) { tour["Shots"].push_back(ToJson(shot)); } } @@ -276,8 +311,58 @@ namespace Editor { } } + void LoadPaths(Track* track, const std::string& trackPath) { + std::string path_file = (trackPath + "/data_paths").c_str(); + + auto res = std::dynamic_pointer_cast<MK64::Paths>(ResourceLoad(path_file.c_str())); + + if (res != nullptr) { + auto& paths = res->PathList; + + size_t i = 0; + u16* ptr = &track->Props.PathSizes.unk0; + for (auto& path : paths) { + if (i >= ARRAY_COUNT(track->Props.PathTable2)) { + printf("[Track.cpp] The game can only import 5 paths. Found more than 5. Skipping the rest\n"); + break; // Only 5 paths allowed. 4 track, 1 vehicle + } + ptr[i] = path.size(); + track->Props.PathTable2[i] = (TrackPathPoint*) path.data(); + + i += 1; + } + } + gVehiclePathSize = track->Props.PathSizes.unk0; // This is likely incorrect. + } + + void LoadTrackInfoData(TrackInfo& info, nlohmann::json& data) { + if (!data.contains("Props") || !data["Props"].is_object()) { + SPDLOG_INFO("[SceneManager] [LoadTrackInfoData] Track is missing props data. Is the scene.json file corrupt?"); + return; + } + + try { + nlohmann::json& j = data.at("Props"); + + info.ResourceName = j.at("ResourceName").get<std::string>(); + info.Name = j.at("Name").get<std::string>(); + info.DebugName = j.at("DebugName").get<std::string>(); + info.Length = j.at("TrackLength").get<std::string>(); + + printf("[SceneManager] [LoadTrackInfoData] ResourceName: %s, Name: %s, DebugName: %s, Length: %s\n", + info.ResourceName.c_str(), + info.Name.c_str(), + info.DebugName.c_str(), + info.Length.c_str() + ); + } catch(const std::exception& e) { + std::cerr << " Error parsing track properties: " << e.what() << std::endl; + std::cerr << " Is your scene.json file out of date?" << std::endl; + } + } + void LoadActors(Track* track, nlohmann::json& data) { - if (!data.contains("Actors") || !data["Actors"].is_object()) { + if (!data.contains("Actors") || !data["Actors"].is_array()) { SPDLOG_INFO(" This track contains no actors"); return; } @@ -294,12 +379,12 @@ namespace Editor { } void LoadStaticMeshActors(Track* track, nlohmann::json& data) { - if (!data.contains("StaticMeshActors") || !data["StaticMeshActors"].is_object()) { + if (!data.contains("StaticMeshActors") || !data["StaticMeshActors"].is_array()) { SPDLOG_INFO(" This track contains no StaticMeshActors!"); return; } - gWorldInstance.StaticMeshActors.clear(); // Clear existing actors, if any + GetWorld()->StaticMeshActors.clear(); // Clear existing actors, if any for (const auto& actorJson : data["StaticMeshActors"]) { Load_AddStaticMeshActor(actorJson); @@ -308,7 +393,7 @@ namespace Editor { void LoadTour(Track* track, nlohmann::json& data) { if (!data.contains("Tour") || !data["Tour"].is_object()) { - SPDLOG_INFO(" This track does not contain a camera tour"); + SPDLOG_INFO(" This track does not contain a camera tour"); return; } |
