diff --git a/application/F3DStarter.cxx b/application/F3DStarter.cxx index 6e3a33318b..d77ce352e1 100644 --- a/application/F3DStarter.cxx +++ b/application/F3DStarter.cxx @@ -255,7 +255,7 @@ class F3DStarter::F3DInternals const std::regex numberingRe("\\{(n:?([0-9]*))\\}"); const std::regex dateRe("date:?([A-Za-z%]*)"); - /* Return a non empty file related string depending on the currently loaded files */ + /* Return a file related string depending on the currently loaded files, or the empty string if a single file is loaded */ const auto fileCheck = [&]() { if (this->LoadedFiles.size() == 0) @@ -288,30 +288,32 @@ class F3DStarter::F3DInternals return F3D::AppVersionFull; } // TODO update doc - // TODO test multifile else if (var == "model") { std::string output = fileCheck(); if (output.empty()) { - return this->LoadedFiles[0].stem().string(); + output = this->LoadedFiles[0].stem().string(); } + return output; } else if (var == "model.ext") { std::string output = fileCheck(); if (output.empty()) { - return this->LoadedFiles[0].filename().string(); + output = this->LoadedFiles[0].filename().string(); } + return output; } else if (var == "model_ext") { std::string output = fileCheck(); if (output.empty()) { - return this->LoadedFiles[0].extension().string().substr(1); + output = this->LoadedFiles[0].extension().string().substr(1); } + return output; } else if (std::regex_match(var, dateRe)) { @@ -454,7 +456,6 @@ class F3DStarter::F3DInternals std::map> loggingMap; // For each input file, order matter - // TODO add a multifile test for (const auto& tmpPath : paths) { std::string inputFile = tmpPath.string(); @@ -644,6 +645,7 @@ class F3DStarter::F3DInternals } } + // Recover a vector of unique parent paths from a vector of paths static std::vector ParentPaths(const std::vector& paths) { std::vector parents; @@ -787,7 +789,6 @@ int F3DStarter::Start(int argc, char** argv) } if (keySym == "Down") { - // TODO add a multifile test if (this->Internals->LoadedFiles.size() > 0) { for (const auto& parentPath : F3DInternals::ParentPaths(this->Internals->LoadedFiles)) @@ -839,7 +840,6 @@ int F3DStarter::Start(int argc, char** argv) } if (index > -1) { - // TODO add a multifile test this->LoadFile(index); } this->RequestRender(); @@ -1028,8 +1028,8 @@ void F3DStarter::LoadFile(int index, bool relativeIndex, bool forceClear) bool clear = forceClear ? true : this->Internals->CurrentFilesGroupIndex != groupIndex; this->Internals->CurrentFilesGroupIndex = groupIndex; - // Create a nice looking filename info eg: "cow.vtp (1/5)" - // Each group contains at least one path + // Create a nice looking group index eg: "(1/5)" + // XXX: Each group contains at least one path std::string groupIdx = "(" + std::to_string(groupIndex + 1) + "/" + std::to_string(this->Internals->FilesGroups.size()) + ")"; this->LoadFile(this->Internals->FilesGroups[groupIndex], clear, groupIdx); @@ -1125,7 +1125,6 @@ void F3DStarter::LoadFile( static_cast(this->Internals->AppOptions.MaxSize * BYTES_IN_MIB)) { f3d::log::info(tmpPath.string(), " skipped, file is bigger than max size"); - // TODO add a multifile test } else { @@ -1142,16 +1141,18 @@ void F3DStarter::LoadFile( if (!localPaths.empty()) { - std::copy( - localPaths.begin(), localPaths.end(), std::back_inserter(this->Internals->LoadedFiles)); // Add files to the scene loader.add(localPaths); + + // Update loaded files + std::copy( + localPaths.begin(), localPaths.end(), std::back_inserter(this->Internals->LoadedFiles)); } } } catch (const f3d::loader::load_failure_exception& ex) { - f3d::log::error("Could not load files: ", ex.what()); + f3d::log::error("Some of these files could not be loaded: ", ex.what()); for (const fs::path& tmpPath : localPaths) { f3d::log::error(" ", tmpPath.string()); @@ -1167,10 +1168,11 @@ void F3DStarter::LoadFile( std::string filenameInfo; if (this->Internals->LoadedFiles.size() > 0) { + // Loaded files, create a filename info like this: + // "(1/5) cow.vtp + N [+UNSUPPORTED]" filenameInfo = groupIdx + " " + this->Internals->LoadedFiles.at(0).filename().string(); if (this->Internals->LoadedFiles.size() > 1) { - // TODO add a multifile test filenameInfo += " +" + std::to_string(this->Internals->LoadedFiles.size() - 1); } if (unsupported) @@ -1178,6 +1180,7 @@ void F3DStarter::LoadFile( filenameInfo += " [+UNSUPPORTED]"; } + // Update dmon wtch logic if (this->Internals->AppOptions.Watch) { // Always unwatch and watch current folder, even on reload @@ -1199,6 +1202,9 @@ void F3DStarter::LoadFile( } else { + // No files loaded, create a simple filename info like this: + // (1/5) cow.vtt [UNSUPPORTED] + // (1/1) cow.vtt [+UNSUPPORTED] if (unsupported) { filenameInfo = groupIdx + " " + paths.at(0).filename().string() + " ["; @@ -1298,6 +1304,7 @@ void F3DStarter::SaveScreenshot(const std::string& filenameTemplate, bool minima //---------------------------------------------------------------------------- int F3DStarter::AddFile(const fs::path& path, bool quiet) { + // Check file exists auto tmpPath = fs::absolute(path); if (!fs::exists(tmpPath)) { @@ -1307,6 +1314,7 @@ int F3DStarter::AddFile(const fs::path& path, bool quiet) } return -1; } + // If file is a folder, add files recursively else if (fs::is_directory(tmpPath)) { std::set sortedPaths; @@ -1323,6 +1331,7 @@ int F3DStarter::AddFile(const fs::path& path, bool quiet) } else { + // Check if file has already been added bool found = false; std::vector>::iterator it; for (it = this->Internals->FilesGroups.begin(); it != this->Internals->FilesGroups.end(); it++) @@ -1337,16 +1346,18 @@ int F3DStarter::AddFile(const fs::path& path, bool quiet) if (!found) { + // Add to the right file group if (this->Internals->AppOptions.MultiFileMode == "all") { if (this->Internals->FilesGroups.size() == 0) { this->Internals->FilesGroups.resize(1); } + assert(this->Internals->FilesGroups.size() == 1); this->Internals->FilesGroups[0].emplace_back(tmpPath); } - else // if (this->Internals->AppOptions.MultiFileMode == "single") XXX more grouping mode may - // be added in the future + else // if (this->Internals->AppOptions.MultiFileMode == "single") + // XXX more grouping mode may be added in the future { this->Internals->FilesGroups.emplace_back(std::vector{ tmpPath }); } @@ -1354,6 +1365,7 @@ int F3DStarter::AddFile(const fs::path& path, bool quiet) } else { + // If already added, just return the index of the group containing the file if (!quiet) { f3d::log::warn("File ", tmpPath.string(), " has already been added"); diff --git a/application/testing/CMakeLists.txt b/application/testing/CMakeLists.txt index 4364e2c898..3480fa1cea 100644 --- a/application/testing/CMakeLists.txt +++ b/application/testing/CMakeLists.txt @@ -191,9 +191,11 @@ f3d_test(NAME TestUTF8 DATA "(ノಠ益ಠ )ノ.vtp") f3d_test(NAME TestFilenameCommasSpaces DATA "tetrahedron, with commas & spaces.stl") f3d_test(NAME TestFont DATA suzanne.ply ARGS -n --font-file=${F3D_SOURCE_DIR}/testing/data/Crosterian.ttf) f3d_test(NAME TestAnimationIndex DATA InterpolationTest.glb ARGS --animation-index=7 --animation-time=0.5 --animation-progress) +f3d_test(NAME TestMultiInputAnimationIndex ARGS ${F3D_SOURCE_DIR}/testing/data/InterpolationTest.glb ${F3D_SOURCE_DIR}/testing/data/BoxAnimated.gltf --animation-index=9 --animation-time=0.85 --animation-progress --multi-file-mode=all) f3d_test(NAME TestAnimationAutoplay DATA InterpolationTest.glb ARGS --animation-autoplay) f3d_test(NAME TestMaxSizeBelow DATA suzanne.stl ARGS --max-size=1) f3d_test(NAME TestMaxSizeAbove DATA WaterBottle.glb ARGS --max-size=0.2 REGEXP "file is bigger than max size" NO_BASELINE) +f3d_test(NAME TestMaxSizeAboveMultiFile ARGS ${F3D_SOURCE_DIR}/testing/data/suzanne.obj ${F3D_SOURCE_DIR}/testing/data/WaterBottle.glb --multi-file-mode=all --max-size=0.6 --opacity=0.5) f3d_test(NAME TestAlternativeOptionSyntax DATA WaterBottle.glb ARGS --max-size 0.2 REGEXP "file is bigger than max size" NO_BASELINE) f3d_test(NAME TestNonExistentFile DATA nonExistentFile.vtp ARGS --filename WILL_FAIL) f3d_test(NAME TestUnsupportedFile DATA unsupportedFile.dummy ARGS --filename WILL_FAIL) @@ -203,6 +205,7 @@ f3d_test(NAME TestNoRenderWithOptions DATA dragon.vtu ARGS --hdri-ambient --axis f3d_test(NAME TestNoFile NO_DATA_FORCE_RENDER) f3d_test(NAME TestMultiFile DATA mb/recursive ARGS --multi-file-mode=all) f3d_test(NAME TestMultiFileColoring DATA mb/recursive ARGS --multi-file-mode=all -s --coloring-array=Polynomial -b) +f3d_test(NAME TestMultiInputColoringTexture ARGS ${F3D_SOURCE_DIR}/testing/data/mb/recursive/mb_1_0.vtp ${F3D_SOURCE_DIR}/testing/data/mb/recursive/mb_2_0.vtp ${F3D_SOURCE_DIR}/testing/data/world.obj --multi-file-mode=all -sb --coloring-array=Normals --comp=1) f3d_test(NAME TestMultiInputPositionals ARGS ${F3D_SOURCE_DIR}/testing/data/mb/recursive/mb_0_0.vtu ${F3D_SOURCE_DIR}/testing/data/mb/recursive/mb_1_0.vtp --multi-file-mode=all -s --coloring-array=Polynomial -b) f3d_test(NAME TestMultiInputArg ARGS --input ${F3D_SOURCE_DIR}/testing/data/mb/recursive/mb_0_0.vtu ${F3D_SOURCE_DIR}/testing/data/mb/recursive/mb_1_0.vtp --multi-file-mode=all -s --coloring-array=Polynomial -b) f3d_test(NAME TestMultiInputMultiArgs ARGS --input ${F3D_SOURCE_DIR}/testing/data/mb/recursive/mb_0_0.vtu --input ${F3D_SOURCE_DIR}/testing/data/mb/recursive/mb_1_0.vtp --multi-file-mode=all -s --coloring-array=Polynomial -b) @@ -312,6 +315,8 @@ if(NOT F3D_MACOS_BUNDLE) f3d_test(NAME TestConfigFileBuild DATA dragon.vtu CONFIG complex_build.json) f3d_test(NAME TestConfigStemBuild DATA dragon.vtu CONFIG complex_build) f3d_test(NAME TestConfigFileUpperCase DATA suzanne_upper.STL CONFIG complex_build) + f3d_test(NAME TestConfigFileMultiInputSTL ARGS ARGS ${F3D_SOURCE_DIR}/testing/data/mb/recursive/mb_1_0.vtp ${F3D_SOURCE_DIR}/testing/data/suzanne.stl --multi-file-mode=all CONFIG complex_build) + f3d_test(NAME TestConfigFileMultiInputVTP ARGS ARGS ${F3D_SOURCE_DIR}/testing/data/mb/recursive/mb_1_0.vtp ${F3D_SOURCE_DIR}/testing/data/suzanne.stl ${F3D_SOURCE_DIR}/testing/data/mb/recursive/mb_2_0.vtp --multi-file-mode=all CONFIG complex_build) file(COPY "${F3D_SOURCE_DIR}/resources/configs/config.d/" "${F3D_SOURCE_DIR}/plugins/native/configs/config.d/" DESTINATION "${CMAKE_BINARY_DIR}/share/f3d/configs/config_build.d") f3d_test(NAME TestDefaultConfigFileVTU DATA dragon.vtu CONFIG config_build LONG_TIMEOUT TONE_MAPPING) @@ -336,6 +341,7 @@ endif() f3d_test(NAME TestGLTFImporterUnlit DATA UnlitTest.glb) f3d_test(NAME TestMaterial DATA suzanne.ply ARGS --color=0.72,0.45,0.2 --metallic=0.7 --roughness=0.2) +f3d_test(NAME TestMaterialFullScene DATA WaterBottle.glb ARGS --color=0.9,0.1,0.1 --metallic=0.7 --roughness=0.2) f3d_test(NAME TestMetaData DATA pdiag.vtu ARGS -m) f3d_test(NAME TestEdges DATA suzanne.ply ARGS -e) f3d_test(NAME TestLineWidth DATA cow.vtk ARGS -e --line-width=5) @@ -385,6 +391,7 @@ endif() f3d_test(NAME TestCameraPersp DATA Cameras.gltf ARGS --camera-index=0) f3d_test(NAME TestCameraOrtho DATA Cameras.gltf ARGS --camera-index=1) f3d_test(NAME TestCameraIndexConfiguration DATA Cameras.gltf ARGS --camera-index=0 --camera-azimuth-angle=15 --camera-position=0.7,0.5,3) +f3d_test(NAME TestMultiInputCameraIndex ARGS ${F3D_SOURCE_DIR}/testing/data/Cameras.gltf ${F3D_SOURCE_DIR}/testing/data/CameraAnimated.glb --multi-file-mode=all --camera-index=2 --opacity=0.5) # Test Verbose camera f3d_test(NAME TestVerboseCamera DATA Cameras.gltf ARGS --camera-index=1 --verbose NO_RENDER REGEXP "0:.*1:") @@ -964,6 +971,13 @@ set_tests_properties(f3d::TestInvalidCLIArgs PROPERTIES PASS_REGULAR_EXPRESSION # Test that f3d resolution can be controlled from config file add_test(NAME f3d::TestConfigResolution COMMAND $ --config=${F3D_SOURCE_DIR}/testing/configs/resolution.json ${F3D_SOURCE_DIR}/testing/data/suzanne.stl --output=${CMAKE_BINARY_DIR}/Testing/Temporary/TestConfigResolution.png --ref=${F3D_SOURCE_DIR}/testing/baselines/TestConfigResolution.png) +# Test filename template with multiple files +add_test(NAME f3d::TestMultiFileFileNameTemplate COMMAND $ ${F3D_SOURCE_DIR}/testing/data/suzanne.stl ${F3D_SOURCE_DIR}/testing/data/dragon.vtu --output=${CMAKE_BINARY_DIR}/Testing/Temporary/{model.ext}.png PASS_REGULAR_EXPRESSION "multi_file.png") + +# Test filename template with no files +add_test(NAME f3d::TestNoFileFileNameTemplate COMMAND $ --output=${CMAKE_BINARY_DIR}/Testing/Temporary/{model.ext}.png PASS_REGULAR_EXPRESSION "no_file.png") +set_tests_properties(f3d::TestNoFileFileNameTemplate PROPERTIES ENVIRONMENT "CTEST_F3D_NO_DATA_FORCE_RENDER=1") + # Test failure without a reference, please do not create a TestNoRef.png file f3d_test(NAME TestNoRef DATA cow.vtp WILL_FAIL) diff --git a/library/private/window_impl.h b/library/private/window_impl.h index 12915945c3..0f62a41187 100644 --- a/library/private/window_impl.h +++ b/library/private/window_impl.h @@ -70,7 +70,7 @@ class window_impl : public window /** * Implementation only API. - * Set the importer on an already created vtkF3DRendererWithColoring + * Set the importer on the internal renderer */ void SetImporter(vtkF3DMetaImporter* importer); diff --git a/testing/baselines/TestConfigFileMultiInputSTL.png b/testing/baselines/TestConfigFileMultiInputSTL.png new file mode 100644 index 0000000000..4c608f224b --- /dev/null +++ b/testing/baselines/TestConfigFileMultiInputSTL.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c05538a8c7247c4172721e1f18580d5edea5d95826b4cec2abc1876a2d6c6d7 +size 34188 diff --git a/testing/baselines/TestConfigFileMultiInputVTP.png b/testing/baselines/TestConfigFileMultiInputVTP.png new file mode 100644 index 0000000000..a3c83a7e93 --- /dev/null +++ b/testing/baselines/TestConfigFileMultiInputVTP.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a809177e1d585e86191d8a0755630c5513a854d0916336baf86c1e87878ae600 +size 47999 diff --git a/testing/baselines/TestMaterialFullScene.png b/testing/baselines/TestMaterialFullScene.png new file mode 100644 index 0000000000..a4df8df4e1 --- /dev/null +++ b/testing/baselines/TestMaterialFullScene.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00b992a31481c9838b545b3c469631c21c366d9b0826fde6171b56639859f032 +size 15591 diff --git a/testing/baselines/TestMaxSizeAboveMultiFile.png b/testing/baselines/TestMaxSizeAboveMultiFile.png new file mode 100644 index 0000000000..9f5dec9678 --- /dev/null +++ b/testing/baselines/TestMaxSizeAboveMultiFile.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:103fd900202833d926a3662214a6abe92cb3d29af9f2f52d0b8bdb0c529b07ba +size 21417 diff --git a/testing/baselines/TestMultiInputAnimationIndex.png b/testing/baselines/TestMultiInputAnimationIndex.png new file mode 100644 index 0000000000..f8822c3462 --- /dev/null +++ b/testing/baselines/TestMultiInputAnimationIndex.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e788c601396836ab75734bb69ac22ba9605374c12fb635885768fc4e5ef51ebb +size 4947 diff --git a/testing/baselines/TestMultiInputCameraIndex.png b/testing/baselines/TestMultiInputCameraIndex.png new file mode 100644 index 0000000000..87f2e42a61 --- /dev/null +++ b/testing/baselines/TestMultiInputCameraIndex.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab6326ba1da12c057c1d52e8b3e3bc63ee86c55bb4c81e52126da0224cd42974 +size 3454 diff --git a/testing/baselines/TestMultiInputColoringTexture.png b/testing/baselines/TestMultiInputColoringTexture.png new file mode 100644 index 0000000000..7a427c02a5 --- /dev/null +++ b/testing/baselines/TestMultiInputColoringTexture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae5299f32b0fb18e6d075dd1a0d2da4d0f56e706d68e99c016ff67280fa9cc27 +size 32236 diff --git a/testing/configs/complex.json b/testing/configs/complex.json index 7bded1e66c..177d1d77ea 100644 --- a/testing/configs/complex.json +++ b/testing/configs/complex.json @@ -7,6 +7,7 @@ }, ".*(vt.)": { + "up": "+Y", "bar": true, "render.effect.ambient_occlusion": true, "filename": true diff --git a/testing/data/mb/recursive/f3d.glb b/testing/data/mb/recursive/f3d.glb new file mode 100644 index 0000000000..bdce4cdb98 --- /dev/null +++ b/testing/data/mb/recursive/f3d.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f4b8990cb6a45a366a724de79f6c996cc2e92abe6161bd78735780d4a2db5b8 +size 3652