You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Groups/ActorGroup.cpp

191 lines
8.2 KiB
C++

/*
* 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 <AzCore/RTTI/ReflectContext.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
#include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
#include <SceneAPI/SceneCore/Containers/Views/SceneGraphDownwardsIterator.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IRule.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IBoneData.h>
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshData.h>
#include <SceneAPI/SceneCore/DataTypes/Groups/ISceneNodeGroup.h>
#include <SceneAPI/SceneData/GraphData/RootBoneData.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
#include <SceneAPI/SceneData/Rules/CoordinateSystemRule.h>
#include <SceneAPIExt/Groups/ActorGroup.h>
#include <SceneAPIExt/Behaviors/ActorGroupBehavior.h>
namespace EMotionFX
{
namespace Pipeline
{
namespace Group
{
AZ_CLASS_ALLOCATOR_IMPL(ActorGroup, AZ::SystemAllocator, 0)
ActorGroup::ActorGroup()
: m_id(AZ::Uuid::CreateRandom())
{
}
const AZStd::string& ActorGroup::GetName() const
{
return m_name;
}
void ActorGroup::SetName(const AZStd::string& name)
{
m_name = name;
}
void ActorGroup::SetName(AZStd::string&& name)
{
m_name = AZStd::move(name);
}
const AZ::Uuid& ActorGroup::GetId() const
{
return m_id;
}
void ActorGroup::OverrideId(const AZ::Uuid& id)
{
m_id = id;
}
AZ::SceneAPI::Containers::RuleContainer& ActorGroup::GetRuleContainer()
{
return m_rules;
}
const AZ::SceneAPI::Containers::RuleContainer& ActorGroup::GetRuleContainerConst() const
{
return m_rules;
}
const AZStd::string & ActorGroup::GetSelectedRootBone() const
{
return m_selectedRootBone;
}
void ActorGroup::SetSelectedRootBone(const AZStd::string & selectedRootBone)
{
m_selectedRootBone = selectedRootBone;
}
void ActorGroup::SetBestMatchingRootBone(const AZ::SceneAPI::Containers::SceneGraph& sceneGraph)
{
auto nameContentView = AZ::SceneAPI::Containers::Views::MakePairView(sceneGraph.GetNameStorage(), sceneGraph.GetContentStorage());
auto graphDownwardsView = AZ::SceneAPI::Containers::Views::MakeSceneGraphDownwardsView<AZ::SceneAPI::Containers::Views::BreadthFirst>(
sceneGraph, sceneGraph.GetRoot(), nameContentView.begin(), true);
for (auto it = graphDownwardsView.begin(); it != graphDownwardsView.end(); ++it)
{
if (it->second && it->second->RTTI_IsTypeOf(AZ::SceneData::GraphData::RootBoneData::TYPEINFO_Uuid()))
{
SetSelectedRootBone(it->first.GetPath());
return;
}
}
}
void ActorGroup::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (!serializeContext)
{
// Check if the context is serialized and has actorGroup class data.
return;
}
serializeContext->Class<IActorGroup, AZ::SceneAPI::DataTypes::IGroup>()->Version(3, IActorGroupVersionConverter);
serializeContext->Class<ActorGroup, IActorGroup>()->Version(6, ActorVersionConverter)
->Field("name", &ActorGroup::m_name)
->Field("selectedRootBone", &ActorGroup::m_selectedRootBone)
->Field("id", &ActorGroup::m_id)
->Field("rules", &ActorGroup::m_rules);
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<ActorGroup>("Actor group", "Configure actor data exporting.")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute("AutoExpand", true)
->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
->DataElement(AZ_CRC("ManifestName", 0x5215b349), &ActorGroup::m_name, "Name actor",
"Name for the group. This name will also be used as the name for the generated file.")
->Attribute("FilterType", IActorGroup::TYPEINFO_Uuid())
->DataElement("NodeListSelection", &ActorGroup::m_selectedRootBone, "Select root bone", "The root bone of the animation that will be exported.")
->Attribute("ClassTypeIdFilter", AZ::SceneAPI::DataTypes::IBoneData::TYPEINFO_Uuid())
->DataElement(AZ::Edit::UIHandlers::Default, &ActorGroup::m_rules, "", "Add or remove rules to fine-tune the export process.")
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20));
}
}
bool ActorGroup::IActorGroupVersionConverter(
[[maybe_unused]] AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
{
const unsigned int version = classElement.GetVersion();
bool result = true;
// In version 1 IActorGroup is directly inherit from IGroup, so there is nothing to do.
// In version 2 IActroGroup is inherit from ISceneNodeGroup, which inherit from IGroup. We need to remove ISceneNodeGroup in-between.
if (version == 2)
{
AZ::SerializeContext::DataElementNode iSceneNodeGroupNode = classElement.GetSubElement(0);
AZ::SerializeContext::DataElementNode iGroupNode = iSceneNodeGroupNode.GetSubElement(0);
classElement.RemoveElement(0);
result = result && classElement.AddElement(iGroupNode);
}
return result;
}
bool ActorGroup::ActorVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
{
const unsigned int version = classElement.GetVersion();
bool result = true;
// Added a uuid "id" as the unique identifier to replace the file name.
// Setting it to null by default and expecting a behavior to patch this when additional information is available.
if (version < 2)
{
result = result && classElement.AddElementWithData<AZ::Uuid>(context, "id", AZ::Uuid::CreateNull()) != -1;
classElement.RemoveElementByName(AZ_CRC("autoCreateTrajectoryNode"));
}
if (version < 3)
{
classElement.RemoveElementByName(AZ_CRC("loadMorphTargets", 0xfd19aef8));
}
// Coordinate system rule moved to the SceneAPI
if (version < 5)
{
if (!AZ::SceneAPI::SceneData::CoordinateSystemRule::ConvertLegacyCoordinateSystemRule(context, classElement))
{
AZ_TracePrintf(AZ::SceneAPI::Utilities::ErrorWindow, "Cannot convert legacy coordinate system rule.\n");
return false;
}
}
if (version < 6)
{
classElement.RemoveElementByName(AZ_CRC("nodeSelectionList"));
}
return result;
}
}
}
}