From f552fc7ccd97bc8ba7cc1841c4c4f5af5122332e Mon Sep 17 00:00:00 2001 From: hultonha Date: Fri, 16 Apr 2021 17:30:06 +0100 Subject: [PATCH] Fix for ReadMesh error reporting --- .../Code/Include/WhiteBox/WhiteBoxToolApi.h | 22 +++++++++++++++---- .../Source/Asset/WhiteBoxMeshAssetHandler.cpp | 7 ++++-- .../Code/Source/Core/WhiteBoxToolApi.cpp | 12 +++++----- .../Code/Source/EditorWhiteBoxComponent.cpp | 14 ++++++------ Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp | 3 ++- 5 files changed, 38 insertions(+), 20 deletions(-) diff --git a/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h b/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h index 5b8d384774..8e74c09f52 100644 --- a/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h +++ b/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h @@ -729,15 +729,29 @@ namespace WhiteBox /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Serialization + //! The result of attempting to deserialize a white box mesh from a white box mesh stream. + enum class ReadResult + { + Full, //!< The white box mesh stream was full and was read into white box mesh (it is now initialized). + Empty, //!< The white box mesh stream was empty so no white box mesh was loaded. + Error //!< An error occurred while trying to deserialize white box mesh stream. + }; + //! Take an input stream of bytes and create a white box mesh from the deserialized data. - //! @return Will return false if any error was encountered during deserialization, true otherwise. + //! @return Will return ReadResult::Full if the white box mesh stream was filled with data and + //! the white box mesh was initialized, ReadResult::Empty if white box mesh stream did not contain + //! any data (white box mesh will be left empty) or ReadResult::Error if any error was encountered + //! during deserialization. //! @note A white box mesh must have been created first. - bool ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input); + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input); //! Take an input stream and create a white box mesh from the deserialized data. - //! @return Will return false if any error was encountered during deserialization, true otherwise. + //! @return Will return ReadResult::Full if the white box mesh stream was filled with data and + //! the white box mesh was initialized, ReadResult::Empty if white box mesh stream did not contain + //! any data (white box mesh will be left empty) or ReadResult::Error if any error was encountered + //! during deserialization. //! @note The input stream must not skip white space characters (std::noskipws must be set on the stream). - bool ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input); + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input); //! Take a white box mesh and write it out to a stream of bytes. //! @return Will return false if any error was encountered during serialization, true otherwise. diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp index 7aa12777e0..3ed22a3d1b 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp @@ -118,12 +118,15 @@ namespace WhiteBox stream->Read(size, whiteBoxData.data()); auto whiteBoxMesh = WhiteBox::Api::CreateWhiteBoxMesh(); - const bool success = WhiteBox::Api::ReadMesh(*whiteBoxMesh, whiteBoxData); + const auto result = WhiteBox::Api::ReadMesh(*whiteBoxMesh, whiteBoxData); + // if result is not 'Full', then whiteBoxMeshAsset could be empty which is most likely an error + // as no data was loaded from the asset, or it was not correctly read in stream->Read(..) + const auto success = result == Api::ReadResult::Full; if (success) { whiteBoxMeshAsset->SetMesh(AZStd::move(whiteBoxMesh)); - whiteBoxMeshAsset->SetWhiteBoxData(whiteBoxData); + whiteBoxMeshAsset->SetWhiteBoxData(AZStd::move(whiteBoxData)); } return success ? AZ::Data::AssetHandler::LoadResult::LoadComplete diff --git a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp index 03f2545ae1..5803f066ae 100644 --- a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp +++ b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp @@ -3403,13 +3403,13 @@ namespace WhiteBox return false; } - bool ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input) + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); if (input.empty()) { - return false; + return ReadResult::Empty; } std::string inputStr; @@ -3423,19 +3423,19 @@ namespace WhiteBox return ReadMesh(whiteBox, whiteBoxStream); } - bool ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input) + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input) { const auto skipws = input.flags() & std::ios_base::skipws; AZ_Assert(skipws == 0, "Input stream must not skip white space characters"); if (skipws != 0) { - return false; + return ReadResult::Error; } AZStd::lock_guard lg(g_omSerializationLock); OpenMesh::IO::Options options{OpenMesh::IO::Options::FaceTexCoord | OpenMesh::IO::Options::FaceNormal}; - return OpenMesh::IO::read_mesh(whiteBox.mesh, input, ".om", options); + return OpenMesh::IO::read_mesh(whiteBox.mesh, input, ".om", options) ? ReadResult::Full : ReadResult::Error; } WhiteBoxMeshPtr CloneMesh(const WhiteBoxMesh& whiteBox) @@ -3449,7 +3449,7 @@ namespace WhiteBox } WhiteBoxMeshPtr newMesh = CreateWhiteBoxMesh(); - if (!ReadMesh(*newMesh, clonedData)) + if (ReadMesh(*newMesh, clonedData) != ReadResult::Full) { return nullptr; } diff --git a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp index 61012b8577..e88b4ce686 100644 --- a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp +++ b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp @@ -348,14 +348,14 @@ namespace WhiteBox else { // attempt to load the mesh - if (Api::ReadMesh(*m_whiteBox, m_whiteBoxData)) + const auto result = Api::ReadMesh(*m_whiteBox, m_whiteBoxData); + AZ_Error("EditorWhiteBoxComponent", result != WhiteBox::Api::ReadResult::Error, "Error deserializing white box mesh stream"); + + // if the read was successful but the byte stream is empty + // (there was nothing to load), create a default mesh + if (result == Api::ReadResult::Empty) { - // if the read was successful but the byte stream is empty - // (there was nothing to load), create a default mesh - if (m_whiteBoxData.empty()) - { - Api::InitializeAsUnitCube(*m_whiteBox); - } + Api::InitializeAsUnitCube(*m_whiteBox); } } } diff --git a/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp b/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp index 1d55539720..1135a915ec 100644 --- a/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp +++ b/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp @@ -470,6 +470,7 @@ namespace UnitTest TEST_F(WhiteBoxTestFixture, MeshNotDeserializedWithSkipWhiteSpaceStream) { namespace Api = WhiteBox::Api; + using testing::Eq; Api::InitializeAsUnitCube(*m_whiteBox); AZStd::vector serializedWhiteBox; @@ -485,7 +486,7 @@ namespace UnitTest // note: std::stringstream will default to skip white space characters AZ_TEST_START_TRACE_SUPPRESSION; - EXPECT_FALSE(Api::ReadMesh(*m_whiteBox, whiteBoxStream)); + EXPECT_THAT(Api::ReadMesh(*m_whiteBox, whiteBoxStream), Eq(Api::ReadResult::Error)); AZ_TEST_STOP_TRACE_SUPPRESSION(1); }