diff --git a/src/Magnum/Trade/MaterialData.cpp b/src/Magnum/Trade/MaterialData.cpp index 80be300c5..c7461c5f6 100644 --- a/src/Magnum/Trade/MaterialData.cpp +++ b/src/Magnum/Trade/MaterialData.cpp @@ -367,6 +367,14 @@ MaterialData::~MaterialData() = default; MaterialData& MaterialData::operator=(MaterialData&&) noexcept = default; +UnsignedInt MaterialData::attributeDataOffset(const UnsignedInt layer) const { + CORRADE_ASSERT(layer <= layerCount(), + "Trade::MaterialData::attributeDataOffset(): index" << layer << "out of range for" << layerCount() << "layers", {}); + if(!_layerOffsets) + return layer == 0 ? 0 : _data.size(); + return layer == 0 ? 0 : _layerOffsets[layer - 1]; +} + UnsignedInt MaterialData::findLayerIdInternal(const Containers::StringView layer) const { for(std::size_t i = 1; i < _layerOffsets.size(); ++i) { if(_layerOffsets[i] > _layerOffsets[i - 1] && diff --git a/src/Magnum/Trade/MaterialData.h b/src/Magnum/Trade/MaterialData.h index 555c945a8..d93888bec 100644 --- a/src/Magnum/Trade/MaterialData.h +++ b/src/Magnum/Trade/MaterialData.h @@ -2238,6 +2238,17 @@ class MAGNUM_TRADE_EXPORT MaterialData { return _layerOffsets.isEmpty() ? 1 : _layerOffsets.size(); } + /** + * @brief Offset of a layer inside attribute data + * + * Returns the offset where attributes for @p layer start in the array + * returned by @ref atttributeData() const. The @p layer is expected + * to be less *or equal to* @ref layerCount(), i.e. it's always + * possible to call this function with @cpp layer @ce and + * @cpp layer + 1 @ce to get the attribute range for given layer. + */ + UnsignedInt attributeDataOffset(UnsignedInt layer) const; + /** * @brief Whether a material has given named layer * @@ -2579,6 +2590,7 @@ class MAGNUM_TRADE_EXPORT MaterialData { * * The @p layer is expected to be smaller than @ref layerCount() const, * @p id is expected to be smaller than @ref attributeCount(UnsignedInt) const. + * @see @ref attributeDataOffset() */ const MaterialAttributeData& attributeData(UnsignedInt layer, UnsignedInt id) const; @@ -2586,6 +2598,7 @@ class MAGNUM_TRADE_EXPORT MaterialData { * @brief Raw attribute data in the base material * * The @p @p id is expected to be smaller than @ref attributeCount() const. + * @see @ref attributeDataOffset() */ const MaterialAttributeData& attributeData(UnsignedInt id) const { return attributeData(0, id); diff --git a/src/Magnum/Trade/Test/MaterialDataTest.cpp b/src/Magnum/Trade/Test/MaterialDataTest.cpp index a780cb422..d90a53f75 100644 --- a/src/Magnum/Trade/Test/MaterialDataTest.cpp +++ b/src/Magnum/Trade/Test/MaterialDataTest.cpp @@ -991,6 +991,9 @@ void MaterialDataTest::construct() { CORRADE_COMPARE(data.layerName(0), ""); CORRADE_VERIFY(!data.hasLayer("")); + CORRADE_COMPARE(data.attributeDataOffset(0), 0); + CORRADE_COMPARE(data.attributeDataOffset(1), 4); + /* Verify sorting */ CORRADE_COMPARE(data.attributeName(0), "AmbientTextureMatrix"); CORRADE_COMPARE(data.attributeName(1), "DiffuseTextureCoordinates"); @@ -1184,6 +1187,12 @@ void MaterialDataTest::constructLayers() { CORRADE_COMPARE(data.layerCount(), 4); CORRADE_COMPARE(data.layerData().size(), 4); + CORRADE_COMPARE(data.attributeDataOffset(0), 0); + CORRADE_COMPARE(data.attributeDataOffset(1), 2); + CORRADE_COMPARE(data.attributeDataOffset(2), 5); + CORRADE_COMPARE(data.attributeDataOffset(3), 5); + CORRADE_COMPARE(data.attributeDataOffset(4), 7); + CORRADE_COMPARE(data.attributeData().size(), 7); CORRADE_COMPARE(data.attributeCount(0), 2); CORRADE_COMPARE(data.attributeCount(1), 3); @@ -2580,8 +2589,12 @@ void MaterialDataTest::accessLayerOutOfBounds() { {MaterialAttribute::SpecularTexture, 3u} }, {0, 2}}; + /* This is fine */ + data.attributeDataOffset(2); + std::ostringstream out; Error redirectError{&out}; + data.attributeDataOffset(3); data.layerName(2); data.layerFactor(2); data.layerFactorTexture(2); @@ -2622,6 +2635,7 @@ void MaterialDataTest::accessLayerOutOfBounds() { data.attributeOr(2, "AlphaMask", false); data.attributeOr(2, MaterialAttribute::AlphaMask, false); CORRADE_COMPARE(out.str(), + "Trade::MaterialData::attributeDataOffset(): index 3 out of range for 2 layers\n" "Trade::MaterialData::layerName(): index 2 out of range for 2 layers\n" "Trade::MaterialData::layerFactor(): index 2 out of range for 2 layers\n" "Trade::MaterialData::layerFactorTexture(): index 2 out of range for 2 layers\n"