-
Notifications
You must be signed in to change notification settings - Fork 1
feat(ps1): TMD mesh + TIM texture import #394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
35c2eb8
bf5fd1f
5354471
b3366ce
be6cea4
4be2d52
58ad654
e40bfa9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -52,6 +52,7 @@ THE SOFTWARE. | |||||||||||||||||||||||||||||||
| #include "Assimp/BoneProcessor.h" | ||||||||||||||||||||||||||||||||
| #include "Assimp/AnimationProcessor.h" | ||||||||||||||||||||||||||||||||
| #include "CLIPipeline.h" | ||||||||||||||||||||||||||||||||
| #include "PS1/PS1TMD.h" | ||||||||||||||||||||||||||||||||
| #include "EditableMesh.h" | ||||||||||||||||||||||||||||||||
| #include "EditModeController.h" | ||||||||||||||||||||||||||||||||
| #include <OgreMaterialManager.h> | ||||||||||||||||||||||||||||||||
|
|
@@ -79,7 +80,8 @@ const QMap<QString, QString> MeshImporterExporter::exportFormats = { | |||||||||||||||||||||||||||||||
| {"glTF 2.0 (*.gltf)", ".gltf"}, | ||||||||||||||||||||||||||||||||
| {"glTF 2.0 Binary (*.glb)", ".glb"}, | ||||||||||||||||||||||||||||||||
| {"Assimp Binary (*.assbin)", ".assbin"}, | ||||||||||||||||||||||||||||||||
| {"FBX Binary (*.fbx)", ".fbx"} | ||||||||||||||||||||||||||||||||
| {"FBX Binary (*.fbx)", ".fbx"}, | ||||||||||||||||||||||||||||||||
| {"PlayStation TMD (*.tmd)", ".tmd"} | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| void MeshImporterExporter::configureCamera(const Ogre::Entity *en) | ||||||||||||||||||||||||||||||||
|
|
@@ -1203,6 +1205,27 @@ void MeshImporterExporter::importer(const QStringList &_uriList, unsigned int ad | |||||||||||||||||||||||||||||||
| AnimationMerger::registerSkeletonUpAxis(en->getMesh()->getSkeleton()->getName(), 1); | ||||||||||||||||||||||||||||||||
| applyNormalMapsToEntity(en); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| else if (!file.suffix().compare(QStringLiteral("tmd"), Qt::CaseInsensitive)) | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| const std::string meshName = (file.baseName() + QStringLiteral("_tmd")).toStdString(); | ||||||||||||||||||||||||||||||||
| Ogre::MeshPtr mesh = PS1TMD::importTmd(file.filePath(), meshName); | ||||||||||||||||||||||||||||||||
| if (!mesh) { | ||||||||||||||||||||||||||||||||
| QMessageBox::warning( | ||||||||||||||||||||||||||||||||
| nullptr, | ||||||||||||||||||||||||||||||||
| QStringLiteral("PlayStation TMD"), | ||||||||||||||||||||||||||||||||
| QStringLiteral("Could not import %1 — invalid file or unsupported primitive types.") | ||||||||||||||||||||||||||||||||
| .arg(file.fileName())); | ||||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
Comment on lines
+1212
to
+1219
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Confirm whether CLIPipeline calls MeshImporterExporter::importer (the function that now shows the QMessageBox)
rg -nP -C3 'MeshImporterExporter::importer\b|MeshImporterExporter::sceneImporter\b' --type=cpp
# And what kind of QApplication the CLI entrypoint creates
rg -nP -C3 'QCoreApplication|QGuiApplication|QApplication' src/CLIPipeline.cpp src/main.cppRepository: fernandotonon/QtMeshEditor Length of output: 27458 🏁 Script executed: # Check the exact context around lines 1212-1219 in MeshImporterExporter.cpp
sed -n '1205,1230p' src/MeshImporterExporter.cppRepository: fernandotonon/QtMeshEditor Length of output: 1322 🏁 Script executed: # Also check the other failure paths mentioned in the review (lines 1187, 1200, 1286)
echo "=== .mesh failure path around line 1187 ===" && sed -n '1180,1195p' src/MeshImporterExporter.cpp
echo "=== .xml failure path around line 1200 ===" && sed -n '1193,1210p' src/MeshImporterExporter.cpp
echo "=== Assimp failure path around line 1286 ===" && sed -n '1280,1295p' src/MeshImporterExporter.cppRepository: fernandotonon/QtMeshEditor Length of output: 3303 🏁 Script executed: # Check if there are any TMD import tests that might show how the CLI/headless code path works
rg -n 'tmd|TMD' src/MeshImporterExporter_test.cpp | head -20Repository: fernandotonon/QtMeshEditor Length of output: 568 🏁 Script executed: # Verify what happens when QMessageBox is used in a CLI context without user interaction
# Check if there are any guards or conditions around QMessageBox usage elsewhere
rg -n 'QMessageBox' src/MeshImporterExporter.cpp src/CLIPipeline.cpp src/mainwindow.cppRepository: fernandotonon/QtMeshEditor Length of output: 2193 🏁 Script executed: # Check the context around line 1356 - the export QMessageBox
sed -n '1350,1365p' src/MeshImporterExporter.cppRepository: fernandotonon/QtMeshEditor Length of output: 729 🏁 Script executed: # Check if CLIPipeline's QApplication is created before or after MeshImporterExporter::importer calls
grep -n 'new QApplication\|QApplication a\|MeshImporterExporter::importer' src/CLIPipeline.cpp | head -30Repository: fernandotonon/QtMeshEditor Length of output: 726 🏁 Script executed: # Get the full context for the .xml path failure to understand what return does
sed -n '1200,1210p' src/MeshImporterExporter.cppRepository: fernandotonon/QtMeshEditor Length of output: 683 🏁 Script executed: # Check the function signature to see if return in the middle of the loop exits the whole function
sed -n '1162,1175p' src/MeshImporterExporter.cppRepository: fernandotonon/QtMeshEditor Length of output: 616 🏁 Script executed: # Check if there's a test that exercises the .xml failure path to see expected behavior
rg -n 'mesh.xml|importOgreXmlMesh' src/MeshImporterExporter_test.cpp -A 3 -B 3 | head -40Repository: fernandotonon/QtMeshEditor Length of output: 1530 🏁 Script executed: # Check if the exporter function is meant to be GUI-only or can be called from CLI
rg -n 'MeshImporterExporter::exporter\b' src/*.cppRepository: fernandotonon/QtMeshEditor Length of output: 4249 Remove The other branches in this loop (
Recommend logging the failure and letting the existing presentation layer handle it, matching the pattern used by other format branches. 🛡️ Suggested replacement const std::string meshName = (file.baseName() + QStringLiteral("_tmd")).toStdString();
Ogre::MeshPtr mesh = PS1TMD::importTmd(file.filePath(), meshName);
if (!mesh) {
- QMessageBox::warning(
- nullptr,
- QStringLiteral("PlayStation TMD"),
- QStringLiteral("Could not import %1 — invalid file or unsupported primitive types.")
- .arg(file.fileName()));
+ Ogre::LogManager::getSingleton().logMessage(
+ QStringLiteral("PS1TMD: Could not import %1 — invalid file or unsupported primitive types.")
+ .arg(file.fileName()).toStdString(),
+ Ogre::LML_WARNING);
continue;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| SentryReporter::addBreadcrumb( | ||||||||||||||||||||||||||||||||
| QStringLiteral("file.import"), | ||||||||||||||||||||||||||||||||
| QStringLiteral("Imported PlayStation TMD: %1").arg(file.fileName())); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| sn = Manager::getSingleton()->addSceneNode(file.baseName()); | ||||||||||||||||||||||||||||||||
| en = Manager::getSingleton()->createEntity(sn, mesh); | ||||||||||||||||||||||||||||||||
| applyNormalMapsToEntity(en); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| AssimpToOgreImporter importer; | ||||||||||||||||||||||||||||||||
|
|
@@ -1435,6 +1458,11 @@ int MeshImporterExporter::exporter(const Ogre::SceneNode *_sn, const QString &_u | |||||||||||||||||||||||||||||||
| // .material and extracted image files next to the FBX. | ||||||||||||||||||||||||||||||||
| if (!ok) | ||||||||||||||||||||||||||||||||
| return -1; | ||||||||||||||||||||||||||||||||
| } else if (_format == QStringLiteral("PlayStation TMD (*.tmd)")) { | ||||||||||||||||||||||||||||||||
| if (!PS1TMD::exportEntity(e, _uri)) | ||||||||||||||||||||||||||||||||
| return -1; | ||||||||||||||||||||||||||||||||
| SentryReporter::addBreadcrumb(QStringLiteral("file.export"), | ||||||||||||||||||||||||||||||||
| QStringLiteral("Exported PlayStation TMD: %1").arg(_uri)); | ||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||
| // Export using Assimp — build aiScene directly from Ogre mesh data | ||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mesh.xmlwill never match with the current classifier.openFile(),fileTypeForPath(), andrefreshFiles()all passQFileInfo::suffix(), somodel.mesh.xmlis still seen asxmland this new allowlist entry stays dead. Switch those call sites tocompleteSuffix()(or normalize multi-part extensions before lookup) so.mesh.xmlcan actually be opened and filtered as a mesh.Suggested fix
Apply the same change in:
AssetBrowserController::openFile()AssetBrowserController::fileTypeForPath()AssetBrowserController::refreshFiles()🤖 Prompt for AI Agents