diff --git a/.gitignore b/.gitignore index bb8f4ac65c..e5ae317f73 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ _version.py # wasm process related node_modules + +# testing related +.cache diff --git a/application/F3DColorMapTools.cxx b/application/F3DColorMapTools.cxx index 57961f65b2..35faccb1c3 100644 --- a/application/F3DColorMapTools.cxx +++ b/application/F3DColorMapTools.cxx @@ -4,6 +4,7 @@ #include "image.h" #include "log.h" +#include "utils.h" #include @@ -11,56 +12,63 @@ namespace fs = std::filesystem; namespace F3DColorMapTools { -std::string Find(const std::string& str) +fs::path Find(const std::string& str) { - if (fs::exists(str)) + try { - fs::path resolved = fs::canonical(str); - if (fs::is_regular_file(resolved)) + fs::path fullPath(f3d::utils::collapsePath(str)); + if (fs::exists(fullPath)) { - // already full path - return resolved.string(); + if (fs::is_regular_file(fullPath)) + { + // already full path + return fullPath; + } } - } - std::vector dirsToCheck{ F3DSystemTools::GetUserConfigFileDirectory() / "colormaps", + std::vector dirsToCheck{ F3DSystemTools::GetUserConfigFileDirectory() / "colormaps", #ifdef __APPLE__ - "/usr/local/etc/f3d/colormaps", + "/usr/local/etc/f3d/colormaps", #endif #ifdef __linux__ - "/etc/f3d/colormaps", "/usr/share/f3d/colormaps", + "/etc/f3d/colormaps", "/usr/share/f3d/colormaps", #endif - F3DSystemTools::GetBinaryResourceDirectory() / "colormaps" }; + F3DSystemTools::GetBinaryResourceDirectory() / "colormaps" }; - for (const fs::path& dir : dirsToCheck) - { - // If the string is a stem, try adding supported extensions - if (fs::path(str).stem() == str) + for (const fs::path& dir : dirsToCheck) { - for (const std::string& ext : f3d::image::getSupportedFormats()) + // If the string is a stem, try adding supported extensions + if (fs::path(str).stem() == str) { - fs::path cmPath = dir / (str + ext); - if (fs::exists(cmPath)) + for (const std::string& ext : f3d::image::getSupportedFormats()) { - return cmPath.string(); + fs::path cmPath = dir / (str + ext); + if (fs::exists(cmPath)) + { + return cmPath; + } } } - } - else - { - // If not, use directly - fs::path cmPath = dir / str; - if (fs::exists(cmPath)) + else { - return cmPath.string(); + // If not, use directly + fs::path cmPath = dir / str; + if (fs::exists(cmPath)) + { + return cmPath; + } } } } + catch (const fs::filesystem_error& ex) + { + f3d::log::error("Unable to look for color map ", str, ": ", ex.what()); + } return {}; } -std::vector Read(const std::string& path) +std::vector Read(const fs::path& path) { try { diff --git a/application/F3DColorMapTools.h b/application/F3DColorMapTools.h index 8641898853..9d972449f4 100644 --- a/application/F3DColorMapTools.h +++ b/application/F3DColorMapTools.h @@ -7,13 +7,14 @@ #ifndef F3DColorMapReader_h #define F3DColorMapReader_h +#include #include #include namespace F3DColorMapTools { -std::string Find(const std::string& str); -std::vector Read(const std::string& path); +std::filesystem::path Find(const std::string& str); +std::vector Read(const std::filesystem::path& path); } #endif diff --git a/application/F3DConfigFileTools.cxx b/application/F3DConfigFileTools.cxx index aace7e8191..5aba8264cd 100644 --- a/application/F3DConfigFileTools.cxx +++ b/application/F3DConfigFileTools.cxx @@ -5,6 +5,7 @@ #include "nlohmann/json.hpp" #include "log.h" +#include "utils.h" #include #include @@ -21,7 +22,7 @@ namespace */ std::vector GetConfigPaths(const std::string& configSearch) { - std::vector paths; + std::vector paths; fs::path configPath; std::vector dirsToCheck = { @@ -111,7 +112,8 @@ F3DConfigFileTools::ReadConfigFiles(const std::string& userConfig) } else { - configPaths.emplace_back(userConfig); + // Collapse full path into an absolute path + configPaths.emplace_back(f3d::utils::collapsePath(userConfig)); } // Recover actual individual config file paths @@ -133,7 +135,7 @@ F3DConfigFileTools::ReadConfigFiles(const std::string& userConfig) if (fs::is_directory(configPath)) { f3d::log::debug("Using config directory ", configPath.string()); - for (auto& entry : std::filesystem::directory_iterator(configPath)) + for (auto& entry : fs::directory_iterator(configPath)) { actualConfigFilePaths.emplace(entry); } diff --git a/application/F3DStarter.cxx b/application/F3DStarter.cxx index a8739c5409..e12e0a307d 100644 --- a/application/F3DStarter.cxx +++ b/application/F3DStarter.cxx @@ -273,7 +273,7 @@ class F3DStarter::F3DInternals * - `{n:2}`, `{n:3}`, ...: zero-padded auto-incremented number to make filename unique * (up to 1000000) */ - fs::path applyFilenameTemplate(const std::string& templateString) + fs::path applyFilenameTemplate(const fs::path& templatePath) { constexpr size_t maxNumberingAttempts = 1000000; const std::regex numberingRe("(n:?(.*))"); @@ -359,7 +359,7 @@ class F3DStarter::F3DInternals throw f3d::utils::string_template::lookup_error(var); }; - f3d::utils::string_template stringTemplate(templateString); + f3d::utils::string_template stringTemplate(templatePath.string()); stringTemplate.substitute(variableLookup); const auto hasNumbering = [&]() @@ -598,7 +598,7 @@ class F3DStarter::F3DInternals const std::string& colorMapFile = this->AppOptions.ColorMapFile; if (!colorMapFile.empty()) { - std::string fullPath = F3DColorMapTools::Find(colorMapFile); + fs::path fullPath = F3DColorMapTools::Find(colorMapFile); if (!fullPath.empty()) { @@ -863,8 +863,6 @@ int F3DStarter::Start(int argc, char** argv) f3d::log::debug("========== Configuring engine =========="); double deltaTime = 1.0 / this->Internals->AppOptions.FrameRate; - const std::string& reference = this->Internals->AppOptions.Reference; - const std::string& output = this->Internals->AppOptions.Output; if (this->Internals->AppOptions.NoRender) { @@ -872,8 +870,8 @@ int F3DStarter::Start(int argc, char** argv) } else { - bool offscreen = - !reference.empty() || !output.empty() || this->Internals->AppOptions.BindingsList; + bool offscreen = !this->Internals->AppOptions.Reference.empty() || + !this->Internals->AppOptions.Output.empty() || this->Internals->AppOptions.BindingsList; if (this->Internals->AppOptions.RenderingBackend == "egl") { @@ -913,7 +911,7 @@ int F3DStarter::Start(int argc, char** argv) // Add all input files for (auto& file : inputFiles) { - this->AddFile(fs::path(file)); + this->AddFile(f3d::utils::collapsePath(file)); } // Load a file @@ -944,8 +942,8 @@ int F3DStarter::Start(int argc, char** argv) } // Play recording if any - const std::string& interactionTestPlayFile = - this->Internals->AppOptions.InteractionTestPlayFile; + fs::path interactionTestPlayFile = + f3d::utils::collapsePath(this->Internals->AppOptions.InteractionTestPlayFile); if (!interactionTestPlayFile.empty()) { // For better testing, render once before the interaction @@ -957,8 +955,8 @@ int F3DStarter::Start(int argc, char** argv) } // Start recording if needed - const std::string& interactionTestRecordFile = - this->Internals->AppOptions.InteractionTestRecordFile; + fs::path interactionTestRecordFile = + f3d::utils::collapsePath(this->Internals->AppOptions.InteractionTestRecordFile); if (!interactionTestRecordFile.empty()) { if (!interactor.recordInteraction(interactionTestRecordFile)) @@ -968,7 +966,8 @@ int F3DStarter::Start(int argc, char** argv) } // Process Command Script file - const std::string& commandScriptFile = this->Internals->AppOptions.CommandScriptFile; + fs::path commandScriptFile = + f3d::utils::collapsePath(this->Internals->AppOptions.CommandScriptFile); if (!commandScriptFile.empty()) { std::ifstream scriptFile(commandScriptFile); @@ -993,6 +992,10 @@ int F3DStarter::Start(int argc, char** argv) char* noDataForceRender = std::getenv("CTEST_F3D_NO_DATA_FORCE_RENDER"); + fs::path reference = f3d::utils::collapsePath(this->Internals->AppOptions.Reference); + fs::path output = this->Internals->applyFilenameTemplate( + f3d::utils::collapsePath(this->Internals->AppOptions.Output)); + // Render and compare with file if needed if (!reference.empty()) { @@ -1002,21 +1005,29 @@ int F3DStarter::Start(int argc, char** argv) return EXIT_FAILURE; } - if (!fs::exists(reference)) + try { - if (output.empty()) + if (!fs::exists(reference)) { - f3d::log::error("Reference image ", reference, - " does not exist, use the output option to output current rendering into an image " - "file.\n"); - } - else - { - window.renderToImage(this->Internals->AppOptions.NoBackground).save(output); + if (output.empty()) + { + f3d::log::error("Reference image ", reference, + " does not exist, use the output option to output current rendering into an image " + "file.\n"); + } + else + { + window.renderToImage(this->Internals->AppOptions.NoBackground).save(output); - f3d::log::error("Reference image " + reference + - " does not exist, current rendering has been outputted to " + output + ".\n"); + f3d::log::error("Reference image ", reference, + " does not exist, current rendering has been outputted to ", output, ".\n"); + } + return EXIT_FAILURE; } + } + catch (const fs::filesystem_error& ex) + { + f3d::log::error("Error reading reference image: ", ex.what()); return EXIT_FAILURE; } @@ -1072,9 +1083,8 @@ int F3DStarter::Start(int argc, char** argv) } else { - fs::path path = this->Internals->applyFilenameTemplate(output); - img.save(path.string()); - f3d::log::debug("Output image saved to ", path); + img.save(output); + f3d::log::debug("Output image saved to ", output); } if (this->Internals->FilesGroups.size() > 1) @@ -1397,13 +1407,20 @@ void F3DStarter::SaveScreenshot(const std::string& filenameTemplate, bool minima return fs::current_path(); }; - fs::path pathTemplate = fs::path(filenameTemplate).make_preferred(); - fs::path fullPathTemplate = - pathTemplate.is_absolute() ? pathTemplate : getScreenshotDir() / pathTemplate; - fs::path path = this->Internals->applyFilenameTemplate(fullPathTemplate.string()); + fs::path path; + try + { + path = this->Internals->applyFilenameTemplate( + f3d::utils::collapsePath(filenameTemplate, getScreenshotDir())); - fs::create_directories(fs::path(path).parent_path()); - f3d::log::info("saving screenshot to " + path.string()); + fs::create_directories(path.parent_path()); + f3d::log::info("saving screenshot to " + path.string()); + } + catch (const fs::filesystem_error& ex) + { + f3d::log::error("Error recovering screenshot path: ", ex.what()); + return; + } f3d::options& options = this->Internals->Engine->getOptions(); f3d::options optionsCopy = this->Internals->Engine->getOptions(); @@ -1425,7 +1442,7 @@ void F3DStarter::SaveScreenshot(const std::string& filenameTemplate, bool minima f3d::image img = this->Internals->Engine->getWindow().renderToImage(noBackground); this->Internals->addOutputImageMetadata(img); - img.save(path.string(), f3d::image::SaveFormat::PNG); + img.save(path, f3d::image::SaveFormat::PNG); options.render.light.intensity *= 5; this->Render(); @@ -1437,79 +1454,91 @@ 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)) - { - if (!quiet) - { - f3d::log::error("File ", tmpPath.string(), " does not exist"); - } - return -1; - } - // If file is a folder, add files recursively - else if (fs::is_directory(tmpPath)) + try { - std::set sortedPaths; - for (const auto& entry : fs::directory_iterator(tmpPath)) + // Check file exists + auto tmpPath = fs::absolute(path); + if (!fs::exists(tmpPath)) { - sortedPaths.insert(entry.path()); + if (!quiet) + { + f3d::log::error("File ", tmpPath.string(), " does not exist"); + } + return -1; } - for (const auto& entryPath : sortedPaths) + // If file is a folder, add files recursively + else if (fs::is_directory(tmpPath)) { - // Recursively add all files - this->AddFile(entryPath, quiet); + std::set sortedPaths; + for (const auto& entry : fs::directory_iterator(tmpPath)) + { + sortedPaths.insert(entry.path()); + } + for (const auto& entryPath : sortedPaths) + { + // Recursively add all files + this->AddFile(entryPath, quiet); + } + return static_cast(this->Internals->FilesGroups.size()) - 1; } - return static_cast(this->Internals->FilesGroups.size()) - 1; - } - 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++) + else { - auto localIt = std::find(it->begin(), it->end(), tmpPath); - found |= localIt != it->end(); - if (found) + // 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++) { - break; + auto localIt = std::find(it->begin(), it->end(), tmpPath); + found |= localIt != it->end(); + if (found) + { + break; + } } - } - if (!found) - { - // Add to the right file group - // XXX more multi-file mode may be added in the future - if (this->Internals->AppOptions.MultiFileMode == "all") + if (!found) { - if (this->Internals->FilesGroups.empty()) + // Add to the right file group + // XXX more multi-file mode may be added in the future + if (this->Internals->AppOptions.MultiFileMode == "all") + { + if (this->Internals->FilesGroups.empty()) + { + this->Internals->FilesGroups.resize(1); + } + assert(this->Internals->FilesGroups.size() == 1); + this->Internals->FilesGroups[0].emplace_back(tmpPath); + } + else { - this->Internals->FilesGroups.resize(1); + if (this->Internals->AppOptions.MultiFileMode != "single") + { + f3d::log::warn("Unrecognized multi-file-mode: ", + this->Internals->AppOptions.MultiFileMode, ". Assuming \"single\" mode."); + } + this->Internals->FilesGroups.emplace_back(std::vector{ tmpPath }); } - assert(this->Internals->FilesGroups.size() == 1); - this->Internals->FilesGroups[0].emplace_back(tmpPath); + return static_cast(this->Internals->FilesGroups.size()) - 1; } else { - if (this->Internals->AppOptions.MultiFileMode != "single") + // If already added, just return the index of the group containing the file + if (!quiet) { - f3d::log::warn("Unrecognized multi-file-mode: ", - this->Internals->AppOptions.MultiFileMode, ". Assuming \"single\" mode."); + f3d::log::warn("File ", tmpPath.string(), " has already been added"); } - this->Internals->FilesGroups.emplace_back(std::vector{ tmpPath }); + return static_cast(std::distance(this->Internals->FilesGroups.begin(), it)); } - return static_cast(this->Internals->FilesGroups.size()) - 1; } - else + } + catch (const fs::filesystem_error& ex) + { + if (!quiet) { - // 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"); - } - return static_cast(std::distance(this->Internals->FilesGroups.begin(), it)); + f3d::log::error("Error adding file: ", ex.what()); } + return -1; } } @@ -1620,7 +1649,7 @@ void F3DStarter::AddCommands() int index = -1; for (const std::string& file : files) { - index = this->AddFile(fs::path(file)); + index = this->AddFile(f3d::utils::collapsePath(file)); } if (index > -1) { @@ -1665,7 +1694,7 @@ void F3DStarter::AddCommands() } else { - index = this->AddFile(fs::path(file)); + index = this->AddFile(f3d::utils::collapsePath(file)); } } if (index > -1) diff --git a/application/testing/CMakeLists.txt b/application/testing/CMakeLists.txt index 92b9aebb06..0d1f0725c6 100644 --- a/application/testing/CMakeLists.txt +++ b/application/testing/CMakeLists.txt @@ -890,8 +890,8 @@ f3d_test(NAME TestUnsupportedInputOutput DATA unsupportedFile.dummy REGEXP "No f f3d_test(NAME TestOutputNoBackground DATA cow.vtp ARGS --no-background NO_BASELINE) # Basic record and play test -f3d_test(NAME TestInteractionRecord DATA cow.vtp ARGS --interaction-test-record=${CMAKE_BINARY_DIR}/Testing/Temporary/interaction.log NO_BASELINE) -f3d_test(NAME TestInteractionPlay DATA cow.vtp ARGS --interaction-test-play=${CMAKE_BINARY_DIR}/Testing/Temporary/interaction.log DEPENDS TestInteractionRecord NO_BASELINE) +f3d_test(NAME TestInteractionRecord DATA cow.vtp ARGS --interaction-test-record=${CMAKE_BINARY_DIR}/Testing/Temporary/TestInteractionRecord.log NO_BASELINE) +f3d_test(NAME TestInteractionPlay DATA cow.vtp ARGS --interaction-test-play=${CMAKE_BINARY_DIR}/Testing/Temporary/TestInteractionRecord.log DEPENDS TestInteractionRecord NO_BASELINE) # Command Script Test f3d_test(NAME TestCommandScriptBasic DATA dragon.vtu SCRIPT TestCommandScriptBasic.txt --reference=${F3D_SOURCE_DIR}/testing/baselines/TestCommandScriptBasic.png) @@ -1142,13 +1142,40 @@ add_test(NAME f3d::TestConfigResolution COMMAND $ --config=${F3 # 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 --multi-file-mode=all --verbose) -set_tests_properties(f3d::TestMultiFileFileNameTemplate PROPERTIES PASS_REGULAR_EXPRESSION "Output image saved to \".*/Testing/Temporary/multi_file.png\"") +set_tests_properties(f3d::TestMultiFileFileNameTemplate PROPERTIES 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 --verbose) -set_tests_properties(f3d::TestNoFileFileNameTemplate PROPERTIES PASS_REGULAR_EXPRESSION "Output image saved to \".*/Testing/Temporary/no_file.png\"") +set_tests_properties(f3d::TestNoFileFileNameTemplate PROPERTIES PASS_REGULAR_EXPRESSION "no_file.png") set_tests_properties(f3d::TestNoFileFileNameTemplate PROPERTIES ENVIRONMENT "CTEST_F3D_NO_DATA_FORCE_RENDER=1") +if(NOT WIN32) + add_test(NAME f3d::TestHOMEOutput COMMAND $ ${F3D_SOURCE_DIR}/testing/data/suzanne.stl --output=~/Testing/Temporary/TestHOMEOutput.png --resolution=300,300 --no-config) + set_tests_properties(f3d::TestHOMEOutput PROPERTIES ENVIRONMENT "HOME=${CMAKE_BINARY_DIR}") + set_tests_properties(f3d::TestHOMEOutput PROPERTIES FIXTURES_SETUP f3d::TestHOMEOutput_FIXTURE) + + add_test(NAME f3d::TestHOMEReference COMMAND $ ${F3D_SOURCE_DIR}/testing/data/suzanne.stl --output=${CMAKE_BINARY_DIR}/Testing/Temporary/TestHOMEReference.png --reference=~/Testing/Temporary/TestHOMEOutput.png --resolution=300,300 --no-config) + set_tests_properties(f3d::TestHOMEReference PROPERTIES ENVIRONMENT "HOME=${CMAKE_BINARY_DIR}") + set_tests_properties(f3d::TestHOMEReference PROPERTIES FIXTURES_REQUIRED f3d::TestHOMEOutput_FIXTURE) + + add_test(NAME f3d::TestHOMEOutputTemplate COMMAND $ ${F3D_SOURCE_DIR}/testing/data/suzanne.stl --output=~/Testing/Temporary/{model}{n}.png --resolution=300,300 --verbose) + set_tests_properties(f3d::TestHOMEOutputTemplate PROPERTIES ENVIRONMENT "HOME=${CMAKE_BINARY_DIR}") + + f3d_test(NAME TestHOMEInput ARGS --input=~/testing/data/suzanne.stl ENV "HOME=${F3D_SOURCE_DIR}") + f3d_test(NAME TestHOMEConfig DATA suzanne.stl CONFIG ~/testing/configs/complex.json ENV "HOME=${F3D_SOURCE_DIR}") + f3d_test(NAME TestHOMEPlugin ARGS --load-plugins=~/testing/data/invalid.so REGEXP "Cannot open the library" NO_BASELINE ENV "HOME=${F3D_SOURCE_DIR}") + f3d_test(NAME TestHOMEInteractionRecord DATA cow.vtp ARGS --interaction-test-record=~/Testing/Temporary/TestHOMEInteractionRecord.log NO_BASELINE ENV "HOME=${CMAKE_BINARY_DIR}") + f3d_test(NAME TestHOMEInteractionPlay DATA cow.vtp ARGS --interaction-test-play=~/Testing/Temporary/TestHOMEInteractionRecord.log DEPENDS TestHOMEInteractionRecord NO_BASELINE ENV "HOME=${CMAKE_BINARY_DIR}") + f3d_test(NAME TestHOMEColorMapFile DATA dragon.vtu ARGS --colormap-file=~/testing/data/viridis8.png --scalar-coloring --coloring-component=1 ENV "HOME=${F3D_SOURCE_DIR}") + f3d_test(NAME TestHOMEScreenshot DATA suzanne.ply ARGS --screenshot-filename=~/Testing/Temporary/TestHOMEScreenshot.png --interaction-test-play=${F3D_SOURCE_DIR}/testing/recordings/TestScreenshot.log REGEXP "saving screenshot to ${CMAKE_BINARY_DIR}/Testing/Temporary/TestHOMEScreenshot.png" NO_BASELINE ENV "HOME=${CMAKE_BINARY_DIR}") + f3d_test(NAME TestHOMECommandScript DATA suzanne.ply ARGS --command-script=~/testing/scripts/TestHOMECommandScript.txt REGEXP "Camera focal point" NO_BASELINE ENV "HOME=${F3D_SOURCE_DIR}") + + STRING(RANDOM LENGTH 257 ALPHABET "x" _f3d_test_invalid_folder) + f3d_test(NAME TestColorMapTooLong DATA dragon.vtu ARGS --colormap-file=${_f3d_test_invalid_folder}/file.ext --scalar-coloring REGEXP "File name too long" NO_BASELINE) + f3d_test(NAME TestScreenshotTooLong DATA suzanne.ply ARGS --screenshot-filename=${_f3d_test_invalid_folder}/file.ext --interaction-test-play=${F3D_SOURCE_DIR}/testing/recordings/TestScreenshot.log REGEXP "File name too long" NO_BASELINE) + f3d_test(NAME TestInputTooLong ARGS --input=${_f3d_test_invalid_folder}/file.ext REGEXP "File name too long" NO_BASELINE) +endif() + # 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/doc/user/COLOR_MAPS.md b/doc/user/COLOR_MAPS.md index aa13e26397..1c54dbcc43 100644 --- a/doc/user/COLOR_MAPS.md +++ b/doc/user/COLOR_MAPS.md @@ -3,8 +3,8 @@ ## Image files It is possible to specify a color map using the `--colormap-file` option. -The value of the option can be a path to an image file, a filename or a filestem. -If it is not a path, these directories are used to find the file (in this order): +The value of the option can be an absolute path to an image file, a relative path, a filename or a filestem. +If it is not an absolute path, these directories are used to find the file (in this order): * Linux: `${XDG_CONFIG_HOME}/f3d/colormaps`, `~/.config/f3d/colormaps`, `/etc/f3d/colormaps`, `/usr/share/f3d/colormaps`, `[install_dir]/share/f3d/colormaps` * Windows: `%APPDATA%\f3d\colormaps`, `[install_dir]\share\f3d\configs\colormaps` * macOS: `${XDG_CONFIG_HOME}/f3d/colormaps`, `~/.config/f3d/colormaps`, `/usr/local/etc/f3d/colormaps`, `f3d.app/Contents/Resources/configs/colormaps` diff --git a/doc/user/OPTIONS.md b/doc/user/OPTIONS.md index 26b36aadcb..8113c4b890 100644 --- a/doc/user/OPTIONS.md +++ b/doc/user/OPTIONS.md @@ -24,7 +24,7 @@ Options|Type
Default|Description \-\-frame-rate=\|double
30.0|Frame rate used to refresh animation and other repeated tasks (watch, UI). Does not impact rendering frame rate. \-\-load-plugins=\|string
-|List of plugins to load separated with a comma. Official plugins are `alembic`, `assimp`, `draco`, `exodus`, `occt`, `usd`, `vdb`. See [plugins](PLUGINS.md) for more info. \-\-scan-plugins||Scan standard directories for plugins and display their names, results may be incomplete. See [plugins](PLUGINS.md) for more info. -\-\-screenshot-filename=\|string
`{app}/{model}_{n}.png`|Filename to save [screenshots](INTERACTIONS.md#taking-screenshots) to. Can use [template variables](#filename-templating). +\-\-screenshot-filename=\|string
`{app}/{model}_{n}.png`|Filename to save [screenshots](INTERACTIONS.md#taking-screenshots) to. Can use [template variables](#filename-templating). Supports relative paths [as described](INTERACTIONS.md#taking-screenshots). \-\-rendering-backend=\|string
auto|Rendering backend to load, `auto` means to let F3D pick the correct one for you depending on your system capabilities. Use `egl` or `osmesa` on linux to force headless rendering. ## General Options diff --git a/library/src/engine.cxx b/library/src/engine.cxx index 5d083d529f..ada3e2e370 100644 --- a/library/src/engine.cxx +++ b/library/src/engine.cxx @@ -1,14 +1,14 @@ #include "engine.h" #include "config.h" +#include "factory.h" #include "init.h" #include "interactor_impl.h" #include "log.h" #include "scene_impl.h" +#include "utils.h" #include "window_impl.h" -#include "factory.h" - #include "vtkF3DNoRenderWindow.h" #include @@ -279,7 +279,7 @@ void engine::loadPlugin(const std::string& pathOrName, const std::vectorInternals->StopEventLoop(); } - catch (const std::filesystem::filesystem_error& ex) + catch (const fs::filesystem_error& ex) { log::error("Could not play recording: ", ex.what()); return false; @@ -1196,7 +1196,7 @@ bool interactor_impl::recordInteraction(const fs::path& file) this->Internals->Recorder->On(); this->Internals->Recorder->Record(); } - catch (const std::filesystem::filesystem_error& ex) + catch (const fs::filesystem_error& ex) { log::error("Could not record: ", ex.what()); return false; diff --git a/testing/baselines/TestHOMEColorMapFile.png b/testing/baselines/TestHOMEColorMapFile.png new file mode 100644 index 0000000000..a8dfe225b5 --- /dev/null +++ b/testing/baselines/TestHOMEColorMapFile.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e0191ed9ed693f5f91396ca2ec43dcd087f718bdf232c24eaefdb20db1d9a5f +size 25176 diff --git a/testing/baselines/TestHOMEConfig.png b/testing/baselines/TestHOMEConfig.png new file mode 100644 index 0000000000..e5951c362c --- /dev/null +++ b/testing/baselines/TestHOMEConfig.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28bd2baa712dbc713a7259d25ecabefa16021cad7a09ae06258fb6a4f692e845 +size 29344 diff --git a/testing/baselines/TestHOMEInput.png b/testing/baselines/TestHOMEInput.png new file mode 100644 index 0000000000..b89d9190e5 --- /dev/null +++ b/testing/baselines/TestHOMEInput.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0fcda6faec9c61345bf82e3e9777bcb2f8137129090df2d4e3fbdb13acd6aeb +size 25409 diff --git a/testing/scripts/TestHOMECommandScript.txt b/testing/scripts/TestHOMECommandScript.txt new file mode 100644 index 0000000000..939dd57f2f --- /dev/null +++ b/testing/scripts/TestHOMECommandScript.txt @@ -0,0 +1 @@ +print_scene_info