diff --git a/src/Magnum/SceneTools/Filter.cpp b/src/Magnum/SceneTools/Filter.cpp index e52229c17..8d7b1f2ff 100644 --- a/src/Magnum/SceneTools/Filter.cpp +++ b/src/Magnum/SceneTools/Filter.cpp @@ -204,10 +204,16 @@ Trade::SceneData filterFieldEntries(const Trade::SceneData& scene, const Contain filteredMapping = {{nullptr, mappingTypeSize*filteredFieldSize}, filteredFieldSize, std::ptrdiff_t(mappingTypeSize)}; } + /* Preserve flags, but if the field was marked as having implicit + mapping before, item removal causes it to be only ordered now */ + Trade::SceneFieldFlags fieldFlags = scene.fieldFlags(fieldId); + if(fieldFlags >= Trade::SceneFieldFlag::ImplicitMapping) + fieldFlags &= (~Trade::SceneFieldFlag::ImplicitMapping)|Trade::SceneFieldFlag::OrderedMapping; + const std::size_t fieldTypeSize = Trade::sceneFieldTypeSize(fieldType); fields[fieldId] = Trade::SceneFieldData{scene.fieldName(fieldId), scene.mappingType(), filteredMapping, - fieldType, Containers::StridedArrayView1D{{nullptr, fieldTypeSize*filteredFieldSize}, filteredFieldSize, std::ptrdiff_t(fieldTypeSize)}, scene.fieldArraySize(fieldId)}; + fieldType, Containers::StridedArrayView1D{{nullptr, fieldTypeSize*filteredFieldSize}, filteredFieldSize, std::ptrdiff_t(fieldTypeSize)}, scene.fieldArraySize(fieldId), fieldFlags}; ++sharedMapping.filteredCount; } diff --git a/src/Magnum/SceneTools/Filter.h b/src/Magnum/SceneTools/Filter.h index f0ecaea40..11e5382a3 100644 --- a/src/Magnum/SceneTools/Filter.h +++ b/src/Magnum/SceneTools/Filter.h @@ -115,6 +115,15 @@ mapping only partially don't have any special handling. The data repacking is performed using @ref combineFields(), see its documentation for more information. +Field flags are preserved except for @ref Trade::SceneFieldFlag::ImplicitMapping +--- if a field with this flag is present in the list, the field is downgraded +to @ref Trade::SceneFieldFlag::OrderedMapping, as removing field entries makes +the mapping to no longer be an implicit sequence (but the order is still +preserved). For simplicity this downgrade happens always, even if all bits for +given field may be set. Fields with +@ref Trade::SceneFieldFlag::ImplicitMapping that aren't present in the list +have the flag preserved. + As an example, let's assume in the following snippet the scene contains @ref Trade::SceneField::Translation, @relativeref{Trade::SceneField,Rotation}, @relativeref{Trade::SceneField,Mesh}, diff --git a/src/Magnum/SceneTools/Test/FilterTest.cpp b/src/Magnum/SceneTools/Test/FilterTest.cpp index a6a9b083b..2ea6576a7 100644 --- a/src/Magnum/SceneTools/Test/FilterTest.cpp +++ b/src/Magnum/SceneTools/Test/FilterTest.cpp @@ -315,11 +315,11 @@ void FilterTest::fieldEntries() { setTestCaseDescription(data.name); const struct Data { - UnsignedShort meshMapping[5]{7, 8, 6666, 3, 6666}; + UnsignedShort meshMapping[5]{7, 8, 900, 1000, 11000}; UnsignedByte mesh[5]{2, 3, 222, 1, 222}; - UnsignedShort lightMapping[4]{3, 1, 2, 2}; + UnsignedShort lightMapping[4]{0, 1, 2, 3}; UnsignedInt light[4]{12, 23, 32, 31}; - UnsignedShort arrayMapping[3]{6666, 3, 2}; + UnsignedShort arrayMapping[3]{0, 1, 2}; Float array[3][2]{{77.0f, 88.0f}, {1.0f, 2.0f}, {3.0f, 4.0f}}; UnsignedShort visibilityMapping[2]{12, 33}; bool visible[2]{true, false}; @@ -328,18 +328,25 @@ void FilterTest::fieldEntries() { } sceneData[1]{}; Trade::SceneData scene{Trade::SceneMappingType::UnsignedShort, 76, {}, sceneData, { + /* The ordered flag should get preserved as removing items preserves + order*/ Trade::SceneFieldData{Trade::SceneField::Mesh, Containers::arrayView(sceneData->meshMapping), - Containers::arrayView(sceneData->mesh)}, + Containers::arrayView(sceneData->mesh), + Trade::SceneFieldFlag::OrderedMapping}, /* Offset-only, to verify it get converted to absolute when it reaches - combine() at the end */ + combine() at the end. The implicit flag gets preserved because the + field isn't touched in any way. */ Trade::SceneFieldData{Trade::SceneField::Light, 4, Trade::SceneMappingType::UnsignedShort, offsetof(Data, lightMapping), sizeof(UnsignedShort), - Trade::SceneFieldType::UnsignedInt, offsetof(Data, light), sizeof(UnsignedInt)}, - /* Array */ + Trade::SceneFieldType::UnsignedInt, offsetof(Data, light), sizeof(UnsignedInt), + Trade::SceneFieldFlag::ImplicitMapping}, + /* Array. Here the flag gets downgraded to just an OrderedMapping + because items are removed. */ Trade::SceneFieldData{Trade::sceneFieldCustom(333), Containers::arrayView(sceneData->arrayMapping), - Containers::arrayCast<2, const Float>(Containers::stridedArrayView(sceneData->array))}, + Containers::arrayCast<2, const Float>(Containers::stridedArrayView(sceneData->array)), + Trade::SceneFieldFlag::ImplicitMapping}, /* Bit field. Should cause no assert as it's just passed through. */ Trade::SceneFieldData{Trade::sceneFieldCustom(15), Containers::arrayView(sceneData->visibilityMapping), @@ -384,8 +391,10 @@ void FilterTest::fieldEntries() { CORRADE_COMPARE(filtered.mappingBound(), 76); CORRADE_VERIFY(filtered.hasField(Trade::SceneField::Mesh)); + /* The flag gets preserved here */ + CORRADE_COMPARE(filtered.fieldFlags(Trade::SceneField::Mesh), Trade::SceneFieldFlag::OrderedMapping); CORRADE_COMPARE_AS(filtered.mapping(Trade::SceneField::Mesh), - Containers::arrayView({7, 8, 3}), + Containers::arrayView({7, 8, 1000}), TestSuite::Compare::Container); CORRADE_COMPARE_AS(filtered.field(Trade::SceneField::Mesh), Containers::arrayView({2, 3, 1}), @@ -393,6 +402,8 @@ void FilterTest::fieldEntries() { /* Lights weren't listed and thus stayed untouched */ CORRADE_VERIFY(filtered.hasField(Trade::SceneField::Light)); + /* The flag gets preserved here as well as the field wasn't touched */ + CORRADE_COMPARE(filtered.fieldFlags(Trade::SceneField::Light), Trade::SceneFieldFlag::ImplicitMapping); CORRADE_COMPARE_AS(filtered.mapping(Trade::SceneField::Light), Containers::arrayView(sceneData->lightMapping), TestSuite::Compare::Container); @@ -401,8 +412,10 @@ void FilterTest::fieldEntries() { TestSuite::Compare::Container); CORRADE_VERIFY(filtered.hasField(Trade::sceneFieldCustom(333))); + /* The field isn't implicitly mapped anymore */ + CORRADE_COMPARE(filtered.fieldFlags(Trade::sceneFieldCustom(333)), Trade::SceneFieldFlag::OrderedMapping); CORRADE_COMPARE_AS(filtered.mapping(Trade::sceneFieldCustom(333)), - Containers::arrayView({3, 2}), + Containers::arrayView({1, 2}), TestSuite::Compare::Container); CORRADE_COMPARE_AS((Containers::arrayCast<1, const Vector2>(filtered.field(Trade::sceneFieldCustom(333)))), Containers::arrayView({{1.0f, 2.0f}, {3.0f, 4.0f}}), @@ -795,10 +808,12 @@ template void FilterTest::objects() { Trade::SceneFieldData{Trade::SceneField::Light, Containers::arrayView(data->lightMapping), Containers::arrayView(data->light)}, - /* This one gets all entries removed */ + /* This one gets all entries removed. The flags should get preserved + even in that case tho. */ Trade::SceneFieldData{Trade::SceneField::Parent, Containers::arrayView(data->parentMapping), - Containers::arrayView(data->parents)}, + Containers::arrayView(data->parents), + Trade::SceneFieldFlag::OrderedMapping}, /* This one is already empty */ Trade::SceneFieldData{Trade::SceneField::Camera, Containers::ArrayView{}, @@ -832,8 +847,9 @@ template void FilterTest::objects() { Containers::arrayView({23}), TestSuite::Compare::Container); - /* Parents are all removed */ + /* Parents are all removed, flags stay */ CORRADE_VERIFY(filtered.hasField(Trade::SceneField::Parent)); + CORRADE_COMPARE(filtered.fieldFlags(Trade::SceneField::Parent), Trade::SceneFieldFlag::OrderedMapping); CORRADE_COMPARE(filtered.fieldSize(Trade::SceneField::Parent), 0); /* Cameras were empty before already */