diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index e1c9026c74..3adcaa495b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -25,12 +25,16 @@ namespace AZ void EditorMeshComponent::Reflect(AZ::ReflectContext* context) { BaseClass::Reflect(context); + EditorMeshStats::Reflect(context); if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) { + serializeContext->RegisterGenericType(); + serializeContext->Class() ->Version(2, ConvertToEditorRenderComponentAdapter<1>) ->Field("addMaterialComponentFlag", &EditorMeshComponent::m_addMaterialComponentFlag) + ->Field("meshStats", &EditorMeshComponent::m_stats) ; // This shouldn't be registered here, but is required to make a vector from EditorMeshComponentTypeId. This can be removed when one of the following happens: @@ -55,6 +59,8 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ButtonText, "Add Material Component") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorMeshComponent::AddEditorMaterialComponent) ->Attribute(AZ::Edit::Attributes::Visibility, &EditorMeshComponent::GetEditorMaterialComponentVisibility) + ->DataElement(AZ::Edit::UIHandlers::Default, &EditorMeshComponent::m_stats, "Mesh Stats", "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, false) ; editContext->Class( @@ -204,6 +210,22 @@ namespace AZ void EditorMeshComponent::OnModelReady(const Data::Asset& /*modelAsset*/, const Data::Instance& /*model*/) { + const auto& lodAssets = m_controller.GetConfiguration().m_modelAsset->GetLodAssets(); + m_stats.m_meshStatsForLod.clear(); + m_stats.m_meshStatsForLod.reserve(lodAssets.size()); + for (const auto& lodAsset : lodAssets) + { + EditorMeshStatsForLod stats; + const auto& meshes = lodAsset->GetMeshes(); + stats.m_meshCount = meshes.size(); + for (const auto& mesh : meshes) + { + stats.m_vertCount += mesh.GetVertexCount(); + stats.m_triCount += mesh.GetIndexCount() / 3; + } + m_stats.m_meshStatsForLod.emplace_back(AZStd::move(stats)); + } + // Refresh the tree when the model loads to update UI based on the model. AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, @@ -216,6 +238,10 @@ namespace AZ // places it in a bad state, which happens in OnConfigurationChanged base function. // This is a bug with AssetManager [LYN-2249] auto temp = m_controller.m_configuration.m_modelAsset; + + m_stats.m_meshStatsForLod.swap({}); + SetDirty(); + return BaseClass::OnConfigurationChanged(); } } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h index 41ea80f8d1..3397540a92 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace AZ { @@ -71,6 +72,9 @@ namespace AZ // Flag used for button placement bool m_addMaterialComponentFlag = false; + + // Stats for current mesh asset + EditorMeshStats m_stats; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStats.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStats.cpp new file mode 100644 index 0000000000..0830b6d83f --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStats.cpp @@ -0,0 +1,85 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include + +#include +#include + +namespace AZ +{ + namespace Render + { + void EditorMeshStatsForLod::Reflect(ReflectContext* context) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Field("meshCount", &EditorMeshStatsForLod::m_meshCount) + ->Field("vertCount", &EditorMeshStatsForLod::m_vertCount) + ->Field("triCount", &EditorMeshStatsForLod::m_triCount) + ; + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class("EditorMeshStatsForLod", "") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Default, &EditorMeshStatsForLod::m_meshCount, "Mesh Count", "") + ->Attribute(AZ::Edit::Attributes::ReadOnly, true) + ->DataElement(AZ::Edit::UIHandlers::Default, &EditorMeshStatsForLod::m_vertCount, "Vert Count", "") + ->Attribute(AZ::Edit::Attributes::ReadOnly, true) + ->DataElement(AZ::Edit::UIHandlers::Default, &EditorMeshStatsForLod::m_triCount, "Tri Count", "") + ->Attribute(AZ::Edit::Attributes::ReadOnly, true) + ; + } + } + } + + void EditorMeshStats::Reflect(ReflectContext* context) + { + EditorMeshStatsForLod::Reflect(context); + + if (auto jsonContext = azrtti_cast(context)) + { + jsonContext->Serializer()->HandlesType(); + } + + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Field("meshStatsForLod", &EditorMeshStats::m_meshStatsForLod) + ; + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class( + "EditorMeshStats", "") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->DataElement(AZ::Edit::UIHandlers::Default, &EditorMeshStats::m_meshStatsForLod, "Mesh Stats", "") + ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") + ->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::IndexedChildNameLabelOverride, &EditorMeshStats::GetLodLabel) + ; + } + } + } + + AZStd::string EditorMeshStats::GetLodLabel(int index) const + { + return AZStd::string::format("LOD %d", index); + } + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStats.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStats.h new file mode 100644 index 0000000000..6bdce7c008 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStats.h @@ -0,0 +1,47 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + struct EditorMeshStatsForLod final + { + AZ_RTTI(EditorMeshStatsForLod, "{626E3AEB-0F7A-4777-BAF1-2BBA8C1857ED}"); + AZ_CLASS_ALLOCATOR(EditorMeshStatsForLod, SystemAllocator, 0); + + static void Reflect(ReflectContext* context); + + AZ::u32 m_meshCount = 0; + AZ::u32 m_vertCount = 0; + AZ::u32 m_triCount = 0; + }; + + struct EditorMeshStats final + { + AZ_RTTI(EditorMeshStats, "{68D0D3EF-17BB-46EA-B98F-51355402CCD6}"); + AZ_CLASS_ALLOCATOR(EditorMeshStats, SystemAllocator, 0); + + static void Reflect(ReflectContext* context); + AZStd::string GetLodLabel(int index) const; + + AZStd::vector m_meshStatsForLod; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStatsSerializer.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStatsSerializer.cpp new file mode 100644 index 0000000000..ad32c745be --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStatsSerializer.cpp @@ -0,0 +1,54 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include + +namespace AZ +{ + namespace Render + { + AZ_CLASS_ALLOCATOR_IMPL(JsonEditorMeshStatsSerializer, AZ::SystemAllocator, 0); + + JsonSerializationResult::Result JsonEditorMeshStatsSerializer::Load( + [[maybe_unused]] void* outputValue, + [[maybe_unused]] const Uuid& outputValueTypeId, + [[maybe_unused]] const rapidjson::Value& inputValue, + JsonDeserializerContext& context) + { + namespace JSR = JsonSerializationResult; + + JSR::ResultCode result(JSR::Tasks::ReadField); + + return context.Report( + result, + "Successfully loaded EditorMeshStats information."); + } + + JsonSerializationResult::Result JsonEditorMeshStatsSerializer::Store( + [[maybe_unused]] rapidjson::Value& outputValue, + [[maybe_unused]] const void* inputValue, + [[maybe_unused]] const void* defaultValue, + [[maybe_unused]] const Uuid& valueTypeId, + JsonSerializerContext& context) + { + namespace JSR = JsonSerializationResult; + + JSR::ResultCode result(JSR::Tasks::WriteValue); + + return context.Report( + result, + "Successfully stored EditorMeshStats information."); + } + + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStatsSerializer.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStatsSerializer.h new file mode 100644 index 0000000000..733fc3dc97 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshStatsSerializer.h @@ -0,0 +1,40 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#pragma once + +#include +#include + +namespace AZ +{ + namespace Render + { + // Custom JSON serializer for Mesh Stats + // Mesh stats should not be serialized with EditorMeshComponent, because they are calculated based on active model, + // so the serializer simply provides empty load/store functions + class JsonEditorMeshStatsSerializer : public BaseJsonSerializer + { + public: + AZ_RTTI(JsonEditorMeshStatsSerializer, "{571290F5-98C9-45AE-BC8C-E40968B5BA6F}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + + JsonSerializationResult::Result Load( + void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + JsonDeserializerContext& context) override; + + JsonSerializationResult::Result Store( + rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, + JsonSerializerContext& context) override; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake index 020f9014aa..3390529bc6 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake @@ -52,8 +52,12 @@ set(FILES Source/Material/MaterialThumbnail.h Source/Mesh/EditorMeshComponent.h Source/Mesh/EditorMeshComponent.cpp + Source/Mesh/EditorMeshStats.h + Source/Mesh/EditorMeshStats.cpp Source/Mesh/EditorMeshSystemComponent.cpp Source/Mesh/EditorMeshSystemComponent.h + Source/Mesh/EditorMeshStatsSerializer.cpp + Source/Mesh/EditorMeshStatsSerializer.h Source/Mesh/MeshThumbnail.h Source/Mesh/MeshThumbnail.cpp Source/OcclusionCullingPlane/EditorOcclusionCullingPlaneComponent.h