diff --git a/src/Magnum/Trade/MeshData.h b/src/Magnum/Trade/MeshData.h index 3e8b94d17..72a2f8f3d 100644 --- a/src/Magnum/Trade/MeshData.h +++ b/src/Magnum/Trade/MeshData.h @@ -483,6 +483,15 @@ class MAGNUM_TRADE_EXPORT MeshAttributeData { * by GPU APIs. */ explicit MeshAttributeData(MeshAttribute name, VertexFormat format, const Containers::StridedArrayView1D& data, UnsignedShort arraySize = 0, Int morphTargetId = -1) noexcept; + #ifndef DOXYGEN_GENERATING_OUTPUT + /* These two are here to direct StridedArrayView1D<[const ]char> to the + 1D overload, because that's likely what one wants. The 2D conversion + adds a dimension at the front, which would make the attribute have + just a single vertex with likely a sparse second dimension, causing + an immediate assert. */ + explicit MeshAttributeData(MeshAttribute name, VertexFormat format, const Containers::StridedArrayView1D& data, UnsignedShort arraySize = 0, Int morphTargetId = -1) noexcept: MeshAttributeData{name, format, Containers::StridedArrayView1D{data}, arraySize, morphTargetId} {} + explicit MeshAttributeData(MeshAttribute name, VertexFormat format, const Containers::StridedArrayView1D& data, UnsignedShort arraySize = 0, Int morphTargetId = -1) noexcept: MeshAttributeData{name, format, Containers::StridedArrayView1D{data}, arraySize, morphTargetId} {} + #endif /** * @brief Constructor diff --git a/src/Magnum/Trade/Test/MeshDataTest.cpp b/src/Magnum/Trade/Test/MeshDataTest.cpp index 63d02a19d..9a1100ab7 100644 --- a/src/Magnum/Trade/Test/MeshDataTest.cpp +++ b/src/Magnum/Trade/Test/MeshDataTest.cpp @@ -73,6 +73,7 @@ struct MeshDataTest: TestSuite::Tester { void constructAttribute2DNonContiguous(); void constructAttributeTypeErased(); void constructAttributeTypeErasedMorphTarget(); + template void constructAttributeTypeErasedCharAmbiguity(); void constructAttributeNullptr(); void constructAttributeNullptrMorphTarget(); void constructAttributePadding(); @@ -284,6 +285,8 @@ MeshDataTest::MeshDataTest() { &MeshDataTest::constructAttribute2DNonContiguous, &MeshDataTest::constructAttributeTypeErased, &MeshDataTest::constructAttributeTypeErasedMorphTarget, + &MeshDataTest::constructAttributeTypeErasedCharAmbiguity, + &MeshDataTest::constructAttributeTypeErasedCharAmbiguity, &MeshDataTest::constructAttributeNullptr, &MeshDataTest::constructAttributeNullptrMorphTarget, &MeshDataTest::constructAttributePadding, @@ -1043,6 +1046,34 @@ void MeshDataTest::constructAttributeTypeErasedMorphTarget() { CORRADE_VERIFY(positions.data().data() == positionData); } +template struct NameTraits; +template<> struct NameTraits { + static const char* name() { return "char"; } +}; +template<> struct NameTraits { + static const char* name() { return "const char"; } +}; + +template void MeshDataTest::constructAttributeTypeErasedCharAmbiguity() { + setTestCaseTemplateName(NameTraits::name()); + + /* StridedArrayView1D<[const ]char> is convertible to both + StridedArrayView1D and StridedArrayView2D, + verify the void is preferred. 2D conversion would result in the size + being {1, 3} which doesn't make sense. */ + char data[3]{}; + Containers::StridedArrayView1D view = data; + MeshAttributeData attribute{meshAttributeCustom(15), VertexFormat::Byte, view, 0, 33}; + CORRADE_VERIFY(!attribute.isOffsetOnly()); + CORRADE_COMPARE(attribute.arraySize(), 0); + CORRADE_COMPARE(attribute.morphTargetId(), 33); + CORRADE_COMPARE(attribute.name(), meshAttributeCustom(15)); + CORRADE_COMPARE(attribute.format(), VertexFormat::Byte); + /* If the delegation would be wrong, size would be 1 */ + CORRADE_COMPARE(attribute.data().size(), 3); + CORRADE_VERIFY(attribute.data().data() == data); +} + void MeshDataTest::constructAttributeNullptr() { MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector2, nullptr}; CORRADE_VERIFY(!positions.isOffsetOnly());