From 31381371e83eb2d1c4e289f1b483d0536fae497b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 3 Jun 2025 21:40:56 +0200 Subject: [PATCH] Any{Image,Scene}Importer: propagate importerState() as well. Is critically needed for the GltfImporter now, as the per-data importer state is not useful on its own anymore and needs the Utility::Json instance as well. And doing the same for AnyImageImporter as well for feature parity. --- doc/changelog.dox | 2 +- .../AnyImageImporter/AnyImageImporter.cpp | 2 + .../AnyImageImporter/AnyImageImporter.h | 11 ++++-- .../Test/AnyImageImporterTest.cpp | 35 +++++++++++++++++- .../AnyImageImporter/Test/CMakeLists.txt | 2 + .../AnyImageImporter/Test/dispose_bgnd.gif | Bin 0 -> 1450 bytes .../AnySceneImporter/AnySceneImporter.cpp | 2 + .../AnySceneImporter/AnySceneImporter.h | 10 +++-- .../Test/AnySceneImporterTest.cpp | 24 +++++++++++- 9 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 src/MagnumPlugins/AnyImageImporter/Test/dispose_bgnd.gif diff --git a/doc/changelog.dox b/doc/changelog.dox index 11b4471f0..d3586e2de 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -1020,7 +1020,7 @@ See also: the target implementation. - @relativeref{Trade,AnyImageImporter} and @relativeref{Trade,AnySceneImporter} now can propagate also file callbacks - to the concrete plugin. + and @ref Trade::AbstractImporter::importerState() 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 916cd34f9..bbbfbed55 100644 --- a/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp +++ b/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp @@ -345,6 +345,8 @@ UnsignedInt AnyImageImporter::doImage3DLevelCount(UnsignedInt id) { return _in-> Containers::Optional AnyImageImporter::doImage3D(const UnsignedInt id, const UnsignedInt level) { return _in->image3D(id, level); } +const void* AnyImageImporter::doImporterState() const { return _in->importerState(); } + }} CORRADE_PLUGIN_REGISTER(AnyImageImporter, Magnum::Trade::AnyImageImporter, diff --git a/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.h b/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.h index 00312d993..a0f326290 100644 --- a/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.h +++ b/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.h @@ -157,10 +157,11 @@ 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() -and @ref image1D() / @ref image2D() / @ref image3D() functions are then proxied -to the concrete implementation. The @ref close() function closes and discards -the internally instantiated plugin; @ref isOpened() works as usual. +@ref image1DLevelCount() / @ref image2DLevelCount() / @ref image3DLevelCount(), +@ref image1D() / @ref image2D() / @ref image3D() and @ref importerState() +functions are then proxied to the concrete implementation. The @ref close() +function closes and discards the internally instantiated plugin; +@ref isOpened() works as usual. Besides delegating the flags, the @ref AnyImageImporter itself recognizes @ref ImporterFlag::Verbose, printing info about the concrete plugin being used @@ -213,6 +214,8 @@ class MAGNUM_ANYIMAGEIMPORTER_EXPORT AnyImageImporter: public AbstractImporter { MAGNUM_ANYIMAGEIMPORTER_LOCAL UnsignedInt doImage3DLevelCount(UnsignedInt id) override; MAGNUM_ANYIMAGEIMPORTER_LOCAL Containers::Optional doImage3D(UnsignedInt id, UnsignedInt level) override; + MAGNUM_ANYIMAGEIMPORTER_LOCAL const void* doImporterState() const override; + Containers::Pointer _in; }; diff --git a/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp b/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp index 2186491bf..4522da154 100644 --- a/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp +++ b/src/MagnumPlugins/AnyImageImporter/Test/AnyImageImporterTest.cpp @@ -26,9 +26,11 @@ */ #include +#include #include #include #include +#include #include #include #include @@ -70,6 +72,8 @@ struct AnyImageImporterTest: TestSuite::Tester { void imageLevels2D(); void imageLevels3D(); + void importerState(); + /* Explicitly forbid system-wide plugin dependencies */ PluginManager::Manager _manager{"nonexistent"}; }; @@ -242,7 +246,9 @@ AnyImageImporterTest::AnyImageImporterTest() { &AnyImageImporterTest::images3D, &AnyImageImporterTest::imageLevels1D, &AnyImageImporterTest::imageLevels2D, - &AnyImageImporterTest::imageLevels3D}); + &AnyImageImporterTest::imageLevels3D, + + &AnyImageImporterTest::importerState}); /* Load the plugin directly from the build tree. Otherwise it's static and already loaded. */ @@ -653,6 +659,33 @@ void AnyImageImporterTest::imageLevels3D() { CORRADE_COMPARE(image->size(), (Vector3i{2, 1, 3})); } +void AnyImageImporterTest::importerState() { + PluginManager::Manager manager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR}; + #ifdef ANYIMAGEIMPORTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYIMAGEIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + /* Catch also ABI and interface mismatch errors */ + if(!(manager.load("StbImageImporter") & PluginManager::LoadState::Loaded)) + CORRADE_SKIP("StbImageImporter plugin can't be loaded."); + + /* Ensure StbImageImporter is picked, and not for example + DevIlImageImporter */ + manager.setPreferredPlugins("GifImporter", {"StbImageImporter"}); + + Containers::Pointer importer = manager.instantiate("AnyImageImporter"); + CORRADE_VERIFY(importer->openFile(Utility::Path::join(ANYIMAGEIMPORTER_TEST_DIR, "dispose_bgnd.gif"))); + + /* Testing the same as in StbImageImporterTest::animatedGif(). Importer + state should expose the delays, in milliseconds. */ + CORRADE_COMPARE(importer->image2DCount(), 5); + CORRADE_VERIFY(importer->importerState()); + CORRADE_COMPARE_AS( + Containers::arrayView(reinterpret_cast(importer->importerState()), importer->image2DCount()), + Containers::arrayView({1000, 1000, 1000, 1000, 1000}), + TestSuite::Compare::Container); +} + }}}} CORRADE_TEST_MAIN(Magnum::Trade::Test::AnyImageImporterTest) diff --git a/src/MagnumPlugins/AnyImageImporter/Test/CMakeLists.txt b/src/MagnumPlugins/AnyImageImporter/Test/CMakeLists.txt index b1fbc1378..990023fcb 100644 --- a/src/MagnumPlugins/AnyImageImporter/Test/CMakeLists.txt +++ b/src/MagnumPlugins/AnyImageImporter/Test/CMakeLists.txt @@ -54,6 +54,8 @@ corrade_add_test(AnyImageImporterTest AnyImageImporterTest.cpp 8x8.astc # Generated by AnyImageConverterTest::propagateConfiguration2D() depth32f-custom-channels.exr + # From StbImageImporter test data + dispose_bgnd.gif # From KtxImporter test data 1d-mipmaps.ktx2 2d-mipmaps.ktx2 diff --git a/src/MagnumPlugins/AnyImageImporter/Test/dispose_bgnd.gif b/src/MagnumPlugins/AnyImageImporter/Test/dispose_bgnd.gif new file mode 100644 index 0000000000000000000000000000000000000000..d68504010fe1248b656d15ee84172da4ab402219 GIT binary patch literal 1450 zcmYk*dpOg390%~Drc~ z%-Iz$W>&3$+SY`PXz7U!Q~KtU``ig>i5p6lQFeuJ`lA3cRA6#wv@Ry}Ug$M`1ATit zD~#I=yMKnAT-&ZJ$YspM9QezeH({0VrMhWTk~4r(;`mLbmn?bo;qmVwo`~9zpG-_h zFKf7ius2&!c?XDt*JoVTN`+qabKVPR;>H7qxS>JZ zS{xAPF&dTCfl@IHhs)_=)g4RW!5?+iVYnG2kwPLedNL7qxD@Eh;S16V~VNT4n;G|)uo{&rKD(KfUe z&5lTEg%17+3-@h)ns#0%`3}8W((p5={-9c=B`3GFV=(@*3fXf&&VFT~(QzRP6)fET zh)dCtcQbSLk2NDJxuJ{_A_8rcY$Fq>#ZItzyh3mh9uXgN#UkFYFv5lvinWI+U{j2+ zF&bCT<|k+0tKfF%N-4J%mGwAd^Go`BesQHG5wj**d2fCnwEO!tB zJr0)uTdQAxJrI7$w%fWBHuHR}J~Nhxc%}y#B8v6l%w?%9R=S!9ZPa>3p_kRvNz3wn zwEV@UOA6j7*2yCkcG&?~RT+0GAVo?|Rgk-Fg*hQkjw4Vk&3?X$29tB+@HBLEmWONZ z%`lo4BBC&fUP7hBA_$3DH!JhXC}@WC9d>Cvvw%TpF)WE~z&A0ud94rH^Q$;r{_%IZ z%T*XO-f(?C;Xb9eu5(0_@oxD&v{WMYa+wbIzJ$Uu`8e$iC$@64D(%#%wcMK4$7WC zk>@27kloi$d%v1mH0D#a1;?;ytgSS6m5%8Br*obLI0_2*m|$G+?-w8)>slY^TG-%c zIuH$CW2DK8vFeQL2WtXt@k&!g1image3DName(id); } Containers::Optional AnySceneImporter::doImage3D(const UnsignedInt id, const UnsignedInt level) { return _in->image3D(id, level); } +const void* AnySceneImporter::doImporterState() const { return _in->importerState(); } + }} CORRADE_PLUGIN_REGISTER(AnySceneImporter, Magnum::Trade::AnySceneImporter, diff --git a/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.h b/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.h index 3c738b922..89d5efdfa 100644 --- a/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.h +++ b/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.h @@ -164,10 +164,10 @@ the target plugin. Calls to the @ref animation(), @ref scene(), @ref light(), @ref camera(), @ref skin2D(), @ref skin3D(), @ref mesh(), @ref material(), @ref texture(), -@ref image1D(), @ref image2D(), @ref image3D() and corresponding -count-/name-related functions are then proxied to the concrete implementation. -The @ref close() function closes and discards the internally instantiated -plugin; @ref isOpened() works as usual. +@ref image1D(), @ref image2D(), @ref image3D(), corresponding +count-/name-related functions and the @ref importerState() function are then +proxied to the concrete implementation. The @ref close() function closes and +discards the internally instantiated plugin; @ref isOpened() works as usual. While the @ref meshAttributeName(), @ref meshAttributeForName(), @ref sceneFieldName() and @ref sceneFieldForName() APIs can be called without a @@ -302,6 +302,8 @@ class MAGNUM_ANYSCENEIMPORTER_EXPORT AnySceneImporter: public AbstractImporter { MAGNUM_ANYSCENEIMPORTER_LOCAL Containers::String doImage3DName(UnsignedInt id) override; MAGNUM_ANYSCENEIMPORTER_LOCAL Containers::Optional doImage3D(UnsignedInt id, UnsignedInt level) override; + MAGNUM_ANYSCENEIMPORTER_LOCAL const void* doImporterState() const override; + Containers::Pointer _in; }; diff --git a/src/MagnumPlugins/AnySceneImporter/Test/AnySceneImporterTest.cpp b/src/MagnumPlugins/AnySceneImporter/Test/AnySceneImporterTest.cpp index dafe60bf9..14f1539a6 100644 --- a/src/MagnumPlugins/AnySceneImporter/Test/AnySceneImporterTest.cpp +++ b/src/MagnumPlugins/AnySceneImporter/Test/AnySceneImporterTest.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "Magnum/Math/Vector3.h" @@ -107,6 +108,8 @@ struct AnySceneImporterTest: TestSuite::Tester { void imageLevels2D(); void imageLevels3D(); + void importerState(); + /* Explicitly forbid system-wide plugin dependencies */ PluginManager::Manager _manager{"nonexistent"}; }; @@ -240,7 +243,9 @@ AnySceneImporterTest::AnySceneImporterTest() { &AnySceneImporterTest::images3D, &AnySceneImporterTest::imageLevels1D, &AnySceneImporterTest::imageLevels2D, - &AnySceneImporterTest::imageLevels3D}); + &AnySceneImporterTest::imageLevels3D, + + &AnySceneImporterTest::importerState}); /* Load the plugin directly from the build tree. Otherwise it's static and already loaded. */ @@ -891,6 +896,23 @@ void AnySceneImporterTest::imageLevels3D() { CORRADE_COMPARE(image->size(), (Vector3i{1, 1, 3})); } +void AnySceneImporterTest::importerState() { + PluginManager::Manager manager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR}; + #ifdef ANYSCENEIMPORTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYSCENEIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + /* Catch also ABI and interface mismatch errors */ + if(manager.load("GltfImporter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("GltfImporter plugin can't be loaded."); + + Containers::Pointer importer = manager.instantiate("AnySceneImporter"); + CORRADE_VERIFY(importer->openFile(Utility::Path::join(ANYSCENEIMPORTER_TEST_DIR, "meshes.gltf"))); + + CORRADE_VERIFY(importer->importerState()); + CORRADE_COMPARE(static_cast(importer->importerState())->root()["asset"]["version"].asString(), "2.0"); +} + }}}} CORRADE_TEST_MAIN(Magnum::Trade::Test::AnySceneImporterTest)