diff --git a/src/Magnum/SceneTools/Test/CMakeLists.txt b/src/Magnum/SceneTools/Test/CMakeLists.txt index f6fbce27f..208885c27 100644 --- a/src/Magnum/SceneTools/Test/CMakeLists.txt +++ b/src/Magnum/SceneTools/Test/CMakeLists.txt @@ -52,72 +52,80 @@ corrade_add_test(SceneToolsConvertToSingleFun___Test ConvertToSingleFunctionObje corrade_add_test(SceneToolsFlattenMeshHierarchyTest FlattenMeshHierarchyTest.cpp LIBRARIES MagnumSceneToolsTestLib) corrade_add_test(SceneToolsOrderClusterParentsTest OrderClusterParentsTest.cpp LIBRARIES MagnumSceneToolsTestLib) -corrade_add_test(SceneToolsSceneConverterTest SceneConverterTest.cpp - LIBRARIES - MagnumSceneTools - # Link the same static plugins as for the magnum-sceneconverter - # executable so plugin existence checks are consistent between the two - ${MAGNUM_SCENECONVERTER_STATIC_PLUGINS} +corrade_add_test(SceneToolsSceneConverterImple___Test SceneConverterImplementationTest.cpp + LIBRARIES MagnumSceneTools FILES - SceneConverterTestFiles/blue4x4.png - # magnum-imageconverter --layers blue4x4.png --array blue4x4x1.ktx2 -c writerName= - SceneConverterTestFiles/blue4x4x1.ktx2 - SceneConverterTestFiles/broken-image-2d.gltf - SceneConverterTestFiles/broken-image-3d.gltf - SceneConverterTestFiles/broken-mesh.obj - SceneConverterTestFiles/broken-scene.gltf - SceneConverterTestFiles/dxt1.dds - SceneConverterTestFiles/empty.gltf - SceneConverterTestFiles/image-dds.gltf - SceneConverterTestFiles/images-2d.gltf - SceneConverterTestFiles/images-2d-1x1.bin - SceneConverterTestFiles/images-2d-1x1.gltf - SceneConverterTestFiles/images-3d.gltf - SceneConverterTestFiles/images-3d-1x1x1.bin - SceneConverterTestFiles/images-3d-1x1x1.gltf - SceneConverterTestFiles/info-data.txt - SceneConverterTestFiles/info-data-ignored-output.txt - SceneConverterTestFiles/info-animations.txt - SceneConverterTestFiles/info-cameras.txt - SceneConverterTestFiles/info-images.txt - SceneConverterTestFiles/info-lights.txt - SceneConverterTestFiles/info-materials.txt - SceneConverterTestFiles/info-meshes-bounds.txt - SceneConverterTestFiles/info-meshes.txt - SceneConverterTestFiles/info-objects.txt - SceneConverterTestFiles/info-references.txt - SceneConverterTestFiles/info-scenes-objects.txt - SceneConverterTestFiles/info-scenes.txt - SceneConverterTestFiles/info-skins.txt - SceneConverterTestFiles/info-textures.txt - SceneConverterTestFiles/point.obj - SceneConverterTestFiles/quad-duplicates-fuzzy.obj - SceneConverterTestFiles/quad-duplicates.obj - SceneConverterTestFiles/quad-duplicates.ply - SceneConverterTestFiles/quad-name-custom-attributes-duplicates.bin - SceneConverterTestFiles/quad-name-custom-attributes-duplicates.gltf - SceneConverterTestFiles/quad-name-custom-attributes.bin - SceneConverterTestFiles/quad-name-custom-attributes.gltf - SceneConverterTestFiles/quad-normals-texcoords.obj - SceneConverterTestFiles/quad-strip.bin - SceneConverterTestFiles/quad-strip.gltf - SceneConverterTestFiles/quad.bin - SceneConverterTestFiles/quad.gltf - SceneConverterTestFiles/quad.obj - SceneConverterTestFiles/quad.ply - SceneConverterTestFiles/red2x2.png - # magnum-imageconverter --layers red2x2.png --array red2x2x1.ktx2 -c writerName= - SceneConverterTestFiles/red2x2x1.ktx2 - SceneConverterTestFiles/two-quads-duplicates-fuzzy.bin - SceneConverterTestFiles/two-quads-duplicates-fuzzy.gltf - SceneConverterTestFiles/two-quads-duplicates.bin - SceneConverterTestFiles/two-quads-duplicates.gltf - SceneConverterTestFiles/two-quads.bin - SceneConverterTestFiles/two-quads.gltf - SceneConverterTestFiles/two-triangles-transformed.bin - SceneConverterTestFiles/two-triangles-transformed.gltf - SceneConverterTestFiles/two-triangles.obj) -target_include_directories(SceneToolsSceneConverterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$) -if(MAGNUM_WITH_SCENECONVERTER AND CORRADE_TARGET_UNIX) - add_dependencies(SceneToolsSceneConverterTest magnum-sceneconverter) + SceneConverterImplementationTestFiles/info-animations.txt + SceneConverterImplementationTestFiles/info-cameras.txt + SceneConverterImplementationTestFiles/info-images.txt + SceneConverterImplementationTestFiles/info-lights.txt + SceneConverterImplementationTestFiles/info-materials.txt + SceneConverterImplementationTestFiles/info-meshes-bounds.txt + SceneConverterImplementationTestFiles/info-meshes.txt + SceneConverterImplementationTestFiles/info-objects.txt + SceneConverterImplementationTestFiles/info-references.txt + SceneConverterImplementationTestFiles/info-scenes-objects.txt + SceneConverterImplementationTestFiles/info-scenes.txt + SceneConverterImplementationTestFiles/info-skins.txt + SceneConverterImplementationTestFiles/info-textures.txt) +target_include_directories(SceneToolsSceneConverterImple___Test PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$) + +# Executable testing is implemented on Unix platforms only at the moment +if(CORRADE_TARGET_UNIX AND NOT CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT) + corrade_add_test(SceneToolsSceneConverterTest SceneConverterTest.cpp + LIBRARIES + MagnumSceneTools + # Link the same static plugins as for the magnum-sceneconverter + # executable so plugin existence checks are consistent between the two + ${MAGNUM_SCENECONVERTER_STATIC_PLUGINS} + FILES + SceneConverterTestFiles/blue4x4.png + # magnum-imageconverter --layers blue4x4.png --array blue4x4x1.ktx2 -c writerName= + SceneConverterTestFiles/blue4x4x1.ktx2 + SceneConverterTestFiles/broken-image-2d.gltf + SceneConverterTestFiles/broken-image-3d.gltf + SceneConverterTestFiles/broken-mesh.obj + SceneConverterTestFiles/broken-scene.gltf + SceneConverterTestFiles/dxt1.dds + SceneConverterTestFiles/empty.gltf + SceneConverterTestFiles/image-dds.gltf + SceneConverterTestFiles/images-2d.gltf + SceneConverterTestFiles/images-2d-1x1.bin + SceneConverterTestFiles/images-2d-1x1.gltf + SceneConverterTestFiles/images-3d.gltf + SceneConverterTestFiles/images-3d-1x1x1.bin + SceneConverterTestFiles/images-3d-1x1x1.gltf + SceneConverterTestFiles/info-data.txt + SceneConverterTestFiles/info-data-ignored-output.txt + SceneConverterTestFiles/point.obj + SceneConverterTestFiles/quad-duplicates-fuzzy.obj + SceneConverterTestFiles/quad-duplicates.obj + SceneConverterTestFiles/quad-duplicates.ply + SceneConverterTestFiles/quad-name-custom-attributes-duplicates.bin + SceneConverterTestFiles/quad-name-custom-attributes-duplicates.gltf + SceneConverterTestFiles/quad-name-custom-attributes.bin + SceneConverterTestFiles/quad-name-custom-attributes.gltf + SceneConverterTestFiles/quad-normals-texcoords.obj + SceneConverterTestFiles/quad-strip.bin + SceneConverterTestFiles/quad-strip.gltf + SceneConverterTestFiles/quad.bin + SceneConverterTestFiles/quad.gltf + SceneConverterTestFiles/quad.obj + SceneConverterTestFiles/quad.ply + SceneConverterTestFiles/red2x2.png + # magnum-imageconverter --layers red2x2.png --array red2x2x1.ktx2 -c writerName= + SceneConverterTestFiles/red2x2x1.ktx2 + SceneConverterTestFiles/two-quads-duplicates-fuzzy.bin + SceneConverterTestFiles/two-quads-duplicates-fuzzy.gltf + SceneConverterTestFiles/two-quads-duplicates.bin + SceneConverterTestFiles/two-quads-duplicates.gltf + SceneConverterTestFiles/two-quads.bin + SceneConverterTestFiles/two-quads.gltf + SceneConverterTestFiles/two-triangles-transformed.bin + SceneConverterTestFiles/two-triangles-transformed.gltf + SceneConverterTestFiles/two-triangles.obj) + target_include_directories(SceneToolsSceneConverterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$) + if(MAGNUM_WITH_SCENECONVERTER) + add_dependencies(SceneToolsSceneConverterTest magnum-sceneconverter) + endif() endif() diff --git a/src/Magnum/SceneTools/Test/SceneConverterImplementationTest.cpp b/src/Magnum/SceneTools/Test/SceneConverterImplementationTest.cpp new file mode 100644 index 000000000..cbc2b36c5 --- /dev/null +++ b/src/Magnum/SceneTools/Test/SceneConverterImplementationTest.cpp @@ -0,0 +1,1231 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "Magnum/Math/CubicHermite.h" +#include "Magnum/Math/Matrix3.h" +#include "Magnum/Math/Matrix4.h" + +#include "Magnum/SceneTools/Implementation/sceneConverterUtilities.h" + +#include "configure.h" + +namespace Magnum { namespace SceneTools { namespace Test { namespace { + +struct SceneConverterImplementationTest: TestSuite::Tester { + explicit SceneConverterImplementationTest(); + + void infoEmpty(); + void infoScenesObjects(); + void infoAnimations(); + void infoSkins(); + void infoLights(); + void infoCameras(); + void infoMaterials(); + void infoMeshes(); + void infoMeshesBounds(); + void infoTextures(); + void infoImages(); + /* Image info further tested in ImageConverterImplementationTest */ + void infoReferenceCount(); + void infoError(); + + Utility::Arguments _infoArgs; +}; + +using namespace Containers::Literals; +using namespace Math::Literals; + +const struct { + const char* name; + const char* arg; + const char* expected; + bool printVisualCheck; +} InfoScenesObjectsData[]{ + {"", "--info", "info-scenes-objects.txt", true}, + {"only scenes", "--info-scenes", "info-scenes.txt", false}, + {"only objects", "--info-objects", "info-objects.txt", false}, +}; + +const struct { + const char* name; + bool oneOrAll; + bool printVisualCheck; +} InfoOneOrAllData[]{ + {"", true, true}, + {"--info", false, false}, +}; + +SceneConverterImplementationTest::SceneConverterImplementationTest() { + addTests({&SceneConverterImplementationTest::infoEmpty}); + + addInstancedTests({&SceneConverterImplementationTest::infoScenesObjects}, + Containers::arraySize(InfoScenesObjectsData)); + + addInstancedTests({&SceneConverterImplementationTest::infoAnimations, + &SceneConverterImplementationTest::infoSkins, + &SceneConverterImplementationTest::infoLights, + &SceneConverterImplementationTest::infoCameras, + &SceneConverterImplementationTest::infoMaterials, + &SceneConverterImplementationTest::infoMeshes}, + Containers::arraySize(InfoOneOrAllData)); + + addTests({&SceneConverterImplementationTest::infoMeshesBounds}); + + addInstancedTests({&SceneConverterImplementationTest::infoTextures, + &SceneConverterImplementationTest::infoImages}, + Containers::arraySize(InfoOneOrAllData)); + + addTests({&SceneConverterImplementationTest::infoReferenceCount, + &SceneConverterImplementationTest::infoError}); + + /* A subset of arguments needed by the info printing code */ + _infoArgs.addBooleanOption("info") + .addBooleanOption("info-scenes") + .addBooleanOption("info-objects") + .addBooleanOption("info-animations") + .addBooleanOption("info-skins") + .addBooleanOption("info-lights") + .addBooleanOption("info-cameras") + .addBooleanOption("info-materials") + .addBooleanOption("info-meshes") + .addBooleanOption("info-textures") + .addBooleanOption("info-images") + .addBooleanOption("bounds"); +} + +void SceneConverterImplementationTest::infoEmpty() { + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + } importer; + + const char* argv[]{"", "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, {}, _infoArgs, importer, time) == false); + CORRADE_COMPARE(out.str(), ""); +} + +void SceneConverterImplementationTest::infoScenesObjects() { + auto&& data = InfoScenesObjectsData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + /* First scene has 4, second 7, the last three are not in any scene and + thus not listed. Object 5 has no fields and thus not listed either. */ + UnsignedLong doObjectCount() const override { return 10; } + UnsignedInt doSceneCount() const override { return 2; } + Containers::String doSceneName(UnsignedInt id) override { + return id == 0 ? "A simple scene" : ""; + } + Containers::String doObjectName(UnsignedLong id) override { + if(id == 0) return "Parent-less mesh"; + if(id == 2) return "Two meshes, shared among two scenes"; + if(id == 4) return "Two custom arrays"; + if(id == 6) return "Only in the second scene, but no fields, thus same as unreferenced"; + if(id == 8) return "Not in any scene"; + return ""; + } + Containers::String doSceneFieldName(UnsignedInt name) override { + if(name == 1337) return "DirectionVector"; + return ""; + } + Containers::Optional doScene(UnsignedInt id) override { + /* Builtin fields, some duplicated, one marked as ordered */ + if(id == 0) { + Containers::ArrayView parentMapping; + Containers::ArrayView parents; + Containers::ArrayView meshMapping; + Containers::ArrayView meshes; + Containers::ArrayTuple data{ + {NoInit, 3, parentMapping}, + {ValueInit, 3, parents}, + {NoInit, 4, meshMapping}, + {ValueInit, 4, meshes}, + }; + Utility::copy({1, 3, 2}, parentMapping); + Utility::copy({2, 0, 2, 1}, meshMapping); + /* No need to fill the data, zero-init is fine */ + return Trade::SceneData{Trade::SceneMappingType::UnsignedInt, 4, std::move(data), { + Trade::SceneFieldData{Trade::SceneField::Parent, parentMapping, parents}, + Trade::SceneFieldData{Trade::SceneField::Mesh, meshMapping, meshes, Trade::SceneFieldFlag::OrderedMapping}, + }}; + } + + /* Two custom fields, one array. Stored as an external memory. */ + if(id == 1) { + return Trade::SceneData{Trade::SceneMappingType::UnsignedByte, 8, Trade::DataFlag::ExternallyOwned|Trade::DataFlag::Mutable, scene2Data, { + Trade::SceneFieldData{Trade::sceneFieldCustom(42), Containers::arrayView(scene2Data->customMapping), Containers::arrayView(scene2Data->custom)}, + Trade::SceneFieldData{Trade::sceneFieldCustom(1337), Trade::SceneMappingType::UnsignedByte, scene2Data->customArrayMapping, Trade::SceneFieldType::Short, scene2Data->customArray, 3}, + }}; + } + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + struct { + UnsignedByte customMapping[2]; + Double custom[2]; + UnsignedByte customArrayMapping[3]; + Vector3s customArray[3]; + } scene2Data[1]{{ + /* No need to fill the data, zero-init is fine */ + {7, 3}, {}, {2, 4, 4}, {} + }}; + } importer; + + const char* argv[]{"", data.arg}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + if(data.printVisualCheck) { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, {}, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join({SCENETOOLS_TEST_DIR, "SceneConverterImplementationTestFiles", data.expected}), + TestSuite::Compare::StringToFile); +} + +void SceneConverterImplementationTest::infoAnimations() { + auto&& data = InfoOneOrAllData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doAnimationCount() const override { return 2; } + Containers::String doAnimationName(UnsignedInt id) override { + return id == 1 ? "Custom track duration and interpolator function" : ""; + } + Containers::Optional doAnimation(UnsignedInt id) override { + /* First has two tracks with a shared time and implicit duration, + one with a different result type. */ + if(id == 0) { + Containers::ArrayView time; + Containers::ArrayView translation; + Containers::ArrayView rotation; + Containers::ArrayTuple data{ + {ValueInit, 3, time}, + {ValueInit, 3, translation}, + {ValueInit, 3, rotation} + }; + Utility::copy({0.5f, 1.0f, 1.25f}, time); + return Trade::AnimationData{std::move(data), { + /** @todo cleanup once AnimationTrackData has sane + constructors */ + Trade::AnimationTrackData{Trade::AnimationTrackTargetType::Translation2D, 17, Animation::TrackView{time, translation, Animation::Interpolation::Linear, Animation::Extrapolation::DefaultConstructed, Animation::Extrapolation::Constant}}, + Trade::AnimationTrackData{Trade::AnimationTrackTargetType::Rotation2D, 17, Animation::TrackView{time, rotation, Animation::Interpolation::Constant, Animation::Extrapolation::Extrapolated}}, + }}; + } + + /* Second has track duration different from animation duration and + a custom interpolator. Stored as an external memory. */ + if(id == 1) { + return Trade::AnimationData{Trade::DataFlag::ExternallyOwned, animation2Data, { + /** @todo cleanup once AnimationTrackData has sane + constructors */ + Trade::AnimationTrackData{Trade::AnimationTrackTargetType::Scaling3D, 666, Animation::TrackView{animation2Data->time, animation2Data->scaling, Math::lerp, Animation::Extrapolation::DefaultConstructed, Animation::Extrapolation::Constant}}, + }, {0.1f, 1.3f}}; + } + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + struct { + Float time[5]; + Vector3 scaling[5]; + } animation2Data[1]{{ + {0.75f, 0.75f, 1.0f, 1.0f, 1.25f}, + {} + }}; + } importer; + + const char* argv[]{"", data.oneOrAll ? "--info-animations" : "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + if(data.printVisualCheck) { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, {}, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterImplementationTestFiles/info-animations.txt"), + TestSuite::Compare::StringToFile); +} + +void SceneConverterImplementationTest::infoSkins() { + auto&& data = InfoOneOrAllData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doSkin2DCount() const override { return 2; } + Containers::String doSkin2DName(UnsignedInt id) override { + return id == 1 ? "Second 2D skin, external data" : ""; + } + Containers::Optional doSkin2D(UnsignedInt id) override { + /* First a regular skin, second externally owned */ + if(id == 0) return Trade::SkinData2D{ + {3, 6, 7, 12, 22}, + {{}, {}, {}, {}, {}} + }; + + if(id == 1) return Trade::SkinData2D{Trade::DataFlag::ExternallyOwned, skin2JointData, Trade::DataFlag::ExternallyOwned, skin2MatrixData}; + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt doSkin3DCount() const override { return 3; } + Containers::String doSkin3DName(UnsignedInt id) override { + return id == 0 ? "First 3D skin, external data" : ""; + } + Containers::Optional doSkin3D(UnsignedInt id) override { + /* Reverse order in 3D, plus one more to ensure the count isn't + mismatched between 2D and 3D */ + if(id == 0) return Trade::SkinData3D{Trade::DataFlag::ExternallyOwned, skin3JointData, Trade::DataFlag::ExternallyOwned, skin3MatrixData}; + + if(id == 1) return Trade::SkinData3D{ + {3, 22}, + {{}, {}} + }; + + if(id == 2) return Trade::SkinData3D{ + {3}, + {{}} + }; + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt skin2JointData[15]; + Matrix3 skin2MatrixData[15]; + UnsignedInt skin3JointData[12]; + Matrix4 skin3MatrixData[12]; + } importer; + + const char* argv[]{"", data.oneOrAll ? "--info-skins" : "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + if(data.printVisualCheck) { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, {}, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterImplementationTestFiles/info-skins.txt"), + TestSuite::Compare::StringToFile); +} + +void SceneConverterImplementationTest::infoLights() { + auto&& data = InfoOneOrAllData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doLightCount() const override { return 2; } + Containers::String doLightName(UnsignedInt id) override { + return id == 1 ? "Directional light with always-implicit attenuation and range" : ""; + } + Containers::Optional doLight(UnsignedInt id) override { + /* First a blue spot light */ + if(id == 0) return Trade::LightData{ + Trade::LightData::Type::Spot, + 0x3457ff_rgbf, + 15.0f, + {1.2f, 0.3f, 0.04f}, + 100.0f, + 55.0_degf, + 85.0_degf + }; + + /* Second a yellow directional light with infinite range */ + if(id == 1) return Trade::LightData{ + Trade::LightData::Type::Directional, + 0xff5734_rgbf, + 5.0f + }; + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + } importer; + + const char* argv[]{"", data.oneOrAll ? "--info-lights" : "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + if(data.printVisualCheck) { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterImplementationTestFiles/info-lights.txt"), + TestSuite::Compare::StringToFile); +} + +void SceneConverterImplementationTest::infoCameras() { + auto&& data = InfoOneOrAllData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doCameraCount() const override { return 3; } + Containers::String doCameraName(UnsignedInt id) override { + return id == 0 ? "Orthographic 2D" : ""; + } + Containers::Optional doCamera(UnsignedInt id) override { + /* First 2D ortho camera, where near/far will get omited */ + if(id == 0) return Trade::CameraData{ + Trade::CameraType::Orthographic2D, + {5.0f, 6.0f}, + 0.0f, 0.0f + }; + + /* 3D ortho camera */ + if(id == 1) return Trade::CameraData{ + Trade::CameraType::Orthographic3D, + {2.0f, 3.0f}, + -1.0f, 0.5f + }; + + /* Third a perspective camera, specified with size, but printed + with FoV */ + if(id == 2) return Trade::CameraData{ + Trade::CameraType::Perspective3D, + 35.0_degf, 4.0f/3.0f, 0.01f, 100.0f + }; + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + } importer; + + const char* argv[]{"", data.oneOrAll ? "--info-cameras" : "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + if(data.printVisualCheck) { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterImplementationTestFiles/info-cameras.txt"), + TestSuite::Compare::StringToFile); +} + +void SceneConverterImplementationTest::infoMaterials() { + auto&& data = InfoOneOrAllData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doMaterialCount() const override { return 2; } + Containers::String doMaterialName(UnsignedInt id) override { + return id == 1 ? "Lots o' laierz" : ""; + } + Containers::Optional doMaterial(UnsignedInt id) override { + /* First has custom attributes */ + if(id == 0) return Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { + {Trade::MaterialAttribute::BaseColor, 0x3bd26799_rgbaf}, + {Trade::MaterialAttribute::DoubleSided, true}, + {Trade::MaterialAttribute::EmissiveColor, 0xe9eca_rgbf}, + {Trade::MaterialAttribute::RoughnessTexture, 67u}, + {Trade::MaterialAttribute::RoughnessTextureMatrix, Matrix3::translation({0.25f, 0.75f})}, + {Trade::MaterialAttribute::RoughnessTextureSwizzle, Trade::MaterialTextureSwizzle::B}, + {"reflectionAngle", 35.0_degf}, + /* These shouldn't have a color swatch rendered */ + {"notAColour4", Vector4{0.1f, 0.2f, 0.3f, 0.4f}}, + {"notAColour3", Vector3{0.2f, 0.3f, 0.4f}}, + {"data", Containers::ArrayView{"0123456789abcdef", 17}}, + {"deadBeef", reinterpret_cast(0xdeadbeef)}, + {"undeadBeef", reinterpret_cast(0xbeefbeef)}, + }}; + + /* Second has layers, custom layers, unnamed layers and a name */ + if(id == 1) return Trade::MaterialData{Trade::MaterialType::PbrClearCoat|Trade::MaterialType::Phong, { + {Trade::MaterialAttribute::DiffuseColor, 0xc7cf2f99_rgbaf}, + {Trade::MaterialLayer::ClearCoat}, + {Trade::MaterialAttribute::LayerFactor, 0.5f}, + {Trade::MaterialAttribute::LayerFactorTexture, 3u}, + {Trade::MaterialAttribute::LayerName, "anEmptyLayer"}, + {Trade::MaterialAttribute::LayerFactor, 0.25f}, + {Trade::MaterialAttribute::LayerFactorTexture, 2u}, + {"yes", "a string"}, + }, {1, 4, 5, 8}}; + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + } importer; + + const char* argv[]{"", data.oneOrAll ? "--info-materials" : "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + if(data.printVisualCheck) { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterImplementationTestFiles/info-materials.txt"), + TestSuite::Compare::StringToFile); +} + +void SceneConverterImplementationTest::infoMeshes() { + auto&& data = InfoOneOrAllData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doMeshCount() const override { return 3; } + UnsignedInt doMeshLevelCount(UnsignedInt id) override { + return id == 1 ? 2 : 1; + } + Containers::String doMeshName(UnsignedInt id) override { + return id == 1 ? "LODs? No, meshets." : ""; + } + Containers::String doMeshAttributeName(UnsignedShort name) override { + if(name == 25) return "vertices"; + if(name == 26) return "triangles"; + /* 37 (triangleCount) deliberately not named */ + if(name == 116) return "vertexCount"; + + return ""; + } + Containers::Optional doMesh(UnsignedInt id, UnsignedInt level) override { + /* First is indexed & externally owned */ + if(id == 0 && level == 0) return Trade::MeshData{MeshPrimitive::Points, + Trade::DataFlag::ExternallyOwned, indices, + Trade::MeshIndexData{indices}, + Trade::DataFlag::ExternallyOwned|Trade::DataFlag::Mutable, points, { + Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::arrayView(points)} + }}; + + /* Second is multi-level, with second level being indexed meshlets + with custom (array) attributes */ + if(id == 1 && level == 0) { + Containers::ArrayView positions; + Containers::ArrayView tangents; + Containers::ArrayTuple data{ + {NoInit, 250, positions}, + {NoInit, 250, tangents}, + }; + return Trade::MeshData{MeshPrimitive::Triangles, std::move(data), { + Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}, + Trade::MeshAttributeData{Trade::MeshAttribute::Tangent, tangents}, + }}; + } + if(id == 1 && level == 1) { + Containers::StridedArrayView2D vertices; + Containers::StridedArrayView2D indices; + Containers::ArrayView triangleCount; + Containers::ArrayView vertexCount; + Containers::ArrayTuple data{ + {NoInit, {135, 64}, vertices}, + {NoInit, {135, 126}, indices}, + {NoInit, 135, triangleCount}, + {NoInit, 135, vertexCount}, + }; + return Trade::MeshData{MeshPrimitive::Meshlets, std::move(data), { + Trade::MeshAttributeData{Trade::meshAttributeCustom(25), vertices}, + Trade::MeshAttributeData{Trade::meshAttributeCustom(26), indices}, + Trade::MeshAttributeData{Trade::meshAttributeCustom(37), triangleCount}, + Trade::MeshAttributeData{Trade::meshAttributeCustom(116), vertexCount}, + }}; + } + + /* Third is an empty instance mesh */ + if(id == 2 && level == 0) return Trade::MeshData{MeshPrimitive::Instances, 15}; + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedShort indices[70]; + Vector3 points[50]; + } importer; + + const char* argv[]{"", data.oneOrAll ? "--info-meshes" : "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + if(data.printVisualCheck) { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterImplementationTestFiles/info-meshes.txt"), + TestSuite::Compare::StringToFile); +} + +void SceneConverterImplementationTest::infoMeshesBounds() { + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doMeshCount() const override { return 1; } + Containers::Optional doMesh(UnsignedInt, UnsignedInt) override { + return Trade::MeshData{MeshPrimitive::Lines, + {}, indexData, Trade::MeshIndexData{indexData}, + {}, vertexData, { + Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::arrayView(vertexData->positions)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Tangent, Containers::arrayView(vertexData->tangent)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Bitangent, Containers::arrayView(vertexData->bitangent)}, + Trade::MeshAttributeData{Trade::MeshAttribute::ObjectId, Containers::arrayView(vertexData->objectId)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Normal, Containers::arrayView(vertexData->normal)}, + Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, Containers::arrayView(vertexData->textureCoordinates)}, + Trade::MeshAttributeData{Trade::MeshAttribute::Color, Containers::arrayView(vertexData->color)}, + Trade::MeshAttributeData{Trade::MeshAttribute::ObjectId, Containers::arrayView(vertexData->objectIdSecondary)}, + }}; + } + + UnsignedByte indexData[3]{15, 3, 176}; + + struct { + Vector3 positions[2]; + Vector3 tangent[2]; + Vector3 bitangent[2]; + UnsignedShort objectId[2]; + Vector3 normal[2]; + Vector2 textureCoordinates[2]; + Vector4 color[2]; + UnsignedInt objectIdSecondary[2]; + } vertexData[1]{{ + {{0.1f, -0.1f, 0.2f}, {0.2f, 0.0f, -0.2f}}, + {{0.2f, -0.2f, 0.8f}, {0.3f, 0.8f, 0.2f}}, + {{0.4f, 0.2f, 1.0f}, {0.3f, 0.9f, 0.0f}}, + {155, 12}, + {{0.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 1.0f}}, + {{0.5f, 0.5f}, {1.5f, 0.5f}}, + {0x99336600_rgbaf, 0xff663333_rgbaf}, + {15, 337}, + }}; + } importer; + + const char* argv[]{"", "--info-meshes", "--bounds"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterImplementationTestFiles/info-meshes-bounds.txt"), + TestSuite::Compare::StringToFile); +} + +void SceneConverterImplementationTest::infoTextures() { + auto&& data = InfoOneOrAllData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doTextureCount() const override { return 2; } + Containers::String doTextureName(UnsignedInt id) override { + return id == 1 ? "Name!" : ""; + } + Containers::Optional doTexture(UnsignedInt id) override { + /* First a 1D texture */ + if(id == 0) return Trade::TextureData{ + Trade::TextureType::Texture1D, + SamplerFilter::Nearest, + SamplerFilter::Linear, + SamplerMipmap::Nearest, + SamplerWrapping::Repeat, + 666 + }; + + /* Second a 2D array texture */ + if(id == 1) return Trade::TextureData{ + Trade::TextureType::Texture2DArray, + SamplerFilter::Linear, + SamplerFilter::Nearest, + SamplerMipmap::Linear, + {SamplerWrapping::MirroredRepeat, SamplerWrapping::ClampToEdge, SamplerWrapping::MirrorClampToEdge}, + 3 + }; + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + } importer; + + const char* argv[]{"", data.oneOrAll ? "--info-textures" : "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + if(data.printVisualCheck) { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterImplementationTestFiles/info-textures.txt"), + TestSuite::Compare::StringToFile); +} + +void SceneConverterImplementationTest::infoImages() { + auto&& data = InfoOneOrAllData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + /* Just the very basics to ensure image info *is* printed. Tested in full + in ImageConverterTest. */ + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doImage1DCount() const override { return 1; } + Containers::Optional doImage1D(UnsignedInt, UnsignedInt) override { + return Trade::ImageData1D{PixelFormat::R32F, 1024, Containers::Array{NoInit, 4096}}; + } + } importer; + + const char* argv[]{"", data.oneOrAll ? "--info-images" : "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + if(data.printVisualCheck) { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterImplementationTestFiles/info-images.txt"), + TestSuite::Compare::StringToFile); +} + +void SceneConverterImplementationTest::infoReferenceCount() { + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + /* One data of each kind should be always referenced twice+, one once, + one not at all, and one reference should be OOB */ + + UnsignedLong doObjectCount() const override { return 4; } + Containers::String doObjectName(UnsignedLong id) override { + return id == 2 ? "Not referenced" : ""; + } + UnsignedInt doSceneCount() const override { return 2; } + Containers::Optional doScene(UnsignedInt id) override { + if(id == 0) return Trade::SceneData{Trade::SceneMappingType::UnsignedInt, 2, {}, sceneData3D, { + /* To mark the scene as 3D */ + Trade::SceneFieldData{Trade::SceneField::Transformation, Trade::SceneMappingType::UnsignedInt, nullptr, Trade::SceneFieldType::Matrix4x4, nullptr}, + Trade::SceneFieldData{Trade::SceneField::Mesh, + Containers::arrayView(sceneData3D->mapping), + Containers::arrayView(sceneData3D->meshes)}, + Trade::SceneFieldData{Trade::SceneField::MeshMaterial, + Containers::arrayView(sceneData3D->mapping), + Containers::arrayView(sceneData3D->materials)}, + Trade::SceneFieldData{Trade::SceneField::Light, + Containers::arrayView(sceneData3D->mapping), + Containers::arrayView(sceneData3D->lights)}, + Trade::SceneFieldData{Trade::SceneField::Camera, + Containers::arrayView(sceneData3D->mapping), + Containers::arrayView(sceneData3D->cameras)}, + Trade::SceneFieldData{Trade::SceneField::Skin, + Containers::arrayView(sceneData3D->mapping), + Containers::arrayView(sceneData3D->skins)}, + }}; + if(id == 1) return Trade::SceneData{Trade::SceneMappingType::UnsignedInt, 4, {}, sceneData2D, { + /* To mark the scene as 2D */ + Trade::SceneFieldData{Trade::SceneField::Transformation, Trade::SceneMappingType::UnsignedInt, nullptr, Trade::SceneFieldType::Matrix3x3, nullptr}, + Trade::SceneFieldData{Trade::SceneField::Mesh, + Containers::arrayView(sceneData2D->mapping), + Containers::arrayView(sceneData2D->meshes)}, + Trade::SceneFieldData{Trade::SceneField::Skin, + Containers::arrayView(sceneData2D->mapping), + Containers::arrayView(sceneData2D->skins)}, + }}; + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt doSkin2DCount() const override { return 3; } + Containers::String doSkin2DName(UnsignedInt id) override { + return id == 2 ? "Not referenced" : ""; + } + Containers::Optional doSkin2D(UnsignedInt id) override { + if(id == 0) return Trade::SkinData2D{ + {35, 22}, + {{}, {}} + }; + if(id == 1) return Trade::SkinData2D{ + {33, 10, 100}, + {{}, {}, {}} + }; + if(id == 2) return Trade::SkinData2D{ + {66}, + {{}} + }; + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt doSkin3DCount() const override { return 3; } + Containers::String doSkin3DName(UnsignedInt id) override { + return id == 0 ? "Not referenced" : ""; + } + Containers::Optional doSkin3D(UnsignedInt id) override { + if(id == 0) return Trade::SkinData3D{ + {35, 22}, + {{}, {}} + }; + if(id == 1) return Trade::SkinData3D{ + {37}, + {{}} + }; + if(id == 2) return Trade::SkinData3D{ + {300, 10, 1000}, + {{}, {}, {}} + }; + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt doLightCount() const override { return 3; } + Containers::String doLightName(UnsignedInt id) override { + return id == 1 ? "Not referenced" : ""; + } + Containers::Optional doLight(UnsignedInt id) override { + if(id == 0) return Trade::LightData{ + Trade::LightData::Type::Directional, + 0x57ff34_rgbf, + 5.0f + }; + if(id == 1) return Trade::LightData{ + Trade::LightData::Type::Ambient, + 0xff5734_rgbf, + 0.1f + }; + if(id == 2) return Trade::LightData{ + Trade::LightData::Type::Directional, + 0x3457ff_rgbf, + 1.0f + }; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt doCameraCount() const override { return 3; } + Containers::String doCameraName(UnsignedInt id) override { + return id == 0 ? "Not referenced" : ""; + } + Containers::Optional doCamera(UnsignedInt id) override { + if(id == 0) return Trade::CameraData{ + Trade::CameraType::Orthographic3D, + {2.0f, 3.0f}, + -1.0f, 0.5f + }; + if(id == 1) return Trade::CameraData{ + Trade::CameraType::Orthographic3D, + {2.0f, 2.0f}, + 0.0f, 1.0f + }; + if(id == 2) return Trade::CameraData{ + Trade::CameraType::Orthographic2D, + {2.0f, 2.0f}, + 0.0f, 0.0f + }; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt doMaterialCount() const override { return 3; } + Containers::String doMaterialName(UnsignedInt id) override { + return id == 2 ? "Not referenced" : ""; + } + Containers::Optional doMaterial(UnsignedInt id) override { + if(id == 0) return Trade::MaterialData{{}, { + {Trade::MaterialAttribute::DiffuseTexture, 2u}, + {Trade::MaterialAttribute::BaseColorTexture, 2u}, + }}; + if(id == 1) return Trade::MaterialData{{}, { + {"lookupTexture", 0u}, + {"volumeTexture", 3u}, + {Trade::MaterialAttribute::NormalTexture, 17u}, + {Trade::MaterialAttribute::EmissiveTexture, 4u}, + }}; + if(id == 2) return Trade::MaterialData{{}, {}}; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt doMeshCount() const override { return 3; } + Containers::String doMeshName(UnsignedInt id) override { + return id == 1 ? "Not referenced" : ""; + } + Containers::Optional doMesh(UnsignedInt id, UnsignedInt) override { + if(id == 0) return Trade::MeshData{MeshPrimitive::Points, 5}; + if(id == 1) return Trade::MeshData{MeshPrimitive::Lines, 4}; + if(id == 2) return Trade::MeshData{MeshPrimitive::TriangleFan, 4}; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt doTextureCount() const override { return 5; } + Containers::String doTextureName(UnsignedInt id) override { + return id == 1 ? "Not referenced" : ""; + } + Containers::Optional doTexture(UnsignedInt id) override { + if(id == 0) return Trade::TextureData{ + Trade::TextureType::Texture1D, + SamplerFilter::Nearest, + SamplerFilter::Linear, + SamplerMipmap::Nearest, + SamplerWrapping::Repeat, + 1 + }; + if(id == 1) return Trade::TextureData{ + Trade::TextureType::Texture1DArray, + SamplerFilter::Nearest, + SamplerFilter::Linear, + SamplerMipmap::Nearest, + SamplerWrapping::Repeat, + 225 + }; + if(id == 2) return Trade::TextureData{ + Trade::TextureType::Texture2D, + SamplerFilter::Nearest, + SamplerFilter::Linear, + SamplerMipmap::Nearest, + SamplerWrapping::Repeat, + 0 + }; + if(id == 3) return Trade::TextureData{ + Trade::TextureType::Texture3D, + SamplerFilter::Nearest, + SamplerFilter::Linear, + SamplerMipmap::Nearest, + SamplerWrapping::Repeat, + 1 + }; + if(id == 4) return Trade::TextureData{ + Trade::TextureType::Texture2D, + SamplerFilter::Nearest, + SamplerFilter::Linear, + SamplerMipmap::Nearest, + SamplerWrapping::Repeat, + 0 + }; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt doImage1DCount() const override { return 2; } + Containers::String doImage1DName(UnsignedInt id) override { + return id == 0 ? "Not referenced" : ""; + } + Containers::Optional doImage1D(UnsignedInt id, UnsignedInt) override { + if(id == 0) + return Trade::ImageData1D{PixelFormat::RGBA8I, 1, Containers::Array{NoInit, 4}}; + if(id == 1) + return Trade::ImageData1D{PixelFormat::R8I, 4, Containers::Array{NoInit, 4}}; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt doImage2DCount() const override { return 2; } + Containers::String doImage2DName(UnsignedInt id) override { + return id == 1 ? "Not referenced" : ""; + } + Containers::Optional doImage2D(UnsignedInt id, UnsignedInt) override { + if(id == 0) + return Trade::ImageData2D{PixelFormat::RGBA8I, {1, 2}, Containers::Array{NoInit, 8}}; + if(id == 1) + return Trade::ImageData2D{PixelFormat::R8I, {4, 1}, Containers::Array{NoInit, 4}}; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + UnsignedInt doImage3DCount() const override { return 2; } + Containers::String doImage3DName(UnsignedInt id) override { + return id == 0 ? "Not referenced" : ""; + } + Containers::Optional doImage3D(UnsignedInt id, UnsignedInt) override { + if(id == 0) + return Trade::ImageData3D{PixelFormat::RGBA8I, {1, 2, 1}, Containers::Array{NoInit, 8}}; + if(id == 1) + return Trade::ImageData3D{PixelFormat::R8I, {4, 1, 1}, Containers::Array{NoInit, 4}}; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + + struct { + UnsignedInt mapping[4]; + UnsignedInt meshes[4]; + Int materials[4]; + UnsignedInt lights[4]; + UnsignedInt cameras[4]; + UnsignedInt skins[4]; + } sceneData3D[1]{{ + {0, 1, 1, 25}, + {2, 0, 2, 67}, + {0, 1, 23, 0}, + {0, 17, 0, 2}, + {166, 1, 2, 1}, + {1, 1, 22, 2} + }}; + + struct { + UnsignedInt mapping[3]; + UnsignedInt meshes[3]; + UnsignedInt skins[3]; + } sceneData2D[1]{{ + {3, 116, 1}, + {2, 0, 23}, + {177, 0, 1} + }}; + } importer; + + const char* argv[]{"", "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterImplementationTestFiles/info-references.txt"), + TestSuite::Compare::StringToFile); +} + +void SceneConverterImplementationTest::infoError() { + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + /* The one single object is named, and that name should be printed + after all error messages */ + UnsignedLong doObjectCount() const override { return 1; } + Containers::String doObjectName(UnsignedLong) override { return "A name"; } + + UnsignedInt doSceneCount() const override { return 2; } + Containers::Optional doScene(UnsignedInt id) override { + Error{} << "Scene" << id << "error!"; + return {}; + } + + UnsignedInt doAnimationCount() const override { return 2; } + Containers::Optional doAnimation(UnsignedInt id) override { + Error{} << "Animation" << id << "error!"; + return {}; + } + + UnsignedInt doSkin2DCount() const override { return 2; } + Containers::Optional doSkin2D(UnsignedInt id) override { + Error{} << "2D skin" << id << "error!"; + return {}; + } + + UnsignedInt doSkin3DCount() const override { return 2; } + Containers::Optional doSkin3D(UnsignedInt id) override { + Error{} << "3D skin" << id << "error!"; + return {}; + } + + UnsignedInt doLightCount() const override { return 2; } + Containers::Optional doLight(UnsignedInt id) override { + Error{} << "Light" << id << "error!"; + return {}; + } + + UnsignedInt doCameraCount() const override { return 2; } + Containers::Optional doCamera(UnsignedInt id) override { + Error{} << "Camera" << id << "error!"; + return {}; + } + + UnsignedInt doMaterialCount() const override { return 2; } + Containers::Optional doMaterial(UnsignedInt id) override { + Error{} << "Material" << id << "error!"; + return {}; + } + + UnsignedInt doMeshCount() const override { return 2; } + Containers::Optional doMesh(UnsignedInt id, UnsignedInt) override { + Error{} << "Mesh" << id << "error!"; + return {}; + } + + UnsignedInt doTextureCount() const override { return 2; } + Containers::Optional doTexture(UnsignedInt id) override { + Error{} << "Texture" << id << "error!"; + return {}; + } + + /* Errors for all image types tested in ImageConverterTest */ + UnsignedInt doImage2DCount() const override { return 2; } + Containers::Optional doImage2D(UnsignedInt id, UnsignedInt) override { + Error{} << "Image" << id << "error!"; + return {}; + } + } importer; + + const char* argv[]{"", "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + std::ostringstream out; + Debug redirectOutput{&out}; + Error redirectError{&out}; + /* It should return a failure */ + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, {}, _infoArgs, importer, time) == true); + CORRADE_COMPARE(out.str(), + /* It should not exit after first error... */ + "Scene 0 error!\n" + "Scene 1 error!\n" + "Animation 0 error!\n" + "Animation 1 error!\n" + "2D skin 0 error!\n" + "2D skin 1 error!\n" + "3D skin 0 error!\n" + "3D skin 1 error!\n" + "Light 0 error!\n" + "Light 1 error!\n" + "Camera 0 error!\n" + "Camera 1 error!\n" + "Material 0 error!\n" + "Material 1 error!\n" + "Mesh 0 error!\n" + "Mesh 1 error!\n" + "Texture 0 error!\n" + "Texture 1 error!\n" + "Image 0 error!\n" + "Image 1 error!\n" + /* ... and it should print all info output after the errors */ + "Object 0: A name\n"); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::SceneTools::Test::SceneConverterImplementationTest) diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-animations.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-animations.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-animations.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-animations.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-cameras.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-cameras.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-cameras.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-cameras.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-images.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-images.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-images.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-images.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-lights.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-lights.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-lights.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-lights.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-materials.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-materials.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-materials.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-materials.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-meshes-bounds.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-meshes-bounds.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-meshes-bounds.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-meshes-bounds.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-meshes.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-meshes.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-meshes.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-meshes.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-objects.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-objects.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-objects.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-objects.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-references.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-references.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-references.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-references.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-scenes-objects.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-scenes-objects.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-scenes-objects.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-scenes-objects.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-scenes.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-scenes.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-scenes.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-scenes.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-skins.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-skins.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-skins.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-skins.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-textures.txt b/src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-textures.txt similarity index 100% rename from src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-textures.txt rename to src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-textures.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTest.cpp b/src/Magnum/SceneTools/Test/SceneConverterTest.cpp index 9613406ec..676dca78e 100644 --- a/src/Magnum/SceneTools/Test/SceneConverterTest.cpp +++ b/src/Magnum/SceneTools/Test/SceneConverterTest.cpp @@ -23,24 +23,22 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include +#include +#include +#include +#include +#include #include #include #include #include -#include -#include +#include #include -#include "Magnum/Math/CubicHermite.h" -#include "Magnum/Math/Matrix3.h" -#include "Magnum/Math/Matrix4.h" #include "Magnum/Trade/AbstractImageConverter.h" +#include "Magnum/Trade/AbstractImporter.h" #include "Magnum/Trade/AbstractSceneConverter.h" -#include "Magnum/SceneTools/Implementation/sceneConverterUtilities.h" - #include "configure.h" namespace Magnum { namespace SceneTools { namespace Test { namespace { @@ -48,54 +46,13 @@ namespace Magnum { namespace SceneTools { namespace Test { namespace { struct SceneConverterTest: TestSuite::Tester { explicit SceneConverterTest(); - void infoImplementationEmpty(); - void infoImplementationScenesObjects(); - void infoImplementationAnimations(); - void infoImplementationSkins(); - void infoImplementationLights(); - void infoImplementationCameras(); - void infoImplementationMaterials(); - void infoImplementationMeshes(); - void infoImplementationMeshesBounds(); - void infoImplementationTextures(); - void infoImplementationImages(); - /* Image info further tested in ImageConverterTest */ - void infoImplementationReferenceCount(); - void infoImplementationError(); - - #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT void info(); void convert(); void error(); - #endif - - Utility::Arguments _infoArgs; }; using namespace Containers::Literals; -using namespace Math::Literals; - -const struct { - const char* name; - const char* arg; - const char* expected; - bool printVisualCheck; -} InfoImplementationScenesObjectsData[]{ - {"", "--info", "info-scenes-objects.txt", true}, - {"only scenes", "--info-scenes", "info-scenes.txt", false}, - {"only objects", "--info-objects", "info-objects.txt", false}, -}; - -const struct { - const char* name; - bool oneOrAll; - bool printVisualCheck; -} InfoImplementationOneOrAllData[]{ - {"", true, true}, - {"--info", false, false}, -}; -#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT const struct { const char* name; Containers::Array args; @@ -768,32 +725,8 @@ const struct { "Trade::GltfSceneConverter::add(): can't load NonexistentImageConverter for image conversion\n" "Cannot add 3D image 0\n"}, }; -#endif SceneConverterTest::SceneConverterTest() { - addTests({&SceneConverterTest::infoImplementationEmpty}); - - addInstancedTests({&SceneConverterTest::infoImplementationScenesObjects}, - Containers::arraySize(InfoImplementationScenesObjectsData)); - - addInstancedTests({&SceneConverterTest::infoImplementationAnimations, - &SceneConverterTest::infoImplementationSkins, - &SceneConverterTest::infoImplementationLights, - &SceneConverterTest::infoImplementationCameras, - &SceneConverterTest::infoImplementationMaterials, - &SceneConverterTest::infoImplementationMeshes}, - Containers::arraySize(InfoImplementationOneOrAllData)); - - addTests({&SceneConverterTest::infoImplementationMeshesBounds}); - - addInstancedTests({&SceneConverterTest::infoImplementationTextures, - &SceneConverterTest::infoImplementationImages}, - Containers::arraySize(InfoImplementationOneOrAllData)); - - addTests({&SceneConverterTest::infoImplementationReferenceCount, - &SceneConverterTest::infoImplementationError}); - - #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT addInstancedTests({&SceneConverterTest::info}, Containers::arraySize(InfoData)); @@ -802,1130 +735,11 @@ SceneConverterTest::SceneConverterTest() { addInstancedTests({&SceneConverterTest::error}, Containers::arraySize(ErrorData)); - #endif - - /* A subset of arguments needed by the info printing code */ - _infoArgs.addBooleanOption("info") - .addBooleanOption("info-scenes") - .addBooleanOption("info-objects") - .addBooleanOption("info-animations") - .addBooleanOption("info-skins") - .addBooleanOption("info-lights") - .addBooleanOption("info-cameras") - .addBooleanOption("info-materials") - .addBooleanOption("info-meshes") - .addBooleanOption("info-textures") - .addBooleanOption("info-images") - .addBooleanOption("bounds"); /* Create output dir, if doesn't already exist */ Utility::Path::make(Utility::Path::join(SCENETOOLS_TEST_OUTPUT_DIR, "SceneConverterTestFiles")); } -void SceneConverterTest::infoImplementationEmpty() { - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - } importer; - - const char* argv[]{"", "--info"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, {}, _infoArgs, importer, time) == false); - CORRADE_COMPARE(out.str(), ""); -} - -void SceneConverterTest::infoImplementationScenesObjects() { - auto&& data = InfoImplementationScenesObjectsData[testCaseInstanceId()]; - setTestCaseDescription(data.name); - - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - /* First scene has 4, second 7, the last three are not in any scene and - thus not listed. Object 5 has no fields and thus not listed either. */ - UnsignedLong doObjectCount() const override { return 10; } - UnsignedInt doSceneCount() const override { return 2; } - Containers::String doSceneName(UnsignedInt id) override { - return id == 0 ? "A simple scene" : ""; - } - Containers::String doObjectName(UnsignedLong id) override { - if(id == 0) return "Parent-less mesh"; - if(id == 2) return "Two meshes, shared among two scenes"; - if(id == 4) return "Two custom arrays"; - if(id == 6) return "Only in the second scene, but no fields, thus same as unreferenced"; - if(id == 8) return "Not in any scene"; - return ""; - } - Containers::String doSceneFieldName(UnsignedInt name) override { - if(name == 1337) return "DirectionVector"; - return ""; - } - Containers::Optional doScene(UnsignedInt id) override { - /* Builtin fields, some duplicated, one marked as ordered */ - if(id == 0) { - Containers::ArrayView parentMapping; - Containers::ArrayView parents; - Containers::ArrayView meshMapping; - Containers::ArrayView meshes; - Containers::ArrayTuple data{ - {NoInit, 3, parentMapping}, - {ValueInit, 3, parents}, - {NoInit, 4, meshMapping}, - {ValueInit, 4, meshes}, - }; - Utility::copy({1, 3, 2}, parentMapping); - Utility::copy({2, 0, 2, 1}, meshMapping); - /* No need to fill the data, zero-init is fine */ - return Trade::SceneData{Trade::SceneMappingType::UnsignedInt, 4, std::move(data), { - Trade::SceneFieldData{Trade::SceneField::Parent, parentMapping, parents}, - Trade::SceneFieldData{Trade::SceneField::Mesh, meshMapping, meshes, Trade::SceneFieldFlag::OrderedMapping}, - }}; - } - - /* Two custom fields, one array. Stored as an external memory. */ - if(id == 1) { - return Trade::SceneData{Trade::SceneMappingType::UnsignedByte, 8, Trade::DataFlag::ExternallyOwned|Trade::DataFlag::Mutable, scene2Data, { - Trade::SceneFieldData{Trade::sceneFieldCustom(42), Containers::arrayView(scene2Data->customMapping), Containers::arrayView(scene2Data->custom)}, - Trade::SceneFieldData{Trade::sceneFieldCustom(1337), Trade::SceneMappingType::UnsignedByte, scene2Data->customArrayMapping, Trade::SceneFieldType::Short, scene2Data->customArray, 3}, - }}; - } - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - struct { - UnsignedByte customMapping[2]; - Double custom[2]; - UnsignedByte customArrayMapping[3]; - Vector3s customArray[3]; - } scene2Data[1]{{ - /* No need to fill the data, zero-init is fine */ - {7, 3}, {}, {2, 4, 4}, {} - }}; - } importer; - - const char* argv[]{"", data.arg}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - /* Print to visually verify coloring */ - if(data.printVisualCheck) { - Debug{} << "======================== visual color verification start ======================="; - Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); - Debug{} << "======================== visual color verification end ========================="; - } - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, {}, _infoArgs, importer, time) == false); - CORRADE_COMPARE_AS(out.str(), - Utility::Path::join({SCENETOOLS_TEST_DIR, "SceneConverterTestFiles", data.expected}), - TestSuite::Compare::StringToFile); -} - -void SceneConverterTest::infoImplementationAnimations() { - auto&& data = InfoImplementationOneOrAllData[testCaseInstanceId()]; - setTestCaseDescription(data.name); - - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - UnsignedInt doAnimationCount() const override { return 2; } - Containers::String doAnimationName(UnsignedInt id) override { - return id == 1 ? "Custom track duration and interpolator function" : ""; - } - Containers::Optional doAnimation(UnsignedInt id) override { - /* First has two tracks with a shared time and implicit duration, - one with a different result type. */ - if(id == 0) { - Containers::ArrayView time; - Containers::ArrayView translation; - Containers::ArrayView rotation; - Containers::ArrayTuple data{ - {ValueInit, 3, time}, - {ValueInit, 3, translation}, - {ValueInit, 3, rotation} - }; - Utility::copy({0.5f, 1.0f, 1.25f}, time); - return Trade::AnimationData{std::move(data), { - /** @todo cleanup once AnimationTrackData has sane - constructors */ - Trade::AnimationTrackData{Trade::AnimationTrackTargetType::Translation2D, 17, Animation::TrackView{time, translation, Animation::Interpolation::Linear, Animation::Extrapolation::DefaultConstructed, Animation::Extrapolation::Constant}}, - Trade::AnimationTrackData{Trade::AnimationTrackTargetType::Rotation2D, 17, Animation::TrackView{time, rotation, Animation::Interpolation::Constant, Animation::Extrapolation::Extrapolated}}, - }}; - } - - /* Second has track duration different from animation duration and - a custom interpolator. Stored as an external memory. */ - if(id == 1) { - return Trade::AnimationData{Trade::DataFlag::ExternallyOwned, animation2Data, { - /** @todo cleanup once AnimationTrackData has sane - constructors */ - Trade::AnimationTrackData{Trade::AnimationTrackTargetType::Scaling3D, 666, Animation::TrackView{animation2Data->time, animation2Data->scaling, Math::lerp, Animation::Extrapolation::DefaultConstructed, Animation::Extrapolation::Constant}}, - }, {0.1f, 1.3f}}; - } - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - struct { - Float time[5]; - Vector3 scaling[5]; - } animation2Data[1]{{ - {0.75f, 0.75f, 1.0f, 1.0f, 1.25f}, - {} - }}; - } importer; - - const char* argv[]{"", data.oneOrAll ? "--info-animations" : "--info"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - /* Print to visually verify coloring */ - if(data.printVisualCheck) { - Debug{} << "======================== visual color verification start ======================="; - Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); - Debug{} << "======================== visual color verification end ========================="; - } - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, {}, _infoArgs, importer, time) == false); - CORRADE_COMPARE_AS(out.str(), - Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterTestFiles/info-animations.txt"), - TestSuite::Compare::StringToFile); -} - -void SceneConverterTest::infoImplementationSkins() { - auto&& data = InfoImplementationOneOrAllData[testCaseInstanceId()]; - setTestCaseDescription(data.name); - - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - UnsignedInt doSkin2DCount() const override { return 2; } - Containers::String doSkin2DName(UnsignedInt id) override { - return id == 1 ? "Second 2D skin, external data" : ""; - } - Containers::Optional doSkin2D(UnsignedInt id) override { - /* First a regular skin, second externally owned */ - if(id == 0) return Trade::SkinData2D{ - {3, 6, 7, 12, 22}, - {{}, {}, {}, {}, {}} - }; - - if(id == 1) return Trade::SkinData2D{Trade::DataFlag::ExternallyOwned, skin2JointData, Trade::DataFlag::ExternallyOwned, skin2MatrixData}; - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt doSkin3DCount() const override { return 3; } - Containers::String doSkin3DName(UnsignedInt id) override { - return id == 0 ? "First 3D skin, external data" : ""; - } - Containers::Optional doSkin3D(UnsignedInt id) override { - /* Reverse order in 3D, plus one more to ensure the count isn't - mismatched between 2D and 3D */ - if(id == 0) return Trade::SkinData3D{Trade::DataFlag::ExternallyOwned, skin3JointData, Trade::DataFlag::ExternallyOwned, skin3MatrixData}; - - if(id == 1) return Trade::SkinData3D{ - {3, 22}, - {{}, {}} - }; - - if(id == 2) return Trade::SkinData3D{ - {3}, - {{}} - }; - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt skin2JointData[15]; - Matrix3 skin2MatrixData[15]; - UnsignedInt skin3JointData[12]; - Matrix4 skin3MatrixData[12]; - } importer; - - const char* argv[]{"", data.oneOrAll ? "--info-skins" : "--info"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - /* Print to visually verify coloring */ - if(data.printVisualCheck) { - Debug{} << "======================== visual color verification start ======================="; - Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); - Debug{} << "======================== visual color verification end ========================="; - } - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, {}, _infoArgs, importer, time) == false); - CORRADE_COMPARE_AS(out.str(), - Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterTestFiles/info-skins.txt"), - TestSuite::Compare::StringToFile); -} - -void SceneConverterTest::infoImplementationLights() { - auto&& data = InfoImplementationOneOrAllData[testCaseInstanceId()]; - setTestCaseDescription(data.name); - - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - UnsignedInt doLightCount() const override { return 2; } - Containers::String doLightName(UnsignedInt id) override { - return id == 1 ? "Directional light with always-implicit attenuation and range" : ""; - } - Containers::Optional doLight(UnsignedInt id) override { - /* First a blue spot light */ - if(id == 0) return Trade::LightData{ - Trade::LightData::Type::Spot, - 0x3457ff_rgbf, - 15.0f, - {1.2f, 0.3f, 0.04f}, - 100.0f, - 55.0_degf, - 85.0_degf - }; - - /* Second a yellow directional light with infinite range */ - if(id == 1) return Trade::LightData{ - Trade::LightData::Type::Directional, - 0xff5734_rgbf, - 5.0f - }; - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - } importer; - - const char* argv[]{"", data.oneOrAll ? "--info-lights" : "--info"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - /* Print to visually verify coloring */ - if(data.printVisualCheck) { - Debug{} << "======================== visual color verification start ======================="; - Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); - Debug{} << "======================== visual color verification end ========================="; - } - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); - CORRADE_COMPARE_AS(out.str(), - Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterTestFiles/info-lights.txt"), - TestSuite::Compare::StringToFile); -} - -void SceneConverterTest::infoImplementationCameras() { - auto&& data = InfoImplementationOneOrAllData[testCaseInstanceId()]; - setTestCaseDescription(data.name); - - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - UnsignedInt doCameraCount() const override { return 3; } - Containers::String doCameraName(UnsignedInt id) override { - return id == 0 ? "Orthographic 2D" : ""; - } - Containers::Optional doCamera(UnsignedInt id) override { - /* First 2D ortho camera, where near/far will get omited */ - if(id == 0) return Trade::CameraData{ - Trade::CameraType::Orthographic2D, - {5.0f, 6.0f}, - 0.0f, 0.0f - }; - - /* 3D ortho camera */ - if(id == 1) return Trade::CameraData{ - Trade::CameraType::Orthographic3D, - {2.0f, 3.0f}, - -1.0f, 0.5f - }; - - /* Third a perspective camera, specified with size, but printed - with FoV */ - if(id == 2) return Trade::CameraData{ - Trade::CameraType::Perspective3D, - 35.0_degf, 4.0f/3.0f, 0.01f, 100.0f - }; - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - } importer; - - const char* argv[]{"", data.oneOrAll ? "--info-cameras" : "--info"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - /* Print to visually verify coloring */ - if(data.printVisualCheck) { - Debug{} << "======================== visual color verification start ======================="; - Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); - Debug{} << "======================== visual color verification end ========================="; - } - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); - CORRADE_COMPARE_AS(out.str(), - Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterTestFiles/info-cameras.txt"), - TestSuite::Compare::StringToFile); -} - -void SceneConverterTest::infoImplementationMaterials() { - auto&& data = InfoImplementationOneOrAllData[testCaseInstanceId()]; - setTestCaseDescription(data.name); - - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - UnsignedInt doMaterialCount() const override { return 2; } - Containers::String doMaterialName(UnsignedInt id) override { - return id == 1 ? "Lots o' laierz" : ""; - } - Containers::Optional doMaterial(UnsignedInt id) override { - /* First has custom attributes */ - if(id == 0) return Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { - {Trade::MaterialAttribute::BaseColor, 0x3bd26799_rgbaf}, - {Trade::MaterialAttribute::DoubleSided, true}, - {Trade::MaterialAttribute::EmissiveColor, 0xe9eca_rgbf}, - {Trade::MaterialAttribute::RoughnessTexture, 67u}, - {Trade::MaterialAttribute::RoughnessTextureMatrix, Matrix3::translation({0.25f, 0.75f})}, - {Trade::MaterialAttribute::RoughnessTextureSwizzle, Trade::MaterialTextureSwizzle::B}, - {"reflectionAngle", 35.0_degf}, - /* These shouldn't have a color swatch rendered */ - {"notAColour4", Vector4{0.1f, 0.2f, 0.3f, 0.4f}}, - {"notAColour3", Vector3{0.2f, 0.3f, 0.4f}}, - {"data", Containers::ArrayView{"0123456789abcdef", 17}}, - {"deadBeef", reinterpret_cast(0xdeadbeef)}, - {"undeadBeef", reinterpret_cast(0xbeefbeef)}, - }}; - - /* Second has layers, custom layers, unnamed layers and a name */ - if(id == 1) return Trade::MaterialData{Trade::MaterialType::PbrClearCoat|Trade::MaterialType::Phong, { - {Trade::MaterialAttribute::DiffuseColor, 0xc7cf2f99_rgbaf}, - {Trade::MaterialLayer::ClearCoat}, - {Trade::MaterialAttribute::LayerFactor, 0.5f}, - {Trade::MaterialAttribute::LayerFactorTexture, 3u}, - {Trade::MaterialAttribute::LayerName, "anEmptyLayer"}, - {Trade::MaterialAttribute::LayerFactor, 0.25f}, - {Trade::MaterialAttribute::LayerFactorTexture, 2u}, - {"yes", "a string"}, - }, {1, 4, 5, 8}}; - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - } importer; - - const char* argv[]{"", data.oneOrAll ? "--info-materials" : "--info"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - /* Print to visually verify coloring */ - if(data.printVisualCheck) { - Debug{} << "======================== visual color verification start ======================="; - Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); - Debug{} << "======================== visual color verification end ========================="; - } - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); - CORRADE_COMPARE_AS(out.str(), - Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterTestFiles/info-materials.txt"), - TestSuite::Compare::StringToFile); -} - -void SceneConverterTest::infoImplementationMeshes() { - auto&& data = InfoImplementationOneOrAllData[testCaseInstanceId()]; - setTestCaseDescription(data.name); - - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - UnsignedInt doMeshCount() const override { return 3; } - UnsignedInt doMeshLevelCount(UnsignedInt id) override { - return id == 1 ? 2 : 1; - } - Containers::String doMeshName(UnsignedInt id) override { - return id == 1 ? "LODs? No, meshets." : ""; - } - Containers::String doMeshAttributeName(UnsignedShort name) override { - if(name == 25) return "vertices"; - if(name == 26) return "triangles"; - /* 37 (triangleCount) deliberately not named */ - if(name == 116) return "vertexCount"; - - return ""; - } - Containers::Optional doMesh(UnsignedInt id, UnsignedInt level) override { - /* First is indexed & externally owned */ - if(id == 0 && level == 0) return Trade::MeshData{MeshPrimitive::Points, - Trade::DataFlag::ExternallyOwned, indices, - Trade::MeshIndexData{indices}, - Trade::DataFlag::ExternallyOwned|Trade::DataFlag::Mutable, points, { - Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::arrayView(points)} - }}; - - /* Second is multi-level, with second level being indexed meshlets - with custom (array) attributes */ - if(id == 1 && level == 0) { - Containers::ArrayView positions; - Containers::ArrayView tangents; - Containers::ArrayTuple data{ - {NoInit, 250, positions}, - {NoInit, 250, tangents}, - }; - return Trade::MeshData{MeshPrimitive::Triangles, std::move(data), { - Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}, - Trade::MeshAttributeData{Trade::MeshAttribute::Tangent, tangents}, - }}; - } - if(id == 1 && level == 1) { - Containers::StridedArrayView2D vertices; - Containers::StridedArrayView2D indices; - Containers::ArrayView triangleCount; - Containers::ArrayView vertexCount; - Containers::ArrayTuple data{ - {NoInit, {135, 64}, vertices}, - {NoInit, {135, 126}, indices}, - {NoInit, 135, triangleCount}, - {NoInit, 135, vertexCount}, - }; - return Trade::MeshData{MeshPrimitive::Meshlets, std::move(data), { - Trade::MeshAttributeData{Trade::meshAttributeCustom(25), vertices}, - Trade::MeshAttributeData{Trade::meshAttributeCustom(26), indices}, - Trade::MeshAttributeData{Trade::meshAttributeCustom(37), triangleCount}, - Trade::MeshAttributeData{Trade::meshAttributeCustom(116), vertexCount}, - }}; - } - - /* Third is an empty instance mesh */ - if(id == 2 && level == 0) return Trade::MeshData{MeshPrimitive::Instances, 15}; - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedShort indices[70]; - Vector3 points[50]; - } importer; - - const char* argv[]{"", data.oneOrAll ? "--info-meshes" : "--info"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - /* Print to visually verify coloring */ - if(data.printVisualCheck) { - Debug{} << "======================== visual color verification start ======================="; - Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); - Debug{} << "======================== visual color verification end ========================="; - } - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); - CORRADE_COMPARE_AS(out.str(), - Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterTestFiles/info-meshes.txt"), - TestSuite::Compare::StringToFile); -} - -void SceneConverterTest::infoImplementationMeshesBounds() { - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - UnsignedInt doMeshCount() const override { return 1; } - Containers::Optional doMesh(UnsignedInt, UnsignedInt) override { - return Trade::MeshData{MeshPrimitive::Lines, - {}, indexData, Trade::MeshIndexData{indexData}, - {}, vertexData, { - Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::arrayView(vertexData->positions)}, - Trade::MeshAttributeData{Trade::MeshAttribute::Tangent, Containers::arrayView(vertexData->tangent)}, - Trade::MeshAttributeData{Trade::MeshAttribute::Bitangent, Containers::arrayView(vertexData->bitangent)}, - Trade::MeshAttributeData{Trade::MeshAttribute::ObjectId, Containers::arrayView(vertexData->objectId)}, - Trade::MeshAttributeData{Trade::MeshAttribute::Normal, Containers::arrayView(vertexData->normal)}, - Trade::MeshAttributeData{Trade::MeshAttribute::TextureCoordinates, Containers::arrayView(vertexData->textureCoordinates)}, - Trade::MeshAttributeData{Trade::MeshAttribute::Color, Containers::arrayView(vertexData->color)}, - Trade::MeshAttributeData{Trade::MeshAttribute::ObjectId, Containers::arrayView(vertexData->objectIdSecondary)}, - }}; - } - - UnsignedByte indexData[3]{15, 3, 176}; - - struct { - Vector3 positions[2]; - Vector3 tangent[2]; - Vector3 bitangent[2]; - UnsignedShort objectId[2]; - Vector3 normal[2]; - Vector2 textureCoordinates[2]; - Vector4 color[2]; - UnsignedInt objectIdSecondary[2]; - } vertexData[1]{{ - {{0.1f, -0.1f, 0.2f}, {0.2f, 0.0f, -0.2f}}, - {{0.2f, -0.2f, 0.8f}, {0.3f, 0.8f, 0.2f}}, - {{0.4f, 0.2f, 1.0f}, {0.3f, 0.9f, 0.0f}}, - {155, 12}, - {{0.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 1.0f}}, - {{0.5f, 0.5f}, {1.5f, 0.5f}}, - {0x99336600_rgbaf, 0xff663333_rgbaf}, - {15, 337}, - }}; - } importer; - - const char* argv[]{"", "--info-meshes", "--bounds"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - /* Print to visually verify coloring */ - { - Debug{} << "======================== visual color verification start ======================="; - Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); - Debug{} << "======================== visual color verification end ========================="; - } - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); - CORRADE_COMPARE_AS(out.str(), - Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterTestFiles/info-meshes-bounds.txt"), - TestSuite::Compare::StringToFile); -} - -void SceneConverterTest::infoImplementationTextures() { - auto&& data = InfoImplementationOneOrAllData[testCaseInstanceId()]; - setTestCaseDescription(data.name); - - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - UnsignedInt doTextureCount() const override { return 2; } - Containers::String doTextureName(UnsignedInt id) override { - return id == 1 ? "Name!" : ""; - } - Containers::Optional doTexture(UnsignedInt id) override { - /* First a 1D texture */ - if(id == 0) return Trade::TextureData{ - Trade::TextureType::Texture1D, - SamplerFilter::Nearest, - SamplerFilter::Linear, - SamplerMipmap::Nearest, - SamplerWrapping::Repeat, - 666 - }; - - /* Second a 2D array texture */ - if(id == 1) return Trade::TextureData{ - Trade::TextureType::Texture2DArray, - SamplerFilter::Linear, - SamplerFilter::Nearest, - SamplerMipmap::Linear, - {SamplerWrapping::MirroredRepeat, SamplerWrapping::ClampToEdge, SamplerWrapping::MirrorClampToEdge}, - 3 - }; - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - } importer; - - const char* argv[]{"", data.oneOrAll ? "--info-textures" : "--info"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - /* Print to visually verify coloring */ - if(data.printVisualCheck) { - Debug{} << "======================== visual color verification start ======================="; - Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); - Debug{} << "======================== visual color verification end ========================="; - } - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); - CORRADE_COMPARE_AS(out.str(), - Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterTestFiles/info-textures.txt"), - TestSuite::Compare::StringToFile); -} - -void SceneConverterTest::infoImplementationImages() { - auto&& data = InfoImplementationOneOrAllData[testCaseInstanceId()]; - setTestCaseDescription(data.name); - - /* Just the very basics to ensure image info *is* printed. Tested in full - in ImageConverterTest. */ - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - UnsignedInt doImage1DCount() const override { return 1; } - Containers::Optional doImage1D(UnsignedInt, UnsignedInt) override { - return Trade::ImageData1D{PixelFormat::R32F, 1024, Containers::Array{NoInit, 4096}}; - } - } importer; - - const char* argv[]{"", data.oneOrAll ? "--info-images" : "--info"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - /* Print to visually verify coloring */ - if(data.printVisualCheck) { - Debug{} << "======================== visual color verification start ======================="; - Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); - Debug{} << "======================== visual color verification end ========================="; - } - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); - CORRADE_COMPARE_AS(out.str(), - Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterTestFiles/info-images.txt"), - TestSuite::Compare::StringToFile); -} - -void SceneConverterTest::infoImplementationReferenceCount() { - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - /* One data of each kind should be always referenced twice+, one once, - one not at all, and one reference should be OOB */ - - UnsignedLong doObjectCount() const override { return 4; } - Containers::String doObjectName(UnsignedLong id) override { - return id == 2 ? "Not referenced" : ""; - } - UnsignedInt doSceneCount() const override { return 2; } - Containers::Optional doScene(UnsignedInt id) override { - if(id == 0) return Trade::SceneData{Trade::SceneMappingType::UnsignedInt, 2, {}, sceneData3D, { - /* To mark the scene as 3D */ - Trade::SceneFieldData{Trade::SceneField::Transformation, Trade::SceneMappingType::UnsignedInt, nullptr, Trade::SceneFieldType::Matrix4x4, nullptr}, - Trade::SceneFieldData{Trade::SceneField::Mesh, - Containers::arrayView(sceneData3D->mapping), - Containers::arrayView(sceneData3D->meshes)}, - Trade::SceneFieldData{Trade::SceneField::MeshMaterial, - Containers::arrayView(sceneData3D->mapping), - Containers::arrayView(sceneData3D->materials)}, - Trade::SceneFieldData{Trade::SceneField::Light, - Containers::arrayView(sceneData3D->mapping), - Containers::arrayView(sceneData3D->lights)}, - Trade::SceneFieldData{Trade::SceneField::Camera, - Containers::arrayView(sceneData3D->mapping), - Containers::arrayView(sceneData3D->cameras)}, - Trade::SceneFieldData{Trade::SceneField::Skin, - Containers::arrayView(sceneData3D->mapping), - Containers::arrayView(sceneData3D->skins)}, - }}; - if(id == 1) return Trade::SceneData{Trade::SceneMappingType::UnsignedInt, 4, {}, sceneData2D, { - /* To mark the scene as 2D */ - Trade::SceneFieldData{Trade::SceneField::Transformation, Trade::SceneMappingType::UnsignedInt, nullptr, Trade::SceneFieldType::Matrix3x3, nullptr}, - Trade::SceneFieldData{Trade::SceneField::Mesh, - Containers::arrayView(sceneData2D->mapping), - Containers::arrayView(sceneData2D->meshes)}, - Trade::SceneFieldData{Trade::SceneField::Skin, - Containers::arrayView(sceneData2D->mapping), - Containers::arrayView(sceneData2D->skins)}, - }}; - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt doSkin2DCount() const override { return 3; } - Containers::String doSkin2DName(UnsignedInt id) override { - return id == 2 ? "Not referenced" : ""; - } - Containers::Optional doSkin2D(UnsignedInt id) override { - if(id == 0) return Trade::SkinData2D{ - {35, 22}, - {{}, {}} - }; - if(id == 1) return Trade::SkinData2D{ - {33, 10, 100}, - {{}, {}, {}} - }; - if(id == 2) return Trade::SkinData2D{ - {66}, - {{}} - }; - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt doSkin3DCount() const override { return 3; } - Containers::String doSkin3DName(UnsignedInt id) override { - return id == 0 ? "Not referenced" : ""; - } - Containers::Optional doSkin3D(UnsignedInt id) override { - if(id == 0) return Trade::SkinData3D{ - {35, 22}, - {{}, {}} - }; - if(id == 1) return Trade::SkinData3D{ - {37}, - {{}} - }; - if(id == 2) return Trade::SkinData3D{ - {300, 10, 1000}, - {{}, {}, {}} - }; - - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt doLightCount() const override { return 3; } - Containers::String doLightName(UnsignedInt id) override { - return id == 1 ? "Not referenced" : ""; - } - Containers::Optional doLight(UnsignedInt id) override { - if(id == 0) return Trade::LightData{ - Trade::LightData::Type::Directional, - 0x57ff34_rgbf, - 5.0f - }; - if(id == 1) return Trade::LightData{ - Trade::LightData::Type::Ambient, - 0xff5734_rgbf, - 0.1f - }; - if(id == 2) return Trade::LightData{ - Trade::LightData::Type::Directional, - 0x3457ff_rgbf, - 1.0f - }; - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt doCameraCount() const override { return 3; } - Containers::String doCameraName(UnsignedInt id) override { - return id == 0 ? "Not referenced" : ""; - } - Containers::Optional doCamera(UnsignedInt id) override { - if(id == 0) return Trade::CameraData{ - Trade::CameraType::Orthographic3D, - {2.0f, 3.0f}, - -1.0f, 0.5f - }; - if(id == 1) return Trade::CameraData{ - Trade::CameraType::Orthographic3D, - {2.0f, 2.0f}, - 0.0f, 1.0f - }; - if(id == 2) return Trade::CameraData{ - Trade::CameraType::Orthographic2D, - {2.0f, 2.0f}, - 0.0f, 0.0f - }; - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt doMaterialCount() const override { return 3; } - Containers::String doMaterialName(UnsignedInt id) override { - return id == 2 ? "Not referenced" : ""; - } - Containers::Optional doMaterial(UnsignedInt id) override { - if(id == 0) return Trade::MaterialData{{}, { - {Trade::MaterialAttribute::DiffuseTexture, 2u}, - {Trade::MaterialAttribute::BaseColorTexture, 2u}, - }}; - if(id == 1) return Trade::MaterialData{{}, { - {"lookupTexture", 0u}, - {"volumeTexture", 3u}, - {Trade::MaterialAttribute::NormalTexture, 17u}, - {Trade::MaterialAttribute::EmissiveTexture, 4u}, - }}; - if(id == 2) return Trade::MaterialData{{}, {}}; - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt doMeshCount() const override { return 3; } - Containers::String doMeshName(UnsignedInt id) override { - return id == 1 ? "Not referenced" : ""; - } - Containers::Optional doMesh(UnsignedInt id, UnsignedInt) override { - if(id == 0) return Trade::MeshData{MeshPrimitive::Points, 5}; - if(id == 1) return Trade::MeshData{MeshPrimitive::Lines, 4}; - if(id == 2) return Trade::MeshData{MeshPrimitive::TriangleFan, 4}; - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt doTextureCount() const override { return 5; } - Containers::String doTextureName(UnsignedInt id) override { - return id == 1 ? "Not referenced" : ""; - } - Containers::Optional doTexture(UnsignedInt id) override { - if(id == 0) return Trade::TextureData{ - Trade::TextureType::Texture1D, - SamplerFilter::Nearest, - SamplerFilter::Linear, - SamplerMipmap::Nearest, - SamplerWrapping::Repeat, - 1 - }; - if(id == 1) return Trade::TextureData{ - Trade::TextureType::Texture1DArray, - SamplerFilter::Nearest, - SamplerFilter::Linear, - SamplerMipmap::Nearest, - SamplerWrapping::Repeat, - 225 - }; - if(id == 2) return Trade::TextureData{ - Trade::TextureType::Texture2D, - SamplerFilter::Nearest, - SamplerFilter::Linear, - SamplerMipmap::Nearest, - SamplerWrapping::Repeat, - 0 - }; - if(id == 3) return Trade::TextureData{ - Trade::TextureType::Texture3D, - SamplerFilter::Nearest, - SamplerFilter::Linear, - SamplerMipmap::Nearest, - SamplerWrapping::Repeat, - 1 - }; - if(id == 4) return Trade::TextureData{ - Trade::TextureType::Texture2D, - SamplerFilter::Nearest, - SamplerFilter::Linear, - SamplerMipmap::Nearest, - SamplerWrapping::Repeat, - 0 - }; - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt doImage1DCount() const override { return 2; } - Containers::String doImage1DName(UnsignedInt id) override { - return id == 0 ? "Not referenced" : ""; - } - Containers::Optional doImage1D(UnsignedInt id, UnsignedInt) override { - if(id == 0) - return Trade::ImageData1D{PixelFormat::RGBA8I, 1, Containers::Array{NoInit, 4}}; - if(id == 1) - return Trade::ImageData1D{PixelFormat::R8I, 4, Containers::Array{NoInit, 4}}; - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt doImage2DCount() const override { return 2; } - Containers::String doImage2DName(UnsignedInt id) override { - return id == 1 ? "Not referenced" : ""; - } - Containers::Optional doImage2D(UnsignedInt id, UnsignedInt) override { - if(id == 0) - return Trade::ImageData2D{PixelFormat::RGBA8I, {1, 2}, Containers::Array{NoInit, 8}}; - if(id == 1) - return Trade::ImageData2D{PixelFormat::R8I, {4, 1}, Containers::Array{NoInit, 4}}; - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - UnsignedInt doImage3DCount() const override { return 2; } - Containers::String doImage3DName(UnsignedInt id) override { - return id == 0 ? "Not referenced" : ""; - } - Containers::Optional doImage3D(UnsignedInt id, UnsignedInt) override { - if(id == 0) - return Trade::ImageData3D{PixelFormat::RGBA8I, {1, 2, 1}, Containers::Array{NoInit, 8}}; - if(id == 1) - return Trade::ImageData3D{PixelFormat::R8I, {4, 1, 1}, Containers::Array{NoInit, 4}}; - CORRADE_INTERNAL_ASSERT_UNREACHABLE(); - } - - struct { - UnsignedInt mapping[4]; - UnsignedInt meshes[4]; - Int materials[4]; - UnsignedInt lights[4]; - UnsignedInt cameras[4]; - UnsignedInt skins[4]; - } sceneData3D[1]{{ - {0, 1, 1, 25}, - {2, 0, 2, 67}, - {0, 1, 23, 0}, - {0, 17, 0, 2}, - {166, 1, 2, 1}, - {1, 1, 22, 2} - }}; - - struct { - UnsignedInt mapping[3]; - UnsignedInt meshes[3]; - UnsignedInt skins[3]; - } sceneData2D[1]{{ - {3, 116, 1}, - {2, 0, 23}, - {177, 0, 1} - }}; - } importer; - - const char* argv[]{"", "--info"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - /* Print to visually verify coloring */ - { - Debug{} << "======================== visual color verification start ======================="; - Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); - Debug{} << "======================== visual color verification end ========================="; - } - - std::ostringstream out; - Debug redirectOutput{&out}; - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); - CORRADE_COMPARE_AS(out.str(), - Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterTestFiles/info-references.txt"), - TestSuite::Compare::StringToFile); -} - -void SceneConverterTest::infoImplementationError() { - struct Importer: Trade::AbstractImporter { - Trade::ImporterFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } - void doClose() override {} - - /* The one single object is named, and that name should be printed - after all error messages */ - UnsignedLong doObjectCount() const override { return 1; } - Containers::String doObjectName(UnsignedLong) override { return "A name"; } - - UnsignedInt doSceneCount() const override { return 2; } - Containers::Optional doScene(UnsignedInt id) override { - Error{} << "Scene" << id << "error!"; - return {}; - } - - UnsignedInt doAnimationCount() const override { return 2; } - Containers::Optional doAnimation(UnsignedInt id) override { - Error{} << "Animation" << id << "error!"; - return {}; - } - - UnsignedInt doSkin2DCount() const override { return 2; } - Containers::Optional doSkin2D(UnsignedInt id) override { - Error{} << "2D skin" << id << "error!"; - return {}; - } - - UnsignedInt doSkin3DCount() const override { return 2; } - Containers::Optional doSkin3D(UnsignedInt id) override { - Error{} << "3D skin" << id << "error!"; - return {}; - } - - UnsignedInt doLightCount() const override { return 2; } - Containers::Optional doLight(UnsignedInt id) override { - Error{} << "Light" << id << "error!"; - return {}; - } - - UnsignedInt doCameraCount() const override { return 2; } - Containers::Optional doCamera(UnsignedInt id) override { - Error{} << "Camera" << id << "error!"; - return {}; - } - - UnsignedInt doMaterialCount() const override { return 2; } - Containers::Optional doMaterial(UnsignedInt id) override { - Error{} << "Material" << id << "error!"; - return {}; - } - - UnsignedInt doMeshCount() const override { return 2; } - Containers::Optional doMesh(UnsignedInt id, UnsignedInt) override { - Error{} << "Mesh" << id << "error!"; - return {}; - } - - UnsignedInt doTextureCount() const override { return 2; } - Containers::Optional doTexture(UnsignedInt id) override { - Error{} << "Texture" << id << "error!"; - return {}; - } - - /* Errors for all image types tested in ImageConverterTest */ - UnsignedInt doImage2DCount() const override { return 2; } - Containers::Optional doImage2D(UnsignedInt id, UnsignedInt) override { - Error{} << "Image" << id << "error!"; - return {}; - } - } importer; - - const char* argv[]{"", "--info"}; - CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); - - std::chrono::high_resolution_clock::duration time; - - std::ostringstream out; - Debug redirectOutput{&out}; - Error redirectError{&out}; - /* It should return a failure */ - CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, {}, _infoArgs, importer, time) == true); - CORRADE_COMPARE(out.str(), - /* It should not exit after first error... */ - "Scene 0 error!\n" - "Scene 1 error!\n" - "Animation 0 error!\n" - "Animation 1 error!\n" - "2D skin 0 error!\n" - "2D skin 1 error!\n" - "3D skin 0 error!\n" - "3D skin 1 error!\n" - "Light 0 error!\n" - "Light 1 error!\n" - "Camera 0 error!\n" - "Camera 1 error!\n" - "Material 0 error!\n" - "Material 1 error!\n" - "Mesh 0 error!\n" - "Mesh 1 error!\n" - "Texture 0 error!\n" - "Texture 1 error!\n" - "Image 0 error!\n" - "Image 1 error!\n" - /* ... and it should print all info output after the errors */ - "Object 0: A name\n"); -} - -#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT namespace { #ifdef SCENECONVERTER_EXECUTABLE_FILENAME @@ -1964,12 +778,8 @@ void SceneConverterTest::info() { setTestCaseDescription(data.name); #ifndef SCENECONVERTER_EXECUTABLE_FILENAME - #ifdef CORRADE_TARGET_UNIX CORRADE_SKIP("magnum-sceneconverter not built, can't test"); #else - CORRADE_SKIP("Executable testing implemented only on Unix platforms"); - #endif - #else /* Check if required plugins can be loaded. Catches also ABI and interface mismatch errors. */ PluginManager::Manager importerManager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR}; @@ -1991,12 +801,8 @@ void SceneConverterTest::convert() { setTestCaseDescription(data.name); #ifndef SCENECONVERTER_EXECUTABLE_FILENAME - #ifdef CORRADE_TARGET_UNIX CORRADE_SKIP("magnum-sceneconverter not built, can't test"); #else - CORRADE_SKIP("Executable testing implemented only on Unix platforms"); - #endif - #else /* Check if required plugins can be loaded. Catches also ABI and interface mismatch errors. */ PluginManager::Manager importerManager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR}; @@ -2043,12 +849,8 @@ void SceneConverterTest::error() { setTestCaseDescription(data.name); #ifndef SCENECONVERTER_EXECUTABLE_FILENAME - #ifdef CORRADE_TARGET_UNIX CORRADE_SKIP("magnum-sceneconverter not built, can't test"); #else - CORRADE_SKIP("Executable testing implemented only on Unix platforms"); - #endif - #else /* Check if required plugins can be loaded. Catches also ABI and interface mismatch errors. */ PluginManager::Manager importerManager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR}; @@ -2087,7 +889,6 @@ void SceneConverterTest::error() { CORRADE_VERIFY(!output.first()); #endif } -#endif }}}} diff --git a/src/Magnum/Trade/Test/CMakeLists.txt b/src/Magnum/Trade/Test/CMakeLists.txt index 3360dd59c..7364ecc3f 100644 --- a/src/Magnum/Trade/Test/CMakeLists.txt +++ b/src/Magnum/Trade/Test/CMakeLists.txt @@ -55,11 +55,11 @@ corrade_add_test(TradeCameraDataTest CameraDataTest.cpp LIBRARIES MagnumTradeTes corrade_add_test(TradeDataTest DataTest.cpp LIBRARIES MagnumTrade) corrade_add_test(TradeFlatMaterialDataTest FlatMaterialDataTest.cpp LIBRARIES MagnumTradeTestLib) -corrade_add_test(TradeImageConverterTest ImageConverterTest.cpp +corrade_add_test(TradeImageConverterImplementa___Test ImageConverterImplementationTest.cpp LIBRARIES MagnumTrade FILES - ImageConverterTestFiles/info.txt) -target_include_directories(TradeImageConverterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + ImageConverterImplementationTestFiles/info.txt) +target_include_directories(TradeImageConverterImplementa___Test PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) corrade_add_test(TradeImageDataTest ImageDataTest.cpp LIBRARIES MagnumTradeTestLib) corrade_add_test(TradeLightDataTest LightDataTest.cpp LIBRARIES MagnumTradeTestLib) diff --git a/src/Magnum/Trade/Test/ImageConverterTest.cpp b/src/Magnum/Trade/Test/ImageConverterImplementationTest.cpp similarity index 93% rename from src/Magnum/Trade/Test/ImageConverterTest.cpp rename to src/Magnum/Trade/Test/ImageConverterImplementationTest.cpp index 812caf3aa..be66e56ea 100644 --- a/src/Magnum/Trade/Test/ImageConverterTest.cpp +++ b/src/Magnum/Trade/Test/ImageConverterImplementationTest.cpp @@ -36,19 +36,19 @@ namespace Magnum { namespace Trade { namespace Test { namespace { -struct ImageConverterTest: TestSuite::Tester { - explicit ImageConverterTest(); +struct ImageConverterImplementationTest: TestSuite::Tester { + explicit ImageConverterImplementationTest(); - void infoImplementation(); - void infoImplementationError(); + void info(); + void infoError(); }; -ImageConverterTest::ImageConverterTest() { - addTests({&ImageConverterTest::infoImplementation, - &ImageConverterTest::infoImplementationError}); +ImageConverterImplementationTest::ImageConverterImplementationTest() { + addTests({&ImageConverterImplementationTest::info, + &ImageConverterImplementationTest::infoError}); } -void ImageConverterTest::infoImplementation() { +void ImageConverterImplementationTest::info() { struct Importer: Trade::AbstractImporter { Trade::ImporterFeatures doFeatures() const override { return {}; } bool doIsOpened() const override { return true; } @@ -139,11 +139,11 @@ void ImageConverterTest::infoImplementation() { Debug redirectOutput{&out}; Implementation::printImageInfo(Debug::Flag::DisableColors, infos, nullptr, nullptr, nullptr); CORRADE_COMPARE_AS(out.str(), - Utility::Path::join(TRADE_TEST_DIR, "ImageConverterTestFiles/info.txt"), + Utility::Path::join(TRADE_TEST_DIR, "ImageConverterImplementationTestFiles/info.txt"), TestSuite::Compare::StringToFile); } -void ImageConverterTest::infoImplementationError() { +void ImageConverterImplementationTest::infoError() { struct Importer: Trade::AbstractImporter { Trade::ImporterFeatures doFeatures() const override { return {}; } bool doIsOpened() const override { return true; } @@ -189,4 +189,4 @@ void ImageConverterTest::infoImplementationError() { }}}} -CORRADE_TEST_MAIN(Magnum::Trade::Test::ImageConverterTest) +CORRADE_TEST_MAIN(Magnum::Trade::Test::ImageConverterImplementationTest) diff --git a/src/Magnum/Trade/Test/ImageConverterTestFiles/info.txt b/src/Magnum/Trade/Test/ImageConverterImplementationTestFiles/info.txt similarity index 100% rename from src/Magnum/Trade/Test/ImageConverterTestFiles/info.txt rename to src/Magnum/Trade/Test/ImageConverterImplementationTestFiles/info.txt