summaryrefslogtreecommitdiff
path: root/src/engine/editor/SceneManager.cpp
diff options
context:
space:
mode:
authorMegaMech <MegaMech@users.noreply.github.com>2025-12-07 13:14:45 -0700
committerGitHub <noreply@github.com>2025-12-07 13:14:45 -0700
commit65853330926fa5c77ad75effab8c479ba1d96952 (patch)
treeb2bd8f865401a8d7c4ce9f78b94f34bfb778dbaf /src/engine/editor/SceneManager.cpp
parent02ad54ca72f5baf4614cb9b7c30f8dd780764d90 (diff)
Camera Refactor --> Adds Track Tour Camera (#568)
* Impl SpawnParams * Added json submodule * Update json * Update * Works * Remove comment * Works refactor * Snowman and thwomp working * Impl hot air balloon * More progress * All OObjects are done * cleanup * Refactor 2Dpath to normal path * Update nlohmann json & fix compile * Rest of actors * MORE CHANGES * Finish actors * Done PR, some fix to collision viewer * Impl falling rocks * Add const * wip editor refactor * Property work * continue * Overridable editor properties * Actor saving/loading works now * Fix light alignment * Clarification * Impl penguin * params impl signs * properties impl falling rock * More property impls * impl air balloon * Add spawnParams to OObject Translate * Snowman translate better * impl hedgehog properly * properties impl trophy * thwomp progress * Finish impl properties * Fix compile * Fix cursor collisions * Move registered actors * Rename pathPoint XYZ to xyz * Fix editor pause bug * Clean up * Review comments * Remove SpawnParams struct from actor classes * Rename * Player Label First Iteration * Work now * Working 3d text * Fix boo bug * Finish AText actor * Fix spawnparams compile * Register AText * Finish Text Actor * Fix thwomp interpolation * Fix compile * Fix crab and hedgehog * Fix loading flagpole * Fix Hot Air Balloon * Turn zbuffer on for AText * Update * Camera Refactor * Camera Refactor Complete * Place Lookbehind behind a CVar * Make Tour CVar * Fix Tour Camera Billboarding * micro optimization * Impl tour cam in imgui editor and add to scenefile * As per review * Revert cleanWorld change as per review * Cleanup SceneManager * Func rename * Proper enabling of freecam and wip zoom fix * Couple fix * Fix credits * Fix podium ceremony * Stop music on reset & label new play sequence func * Rename func_800C8EF8 to play_sequence2 * Rename func_800CA414 to play_sequences * Fix compile * Label play_sequences * Clean up * Verify lakitu access * Renames * Fix tour enable logic * Add Audio * tour camera impl ending transition * As per review * Fix linux compile, probably * Update TourCamera.cpp * Update TourCamera.cpp * Update TrackProperties.cpp * Update TrackProperties.cpp * Update Game.cpp * Update SceneManager.cpp * Update camera.c * Update render_objects.h * Update render_objects.h * Update code_80057C60.h * fixing compile * addition --------- Co-authored-by: MegaMech <7255464+MegaMech@users.noreply.github.com>
Diffstat (limited to 'src/engine/editor/SceneManager.cpp')
-rw-r--r--src/engine/editor/SceneManager.cpp303
1 files changed, 195 insertions, 108 deletions
diff --git a/src/engine/editor/SceneManager.cpp b/src/engine/editor/SceneManager.cpp
index f34b18adb..90a33f48f 100644
--- a/src/engine/editor/SceneManager.cpp
+++ b/src/engine/editor/SceneManager.cpp
@@ -1,4 +1,5 @@
#include "SceneManager.h"
+
#include "port/Game.h"
#include "engine/CoreMath.h"
#include "World.h"
@@ -19,7 +20,7 @@
#include "engine/objects/Object.h"
#include "engine/objects/Thwomp.h"
#include "engine/objects/Snowman.h"
-#include <iostream>
+#include "engine/cameras/TourCamera.h"
extern "C" {
#include "common_structs.h"
@@ -28,112 +29,98 @@ extern "C" {
}
namespace Editor {
-
std::shared_ptr<Ship::Archive> CurrentArchive;
std::string SceneFile = "";
void SaveLevel() {
- auto props = gWorldInstance.GetCurrentCourse()->Props;
+ if ((!CurrentArchive) || (SceneFile.empty())) {
+ SPDLOG_INFO("[SceneManager] [SaveLevel] Could not save scene file, SceneFile or CurrentArchive not set");
+ return;
+ }
+ nlohmann::json data;
- if ((CurrentArchive) && (!SceneFile.empty())) {
- nlohmann::json data;
-
- data["Props"] = props.to_json();
+ /**
+ * Save track properties, static mesh actors, actors, and tour camera
+ */
+ data["Props"] = gWorldInstance.GetCurrentCourse()->Props.to_json();
- nlohmann::json staticMesh;
+ nlohmann::json staticMesh;
+ SaveStaticMeshActors(staticMesh);
+ data["StaticMeshActors"] = staticMesh;
- for (const auto& mesh : gWorldInstance.StaticMeshActors) {
- staticMesh.push_back(mesh->to_json());
- }
- data["StaticMeshActors"] = staticMesh;
- nlohmann::json actors;
+ nlohmann::json actors;
+ SaveActors(actors);
+ data["Actors"] = actors;
- SaveActors(actors);
- data["Actors"] = actors;
-
- try {
- auto dat = data.dump(2);
- std::vector<uint8_t> stringify;
- stringify.assign(dat.begin(), dat.end());
+ if (gWorldInstance.GetCurrentCourse()->TourShots.size() != 0) {
+ nlohmann::json tour;
+ SaveTour(tour);
+ data["Tour"] = tour;
+ }
- bool wrote = GameEngine::Instance->context->GetResourceManager()->GetArchiveManager()->WriteFile(CurrentArchive, SceneFile, stringify);
- if (wrote) {
- // Tell the cache this needs to be reloaded
- auto resource = GameEngine::Instance->context->GetResourceManager()->GetCachedResource(SceneFile);
- if (resource) {
- resource->Dirty();
- }
- } else {
- printf("[SceneManager::SaveLevel] Failed to write scene file!\n");
+ /**
+ * Write data to file
+ */
+ try {
+ std::string jsonStr = data.dump(2);
+ std::vector<uint8_t> bytes; // Turn the str into raw data
+ bytes.assign(jsonStr.begin(), jsonStr.end());
+
+ // Write file to disk
+ bool wrote = GameEngine::Instance->context->GetResourceManager()->GetArchiveManager()->WriteFile(CurrentArchive, SceneFile, bytes);
+ if (wrote) {
+ // Tell the cache this file needs to be reloaded
+ auto resource = GameEngine::Instance->context->GetResourceManager()->GetCachedResource(SceneFile);
+ if (resource) {
+ resource->Dirty();
}
- } catch (const nlohmann::json::exception& e) {
- printf("[SceneManager::SaveLevel]\n JSON error during dump: %s\n", e.what());
+ } else {
+ SPDLOG_INFO("[SceneManager] [SaveLevel] Failed to write scene file!");
}
- } else {
- printf("Could not save scene file, SceneFile or CurrentArchive not set\n");
+ } catch (const nlohmann::json::exception& e) {
+ SPDLOG_INFO("[SceneManager] [SaveLevel] JSON error during dump: {}", e.what());
}
}
-
/** Do not use gWorldInstance.CurrentCourse during loading! The current track is not guaranteed! **/
void LoadLevel(Course* course, std::string sceneFile) {
SceneFile = sceneFile;
- if ((nullptr != course) && (nullptr != course->RootArchive)) {
- auto initData = std::make_shared<Ship::ResourceInitData>();
- initData->Parent = course->RootArchive;
- initData->Format = RESOURCE_FORMAT_BINARY;
- initData->ByteOrder = Ship::Endianness::Little;
- initData->Type = static_cast<uint32_t>(Ship::ResourceType::Json);
- initData->ResourceVersion = 0;
-
- nlohmann::json data = std::static_pointer_cast<Ship::Json>(
- GameEngine::Instance->context->GetResourceManager()->LoadResource(sceneFile, true, initData))->Data;
-
- if (data.is_null() || data.empty()) {
- return;
- }
+ if ((nullptr == course) || (nullptr == course->RootArchive)) {
+ SPDLOG_INFO("[SceneManager] [LoadLevel] Failed to load scenefile, course or rootarchive were null");
+ return;
+ }
- // Load the Props (deserialize it)
- if (data.contains("Props")) {
- auto& propsJson = data["Props"];
- try {
- course->Props.from_json(propsJson);
- } catch(const std::exception& e) {
- std::cerr << "SceneManager::LoadLevel() Error parsing track properties: " << e.what() << std::endl;
- std::cerr << " Is your scene.json file out of date?" << std::endl;
- }
- } else {
- std::cerr << "Props data not found in the JSON file!" << std::endl;
- }
+ /*
+ * 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 = course->RootArchive;
+ 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] [LoadLevel] Scenefile corrupted or contained no data");
+ return;
+ }
- /** Populate Track SpawnParams for spawning actors **/
- if (data.contains("Actors")) {
- auto & actorsJson = data["Actors"];
- course->SpawnList.clear();
- for (const auto& actor : actorsJson) {
- SpawnParams params;
- params.from_json(actor); //<SpawnParams>();
- if (!params.Name.empty()) {
- course->SpawnList.push_back(params);
- }
- }
- SPDLOG_INFO("[SceneManager] Loaded Scene File!");
- }
+ SPDLOG_INFO("[SceneManager] [LoadLevel] Loading track scenefile...");
- // Load the Actors (deserialize them)
- if (data.contains("StaticMeshActors")) {
- auto& actorsJson = data["StaticMeshActors"];
- gWorldInstance.StaticMeshActors.clear(); // Clear existing actors, if any
-
- for (const auto& actorJson : actorsJson) {
- Load_AddStaticMeshActor(actorJson);
- }
- } else {
- SPDLOG_INFO("[SceneManager::LoadLevel] [scene.json] This track contains no StaticMeshActors!");
- }
- }
+ // Load the Props, and populate actors
+ LoadProps(course, data);
+ LoadActors(course, data);
+ LoadStaticMeshActors(course, data);
+ LoadTour(course, data);
+ SPDLOG_INFO("[SceneManager] [LoadLevel] Scene File Loaded!");
}
void Load_AddStaticMeshActor(const nlohmann::json& actorJson) {
@@ -150,31 +137,46 @@ namespace Editor {
SceneFile = sceneFile;
}
+ // Called from ContentBrowser.cpp
void LoadMinimap(Course* course, std::string filePath) {
- printf("LOADING MINIMAP %s\n", filePath.c_str());
- if ((nullptr != course) && (nullptr != course->RootArchive)) {
- auto initData = std::make_shared<Ship::ResourceInitData>();
- initData->Parent = course->RootArchive;
- 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));
-
- if (ptr) {
- printf("LOADED MINIMAP!\n");
- MK64::MinimapTexture texture = ptr->Texture;
- course->Props.Minimap.Texture = (const char*)texture.Data;
- course->Props.Minimap.Width = texture.Width;
- course->Props.Minimap.Height = texture.Height;
- } else { // Fallback
- course->Props.Minimap.Texture = minimap_mario_raceway;
- course->Props.Minimap.Width = ResourceGetTexWidthByName(course->Props.Minimap.Texture);
- course->Props.Minimap.Height = ResourceGetTexHeightByName(course->Props.Minimap.Texture);
- }
+ SPDLOG_INFO(" Loading {} minimap...", filePath);
+ if (nullptr == course->RootArchive) {
+ SPDLOG_INFO("[SceneManager] [LoadMinimap] Root archive is nullptr");
+ SetDefaultMinimap(course);
+ 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 = course->RootArchive;
+ 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));
+
+ if (ptr) {
+ SPDLOG_INFO(" Minimap Loaded!");
+ MK64::MinimapTexture texture = ptr->Texture;
+ course->Props.Minimap.Texture = (const char*)texture.Data;
+ course->Props.Minimap.Width = texture.Width;
+ course->Props.Minimap.Height = texture.Height;
+ } else { // Fallback
+ SetDefaultMinimap(course);
+ }
+ }
+
+ // Sets the default minimap if none has been set
+ void SetDefaultMinimap(Course* course) {
+ course->Props.Minimap.Texture = minimap_mario_raceway;
+ course->Props.Minimap.Width = ResourceGetTexWidthByName(course->Props.Minimap.Texture);
+ course->Props.Minimap.Height = ResourceGetTexHeightByName(course->Props.Minimap.Texture);
+ SPDLOG_INFO(" No minimap found! Falling back to default minimap");
}
void SaveActors(nlohmann::json& actorList) {
@@ -243,4 +245,89 @@ namespace Editor {
}
}
}
+
+ void SaveStaticMeshActors(nlohmann::json& actorList) {
+ for (const auto& mesh : gWorldInstance.StaticMeshActors) {
+ actorList.push_back(mesh->to_json());
+ }
+ }
+
+ void SaveTour(nlohmann::json& tour) {
+ tour["Enabled"] = gWorldInstance.GetCurrentCourse()->bTourEnabled;
+
+ // Camera shots
+ tour["Shots"] = nlohmann::json::array();
+ for (const auto& shot : gWorldInstance.GetCurrentCourse()->TourShots) {
+ tour["Shots"].push_back(ToJson(shot));
+ }
+ }
+
+ void LoadProps(Course* course, nlohmann::json& data) {
+ if (!data.contains("Props") || !data["Props"].is_object()) {
+ SPDLOG_INFO("Track is missing props data. Is the scene.json file corrupt?");
+ return;
+ }
+
+ try {
+ course->Props.from_json(data["Props"]);
+ } 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(Course* course, nlohmann::json& data) {
+ if (!data.contains("Actors") || !data["Actors"].is_object()) {
+ SPDLOG_INFO(" This track contains no actors");
+ return;
+ }
+
+ course->SpawnList.clear(); // Clear existing actors, if any
+
+ for (const auto& actor : data["Actors"]) {
+ SpawnParams params;
+ params.from_json(actor); //<SpawnParams>();
+ if (!params.Name.empty()) {
+ course->SpawnList.push_back(params);
+ }
+ }
+ }
+
+ void LoadStaticMeshActors(Course* course, nlohmann::json& data) {
+ if (!data.contains("StaticMeshActors") || !data["StaticMeshActors"].is_object()) {
+ SPDLOG_INFO(" This track contains no StaticMeshActors!");
+ return;
+ }
+
+ gWorldInstance.StaticMeshActors.clear(); // Clear existing actors, if any
+
+ for (const auto& actorJson : data["StaticMeshActors"]) {
+ Load_AddStaticMeshActor(actorJson);
+ }
+ }
+
+ void LoadTour(Course* course, nlohmann::json& data) {
+ if (!data.contains("Tour") || !data["Tour"].is_object()) {
+ SPDLOG_INFO(" This track does not contain a camera tour");
+ return;
+ }
+
+ nlohmann::json& tours = data["Tour"];
+
+ // Enable flag
+ if (tours.contains("Enabled")) {
+ course->bTourEnabled = tours["Enabled"].get<bool>();
+ } else {
+ course->bTourEnabled = false;
+ }
+
+ // Camera shots
+ if (tours.contains("Shots") && tours["Shots"].is_array()) {
+ course->TourShots.clear();
+
+ for (const auto& shotJson : tours["Shots"]) {
+ course->TourShots.push_back(FromJsonCameraShot(shotJson));
+ }
+ }
+ }
}