diff options
| author | MegaMech <MegaMech@users.noreply.github.com> | 2025-12-13 11:50:28 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-13 11:50:28 -0700 |
| commit | b934e98fc34964970ab5efacb2fb7c3372ae0b1a (patch) | |
| tree | cd96e5fabec7fdcc098d0de33b3b7e2754fb6cd5 /src/engine/editor | |
| parent | e6acb59ef4797ce27ddc9e21982c3f4e40824b52 (diff) | |
Refactor Track Class To Instantiate On Track Load (#587)
* Initial Commit
* First compilation of Registry template
* Further changes
* wip changes
* Impl TrackBrowser and Registry Info
* Remove const from TInfo
* Prep GetWorld
* Name refactor
* Refactor gWorldInstance to GetWorld()
* wip
* Should work now
* Data menu work again
* Fix editor staying open after program close
* Rename LoadLevel to LoadTrackDataFromJson
* More changes
* Add statue
* Add search to content browser using tags
* Fix statue pos and register tags
* Fix actor loading
* Fix delete all bug which deleted cameras
* reduce some boiler plate in actor and object
* Remove unused rulesets
* Search bar for all tabs
* fix data screen
* fix actor spawning
* temp editor fix
* Clean up
* improve extra mode transformation
* fix podium crash
* Fix editor clicking
* Fix editor clicking 2
* fix extra in custom track
* Fix FI for three actors
* Fix divide by zero error
* Ids managed by Registry
* Add scary comment
---------
Co-authored-by: MegaMech <7255464+MegaMech@users.noreply.github.com>
Co-authored-by: coco875 <pereira.jannin@gmail.com>
Diffstat (limited to 'src/engine/editor')
| -rw-r--r-- | src/engine/editor/Collision.cpp | 6 | ||||
| -rw-r--r-- | src/engine/editor/Editor.cpp | 83 | ||||
| -rw-r--r-- | src/engine/editor/Editor.h | 39 | ||||
| -rw-r--r-- | src/engine/editor/EditorMath.cpp | 6 | ||||
| -rw-r--r-- | src/engine/editor/Gizmo.cpp | 8 | ||||
| -rw-r--r-- | src/engine/editor/Light.cpp | 2 | ||||
| -rw-r--r-- | src/engine/editor/ObjectPicker.cpp | 12 | ||||
| -rw-r--r-- | src/engine/editor/SceneManager.cpp | 179 | ||||
| -rw-r--r-- | src/engine/editor/SceneManager.h | 14 |
9 files changed, 253 insertions, 96 deletions
diff --git a/src/engine/editor/Collision.cpp b/src/engine/editor/Collision.cpp index 5a6d734ba..f79865899 100644 --- a/src/engine/editor/Collision.cpp +++ b/src/engine/editor/Collision.cpp @@ -7,6 +7,7 @@ #include "engine/Actor.h" #include "engine/objects/Object.h" #include "engine/editor/GameObject.h" +#include "port/Game.h" extern "C" { #include "main.h" @@ -24,11 +25,6 @@ namespace Editor { size_t i = 0; bool run = true; - //! @attention Objects will not be clickable if editor is enabled mid-race. - if (CVarGetInteger("gEditorEnabled", false) == true) { - return; - } - while (run) { i++; lo = ptr->words.w0; diff --git a/src/engine/editor/Editor.cpp b/src/engine/editor/Editor.cpp index 911cc9a8c..698a6cc40 100644 --- a/src/engine/editor/Editor.cpp +++ b/src/engine/editor/Editor.cpp @@ -12,6 +12,7 @@ #include <ship/controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h> #include <ship/window/Window.h> +#include "engine/TrackBrowser.h" #include "engine/actors/Ship.h" #include "port/Game.h" @@ -24,7 +25,10 @@ extern "C" { } namespace Editor { + Editor* Editor::Instance; + Editor::Editor() { + Instance = this; } Editor::~Editor() { @@ -43,28 +47,65 @@ namespace Editor { printf("Editor: Loading Complete!\n"); } + void Editor::Enable() { + bEditorEnabled = true; + bIsEditorPaused = true; + CVarSetInteger("gFreecam", true); + CM_SetFreeCamera(true); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Tools")->Show(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Scene Explorer")->Show(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Content Browser")->Show(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Track Properties")->Show(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Properties")->Show(); + } + + void Editor::Disable() { + bEditorEnabled = false; + bIsEditorPaused = false; + CVarSetInteger("gFreecam", false); + CM_SetFreeCamera(false); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Tools")->Hide(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Scene Explorer")->Hide(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Content Browser")->Hide(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Track Properties")->Hide(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Properties")->Hide(); + } + + bool Editor::IsEnabled() { + return bEditorEnabled; + } + + void Editor::Play() { + bIsEditorPaused = false; + } + + void Editor::Pause() { + bIsEditorPaused = true; + } + + bool Editor::IsPaused() { + return bIsEditorPaused; + } + + void Editor::TogglePlayState() { + bIsEditorPaused = !bIsEditorPaused; + } + void Editor::GenerateCollision() { - // for (auto& actor : gWorldInstance.Actors) { + // for (auto& actor : GetWorld()->Actors) { // GenerateCollisionMesh(actor, (Gfx*)actor->Model, 1.0f); // } } void Editor::Tick() { - if (CVarGetInteger("gEditorEnabled", 0) == true) { + if (Editor_IsEnabled() == true) { bEditorEnabled = true; } else { bEditorEnabled = false; - gIsEditorPaused = false; // Prevents game being paused with the editor closed. + bIsEditorPaused = false; // Prevents game being paused with the editor closed. return; } - // Set camera - if (CVarGetInteger("gFreecam", 0) == true) { - eCamera = &cameras[CAMERA_FREECAM]; - } else { - eCamera = &cameras[0]; - } - auto wnd = GameEngine::Instance->context->GetWindow(); static bool wasMouseDown = false; @@ -111,7 +152,6 @@ namespace Editor { if (!isDragging) { eObjectPicker.SelectObject(eGameObjects); } - } wasMouseDown = isMouseDown; // Update previous state @@ -197,3 +237,24 @@ namespace Editor { eObjectPicker.eGizmo.dimensions.MaxZ = maxZ + 1000; } } + +/** C BRIDGE FUNCTIONS **/ + +extern "C" void Editor_Launch(const char* resourceName) { +#if not defined(__SWITCH__) and not defined(__WIIU__) + TrackBrowser::Instance->SetTrack(std::string(resourceName)); + gEditor.Enable(); +#endif +} + +extern "C" void Editor_SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY) { + gEditor.SetLevelDimensions(minX, maxX, minZ, maxZ, minY, maxY); +} + +extern "C" bool Editor_IsEnabled() { + return gEditor.IsEnabled(); +} + +extern "C" bool Editor_IsPaused() { + return gEditor.IsPaused(); +} diff --git a/src/engine/editor/Editor.h b/src/engine/editor/Editor.h index 38af5b915..77169de46 100644 --- a/src/engine/editor/Editor.h +++ b/src/engine/editor/Editor.h @@ -1,12 +1,12 @@ -#ifndef __EDITOR_H__ -#define __EDITOR_H__ +#ifndef EDITOR_H +#define EDITOR_H #include <libultraship/libultraship.h> #include <libultra/gbi.h> -#include "GameObject.h" #ifdef __cplusplus +#include "GameObject.h" extern "C" { #include "camera.h" } @@ -17,15 +17,23 @@ namespace Editor { class Editor { public: + static Editor* Instance; Editor(); ~Editor(); ObjectPicker eObjectPicker; std::vector<GameObject*> eGameObjects; - + + void Load(); + void Enable(); + void Disable(); + bool IsEnabled(); + void Play(); + void Pause(); + bool IsPaused(); + void TogglePlayState(); void Tick(); void Draw(); - void Load(); void GenerateCollision(); GameObject* AddObject(FVector pos, IRotator rot, FVector scale, const char* model, float collScale, GameObject::CollisionType collision, float boundingBoxSize); void AddLight(const char* name, FVector* pos, s8* rot); @@ -36,10 +44,9 @@ public: void SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY); void ClearMatrixPool(); void DeleteObject(); - bool bEditorEnabled = false; - - Camera* eCamera = &cameras[0]; private: + bool bIsEditorPaused = false; + bool bEditorEnabled = false; bool _draw = false; Vec3f _ray; @@ -47,9 +54,19 @@ private: void Copy(MtxF* src, MtxF* dest); void Clear(MtxF* mf); }; -} +} // namespace Editor +#endif // __cplusplus + + +#ifdef __cplusplus +#define EXTERN_C extern "C" +#else +#define EXTERN_C #endif -void SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY); +EXTERN_C void Editor_Launch(const char* resourceName); +EXTERN_C void Editor_SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY); +EXTERN_C bool Editor_IsEnabled(); +EXTERN_C bool Editor_IsPaused(); -#endif // __EDITOR_H__ +#endif // EDITOR_H diff --git a/src/engine/editor/EditorMath.cpp b/src/engine/editor/EditorMath.cpp index 93d826ace..620aa2b48 100644 --- a/src/engine/editor/EditorMath.cpp +++ b/src/engine/editor/EditorMath.cpp @@ -42,7 +42,7 @@ bool IsInGameScreen() { FVector ScreenRayTrace() { auto wnd = GameEngine::Instance->context->GetWindow(); - Camera* camera = gEditor.eCamera; + Camera* camera = gScreenOneCtx->camera; Ship::Coords mouse = wnd->GetMousePos(); auto gfx_current_game_window_viewport = GetInterpreter()->mGameWindowViewport; @@ -62,7 +62,7 @@ FVector ScreenRayTrace() { Mat4 perspMtx; u16 perspNorm; - guPerspectiveF(perspMtx, &perspNorm, gCameraFOV[0], OTRGetAspectRatio(), CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f); + guPerspectiveF(perspMtx, &perspNorm, 40, OTRGetAspectRatio(), CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f); Mat4 inversePerspMtx; if (InverseMatrix((float*)&perspMtx, (float*)&inversePerspMtx) != 2) { @@ -412,7 +412,7 @@ void SetRotatorFromDirection(FVector direction, IRotator* rot) { } FVector GetPositionAheadOfCamera(f32 dist) { - Camera* camera = gEditor.eCamera; + Camera* camera = gScreenOneCtx->camera; FVector pos = FVector(camera->pos[0], camera->pos[1], camera->pos[2]); f32 pitch = (camera->rot[2] / 65535.0f) * 360.0f; diff --git a/src/engine/editor/Gizmo.cpp b/src/engine/editor/Gizmo.cpp index 6cb4c74a8..4d3c86d25 100644 --- a/src/engine/editor/Gizmo.cpp +++ b/src/engine/editor/Gizmo.cpp @@ -112,7 +112,7 @@ void Gizmo::Translate() { static float length = 180.0f; // Default value std::visit([this](auto* obj) { - Camera* camera = gEditor.eCamera; + Camera* camera = gScreenOneCtx->camera; float x, y, z = 0; if (nullptr == obj) { return; @@ -217,7 +217,7 @@ f32 Gizmo::SnapToSurface(const FVector pos) { void Gizmo::Rotate() { std::visit([this](auto* obj) { - Camera* camera = gEditor.eCamera; + Camera* camera = gScreenOneCtx->camera; FVector cam = FVector(camera->pos[0], camera->pos[1], camera->pos[2]); IRotator rot; @@ -269,7 +269,7 @@ void Gizmo::Rotate() { void Gizmo::Scale() { std::visit([this](auto* obj) { - Camera* camera = gEditor.eCamera; + Camera* camera = gScreenOneCtx->camera; FVector cam = FVector(camera->pos[0], camera->pos[1], camera->pos[2]); if (nullptr == obj) { return; @@ -398,7 +398,7 @@ void Gizmo::DrawHandles() { Editor_AddMatrix(mainMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); if (center) { - Camera* camera = gEditor.eCamera; + Camera* camera = gScreenOneCtx->camera; Mat4 CenterMtx; Editor_MatrixIdentity(CenterMtx); diff --git a/src/engine/editor/Light.cpp b/src/engine/editor/Light.cpp index 6aa332d6e..53dc00864 100644 --- a/src/engine/editor/Light.cpp +++ b/src/engine/editor/Light.cpp @@ -57,7 +57,7 @@ size_t LightObject::NumLights = 0; SetDirectionFromRotator(Rot, Direction); } void LightObject::Draw() { - Camera* camera = gEditor.eCamera; + Camera* camera = gScreenOneCtx->camera; Mat4 mtx_sun; Editor_MatrixIdentity(mtx_sun); gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH); diff --git a/src/engine/editor/ObjectPicker.cpp b/src/engine/editor/ObjectPicker.cpp index 0d88db35c..cbce7dd09 100644 --- a/src/engine/editor/ObjectPicker.cpp +++ b/src/engine/editor/ObjectPicker.cpp @@ -35,7 +35,7 @@ void ObjectPicker::Tick() { } void ObjectPicker::SelectObject(std::vector<GameObject*> objects) { - Camera* camera = gEditor.eCamera; + Camera* camera = gScreenOneCtx->camera; Ray ray; ray.Origin = FVector(camera->pos[0], camera->pos[1], camera->pos[2]); @@ -59,7 +59,7 @@ void ObjectPicker::SelectObject(std::vector<GameObject*> objects) { } void ObjectPicker::DragHandle() { - Camera* camera = gEditor.eCamera; + Camera* camera = gScreenOneCtx->camera; Ray ray; ray.Origin = FVector(camera->pos[0], camera->pos[1], camera->pos[2]); ray.Direction = ScreenRayTrace(); @@ -136,7 +136,7 @@ void ObjectPicker::Draw() { }, _selected); if (Debug) { - Camera* camera = gEditor.eCamera; + Camera* camera = gScreenOneCtx->camera; Mat4 CursorMtx; IRotator rot = IRotator(0,0,0); FVector scale = FVector(1, 1, 1); @@ -249,7 +249,7 @@ std::pair<AActor*, float> ObjectPicker::CheckAActorRay(Ray ray) { AActor* hitActor = nullptr; float hitDistance = FLT_MAX; - for (auto actor : gWorldInstance.Actors) { + for (const auto& actor : GetWorld()->Actors) { if ((actor->bPendingDestroy) && (!actor->IsMod())) { continue; } @@ -265,7 +265,7 @@ std::pair<AActor*, float> ObjectPicker::CheckAActorRay(Ray ray) { if (IntersectRayTriangleAndTransform(ray, FVector(actor->Pos[0], actor->Pos[1], actor->Pos[2]), tri, t)) { if (t < hitDistance) { hitDistance = t; - hitActor = static_cast<AActor*>(actor); + hitActor = actor.get(); } } } @@ -283,7 +283,7 @@ std::pair<AActor*, float> ObjectPicker::CheckAActorRay(Ray ray) { if (QueryCollisionRayActor(&ray.Origin.x, &ray.Direction.x, boxMin, boxMax, &t)) { if (t < hitDistance) { hitDistance = t; - hitActor = static_cast<AActor*>(actor); + hitActor = actor.get(); } } } 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; } diff --git a/src/engine/editor/SceneManager.h b/src/engine/editor/SceneManager.h index f7b3a50bb..48b52a1e2 100644 --- a/src/engine/editor/SceneManager.h +++ b/src/engine/editor/SceneManager.h @@ -7,28 +7,26 @@ #include <nlohmann/json.hpp> namespace Editor { - void SaveLevel(); - void LoadLevel(Track* track, std::string sceneFile); + void SaveLevel(Track* track); + void LoadTrackDataFromJson(Track* track, const std::string& trackPath); + void LoadTrackInfo(TrackInfo& info, std::shared_ptr<Ship::Archive> archive, std::string sceneFile); void Load_AddStaticMeshActor(const nlohmann::json& actorJson); - void SetSceneFile(std::shared_ptr<Ship::Archive> archive, std::string sceneFile); void LoadMinimap(Track* track, std::string filePath); void SetDefaultMinimap(Track* track); void SaveActors(nlohmann::json& actorList); void SaveStaticMeshActors(nlohmann::json& actorList); - void SaveTour(nlohmann::json& tour); + void SaveTour(Track* track, nlohmann::json& tour); void LoadProps(Track* track, nlohmann::json& data); + void LoadPaths(Track* track, const std::string& trackPath); + void LoadTrackInfoData(TrackInfo& info, nlohmann::json& data); void LoadActors(Track* track, nlohmann::json& data); void LoadStaticMeshActors(Track* track, nlohmann::json& data); void LoadTour(Track* track, nlohmann::json& data); void SpawnActors(std::vector<std::pair<std::string, SpawnParams>> spawnList); - extern std::shared_ptr<Ship::Archive> CurrentArchive; // This is used to retrieve and write the scene data file - extern std::string SceneFile; - - inline nlohmann::json ToJson(const FVector& v) { return { {"x", v.x}, |
