From d1dda87231eb56c82ad333adcfb5d49c191368b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 2 Sep 2021 18:26:28 +0200 Subject: [PATCH] Trade: add SceneField string mapping APIs to AbstractImporter. --- src/Magnum/Trade/AbstractImporter.cpp | 19 ++++++ src/Magnum/Trade/AbstractImporter.h | 49 +++++++++++++- src/Magnum/Trade/SceneData.h | 4 +- .../Trade/Test/AbstractImporterTest.cpp | 64 +++++++++++++++++++ 4 files changed, 134 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Trade/AbstractImporter.cpp b/src/Magnum/Trade/AbstractImporter.cpp index 3d7d95f7e..c470ac375 100644 --- a/src/Magnum/Trade/AbstractImporter.cpp +++ b/src/Magnum/Trade/AbstractImporter.cpp @@ -306,6 +306,25 @@ Containers::Optional AbstractImporter::scene(const std::string& name) return scene(id); /* not doScene(), so we get the range checks also */ } +SceneField AbstractImporter::sceneFieldForName(const std::string& name) { + const SceneField out = doSceneFieldForName(name); + CORRADE_ASSERT(out == SceneField{} || isSceneFieldCustom(out), + "Trade::AbstractImporter::sceneFieldForName(): implementation-returned" << out << "is neither custom nor invalid", {}); + return out; +} + +SceneField AbstractImporter::doSceneFieldForName(const std::string&) { + return {}; +} + +std::string AbstractImporter::sceneFieldName(SceneField name) { + CORRADE_ASSERT(isSceneFieldCustom(name), + "Trade::AbstractImporter::sceneFieldName():" << name << "is not custom", {}); + return doSceneFieldName(sceneFieldCustom(name)); +} + +std::string AbstractImporter::doSceneFieldName(UnsignedInt) { return {}; } + UnsignedInt AbstractImporter::animationCount() const { CORRADE_ASSERT(isOpened(), "Trade::AbstractImporter::animationCount(): no file opened", {}); return doAnimationCount(); diff --git a/src/Magnum/Trade/AbstractImporter.h b/src/Magnum/Trade/AbstractImporter.h index a1684f47a..47c240250 100644 --- a/src/Magnum/Trade/AbstractImporter.h +++ b/src/Magnum/Trade/AbstractImporter.h @@ -307,7 +307,9 @@ name doesn't exist. @ref object2DForName() / @ref object3DForName(), imported with @ref object2D(const std::string&) / @ref object3D(const std::string&) - Scene names using @ref sceneName() & @ref sceneForName(), imported with - @ref scene(const std::string&) + @ref scene(const std::string&). Scenes themselves can have custom fields, + for which the name mapping can be retrieved using @ref sceneFieldName() and + @ref sceneFieldForName(). - Skin names using @ref skin2DName() / @ref skin3DName() & @ref skin2DForName() / @ref skin3DForName(), imported with @ref skin2D(const std::string&) / @ref skin3D(const std::string&) @@ -763,6 +765,34 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi */ Containers::Optional scene(const std::string& name); + /** + * @brief Scene field for given name + * @m_since_latest + * + * If the name is not recognized, returns a zero (invalid) + * @ref SceneField, otherwise returns a custom scene field. Note that + * the value returned by this function may depend on whether a file is + * opened or not and also be different for different files --- see + * documentation of a particular importer for more information. + * @see @ref isSceneFieldCustom() + */ + SceneField sceneFieldForName(const std::string& name); + + /** + * @brief String name for given custom scene field + * @m_since_latest + * + * Given a custom @p name returned by @ref scene() in a @ref SceneData, + * returns a string identifier. If a string representation is not + * available or @p name is not recognized, returns an empty string. + * Expects that @p name is custom. Note that the value returned by + * this function may depend on whether a file is opened or not and also + * be different for different files --- see documentation of a + * particular importer for more information. + * @see @ref isSceneFieldCustom() + */ + std::string sceneFieldName(SceneField name); + /** * @brief Animation count * @@ -1759,6 +1789,23 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi /** @brief Implementation for @ref scene() */ virtual Containers::Optional doScene(UnsignedInt id); + /** + * @brief Implementation for @ref sceneFieldForName() + * @m_since_latest + * + * Default implementation returns an invalid (zero) value. + */ + virtual SceneField doSceneFieldForName(const std::string& name); + + /** + * @brief Implementation for @ref sceneFieldName() + * @m_since_latest + * + * Receives the custom ID extracted via @ref sceneFieldCustom(SceneField). + * Default implementation returns an empty string. + */ + virtual std::string doSceneFieldName(UnsignedInt name); + /** * @brief Implementation for @ref animationCount() * diff --git a/src/Magnum/Trade/SceneData.h b/src/Magnum/Trade/SceneData.h index 2eb7e2943..48569d955 100644 --- a/src/Magnum/Trade/SceneData.h +++ b/src/Magnum/Trade/SceneData.h @@ -83,7 +83,9 @@ MAGNUM_TRADE_EXPORT UnsignedInt sceneObjectTypeSize(SceneObjectType type); @m_since_latest See @ref SceneData for more information. -@see @ref SceneFieldData, @ref SceneFieldType +@see @ref SceneFieldData, @ref SceneFieldType, + @ref AbstractImporter::sceneFieldForName(), + @ref AbstractImporter::sceneFieldName() */ enum class SceneField: UnsignedInt { /* Zero used for an invalid value */ diff --git a/src/Magnum/Trade/Test/AbstractImporterTest.cpp b/src/Magnum/Trade/Test/AbstractImporterTest.cpp index 6f4f43f28..05deeba0f 100644 --- a/src/Magnum/Trade/Test/AbstractImporterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImporterTest.cpp @@ -115,6 +115,10 @@ struct AbstractImporterTest: TestSuite::Tester { void sceneNotImplemented(); void sceneOutOfRange(); + void sceneFieldName(); + void sceneFieldNameNotImplemented(); + void sceneFieldNameNotCustom(); + void animation(); void animationNameNotImplemented(); void animationForNameOutOfRange(); @@ -360,6 +364,10 @@ AbstractImporterTest::AbstractImporterTest() { &AbstractImporterTest::sceneNotImplemented, &AbstractImporterTest::sceneOutOfRange, + &AbstractImporterTest::sceneFieldName, + &AbstractImporterTest::sceneFieldNameNotImplemented, + &AbstractImporterTest::sceneFieldNameNotCustom, + &AbstractImporterTest::animation, &AbstractImporterTest::animationForNameOutOfRange, &AbstractImporterTest::animationNameNotImplemented, @@ -1757,6 +1765,62 @@ void AbstractImporterTest::sceneOutOfRange() { CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::scene(): index 8 out of range for 8 entries\n"); } +void AbstractImporterTest::sceneFieldName() { + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return false; } + void doClose() override {} + + SceneField doSceneFieldForName(const std::string& name) override { + if(name == "OctreeCell") return sceneFieldCustom(100037); + return SceneField{}; + } + + std::string doSceneFieldName(UnsignedInt id) override { + if(id == 100037) return "OctreeCell"; + return ""; + } + } importer; + + CORRADE_COMPARE(importer.sceneFieldForName("OctreeCell"), sceneFieldCustom(100037)); + CORRADE_COMPARE(importer.sceneFieldName(sceneFieldCustom(100037)), "OctreeCell"); +} + +void AbstractImporterTest::sceneFieldNameNotImplemented() { + struct: AbstractImporter { + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return false; } + void doClose() override {} + } importer; + + CORRADE_COMPARE(importer.sceneFieldForName(""), SceneField{}); + CORRADE_COMPARE(importer.sceneFieldName(sceneFieldCustom(100037)), ""); +} + +void AbstractImporterTest::sceneFieldNameNotCustom() { + #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 false; } + void doClose() override {} + + SceneField doSceneFieldForName(const std::string&) override { + return SceneField::Translation; + } + } importer; + + std::ostringstream out; + Error redirectError{&out}; + importer.sceneFieldForName("OctreeCell"); + importer.sceneFieldName(SceneField::Translation); + CORRADE_COMPARE(out.str(), + "Trade::AbstractImporter::sceneFieldForName(): implementation-returned Trade::SceneField::Translation is neither custom nor invalid\n" + "Trade::AbstractImporter::sceneFieldName(): Trade::SceneField::Translation is not custom\n"); +} + void AbstractImporterTest::animation() { struct: AbstractImporter { ImporterFeatures doFeatures() const override { return {}; }