Browse Source

Trade: add scene{Object,Field}TypeAlignment().

Support utilities needed for SceneTools that will operate on arbitrary
SceneData (adding/removing fields, objects...) without having to know
what each field means and how it needs to be treated.

Honestly the same would make sense for the VertexFormat enum as well.
But not now, later.
pull/525/head
Vladimír Vondruš 5 years ago
parent
commit
e858ab2dd8
  1. 130
      src/Magnum/Trade/SceneData.cpp
  2. 28
      src/Magnum/Trade/SceneData.h
  3. 47
      src/Magnum/Trade/Test/SceneDataTest.cpp

130
src/Magnum/Trade/SceneData.cpp

@ -82,6 +82,24 @@ UnsignedInt sceneObjectTypeSize(const SceneObjectType type) {
CORRADE_ASSERT_UNREACHABLE("Trade::sceneObjectTypeSize(): invalid type" << type, {});
}
UnsignedInt sceneObjectTypeAlignment(const SceneObjectType type) {
#ifdef CORRADE_TARGET_GCC
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch"
#endif
switch(type) {
case SceneObjectType::UnsignedByte: return 1;
case SceneObjectType::UnsignedShort: return 2;
case SceneObjectType::UnsignedInt: return 4;
case SceneObjectType::UnsignedLong: return 8;
}
#ifdef CORRADE_TARGET_GCC
#pragma GCC diagnostic pop
#endif
CORRADE_ASSERT_UNREACHABLE("Trade::sceneObjectTypeAlignment(): invalid type" << type, {});
}
Debug& operator<<(Debug& debug, const SceneField value) {
debug << "Trade::SceneField" << Debug::nospace;
@ -343,6 +361,118 @@ UnsignedInt sceneFieldTypeSize(const SceneFieldType type) {
CORRADE_ASSERT_UNREACHABLE("Trade::sceneFieldTypeSize(): invalid type" << type, {});
}
UnsignedInt sceneFieldTypeAlignment(const SceneFieldType type) {
#ifdef CORRADE_TARGET_GCC
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch"
#endif
switch(type) {
case SceneFieldType::UnsignedByte:
case SceneFieldType::Vector2ub:
case SceneFieldType::Vector3ub:
case SceneFieldType::Vector4ub:
case SceneFieldType::Byte:
case SceneFieldType::Vector2b:
case SceneFieldType::Vector3b:
case SceneFieldType::Vector4b:
return 1;
case SceneFieldType::UnsignedShort:
case SceneFieldType::Vector2us:
case SceneFieldType::Vector3us:
case SceneFieldType::Vector4us:
case SceneFieldType::Short:
case SceneFieldType::Vector2s:
case SceneFieldType::Vector3s:
case SceneFieldType::Vector4s:
case SceneFieldType::Half:
case SceneFieldType::Vector2h:
case SceneFieldType::Vector3h:
case SceneFieldType::Vector4h:
case SceneFieldType::Matrix2x2h:
case SceneFieldType::Matrix2x3h:
case SceneFieldType::Matrix2x4h:
case SceneFieldType::Matrix3x2h:
case SceneFieldType::Matrix3x3h:
case SceneFieldType::Matrix3x4h:
case SceneFieldType::Matrix4x2h:
case SceneFieldType::Matrix4x3h:
case SceneFieldType::Matrix4x4h:
case SceneFieldType::Range1Dh:
case SceneFieldType::Range2Dh:
case SceneFieldType::Range3Dh:
case SceneFieldType::Degh:
case SceneFieldType::Radh:
return 2;
case SceneFieldType::UnsignedInt:
case SceneFieldType::Vector2ui:
case SceneFieldType::Vector3ui:
case SceneFieldType::Vector4ui:
case SceneFieldType::Int:
case SceneFieldType::Vector2i:
case SceneFieldType::Vector3i:
case SceneFieldType::Vector4i:
case SceneFieldType::Float:
case SceneFieldType::Vector2:
case SceneFieldType::Vector3:
case SceneFieldType::Vector4:
case SceneFieldType::Matrix2x2:
case SceneFieldType::Matrix2x3:
case SceneFieldType::Matrix2x4:
case SceneFieldType::Matrix3x2:
case SceneFieldType::Matrix3x3:
case SceneFieldType::Matrix3x4:
case SceneFieldType::Matrix4x2:
case SceneFieldType::Matrix4x3:
case SceneFieldType::Matrix4x4:
case SceneFieldType::Range1Di:
case SceneFieldType::Range2Di:
case SceneFieldType::Range3Di:
case SceneFieldType::Range1D:
case SceneFieldType::Range2D:
case SceneFieldType::Range3D:
case SceneFieldType::Complex:
case SceneFieldType::Quaternion:
case SceneFieldType::DualComplex:
case SceneFieldType::DualQuaternion:
case SceneFieldType::Deg:
case SceneFieldType::Rad:
return 4;
case SceneFieldType::UnsignedLong:
case SceneFieldType::Long:
case SceneFieldType::Double:
case SceneFieldType::Vector2d:
case SceneFieldType::Vector3d:
case SceneFieldType::Vector4d:
case SceneFieldType::Matrix2x2d:
case SceneFieldType::Matrix2x3d:
case SceneFieldType::Matrix2x4d:
case SceneFieldType::Matrix3x2d:
case SceneFieldType::Matrix3x3d:
case SceneFieldType::Matrix3x4d:
case SceneFieldType::Matrix4x2d:
case SceneFieldType::Matrix4x3d:
case SceneFieldType::Matrix4x4d:
case SceneFieldType::Range1Dd:
case SceneFieldType::Range2Dd:
case SceneFieldType::Range3Dd:
case SceneFieldType::Complexd:
case SceneFieldType::Quaterniond:
case SceneFieldType::DualComplexd:
case SceneFieldType::DualQuaterniond:
case SceneFieldType::Degd:
case SceneFieldType::Radd:
return 8;
case SceneFieldType::Pointer:
case SceneFieldType::MutablePointer:
return sizeof(void*);
}
#ifdef CORRADE_TARGET_GCC
#pragma GCC diagnostic pop
#endif
CORRADE_ASSERT_UNREACHABLE("Trade::sceneFieldTypeAlignment(): invalid type" << type, {});
}
SceneFieldData::SceneFieldData(const SceneField name, const Containers::StridedArrayView2D<const char>& objectData, const SceneFieldType fieldType, const Containers::StridedArrayView2D<const char>& fieldData, const UnsignedShort fieldArraySize) noexcept: SceneFieldData{name, {}, Containers::StridedArrayView1D<const void>{{objectData.data(), ~std::size_t{}}, objectData.size()[0], objectData.stride()[0]}, fieldType, Containers::StridedArrayView1D<const void>{{fieldData.data(), ~std::size_t{}}, fieldData.size()[0], fieldData.stride()[0]}, fieldArraySize} {
/* Yes, this calls into a constexpr function defined in the header --
because I feel that makes more sense than duplicating the full assert

28
src/Magnum/Trade/SceneData.h

@ -26,7 +26,7 @@
*/
/** @file
* @brief Class @ref Magnum::Trade::SceneData, @ref Magnum::Trade::SceneFieldData, enum @ref Magnum::Trade::SceneObjectType, @ref Magnum::Trade::SceneField, @ref Magnum::Trade::SceneFieldType, function @ref Magnum::sceneObjectTypeSize(), @ref Magnum::sceneFieldTypeSize(), @ref Magnum::Trade::isSceneFieldCustom(), @ref Magnum::sceneFieldCustom()
* @brief Class @ref Magnum::Trade::SceneData, @ref Magnum::Trade::SceneFieldData, enum @ref Magnum::Trade::SceneObjectType, @ref Magnum::Trade::SceneField, @ref Magnum::Trade::SceneFieldType, function @ref Magnum::sceneObjectTypeSize(), @ref Magnum::sceneObjectTypeAlignment(), @ref Magnum::sceneFieldTypeSize(), @ref Magnum::sceneFieldTypeAlignment(), @ref Magnum::Trade::isSceneFieldCustom(), @ref Magnum::sceneFieldCustom()
*/
#include <Corrade/Containers/Array.h>
@ -51,7 +51,8 @@ Type used for mapping fields to corresponding objects. Unlike
@ref SceneFieldType that is different for different fields, the object type is
the same for all fields, and is guaranteed to be large enough to fit all
@ref SceneData::objectCount() objects.
@see @ref SceneData::objectType(), @ref sceneObjectTypeSize()
@see @ref SceneData::objectType(), @ref sceneObjectTypeSize(),
@ref sceneObjectTypeAlignment()
*/
enum class SceneObjectType: UnsignedByte {
/* Zero used for an invalid value */
@ -80,9 +81,19 @@ MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, SceneObjectType value);
/**
@brief Size of given scene object type
@m_since_latest
@see @ref sceneObjectTypeAlignment()
*/
MAGNUM_TRADE_EXPORT UnsignedInt sceneObjectTypeSize(SceneObjectType type);
/**
@brief Alignment of given scene object type
@m_since_latest
Returns the same value as @ref sceneObjectTypeSize().
*/
MAGNUM_TRADE_EXPORT UnsignedInt sceneObjectTypeAlignment(SceneObjectType type);
/**
@brief Scene field name
@m_since_latest
@ -368,7 +379,8 @@ constexpr UnsignedInt sceneFieldCustom(SceneField name) {
A type in which a @ref SceneField is stored. See @ref SceneData for more
information.
@see @ref SceneFieldData, @ref sceneFieldTypeSize()
@see @ref SceneFieldData, @ref sceneFieldTypeSize(),
@ref sceneFieldTypeAlignment()
*/
enum class SceneFieldType: UnsignedShort {
/* Zero used for an invalid value */
@ -509,9 +521,19 @@ MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, SceneFieldType value);
/**
@brief Size of given scene field type
@m_since_latest
@see @ref sceneFieldTypeAlignment()
*/
MAGNUM_TRADE_EXPORT UnsignedInt sceneFieldTypeSize(SceneFieldType type);
/**
@brief Alignment of given scene field type
@m_since_latest
@see @ref sceneFieldTypeSize()
*/
MAGNUM_TRADE_EXPORT UnsignedInt sceneFieldTypeAlignment(SceneFieldType type);
/**
@brief Scene field data
@m_since_latest

47
src/Magnum/Trade/Test/SceneDataTest.cpp

@ -50,8 +50,8 @@ namespace Magnum { namespace Trade { namespace Test { namespace {
struct SceneDataTest: TestSuite::Tester {
explicit SceneDataTest();
void objectTypeSize();
void objectTypeSizeInvalid();
void objectTypeSizeAlignment();
void objectTypeSizeAlignmentInvalid();
void debugObjectType();
void customFieldName();
@ -59,8 +59,8 @@ struct SceneDataTest: TestSuite::Tester {
void customFieldNameNotCustom();
void debugFieldName();
void fieldTypeSize();
void fieldTypeSizeInvalid();
void fieldTypeSizeAlignment();
void fieldTypeSizeAlignmentInvalid();
void debugFieldType();
void constructField();
@ -223,8 +223,8 @@ const struct {
#endif
SceneDataTest::SceneDataTest() {
addTests({&SceneDataTest::objectTypeSize,
&SceneDataTest::objectTypeSizeInvalid,
addTests({&SceneDataTest::objectTypeSizeAlignment,
&SceneDataTest::objectTypeSizeAlignmentInvalid,
&SceneDataTest::debugObjectType,
&SceneDataTest::customFieldName,
@ -232,8 +232,8 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::customFieldNameNotCustom,
&SceneDataTest::debugFieldName,
&SceneDataTest::fieldTypeSize,
&SceneDataTest::fieldTypeSizeInvalid,
&SceneDataTest::fieldTypeSizeAlignment,
&SceneDataTest::fieldTypeSizeAlignmentInvalid,
&SceneDataTest::debugFieldType,
&SceneDataTest::constructField,
@ -427,14 +427,18 @@ SceneDataTest::SceneDataTest() {
using namespace Math::Literals;
void SceneDataTest::objectTypeSize() {
void SceneDataTest::objectTypeSizeAlignment() {
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedByte), 1);
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedByte), 1);
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedShort), 2);
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedShort), 2);
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedInt), 4);
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedInt), 4);
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedLong), 8);
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedLong), 8);
}
void SceneDataTest::objectTypeSizeInvalid() {
void SceneDataTest::objectTypeSizeAlignmentInvalid() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
@ -443,11 +447,15 @@ void SceneDataTest::objectTypeSizeInvalid() {
Error redirectError{&out};
sceneObjectTypeSize(SceneObjectType{});
sceneObjectTypeAlignment(SceneObjectType{});
sceneObjectTypeSize(SceneObjectType(0x73));
sceneObjectTypeAlignment(SceneObjectType(0x73));
CORRADE_COMPARE(out.str(),
"Trade::sceneObjectTypeSize(): invalid type Trade::SceneObjectType(0x0)\n"
"Trade::sceneObjectTypeSize(): invalid type Trade::SceneObjectType(0x73)\n");
"Trade::sceneObjectTypeAlignment(): invalid type Trade::SceneObjectType(0x0)\n"
"Trade::sceneObjectTypeSize(): invalid type Trade::SceneObjectType(0x73)\n"
"Trade::sceneObjectTypeAlignment(): invalid type Trade::SceneObjectType(0x73)\n");
}
void SceneDataTest::debugObjectType() {
@ -506,7 +514,7 @@ void SceneDataTest::debugFieldName() {
CORRADE_COMPARE(out.str(), "Trade::SceneField::Transformation Trade::SceneField::Custom(73) Trade::SceneField(0xdeadda7)\n");
}
void SceneDataTest::fieldTypeSize() {
void SceneDataTest::fieldTypeSizeAlignment() {
/* Test at least one of every size */
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Byte), sizeof(Byte));
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Degh), sizeof(Degh));
@ -526,9 +534,16 @@ void SceneDataTest::fieldTypeSize() {
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix3x4d), sizeof(Matrix3x4d));
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix4x4d), sizeof(Matrix4x4d));
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Pointer), sizeof(const void*));
/* Test at least one of every alignment */
CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Vector3ub), alignof(UnsignedByte));
CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Matrix3x3h), alignof(Half));
CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Range3Di), alignof(UnsignedInt));
CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::DualComplexd), alignof(Double));
CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Pointer), alignof(const void*));
}
void SceneDataTest::fieldTypeSizeInvalid() {
void SceneDataTest::fieldTypeSizeAlignmentInvalid() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
@ -537,11 +552,15 @@ void SceneDataTest::fieldTypeSizeInvalid() {
Error redirectError{&out};
sceneFieldTypeSize(SceneFieldType{});
sceneFieldTypeAlignment(SceneFieldType{});
sceneFieldTypeSize(SceneFieldType(0xdead));
sceneFieldTypeAlignment(SceneFieldType(0xdead));
CORRADE_COMPARE(out.str(),
"Trade::sceneFieldTypeSize(): invalid type Trade::SceneFieldType(0x0)\n"
"Trade::sceneFieldTypeSize(): invalid type Trade::SceneFieldType(0xdead)\n");
"Trade::sceneFieldTypeAlignment(): invalid type Trade::SceneFieldType(0x0)\n"
"Trade::sceneFieldTypeSize(): invalid type Trade::SceneFieldType(0xdead)\n"
"Trade::sceneFieldTypeAlignment(): invalid type Trade::SceneFieldType(0xdead)\n");
}
void SceneDataTest::debugFieldType() {

Loading…
Cancel
Save