From 7a462590aba28a3b964a74f1d1491e0d908656d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 18 Feb 2022 12:56:56 +0100 Subject: [PATCH] Any{Scene,Image}Importer: propagate file callbacks as well. --- doc/changelog.dox | 3 ++ .../AnyImageImporter/AnyImageImporter.cpp | 12 ++++++-- .../AnyImageImporter/AnyImageImporter.h | 14 +++++---- .../Test/AnyImageImporterTest.cpp | 27 +++++++++++++++++ .../AnySceneImporter/AnySceneImporter.cpp | 7 +++-- .../AnySceneImporter/AnySceneImporter.h | 12 ++++---- .../Test/AnySceneImporterTest.cpp | 29 ++++++++++++++++++- 7 files changed, 87 insertions(+), 17 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index f3dec08b3..ff47cf039 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -491,6 +491,9 @@ See also: plugin to apply the option to with `-I` / `-C`. For better usability, the plugins also warn if the user specifies and option that is not present in the target implementation. +- @relativeref{Trade,AnyImageImporter} and + @relativeref{Trade,AnySceneImporter} now can propagate also file callbacks + to the concrete plugin. - @relativeref{Trade,AnyImageConverter} now implements also conversion of 3D and multi-level 2D/3D images for formats that support it (such as Basis Universal or OpenEXR) diff --git a/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp b/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp index ed9c590c6..d910e4eaa 100644 --- a/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp +++ b/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp @@ -48,7 +48,9 @@ AnyImageImporter::AnyImageImporter(AnyImageImporter&&) noexcept = default; AnyImageImporter::~AnyImageImporter() = default; -ImporterFeatures AnyImageImporter::doFeatures() const { return ImporterFeature::OpenData; } +ImporterFeatures AnyImageImporter::doFeatures() const { + return ImporterFeature::OpenData|ImporterFeature::FileCallback; +} bool AnyImageImporter::doIsOpened() const { return !!_in; } @@ -138,9 +140,10 @@ void AnyImageImporter::doOpenFile(const std::string& filename) { d << "(provided by" << metadata->name() << Debug::nospace << ")"; } - /* Instantiate the plugin, propagate flags */ + /* Instantiate the plugin, propagate flags and the file callback, if set */ Containers::Pointer importer = static_cast*>(manager())->instantiate(plugin); importer->setFlags(flags()); + if(fileCallback()) importer->setFileCallback(fileCallback(), fileCallbackUserData()); /* Propagate configuration */ Magnum::Implementation::propagateConfiguration("Trade::AnyImageImporter::openFile():", {}, metadata->name(), configuration(), importer->configuration()); @@ -244,7 +247,10 @@ void AnyImageImporter::doOpenData(Containers::Array&& data, DataFlags) { d << "(provided by" << metadata->name() << Debug::nospace << ")"; } - /* Instantiate the plugin, propagate flags */ + /* Instantiate the plugin, propagate flags. File callbacks not propagated + here as no image importers currently load any extra files. */ + /** @todo revisit callbacks when that becomes true (such as loading XMP + files accompanying RAWs) */ Containers::Pointer importer = static_cast*>(manager())->instantiate(plugin); importer->setFlags(flags()); diff --git a/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.h b/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.h index f89a2944c..d85a1a452 100644 --- a/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.h +++ b/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.h @@ -53,8 +53,9 @@ namespace Magnum { namespace Trade { /** @brief Any image importer plugin -Detects file type based on file extension, loads corresponding plugin and then -tries to open the file with it. Supported formats: +Detects file type based on file extension or a signature at the start of the +file, loads corresponding plugin and then tries to open the file with it. +Supported formats: - Basis Universal (`*.basis` or data with corresponding signature), loaded with @ref BasisImporter or any other plugin that provides it @@ -99,6 +100,7 @@ tries to open the file with it. Supported formats: Detecting file type through @ref openData() is supported only for a subset of formats that are marked as such in the list above. +@ref ImporterFeature::FileCallback is supported as well. @section Trade-AnyImageImporter-usage Usage @@ -135,10 +137,10 @@ information. On a call to @ref openFile() / @ref openData(), a file format is detected from the extension / file signature and a corresponding plugin is loaded. After -that, flags set via @ref setFlags() and options set through -@ref configuration() are propagated to the concrete implementation, with a -warning emitted in case given option is not present in the default -configuration of the target plugin. +that, flags set via @ref setFlags(), file callbacks set via +@ref setFileCallback() and options set through @ref configuration() are +propagated to the concrete implementation. A warning is emitted in case an +option set is not present in the default configuration of the target plugin. Calls to the @ref image1DCount() / @ref image2DCount() / @ref image3DCount(), @ref image1DLevelCount() / @ref image2DLevelCount() / @ref image3DLevelCount() diff --git a/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp b/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp index 8bc519809..d8c792d7e 100644 --- a/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp +++ b/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp @@ -60,6 +60,7 @@ struct AnyImageImporterTest: TestSuite::Tester { void propagateConfigurationUnknown(); /* configuration propagation fully tested in AnySceneImporter, as there the plugins have configuration subgroups as well */ + void propagateFileCallback(); /* Explicitly forbid system-wide plugin dependencies */ PluginManager::Manager _manager{"nonexistent"}; @@ -182,6 +183,8 @@ AnyImageImporterTest::AnyImageImporterTest() { addInstancedTests({&AnyImageImporterTest::propagateConfigurationUnknown}, Containers::arraySize(Load2DData)); + addTests({&AnyImageImporterTest::propagateFileCallback}); + /* Load the plugin directly from the build tree. Otherwise it's static and already loaded. */ #ifdef ANYIMAGEIMPORTER_PLUGIN_FILENAME @@ -405,6 +408,30 @@ void AnyImageImporterTest::propagateConfigurationUnknown() { CORRADE_COMPARE(out.str(), Utility::formatString("Trade::AnyImageImporter::{}(): option noSuchOption not recognized by TgaImporter\n", data.messageFunctionName)); } +void AnyImageImporterTest::propagateFileCallback() { + if(!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("TgaImporter plugin not enabled, cannot test"); + + Containers::Pointer importer = _manager.instantiate("AnyImageImporter"); + + Containers::Array storage; + importer->setFileCallback([](const std::string&, InputFileCallbackPolicy, Containers::Array& storage) -> Containers::Optional> { + storage = Utility::Directory::read(TGA_FILE); + return Containers::ArrayView{storage}; + }, storage); + + CORRADE_VERIFY(importer->openFile("you-know-where-the-file-is.tga")); + CORRADE_COMPARE(importer->image2DCount(), 1); + + /* Check only size, as it is good enough proof that it is working */ + Containers::Optional image = importer->image2D(0); + CORRADE_VERIFY(image); + CORRADE_COMPARE(image->size(), Vector2i(3, 2)); + + importer->close(); + CORRADE_VERIFY(!importer->isOpened()); +} + }}}} CORRADE_TEST_MAIN(Magnum::Trade::Test::AnyImageImporterTest) diff --git a/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.cpp b/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.cpp index b57a981cf..9b2f2130d 100644 --- a/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.cpp +++ b/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.cpp @@ -61,7 +61,9 @@ AnySceneImporter::AnySceneImporter(PluginManager::AbstractManager& manager, cons AnySceneImporter::~AnySceneImporter() = default; -ImporterFeatures AnySceneImporter::doFeatures() const { return {}; } +ImporterFeatures AnySceneImporter::doFeatures() const { + return ImporterFeature::FileCallback; +} bool AnySceneImporter::doIsOpened() const { return !!_in; } @@ -152,9 +154,10 @@ void AnySceneImporter::doOpenFile(const std::string& filename) { d << "(provided by" << metadata->name() << Debug::nospace << ")"; } - /* Instantiate the plugin, propagate flags */ + /* Instantiate the plugin, propagate flags and the file callback, if set */ Containers::Pointer importer = static_cast*>(manager())->instantiate(plugin); importer->setFlags(flags()); + if(fileCallback()) importer->setFileCallback(fileCallback(), fileCallbackUserData()); /* Propagate configuration */ Magnum::Implementation::propagateConfiguration("Trade::AnySceneImporter::openFile():", {}, metadata->name(), configuration(), importer->configuration()); diff --git a/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.h b/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.h index ba2613307..bb55a2c4d 100644 --- a/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.h +++ b/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.h @@ -95,7 +95,8 @@ tries to open the file with it. Supported formats: `ValveImporter` - XGL (`*.xgl`, `*.zgl`), loaded with any plugin that provides `XglImporter` -Only loading from files is supported. +Only loading from files is supported as the filename is used to detect the +format, however @ref ImporterFeature::FileCallback is supported as well. @section Trade-AnySceneImporter-usage Usage @@ -131,10 +132,11 @@ information. @section Trade-AnySceneImporter-proxy Interface proxying and option propagation On a call to @ref openFile(), a file format is detected from the extension and -a corresponding plugin is loaded. After that, flags set via @ref setFlags() and -options set through @ref configuration() are propagated to the concrete -implementation, with a warning emitted in case given option is not present in -the default configuration of the target plugin. +a corresponding plugin is loaded. After that, flags set via @ref setFlags(), +file callbacks set via @ref setFileCallback() and options set through +@ref configuration() are propagated to the concrete implementation. A warning +is emitted in case an option set is not present in the default configuration of +the target plugin. Calls to the @ref animation(), @ref scene(), @ref light(), @ref camera(), @ref object2D(), @ref object3D(), @ref skin2D(), @ref skin3D(), @ref mesh(), diff --git a/src/MagnumPlugins/AnySceneImporter/Test/AnySceneImporterTest.cpp b/src/MagnumPlugins/AnySceneImporter/Test/AnySceneImporterTest.cpp index 774805ad6..e2048bc08 100644 --- a/src/MagnumPlugins/AnySceneImporter/Test/AnySceneImporterTest.cpp +++ b/src/MagnumPlugins/AnySceneImporter/Test/AnySceneImporterTest.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "Magnum/Math/Vector3.h" @@ -60,6 +61,7 @@ struct AnySceneImporterTest: TestSuite::Tester { void propagateFlags(); void propagateConfiguration(); void propagateConfigurationUnknown(); + void propagateFileCallback(); /* Explicitly forbid system-wide plugin dependencies */ PluginManager::Manager _manager{"nonexistent"}; @@ -103,7 +105,8 @@ AnySceneImporterTest::AnySceneImporterTest() { &AnySceneImporterTest::propagateFlags, &AnySceneImporterTest::propagateConfiguration, - &AnySceneImporterTest::propagateConfigurationUnknown}); + &AnySceneImporterTest::propagateConfigurationUnknown, + &AnySceneImporterTest::propagateFileCallback}); /* Load the plugin directly from the build tree. Otherwise it's static and already loaded. */ @@ -271,6 +274,30 @@ void AnySceneImporterTest::propagateConfigurationUnknown() { "Trade::AnySceneImporter::openFile(): option postprocess/feh/noHereNotEither not recognized by AssimpImporter\n"); } +void AnySceneImporterTest::propagateFileCallback() { + if(!(_manager.loadState("ObjImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("ObjImporter plugin not enabled, cannot test"); + + Containers::Pointer importer = _manager.instantiate("AnySceneImporter"); + + Containers::Array storage; + importer->setFileCallback([](const std::string&, InputFileCallbackPolicy, Containers::Array& storage) -> Containers::Optional> { + storage = Utility::Directory::read(OBJ_FILE); + return Containers::ArrayView{storage}; + }, storage); + + CORRADE_VERIFY(importer->openFile("you-know-where-the-file-is.obj")); + CORRADE_COMPARE(importer->meshCount(), 1); + + /* Check only size, as it is good enough proof that it is working */ + Containers::Optional mesh = importer->mesh(0); + CORRADE_VERIFY(mesh); + CORRADE_COMPARE(mesh->vertexCount(), 3); + + importer->close(); + CORRADE_VERIFY(!importer->isOpened()); +} + }}}} CORRADE_TEST_MAIN(Magnum::Trade::Test::AnySceneImporterTest)