From a462df2991e4e5e76117c49148d76e4a4c7dbe03 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Fri, 25 Jun 2021 16:17:17 +0200 Subject: [PATCH 1/3] [LYN-4727] Version converter for motion group that ports XML serialized object-based commands to Json event data --- .../SceneAPIExt/Groups/MotionGroup.cpp | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Groups/MotionGroup.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Groups/MotionGroup.cpp index d3b74dd72f..c699e12a0c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Groups/MotionGroup.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Groups/MotionGroup.cpp @@ -16,9 +16,11 @@ #include #include #include +#include #include #include +#include #include namespace EMotionFX @@ -89,7 +91,7 @@ namespace EMotionFX serializeContext->Class()->Version(1); - serializeContext->Class()->Version(5, VersionConverter) + serializeContext->Class()->Version(6, VersionConverter) ->Field("name", &MotionGroup::m_name) ->Field("selectedRootBone", &MotionGroup::m_selectedRootBone) ->Field("id", &MotionGroup::m_id) @@ -225,6 +227,60 @@ namespace EMotionFX } } + // Motion meta data introduced (no more string- or object-based commands stored in the former meta data rule) + if (version < 6) + { + AZ::SerializeContext::DataElementNode* ruleContainerNode = classElement.FindSubElement(AZ_CRC("rules", 0x899a993c)); + if (!ruleContainerNode) + { + AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Can't find rule container.\n"); + return false; + } + + AZ::SerializeContext::DataElementNode* rulesNode = ruleContainerNode->FindSubElement(AZ_CRC("rules", 0x899a993c)); + if (!rulesNode) + { + AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Can't find rules within rule container.\n"); + return false; + } + + const int numRules = rulesNode->GetNumSubElements(); + for (int i = 0; i < numRules; ++i) + { + AZ::SerializeContext::DataElementNode& sharedPointerNode = rulesNode->GetSubElement(i); + if (sharedPointerNode.GetNumSubElements() == 1) + { + AZ::SerializeContext::DataElementNode& currentRuleNode = sharedPointerNode.GetSubElement(0); + if (currentRuleNode.GetId() == azrtti_typeid()) + { + // Read the old, command-based meta data rule and retrieve the command objects. + Rule::MetaDataRule oldMetaDataRule; + currentRuleNode.GetData(oldMetaDataRule); + const AZStd::vector& commands = oldMetaDataRule.GetMetaData&>(); + + // Apply the commands onto a temporary motion. + auto motion = new EMotionFX::Motion(""); + motion->SetMotionData(aznew EMotionFX::NonUniformMotionData()); + CommandSystem::MetaData::ApplyMetaDataOnMotion(motion, commands); + + // Construct the new motion meta data rule. + auto metaData = AZStd::make_shared(motion->GetMotionExtractionFlags(), motion->GetEventTable()); + auto metaDataRule = AZStd::make_shared(metaData); + + // Add the new motion meta data rule. + AZ::SceneAPI::Containers::RuleContainer ruleContainer; + ruleContainerNode->GetDataHierarchy(context, ruleContainer); + ruleContainer.RemoveRule(i); + ruleContainer.AddRule(metaDataRule); + ruleContainerNode->SetData(context, ruleContainer); + + motion->Destroy(); + break; + } + } + } + } + return result; } } From 44c813824e0f08a74988d1e27d763cc692be8090 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Fri, 25 Jun 2021 16:18:12 +0200 Subject: [PATCH 2/3] [LYN-4727] Memory management improvements and clear ownership for motion meta data --- .../SceneAPIExt/Rules/MotionMetaDataRule.cpp | 38 +++++++++++++++++-- .../SceneAPIExt/Rules/MotionMetaDataRule.h | 22 +++++++---- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.cpp index f57e4ec268..2bd7e2a57e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.cpp @@ -28,12 +28,44 @@ namespace EMotionFX::Pipeline::Rule ; } - MotionMetaDataRule::MotionMetaDataRule() - : ExternalToolRule() + MotionMetaData::MotionMetaData(EMotionFX::EMotionExtractionFlags extractionFlags, EMotionFX::MotionEventTable* eventTable) + : m_motionExtractionFlags(extractionFlags) + { + m_motionEventTable = CloneMotionEventTable(eventTable); + } + + MotionMetaData::MotionMetaData() + : m_motionExtractionFlags(static_cast(0)) { } - MotionMetaDataRule::MotionMetaDataRule(const MotionMetaData& data) + AZStd::unique_ptr MotionMetaData::GetClonedEventTable(EMotionFX::Motion* targetMotion) const + { + AZStd::unique_ptr clonedEventTable = AZStd::move(CloneMotionEventTable(m_motionEventTable.get())); + clonedEventTable->InitAfterLoading(targetMotion); + return AZStd::move(clonedEventTable); + } + + AZStd::unique_ptr MotionMetaData::CloneMotionEventTable(EMotionFX::MotionEventTable* sourceEventTable) + { + AZ::SerializeContext* serializeContext = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + if (!serializeContext) + { + AZ_Error("EMotionFX", false, "Cannot clone motion event table for motion meta data. Can't get serialize context from component application."); + return {}; + } + + AZStd::unique_ptr clonedEventTable(serializeContext->CloneObject(sourceEventTable)); + return AZStd::move(clonedEventTable); + } + + MotionMetaDataRule::MotionMetaDataRule() + : ExternalToolRule>() + { + } + + MotionMetaDataRule::MotionMetaDataRule(const AZStd::shared_ptr& data) : MotionMetaDataRule() { m_data = data; diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.h b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.h index 099451ff7e..8ede0e130f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.h +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include #include @@ -20,32 +21,39 @@ namespace EMotionFX::Pipeline::Rule AZ_RTTI(EMotionFX::Pipeline::Rule::MotionMetaData, "{A381A915-3CB3-4F60-82B3-70865CFA1F4F}"); AZ_CLASS_ALLOCATOR(MotionMetaData, AZ::SystemAllocator, 0) - MotionMetaData() = default; + MotionMetaData(); + MotionMetaData(EMotionFX::EMotionExtractionFlags extractionFlags, EMotionFX::MotionEventTable* eventTable); virtual ~MotionMetaData() = default; + EMotionFX::EMotionExtractionFlags GetMotionExtractionFlags() const { return m_motionExtractionFlags; } + AZStd::unique_ptr GetClonedEventTable(EMotionFX::Motion* targetMotion) const; + static void Reflect(AZ::ReflectContext* context); - EMotionFX::MotionEventTable* m_motionEventTable = nullptr; + private: + static AZStd::unique_ptr CloneMotionEventTable(EMotionFX::MotionEventTable* sourceEventTable); + EMotionFX::EMotionExtractionFlags m_motionExtractionFlags; + AZStd::unique_ptr m_motionEventTable; }; class MotionMetaDataRule - : public ExternalToolRule + : public ExternalToolRule> { public: AZ_RTTI(EMotionFX::Pipeline::Rule::MotionMetaDataRule, "{E68D0C3D-CBFF-4536-95C1-676474B351A5}", AZ::SceneAPI::DataTypes::IRule); AZ_CLASS_ALLOCATOR(MotionMetaDataRule, AZ::SystemAllocator, 0) MotionMetaDataRule(); - MotionMetaDataRule(const MotionMetaData& data); + MotionMetaDataRule(const AZStd::shared_ptr& data); ~MotionMetaDataRule() final = default; - const MotionMetaData& GetData() const override { return m_data; } - void SetData(const MotionMetaData& data) override { m_data = data; } + const AZStd::shared_ptr& GetData() const override { return m_data; } + void SetData(const AZStd::shared_ptr& data) override { m_data = data; } static void Reflect(AZ::ReflectContext* context); private: - MotionMetaData m_data; + AZStd::shared_ptr m_data; }; } // EMotionFX::Pipeline::Rule From a3d314d0593eb8d80126bfa8e79a8e5d8ed5092b Mon Sep 17 00:00:00 2001 From: Benjamin Jillich Date: Fri, 25 Jun 2021 16:18:54 +0200 Subject: [PATCH 3/3] [LYN-4727] Adapting the motion group exporter and the save commands to the motion meta data changes --- .../Pipeline/RCExt/Motion/MotionGroupExporter.cpp | 9 ++++----- .../Pipeline/SceneAPIExt/Rules/ExternalToolRule.inl | 2 +- .../Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.cpp | 9 ++++----- .../Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp | 6 ++---- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionGroupExporter.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionGroupExporter.cpp index b44f2c36b3..c4ed3307ae 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionGroupExporter.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Motion/MotionGroupExporter.cpp @@ -84,12 +84,11 @@ namespace EMotionFX } // Apply motion meta data. - EMotionFX::Pipeline::Rule::MotionMetaData motionMetaData; - if (EMotionFX::Pipeline::Rule::LoadFromGroup(motionGroup, motionMetaData)) + AZStd::shared_ptr motionMetaData; + if (EMotionFX::Pipeline::Rule::LoadFromGroup(motionGroup, motionMetaData)) { - motion->SetEventTable(AZStd::unique_ptr(motionMetaData.m_motionEventTable)); - motion->GetEventTable()->InitAfterLoading(motion); - motion->SetMotionExtractionFlags(motionMetaData.m_motionExtractionFlags); + motion->SetEventTable(motionMetaData->GetClonedEventTable(motion)); + motion->SetMotionExtractionFlags(motionMetaData->GetMotionExtractionFlags()); } ExporterLib::SaveMotion(filename, motion, MCore::Endian::ENDIAN_LITTLE); diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/ExternalToolRule.inl b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/ExternalToolRule.inl index e98e2e7187..da97743229 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/ExternalToolRule.inl +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/ExternalToolRule.inl @@ -35,7 +35,7 @@ namespace EMotionFX return false; } - outData = rule->GetData(); + outData = AZStd::move(rule->GetData()); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.cpp index 2bd7e2a57e..40648a7f8f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Rules/MotionMetaDataRule.cpp @@ -41,9 +41,9 @@ namespace EMotionFX::Pipeline::Rule AZStd::unique_ptr MotionMetaData::GetClonedEventTable(EMotionFX::Motion* targetMotion) const { - AZStd::unique_ptr clonedEventTable = AZStd::move(CloneMotionEventTable(m_motionEventTable.get())); + AZStd::unique_ptr clonedEventTable = CloneMotionEventTable(m_motionEventTable.get()); clonedEventTable->InitAfterLoading(targetMotion); - return AZStd::move(clonedEventTable); + return clonedEventTable; } AZStd::unique_ptr MotionMetaData::CloneMotionEventTable(EMotionFX::MotionEventTable* sourceEventTable) @@ -57,7 +57,7 @@ namespace EMotionFX::Pipeline::Rule } AZStd::unique_ptr clonedEventTable(serializeContext->CloneObject(sourceEventTable)); - return AZStd::move(clonedEventTable); + return clonedEventTable; } MotionMetaDataRule::MotionMetaDataRule() @@ -66,9 +66,8 @@ namespace EMotionFX::Pipeline::Rule } MotionMetaDataRule::MotionMetaDataRule(const AZStd::shared_ptr& data) - : MotionMetaDataRule() + : m_data(data) { - m_data = data; } void MotionMetaDataRule::Reflect(AZ::ReflectContext* context) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp index 920006b1d4..8c22d657c3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp @@ -315,10 +315,8 @@ namespace EMStudio EMotionFX::Pipeline::Rule::RemoveRuleFromGroup>(*scene, group); // Add motion meta data. - EMotionFX::Pipeline::Rule::MotionMetaData motionMetaData; - motionMetaData.m_motionEventTable = motion->GetEventTable(); - motionMetaData.m_motionExtractionFlags = motion->GetMotionExtractionFlags(); - EMotionFX::Pipeline::Rule::SaveToGroup(*scene, group, motionMetaData); + auto motionMetaData = AZStd::make_shared(motion->GetMotionExtractionFlags(), motion->GetEventTable()); + EMotionFX::Pipeline::Rule::SaveToGroup>(*scene, group, motionMetaData); } }