Browse Source

Trade: mutable access to MaterialData attribute values.

Hah, so many overloads. Not providing mutable access to keys or layer
offsets as that would break the invariant of the internal array always
being sorted.
pull/537/head
Vladimír Vondruš 5 years ago
parent
commit
78cf81bfca
  1. 9
      doc/snippets/MagnumTrade.cpp
  2. 100
      src/Magnum/Trade/MaterialData.cpp
  3. 315
      src/Magnum/Trade/MaterialData.h
  4. 87
      src/Magnum/Trade/MaterialLayerData.h
  5. 519
      src/Magnum/Trade/Test/MaterialDataTest.cpp

9
doc/snippets/MagnumTrade.cpp

@ -468,6 +468,15 @@ if(data.types() & Trade::MaterialType::PbrClearCoat) {
/* [MaterialData-usage-layers-types] */
}
{
Trade::MaterialData data{{}, {}};
/* [MaterialData-usage-mutable] */
Color4& color = data.mutableAttribute<Color4>(Trade::MaterialAttribute::BaseColor);
ColorHsv hsv = color.toHsv();
color.rgb() = Color3::fromHsv({hsv.hue, hsv.saturation*0.85f, hsv.value});
/* [MaterialData-usage-mutable] */
}
{
/* [MaterialData-populating] */
Trade::MaterialData data{Trade::MaterialType::PbrMetallicRoughness, {

100
src/Magnum/Trade/MaterialData.cpp

@ -203,7 +203,7 @@ template<> MAGNUM_TRADE_EXPORT Containers::StringView MaterialAttributeData::val
}
#endif
MaterialData::MaterialData(const MaterialTypes types, Containers::Array<MaterialAttributeData>&& attributeData, Containers::Array<UnsignedInt>&& layerData, const void* const importerState) noexcept: _data{std::move(attributeData)}, _layerOffsets{std::move(layerData)}, _types{types}, _importerState{importerState} {
MaterialData::MaterialData(const MaterialTypes types, Containers::Array<MaterialAttributeData>&& attributeData, Containers::Array<UnsignedInt>&& layerData, const void* const importerState) noexcept: _data{std::move(attributeData)}, _layerOffsets{std::move(layerData)}, _types{types}, _attributeDataFlags{DataFlag::Owned|DataFlag::Mutable}, _layerDataFlags{DataFlag::Owned|DataFlag::Mutable}, _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. */
@ -247,7 +247,14 @@ MaterialData::MaterialData(const MaterialTypes types, Containers::Array<Material
MaterialData::MaterialData(const MaterialTypes types, const std::initializer_list<MaterialAttributeData> attributeData, const std::initializer_list<UnsignedInt> layerData, const void* const importerState): MaterialData{types, Implementation::initializerListToArrayWithDefaultDeleter(attributeData), Implementation::initializerListToArrayWithDefaultDeleter(layerData), importerState} {}
MaterialData::MaterialData(const MaterialTypes types, DataFlags, const Containers::ArrayView<const MaterialAttributeData> attributeData, DataFlags, Containers::ArrayView<const UnsignedInt> layerData, const void* const importerState) noexcept: _data{Containers::Array<MaterialAttributeData>{const_cast<MaterialAttributeData*>(attributeData.data()), attributeData.size(), reinterpret_cast<void(*)(MaterialAttributeData*, std::size_t)>(Implementation::nonOwnedArrayDeleter)}}, _layerOffsets{Containers::Array<UnsignedInt>{const_cast<UnsignedInt*>(layerData.data()), layerData.size(), reinterpret_cast<void(*)(UnsignedInt*, std::size_t)>(Implementation::nonOwnedArrayDeleter)}}, _types{types}, _importerState{importerState} {
MaterialData::MaterialData(const MaterialTypes types, const DataFlags attributeDataFlags, const Containers::ArrayView<const MaterialAttributeData> attributeData, const DataFlags layerDataFlags, Containers::ArrayView<const UnsignedInt> layerData, const void* const importerState) noexcept: _data{Containers::Array<MaterialAttributeData>{const_cast<MaterialAttributeData*>(attributeData.data()), attributeData.size(), reinterpret_cast<void(*)(MaterialAttributeData*, std::size_t)>(Implementation::nonOwnedArrayDeleter)}}, _layerOffsets{Containers::Array<UnsignedInt>{const_cast<UnsignedInt*>(layerData.data()), layerData.size(), reinterpret_cast<void(*)(UnsignedInt*, std::size_t)>(Implementation::nonOwnedArrayDeleter)}}, _types{types}, _importerState{importerState} {
CORRADE_ASSERT(!(attributeDataFlags & DataFlag::Owned),
"Trade::MaterialData: can't construct with non-owned attribute data but" << attributeDataFlags, );
CORRADE_ASSERT(!(layerDataFlags & DataFlag::Owned),
"Trade::MaterialData: can't construct with non-owned layer data but" << layerDataFlags, );
_attributeDataFlags = attributeDataFlags;
_layerDataFlags = layerDataFlags;
#ifndef CORRADE_NO_ASSERT
/* Not checking what's already done in MaterialAttributeData constructor */
for(std::size_t i = 0; i != _data.size(); ++i)
@ -685,6 +692,16 @@ const void* MaterialData::attribute(const UnsignedInt layer, const UnsignedInt i
return _data[layerOffset(layer) + id].value();
}
void* MaterialData::mutableAttribute(const UnsignedInt layer, const UnsignedInt id) {
CORRADE_ASSERT(_attributeDataFlags & DataFlag::Mutable,
"Trade::MaterialData::mutableAttribute(): attribute data not mutable", {});
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::mutableAttribute(): index" << layer << "out of range for" << layerCount() << "layers", {});
CORRADE_ASSERT(id < attributeCount(layer),
"Trade::MaterialData::mutableAttribute(): index" << id << "out of range for" << attributeCount(layer) << "attributes in layer" << layer, {});
return const_cast<void*>(_data[layerOffset(layer) + id].value());
}
const void* MaterialData::attribute(const UnsignedInt layer, const Containers::StringView name) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::attribute(): index" << layer << "out of range for" << layerCount() << "layers", {});
@ -694,12 +711,29 @@ const void* MaterialData::attribute(const UnsignedInt layer, const Containers::S
return _data[layerOffset(layer) + id].value();
}
void* MaterialData::mutableAttribute(const UnsignedInt layer, const Containers::StringView name) {
CORRADE_ASSERT(_attributeDataFlags & DataFlag::Mutable,
"Trade::MaterialData::mutableAttribute(): attribute data not mutable", {});
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::mutableAttribute(): index" << layer << "out of range for" << layerCount() << "layers", {});
const UnsignedInt id = attributeFor(layer, name);
CORRADE_ASSERT(id != ~UnsignedInt{},
"Trade::MaterialData::mutableAttribute(): attribute" << name << "not found in layer" << layer, {});
return const_cast<void*>(_data[layerOffset(layer) + id].value());
}
const void* MaterialData::attribute(const UnsignedInt layer, const MaterialAttribute name) const {
const Containers::StringView string = attributeString(name);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << name, {});
return attribute(layer, string);
}
void* MaterialData::mutableAttribute(const UnsignedInt layer, const MaterialAttribute name) {
const Containers::StringView string = attributeString(name);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << name, {});
return mutableAttribute(layer, string);
}
const void* MaterialData::attribute(const Containers::StringView layer, const UnsignedInt id) const {
const UnsignedInt layerId = layerFor(layer);
CORRADE_ASSERT(layerId != ~UnsignedInt{},
@ -709,6 +743,17 @@ const void* MaterialData::attribute(const Containers::StringView layer, const Un
return _data[layerOffset(layerId) + id].value();
}
void* MaterialData::mutableAttribute(const Containers::StringView layer, const UnsignedInt id) {
CORRADE_ASSERT(_attributeDataFlags & DataFlag::Mutable,
"Trade::MaterialData::mutableAttribute(): attribute data not mutable", {});
const UnsignedInt layerId = layerFor(layer);
CORRADE_ASSERT(layerId != ~UnsignedInt{},
"Trade::MaterialData::mutableAttribute(): layer" << layer << "not found", {});
CORRADE_ASSERT(id < attributeCount(layer),
"Trade::MaterialData::mutableAttribute(): index" << id << "out of range for" << attributeCount(layer) << "attributes in layer" << layer, {});
return const_cast<void*>(_data[layerOffset(layerId) + id].value());
}
const void* MaterialData::attribute(const Containers::StringView layer, const Containers::StringView name) const {
const UnsignedInt layerId = layerFor(layer);
CORRADE_ASSERT(layerId != ~UnsignedInt{},
@ -719,30 +764,66 @@ const void* MaterialData::attribute(const Containers::StringView layer, const Co
return _data[layerOffset(layerId) + id].value();
}
void* MaterialData::mutableAttribute(const Containers::StringView layer, const Containers::StringView name) {
CORRADE_ASSERT(_attributeDataFlags & DataFlag::Mutable,
"Trade::MaterialData::mutableAttribute(): attribute data not mutable", {});
const UnsignedInt layerId = layerFor(layer);
CORRADE_ASSERT(layerId != ~UnsignedInt{},
"Trade::MaterialData::mutableAttribute(): layer" << layer << "not found", {});
const UnsignedInt id = attributeFor(layerId, name);
CORRADE_ASSERT(id != ~UnsignedInt{},
"Trade::MaterialData::mutableAttribute(): attribute" << name << "not found in layer" << layer, {});
return const_cast<void*>(_data[layerOffset(layerId) + id].value());
}
const void* MaterialData::attribute(const Containers::StringView layer, const MaterialAttribute name) const {
const Containers::StringView string = attributeString(name);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << name, {});
return attribute(layer, string);
}
void* MaterialData::mutableAttribute(const Containers::StringView layer, const MaterialAttribute name) {
const Containers::StringView string = attributeString(name);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << name, {});
return mutableAttribute(layer, string);
}
const void* MaterialData::attribute(const MaterialLayer layer, const UnsignedInt id) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute(string, id);
}
void* MaterialData::mutableAttribute(const MaterialLayer layer, const UnsignedInt id) {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << layer, {});
return mutableAttribute(string, id);
}
const void* MaterialData::attribute(const MaterialLayer layer, const Containers::StringView name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute(string, name);
}
void* MaterialData::mutableAttribute(const MaterialLayer layer, const Containers::StringView name) {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << layer, {});
return mutableAttribute(string, name);
}
const void* MaterialData::attribute(const MaterialLayer layer, const MaterialAttribute name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute(string, name);
}
void* MaterialData::mutableAttribute(const MaterialLayer layer, const MaterialAttribute name) {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << layer, {});
return mutableAttribute(string, name);
}
#ifndef DOXYGEN_GENERATING_OUTPUT
/* On Windows (MSVC, clang-cl and MinGw) it needs an explicit export otherwise
the symbol doesn't get exported. */
@ -758,6 +839,21 @@ template<> MAGNUM_TRADE_EXPORT Containers::StringView MaterialData::attribute<Co
"Trade::MaterialData::attribute():" << (data._data.data + 1) << "of" << data._data.type << "can't be retrieved as a string", {});
return {data._data.s.nameValue + Implementation::MaterialAttributeDataSize - data._data.s.size - 3, data._data.s.size, Containers::StringViewFlag::NullTerminated};
}
template<> MAGNUM_TRADE_EXPORT Containers::MutableStringView MaterialData::mutableAttribute<Containers::MutableStringView>(const UnsignedInt layer, const UnsignedInt id) {
CORRADE_ASSERT(_attributeDataFlags & DataFlag::Mutable,
"Trade::MaterialData::mutableAttribute(): attribute data not mutable", {});
/* Can't delegate to mutableAttribute() returning void* because that
doesn't include the size */
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::mutableAttribute(): index" << layer << "out of range for" << layerCount() << "layers", {});
CORRADE_ASSERT(id < attributeCount(layer),
"Trade::MaterialData::mutableAttribute(): index" << id << "out of range for" << attributeCount(layer) << "attributes in layer" << layer, {});
const Trade::MaterialAttributeData& data = _data[layerOffset(layer) + id];
CORRADE_ASSERT(data._data.type == MaterialAttributeType::String,
"Trade::MaterialData::mutableAttribute():" << (data._data.data + 1) << "of" << data._data.type << "can't be retrieved as a string", {});
return {const_cast<char*>(data._data.s.nameValue) + Implementation::MaterialAttributeDataSize - data._data.s.size - 3, data._data.s.size, Containers::StringViewFlag::NullTerminated};
}
#endif
const void* MaterialData::tryAttribute(const UnsignedInt layer, const Containers::StringView name) const {

315
src/Magnum/Trade/MaterialData.h

@ -38,6 +38,7 @@
#include "Magnum/Magnum.h"
#include "Magnum/Math/RectangularMatrix.h"
#include "Magnum/Trade/Data.h"
#include "Magnum/Trade/Trade.h"
#include "Magnum/Trade/visibility.h"
@ -1533,6 +1534,24 @@ accessor APIs. The above can be written in a more compact way using
@snippet MagnumTrade.cpp MaterialData-usage-layers-types
@subsection Trade-MaterialData-usage-mutable Mutable data access
The interfaces implicitly return attribute values by copy or through
@cpp const @ce views on the contained data through the @ref attributeData(),
@ref layerData() and @ref attribute() accessors. This is done because in
general case the data can also refer to a memory-mapped file or constant
memory. In cases when it's desirable to modify the attribute values in-place,
there's a set of @ref mutableAttribute() functions. To use these, you need to
check that the data are mutable using @ref attributeDataFlags() first. The
following snippet desaturates the base color of a PBR material:
@snippet MagnumTrade.cpp MaterialData-usage-mutable
Because the class internally expects the attribute data to be sorted and
partitioned into layers, it's not possible to modify attribute names,
add/remove attributes or change layer offsets --- only to edit values of
existing attributes.
@section Trade-MaterialData-populating Populating an instance
A @ref MaterialData instance by default takes over ownership of an
@ -1550,11 +1569,12 @@ internally sorted by name to allow a @f$ \mathcal{O}(\log n) @f$ lookup.
In addition to passing ownership of an array it's also possible to have the
@ref MaterialData instance refer to external data (for example in a
memory-mapped file, constant memory etc.). The additional second argument is
@ref DataFlags that's used only for safely disambiguating from the owning
constructor, and you'll pass a @ref Corrade::Containers::ArrayView instead of
an @ref Corrade::Containers::Array. Note that in this case, since the attribute
data is treated as immutable, you *have to* ensure the list is sorted by name.
memory-mapped file, constant memory etc.). Instead of moving in an
@relativeref{Corrade,Containers::Array} you pass @ref DataFlags describing if
the data is mutable or not together with an
@relativeref{Corrade,Containers::ArrayView}. Note that in this case, since the
attribute data is treated as immutable, you *have to* ensure the list is
already sorted by name.
@snippet MagnumTrade.cpp MaterialData-populating-non-owned
@ -1680,6 +1700,12 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*
* The @p attributeData gets sorted by name internally, expecting no
* duplicates.
*
* The @ref attributeDataFlags() / @ref layerDataFlags() are implicitly
* set to a combination of @ref DataFlag::Owned and
* @ref DataFlag::Mutable. For non-owned data use the
* @ref MaterialData(MaterialTypes, DataFlags, Containers::ArrayView<const MaterialAttributeData>, const void*)
* constructor instead.
*/
explicit MaterialData(MaterialTypes types, Containers::Array<MaterialAttributeData>&& attributeData, const void* importerState = nullptr) noexcept: MaterialData{types, std::move(attributeData), nullptr, importerState} {}
@ -1691,13 +1717,17 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @brief Construct a non-owned material data
* @param types Which material types are described by
* this data. Can be an empty set.
* @param attributeDataFlags Ignored. Used only for a safer
* distinction from the owning constructor.
* @param attributeDataFlags Attribute data flags
* @param attributeData Attribute data
* @param importerState Importer-specific state
*
* The @p attributeData is expected to be already sorted by name,
* without duplicates.
* Compared to @ref MaterialData(MaterialTypes, Containers::Array<MaterialAttributeData>&&, const void*)
* creates an instance that doesn't own the passed attribute data. The
* @p attributeData is expected to be already sorted by name, without
* duplicates. The @p attributeDataFlags can contain
* @ref DataFlag::Mutable to indicate the external data can be
* modified, and is expected to *not* have @ref DataFlag::Owned set.
* The @ref layerDataFlags() are implicitly set to empty @ref DataFlags.
*/
explicit MaterialData(MaterialTypes types, DataFlags attributeDataFlags, Containers::ArrayView<const MaterialAttributeData> attributeData, const void* importerState = nullptr) noexcept: MaterialData{types, attributeDataFlags, attributeData, {}, nullptr, importerState} {}
@ -1714,6 +1744,12 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* either empty or a monotonically non-decreasing sequence of offsets
* not larger than @p attributeData size, with *i*-th item specifying
* end offset of *i*-th layer.
*
* The @ref attributeDataFlags() / @ref layerDataFlags() are implicitly
* set to a combination of @ref DataFlag::Owned and
* @ref DataFlag::Mutable. For non-owned data use the
* @ref MaterialData(MaterialTypes, DataFlags, Containers::ArrayView<const MaterialAttributeData>, DataFlags, Containers::ArrayView<const UnsignedInt>, const void*)
* constructor instead.
*/
explicit MaterialData(MaterialTypes types, Containers::Array<MaterialAttributeData>&& attributeData, Containers::Array<UnsignedInt>&& layerData, const void* importerState = nullptr) noexcept;
@ -1725,19 +1761,21 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* @brief Construct a non-owned material data with layers
* @param types Which material types are described by
* this data. Can be an empty set.
* @param attributeDataFlags Ignored. Used only for a safer
* distinction from the owning constructor.
* @param attributeDataFlags Attribute data flags
* @param attributeData Attribute data
* @param layerDataFlags Ignored. Used only for a safer
* distinction from the owning constructor.
* @param layerDataFlags Layer offset data flags
* @param layerData Layer offset data
* @param importerState Importer-specific state
* @param importerState Importer-specific state
*
* The @p data is expected to be already sorted by name, without
* duplicates inside each layer. The @p layerData is expected to be
* either empty or a monotonically non-decreasing sequence of offsets
* not larger than @p attributeData size, with *i*-th item specifying
* end offset of *i*-th layer.
*
* The @p attributeDataFlags / @p layerDataFlags parameters can contain
* @ref DataFlag::Mutable to indicate the external data can be
* modified, and are expected to *not* have @ref DataFlag::Owned set.
*/
/* The second (ignored) DataFlags is present in order to make it ready
for a possible extension where only one of the data is non-owned.
@ -1758,6 +1796,27 @@ class MAGNUM_TRADE_EXPORT MaterialData {
/** @brief Move assignment */
MaterialData& operator=(MaterialData&&) noexcept;
/**
* @brief Attribute data flags
*¨
* Since the attribute list is always assumed to be sorted and
* partitioned into layers, only attribute values can be edited when
* the @ref DataFlag::Mutable flag is present.
* @see @ref releaseAttributeData(), @ref mutableAttribute()
*/
DataFlags attributeDataFlags() const { return _attributeDataFlags; }
/**
* @brief Layer data flags
*
* Since the attribute list is always assumed to be sorted and
* partitioned into layers, the @ref DataFlag::Mutable flag has no
* effect here --- only attribute values can be edited when
* @ref DataFlag::Mutable is present in @ref attributeDataFlags().
* @see @ref releaseLayerData()
*/
DataFlags layerDataFlags() const { return _layerDataFlags; }
/**
* @brief Material types
*
@ -2201,6 +2260,15 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*/
const void* attribute(UnsignedInt layer, UnsignedInt id) const;
/**
* @brief Type-erased mutable value of an attribute in given material layer
*
* Like @ref attribute(UnsignedInt, UnsignedInt) const but returns a
* mutable pointer. Expects that the material is mutable.
* @see @ref attributeDataFlags()
*/
void* mutableAttribute(UnsignedInt layer, UnsignedInt id);
/**
* @brief Type-erased value of a named attribute in given material layer
*
@ -2222,6 +2290,16 @@ class MAGNUM_TRADE_EXPORT MaterialData {
const void* attribute(UnsignedInt layer, Containers::StringView name) const;
const void* attribute(UnsignedInt layer, MaterialAttribute name) const; /**< @overload */
/**
* @brief Type-erased value of a named attribute in given material layer
*
* Like @ref attribute(UnsignedInt, Containers::StringView) const, but
* returns a mutable pointer. Expects that the material is mutable.
* @see @ref attributeDataFlags()
*/
void* mutableAttribute(UnsignedInt layer, Containers::StringView name);
void* mutableAttribute(UnsignedInt layer, MaterialAttribute name); /**< @overload */
/**
* @brief Type-erased value of an attribute in a named material layer
*
@ -2243,6 +2321,16 @@ class MAGNUM_TRADE_EXPORT MaterialData {
const void* attribute(Containers::StringView layer, UnsignedInt id) const;
const void* attribute(MaterialLayer layer, UnsignedInt id) const; /**< @overload */
/**
* @brief Type-erased mutable value of an attribute in a named material layer
*
* Like @ref attribute(Containers::StringView, UnsignedInt) const but
* returns a mutable pointer. Expects that the material is mutable.
* @see @ref attributeDataFlags()
*/
void* mutableAttribute(Containers::StringView layer, UnsignedInt id);
void* mutableAttribute(MaterialLayer layer, UnsignedInt id); /**< @overload */
/**
* @brief Type-erased value of a named attribute in a named material layer
*
@ -2266,6 +2354,18 @@ class MAGNUM_TRADE_EXPORT MaterialData {
const void* attribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */
const void* attribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */
/**
* @brief Type-erased mutable value of a named attribute in a named material layer
*
* Like @ref attribute(Containers::StringView, Containers::StringView) const
* but returns a mutable pointer. Expects that the material is mutable.
* @see @ref attributeDataFlags()
*/
void* mutableAttribute(Containers::StringView layer, Containers::StringView name);
void* mutableAttribute(Containers::StringView layer, MaterialAttribute name); /**< @overload */
void* mutableAttribute(MaterialLayer layer, Containers::StringView name); /**< @overload */
void* mutableAttribute(MaterialLayer layer, MaterialAttribute name); /**< @overload */
/**
* @brief Type-erased value of an attribute in the base material
*
@ -2276,6 +2376,17 @@ class MAGNUM_TRADE_EXPORT MaterialData {
return attribute(0, id);
}
/**
* @brief Type-erased mutable value of an attribute in the base material
*
* Like @ref attribute(UnsignedInt) const but returns a mutable
* pointer. Expects that the material is mutable.
* @see @ref attributeDataFlags()
*/
void* mutableAttribute(UnsignedInt id) {
return mutableAttribute(0, id);
}
/**
* @brief Type-erased value of a named attribute in the base material
*
@ -2289,6 +2400,20 @@ class MAGNUM_TRADE_EXPORT MaterialData {
return attribute(0, name);
} /**< @overload */
/**
* @brief Type-erased mutable value of a named attribute in the base material
*
* Like @ref attribute(Containers::StringView) const but returns a
* mutable pointer. Expects that the material is mutable.
* @see @ref attributeDataFlags()
*/
void* mutableAttribute(Containers::StringView name) {
return mutableAttribute(0, name);
}
void* mutableAttribute(MaterialAttribute name) {
return mutableAttribute(0, name);
} /**< @overload */
/**
* @brief Value of an attribute in given material layer
*
@ -2302,6 +2427,20 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*/
template<class T> T attribute(UnsignedInt layer, UnsignedInt id) const;
/**
* @brief Mutable value of an attribute in given material layer
*
* Like @ref attribute(UnsignedInt, UnsignedInt) const but returns a
* mutable reference. Expects that the material is mutable. In case of
* a string, you're expected to use
* @relativeref{Corrade,Containers::MutableStringView} instead of
* @relativeref{Corrade,Containers::StringView} for @p T and you get a
* @relativeref{Corrade,Containers::MutableStringView} back by-value,
* not by-reference. Changing the string size is not possible.
* @see @ref attributeDataFlags()
*/
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(UnsignedInt layer, UnsignedInt id);
/**
* @brief Value of a named attribute in given material layer
*
@ -2316,6 +2455,21 @@ class MAGNUM_TRADE_EXPORT MaterialData {
template<class T> T attribute(UnsignedInt layer, Containers::StringView name) const;
template<class T> T attribute(UnsignedInt layer, MaterialAttribute name) const; /**< @overload */
/**
* @brief Mutable value of a named attribute in given material layer
*
* Like @ref attribute(UnsignedInt, Containers::StringView) const but
* returns a mutable reference. Expects that the material is mutable.
* In case of a string, you're expected to use
* @relativeref{Corrade,Containers::MutableStringView} instead of
* @relativeref{Corrade,Containers::StringView} for @p T and you get a
* @relativeref{Corrade,Containers::MutableStringView} back by-value,
* not by-reference. Changing the string size is not possible.
* @see @ref attributeDataFlags()
*/
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(UnsignedInt layer, Containers::StringView name);
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(UnsignedInt layer, MaterialAttribute name); /**< @overload */
/**
* @brief Value of an attribute in a named material layer
*
@ -2331,6 +2485,21 @@ class MAGNUM_TRADE_EXPORT MaterialData {
template<class T> T attribute(Containers::StringView layer, UnsignedInt id) const;
template<class T> T attribute(MaterialLayer layer, UnsignedInt id) const; /**< @overload */
/**
* @brief Mutable value of an attribute in a named material layer
*
* Like @ref attribute(Containers::StringView, UnsignedInt) const but
* returns a mutable reference. Expects that the material is mutable.
* In case of a string, you're expected to use
* @relativeref{Corrade,Containers::MutableStringView} instead of
* @relativeref{Corrade,Containers::StringView} for @p T and you get a
* @relativeref{Corrade,Containers::MutableStringView} back by-value,
* not by-reference. Changing the string size is not possible.
* @see @ref attributeDataFlags()
*/
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(Containers::StringView layer, UnsignedInt id);
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(MaterialLayer layer, UnsignedInt id); /**< @overload */
/**
* @brief Value of a named attribute in a named material layer
*
@ -2347,6 +2516,23 @@ class MAGNUM_TRADE_EXPORT MaterialData {
template<class T> T attribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */
template<class T> T attribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */
/**
* @brief Mutable value of a named attribute in a named material layer
*
* Like @ref attribute(Containers::StringView, Containers::StringView) const
* but returns a mutable reference. Expects that the material is
* mutable. In case of a string, you're expected to use
* @relativeref{Corrade,Containers::MutableStringView} instead of
* @relativeref{Corrade,Containers::StringView} for @p T and you get a
* @relativeref{Corrade,Containers::MutableStringView} back by-value,
* not by-reference. Changing the string size is not possible.
* @see @ref attributeDataFlags()
*/
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(Containers::StringView layer, Containers::StringView name);
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(Containers::StringView layer, MaterialAttribute name); /**< @overload */
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(MaterialLayer layer, Containers::StringView name); /**< @overload */
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(MaterialLayer layer, MaterialAttribute name); /**< @overload */
/**
* @brief Value of an attribute in the base material
*
@ -2357,6 +2543,16 @@ class MAGNUM_TRADE_EXPORT MaterialData {
return attribute<T>(0, id);
}
/**
* @brief Mutable value of an attribute in the base material
*
* Equivalent to calling @ref mutableAttribute(UnsignedInt, UnsignedInt)
* with @p layer set to @cpp 0 @ce.
*/
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(UnsignedInt id) {
return mutableAttribute<T>(0, id);
}
/**
* @brief Value of a named attribute in the base material
*
@ -2370,6 +2566,19 @@ class MAGNUM_TRADE_EXPORT MaterialData {
return attribute<T>(0, name);
} /**< @overload */
/**
* @brief Mutable value of a named attribute in the base material
*
* Equivalent to calling @ref mutableAttribute(UnsignedInt, Containers::StringView)
* with @p layer set to @cpp 0 @ce.
*/
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(Containers::StringView name) {
return mutableAttribute<T>(0, name);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(MaterialAttribute name) {
return mutableAttribute<T>(0, name);
} /**< @overload */
/**
* @brief Type-erased attribute value in given material layer, if exists
*
@ -2545,7 +2754,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* has undefined behavior and might lead to crashes. This is done
* intentionally in order to simplify the interaction between this
* function and @ref releaseAttributeData().
* @see @ref layerData()
* @see @ref layerData(), @ref layerDataFlags()
*/
Containers::Array<UnsignedInt> releaseLayerData();
@ -2562,7 +2771,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
* has undefined behavior and might lead to crashes. This is done
* intentionally in order to simplify the interaction between this
* function and @ref releaseLayerData().
* @see @ref attributeData()
* @see @ref attributeData(), @ref attributeDataFlags()
*/
Containers::Array<MaterialAttributeData> releaseAttributeData();
@ -2591,6 +2800,8 @@ class MAGNUM_TRADE_EXPORT MaterialData {
Containers::Array<MaterialAttributeData> _data;
Containers::Array<UnsignedInt> _layerOffsets;
MaterialTypes _types;
DataFlags _attributeDataFlags, _layerDataFlags;
/* 2 bytes free */
const void* _importerState;
};
@ -2732,8 +2943,22 @@ template<class T> T MaterialData::attribute(const UnsignedInt layer, const Unsig
return *reinterpret_cast<const T*>(value);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type MaterialData::mutableAttribute(const UnsignedInt layer, const UnsignedInt id) {
void* const value = mutableAttribute(layer, id);
#ifdef CORRADE_GRACEFUL_ASSERT
if(!value) return *reinterpret_cast<T*>(this);
#endif
#ifndef CORRADE_NO_ASSERT
const Trade::MaterialAttributeData& data = _data[layerOffset(layer) + id];
#endif
CORRADE_ASSERT(Implementation::MaterialAttributeTypeFor<T>::type() == data._data.type,
"Trade::MaterialData::mutableAttribute():" << (data._data.data + 1) << "is" << data._data.type << "but requested a type equivalent to" << Implementation::MaterialAttributeTypeFor<T>::type(), *reinterpret_cast<T*>(this));
return *reinterpret_cast<T*>(value);
}
#ifndef DOXYGEN_GENERATING_OUTPUT
template<> Containers::StringView MaterialData::attribute<Containers::StringView>(UnsignedInt, UnsignedInt) const;
template<> Containers::MutableStringView MaterialData::mutableAttribute<Containers::MutableStringView>(UnsignedInt, UnsignedInt);
#endif
template<class T> T MaterialData::attribute(const UnsignedInt layer, const Containers::StringView name) const {
@ -2745,12 +2970,27 @@ template<class T> T MaterialData::attribute(const UnsignedInt layer, const Conta
return attribute<T>(layer, id);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type MaterialData::mutableAttribute(const UnsignedInt layer, const Containers::StringView name) {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::mutableAttribute(): index" << layer << "out of range for" << layerCount() << "layers", *reinterpret_cast<T*>(this));
const UnsignedInt id = attributeFor(layer, name);
CORRADE_ASSERT(id != ~UnsignedInt{},
"Trade::MaterialData::mutableAttribute(): attribute" << name << "not found in layer" << layer, *reinterpret_cast<T*>(this));
return mutableAttribute<T>(layer, id);
}
template<class T> T MaterialData::attribute(const UnsignedInt layer, const MaterialAttribute name) const {
const Containers::StringView string = attributeString(name);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << name, {});
return attribute<T>(layer, string);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type MaterialData::mutableAttribute(const UnsignedInt layer, const MaterialAttribute name) {
const Containers::StringView string = attributeString(name);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << name, *reinterpret_cast<T*>(this));
return mutableAttribute<T>(layer, string);
}
template<class T> T MaterialData::attribute(const Containers::StringView layer, const UnsignedInt id) const {
const UnsignedInt layerId = layerFor(layer);
CORRADE_ASSERT(layerId != ~UnsignedInt{},
@ -2760,6 +3000,15 @@ template<class T> T MaterialData::attribute(const Containers::StringView layer,
return attribute<T>(layerId, id);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type MaterialData::mutableAttribute(const Containers::StringView layer, const UnsignedInt id) {
const UnsignedInt layerId = layerFor(layer);
CORRADE_ASSERT(layerId != ~UnsignedInt{},
"Trade::MaterialData::mutableAttribute(): layer" << layer << "not found", *reinterpret_cast<T*>(this));
CORRADE_ASSERT(id < attributeCount(layer),
"Trade::MaterialData::mutableAttribute(): index" << id << "out of range for" << attributeCount(layer) << "attributes in layer" << layer, *reinterpret_cast<T*>(this));
return mutableAttribute<T>(layerId, id);
}
template<class T> T MaterialData::attribute(const Containers::StringView layer, const Containers::StringView name) const {
const UnsignedInt layerId = layerFor(layer);
CORRADE_ASSERT(layerId != ~UnsignedInt{},
@ -2770,30 +3019,64 @@ template<class T> T MaterialData::attribute(const Containers::StringView layer,
return attribute<T>(layerId, id);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type MaterialData::mutableAttribute(const Containers::StringView layer, const Containers::StringView name) {
const UnsignedInt layerId = layerFor(layer);
CORRADE_ASSERT(layerId != ~UnsignedInt{},
"Trade::MaterialData::mutableAttribute(): layer" << layer << "not found", *reinterpret_cast<T*>(this));
const UnsignedInt id = attributeFor(layerId, name);
CORRADE_ASSERT(id != ~UnsignedInt{},
"Trade::MaterialData::mutableAttribute(): attribute" << name << "not found in layer" << layer, *reinterpret_cast<T*>(this));
return mutableAttribute<T>(layerId, id);
}
template<class T> T MaterialData::attribute(const Containers::StringView layer, const MaterialAttribute name) const {
const Containers::StringView string = attributeString(name);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << name, {});
return attribute<T>(layer, string);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type MaterialData::mutableAttribute(const Containers::StringView layer, const MaterialAttribute name) {
const Containers::StringView string = attributeString(name);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << name, *reinterpret_cast<T*>(this));
return mutableAttribute<T>(layer, string);
}
template<class T> T MaterialData::attribute(const MaterialLayer layer, const UnsignedInt id) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute<T>(string, id);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type MaterialData::mutableAttribute(const MaterialLayer layer, const UnsignedInt id) {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << layer, *reinterpret_cast<T*>(this));
return mutableAttribute<T>(string, id);
}
template<class T> T MaterialData::attribute(const MaterialLayer layer, const Containers::StringView name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute<T>(string, name);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type MaterialData::mutableAttribute(const MaterialLayer layer, const Containers::StringView name) {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << layer, *reinterpret_cast<T*>(this));
return mutableAttribute<T>(string, name);
}
template<class T> T MaterialData::attribute(const MaterialLayer layer, const MaterialAttribute name) const {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {});
return attribute<T>(string, name);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type MaterialData::mutableAttribute(const MaterialLayer layer, const MaterialAttribute name) {
const Containers::StringView string = layerString(layer);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << layer, *reinterpret_cast<T*>(this));
return mutableAttribute<T>(string, name);
}
template<class T> Containers::Optional<T> MaterialData::tryAttribute(const UnsignedInt layer, const Containers::StringView name) const {
CORRADE_ASSERT(layer < layerCount(),
"Trade::MaterialData::tryAttribute(): index" << layer << "out of range for" << layerCount() << "layers", {});

87
src/Magnum/Trade/MaterialLayerData.h

@ -182,6 +182,21 @@ template<MaterialLayer layer> class MaterialLayerData: public MaterialData {
return MaterialData::attribute(layer, name);
} /**< @overload */
/**
* @brief Type-erased mutable value of an attribute in this layer
*
* Same as calling @ref MaterialData::mutableAttribute() with @p layer.
*/
void* mutableAttribute(UnsignedInt id) {
return MaterialData::mutableAttribute(layer, id);
}
void* mutableAttribute(Containers::StringView name) {
return MaterialData::mutableAttribute(layer, name);
} /**< @overload */
void* mutableAttribute(MaterialAttribute name) {
return MaterialData::mutableAttribute(layer, name);
} /**< @overload */
/**
* @brief Value of an attribute in this layer
*
@ -197,6 +212,21 @@ template<MaterialLayer layer> class MaterialLayerData: public MaterialData {
return MaterialData::attribute<T>(layer, name);
} /**< @overload */
/**
* @brief Mutable value of an attribute in this layer
*
* Same as calling @ref MaterialData::attribute() with @p layer.
*/
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(UnsignedInt id) {
return MaterialData::mutableAttribute<T>(layer, id);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(Containers::StringView name) {
return MaterialData::mutableAttribute<T>(layer, name);
} /**< @overload */
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(MaterialAttribute name) {
return MaterialData::mutableAttribute<T>(layer, name);
} /**< @overload */
/**
* @brief Type-erased attribute value in this layer, if exists
*
@ -257,6 +287,7 @@ template<MaterialLayer layer> class MaterialLayerData: public MaterialData {
using MaterialData::attributeName;
using MaterialData::attributeType;
using MaterialData::attribute;
using MaterialData::mutableAttribute;
using MaterialData::tryAttribute;
using MaterialData::attributeOr;
#else
@ -374,6 +405,34 @@ template<MaterialLayer layer> class MaterialLayerData: public MaterialData {
return MaterialData::attribute(layer_, name);
}
void* mutableAttribute(UnsignedInt layer_, UnsignedInt id) {
return MaterialData::mutableAttribute(layer_, id);
}
void* mutableAttribute(Containers::StringView layer_, UnsignedInt id) {
return MaterialData::mutableAttribute(layer_, id);
}
void* mutableAttribute(MaterialLayer layer_, UnsignedInt id) {
return MaterialData::mutableAttribute(layer_, id);
}
void* mutableAttribute(UnsignedInt layer_, Containers::StringView name) {
return MaterialData::mutableAttribute(layer_, name);
}
void* mutableAttribute(UnsignedInt layer_, MaterialAttribute name) {
return MaterialData::mutableAttribute(layer_, name);
}
void* mutableAttribute(Containers::StringView layer_, Containers::StringView name) {
return MaterialData::mutableAttribute(layer_, name);
}
void* mutableAttribute(Containers::StringView layer_, MaterialAttribute name) {
return MaterialData::mutableAttribute(layer_, name);
}
void* mutableAttribute(MaterialLayer layer_, Containers::StringView name) {
return MaterialData::mutableAttribute(layer_, name);
}
void* mutableAttribute(MaterialLayer layer_, MaterialAttribute name) {
return MaterialData::mutableAttribute(layer_, name);
}
template<class T> T attribute(UnsignedInt layer_, UnsignedInt id) const {
return MaterialData::attribute<T>(layer_, id);
}
@ -402,6 +461,34 @@ template<MaterialLayer layer> class MaterialLayerData: public MaterialData {
return MaterialData::attribute<T>(layer_, name);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(UnsignedInt layer_, UnsignedInt id) {
return MaterialData::mutableAttribute<T>(layer_, id);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(Containers::StringView layer_, UnsignedInt id) {
return MaterialData::mutableAttribute<T>(layer_, id);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(MaterialLayer layer_, UnsignedInt id) {
return MaterialData::mutableAttribute<T>(layer_, id);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(UnsignedInt layer_, Containers::StringView name) {
return MaterialData::mutableAttribute<T>(layer_, name);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(UnsignedInt layer_, MaterialAttribute name) {
return MaterialData::mutableAttribute<T>(layer_, name);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(Containers::StringView layer_, Containers::StringView name) {
return MaterialData::mutableAttribute<T>(layer_, name);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(Containers::StringView layer_, MaterialAttribute name) {
return MaterialData::mutableAttribute<T>(layer_, name);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(MaterialLayer layer_, Containers::StringView name) {
return MaterialData::mutableAttribute<T>(layer_, name);
}
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value, Containers::MutableStringView, T&>::type mutableAttribute(MaterialLayer layer_, MaterialAttribute name) {
return MaterialData::mutableAttribute<T>(layer_, name);
}
const void* tryAttribute(UnsignedInt layer_, Containers::StringView name) const {
return MaterialData::tryAttribute(layer_, name);
}

519
src/Magnum/Trade/Test/MaterialDataTest.cpp

@ -96,6 +96,8 @@ class MaterialDataTest: public TestSuite::Tester {
void constructNonOwnedDuplicateAttribute();
void constructNonOwnedLayersNotMonotonic();
void constructNonOwnedLayersOffsetOutOfBounds();
void constructNonOwnedAttributeFlagOwned();
void constructNonOwnedLayerFlagOwned();
void constructCopy();
void constructMove();
@ -107,6 +109,7 @@ class MaterialDataTest: public TestSuite::Tester {
void accessPointer();
void accessString();
void accessTextureSwizzle();
void accessMutable();
void accessOptional();
void accessOutOfBounds();
void accessNotFound();
@ -125,6 +128,9 @@ class MaterialDataTest: public TestSuite::Tester {
void accessLayerLayerNameInBaseMaterial();
void accessLayerEmptyLayer();
void accessLayerIndexMutable();
void accessLayerNameMutable();
void accessLayerStringMutable();
void accessLayerIndexOptional();
void accessLayerNameOptional();
void accessLayerStringOptional();
@ -135,11 +141,13 @@ class MaterialDataTest: public TestSuite::Tester {
void accessOutOfBoundsInLayerString();
void accessNotFoundInLayerIndex();
void accessNotFoundInLayerString();
void accessMutableNotAllowed();
void releaseAttributes();
void releaseLayers();
void templateLayerAccess();
void templateLayerAccessMutable();
void debugLayer();
void debugAttribute();
@ -232,6 +240,8 @@ MaterialDataTest::MaterialDataTest() {
&MaterialDataTest::constructNonOwnedDuplicateAttribute,
&MaterialDataTest::constructNonOwnedLayersNotMonotonic,
&MaterialDataTest::constructNonOwnedLayersOffsetOutOfBounds,
&MaterialDataTest::constructNonOwnedAttributeFlagOwned,
&MaterialDataTest::constructNonOwnedLayerFlagOwned,
&MaterialDataTest::constructCopy,
&MaterialDataTest::constructMove,
@ -243,6 +253,7 @@ MaterialDataTest::MaterialDataTest() {
&MaterialDataTest::accessPointer,
&MaterialDataTest::accessString,
&MaterialDataTest::accessTextureSwizzle,
&MaterialDataTest::accessMutable,
&MaterialDataTest::accessOptional,
&MaterialDataTest::accessOutOfBounds,
&MaterialDataTest::accessNotFound,
@ -261,6 +272,9 @@ MaterialDataTest::MaterialDataTest() {
&MaterialDataTest::accessLayerLayerNameInBaseMaterial,
&MaterialDataTest::accessLayerEmptyLayer,
&MaterialDataTest::accessLayerIndexMutable,
&MaterialDataTest::accessLayerNameMutable,
&MaterialDataTest::accessLayerStringMutable,
&MaterialDataTest::accessLayerIndexOptional,
&MaterialDataTest::accessLayerNameOptional,
&MaterialDataTest::accessLayerStringOptional,
@ -271,11 +285,13 @@ MaterialDataTest::MaterialDataTest() {
&MaterialDataTest::accessOutOfBoundsInLayerString,
&MaterialDataTest::accessNotFoundInLayerIndex,
&MaterialDataTest::accessNotFoundInLayerString,
&MaterialDataTest::accessMutableNotAllowed,
&MaterialDataTest::releaseAttributes,
&MaterialDataTest::releaseLayers,
&MaterialDataTest::templateLayerAccess,
&MaterialDataTest::templateLayerAccessMutable,
&MaterialDataTest::debugLayer,
&MaterialDataTest::debugAttribute,
@ -799,6 +815,8 @@ void MaterialDataTest::construct() {
{MaterialAttribute::AmbientTextureMatrix, Matrix3::scaling({0.5f, 1.0f})}
}, &state};
CORRADE_COMPARE(data.attributeDataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_COMPARE(data.layerDataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_COMPARE(data.types(), MaterialType::Phong);
CORRADE_COMPARE(data.layerCount(), 1);
CORRADE_VERIFY(!data.layerData());
@ -825,11 +843,19 @@ void MaterialDataTest::construct() {
CORRADE_COMPARE(data.attribute<UnsignedInt>(1), 5);
CORRADE_COMPARE(data.attribute<bool>(2), true);
CORRADE_COMPARE(data.attribute<Color4>(3), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.mutableAttribute<Matrix3>(0), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(data.mutableAttribute<UnsignedInt>(1), 5);
CORRADE_COMPARE(data.mutableAttribute<bool>(2), true);
CORRADE_COMPARE(data.mutableAttribute<Color4>(3), 0x335566ff_rgbaf);
CORRADE_COMPARE(*static_cast<const Matrix3*>(data.attribute(0)), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute(1)), 5);
CORRADE_COMPARE(*static_cast<const bool*>(data.attribute(2)), true);
CORRADE_COMPARE(*static_cast<const Color4*>(data.attribute(3)), 0x335566ff_rgbaf);
CORRADE_COMPARE(*static_cast<Matrix3*>(data.mutableAttribute(0)), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(*static_cast<UnsignedInt*>(data.mutableAttribute(1)), 5);
CORRADE_COMPARE(*static_cast<bool*>(data.mutableAttribute(2)), true);
CORRADE_COMPARE(*static_cast<Color4*>(data.mutableAttribute(3)), 0x335566ff_rgbaf);
/* Access by name */
CORRADE_VERIFY(data.hasAttribute(MaterialAttribute::DoubleSided));
@ -847,10 +873,16 @@ void MaterialDataTest::construct() {
CORRADE_COMPARE(data.attribute<Matrix3>(MaterialAttribute::AmbientTextureMatrix), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(data.attribute<UnsignedInt>(MaterialAttribute::DiffuseTextureCoordinates), 5);
CORRADE_COMPARE(data.attribute<bool>(MaterialAttribute::DoubleSided), true);
CORRADE_COMPARE(data.mutableAttribute<Matrix3>(MaterialAttribute::AmbientTextureMatrix), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(data.mutableAttribute<UnsignedInt>(MaterialAttribute::DiffuseTextureCoordinates), 5);
CORRADE_COMPARE(data.mutableAttribute<bool>(MaterialAttribute::DoubleSided), true);
CORRADE_COMPARE(*static_cast<const Matrix3*>(data.attribute(MaterialAttribute::AmbientTextureMatrix)), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute(MaterialAttribute::DiffuseTextureCoordinates)), 5);
CORRADE_COMPARE(*static_cast<const bool*>(data.attribute(MaterialAttribute::DoubleSided)), true);
CORRADE_COMPARE(*static_cast<Matrix3*>(data.mutableAttribute(MaterialAttribute::AmbientTextureMatrix)), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(*static_cast<UnsignedInt*>(data.mutableAttribute(MaterialAttribute::DiffuseTextureCoordinates)), 5);
CORRADE_COMPARE(*static_cast<bool*>(data.mutableAttribute(MaterialAttribute::DoubleSided)), true);
/* Access by string */
CORRADE_VERIFY(data.hasAttribute("DoubleSided"));
@ -871,11 +903,19 @@ void MaterialDataTest::construct() {
CORRADE_COMPARE(data.attribute<UnsignedInt>("DiffuseTextureCoordinates"), 5);
CORRADE_COMPARE(data.attribute<bool>("DoubleSided"), true);
CORRADE_COMPARE(data.attribute<Color4>("highlightColor"), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.mutableAttribute<Matrix3>("AmbientTextureMatrix"), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(data.mutableAttribute<UnsignedInt>("DiffuseTextureCoordinates"), 5);
CORRADE_COMPARE(data.mutableAttribute<bool>("DoubleSided"), true);
CORRADE_COMPARE(data.mutableAttribute<Color4>("highlightColor"), 0x335566ff_rgbaf);
CORRADE_COMPARE(*static_cast<const Matrix3*>(data.attribute("AmbientTextureMatrix")), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute("DiffuseTextureCoordinates")), 5);
CORRADE_COMPARE(*static_cast<const bool*>(data.attribute("DoubleSided")), true);
CORRADE_COMPARE(*static_cast<const Color4*>(data.attribute("highlightColor")), 0x335566ff_rgbaf);
CORRADE_COMPARE(*static_cast<Matrix3*>(data.mutableAttribute("AmbientTextureMatrix")), Matrix3::scaling({0.5f, 1.0f}));
CORRADE_COMPARE(*static_cast<UnsignedInt*>(data.mutableAttribute("DiffuseTextureCoordinates")), 5);
CORRADE_COMPARE(*static_cast<bool*>(data.mutableAttribute("DoubleSided")), true);
CORRADE_COMPARE(*static_cast<Color4*>(data.mutableAttribute("highlightColor")), 0x335566ff_rgbaf);
}
void MaterialDataTest::constructEmptyAttribute() {
@ -952,6 +992,8 @@ void MaterialDataTest::constructLayers() {
2, 5, 5, 7
}, &state};
CORRADE_COMPARE(data.attributeDataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_COMPARE(data.layerDataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_COMPARE(data.types(), MaterialType::Phong);
CORRADE_COMPARE(data.importerState(), &state);
@ -999,10 +1041,16 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(data.attribute<UnsignedInt>(0, 0), 5);
CORRADE_COMPARE(data.attribute<Color4>(1, 2), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.attribute<Float>(3, 1), 0.015f);
CORRADE_COMPARE(data.mutableAttribute<UnsignedInt>(0, 0), 5);
CORRADE_COMPARE(data.mutableAttribute<Color4>(1, 2), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.mutableAttribute<Float>(3, 1), 0.015f);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute(0, 0)), 5);
CORRADE_COMPARE(*static_cast<const Color4*>(data.attribute(1, 2)), 0x335566ff_rgbaf);
CORRADE_COMPARE(*static_cast<const Float*>(data.attribute(3, 1)), 0.015f);
CORRADE_COMPARE(*static_cast<UnsignedInt*>(data.mutableAttribute(0, 0)), 5);
CORRADE_COMPARE(*static_cast<Color4*>(data.mutableAttribute(1, 2)), 0x335566ff_rgbaf);
CORRADE_COMPARE(*static_cast<Float*>(data.mutableAttribute(3, 1)), 0.015f);
/* Access by layer ID and attribute name */
CORRADE_VERIFY(data.hasAttribute(0, MaterialAttribute::DiffuseTextureCoordinates));
@ -1027,11 +1075,19 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(data.attribute<bool>(1, MaterialAttribute::AlphaBlend), true);
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, MaterialAttribute::LayerName), "ClearCoat");
CORRADE_COMPARE(data.attribute<UnsignedInt>(3, MaterialAttribute::NormalTexture), 3);
CORRADE_COMPARE(data.mutableAttribute<UnsignedInt>(0, MaterialAttribute::DiffuseTextureCoordinates), 5);
CORRADE_COMPARE(data.mutableAttribute<bool>(1, MaterialAttribute::AlphaBlend), true);
CORRADE_COMPARE(data.mutableAttribute<Containers::MutableStringView>(1, MaterialAttribute::LayerName), "ClearCoat"_s);
CORRADE_COMPARE(data.mutableAttribute<UnsignedInt>(3, MaterialAttribute::NormalTexture), 3);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute(0, MaterialAttribute::DiffuseTextureCoordinates)), 5);
CORRADE_COMPARE(*static_cast<const bool*>(data.attribute(1, MaterialAttribute::AlphaBlend)), true);
CORRADE_COMPARE(static_cast<const char*>(data.attribute(1, MaterialAttribute::LayerName)), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute(3, MaterialAttribute::NormalTexture)), 3);
CORRADE_COMPARE(*static_cast<UnsignedInt*>(data.mutableAttribute(0, MaterialAttribute::DiffuseTextureCoordinates)), 5);
CORRADE_COMPARE(*static_cast<bool*>(data.mutableAttribute(1, MaterialAttribute::AlphaBlend)), true);
CORRADE_COMPARE(static_cast<char*>(data.mutableAttribute(1, MaterialAttribute::LayerName)), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<UnsignedInt*>(data.mutableAttribute(3, MaterialAttribute::NormalTexture)), 3);
/* Access by layer ID and attribute string */
CORRADE_VERIFY(data.hasAttribute(0, "DoubleSided"));
@ -1056,11 +1112,19 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(data.attribute<Color4>(1, "highlightColor"), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, "$LayerName"), "ClearCoat");
CORRADE_COMPARE(data.attribute<UnsignedInt>(3, "NormalTexture"), 3);
CORRADE_COMPARE(data.mutableAttribute<bool>(0, "DoubleSided"), true);
CORRADE_COMPARE(data.mutableAttribute<Color4>(1, "highlightColor"), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.mutableAttribute<Containers::MutableStringView>(1, "$LayerName"), "ClearCoat"_s);
CORRADE_COMPARE(data.mutableAttribute<UnsignedInt>(3, "NormalTexture"), 3);
CORRADE_COMPARE(*static_cast<const bool*>(data.attribute(0, "DoubleSided")), true);
CORRADE_COMPARE(*static_cast<const Color4*>(data.attribute(1, "highlightColor")), 0x335566ff_rgbaf);
CORRADE_COMPARE(static_cast<const char*>(data.attribute(1, "$LayerName")), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute(3, "NormalTexture")), 3);
CORRADE_COMPARE(*static_cast<bool*>(data.mutableAttribute(0, "DoubleSided")), true);
CORRADE_COMPARE(*static_cast<Color4*>(data.mutableAttribute(1, "highlightColor")), 0x335566ff_rgbaf);
CORRADE_COMPARE(static_cast<char*>(data.mutableAttribute(1, "$LayerName")), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<UnsignedInt*>(data.mutableAttribute(3, "NormalTexture")), 3);
/* Access by layer name and attribute ID */
CORRADE_COMPARE(data.attributeName(MaterialLayer::ClearCoat, 1), "AlphaBlend");
@ -1071,9 +1135,13 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(data.attribute<bool>(MaterialLayer::ClearCoat, 1), true);
CORRADE_COMPARE(data.attribute<Color4>(MaterialLayer::ClearCoat, 2), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.mutableAttribute<bool>(MaterialLayer::ClearCoat, 1), true);
CORRADE_COMPARE(data.mutableAttribute<Color4>(MaterialLayer::ClearCoat, 2), 0x335566ff_rgbaf);
CORRADE_COMPARE(*static_cast<const bool*>(data.attribute(MaterialLayer::ClearCoat, 1)), true);
CORRADE_COMPARE(*static_cast<const Color4*>(data.attribute(MaterialLayer::ClearCoat, 2)), 0x335566ff_rgbaf);
CORRADE_COMPARE(*static_cast<bool*>(data.mutableAttribute(MaterialLayer::ClearCoat, 1)), true);
CORRADE_COMPARE(*static_cast<Color4*>(data.mutableAttribute(MaterialLayer::ClearCoat, 2)), 0x335566ff_rgbaf);
/* Access by layer name and attribute name */
CORRADE_VERIFY(data.hasAttribute(MaterialLayer::ClearCoat, MaterialAttribute::AlphaBlend));
@ -1087,9 +1155,13 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(data.attribute<bool>(MaterialLayer::ClearCoat, MaterialAttribute::AlphaBlend), true);
CORRADE_COMPARE(data.attribute<Containers::StringView>(MaterialLayer::ClearCoat, MaterialAttribute::LayerName), "ClearCoat");
CORRADE_COMPARE(data.mutableAttribute<bool>(MaterialLayer::ClearCoat, MaterialAttribute::AlphaBlend), true);
CORRADE_COMPARE(data.mutableAttribute<Containers::MutableStringView>(MaterialLayer::ClearCoat, MaterialAttribute::LayerName), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<const bool*>(data.attribute(MaterialLayer::ClearCoat, MaterialAttribute::AlphaBlend)), true);
CORRADE_COMPARE(static_cast<const char*>(data.attribute(MaterialLayer::ClearCoat, MaterialAttribute::LayerName)), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<bool*>(data.mutableAttribute(MaterialLayer::ClearCoat, MaterialAttribute::AlphaBlend)), true);
CORRADE_COMPARE(static_cast<char*>(data.mutableAttribute(MaterialLayer::ClearCoat, MaterialAttribute::LayerName)), "ClearCoat"_s);
/* Access by layer name and attribute string */
CORRADE_VERIFY(data.hasAttribute(MaterialLayer::ClearCoat, "highlightColor"));
@ -1103,9 +1175,13 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(data.attribute<Color4>(MaterialLayer::ClearCoat, "highlightColor"), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.attribute<Containers::StringView>(MaterialLayer::ClearCoat, "$LayerName"), "ClearCoat");
CORRADE_COMPARE(data.mutableAttribute<Color4>(MaterialLayer::ClearCoat, "highlightColor"), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.mutableAttribute<Containers::MutableStringView>(MaterialLayer::ClearCoat, "$LayerName"), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<const Color4*>(data.attribute(MaterialLayer::ClearCoat, "highlightColor")), 0x335566ff_rgbaf);
CORRADE_COMPARE(static_cast<const char*>(data.attribute(MaterialLayer::ClearCoat, "$LayerName")), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<Color4*>(data.mutableAttribute(MaterialLayer::ClearCoat, "highlightColor")), 0x335566ff_rgbaf);
CORRADE_COMPARE(static_cast<char*>(data.mutableAttribute(MaterialLayer::ClearCoat, "$LayerName")), "ClearCoat"_s);
/* Access by layer string and attribute ID */
CORRADE_COMPARE(data.attributeName("ClearCoat", 1), "AlphaBlend");
@ -1116,9 +1192,13 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(data.attribute<bool>("ClearCoat", 1), true);
CORRADE_COMPARE(data.attribute<Color4>("ClearCoat", 2), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.mutableAttribute<bool>("ClearCoat", 1), true);
CORRADE_COMPARE(data.mutableAttribute<Color4>("ClearCoat", 2), 0x335566ff_rgbaf);
CORRADE_COMPARE(*static_cast<const bool*>(data.attribute("ClearCoat", 1)), true);
CORRADE_COMPARE(*static_cast<const Color4*>(data.attribute("ClearCoat", 2)), 0x335566ff_rgbaf);
CORRADE_COMPARE(*static_cast<bool*>(data.mutableAttribute("ClearCoat", 1)), true);
CORRADE_COMPARE(*static_cast<Color4*>(data.mutableAttribute("ClearCoat", 2)), 0x335566ff_rgbaf);
/* Access by layer string and attribute name */
CORRADE_VERIFY(data.hasAttribute("ClearCoat", MaterialAttribute::AlphaBlend));
@ -1132,9 +1212,13 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(data.attribute<bool>("ClearCoat", MaterialAttribute::AlphaBlend), true);
CORRADE_COMPARE(data.attribute<Containers::StringView>("ClearCoat", MaterialAttribute::LayerName), "ClearCoat");
CORRADE_COMPARE(data.mutableAttribute<bool>("ClearCoat", MaterialAttribute::AlphaBlend), true);
CORRADE_COMPARE(data.mutableAttribute<Containers::MutableStringView>("ClearCoat", MaterialAttribute::LayerName), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<const bool*>(data.attribute("ClearCoat", MaterialAttribute::AlphaBlend)), true);
CORRADE_COMPARE(static_cast<const char*>(data.attribute("ClearCoat", MaterialAttribute::LayerName)), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<bool*>(data.mutableAttribute("ClearCoat", MaterialAttribute::AlphaBlend)), true);
CORRADE_COMPARE(static_cast<char*>(data.mutableAttribute("ClearCoat", MaterialAttribute::LayerName)), "ClearCoat"_s);
/* Access by layer string and attribute string */
CORRADE_VERIFY(data.hasAttribute("ClearCoat", "highlightColor"));
@ -1148,9 +1232,13 @@ void MaterialDataTest::constructLayers() {
CORRADE_COMPARE(data.attribute<Color4>("ClearCoat", "highlightColor"), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.attribute<Containers::StringView>("ClearCoat", "$LayerName"), "ClearCoat");
CORRADE_COMPARE(data.mutableAttribute<Color4>("ClearCoat", "highlightColor"), 0x335566ff_rgbaf);
CORRADE_COMPARE(data.mutableAttribute<Containers::MutableStringView>("ClearCoat", "$LayerName"), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<const Color4*>(data.attribute("ClearCoat", "highlightColor")), 0x335566ff_rgbaf);
CORRADE_COMPARE(static_cast<const char*>(data.attribute("ClearCoat", "$LayerName")), "ClearCoat"_s);
CORRADE_COMPARE(*static_cast<Color4*>(data.mutableAttribute("ClearCoat", "highlightColor")), 0x335566ff_rgbaf);
CORRADE_COMPARE(static_cast<char*>(data.mutableAttribute("ClearCoat", "$LayerName")), "ClearCoat"_s);
}
void MaterialDataTest::constructLayersNotMonotonic() {
@ -1200,6 +1288,8 @@ void MaterialDataTest::constructNonOwned() {
int state{}; /* GCC 11 complains that "maybe uninitialized" w/o the {} */
MaterialData data{MaterialType::Phong, {}, attributes, &state};
CORRADE_COMPARE(data.attributeDataFlags(), DataFlags{});
CORRADE_COMPARE(data.layerDataFlags(), DataFlags{});
/* Expecting the same output as in construct() */
CORRADE_COMPARE(data.types(), MaterialType::Phong);
CORRADE_COMPARE(data.layerCount(), 1);
@ -1244,6 +1334,8 @@ void MaterialDataTest::constructNonOwnedLayers() {
{}, attributes,
{}, layers, &state};
CORRADE_COMPARE(data.attributeDataFlags(), DataFlags{});
CORRADE_COMPARE(data.layerDataFlags(), DataFlags{});
/* Expecting the same output as in constructLayers() */
CORRADE_COMPARE(data.types(), MaterialType::Phong);
CORRADE_COMPARE(data.importerState(), &state);
@ -1382,6 +1474,40 @@ void MaterialDataTest::constructNonOwnedLayersOffsetOutOfBounds() {
CORRADE_COMPARE(out.str(), "Trade::MaterialData: invalid range (2, 6) for layer 1 with 5 attributes in total\n");
}
void MaterialDataTest::constructNonOwnedAttributeFlagOwned() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
MaterialAttributeData attributes[]{
{MaterialAttribute::DoubleSided, true}
};
std::ostringstream out;
Error redirectError{&out};
MaterialData data{{}, DataFlag::Owned, attributes};
CORRADE_COMPARE(out.str(), "Trade::MaterialData: can't construct with non-owned attribute data but Trade::DataFlag::Owned\n");
}
void MaterialDataTest::constructNonOwnedLayerFlagOwned() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
MaterialAttributeData attributes[]{
{MaterialAttribute::DoubleSided, true}
};
UnsignedInt layers[]{
0, 1
};
std::ostringstream out;
Error redirectError{&out};
MaterialData data{{}, {}, attributes, DataFlag::Owned, layers};
CORRADE_COMPARE(out.str(), "Trade::MaterialData: can't construct with non-owned layer data but Trade::DataFlag::Owned\n");
}
void MaterialDataTest::constructCopy() {
CORRADE_VERIFY(!std::is_copy_constructible<MaterialData>{});
CORRADE_VERIFY(!std::is_copy_assignable<MaterialData>{});
@ -1398,6 +1524,8 @@ void MaterialDataTest::constructMove() {
}, &state};
MaterialData b{std::move(a)};
CORRADE_COMPARE(b.attributeDataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_COMPARE(b.layerDataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_COMPARE(a.layerCount(), 1);
CORRADE_COMPARE(a.attributeCount(), 0);
CORRADE_COMPARE(b.types(), MaterialType::Phong);
@ -1412,6 +1540,8 @@ void MaterialDataTest::constructMove() {
c = std::move(b);
CORRADE_COMPARE(b.attributeCount(), 1);
CORRADE_COMPARE(b.layerCount(), 1);
CORRADE_COMPARE(c.attributeDataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_COMPARE(c.layerDataFlags(), DataFlag::Owned|DataFlag::Mutable);
CORRADE_COMPARE(c.types(), MaterialType::Phong);
CORRADE_COMPARE(c.layerCount(), 3);
CORRADE_COMPARE(c.attributeCount(2), 2);
@ -1541,6 +1671,29 @@ void MaterialDataTest::accessTextureSwizzle() {
CORRADE_COMPARE(data.attribute<MaterialTextureSwizzle>(0), MaterialTextureSwizzle::BA);
}
void MaterialDataTest::accessMutable() {
MaterialData data{{}, {
{MaterialAttribute::LayerName, "aye"_s},
{MaterialAttribute::Roughness, 1.0f},
}};
*static_cast<Float*>(data.mutableAttribute(1)) *= 2.0f;
*static_cast<Float*>(data.mutableAttribute(MaterialAttribute::Roughness)) *= 2.0f;
*static_cast<Float*>(data.mutableAttribute("Roughness")) *= 2.0f;
data.mutableAttribute<Float>(1) *= 2.0f;
data.mutableAttribute<Float>(MaterialAttribute::Roughness) *= 2.0f;
data.mutableAttribute<Float>("Roughness") *= 2.0f;
CORRADE_COMPARE(data.attribute<Float>(MaterialAttribute::Roughness), 64.0f);
++*static_cast<char*>(data.mutableAttribute(0));
++*static_cast<char*>(data.mutableAttribute(MaterialAttribute::LayerName));
++*static_cast<char*>(data.mutableAttribute("$LayerName"));
++data.mutableAttribute<Containers::MutableStringView>(0)[0];
++data.mutableAttribute<Containers::MutableStringView>(MaterialAttribute::LayerName)[0];
++data.mutableAttribute<Containers::MutableStringView>("$LayerName")[0];
CORRADE_COMPARE(data.attribute<Containers::StringView>(MaterialAttribute::LayerName), "gye"_s);
}
void MaterialDataTest::accessOptional() {
MaterialData data{{}, {
{MaterialAttribute::AlphaMask, 0.5f},
@ -1583,12 +1736,18 @@ void MaterialDataTest::accessOutOfBounds() {
data.attribute(2);
data.attribute<Int>(2);
data.attribute<Containers::StringView>(2);
data.mutableAttribute(2);
data.mutableAttribute<Int>(2);
data.mutableAttribute<Containers::MutableStringView>(2);
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::attributeName(): index 2 out of range for 2 attributes in layer 0\n"
"Trade::MaterialData::attributeType(): index 2 out of range for 2 attributes in layer 0\n"
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer 0\n"
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer 0\n"
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer 0\n");
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer 0\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 attributes in layer 0\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 attributes in layer 0\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 attributes in layer 0\n");
}
void MaterialDataTest::accessNotFound() {
@ -1608,11 +1767,15 @@ void MaterialDataTest::accessNotFound() {
data.attributeType("DiffuseColour");
data.attribute("DiffuseColour");
data.attribute<Color4>("DiffuseColour");
data.mutableAttribute("DiffuseColour");
data.mutableAttribute<Color4>("DiffuseColour");
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::attributeId(): attribute DiffuseColour not found in layer 0\n"
"Trade::MaterialData::attributeType(): attribute DiffuseColour not found in layer 0\n"
"Trade::MaterialData::attribute(): attribute DiffuseColour not found in layer 0\n"
"Trade::MaterialData::attribute(): attribute DiffuseColour not found in layer 0\n");
"Trade::MaterialData::attribute(): attribute DiffuseColour not found in layer 0\n"
"Trade::MaterialData::mutableAttribute(): attribute DiffuseColour not found in layer 0\n"
"Trade::MaterialData::mutableAttribute(): attribute DiffuseColour not found in layer 0\n");
}
void MaterialDataTest::accessWrongType() {
@ -1629,6 +1792,9 @@ void MaterialDataTest::accessWrongType() {
data.attribute<Color3>(0);
data.attribute<Color3>(MaterialAttribute::DiffuseColor);
data.attribute<Color3>("DiffuseColor");
data.mutableAttribute<Color3>(0);
data.mutableAttribute<Color3>(MaterialAttribute::DiffuseColor);
data.mutableAttribute<Color3>("DiffuseColor");
data.tryAttribute<Color3>(MaterialAttribute::DiffuseColor);
data.tryAttribute<Color3>("DiffuseColor");
data.attributeOr(MaterialAttribute::DiffuseColor, Color3{1.0f});
@ -1637,6 +1803,9 @@ void MaterialDataTest::accessWrongType() {
"Trade::MaterialData::attribute(): DiffuseColor is Trade::MaterialAttributeType::Vector4 but requested a type equivalent to Trade::MaterialAttributeType::Vector3\n"
"Trade::MaterialData::attribute(): DiffuseColor is Trade::MaterialAttributeType::Vector4 but requested a type equivalent to Trade::MaterialAttributeType::Vector3\n"
"Trade::MaterialData::attribute(): DiffuseColor is Trade::MaterialAttributeType::Vector4 but requested a type equivalent to Trade::MaterialAttributeType::Vector3\n"
"Trade::MaterialData::mutableAttribute(): DiffuseColor is Trade::MaterialAttributeType::Vector4 but requested a type equivalent to Trade::MaterialAttributeType::Vector3\n"
"Trade::MaterialData::mutableAttribute(): DiffuseColor is Trade::MaterialAttributeType::Vector4 but requested a type equivalent to Trade::MaterialAttributeType::Vector3\n"
"Trade::MaterialData::mutableAttribute(): DiffuseColor is Trade::MaterialAttributeType::Vector4 but requested a type equivalent to Trade::MaterialAttributeType::Vector3\n"
/* tryAttribute() and attributeOr() delegate to attribute() so the
assert is the same */
"Trade::MaterialData::attribute(): DiffuseColor is Trade::MaterialAttributeType::Vector4 but requested a type equivalent to Trade::MaterialAttributeType::Vector3\n"
@ -1661,16 +1830,24 @@ void MaterialDataTest::accessWrongPointerType() {
/* These are fine (type is not checked) */
data.attribute<Byte*>("mutablePointer");
data.attribute<const Float*>("pointer");
data.mutableAttribute<Byte*>("mutablePointer");
data.mutableAttribute<const Float*>("pointer");
std::ostringstream out;
Error redirectError{&out};
data.attribute<Int>("mutablePointer");
data.attribute<const Int*>("mutablePointer");
data.attribute<Double*>("pointer");
data.mutableAttribute<Int>("mutablePointer");
data.mutableAttribute<const Int*>("mutablePointer");
data.mutableAttribute<Double*>("pointer");
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::attribute(): mutablePointer is Trade::MaterialAttributeType::MutablePointer but requested a type equivalent to Trade::MaterialAttributeType::Int\n"
"Trade::MaterialData::attribute(): mutablePointer is Trade::MaterialAttributeType::MutablePointer but requested a type equivalent to Trade::MaterialAttributeType::Pointer\n"
"Trade::MaterialData::attribute(): pointer is Trade::MaterialAttributeType::Pointer but requested a type equivalent to Trade::MaterialAttributeType::MutablePointer\n");
"Trade::MaterialData::attribute(): pointer is Trade::MaterialAttributeType::Pointer but requested a type equivalent to Trade::MaterialAttributeType::MutablePointer\n"
"Trade::MaterialData::mutableAttribute(): mutablePointer is Trade::MaterialAttributeType::MutablePointer but requested a type equivalent to Trade::MaterialAttributeType::Int\n"
"Trade::MaterialData::mutableAttribute(): mutablePointer is Trade::MaterialAttributeType::MutablePointer but requested a type equivalent to Trade::MaterialAttributeType::Pointer\n"
"Trade::MaterialData::mutableAttribute(): pointer is Trade::MaterialAttributeType::Pointer but requested a type equivalent to Trade::MaterialAttributeType::MutablePointer\n");
}
void MaterialDataTest::accessWrongTypeString() {
@ -1687,6 +1864,9 @@ void MaterialDataTest::accessWrongTypeString() {
data.attribute<Containers::StringView>(0);
data.attribute<Containers::StringView>(MaterialAttribute::Shininess);
data.attribute<Containers::StringView>("Shininess");
data.mutableAttribute<Containers::MutableStringView>(0);
data.mutableAttribute<Containers::MutableStringView>(MaterialAttribute::Shininess);
data.mutableAttribute<Containers::MutableStringView>("Shininess");
data.tryAttribute<Containers::StringView>(MaterialAttribute::Shininess);
data.tryAttribute<Containers::StringView>("Shininess");
data.attributeOr(MaterialAttribute::Shininess, Containers::StringView{});
@ -1695,6 +1875,9 @@ void MaterialDataTest::accessWrongTypeString() {
"Trade::MaterialData::attribute(): Shininess of Trade::MaterialAttributeType::Float can't be retrieved as a string\n"
"Trade::MaterialData::attribute(): Shininess of Trade::MaterialAttributeType::Float can't be retrieved as a string\n"
"Trade::MaterialData::attribute(): Shininess of Trade::MaterialAttributeType::Float can't be retrieved as a string\n"
"Trade::MaterialData::mutableAttribute(): Shininess of Trade::MaterialAttributeType::Float can't be retrieved as a string\n"
"Trade::MaterialData::mutableAttribute(): Shininess of Trade::MaterialAttributeType::Float can't be retrieved as a string\n"
"Trade::MaterialData::mutableAttribute(): Shininess of Trade::MaterialAttributeType::Float can't be retrieved as a string\n"
/* tryAttribute() and attributeOr() delegate to attribute() so the
assert is the same */
"Trade::MaterialData::attribute(): Shininess of Trade::MaterialAttributeType::Float can't be retrieved as a string\n"
@ -1910,6 +2093,117 @@ void MaterialDataTest::accessLayerEmptyLayer() {
CORRADE_COMPARE(data.attribute<UnsignedInt>("crumples", MaterialAttribute::NormalTexture), 3u);
}
void MaterialDataTest::accessLayerIndexMutable() {
MaterialData data{{}, {
{MaterialLayer::ClearCoat},
{MaterialAttribute::Roughness, 1.0f}
}, {0, 2}};
*static_cast<Float*>(data.mutableAttribute(1, 1)) *= 2.0f;
*static_cast<Float*>(data.mutableAttribute(1, "Roughness")) *= 2.0f;
*static_cast<Float*>(data.mutableAttribute(1, MaterialAttribute::Roughness)) *= 2.0f;
data.mutableAttribute<Float>(1, 1) *= 2.0f;
data.mutableAttribute<Float>(1, "Roughness") *= 2.0f;
data.mutableAttribute<Float>(1, MaterialAttribute::Roughness) *= 2.0f;
CORRADE_COMPARE(data.attribute<Float>(1, MaterialAttribute::Roughness), 64.0f);
++*static_cast<char*>(data.mutableAttribute(1, 0));
++*static_cast<char*>(data.mutableAttribute(1, "$LayerName"));
++*static_cast<char*>(data.mutableAttribute(1, MaterialAttribute::LayerName));
++data.mutableAttribute<Containers::MutableStringView>(1, 0)[0];
++data.mutableAttribute<Containers::MutableStringView>(1, "$LayerName")[0];
++data.mutableAttribute<Containers::MutableStringView>(1, MaterialAttribute::LayerName)[0];
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, MaterialAttribute::LayerName), "IlearCoat"_s);
}
void MaterialDataTest::accessLayerNameMutable() {
MaterialData data{{}, {
{MaterialLayer::ClearCoat},
{MaterialAttribute::Roughness, 1.0f}
}, {0, 2}};
*static_cast<Float*>(data.mutableAttribute(MaterialLayer::ClearCoat, 1)) *= 2.0f;
*static_cast<Float*>(data.mutableAttribute(MaterialLayer::ClearCoat, "Roughness")) *= 2.0f;
*static_cast<Float*>(data.mutableAttribute(MaterialLayer::ClearCoat, MaterialAttribute::Roughness)) *= 2.0f;
data.mutableAttribute<Float>(MaterialLayer::ClearCoat, 1) *= 2.0f;
data.mutableAttribute<Float>(MaterialLayer::ClearCoat, "Roughness") *= 2.0f;
data.mutableAttribute<Float>(MaterialLayer::ClearCoat, MaterialAttribute::Roughness) *= 2.0f;
CORRADE_COMPARE(data.attribute<Float>(MaterialLayer::ClearCoat, MaterialAttribute::Roughness), 64.0f);
/* Resetting back so the layer name always stays the same so the next call
can find it. Other than that, the result should be same as in
accessLayerIndexMutable(). */
{
*static_cast<char*>(data.mutableAttribute(MaterialLayer::ClearCoat, 0)) = 'D';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "DlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
*static_cast<char*>(data.mutableAttribute(MaterialLayer::ClearCoat, "$LayerName")) = 'E';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "ElearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
*static_cast<char*>(data.mutableAttribute(MaterialLayer::ClearCoat, MaterialAttribute::LayerName)) = 'F';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "FlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
data.mutableAttribute<Containers::MutableStringView>(MaterialLayer::ClearCoat, 0)[0] = 'G';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "GlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
data.mutableAttribute<Containers::MutableStringView>(MaterialLayer::ClearCoat, "$LayerName")[0] = 'H';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "HlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
data.mutableAttribute<Containers::MutableStringView>(MaterialLayer::ClearCoat, "$LayerName")[0] = 'I';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "IlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
}
}
void MaterialDataTest::accessLayerStringMutable() {
MaterialData data{{}, {
{MaterialLayer::ClearCoat},
{MaterialAttribute::Roughness, 1.0f}
}, {0, 2}};
*static_cast<Float*>(data.mutableAttribute("ClearCoat", 1)) *= 2.0f;
*static_cast<Float*>(data.mutableAttribute("ClearCoat", "Roughness")) *= 2.0f;
*static_cast<Float*>(data.mutableAttribute("ClearCoat", MaterialAttribute::Roughness)) *= 2.0f;
data.mutableAttribute<Float>("ClearCoat", 1) *= 2.0f;
data.mutableAttribute<Float>("ClearCoat", "Roughness") *= 2.0f;
data.mutableAttribute<Float>("ClearCoat", MaterialAttribute::Roughness) *= 2.0f;
CORRADE_COMPARE(data.attribute<Float>("ClearCoat", MaterialAttribute::Roughness), 64.0f);
/* Resetting back so the layer name always stays the same so the next call
can find it. Other than that, the result should be same as in
accessLayerIndexMutable(). */
{
*static_cast<char*>(data.mutableAttribute("ClearCoat", 0)) = 'D';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "DlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
*static_cast<char*>(data.mutableAttribute("ClearCoat", "$LayerName")) = 'E';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "ElearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
*static_cast<char*>(data.mutableAttribute("ClearCoat", MaterialAttribute::LayerName)) = 'F';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "FlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
data.mutableAttribute<Containers::MutableStringView>("ClearCoat", 0)[0] = 'G';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "GlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
data.mutableAttribute<Containers::MutableStringView>("ClearCoat", "$LayerName")[0] = 'H';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "HlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
data.mutableAttribute<Containers::MutableStringView>("ClearCoat", "$LayerName")[0] = 'I';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "IlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
}
}
void MaterialDataTest::accessLayerIndexOptional() {
MaterialData data{{}, {
{MaterialAttribute::DiffuseColor, 0x335566ff_rgbaf},
@ -2024,6 +2318,13 @@ void MaterialDataTest::accessLayerOutOfBounds() {
data.attribute<Int>(2, "AlphaMask");
data.attribute<Int>(2, MaterialAttribute::AlphaMask);
data.attribute<Containers::StringView>(2, 0);
data.mutableAttribute(2, 0);
data.mutableAttribute(2, "AlphaMask");
data.mutableAttribute(2, MaterialAttribute::AlphaMask);
data.mutableAttribute<Int>(2, 0);
data.mutableAttribute<Int>(2, "AlphaMask");
data.mutableAttribute<Int>(2, MaterialAttribute::AlphaMask);
data.mutableAttribute<Containers::MutableStringView>(2, 0);
data.tryAttribute(2, "AlphaMask");
data.tryAttribute(2, MaterialAttribute::AlphaMask);
data.tryAttribute<bool>(2, "AlphaMask");
@ -2053,6 +2354,13 @@ void MaterialDataTest::accessLayerOutOfBounds() {
"Trade::MaterialData::attribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::attribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::attribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::tryAttribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::tryAttribute(): index 2 out of range for 2 layers\n"
"Trade::MaterialData::tryAttribute(): index 2 out of range for 2 layers\n"
@ -2095,6 +2403,13 @@ void MaterialDataTest::accessLayerNotFound() {
data.attribute<Int>("ClearCoat", "AlphaMask");
data.attribute<Int>("ClearCoat", MaterialAttribute::AlphaMask);
data.attribute<Containers::StringView>("ClearCoat", 0);
data.mutableAttribute("ClearCoat", 0);
data.mutableAttribute("ClearCoat", "AlphaMask");
data.mutableAttribute("ClearCoat", MaterialAttribute::AlphaMask);
data.mutableAttribute<Int>("ClearCoat", 0);
data.mutableAttribute<Int>("ClearCoat", "AlphaMask");
data.mutableAttribute<Int>("ClearCoat", MaterialAttribute::AlphaMask);
data.mutableAttribute<Containers::MutableStringView>("ClearCoat", 0);
data.tryAttribute("ClearCoat", "AlphaMask");
data.tryAttribute("ClearCoat", MaterialAttribute::AlphaMask);
data.tryAttribute<bool>("ClearCoat", "AlphaMask");
@ -2124,6 +2439,13 @@ void MaterialDataTest::accessLayerNotFound() {
"Trade::MaterialData::attribute(): layer ClearCoat not found\n"
"Trade::MaterialData::attribute(): layer ClearCoat not found\n"
"Trade::MaterialData::attribute(): layer ClearCoat not found\n"
"Trade::MaterialData::mutableAttribute(): layer ClearCoat not found\n"
"Trade::MaterialData::mutableAttribute(): layer ClearCoat not found\n"
"Trade::MaterialData::mutableAttribute(): layer ClearCoat not found\n"
"Trade::MaterialData::mutableAttribute(): layer ClearCoat not found\n"
"Trade::MaterialData::mutableAttribute(): layer ClearCoat not found\n"
"Trade::MaterialData::mutableAttribute(): layer ClearCoat not found\n"
"Trade::MaterialData::mutableAttribute(): layer ClearCoat not found\n"
"Trade::MaterialData::tryAttribute(): layer ClearCoat not found\n"
"Trade::MaterialData::tryAttribute(): layer ClearCoat not found\n"
"Trade::MaterialData::tryAttribute(): layer ClearCoat not found\n"
@ -2164,6 +2486,13 @@ void MaterialDataTest::accessInvalidLayerName() {
data.attribute<Int>(MaterialLayer(0xfefe), "AlphaMask");
data.attribute<Int>(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask);
data.attribute<Containers::StringView>(MaterialLayer(0xfefe), 0);
data.mutableAttribute(MaterialLayer(0xfefe), 0);
data.mutableAttribute(MaterialLayer(0xfefe), "AlphaMask");
data.mutableAttribute(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask);
data.mutableAttribute<Int>(MaterialLayer(0xfefe), 0);
data.mutableAttribute<Int>(MaterialLayer(0xfefe), "AlphaMask");
data.mutableAttribute<Int>(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask);
data.mutableAttribute<Containers::MutableStringView>(MaterialLayer(0xfefe), 0);
data.tryAttribute(MaterialLayer(0xfefe), "AlphaMask");
data.tryAttribute(MaterialLayer(0xfefe), MaterialAttribute::AlphaMask);
data.tryAttribute<bool>(MaterialLayer(0xfefe), "AlphaMask");
@ -2194,6 +2523,13 @@ void MaterialDataTest::accessInvalidLayerName() {
"Trade::MaterialData::attribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::attribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::mutableAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::mutableAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::mutableAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::mutableAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::mutableAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::mutableAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::mutableAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::tryAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::tryAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
"Trade::MaterialData::tryAttribute(): invalid name Trade::MaterialLayer(0xfefe)\n"
@ -2219,12 +2555,18 @@ void MaterialDataTest::accessOutOfBoundsInLayerIndex() {
data.attribute(1, 2);
data.attribute<Int>(1, 2);
data.attribute<Containers::StringView>(1, 2);
data.mutableAttribute(1, 2);
data.mutableAttribute<Int>(1, 2);
data.mutableAttribute<Containers::MutableStringView>(1, 2);
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::attributeName(): index 2 out of range for 2 attributes in layer 1\n"
"Trade::MaterialData::attributeType(): index 2 out of range for 2 attributes in layer 1\n"
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer 1\n"
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer 1\n"
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer 1\n");
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer 1\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 attributes in layer 1\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 attributes in layer 1\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 attributes in layer 1\n");
}
void MaterialDataTest::accessOutOfBoundsInLayerString() {
@ -2244,12 +2586,18 @@ void MaterialDataTest::accessOutOfBoundsInLayerString() {
data.attribute("ClearCoat", 2);
data.attribute<Int>("ClearCoat", 2);
data.attribute<Containers::StringView>("ClearCoat", 2);
data.mutableAttribute("ClearCoat", 2);
data.mutableAttribute<Int>("ClearCoat", 2);
data.mutableAttribute<Containers::MutableStringView>("ClearCoat", 2);
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::attributeName(): index 2 out of range for 2 attributes in layer ClearCoat\n"
"Trade::MaterialData::attributeType(): index 2 out of range for 2 attributes in layer ClearCoat\n"
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer ClearCoat\n"
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer ClearCoat\n"
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer ClearCoat\n");
"Trade::MaterialData::attribute(): index 2 out of range for 2 attributes in layer ClearCoat\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 attributes in layer ClearCoat\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 attributes in layer ClearCoat\n"
"Trade::MaterialData::mutableAttribute(): index 2 out of range for 2 attributes in layer ClearCoat\n");
}
void MaterialDataTest::accessNotFoundInLayerIndex() {
@ -2269,11 +2617,15 @@ void MaterialDataTest::accessNotFoundInLayerIndex() {
data.attributeType(1, "DiffuseColour");
data.attribute(1, "DiffuseColour");
data.attribute<Color4>(1, "DiffuseColour");
data.mutableAttribute(1, "DiffuseColour");
data.mutableAttribute<Color4>(1, "DiffuseColour");
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::attributeId(): attribute DiffuseColour not found in layer 1\n"
"Trade::MaterialData::attributeType(): attribute DiffuseColour not found in layer 1\n"
"Trade::MaterialData::attribute(): attribute DiffuseColour not found in layer 1\n"
"Trade::MaterialData::attribute(): attribute DiffuseColour not found in layer 1\n");
"Trade::MaterialData::attribute(): attribute DiffuseColour not found in layer 1\n"
"Trade::MaterialData::mutableAttribute(): attribute DiffuseColour not found in layer 1\n"
"Trade::MaterialData::mutableAttribute(): attribute DiffuseColour not found in layer 1\n");
}
void MaterialDataTest::accessNotFoundInLayerString() {
@ -2294,11 +2646,15 @@ void MaterialDataTest::accessNotFoundInLayerString() {
data.attributeType("ClearCoat", "DiffuseColour");
data.attribute("ClearCoat", "DiffuseColour");
data.attribute<Color4>("ClearCoat", "DiffuseColour");
data.mutableAttribute("ClearCoat", "DiffuseColour");
data.mutableAttribute<Color4>("ClearCoat", "DiffuseColour");
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::attributeId(): attribute DiffuseColour not found in layer ClearCoat\n"
"Trade::MaterialData::attributeType(): attribute DiffuseColour not found in layer ClearCoat\n"
"Trade::MaterialData::attribute(): attribute DiffuseColour not found in layer ClearCoat\n"
"Trade::MaterialData::attribute(): attribute DiffuseColour not found in layer ClearCoat\n");
"Trade::MaterialData::attribute(): attribute DiffuseColour not found in layer ClearCoat\n"
"Trade::MaterialData::mutableAttribute(): attribute DiffuseColour not found in layer ClearCoat\n"
"Trade::MaterialData::mutableAttribute(): attribute DiffuseColour not found in layer ClearCoat\n");
}
void MaterialDataTest::accessInvalidAttributeName() {
@ -2323,6 +2679,10 @@ void MaterialDataTest::accessInvalidAttributeName() {
data.attribute("Layer", MaterialAttribute(0xfefe));
data.attribute<Int>(0, MaterialAttribute(0x0));
data.attribute<Int>("Layer", MaterialAttribute(0xfefe));
data.mutableAttribute(0, MaterialAttribute(0x0));
data.mutableAttribute("Layer", MaterialAttribute(0xfefe));
data.mutableAttribute<Int>(0, MaterialAttribute(0x0));
data.mutableAttribute<Int>("Layer", MaterialAttribute(0xfefe));
data.tryAttribute(0, MaterialAttribute(0x0));
data.tryAttribute("Layer", MaterialAttribute(0xfefe));
data.tryAttribute<Int>(0, MaterialAttribute(0x0));
@ -2340,6 +2700,10 @@ void MaterialDataTest::accessInvalidAttributeName() {
"Trade::MaterialData::attribute(): invalid name Trade::MaterialAttribute(0xfefe)\n"
"Trade::MaterialData::attribute(): invalid name Trade::MaterialAttribute(0x0)\n"
"Trade::MaterialData::attribute(): invalid name Trade::MaterialAttribute(0xfefe)\n"
"Trade::MaterialData::mutableAttribute(): invalid name Trade::MaterialAttribute(0x0)\n"
"Trade::MaterialData::mutableAttribute(): invalid name Trade::MaterialAttribute(0xfefe)\n"
"Trade::MaterialData::mutableAttribute(): invalid name Trade::MaterialAttribute(0x0)\n"
"Trade::MaterialData::mutableAttribute(): invalid name Trade::MaterialAttribute(0xfefe)\n"
"Trade::MaterialData::tryAttribute(): invalid name Trade::MaterialAttribute(0x0)\n"
"Trade::MaterialData::tryAttribute(): invalid name Trade::MaterialAttribute(0xfefe)\n"
"Trade::MaterialData::tryAttribute(): invalid name Trade::MaterialAttribute(0x0)\n"
@ -2348,6 +2712,97 @@ void MaterialDataTest::accessInvalidAttributeName() {
"Trade::MaterialData::attributeOr(): invalid name Trade::MaterialAttribute(0xfefe)\n");
}
void MaterialDataTest::accessMutableNotAllowed() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
const MaterialAttributeData attributes[]{
{MaterialAttribute::DiffuseColor, 0x335566ff_rgbaf},
{MaterialAttribute::LayerName, "ClearCoat"},
{MaterialAttribute::Roughness, 0.5f}
};
const UnsignedInt layers[]{
1, 3
};
MaterialData data{{}, {}, attributes, {}, layers};
std::ostringstream out;
Error redirectError{&out};
data.mutableAttribute(0);
data.mutableAttribute("DiffuseColor");
data.mutableAttribute(MaterialAttribute::DiffuseColor);
data.mutableAttribute<Color4>(0);
data.mutableAttribute<Color4>("DiffuseColor");
data.mutableAttribute<Color4>(MaterialAttribute::DiffuseColor);
data.mutableAttribute(1, 1);
data.mutableAttribute(1, "Roughness");
data.mutableAttribute(1, MaterialAttribute::Roughness);
data.mutableAttribute<Float>(1, 1);
data.mutableAttribute<Float>(1, "Roughness");
data.mutableAttribute<Float>(1, MaterialAttribute::Roughness);
data.mutableAttribute<Containers::MutableStringView>(1, 0);
data.mutableAttribute<Containers::MutableStringView>(1, "$LayerName");
data.mutableAttribute<Containers::MutableStringView>(1, MaterialAttribute::LayerName);
data.mutableAttribute("ClearCoat", 1);
data.mutableAttribute("ClearCoat", "Roughness");
data.mutableAttribute("ClearCoat", MaterialAttribute::Roughness);
data.mutableAttribute<Float>("ClearCoat", 1);
data.mutableAttribute<Float>("ClearCoat", "Roughness");
data.mutableAttribute<Float>("ClearCoat", MaterialAttribute::Roughness);
data.mutableAttribute<Containers::MutableStringView>("ClearCoat", 0);
data.mutableAttribute<Containers::MutableStringView>("ClearCoat", "$LayerName");
data.mutableAttribute<Containers::MutableStringView>("ClearCoat", MaterialAttribute::LayerName);
data.mutableAttribute(MaterialLayer::ClearCoat, 1);
data.mutableAttribute(MaterialLayer::ClearCoat, "Roughness");
data.mutableAttribute(MaterialLayer::ClearCoat, MaterialAttribute::Roughness);
data.mutableAttribute<Float>(MaterialLayer::ClearCoat, 1);
data.mutableAttribute<Float>(MaterialLayer::ClearCoat, "Roughness");
data.mutableAttribute<Float>(MaterialLayer::ClearCoat, MaterialAttribute::Roughness);
data.mutableAttribute<Containers::MutableStringView>(MaterialLayer::ClearCoat, 0);
data.mutableAttribute<Containers::MutableStringView>(MaterialLayer::ClearCoat, "$LayerName");
data.mutableAttribute<Containers::MutableStringView>(MaterialLayer::ClearCoat, MaterialAttribute::LayerName);
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n" "Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n" "Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n" "Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n"
"Trade::MaterialData::mutableAttribute(): attribute data not mutable\n");
}
void MaterialDataTest::releaseAttributes() {
MaterialData data{{}, {
{"DiffuseColor", 0xff3366aa_rgbaf},
@ -2427,10 +2882,16 @@ void MaterialDataTest::templateLayerAccess() {
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute(2)), 3);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute(MaterialAttribute::LayerFactorTexture)), 3);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.attribute("LayerFactorTexture")), 3);
CORRADE_COMPARE(*static_cast<UnsignedInt*>(data.mutableAttribute(2)), 3);
CORRADE_COMPARE(*static_cast<UnsignedInt*>(data.mutableAttribute(MaterialAttribute::LayerFactorTexture)), 3);
CORRADE_COMPARE(*static_cast<UnsignedInt*>(data.mutableAttribute("LayerFactorTexture")), 3);
CORRADE_COMPARE(data.attribute<UnsignedInt>(2), 3);
CORRADE_COMPARE(data.attribute<UnsignedInt>(MaterialAttribute::LayerFactorTexture), 3);
CORRADE_COMPARE(data.attribute<UnsignedInt>("LayerFactorTexture"), 3);
CORRADE_COMPARE(data.mutableAttribute<UnsignedInt>(2), 3);
CORRADE_COMPARE(data.mutableAttribute<UnsignedInt>(MaterialAttribute::LayerFactorTexture), 3);
CORRADE_COMPARE(data.mutableAttribute<UnsignedInt>("LayerFactorTexture"), 3);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.tryAttribute(MaterialAttribute::LayerFactorTexture)), 3);
CORRADE_COMPARE(*static_cast<const UnsignedInt*>(data.tryAttribute("LayerFactorTexture")), 3);
@ -2442,6 +2903,50 @@ void MaterialDataTest::templateLayerAccess() {
CORRADE_COMPARE(data.attributeOr("LayerFactorTexture", 5u), 3);
}
void MaterialDataTest::templateLayerAccessMutable() {
MaterialLayerData<MaterialLayer::ClearCoat> data{{}, {
{MaterialLayer::ClearCoat},
{MaterialAttribute::Roughness, 1.0f},
}, {0, 2}};
*static_cast<Float*>(data.mutableAttribute(1)) *= 2.0f;
*static_cast<Float*>(data.mutableAttribute(MaterialAttribute::Roughness)) *= 2.0f;
*static_cast<Float*>(data.mutableAttribute("Roughness")) *= 2.0f;
data.mutableAttribute<Float>(1) *= 2.0f;
data.mutableAttribute<Float>(MaterialAttribute::Roughness) *= 2.0f;
data.mutableAttribute<Float>("Roughness") *= 2.0f;
CORRADE_COMPARE(data.attribute<Float>(MaterialAttribute::Roughness), 64.0f);
/* Resetting back so the layer name always stays the same so the next call
can find it. Other than that, the result should be same as in
accessLayerIndexMutable(). */
{
*static_cast<char*>(data.mutableAttribute("ClearCoat", 0)) = 'D';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "DlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
*static_cast<char*>(data.mutableAttribute("ClearCoat", "$LayerName")) = 'E';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "ElearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
*static_cast<char*>(data.mutableAttribute("ClearCoat", MaterialAttribute::LayerName)) = 'F';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "FlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
data.mutableAttribute<Containers::MutableStringView>("ClearCoat", 0)[0] = 'G';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "GlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
data.mutableAttribute<Containers::MutableStringView>("ClearCoat", "$LayerName")[0] = 'H';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "HlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
} {
data.mutableAttribute<Containers::MutableStringView>("ClearCoat", "$LayerName")[0] = 'I';
CORRADE_COMPARE(data.attribute<Containers::StringView>(1, 0), "IlearCoat");
*static_cast<char*>(data.mutableAttribute(1, 0)) = 'C';
}
}
void MaterialDataTest::debugLayer() {
std::ostringstream out;

Loading…
Cancel
Save