Browse Source

Trade: "optional" access to MaterialData attributes.

pull/459/head
Vladimír Vondruš 6 years ago
parent
commit
9992614c3d
  1. 12
      src/Magnum/Trade/MaterialData.cpp
  2. 67
      src/Magnum/Trade/MaterialData.h
  3. 51
      src/Magnum/Trade/Test/MaterialDataTest.cpp

12
src/Magnum/Trade/MaterialData.cpp

@ -262,6 +262,18 @@ const void* MaterialData::attribute(const MaterialAttribute name) const {
return attribute(string);
}
const void* MaterialData::tryAttribute(const Containers::StringView name) const {
const UnsignedInt id = attributeFor(name);
if(id == ~UnsignedInt{}) return nullptr;
return _data[id].value();
}
const void* MaterialData::tryAttribute(const MaterialAttribute name) const {
const Containers::StringView string = attributeString(name);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::tryAttribute(): invalid name" << name, {});
return tryAttribute(string);
}
Containers::Array<MaterialAttributeData> MaterialData::release() {
return std::move(_data);
}

67
src/Magnum/Trade/MaterialData.h

@ -31,6 +31,7 @@
*/
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StringView.h>
#include "Magnum/Magnum.h"
@ -590,7 +591,11 @@ class MAGNUM_TRADE_EXPORT MaterialData {
/** @brief Attribute count */
UnsignedInt attributeCount() const { return _data.size(); }
/** @brief Whether the material has given attribute */
/**
* @brief Whether the material has given attribute
*
* @see @ref tryAttribute(), @ref attributeOr()
*/
bool hasAttribute(Containers::StringView name) const;
bool hasAttribute(MaterialAttribute name) const; /**< @overload */
@ -643,7 +648,7 @@ class MAGNUM_TRADE_EXPORT MaterialData {
*
* The @p name is expected to exist. Cast the pointer to a concrete
* type based on @ref attributeType().
* @see @ref hasAttribute()
* @see @ref hasAttribute(), @ref tryAttribute(), @ref attributeOr()
*/
const void* attribute(Containers::StringView name) const;
const void* attribute(MaterialAttribute name) const; /**< @overload */
@ -667,6 +672,40 @@ class MAGNUM_TRADE_EXPORT MaterialData {
template<class T> T attribute(Containers::StringView name) const;
template<class T> T attribute(MaterialAttribute name) const; /**< @overload */
/**
* @brief Type-erased attribute value, if exists
*
* Compared to @ref attribute(Containers::StringView name) const, if
* @p name doesn't exist, returns @cpp nullptr @ce instead of
* asserting. Cast the pointer to a concrete type based on
* @ref attributeType().
* @see @ref hasAttribute(), @ref attributeOr()
*/
const void* tryAttribute(Containers::StringView name) const;
const void* tryAttribute(MaterialAttribute name) const; /**< @overload */
/**
* @brief Value of a named attribute, if exists
*
* Compared to @ref attribute(Containers::StringView name) const, if
* @p name doesn't exist, returns @ref Corrade::Containers::NullOpt
* instead of asserting. Expects that @p T corresponds to
* @ref attributeType(Containers::StringView) const for given @p name.
*/
template<class T> Containers::Optional<T> tryAttribute(Containers::StringView name) const;
template<class T> Containers::Optional<T> tryAttribute(MaterialAttribute name) const; /**< @overload */
/**
* @brief Value of a named attribute or a default
*
* Compared to @ref attribute(Containers::StringView name) const, if
* @p name doesn't exist, returns @p defaultValue instead of asserting.
* Expects that @p T corresponds to
* @ref attributeType(Containers::StringView) const for given @p name.
*/
template<class T> T attributeOr(Containers::StringView name, const T& defaultValue) const;
template<class T> T attributeOr(MaterialAttribute name, const T& defaultValue) const; /**< @overload */
/**
* @brief Release data storage
*
@ -774,6 +813,30 @@ template<class T> T MaterialData::attribute(MaterialAttribute name) const {
return attribute<T>(string);
}
template<class T> Containers::Optional<T> MaterialData::tryAttribute(Containers::StringView name) const {
const UnsignedInt id = attributeFor(name);
if(id == ~UnsignedInt{}) return {};
return attribute<T>(id);
}
template<class T> Containers::Optional<T> MaterialData::tryAttribute(MaterialAttribute name) const {
const Containers::StringView string = attributeString(name);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::tryAttribute(): invalid name" << name, {});
return tryAttribute<T>(string);
}
template<class T> T MaterialData::attributeOr(Containers::StringView name, const T& defaultValue) const {
const UnsignedInt id = attributeFor(name);
if(id == ~UnsignedInt{}) return defaultValue;
return attribute<T>(id);
}
template<class T> T MaterialData::attributeOr(MaterialAttribute name, const T& defaultValue) const {
const Containers::StringView string = attributeString(name);
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeOr(): invalid name" << name, {});
return attributeOr<T>(string, defaultValue);
}
}}
#endif

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

@ -73,6 +73,7 @@ class MaterialDataTest: public TestSuite::Tester {
void constructCopy();
void constructMove();
void accessOptional();
void accessOutOfBounds();
void accessInvalidAttributeName();
void accessNotFound();
@ -161,6 +162,7 @@ MaterialDataTest::MaterialDataTest() {
&MaterialDataTest::constructCopy,
&MaterialDataTest::constructMove,
&MaterialDataTest::accessOptional,
&MaterialDataTest::accessOutOfBounds,
&MaterialDataTest::accessInvalidAttributeName,
&MaterialDataTest::accessNotFound,
@ -666,6 +668,31 @@ void MaterialDataTest::constructMove() {
CORRADE_VERIFY(std::is_nothrow_move_assignable<MaterialData>::value);
}
void MaterialDataTest::accessOptional() {
MaterialData data{{
{MaterialAttribute::AlphaMask, 0.5f},
{MaterialAttribute::SpecularTexture, 3u}
}};
/* This exists */
CORRADE_VERIFY(data.tryAttribute("SpecularTexture"));
CORRADE_VERIFY(data.tryAttribute(MaterialAttribute::SpecularTexture));
CORRADE_COMPARE(*static_cast<const Int*>(data.tryAttribute("SpecularTexture")), 3);
CORRADE_COMPARE(*static_cast<const Int*>(data.tryAttribute(MaterialAttribute::SpecularTexture)), 3);
CORRADE_COMPARE(data.tryAttribute<UnsignedInt>("SpecularTexture"), 3);
CORRADE_COMPARE(data.tryAttribute<UnsignedInt>(MaterialAttribute::SpecularTexture), 3);
CORRADE_COMPARE(data.attributeOr("SpecularTexture", 5u), 3);
CORRADE_COMPARE(data.attributeOr(MaterialAttribute::SpecularTexture, 5u), 3);
/* This doesn't */
CORRADE_VERIFY(!data.tryAttribute("DiffuseTexture"));
CORRADE_VERIFY(!data.tryAttribute(MaterialAttribute::DiffuseTexture));
CORRADE_VERIFY(!data.tryAttribute<UnsignedInt>("DiffuseTexture"));
CORRADE_VERIFY(!data.tryAttribute<UnsignedInt>(MaterialAttribute::DiffuseTexture));
CORRADE_COMPARE(data.attributeOr("DiffuseTexture", 5u), 5);
CORRADE_COMPARE(data.attributeOr(MaterialAttribute::DiffuseTexture, 5u), 5);
}
void MaterialDataTest::accessOutOfBounds() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
@ -708,6 +735,12 @@ void MaterialDataTest::accessInvalidAttributeName() {
data.attribute(MaterialAttribute(0xfefe));
data.attribute<Int>(MaterialAttribute(0x0));
data.attribute<Int>(MaterialAttribute(0xfefe));
data.tryAttribute(MaterialAttribute(0x0));
data.tryAttribute(MaterialAttribute(0xfefe));
data.tryAttribute<Int>(MaterialAttribute(0x0));
data.tryAttribute<Int>(MaterialAttribute(0xfefe));
data.attributeOr(MaterialAttribute(0x0), 42);
data.attributeOr(MaterialAttribute(0xfefe), 42);
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::hasAttribute(): invalid name Trade::MaterialAttribute(0x0)\n"
"Trade::MaterialData::hasAttribute(): invalid name Trade::MaterialAttribute(0xfefe)\n"
@ -718,7 +751,13 @@ void MaterialDataTest::accessInvalidAttributeName() {
"Trade::MaterialData::attribute(): invalid name Trade::MaterialAttribute(0x0)\n"
"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::attribute(): 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"
"Trade::MaterialData::tryAttribute(): invalid name Trade::MaterialAttribute(0xfefe)\n"
"Trade::MaterialData::attributeOr(): invalid name Trade::MaterialAttribute(0x0)\n"
"Trade::MaterialData::attributeOr(): invalid name Trade::MaterialAttribute(0xfefe)\n");
}
void MaterialDataTest::accessNotFound() {
@ -759,7 +798,17 @@ void MaterialDataTest::accessWrongType() {
data.attribute<Color3>(0);
data.attribute<Color3>(MaterialAttribute::DiffuseColor);
data.attribute<Color3>("DiffuseColor");
data.tryAttribute<Color3>(MaterialAttribute::DiffuseColor);
data.tryAttribute<Color3>("DiffuseColor");
data.attributeOr(MaterialAttribute::DiffuseColor, Color3{1.0f});
data.attributeOr("DiffuseColor", Color3{1.0f});
CORRADE_COMPARE(out.str(),
"Trade::MaterialData::attribute(): improper type requested for DiffuseColor of Trade::MaterialAttributeType::Vector4\n"
"Trade::MaterialData::attribute(): improper type requested for DiffuseColor of Trade::MaterialAttributeType::Vector4\n"
"Trade::MaterialData::attribute(): improper type requested for DiffuseColor of Trade::MaterialAttributeType::Vector4\n"
/* tryAttribute() and attributeOr() delegate to attribute() so the
assert is the same */
"Trade::MaterialData::attribute(): improper type requested for DiffuseColor of Trade::MaterialAttributeType::Vector4\n"
"Trade::MaterialData::attribute(): improper type requested for DiffuseColor of Trade::MaterialAttributeType::Vector4\n"
"Trade::MaterialData::attribute(): improper type requested for DiffuseColor of Trade::MaterialAttributeType::Vector4\n"
"Trade::MaterialData::attribute(): improper type requested for DiffuseColor of Trade::MaterialAttributeType::Vector4\n");

Loading…
Cancel
Save