From 49feb8b9f6bcabecb5be2ad2279ec45b26ce7cca Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 07:04:27 -0700 Subject: [PATCH] fix(objects): scrub NaN/inf floats at save time Same json-serialization-safety fix as for NPC and WOT saves. Object position/rotation NaN would abort the entire objects.json save and lose all placement work in the session. --- tools/editor/object_placer.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/editor/object_placer.cpp b/tools/editor/object_placer.cpp index e2340ee6..b3cbf93d 100644 --- a/tools/editor/object_placer.cpp +++ b/tools/editor/object_placer.cpp @@ -279,14 +279,18 @@ void ObjectPlacer::undoLastPlace() { bool ObjectPlacer::saveToFile(const std::string& path) const { std::filesystem::create_directories(std::filesystem::path(path).parent_path()); + // nlohmann::json throws on NaN/inf serialization. Scrub on the way + // out so a bad in-memory transform can't kill the whole save. + auto san = [](float x) { return std::isfinite(x) ? x : 0.0f; }; + auto sanScale = [](float x) { return (std::isfinite(x) && x > 0.0f) ? x : 1.0f; }; nlohmann::json arr = nlohmann::json::array(); for (const auto& o : objects_) { arr.push_back({ {"type", static_cast(o.type)}, {"path", o.path}, - {"pos", {o.position.x, o.position.y, o.position.z}}, - {"rot", {o.rotation.x, o.rotation.y, o.rotation.z}}, - {"scale", o.scale}, + {"pos", {san(o.position.x), san(o.position.y), san(o.position.z)}}, + {"rot", {san(o.rotation.x), san(o.rotation.y), san(o.rotation.z)}}, + {"scale", sanScale(o.scale)}, {"uniqueId", o.uniqueId} }); }