diff --git a/src/Magnum/Trade/AbstractMaterialData.cpp b/src/Magnum/Trade/AbstractMaterialData.cpp index aeec37042..0a7a1e3b8 100644 --- a/src/Magnum/Trade/AbstractMaterialData.cpp +++ b/src/Magnum/Trade/AbstractMaterialData.cpp @@ -38,20 +38,6 @@ AbstractMaterialData::AbstractMaterialData(const MaterialType type, const Flags AbstractMaterialData::~AbstractMaterialData() = default; -Debug& operator<<(Debug& debug, const MaterialType value) { - debug << "Trade::MaterialType" << Debug::nospace; - - switch(value) { - /* LCOV_EXCL_START */ - #define _c(value) case MaterialType::value: return debug << "::" #value; - _c(Phong) - #undef _c - /* LCOV_EXCL_STOP */ - } - - return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; -} - Debug& operator<<(Debug& debug, const AbstractMaterialData::Flag value) { debug << "Trade::AbstractMaterialData::Flag" << Debug::nospace; diff --git a/src/Magnum/Trade/AbstractMaterialData.h b/src/Magnum/Trade/AbstractMaterialData.h index 37bc0ae28..b833bf740 100644 --- a/src/Magnum/Trade/AbstractMaterialData.h +++ b/src/Magnum/Trade/AbstractMaterialData.h @@ -29,22 +29,10 @@ * @brief Class @ref Magnum::Trade::AbstractMaterialData, enum @ref Magnum::Trade::MaterialType */ -#include - -#include "Magnum/Magnum.h" -#include "Magnum/Trade/visibility.h" +#include "Magnum/Trade/MaterialData.h" namespace Magnum { namespace Trade { -/** -@brief Material type - -@see @ref AbstractMaterialData::type() -*/ -enum class MaterialType: UnsignedByte { - Phong /**< Phong shading (see @ref PhongMaterialData) */ -}; - /** @brief Material alpha mode @@ -165,9 +153,6 @@ class MAGNUM_TRADE_EXPORT AbstractMaterialData { const void* _importerState; }; -/** @debugoperatorenum{MaterialType} */ -MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialType value); - /** @debugoperatorenum{MaterialAlphaMode} */ MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialAlphaMode value); diff --git a/src/Magnum/Trade/MaterialData.cpp b/src/Magnum/Trade/MaterialData.cpp index b33c4b394..727a5a4a5 100644 --- a/src/Magnum/Trade/MaterialData.cpp +++ b/src/Magnum/Trade/MaterialData.cpp @@ -27,6 +27,7 @@ #include #include +#include #include "Magnum/Math/Vector4.h" #include "Magnum/Math/Matrix.h" @@ -126,7 +127,7 @@ const void* MaterialAttributeData::value() const { return _data.data + Implementation::MaterialAttributeDataSize - materialAttributeTypeSize(_data.type); } -MaterialData::MaterialData(Containers::Array&& data, const void* const importerState) noexcept: _data{std::move(data)}, _importerState{importerState} { +MaterialData::MaterialData(const MaterialTypes types, Containers::Array&& data, const void* const importerState) noexcept: _data{std::move(data)}, _types{types}, _importerState{importerState} { #ifndef CORRADE_NO_ASSERT /* Not checking what's already done in MaterialAttributeData constructor. Done before sorting so the index refers to the actual input index. */ @@ -155,9 +156,9 @@ MaterialData::MaterialData(Containers::Array&& data, cons } } -MaterialData::MaterialData(const std::initializer_list data, const void* const importerState): MaterialData{Implementation::initializerListToArrayWithDefaultDeleter(data), importerState} {} +MaterialData::MaterialData(const MaterialTypes types, const std::initializer_list data, const void* const importerState): MaterialData{types, Implementation::initializerListToArrayWithDefaultDeleter(data), importerState} {} -MaterialData::MaterialData(DataFlags, const Containers::ArrayView data, const void* const importerState) noexcept: _data{Containers::Array{const_cast(data.data()), data.size(), [](MaterialAttributeData*, std::size_t){}}}, _importerState{importerState} { +MaterialData::MaterialData(const MaterialTypes types, DataFlags, const Containers::ArrayView data, const void* const importerState) noexcept: _data{Containers::Array{const_cast(data.data()), data.size(), [](MaterialAttributeData*, std::size_t){}}}, _types{types}, _importerState{importerState} { #ifndef CORRADE_NO_ASSERT /* Not checking what's already done in MaterialAttributeData constructor */ for(std::size_t i = 0; i != _data.size(); ++i) @@ -323,4 +324,24 @@ Debug& operator<<(Debug& debug, const MaterialAttributeType value) { return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedShort(value)) << Debug::nospace << ")"; } +Debug& operator<<(Debug& debug, const MaterialType value) { + debug << "Trade::MaterialType" << Debug::nospace; + + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case MaterialType::value: return debug << "::" #value; + _c(Phong) + #undef _c + /* LCOV_EXCL_STOP */ + } + + return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; +} + +Debug& operator<<(Debug& debug, const MaterialTypes value) { + return Containers::enumSetDebugOutput(debug, value, "Trade::MaterialTypes{}", { + MaterialType::Phong + }); +} + }} diff --git a/src/Magnum/Trade/MaterialData.h b/src/Magnum/Trade/MaterialData.h index d5ada0477..be54b499f 100644 --- a/src/Magnum/Trade/MaterialData.h +++ b/src/Magnum/Trade/MaterialData.h @@ -507,6 +507,32 @@ class MAGNUM_TRADE_EXPORT MaterialAttributeData { static_assert(sizeof(Storage) == Implementation::MaterialAttributeDataSize, "something is off, huh"); }; +/** +@brief Material type + +@see @ref MaterialTypes, @ref MaterialData::types(), + @ref AbstractMaterialData::type() +*/ +enum class MaterialType: UnsignedInt { + Phong = 1 << 0 /**< Phong shading */ +}; + +/** @debugoperatorenum{MaterialType} */ +MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialType value); + +/** +@brief Material types +@m_since_latest + +@see @ref MaterialData::types() +*/ +typedef Containers::EnumSet MaterialTypes; + +CORRADE_ENUMSET_OPERATORS(MaterialTypes) + +/** @debugoperatorenum{MaterialTypes} */ +MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialTypes value); + /** @brief Material data @m_since_latest @@ -543,19 +569,23 @@ class MAGNUM_TRADE_EXPORT MaterialData { public: /** * @brief Construct + * @param types Which material types are described by this + * data. Can be an empty set. * @param data Attribute data * @param importerState Importer-specific state * * The @p data gets sorted by name internally, expecting no duplicates. */ - explicit MaterialData(Containers::Array&& data, const void* importerState = nullptr) noexcept; + explicit MaterialData(MaterialTypes types, Containers::Array&& data, const void* importerState = nullptr) noexcept; /** @overload */ /* Not noexcept because allocation happens inside */ - explicit MaterialData(std::initializer_list data, const void* importerState = nullptr); + explicit MaterialData(MaterialTypes types, std::initializer_list data, const void* importerState = nullptr); /** * @brief Construct a non-owned material data + * @param types Which material types are described by this + * data. Can be an empty set. * @param dataFlags Ignored. Used only for a safer distinction * from the owning constructor. * @param data Attribute data @@ -564,7 +594,7 @@ class MAGNUM_TRADE_EXPORT MaterialData { * The @p data is expected to be already sorted by name, without * duplicates. */ - explicit MaterialData(DataFlags dataFlags, Containers::ArrayView data, const void* importerState = nullptr) noexcept; + explicit MaterialData(MaterialTypes types, DataFlags dataFlags, Containers::ArrayView data, const void* importerState = nullptr) noexcept; ~MaterialData(); @@ -580,6 +610,14 @@ class MAGNUM_TRADE_EXPORT MaterialData { /** @brief Move assignment */ MaterialData& operator=(MaterialData&&) noexcept; + /** + * @brief Material types + * + * Each type indicates that the material data can be interpreted as + * given type. For custom materials the set can also be empty. + */ + MaterialTypes types() const { return _types; } + /** * @brief Raw attribute data * @@ -731,6 +769,7 @@ class MAGNUM_TRADE_EXPORT MaterialData { UnsignedInt attributeFor(Containers::StringView name) const; Containers::Array _data; + MaterialTypes _types; const void* _importerState; }; diff --git a/src/Magnum/Trade/Test/MaterialDataTest.cpp b/src/Magnum/Trade/Test/MaterialDataTest.cpp index 14260820a..913dcc176 100644 --- a/src/Magnum/Trade/Test/MaterialDataTest.cpp +++ b/src/Magnum/Trade/Test/MaterialDataTest.cpp @@ -97,6 +97,7 @@ class MaterialDataTest: public TestSuite::Tester { void debugAttributeType(); void debugType(); + void debugTypes(); void debugFlag(); void debugFlags(); void debugAlphaMode(); @@ -186,6 +187,7 @@ MaterialDataTest::MaterialDataTest() { &MaterialDataTest::debugAttributeType, &MaterialDataTest::debugType, + &MaterialDataTest::debugTypes, &MaterialDataTest::debugFlag, &MaterialDataTest::debugFlags, &MaterialDataTest::debugAlphaMode, @@ -422,13 +424,14 @@ void MaterialDataTest::constructAttributeWrongAccessType() { void MaterialDataTest::construct() { int state; - MaterialData data{{ + MaterialData data{MaterialType::Phong, { {MaterialAttribute::DoubleSided, true}, {MaterialAttribute::DiffuseTextureCoordinates, 5u}, {"highlightColor", 0x335566ff_rgbaf}, {MaterialAttribute::AmbientTextureMatrix, Matrix3::scaling({0.5f, 1.0f})} }, &state}; + CORRADE_COMPARE(data.types(), MaterialType::Phong); CORRADE_COMPARE(data.attributeCount(), 4); CORRADE_COMPARE(data.data().size(), 4); CORRADE_COMPARE(data.importerState(), &state); @@ -509,7 +512,7 @@ void MaterialDataTest::constructEmptyAttribute() { std::ostringstream out; Error redirectError{&out}; - MaterialData{{ + MaterialData{{}, { {"DiffuseTexture"_s, 12u}, MaterialAttributeData{} }}; @@ -537,7 +540,7 @@ void MaterialDataTest::constructDuplicateAttribute() { std::ostringstream out; Error redirectError{&out}; - MaterialData data{std::move(attributes)}; + MaterialData data{{}, std::move(attributes)}; /* Because with graceful asserts it doesn't exit on error, the assertion might get printed multiple times */ CORRADE_COMPARE(Utility::String::partition(out.str(), '\n')[0], "Trade::MaterialData: duplicate attribute DiffuseTextureCoordinates"); @@ -549,7 +552,7 @@ void MaterialDataTest::constructFromImmutableSortedArray() { {"yay this is last"_s, Vector4{0.2f, 0.6f, 0.4f, 1.0f}} }; - MaterialData data{Containers::Array{const_cast(attributes), Containers::arraySize(attributes), [](MaterialAttributeData*, std::size_t) {}}}; + MaterialData data{{}, Containers::Array{const_cast(attributes), Containers::arraySize(attributes), [](MaterialAttributeData*, std::size_t) {}}}; CORRADE_COMPARE(data.attributeCount(), 2); CORRADE_COMPARE(data.attributeName(0), "hello this is first"); @@ -567,9 +570,10 @@ void MaterialDataTest::constructNonOwned() { }; int state; - MaterialData data{{}, attributes, &state}; + MaterialData data{MaterialType::Phong, {}, attributes, &state}; /* Expecting the same output as in construct() */ + CORRADE_COMPARE(data.types(), MaterialType::Phong); CORRADE_COMPARE(data.attributeCount(), 4); CORRADE_COMPARE(data.data().size(), 4); CORRADE_COMPARE(data.data().data(), attributes); @@ -598,7 +602,7 @@ void MaterialDataTest::constructNonOwnedEmptyAttribute() { std::ostringstream out; Error redirectError{&out}; /* nullptr to avoid attributes interpreted as importerState */ - MaterialData{{}, attributes, nullptr}; + MaterialData{{}, {}, attributes, nullptr}; CORRADE_COMPARE(out.str(), "Trade::MaterialData: attribute 1 doesn't specify anything\n"); } @@ -615,7 +619,7 @@ void MaterialDataTest::constructNonOwnedNotSorted() { std::ostringstream out; Error redirectError{&out}; /* nullptr to avoid attributes interpreted as importerState */ - MaterialData{{}, attributes, nullptr}; + MaterialData{{}, {}, attributes, nullptr}; CORRADE_COMPARE(out.str(), "Trade::MaterialData: DiffuseTexture has to be sorted before DiffuseTextureCoordinates if passing non-owned data\n"); } @@ -633,7 +637,7 @@ void MaterialDataTest::constructNonOwnedDuplicateAttribute() { std::ostringstream out; Error redirectError{&out}; /* nullptr to avoid attributes interpreted as importerState */ - MaterialData{{}, attributes, nullptr}; + MaterialData{{}, {}, attributes, nullptr}; CORRADE_COMPARE(out.str(), "Trade::MaterialData: duplicate attribute DiffuseTextureCoordinates\n"); } @@ -644,22 +648,24 @@ void MaterialDataTest::constructCopy() { void MaterialDataTest::constructMove() { int state; - MaterialData a{{ + MaterialData a{MaterialType::Phong, { {MaterialAttribute::DoubleSided, true}, {"boredomFactor", 5} }, &state}; MaterialData b{std::move(a)}; CORRADE_COMPARE(a.attributeCount(), 0); + CORRADE_COMPARE(b.types(), MaterialType::Phong); CORRADE_COMPARE(b.attributeCount(), 2); CORRADE_COMPARE(b.attributeName(0), "DoubleSided"); CORRADE_COMPARE(b.importerState(), &state); - MaterialData c{{ + MaterialData c{MaterialTypes{}, { {MaterialAttribute::AlphaMask, 0.5f} }}; c = std::move(b); CORRADE_COMPARE(b.attributeCount(), 1); + CORRADE_COMPARE(c.types(), MaterialType::Phong); CORRADE_COMPARE(c.attributeCount(), 2); CORRADE_COMPARE(c.attributeName(0), "DoubleSided"); CORRADE_COMPARE(c.importerState(), &state); @@ -669,7 +675,7 @@ void MaterialDataTest::constructMove() { } void MaterialDataTest::accessOptional() { - MaterialData data{{ + MaterialData data{{}, { {MaterialAttribute::AlphaMask, 0.5f}, {MaterialAttribute::SpecularTexture, 3u} }}; @@ -698,7 +704,7 @@ void MaterialDataTest::accessOutOfBounds() { CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif - MaterialData data{{ + MaterialData data{{}, { {MaterialAttribute::AlphaMask, 0.5f}, {MaterialAttribute::SpecularTexture, 3u} }}; @@ -721,7 +727,7 @@ void MaterialDataTest::accessInvalidAttributeName() { CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif - MaterialData data{}; + MaterialData data{{}, {}}; std::ostringstream out; Error redirectError{&out}; @@ -765,7 +771,7 @@ void MaterialDataTest::accessNotFound() { CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif - MaterialData data{{ + MaterialData data{{}, { {"DiffuseColor", 0xff3366aa_rgbaf} }}; @@ -789,7 +795,7 @@ void MaterialDataTest::accessWrongType() { CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif - MaterialData data{{ + MaterialData data{{}, { {"DiffuseColor", 0xff3366aa_rgbaf} }}; @@ -815,7 +821,7 @@ void MaterialDataTest::accessWrongType() { } void MaterialDataTest::release() { - MaterialData data{{ + MaterialData data{{}, { {"DiffuseColor", 0xff3366aa_rgbaf}, {MaterialAttribute::NormalTexture, 0u} }}; @@ -1103,6 +1109,13 @@ void MaterialDataTest::debugType() { CORRADE_COMPARE(out.str(), "Trade::MaterialType::Phong Trade::MaterialType(0xbe)\n"); } +void MaterialDataTest::debugTypes() { + std::ostringstream out; + + Debug{&out} << (MaterialType::Phong|MaterialType(0xe0)) << MaterialTypes{}; + CORRADE_COMPARE(out.str(), "Trade::MaterialType::Phong|Trade::MaterialType(0xe0) Trade::MaterialTypes{}\n"); +} + void MaterialDataTest::debugFlag() { std::ostringstream out; diff --git a/src/Magnum/Trade/Trade.h b/src/Magnum/Trade/Trade.h index 164ae036a..154dd4762 100644 --- a/src/Magnum/Trade/Trade.h +++ b/src/Magnum/Trade/Trade.h @@ -50,7 +50,7 @@ typedef CORRADE_DEPRECATED("use InputFileCallbackPolicy instead") InputFileCallb enum class MaterialAttribute: UnsignedInt; enum class MaterialAttributeType: UnsignedByte; -enum class MaterialType: UnsignedByte; +enum class MaterialType: UnsignedInt; enum class MaterialAlphaMode: UnsignedByte; class AbstractMaterialData; class MaterialAttributeData;