From 3213ede656dd825171762d200fe610adbf2934b7 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Mon, 22 Dec 2025 11:13:33 -0600 Subject: [PATCH] dsq followup work 1 fix animation export filename eroneous append add ::canLoadCachedDSQ(const Torque::Path& path) methods to dae and assimp chains SPECIAL NOTE: as the above leads to dsqs not being previewable in editor, nor being able to understand they shouldn't be filtering out bones, for the block bool readSuccess = false; if (canLoadCached) { readSuccess = shape->read(&cachedStream); } else { readSuccess = shape->importSequences(&cachedStream, cachedPath); } we'll be wanting to inject an armature proxy method to fill out TSShape *shape = new TSShape; untill such time as that's sorted, there's a bool gTryUseDSQs = false; killswitch in for dsqs --- Engine/source/ts/assimp/assimpShapeLoader.cpp | 87 ++++++++++++------- Engine/source/ts/assimp/assimpShapeLoader.h | 1 + .../source/ts/collada/colladaShapeLoader.cpp | 83 ++++++++++++++---- Engine/source/ts/collada/colladaShapeLoader.h | 1 + Engine/source/ts/loader/tsShapeLoader.cpp | 1 + 5 files changed, 127 insertions(+), 46 deletions(-) diff --git a/Engine/source/ts/assimp/assimpShapeLoader.cpp b/Engine/source/ts/assimp/assimpShapeLoader.cpp index 4a1174391..4bcc1df91 100644 --- a/Engine/source/ts/assimp/assimpShapeLoader.cpp +++ b/Engine/source/ts/assimp/assimpShapeLoader.cpp @@ -69,6 +69,7 @@ # define new _new #endif +extern bool gTryUseDSQs; MODULE_BEGIN( AssimpShapeLoader ) MODULE_INIT_AFTER( ShapeLoader ) @@ -664,13 +665,12 @@ bool AssimpShapeLoader::fillGuiTreeView(const char* sourceShapePath, GuiTreeView return true; } -/// Check if an up-to-date cached DTS is available for this DAE file +/// Check if an up-to-date cached DTS is available for this file bool AssimpShapeLoader::canLoadCachedDTS(const Torque::Path& path) { // Generate the cached filename Torque::Path cachedPath(path); - if (String::compare(path.getExtension(), "dsq") != 0) - cachedPath.setExtension("cached.dts"); + cachedPath.setExtension("cached.dts"); // Check if a cached DTS newer than this file is available FileTime cachedModifyTime; @@ -689,6 +689,30 @@ bool AssimpShapeLoader::canLoadCachedDTS(const Torque::Path& path) return false; } +/// Check if an up-to-date cached DSQ is available for this file +bool AssimpShapeLoader::canLoadCachedDSQ(const Torque::Path& path) +{ + // Generate the cached filename + Torque::Path cachedPath(path); + cachedPath.setExtension("dsq"); + + // Check if a cached DTS newer than this file is available + FileTime cachedModifyTime; + if (Platform::getFileTimes(cachedPath.getFullPath(), NULL, &cachedModifyTime)) + { + bool forceLoad = Con::getBoolVariable("$assimp::forceLoad", false); + + FileTime daeModifyTime; + if (!Platform::getFileTimes(path.getFullPath(), NULL, &daeModifyTime) || + (!forceLoad && (Platform::compareFileTimes(cachedModifyTime, daeModifyTime) >= 0))) + { + // Original file not found, or cached DTS is newer + return true; + } + } + return false; +} + void AssimpShapeLoader::assimpLogCallback(const char* message, char* user) { Con::printf("[Assimp log message] %s", StringUnit::getUnit(message, 0, "\n")); @@ -973,30 +997,37 @@ TSShape* assimpLoadShape(const Torque::Path &path) // TODO: add .cached.dts generation. // Generate the cached filename Torque::Path cachedPath(path); - if ( String::compare(path.getExtension(),"dsq") != 0) - cachedPath.setExtension("cached.dts"); + bool canLoadCached = false; + bool canLoadDSQ = false; // Check if an up-to-date cached DTS version of this file exists, and // if so, use that instead. if (AssimpShapeLoader::canLoadCachedDTS(path)) + { + cachedPath.setExtension("cached.dts"); + canLoadCached = true; + } + else if (gTryUseDSQs && AssimpShapeLoader::canLoadCachedDSQ(path)) + { + cachedPath.setExtension("dsq"); + canLoadDSQ = true; + } + if (canLoadCached || canLoadDSQ) { FileStream cachedStream; cachedStream.open(cachedPath.getFullPath(), Torque::FS::File::Read); if (cachedStream.getStatus() == Stream::Ok) { TSShape *shape = new TSShape; - if (String::compare(path.getExtension(), "dsq") == 0) + bool readSuccess = false; + if (canLoadCached) { - if (!shape->importSequences(&cachedStream, cachedPath.getFullPath())) - { - Con::errorf("assimpLoadShape: Load sequence file '%s' failed", cachedPath.getFullPath().c_str()); - delete shape; - shape = NULL; - } - cachedStream.close(); - return shape; + readSuccess = shape->read(&cachedStream); + } + else + { + readSuccess = shape->importSequences(&cachedStream, cachedPath); } - bool readSuccess = shape->read(&cachedStream); cachedStream.close(); if (readSuccess) @@ -1007,10 +1038,13 @@ TSShape* assimpLoadShape(const Torque::Path &path) return shape; } else + { + #ifdef TORQUE_DEBUG + Con::errorf("assimpLoadShape: Load sequence file '%s' failed", cachedPath.getFullPath().c_str()); + #endif delete shape; + } } - - Con::warnf("Failed to load cached shape from %s", cachedPath.getFullPath().c_str()); } if (!Torque::FS::IsFile(path)) @@ -1041,27 +1075,22 @@ TSShape* assimpLoadShape(const Torque::Path &path) realMesh = true; } - if (!realMesh) + if (!realMesh && gTryUseDSQs) { Torque::Path dsqPath(cachedPath); dsqPath.setExtension("dsq"); FileStream animOutStream; - for (S32 i = 0; i < tss->sequences.size(); i++) + dsqPath.setFileName(cachedPath.getFileName()); + if (animOutStream.open(dsqPath.getFullPath(), Torque::FS::File::Write)) { - const String& seqName = tss->getName(tss->sequences[i].nameIndex); - Con::printf("Writing DSQ Animation File for sequence '%s'", seqName.c_str()); - - dsqPath.setFileName(cachedPath.getFileName() + "_" + seqName); - if (animOutStream.open(dsqPath.getFullPath(), Torque::FS::File::Write)) - { - tss->exportSequence(&animOutStream, tss->sequences[i], false); - animOutStream.close(); - } - + Con::printf("Writing DSQ Animation File for '%s'", dsqPath.getFileName().c_str()); + tss->exportSequences(&animOutStream); } } else { + // Cache the model to a DTS file for faster loading next time. + cachedPath.setExtension("cached.dts"); // Cache the model to a DTS file for faster loading next time. FileStream dtsStream; if (dtsStream.open(cachedPath.getFullPath(), Torque::FS::File::Write)) diff --git a/Engine/source/ts/assimp/assimpShapeLoader.h b/Engine/source/ts/assimp/assimpShapeLoader.h index 086e4969f..ac81c5d85 100644 --- a/Engine/source/ts/assimp/assimpShapeLoader.h +++ b/Engine/source/ts/assimp/assimpShapeLoader.h @@ -79,6 +79,7 @@ public: bool fillGuiTreeView(const char* shapePath, GuiTreeViewCtrl* tree); static bool canLoadCachedDTS(const Torque::Path& path); + static bool canLoadCachedDSQ(const Torque::Path& path); static void assimpLogCallback(const char* message, char* user); }; diff --git a/Engine/source/ts/collada/colladaShapeLoader.cpp b/Engine/source/ts/collada/colladaShapeLoader.cpp index 4b8dcb035..66a859934 100644 --- a/Engine/source/ts/collada/colladaShapeLoader.cpp +++ b/Engine/source/ts/collada/colladaShapeLoader.cpp @@ -50,6 +50,7 @@ #include "core/util/zip/zipVolume.h" #include "gfx/bitmap/gBitmap.h" +extern bool gTryUseDSQs; MODULE_BEGIN( ColladaShapeLoader ) MODULE_INIT_AFTER( ShapeLoader ) MODULE_INIT @@ -548,7 +549,39 @@ bool ColladaShapeLoader::canLoadCachedDTS(const Torque::Path& path) return false; } +bool ColladaShapeLoader::canLoadCachedDSQ(const Torque::Path& path) +{ + // Generate the cached filename + Torque::Path cachedPath(path); + cachedPath.setExtension("dsq"); + // Check if a cached DSQ newer than this file is available + FileTime cachedModifyTime; + if (Platform::getFileTimes(cachedPath.getFullPath(), NULL, &cachedModifyTime)) + { + bool forceLoadDAE = Con::getBoolVariable("$collada::forceLoadDAE", false); + + FileTime daeModifyTime; + if (!Platform::getFileTimes(path.getFullPath(), NULL, &daeModifyTime) || + (!forceLoadDAE && (Platform::compareFileTimes(cachedModifyTime, daeModifyTime) >= 0))) + { + // DAE not found, or cached DTS is newer + return true; + } + } + + //assume the dts is good since it was zipped on purpose + Torque::FS::FileSystemRef ref = Torque::FS::GetFileSystem(cachedPath); + if (ref && !String::compare("Zip", ref->getTypeStr().c_str())) + { + bool forceLoadDAE = Con::getBoolVariable("$collada::forceLoadDAE", false); + + if (!forceLoadDAE && Torque::FS::IsFile(cachedPath)) + return true; + } + + return false; +} bool ColladaShapeLoader::checkAndMountSketchup(const Torque::Path& path, String& mountPoint, Torque::Path& daePath) { bool isSketchup = path.getExtension().equal("kmz", String::NoCase); @@ -655,18 +688,36 @@ TSShape* loadColladaShape(const Torque::Path &path) #ifndef DAE2DTS_TOOL // Generate the cached filename Torque::Path cachedPath(path); - cachedPath.setExtension("cached.dts"); - + bool canLoadCached = false; + bool canLoadDSQ = false; // Check if an up-to-date cached DTS version of this file exists, and // if so, use that instead. if (ColladaShapeLoader::canLoadCachedDTS(path)) + { + cachedPath.setExtension("cached.dts"); + canLoadCached = true; + } + else if (gTryUseDSQs && ColladaShapeLoader::canLoadCachedDSQ(path)) + { + cachedPath.setExtension("dsq"); + canLoadDSQ = true; + } + if (canLoadCached || canLoadDSQ) { FileStream cachedStream; cachedStream.open(cachedPath.getFullPath(), Torque::FS::File::Read); if (cachedStream.getStatus() == Stream::Ok) { TSShape *shape = new TSShape; - bool readSuccess = shape->read(&cachedStream); + bool readSuccess = false; + if (canLoadCached) + { + readSuccess = shape->read(&cachedStream); + } + else + { + readSuccess = shape->importSequences(&cachedStream, cachedPath); + } cachedStream.close(); if (readSuccess) @@ -677,10 +728,13 @@ TSShape* loadColladaShape(const Torque::Path &path) return shape; } else + { + #ifdef TORQUE_DEBUG + Con::errorf("loadColladaShape: Load sequence file '%s' failed", cachedPath.getFullPath().c_str()); + #endif delete shape; + } } - - Con::warnf("Failed to load cached COLLADA shape from %s", cachedPath.getFullPath().c_str()); } #endif // DAE2DTS_TOOL @@ -732,28 +786,23 @@ TSShape* loadColladaShape(const Torque::Path &path) realMesh = true; } - if (!realMesh) + if (!realMesh && gTryUseDSQs) { Torque::Path dsqPath(cachedPath); dsqPath.setExtension("dsq"); FileStream animOutStream; - for (S32 i = 0; i < tss->sequences.size(); i++) + dsqPath.setFileName(cachedPath.getFileName()); + if (animOutStream.open(dsqPath.getFullPath(), Torque::FS::File::Write)) { - const String& seqName = tss->getName(tss->sequences[i].nameIndex); - Con::printf("Writing DSQ Animation File for sequence '%s'", seqName.c_str()); - - dsqPath.setFileName(cachedPath.getFileName() + "_" + seqName); - if (animOutStream.open(dsqPath.getFullPath(), Torque::FS::File::Write)) - { - tss->exportSequence(&animOutStream, tss->sequences[i], false); - animOutStream.close(); - } - + Con::printf("Writing DSQ Animation File for '%s'", dsqPath.getFileName().c_str()); + tss->exportSequences(&animOutStream); + animOutStream.close(); } } else { // Cache the Collada model to a DTS file for faster loading next time. + cachedPath.setExtension("cached.dts"); FileStream dtsStream; if (dtsStream.open(cachedPath.getFullPath(), Torque::FS::File::Write)) { diff --git a/Engine/source/ts/collada/colladaShapeLoader.h b/Engine/source/ts/collada/colladaShapeLoader.h index b9ed393b1..54cb2e70f 100644 --- a/Engine/source/ts/collada/colladaShapeLoader.h +++ b/Engine/source/ts/collada/colladaShapeLoader.h @@ -53,6 +53,7 @@ public: void computeBounds(Box3F& bounds) override; static bool canLoadCachedDTS(const Torque::Path& path); + static bool canLoadCachedDSQ(const Torque::Path& path); static bool checkAndMountSketchup(const Torque::Path& path, String& mountPoint, Torque::Path& daePath); static domCOLLADA* getDomCOLLADA(const Torque::Path& path); static domCOLLADA* readColladaFile(const String& path); diff --git a/Engine/source/ts/loader/tsShapeLoader.cpp b/Engine/source/ts/loader/tsShapeLoader.cpp index f26af7608..7baceec71 100644 --- a/Engine/source/ts/loader/tsShapeLoader.cpp +++ b/Engine/source/ts/loader/tsShapeLoader.cpp @@ -40,6 +40,7 @@ MODULE_BEGIN( ShapeLoader ) } MODULE_END; +bool gTryUseDSQs = false; const F32 TSShapeLoader::DefaultTime = -1.0f; const F64 TSShapeLoader::MinFrameRate = 15.0f; const F64 TSShapeLoader::MaxFrameRate = 60.0f;