diff --git a/doc/changelog.dox b/doc/changelog.dox index cc3f4e719..efb0a290a 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -830,6 +830,19 @@ See also: children that got deprecated in favor of @ref Trade::SceneData::SceneData(SceneObjectType, UnsignedLong, Containers::Array&&, Containers::Array&&, const void*) no longer accepts a scene that has both 2D and 3D children. +- The deprecated @cpp Trade::AbstractImporter::object*DCount() @ce, + @cpp Trade::AbstractImporter::object*DForName() @ce, + @cpp Trade::AbstractImporter::object*DName() @ce and + @cpp Trade::AbstractImporter::object*D() @ce accessors now behave different + for objects with multiple mesh assignments. This handling was originally + present in importer plugins themselves, but as the new + @ref Trade::SceneData representation supports multiple mesh/camera/... + assignments to a single object natively, the handling was moved to a single + place in the compatibility layer. Because the compatibility layer cannot + renumber object IDs, the newly added objects are not immediately following + the original ID but instead allocated at the end of the object ID range + reported by the importer. While the newly added objects have different IDs, + they retain the parent name like before. - @ref Trade::AbstractImporter::doDefaultScene() is now @cpp const @ce --- since the function is not expected to fail, no kind of complex lazy population can be done anyway. This is now consistent with `do*Count()` diff --git a/src/Magnum/Trade/AbstractImporter.cpp b/src/Magnum/Trade/AbstractImporter.cpp index 3b027b931..b000a55a7 100644 --- a/src/Magnum/Trade/AbstractImporter.cpp +++ b/src/Magnum/Trade/AbstractImporter.cpp @@ -48,6 +48,8 @@ #include #include +#include "Magnum/Trade/Implementation/sceneTools.h" + #define _MAGNUM_NO_DEPRECATED_MESHDATA /* So it doesn't yell here */ #define _MAGNUM_NO_DEPRECATED_OBJECTDATA /* So it doesn't yell here */ @@ -519,12 +521,20 @@ void AbstractImporter::populateCachedScenes() { _cachedScenes->scenes = Containers::Array>{sceneCount()}; for(UnsignedInt i = 0; i != _cachedScenes->scenes.size(); ++i) { _cachedScenes->scenes[i] = scene(i); - - /* Return the 2D/3D object count based on which scenes are 2D and which - not. The objectCount() provided by the importer is ignored except - for the above, also because it doesn't take into account the - restriction for unique-functioning objects. */ if(_cachedScenes->scenes[i]) { + /* Convert the scene so that each object has only either a mesh + (potentially with a material and a skin), a camera or a light. + The tool requires SceneField::Parent to be present, however if + it's not then we treat the scene as empty in the backwards + compatibility code path anyway, so just skip the processing + altogether in that case. */ + if(_cachedScenes->scenes[i]->hasField(SceneField::Parent)) + _cachedScenes->scenes[i] = Implementation::sceneConvertToSingleFunctionObjects(*_cachedScenes->scenes[i], Containers::arrayView({SceneField::Mesh, SceneField::Camera, SceneField::Light}), objectCount()); + + /* Return the 2D/3D object count based on which scenes are 2D and + which not. The objectCount() provided by the importer is ignored + except for the above, also because it doesn't take into account + the restriction for unique-functioning objects. */ if(_cachedScenes->scenes[i]->is2D()) _cachedScenes->object2DCount = Math::max(_cachedScenes->object2DCount, UnsignedInt(_cachedScenes->scenes[i]->objectCount())); if(_cachedScenes->scenes[i]->is3D()) @@ -578,8 +588,23 @@ std::string AbstractImporter::object2DName(const UnsignedInt id) { } std::string AbstractImporter::doObject2DName(const UnsignedInt id) { - /* Alias to the new interface */ - return doObjectName(id); + /* Alias to the new interface if the ID is known to the new interface, + return an empty string for objects that got newly added in order to make + them single-functioning */ + if(id < doObjectCount()) return doObjectName(id); + + populateCachedScenes(); + for(UnsignedInt i = 0; i != _cachedScenes->scenes.size(); ++i) { + if(!_cachedScenes->scenes[i] || + !_cachedScenes->scenes[i]->is2D() || + _cachedScenes->scenes[i]->objectCount() <= id) + continue; + + if(Containers::Optional parent = _cachedScenes->scenes[i]->parentFor(id)) + return doObjectName(*parent); + } + + return ""; } CORRADE_IGNORE_DEPRECATED_PUSH @@ -638,8 +663,10 @@ Containers::Pointer AbstractImporter::doObject2D(const UnsignedInt const Containers::Array skin = scene.skinsFor(id); const Containers::Optional importerState = scene.importerStateFor(id); - /* All these should have at most 1 item as the old API doesn't have - any way to represent multi-function objects. */ + /* All these should have at most 1 item as the SceneData got processed to + have each object contain either just one mesh or one camera (materials + are implicitly shared with a mesh, skins also). Thus it doesn't matter + in which order we decide on the legacy object type. */ CORRADE_INTERNAL_ASSERT(camera.size() + mesh.size() <= 1); if(!mesh.empty()) { @@ -733,8 +760,23 @@ std::string AbstractImporter::object3DName(const UnsignedInt id) { } std::string AbstractImporter::doObject3DName(const UnsignedInt id) { - /* Alias to the new interface */ - return doObjectName(id); + /* Alias to the new interface if the ID is known to the new interface, + return an empty string for objects that got newly added in order to make + them single-functioning */ + if(id < doObjectCount()) return doObjectName(id); + + populateCachedScenes(); + for(UnsignedInt i = 0; i != _cachedScenes->scenes.size(); ++i) { + if(!_cachedScenes->scenes[i] || + !_cachedScenes->scenes[i]->is3D() || + _cachedScenes->scenes[i]->objectCount() <= id) + continue; + + if(Containers::Optional parent = _cachedScenes->scenes[i]->parentFor(id)) + return doObjectName(*parent); + } + + return ""; } CORRADE_IGNORE_DEPRECATED_PUSH /* Clang doesn't warn, but GCC does */ @@ -794,8 +836,10 @@ Containers::Pointer AbstractImporter::doObject3D(const UnsignedInt const Containers::Array light = scene.lightsFor(id); const Containers::Optional importerState = scene.importerStateFor(id); - /* All these should have at most 1 item as the old API doesn't have - any way to represent multi-function objects. */ + /* All these should have at most 1 item as the SceneData got processed to + have each object contain either just one mesh, one camera or one light + (materials are implicitly shared with a mesh, skins also). Thus it + doesn't matter in which order we decide on the legacy object type. */ CORRADE_INTERNAL_ASSERT(camera.size() + light.size() + mesh.size() <= 1); if(!mesh.empty()) { diff --git a/src/Magnum/Trade/Test/AbstractImporterTest.cpp b/src/Magnum/Trade/Test/AbstractImporterTest.cpp index 09aa1ad70..89e6bafff 100644 --- a/src/Magnum/Trade/Test/AbstractImporterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImporterTest.cpp @@ -51,6 +51,7 @@ #ifdef MAGNUM_BUILD_DEPRECATED #include #include +#include #define _MAGNUM_NO_DEPRECATED_MESHDATA /* So it doesn't yell here */ #define _MAGNUM_NO_DEPRECATED_OBJECTDATA /* So it doesn't yell here */ @@ -123,6 +124,8 @@ struct AbstractImporterTest: TestSuite::Tester { void sceneDeprecatedFallbackParentless3D(); void sceneDeprecatedFallbackTransformless2D(); void sceneDeprecatedFallbackTransformless3D(); + void sceneDeprecatedFallbackMultiFunctionObjects2D(); + void sceneDeprecatedFallbackMultiFunctionObjects3D(); #endif void sceneNameNotImplemented(); void objectNameNotImplemented(); @@ -405,6 +408,8 @@ AbstractImporterTest::AbstractImporterTest() { &AbstractImporterTest::sceneDeprecatedFallbackParentless3D, &AbstractImporterTest::sceneDeprecatedFallbackTransformless2D, &AbstractImporterTest::sceneDeprecatedFallbackTransformless3D, + &AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D, + &AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D, #endif &AbstractImporterTest::sceneForNameOutOfRange, &AbstractImporterTest::objectForNameOutOfRange, @@ -2676,6 +2681,406 @@ void AbstractImporterTest::sceneDeprecatedFallbackTransformless3D() { } CORRADE_IGNORE_DEPRECATED_POP } + +void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D() { + /* Mostly just a copy of SceneToolsTest::convertToSingleFunctionObjects() + except that here we can't use the convenience combining tool so it's + done by hand */ + + struct Parent { + UnsignedInt object; + Int parent; + }; + struct Mesh { + UnsignedInt object; + UnsignedInt mesh; + Int meshMaterial; + }; + struct Camera { + UnsignedInt object; + UnsignedInt camera; + }; + Containers::StridedArrayView1D parents; + Containers::StridedArrayView1D meshes; + Containers::StridedArrayView1D cameras; + Containers::Array dataData = Containers::ArrayTuple{ + {NoInit, 5, parents}, + {NoInit, 7, meshes}, + {NoInit, 2, cameras}, + }; + + Utility::copy({{15, -1}, {21, -1}, {22, 1}, {23, 2}, {1, -1}}, parents); + Utility::copy({ + {15, 6, 4}, + {23, 1, 0}, + {23, 2, 3}, + {23, 4, 2}, + {1, 7, 2}, + {15, 3, 1}, + {21, 5, -1} + }, meshes); + Utility::copy({{22, 1}, {1, 5}}, cameras); + + SceneData data{SceneObjectType::UnsignedInt, 32, std::move(dataData), { + SceneFieldData{SceneField::Parent, parents.slice(&Parent::object), parents.slice(&Parent::parent)}, + SceneFieldData{SceneField::Mesh, meshes.slice(&Mesh::object), meshes.slice(&Mesh::mesh)}, + SceneFieldData{SceneField::MeshMaterial, meshes.slice(&Mesh::object), meshes.slice(&Mesh::meshMaterial)}, + SceneFieldData{SceneField::Camera, cameras.slice(&Camera::object), cameras.slice(&Camera::camera)}, + /* Just to disambiguate this as a 2D scene */ + SceneFieldData{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Matrix3x3, nullptr}, + }}; + + struct Importer: AbstractImporter { + explicit Importer(SceneData&& data): _data{std::move(data)} {} + + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSceneCount() const override { return 3; } + UnsignedLong doObjectCount() const override { return 63; } + std::string doObjectName(UnsignedLong id) override { + if(id == 1) return "object 1"; + if(id == 15) return "object 15"; + if(id == 23) return "object 23"; + if(id == 62) return "last"; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + Containers::Optional doScene(UnsignedInt id) override { + /* This scene should get skipped when querying names as it's not + 2D */ + if(id == 0) + return SceneData{SceneObjectType::UnsignedByte, 32, nullptr, {}}; + /* This scene should get skipped when querying names as it has too + little objects */ + if(id == 1) + return SceneData{SceneObjectType::UnsignedByte, 32, nullptr, { + SceneFieldData{SceneField::Transformation, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Matrix3x3, nullptr} + }}; + if(id == 2) + return SceneData{SceneObjectType::UnsignedInt, 32, {}, _data.data(), sceneFieldDataNonOwningArray(_data.fieldData())}; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + private: + SceneData _data; + } importer{std::move(data)}; + + CORRADE_COMPARE(importer.sceneCount(), 3); + + Containers::Optional scene = importer.scene(2); + CORRADE_VERIFY(scene); + + CORRADE_IGNORE_DEPRECATED_PUSH + CORRADE_COMPARE_AS(scene->children2D(), + (std::vector{15, 21, 1}), + TestSuite::Compare::Container); + CORRADE_COMPARE_AS(scene->children3D(), + std::vector{}, + TestSuite::Compare::Container); + + /* Total object count reported by the importer plus four new added */ + CORRADE_COMPARE(importer.object2DCount(), 63 + 4); + CORRADE_COMPARE(importer.object3DCount(), 0); + + /* Object name should return parent names for the additional objects */ + CORRADE_COMPARE(importer.object2DName(62), "last"); + CORRADE_COMPARE(importer.object2DName(63), "object 23"); + CORRADE_COMPARE(importer.object2DName(64), "object 23"); + CORRADE_COMPARE(importer.object2DName(65), "object 15"); + CORRADE_COMPARE(importer.object2DName(66), "object 1"); + + /* Only 9 objects should exist in total, go in order. Usually the object + IDs will be contiguous so no such mess as this happens. */ + { + Containers::Pointer o = importer.object2D(1); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType2D::Mesh); + CORRADE_COMPARE(o->instance(), 7); + CORRADE_COMPARE_AS(o->children(), + std::vector{66}, + TestSuite::Compare::Container); + MeshObjectData2D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 2); + } { + Containers::Pointer o = importer.object2D(15); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType2D::Mesh); + CORRADE_COMPARE(o->instance(), 6); + CORRADE_COMPARE_AS(o->children(), + std::vector{65}, + TestSuite::Compare::Container); + MeshObjectData2D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 4); + } { + Containers::Pointer o = importer.object2D(21); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType2D::Mesh); + CORRADE_COMPARE(o->instance(), 5); + CORRADE_COMPARE_AS(o->children(), + std::vector{22}, + TestSuite::Compare::Container); + MeshObjectData2D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), -1); + } { + Containers::Pointer o = importer.object2D(22); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType2D::Camera); + CORRADE_COMPARE(o->instance(), 1); + CORRADE_COMPARE_AS(o->children(), + std::vector{23}, + TestSuite::Compare::Container); + } { + Containers::Pointer o = importer.object2D(23); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType2D::Mesh); + CORRADE_COMPARE(o->instance(), 1); + CORRADE_COMPARE_AS(o->children(), + (std::vector{63, 64}), + TestSuite::Compare::Container); + MeshObjectData2D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 0); + } { + Containers::Pointer o = importer.object2D(63); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType2D::Mesh); + CORRADE_COMPARE(o->instance(), 2); + CORRADE_COMPARE_AS(o->children(), + std::vector{}, + TestSuite::Compare::Container); + MeshObjectData2D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 3); + } { + Containers::Pointer o = importer.object2D(64); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType2D::Mesh); + CORRADE_COMPARE(o->instance(), 4); + CORRADE_COMPARE_AS(o->children(), + std::vector{}, + TestSuite::Compare::Container); + MeshObjectData2D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 2); + } { + Containers::Pointer o = importer.object2D(65); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType2D::Mesh); + CORRADE_COMPARE(o->instance(), 3); + CORRADE_COMPARE_AS(o->children(), + std::vector{}, + TestSuite::Compare::Container); + MeshObjectData2D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 1); + } { + Containers::Pointer o = importer.object2D(66); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType2D::Camera); + CORRADE_COMPARE(o->instance(), 5); + CORRADE_COMPARE_AS(o->children(), + std::vector{}, + TestSuite::Compare::Container); + } + CORRADE_IGNORE_DEPRECATED_POP +} + +void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D() { + /* Mostly just a copy of SceneToolsTest::convertToSingleFunctionObjects() + except that here we can't use the convenience combining tool so it's + done by hand */ + + struct Parent { + UnsignedInt object; + Int parent; + }; + struct Mesh { + UnsignedInt object; + UnsignedInt mesh; + Int meshMaterial; + }; + struct Camera { + UnsignedInt object; + UnsignedInt camera; + }; + Containers::StridedArrayView1D parents; + Containers::StridedArrayView1D meshes; + Containers::StridedArrayView1D cameras; + Containers::Array dataData = Containers::ArrayTuple{ + {NoInit, 5, parents}, + {NoInit, 7, meshes}, + {NoInit, 2, cameras}, + }; + + Utility::copy({{15, -1}, {21, -1}, {22, 1}, {23, 2}, {1, -1}}, parents); + Utility::copy({ + {15, 6, 4}, + {23, 1, 0}, + {23, 2, 3}, + {23, 4, 2}, + {1, 7, 2}, + {15, 3, 1}, + {21, 5, -1} + }, meshes); + Utility::copy({{22, 1}, {1, 5}}, cameras); + + SceneData data{SceneObjectType::UnsignedInt, 32, std::move(dataData), { + SceneFieldData{SceneField::Parent, parents.slice(&Parent::object), parents.slice(&Parent::parent)}, + SceneFieldData{SceneField::Mesh, meshes.slice(&Mesh::object), meshes.slice(&Mesh::mesh)}, + SceneFieldData{SceneField::MeshMaterial, meshes.slice(&Mesh::object), meshes.slice(&Mesh::meshMaterial)}, + SceneFieldData{SceneField::Camera, cameras.slice(&Camera::object), cameras.slice(&Camera::camera)}, + /* Just to disambiguate this as a 3D scene */ + SceneFieldData{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Matrix4x4, nullptr}, + }}; + + struct Importer: AbstractImporter { + explicit Importer(SceneData&& data): _data{std::move(data)} {} + + ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSceneCount() const override { return 3; } + UnsignedLong doObjectCount() const override { return 63; } + std::string doObjectName(UnsignedLong id) override { + if(id == 1) return "object 1"; + if(id == 15) return "object 15"; + if(id == 23) return "object 23"; + if(id == 62) return "last"; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + Containers::Optional doScene(UnsignedInt id) override { + /* This scene should get skipped when querying names as it's not + 2D */ + if(id == 0) + return SceneData{SceneObjectType::UnsignedByte, 32, nullptr, {}}; + /* This scene should get skipped when querying names as it has too + little objects */ + if(id == 1) + return SceneData{SceneObjectType::UnsignedByte, 32, nullptr, { + SceneFieldData{SceneField::Transformation, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Matrix4x4, nullptr} + }}; + if(id == 2) + return SceneData{SceneObjectType::UnsignedInt, 32, {}, _data.data(), sceneFieldDataNonOwningArray(_data.fieldData())}; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + private: + SceneData _data; + } importer{std::move(data)}; + + CORRADE_COMPARE(importer.sceneCount(), 3); + + Containers::Optional scene = importer.scene(2); + CORRADE_VERIFY(scene); + + CORRADE_IGNORE_DEPRECATED_PUSH + CORRADE_COMPARE_AS(scene->children2D(), + std::vector{}, + TestSuite::Compare::Container); + CORRADE_COMPARE_AS(scene->children3D(), + (std::vector{15, 21, 1}), + TestSuite::Compare::Container); + + /* Total object count reported by the importer plus four new added */ + CORRADE_COMPARE(importer.object2DCount(), 0); + CORRADE_COMPARE(importer.object3DCount(), 63 + 4); + + /* Object name should return parent names for the additional objects */ + CORRADE_COMPARE(importer.object3DName(62), "last"); + CORRADE_COMPARE(importer.object3DName(63), "object 23"); + CORRADE_COMPARE(importer.object3DName(64), "object 23"); + CORRADE_COMPARE(importer.object3DName(65), "object 15"); + CORRADE_COMPARE(importer.object3DName(66), "object 1"); + + /* Only 9 objects should exist in total, go in order. Usually the object + IDs will be contiguous so no such mess as this happens. */ + { + Containers::Pointer o = importer.object3D(1); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType3D::Mesh); + CORRADE_COMPARE(o->instance(), 7); + CORRADE_COMPARE_AS(o->children(), + std::vector{66}, + TestSuite::Compare::Container); + MeshObjectData3D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 2); + } { + Containers::Pointer o = importer.object3D(15); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType3D::Mesh); + CORRADE_COMPARE(o->instance(), 6); + CORRADE_COMPARE_AS(o->children(), + std::vector{65}, + TestSuite::Compare::Container); + MeshObjectData3D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 4); + } { + Containers::Pointer o = importer.object3D(21); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType3D::Mesh); + CORRADE_COMPARE(o->instance(), 5); + CORRADE_COMPARE_AS(o->children(), + std::vector{22}, + TestSuite::Compare::Container); + MeshObjectData3D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), -1); + } { + Containers::Pointer o = importer.object3D(22); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType3D::Camera); + CORRADE_COMPARE(o->instance(), 1); + CORRADE_COMPARE_AS(o->children(), + std::vector{23}, + TestSuite::Compare::Container); + } { + Containers::Pointer o = importer.object3D(23); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType3D::Mesh); + CORRADE_COMPARE(o->instance(), 1); + CORRADE_COMPARE_AS(o->children(), + (std::vector{63, 64}), + TestSuite::Compare::Container); + MeshObjectData3D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 0); + } { + Containers::Pointer o = importer.object3D(63); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType3D::Mesh); + CORRADE_COMPARE(o->instance(), 2); + CORRADE_COMPARE_AS(o->children(), + std::vector{}, + TestSuite::Compare::Container); + MeshObjectData3D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 3); + } { + Containers::Pointer o = importer.object3D(64); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType3D::Mesh); + CORRADE_COMPARE(o->instance(), 4); + CORRADE_COMPARE_AS(o->children(), + std::vector{}, + TestSuite::Compare::Container); + MeshObjectData3D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 2); + } { + Containers::Pointer o = importer.object3D(65); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType3D::Mesh); + CORRADE_COMPARE(o->instance(), 3); + CORRADE_COMPARE_AS(o->children(), + std::vector{}, + TestSuite::Compare::Container); + MeshObjectData3D& mo = static_cast(*o); + CORRADE_COMPARE(mo.material(), 1); + } { + Containers::Pointer o = importer.object3D(66); + CORRADE_VERIFY(o); + CORRADE_COMPARE(o->instanceType(), ObjectInstanceType3D::Camera); + CORRADE_COMPARE(o->instance(), 5); + CORRADE_COMPARE_AS(o->children(), + std::vector{}, + TestSuite::Compare::Container); + } + CORRADE_IGNORE_DEPRECATED_POP +} #endif void AbstractImporterTest::sceneNameNotImplemented() {