diff --git a/doc/changelog.dox b/doc/changelog.dox index 6977eca3d..43753dc45 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -91,7 +91,8 @@ See also: @ref Trade::PhongMaterialData::normalTextureScale() and @ref Trade::PhongMaterialData::normalTextureSwizzle() to make new features added for PBR materials recognizable also in classic Phong workflows. -- New @ref Trade::SkinData class for skin import +- New @ref Trade::SkinData class and @ref Trade::AbstractImporter::skin2D() / + @ref Trade::AbstractImporter::skin3D() family of APIs for skin import @subsection changelog-latest-changes Changes and improvements diff --git a/src/Magnum/Trade/AbstractImporter.cpp b/src/Magnum/Trade/AbstractImporter.cpp index 2fc827b43..9b566a806 100644 --- a/src/Magnum/Trade/AbstractImporter.cpp +++ b/src/Magnum/Trade/AbstractImporter.cpp @@ -43,6 +43,7 @@ #include "Magnum/Trade/ObjectData2D.h" #include "Magnum/Trade/ObjectData3D.h" #include "Magnum/Trade/SceneData.h" +#include "Magnum/Trade/SkinData.h" #include "Magnum/Trade/TextureData.h" #ifdef MAGNUM_BUILD_DEPRECATED @@ -61,7 +62,7 @@ namespace Magnum { namespace Trade { std::string AbstractImporter::pluginInterface() { return /* [interface] */ -"cz.mosra.magnum.Trade.AbstractImporter/0.3.2" +"cz.mosra.magnum.Trade.AbstractImporter/0.3.3" /* [interface] */ ; } @@ -475,6 +476,90 @@ Containers::Pointer AbstractImporter::object3D(const std::string& return object3D(id); /* not doObject3D(), so we get the range checks also */ } +UnsignedInt AbstractImporter::skin2DCount() const { + CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::skin2DCount(): no file opened", {}); + return doSkin2DCount(); +} + +UnsignedInt AbstractImporter::doSkin2DCount() const { return 0; } + +Int AbstractImporter::skin2DForName(const std::string& name) { + CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::skin2DForName(): no file opened", {}); + return doSkin2DForName(name); +} + +Int AbstractImporter::doSkin2DForName(const std::string&) { return -1; } + +std::string AbstractImporter::skin2DName(const UnsignedInt id) { + CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::skin2DName(): no file opened", {}); + CORRADE_ASSERT(id < doSkin2DCount(), "Trade::AbstractImporter::skin2DName(): index" << id << "out of range for" << doSkin2DCount() << "entries", {}); + return doSkin2DName(id); +} + +std::string AbstractImporter::doSkin2DName(UnsignedInt) { return {}; } + +Containers::Optional AbstractImporter::skin2D(const UnsignedInt id) { + CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::skin2D(): no file opened", {}); + CORRADE_ASSERT(id < doSkin2DCount(), "Trade::AbstractImporter::skin2D(): index" << id << "out of range for" << doSkin2DCount() << "entries", {}); + return doSkin2D(id); +} + +Containers::Optional AbstractImporter::doSkin2D(UnsignedInt) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImporter::skin2D(): not implemented", {}); +} + +Containers::Optional AbstractImporter::skin2D(const std::string& name) { + CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::skin2D(): no file opened", {}); + const Int id = doSkin2DForName(name); + if(id == -1) { + Error{} << "Trade::AbstractImporter::skin2D(): skin" << name << "not found"; + return {}; + } + return skin2D(id); /* not doSkin2D(), so we get the range checks also */ +} + +UnsignedInt AbstractImporter::skin3DCount() const { + CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::skin3DCount(): no file opened", {}); + return doSkin3DCount(); +} + +UnsignedInt AbstractImporter::doSkin3DCount() const { return 0; } + +Int AbstractImporter::skin3DForName(const std::string& name) { + CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::skin3DForName(): no file opened", {}); + return doSkin3DForName(name); +} + +Int AbstractImporter::doSkin3DForName(const std::string&) { return -1; } + +std::string AbstractImporter::skin3DName(const UnsignedInt id) { + CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::skin3DName(): no file opened", {}); + CORRADE_ASSERT(id < doSkin3DCount(), "Trade::AbstractImporter::skin3DName(): index" << id << "out of range for" << doSkin3DCount() << "entries", {}); + return doSkin3DName(id); +} + +std::string AbstractImporter::doSkin3DName(UnsignedInt) { return {}; } + +Containers::Optional AbstractImporter::skin3D(const UnsignedInt id) { + CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::skin3D(): no file opened", {}); + CORRADE_ASSERT(id < doSkin3DCount(), "Trade::AbstractImporter::skin3D(): index" << id << "out of range for" << doSkin3DCount() << "entries", {}); + return doSkin3D(id); +} + +Containers::Optional AbstractImporter::doSkin3D(UnsignedInt) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImporter::skin3D(): not implemented", {}); +} + +Containers::Optional AbstractImporter::skin3D(const std::string& name) { + CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::skin3D(): no file opened", {}); + const Int id = doSkin3DForName(name); + if(id == -1) { + Error{} << "Trade::AbstractImporter::skin3D(): skin" << name << "not found"; + return {}; + } + return skin3D(id); /* not doSkin3D(), so we get the range checks also */ +} + UnsignedInt AbstractImporter::meshCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::meshCount(): no file opened", {}); return doMeshCount(); diff --git a/src/Magnum/Trade/AbstractImporter.h b/src/Magnum/Trade/AbstractImporter.h index 435c35653..5fcb25934 100644 --- a/src/Magnum/Trade/AbstractImporter.h +++ b/src/Magnum/Trade/AbstractImporter.h @@ -214,6 +214,8 @@ expose internal state through various accessors: imported by @ref object2D() or @ref object3D() - @ref SceneData::importerState() can expose importer state for a scene imported by @ref scene() +- @ref SkinData::importerState() can expose importer state for a scene + imported by @ref skin2D() or @ref skin3D() - @ref TextureData::importerState() can expose importer state for a texture imported by @ref texture() @@ -823,6 +825,108 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi */ Containers::Pointer object3D(const std::string& name); + /** + * @brief Two-dimensional skin count + * @m_since_latest + * + * Expects that a file is opened. + */ + UnsignedInt skin2DCount() const; + + /** + * @brief Two-dimensional skin ID for given name + * @m_since_latest + * + * If no skin for given name exists, returns @cpp -1 @ce. Expects that + * a file is opened. + * @see @ref skin2DName(), @ref skin2D(const std::string&) + */ + Int skin2DForName(const std::string& name); + + /** + * @brief Two-dimensional skin name + * @param id Skin ID, from range [0, @ref skin2DCount()). + * @m_since_latest + * + * Expects that a file is opened. + * @see @ref skin2DForName() + */ + std::string skin2DName(UnsignedInt id); + + /** + * @brief Two-dimensional skin + * @param id Skin ID, from range [0, @ref skin2DCount()). + * @m_since_latest + * + * Returns given skin or @ref Containers::NullOpt if importing failed. + * Expects that a file is opened. + * @see @ref skin2D(const std::string&) + */ + Containers::Optional skin2D(UnsignedInt id); + + /** + * @brief Two-dimensional skin for given name + * @m_since_latest + * + * A convenience API combining @ref skin2DForName() and + * @ref skin2D(UnsignedInt). If @ref skin2DForName() returns + * @cpp -1 @ce, prints an error message and returns + * @ref Containers::NullOpt, otherwise propagates the result from + * @ref skin2D(UnsignedInt). Expects that a file is opened. + */ + Containers::Optional skin2D(const std::string& name); + + /** + * @brief Three-dimensional skin count + * @m_since_latest + * + * Expects that a file is opened. + */ + UnsignedInt skin3DCount() const; + + /** + * @brief Three-dimensional skin ID for given name + * @m_since_latest + * + * If no skin for given name exists, returns @cpp -1 @ce. Expects that + * a file is opened. + * @see @ref skin3DName(), @ref skin3D(const std::string&) + */ + Int skin3DForName(const std::string& name); + + /** + * @brief Three-dimensional skin name + * @param id Skin ID, from range [0, @ref skin3DCount()). + * @m_since_latest + * + * Expects that a file is opened. + * @see @ref skin3DForName() + */ + std::string skin3DName(UnsignedInt id); + + /** + * @brief Three-dimensional skin + * @param id Skin ID, from range [0, @ref skin3DCount()). + * @m_since_latest + * + * Returns given skin or @ref Containers::NullOpt if importing failed. + * Expects that a file is opened. + * @see @ref skin3D(const std::string&) + */ + Containers::Optional skin3D(UnsignedInt id); + + /** + * @brief Three-dimensional object for given name + * @m_since_latest + * + * A convenience API combining @ref skin3DForName() and + * @ref skin3D(UnsignedInt). If @ref skin3DForName() returns + * @cpp -1 @ce, prints an error message and returns + * @ref Containers::NullOpt, otherwise propagates the result from + * @ref skin3D(UnsignedInt). Expects that a file is opened. + */ + Containers::Optional skin3D(const std::string& name); + /** * @brief Mesh count * @m_since{2020,06} @@ -1519,6 +1623,66 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi /** @brief Implementation for @ref object3D() */ virtual Containers::Pointer doObject3D(UnsignedInt id); + /** + * @brief Implementation for @ref skin2DCount() + * @m_since_latest + * + * Default implementation returns @cpp 0 @ce. + */ + virtual UnsignedInt doSkin2DCount() const; + + /** + * @brief Implementation for @ref skin2DForName() + * @m_since_latest + * + * Default implementation returns @cpp -1 @ce. + */ + virtual Int doSkin2DForName(const std::string& name); + + /** + * @brief Implementation for @ref skin2DName() + * @m_since_latest + * + * Default implementation returns empty string. + */ + virtual std::string doSkin2DName(UnsignedInt id); + + /** + * @brief Implementation for @ref skin2D() + * @m_since_latest + */ + virtual Containers::Optional doSkin2D(UnsignedInt id); + + /** + * @brief Implementation for @ref skin3DCount() + * @m_since_latest + * + * Default implementation returns @cpp 0 @ce. + */ + virtual UnsignedInt doSkin3DCount() const; + + /** + * @brief Implementation for @ref skin3DForName() + * @m_since_latest + * + * Default implementation returns @cpp -1 @ce. + */ + virtual Int doSkin3DForName(const std::string& name); + + /** + * @brief Implementation for @ref skin3DName() + * @m_since_latest + * + * Default implementation returns empty string. + */ + virtual std::string doSkin3DName(UnsignedInt id); + + /** + * @brief Implementation for @ref skin3D() + * @m_since_latest + */ + virtual Containers::Optional doSkin3D(UnsignedInt id); + /** * @brief Implementation for @ref meshCount() * @m_since{2020,06} diff --git a/src/Magnum/Trade/Test/AbstractImporterTest.cpp b/src/Magnum/Trade/Test/AbstractImporterTest.cpp index 1035525ba..45a4c564b 100644 --- a/src/Magnum/Trade/Test/AbstractImporterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImporterTest.cpp @@ -44,6 +44,7 @@ #include "Magnum/Trade/MeshObjectData3D.h" #include "Magnum/Trade/PhongMaterialData.h" #include "Magnum/Trade/SceneData.h" +#include "Magnum/Trade/SkinData.h" #include "Magnum/Trade/TextureData.h" #ifdef MAGNUM_BUILD_DEPRECATED @@ -141,6 +142,18 @@ struct AbstractImporterTest: TestSuite::Tester { void object3DNotImplemented(); void object3DOutOfRange(); + void skin2D(); + void skin2DNameNotImplemented(); + void skin2DNameOutOfRange(); + void skin2DNotImplemented(); + void skin2DOutOfRange(); + + void skin3D(); + void skin3DNameNotImplemented(); + void skin3DNameOutOfRange(); + void skin3DNotImplemented(); + void skin3DOutOfRange(); + void mesh(); #ifdef MAGNUM_BUILD_DEPRECATED void meshDeprecatedFallback(); @@ -349,6 +362,18 @@ AbstractImporterTest::AbstractImporterTest() { &AbstractImporterTest::object3DNotImplemented, &AbstractImporterTest::object3DOutOfRange, + &AbstractImporterTest::skin2D, + &AbstractImporterTest::skin2DNameNotImplemented, + &AbstractImporterTest::skin2DNameOutOfRange, + &AbstractImporterTest::skin2DNotImplemented, + &AbstractImporterTest::skin2DOutOfRange, + + &AbstractImporterTest::skin3D, + &AbstractImporterTest::skin3DNameNotImplemented, + &AbstractImporterTest::skin3DNameOutOfRange, + &AbstractImporterTest::skin3DNotImplemented, + &AbstractImporterTest::skin3DOutOfRange, + &AbstractImporterTest::mesh, #ifdef MAGNUM_BUILD_DEPRECATED &AbstractImporterTest::meshDeprecatedFallback, @@ -1033,6 +1058,9 @@ void AbstractImporterTest::thingCountNotImplemented() { CORRADE_COMPARE(importer.object2DCount(), 0); CORRADE_COMPARE(importer.object3DCount(), 0); + CORRADE_COMPARE(importer.skin2DCount(), 0); + CORRADE_COMPARE(importer.skin3DCount(), 0); + CORRADE_COMPARE(importer.meshCount(), 0); CORRADE_COMPARE(importer.materialCount(), 0); CORRADE_COMPARE(importer.textureCount(), 0); @@ -1064,6 +1092,9 @@ void AbstractImporterTest::thingCountNoFile() { importer.object2DCount(); importer.object3DCount(); + importer.skin2DCount(); + importer.skin3DCount(); + importer.meshCount(); importer.meshLevelCount(7); importer.materialCount(); @@ -1081,12 +1112,16 @@ void AbstractImporterTest::thingCountNoFile() { "Trade::AbstractImporter::animationCount(): no file opened\n" "Trade::AbstractImporter::lightCount(): no file opened\n" "Trade::AbstractImporter::cameraCount(): no file opened\n" + "Trade::AbstractImporter::object2DCount(): no file opened\n" "Trade::AbstractImporter::object3DCount(): no file opened\n" + + "Trade::AbstractImporter::skin2DCount(): no file opened\n" + "Trade::AbstractImporter::skin3DCount(): no file opened\n" + "Trade::AbstractImporter::meshCount(): no file opened\n" "Trade::AbstractImporter::meshLevelCount(): no file opened\n" "Trade::AbstractImporter::materialCount(): no file opened\n" - "Trade::AbstractImporter::textureCount(): no file opened\n" "Trade::AbstractImporter::image1DCount(): no file opened\n" @@ -1112,6 +1147,9 @@ void AbstractImporterTest::thingForNameNotImplemented() { CORRADE_COMPARE(importer.object2DForName(""), -1); CORRADE_COMPARE(importer.object3DForName(""), -1); + CORRADE_COMPARE(importer.skin2DForName(""), -1); + CORRADE_COMPARE(importer.skin3DForName(""), -1); + CORRADE_COMPARE(importer.meshForName(""), -1); CORRADE_COMPARE(importer.materialForName(""), -1); CORRADE_COMPARE(importer.textureForName(""), -1); @@ -1143,6 +1181,9 @@ void AbstractImporterTest::thingForNameNoFile() { importer.object2DForName(""); importer.object3DForName(""); + importer.skin2DForName(""); + importer.skin3DForName(""); + importer.meshForName(""); importer.materialForName(""); importer.textureForName(""); @@ -1160,6 +1201,9 @@ void AbstractImporterTest::thingForNameNoFile() { "Trade::AbstractImporter::object2DForName(): no file opened\n" "Trade::AbstractImporter::object3DForName(): no file opened\n" + "Trade::AbstractImporter::skin2DForName(): no file opened\n" + "Trade::AbstractImporter::skin3DForName(): no file opened\n" + "Trade::AbstractImporter::meshForName(): no file opened\n" "Trade::AbstractImporter::materialForName(): no file opened\n" "Trade::AbstractImporter::textureForName(): no file opened\n" @@ -1192,6 +1236,9 @@ void AbstractImporterTest::thingByNameNotFound() { CORRADE_VERIFY(!importer.object2D("foobar")); CORRADE_VERIFY(!importer.object3D("foobar")); + CORRADE_VERIFY(!importer.skin2D("foobar")); + CORRADE_VERIFY(!importer.skin3D("foobar")); + CORRADE_VERIFY(!importer.mesh("foobar")); CORRADE_VERIFY(!importer.material("foobar")); CORRADE_VERIFY(!importer.texture("foobar")); @@ -1211,6 +1258,9 @@ void AbstractImporterTest::thingByNameNotFound() { "Trade::AbstractImporter::object2D(): object foobar not found\n" "Trade::AbstractImporter::object3D(): object foobar not found\n" + "Trade::AbstractImporter::skin2D(): skin foobar not found\n" + "Trade::AbstractImporter::skin3D(): skin foobar not found\n" + "Trade::AbstractImporter::mesh(): mesh foobar not found\n" "Trade::AbstractImporter::material(): material foobar not found\n" "Trade::AbstractImporter::texture(): texture foobar not found\n" @@ -1243,6 +1293,9 @@ void AbstractImporterTest::thingNameNoFile() { importer.object2DName(42); importer.object3DName(42); + importer.skin2DName(42); + importer.skin3DName(42); + importer.meshName(42); importer.materialName(42); importer.textureName(42); @@ -1256,8 +1309,13 @@ void AbstractImporterTest::thingNameNoFile() { "Trade::AbstractImporter::animationName(): no file opened\n" "Trade::AbstractImporter::lightName(): no file opened\n" "Trade::AbstractImporter::cameraName(): no file opened\n" + "Trade::AbstractImporter::object2DName(): no file opened\n" "Trade::AbstractImporter::object3DName(): no file opened\n" + + "Trade::AbstractImporter::skin2DName(): no file opened\n" + "Trade::AbstractImporter::skin3DName(): no file opened\n" + "Trade::AbstractImporter::meshName(): no file opened\n" "Trade::AbstractImporter::materialName(): no file opened\n" "Trade::AbstractImporter::textureName(): no file opened\n" @@ -1296,6 +1354,11 @@ void AbstractImporterTest::thingNoFile() { importer.object3D(42); importer.object3D("foo"); + importer.skin2D(42); + importer.skin2D("foo"); + importer.skin3D(42); + importer.skin3D("foo"); + importer.mesh(42); importer.mesh("foo"); importer.material(42); @@ -1328,6 +1391,11 @@ void AbstractImporterTest::thingNoFile() { "Trade::AbstractImporter::object3D(): no file opened\n" "Trade::AbstractImporter::object3D(): no file opened\n" + "Trade::AbstractImporter::skin2D(): no file opened\n" + "Trade::AbstractImporter::skin2D(): no file opened\n" + "Trade::AbstractImporter::skin3D(): no file opened\n" + "Trade::AbstractImporter::skin3D(): no file opened\n" + "Trade::AbstractImporter::mesh(): no file opened\n" "Trade::AbstractImporter::mesh(): no file opened\n" "Trade::AbstractImporter::material(): no file opened\n" @@ -2117,6 +2185,222 @@ void AbstractImporterTest::object3DOutOfRange() { CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::object3D(): index 8 out of range for 8 entries\n"); } +void AbstractImporterTest::skin2D() { + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSkin2DCount() const override { return 8; } + Int doSkin2DForName(const std::string& name) override { + if(name == "eighth") return 7; + return -1; + } + std::string doSkin2DName(UnsignedInt id) override { + if(id == 7) return "eighth"; + return {}; + } + Containers::Optional doSkin2D(UnsignedInt id) override { + if(id == 7) return SkinData2D{{}, {}, &state}; + return {}; + } + } importer; + + CORRADE_COMPARE(importer.skin2DCount(), 8); + CORRADE_COMPARE(importer.skin2DForName("eighth"), 7); + CORRADE_COMPARE(importer.skin2DName(7), "eighth"); + + { + auto data = importer.skin2D(7); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->importerState(), &state); + } { + auto data = importer.skin2D("eighth"); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->importerState(), &state); + } +} + +void AbstractImporterTest::skin2DNameNotImplemented() { + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSkin2DCount() const override { return 8; } + } importer; + + CORRADE_COMPARE(importer.skin2DName(7), ""); +} + +void AbstractImporterTest::skin2DNameOutOfRange() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSkin2DCount() const override { return 8; } + } importer; + + std::ostringstream out; + Error redirectError{&out}; + + importer.skin2DName(8); + CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::skin2DName(): index 8 out of range for 8 entries\n"); +} + +void AbstractImporterTest::skin2DNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSkin2DCount() const override { return 8; } + } importer; + + std::ostringstream out; + Error redirectError{&out}; + + importer.skin2D(7); + CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::skin2D(): not implemented\n"); +} + +void AbstractImporterTest::skin2DOutOfRange() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSkin2DCount() const override { return 8; } + } importer; + + std::ostringstream out; + Error redirectError{&out}; + + importer.skin2D(8); + CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::skin2D(): index 8 out of range for 8 entries\n"); +} + +void AbstractImporterTest::skin3D() { + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSkin3DCount() const override { return 8; } + Int doSkin3DForName(const std::string& name) override { + if(name == "eighth") return 7; + return -1; + } + std::string doSkin3DName(UnsignedInt id) override { + if(id == 7) return "eighth"; + return {}; + } + Containers::Optional doSkin3D(UnsignedInt id) override { + if(id == 7) return SkinData3D{{}, {}, &state}; + return {}; + } + } importer; + + CORRADE_COMPARE(importer.skin3DCount(), 8); + CORRADE_COMPARE(importer.skin3DForName("eighth"), 7); + CORRADE_COMPARE(importer.skin3DName(7), "eighth"); + + { + auto data = importer.skin3D(7); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->importerState(), &state); + } { + auto data = importer.skin3D("eighth"); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->importerState(), &state); + } +} + +void AbstractImporterTest::skin3DNameNotImplemented() { + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSkin3DCount() const override { return 8; } + } importer; + + CORRADE_COMPARE(importer.skin3DName(7), ""); +} + +void AbstractImporterTest::skin3DNameOutOfRange() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSkin3DCount() const override { return 8; } + } importer; + + std::ostringstream out; + Error redirectError{&out}; + + importer.skin3DName(8); + CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::skin3DName(): index 8 out of range for 8 entries\n"); +} + +void AbstractImporterTest::skin3DNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSkin3DCount() const override { return 8; } + } importer; + + std::ostringstream out; + Error redirectError{&out}; + + importer.skin3D(7); + CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::skin3D(): not implemented\n"); +} + +void AbstractImporterTest::skin3DOutOfRange() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSkin3DCount() const override { return 8; } + } importer; + + std::ostringstream out; + Error redirectError{&out}; + + importer.skin3D(8); + CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::skin3D(): index 8 out of range for 8 entries\n"); +} + void AbstractImporterTest::mesh() { struct: AbstractImporter { ImporterFeatures doFeatures() const override { return {}; } diff --git a/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp b/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp index b2a789627..4079dc39d 100644 --- a/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp +++ b/src/MagnumPlugins/AnyImageImporter/AnyImageImporter.cpp @@ -239,4 +239,4 @@ Containers::Optional AnyImageImporter::doImage2D(const UnsignedInt }} CORRADE_PLUGIN_REGISTER(AnyImageImporter, Magnum::Trade::AnyImageImporter, - "cz.mosra.magnum.Trade.AbstractImporter/0.3.2") + "cz.mosra.magnum.Trade.AbstractImporter/0.3.3") diff --git a/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.cpp b/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.cpp index 25048581b..b3d23b755 100644 --- a/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.cpp +++ b/src/MagnumPlugins/AnySceneImporter/AnySceneImporter.cpp @@ -245,4 +245,4 @@ Containers::Optional AnySceneImporter::doImage3D(const UnsignedInt }} CORRADE_PLUGIN_REGISTER(AnySceneImporter, Magnum::Trade::AnySceneImporter, - "cz.mosra.magnum.Trade.AbstractImporter/0.3.2") + "cz.mosra.magnum.Trade.AbstractImporter/0.3.3") diff --git a/src/MagnumPlugins/ObjImporter/ObjImporter.cpp b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp index f6ceb3b35..e22c89bdf 100644 --- a/src/MagnumPlugins/ObjImporter/ObjImporter.cpp +++ b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp @@ -486,4 +486,4 @@ Containers::Optional ObjImporter::doMesh(UnsignedInt id, UnsignedInt) }} CORRADE_PLUGIN_REGISTER(ObjImporter, Magnum::Trade::ObjImporter, - "cz.mosra.magnum.Trade.AbstractImporter/0.3.2") + "cz.mosra.magnum.Trade.AbstractImporter/0.3.3") diff --git a/src/MagnumPlugins/TgaImporter/TgaImporter.cpp b/src/MagnumPlugins/TgaImporter/TgaImporter.cpp index f37a236de..9b3a236d9 100644 --- a/src/MagnumPlugins/TgaImporter/TgaImporter.cpp +++ b/src/MagnumPlugins/TgaImporter/TgaImporter.cpp @@ -206,4 +206,4 @@ Containers::Optional TgaImporter::doImage2D(UnsignedInt, UnsignedIn }} CORRADE_PLUGIN_REGISTER(TgaImporter, Magnum::Trade::TgaImporter, - "cz.mosra.magnum.Trade.AbstractImporter/0.3.2") + "cz.mosra.magnum.Trade.AbstractImporter/0.3.3")