[LYN-4727] Scene Settings: Updating a default motion in the Scene Settings freezes the tool #1590

This commit is contained in:
Benjamin Jillich
2021-06-25 10:14:30 -07:00
committed by GitHub
6 changed files with 115 additions and 23 deletions
@@ -84,12 +84,11 @@ namespace EMotionFX
}
// Apply motion meta data.
EMotionFX::Pipeline::Rule::MotionMetaData motionMetaData;
if (EMotionFX::Pipeline::Rule::LoadFromGroup<EMotionFX::Pipeline::Rule::MotionMetaDataRule, EMotionFX::Pipeline::Rule::MotionMetaData>(motionGroup, motionMetaData))
AZStd::shared_ptr<EMotionFX::Pipeline::Rule::MotionMetaData> motionMetaData;
if (EMotionFX::Pipeline::Rule::LoadFromGroup<EMotionFX::Pipeline::Rule::MotionMetaDataRule>(motionGroup, motionMetaData))
{
motion->SetEventTable(AZStd::unique_ptr<MotionEventTable>(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);
@@ -16,9 +16,11 @@
#include <SceneAPIExt/Rules/MetaDataRule.h>
#include <SceneAPIExt/Rules/MotionRangeRule.h>
#include <SceneAPIExt/Rules/MotionCompressionSettingsRule.h>
#include <SceneAPIExt/Rules/MotionMetaDataRule.h>
#include <SceneAPIExt/Rules/MotionSamplingRule.h>
#include <SceneAPIExt/Groups/MotionGroup.h>
#include <EMotionFX/CommandSystem/Source/MetaData.h>
#include <EMotionFX/Source/MotionData/NonUniformMotionData.h>
namespace EMotionFX
@@ -89,7 +91,7 @@ namespace EMotionFX
serializeContext->Class<IMotionGroup, AZ::SceneAPI::DataTypes::IGroup>()->Version(1);
serializeContext->Class<MotionGroup, IMotionGroup>()->Version(5, VersionConverter)
serializeContext->Class<MotionGroup, IMotionGroup>()->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<Rule::MetaDataRule>())
{
// Read the old, command-based meta data rule and retrieve the command objects.
Rule::MetaDataRule oldMetaDataRule;
currentRuleNode.GetData<Rule::MetaDataRule>(oldMetaDataRule);
const AZStd::vector<MCore::Command*>& commands = oldMetaDataRule.GetMetaData<const AZStd::vector<MCore::Command*>&>();
// 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<EMotionFX::Pipeline::Rule::MotionMetaData>(motion->GetMotionExtractionFlags(), motion->GetEventTable());
auto metaDataRule = AZStd::make_shared<EMotionFX::Pipeline::Rule::MotionMetaDataRule>(metaData);
// Add the new motion meta data rule.
AZ::SceneAPI::Containers::RuleContainer ruleContainer;
ruleContainerNode->GetDataHierarchy<AZ::SceneAPI::Containers::RuleContainer>(context, ruleContainer);
ruleContainer.RemoveRule(i);
ruleContainer.AddRule(metaDataRule);
ruleContainerNode->SetData(context, ruleContainer);
motion->Destroy();
break;
}
}
}
}
return result;
}
}
@@ -35,7 +35,7 @@ namespace EMotionFX
return false;
}
outData = rule->GetData();
outData = AZStd::move(rule->GetData());
return true;
}
@@ -28,15 +28,46 @@ namespace EMotionFX::Pipeline::Rule
;
}
MotionMetaDataRule::MotionMetaDataRule()
: ExternalToolRule<MotionMetaData>()
MotionMetaData::MotionMetaData(EMotionFX::EMotionExtractionFlags extractionFlags, EMotionFX::MotionEventTable* eventTable)
: m_motionExtractionFlags(extractionFlags)
{
m_motionEventTable = CloneMotionEventTable(eventTable);
}
MotionMetaData::MotionMetaData()
: m_motionExtractionFlags(static_cast<EMotionFX::EMotionExtractionFlags>(0))
{
}
MotionMetaDataRule::MotionMetaDataRule(const MotionMetaData& data)
: MotionMetaDataRule()
AZStd::unique_ptr<EMotionFX::MotionEventTable> MotionMetaData::GetClonedEventTable(EMotionFX::Motion* targetMotion) const
{
AZStd::unique_ptr<EMotionFX::MotionEventTable> clonedEventTable = CloneMotionEventTable(m_motionEventTable.get());
clonedEventTable->InitAfterLoading(targetMotion);
return clonedEventTable;
}
AZStd::unique_ptr<EMotionFX::MotionEventTable> 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<EMotionFX::MotionEventTable> clonedEventTable(serializeContext->CloneObject<EMotionFX::MotionEventTable>(sourceEventTable));
return clonedEventTable;
}
MotionMetaDataRule::MotionMetaDataRule()
: ExternalToolRule<AZStd::shared_ptr<MotionMetaData>>()
{
}
MotionMetaDataRule::MotionMetaDataRule(const AZStd::shared_ptr<MotionMetaData>& data)
: m_data(data)
{
m_data = data;
}
void MotionMetaDataRule::Reflect(AZ::ReflectContext* context)
@@ -8,6 +8,7 @@
#pragma once
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <EMotionFX/Source/MotionEventTable.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
#include <SceneAPI/SceneData/SceneDataConfiguration.h>
@@ -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<EMotionFX::MotionEventTable> GetClonedEventTable(EMotionFX::Motion* targetMotion) const;
static void Reflect(AZ::ReflectContext* context);
EMotionFX::MotionEventTable* m_motionEventTable = nullptr;
private:
static AZStd::unique_ptr<EMotionFX::MotionEventTable> CloneMotionEventTable(EMotionFX::MotionEventTable* sourceEventTable);
EMotionFX::EMotionExtractionFlags m_motionExtractionFlags;
AZStd::unique_ptr<EMotionFX::MotionEventTable> m_motionEventTable;
};
class MotionMetaDataRule
: public ExternalToolRule<MotionMetaData>
: public ExternalToolRule<AZStd::shared_ptr<MotionMetaData>>
{
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<MotionMetaData>& 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<MotionMetaData>& GetData() const override { return m_data; }
void SetData(const AZStd::shared_ptr<MotionMetaData>& data) override { m_data = data; }
static void Reflect(AZ::ReflectContext* context);
private:
MotionMetaData m_data;
AZStd::shared_ptr<MotionMetaData> m_data;
};
} // EMotionFX::Pipeline::Rule
@@ -315,10 +315,8 @@ namespace EMStudio
EMotionFX::Pipeline::Rule::RemoveRuleFromGroup<EMotionFX::Pipeline::Rule::MetaDataRule, const AZStd::vector<MCore::Command*>>(*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<EMotionFX::Pipeline::Rule::MotionMetaDataRule, EMotionFX::Pipeline::Rule::MotionMetaData>(*scene, group, motionMetaData);
auto motionMetaData = AZStd::make_shared<EMotionFX::Pipeline::Rule::MotionMetaData>(motion->GetMotionExtractionFlags(), motion->GetEventTable());
EMotionFX::Pipeline::Rule::SaveToGroup<EMotionFX::Pipeline::Rule::MotionMetaDataRule, AZStd::shared_ptr<EMotionFX::Pipeline::Rule::MotionMetaData>>(*scene, group, motionMetaData);
}
}