From b05984d4caeaa879225e10163b7a60f698aa55b0 Mon Sep 17 00:00:00 2001 From: sconel <32552662+sconel@users.noreply.github.com> Date: Fri, 16 Jul 2021 15:20:52 -0700 Subject: [PATCH] Prevent cached world transform and parent data from being serialized in prefab (#2219) Porting over @AMZN-daimini 's work to clean up unneeded data from prefabs by removing cached transform data from json serialization. This is done by writing an explicit json serializer for the Editor Transform component and opting not to store or load the cached Transform fields. Tested by creating new prefabs, loading and as well as resaving old prefabs which included patches aimed at cached transform data. Signed-off-by: sconel --- .../ToolsComponents/TransformComponent.cpp | 8 + .../ToolsComponents/TransformComponent.h | 2 + .../TransformComponentSerializer.cpp | 218 ++++++++++++++++++ .../TransformComponentSerializer.h | 34 +++ .../aztoolsframework_files.cmake | 2 + 5 files changed, 264 insertions(+) create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentSerializer.cpp create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentSerializer.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp index eea6696e4e..45e83be9c9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -1231,6 +1233,12 @@ namespace AzToolsFramework // string-name differs from class-name to avoid collisions with the other "TransformComponent" (AzFramework::TransformComponent). behaviorContext->Class("EditorTransformBus")->RequestBus("TransformBus"); } + + AZ::JsonRegistrationContext* jsonRegistration = azrtti_cast(context); + if (jsonRegistration) + { + jsonRegistration->Serializer()->HandlesType(); + } } void TransformComponent::AddContextMenuActions(QMenu* menu) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h index 3b1a12738b..9143ada54e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h @@ -38,6 +38,8 @@ namespace AzToolsFramework , private AZ::TransformNotificationBus::MultiHandler , private AZ::TransformHierarchyInformationBus::Handler { + friend class JsonTransformComponentSerializer; + public: friend class TransformComponentFactory; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentSerializer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentSerializer.cpp new file mode 100644 index 0000000000..f791d0f403 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentSerializer.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +namespace AzToolsFramework +{ + namespace Components + { + AZ_CLASS_ALLOCATOR_IMPL(JsonTransformComponentSerializer, AZ::SystemAllocator, 0); + + AZ::JsonSerializationResult::Result JsonTransformComponentSerializer::Load( + void* outputValue, [[maybe_unused]] const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue, AZ::JsonDeserializerContext& context) + { + namespace JSR = AZ::JsonSerializationResult; + + AZ_Assert( + azrtti_typeid() == outputValueTypeId, "Unable to deserialize TransformComponent from json because the provided type is %s.", + outputValueTypeId.ToString().c_str()); + + TransformComponent* transformComponentInstance = reinterpret_cast(outputValue); + AZ_Assert(transformComponentInstance, "Output value for JsonTransformComponentSerializer can't be null."); + + JSR::ResultCode result(JSR::Tasks::ReadField); + { + JSR::ResultCode componentIdLoadResult = ContinueLoadingFromJsonObjectField( + &transformComponentInstance->m_id, azrtti_typeidm_id)>(), + inputValue, "Id", context); + + result.Combine(componentIdLoadResult); + } + + { + JSR::ResultCode parentEntityIdLoadResult = ContinueLoadingFromJsonObjectField( + &transformComponentInstance->m_parentEntityId, azrtti_typeidm_parentEntityId)>(), + inputValue, "Parent Entity", context); + + result.Combine(parentEntityIdLoadResult); + } + + { + JSR::ResultCode transformDataLoadResult = ContinueLoadingFromJsonObjectField( + &transformComponentInstance->m_editorTransform, azrtti_typeidm_editorTransform)>(), + inputValue, "Transform Data", context); + + result.Combine(transformDataLoadResult); + } + + { + JSR::ResultCode parentActivationTransformModeLoadResult = ContinueLoadingFromJsonObjectField( + &transformComponentInstance->m_parentActivationTransformMode, azrtti_typeidm_parentActivationTransformMode)>(), + inputValue, "Parent Activation Transform Mode", context); + + result.Combine(parentActivationTransformModeLoadResult); + } + + { + JSR::ResultCode isStaticLoadResult = ContinueLoadingFromJsonObjectField( + &transformComponentInstance->m_isStatic, azrtti_typeidm_isStatic)>(), + inputValue, "IsStatic", context); + + result.Combine(isStaticLoadResult); + } + + { + JSR::ResultCode netSyncEnabledLoadResult = ContinueLoadingFromJsonObjectField( + &transformComponentInstance->m_netSyncEnabled, azrtti_typeidm_netSyncEnabled)>(), + inputValue, "Sync Enabled", context); + + result.Combine(netSyncEnabledLoadResult); + } + + { + JSR::ResultCode interpolatePositionLoadResult = ContinueLoadingFromJsonObjectField( + &transformComponentInstance->m_interpolatePosition, azrtti_typeidm_interpolatePosition)>(), + inputValue, "InterpolatePosition", context); + + result.Combine(interpolatePositionLoadResult); + } + + { + JSR::ResultCode interpolateRotationLoadResult = ContinueLoadingFromJsonObjectField( + &transformComponentInstance->m_interpolateRotation, azrtti_typeidm_interpolateRotation)>(), + inputValue, "InterpolateRotation", context); + + result.Combine(interpolateRotationLoadResult); + } + + return context.Report( + result, + result.GetProcessing() != JSR::Processing::Halted ? "Successfully loaded TransformComponent information." + : "Failed to load TransformComponent information."); + } + + AZ::JsonSerializationResult::Result JsonTransformComponentSerializer::Store( + rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, [[maybe_unused]] const AZ::Uuid& valueTypeId, + AZ::JsonSerializerContext& context) + { + namespace JSR = AZ::JsonSerializationResult; + + AZ_Assert( + azrtti_typeid() == valueTypeId, "Unable to Serialize TransformComponent because the provided type is %s.", + valueTypeId.ToString().c_str()); + + const TransformComponent* transformComponentInstance = reinterpret_cast(inputValue); + AZ_Assert(transformComponentInstance, "Input value for JsonTransformComponentSerializer can't be null."); + const TransformComponent* defaultTransformComponentInstance = reinterpret_cast(defaultValue); + + JSR::ResultCode result(JSR::Tasks::WriteValue); + { + AZ::ScopedContextPath subPathName(context, "m_id"); + const AZ::ComponentId* componentId = &transformComponentInstance->m_id; + const AZ::ComponentId* defaultComponentId = defaultTransformComponentInstance ? &defaultTransformComponentInstance->m_id : nullptr; + + JSR::ResultCode resultComponentId = ContinueStoringToJsonObjectField( + outputValue, "Id", componentId, defaultComponentId, azrtti_typeidm_id)>(), context); + + result.Combine(resultComponentId); + } + + { + AZ::ScopedContextPath subPathName(context, "m_parentEntityId"); + const AZ::EntityId* parentEntityId = &transformComponentInstance->m_parentEntityId; + const AZ::EntityId* defaultParentEntityId = defaultTransformComponentInstance ? &defaultTransformComponentInstance->m_parentEntityId : nullptr; + + JSR::ResultCode resultParentEntityId = ContinueStoringToJsonObjectField( + outputValue, "Parent Entity", parentEntityId, defaultParentEntityId, azrtti_typeidm_parentEntityId)>(), context); + + result.Combine(resultParentEntityId); + } + + { + AZ::ScopedContextPath subPathName(context, "m_editorTransform"); + const EditorTransform* editorTransform = &transformComponentInstance->m_editorTransform; + const EditorTransform* defaultEditorTransform = + defaultTransformComponentInstance ? &defaultTransformComponentInstance->m_editorTransform : nullptr; + + JSR::ResultCode resultEditorTransform = ContinueStoringToJsonObjectField( + outputValue, "Transform Data", editorTransform, defaultEditorTransform, + azrtti_typeidm_editorTransform)>(), context); + + result.Combine(resultEditorTransform); + } + + { + AZ::ScopedContextPath subPathName(context, "m_parentActivationTransformMode"); + const AZ::TransformConfig::ParentActivationTransformMode* parentActivationTransformMode = &transformComponentInstance->m_parentActivationTransformMode; + const AZ::TransformConfig::ParentActivationTransformMode* defaultParentActivationTransformMode = + defaultTransformComponentInstance ? &defaultTransformComponentInstance->m_parentActivationTransformMode : nullptr; + + JSR::ResultCode resultParentActivationTransformMode = ContinueStoringToJsonObjectField( + outputValue, "Parent Activation Transform Mode", parentActivationTransformMode, defaultParentActivationTransformMode, + azrtti_typeidm_parentActivationTransformMode)>(), context); + + result.Combine(resultParentActivationTransformMode); + } + + { + AZ::ScopedContextPath subPathName(context, "m_isStatic"); + const bool* isStatic = &transformComponentInstance->m_isStatic; + const bool* defaultIsStatic = defaultTransformComponentInstance ? &defaultTransformComponentInstance->m_isStatic : nullptr; + + JSR::ResultCode resultIsStatic = ContinueStoringToJsonObjectField( + outputValue, "IsStatic", isStatic, defaultIsStatic, + azrtti_typeidm_isStatic)>(), context); + + result.Combine(resultIsStatic); + } + + { + AZ::ScopedContextPath subPathName(context, "m_netSyncEnabled"); + const bool* netSyncEnabled = &transformComponentInstance->m_netSyncEnabled; + const bool* defaultNetSyncEnabled = defaultTransformComponentInstance ? &defaultTransformComponentInstance->m_netSyncEnabled : nullptr; + + JSR::ResultCode resultNetSyncEnabled = ContinueStoringToJsonObjectField( + outputValue, "Sync Enabled", netSyncEnabled, defaultNetSyncEnabled, azrtti_typeidm_netSyncEnabled)>(), + context); + + result.Combine(resultNetSyncEnabled); + } + + { + AZ::ScopedContextPath subPathName(context, "m_interpolatePosition"); + const AZ::InterpolationMode* interpolatePosition = &transformComponentInstance->m_interpolatePosition; + const AZ::InterpolationMode* defaultInterpolatePosition = defaultTransformComponentInstance ? &defaultTransformComponentInstance->m_interpolatePosition : nullptr; + + JSR::ResultCode resultInterpolatePosition = ContinueStoringToJsonObjectField( + outputValue, "InterpolatePosition", interpolatePosition, defaultInterpolatePosition, azrtti_typeidm_interpolatePosition)>(), + context); + + result.Combine(resultInterpolatePosition); + } + + { + AZ::ScopedContextPath subPathName(context, "m_interpolateRotation"); + const AZ::InterpolationMode* interpolateRotation = &transformComponentInstance->m_interpolateRotation; + const AZ::InterpolationMode* defaultInterpolateRotation = defaultTransformComponentInstance ? &defaultTransformComponentInstance->m_interpolateRotation : nullptr; + + JSR::ResultCode resultInterpolateRotation = ContinueStoringToJsonObjectField( + outputValue, "InterpolateRotation", interpolateRotation, defaultInterpolateRotation, azrtti_typeidm_interpolateRotation)>(), + context); + + result.Combine(resultInterpolateRotation); + } + + return context.Report( + result, + result.GetProcessing() != JSR::Processing::Halted ? "Successfully stored TransformComponent information." + : "Failed to store TransformComponent information."); + } + + } // namespace Components +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentSerializer.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentSerializer.h new file mode 100644 index 0000000000..5d325b556d --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentSerializer.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include + +namespace AzToolsFramework +{ + namespace Components + { + class JsonTransformComponentSerializer + : public AZ::BaseJsonSerializer + { + public: + AZ_RTTI(JsonTransformComponentSerializer, "{F8BA0E22-1DD5-4BCC-A371-0988F8815CF4}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + + AZ::JsonSerializationResult::Result Load( + void* outputValue, const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + AZ::JsonDeserializerContext& context) override; + + AZ::JsonSerializationResult::Result Store( + rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const AZ::Uuid& valueTypeId, + AZ::JsonSerializerContext& context) override; + }; + + } // namespace Components +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 7fbde67ce4..1360f39d08 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -289,6 +289,8 @@ set(FILES ToolsComponents/TransformComponent.h ToolsComponents/TransformComponent.cpp ToolsComponents/TransformComponentBus.h + ToolsComponents/TransformComponentSerializer.h + ToolsComponents/TransformComponentSerializer.cpp ToolsComponents/ScriptEditorComponent.cpp ToolsComponents/ScriptEditorComponent.h ToolsComponents/ToolsAssetCatalogComponent.cpp