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/Rules/MotionSamplingRule.cpp

235 lines
13 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/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <SceneAPIExt/Rules/MotionSamplingRule.h>
#include <EMotionFX/Source/EMotionFXManager.h>
#include <EMotionFX/Source/MotionManager.h>
#include <EMotionFX/Source/MotionData/MotionData.h>
#include <EMotionFX/Source/MotionData/MotionDataFactory.h>
namespace EMotionFX
{
namespace Pipeline
{
namespace Rule
{
AZ_CLASS_ALLOCATOR_IMPL(MotionSamplingRule, AZ::SystemAllocator, 0)
float MotionSamplingRule::GetCustomSampleRate() const
{
return m_customSampleRate;
}
void MotionSamplingRule::SetCustomSampleRate(float rate)
{
m_customSampleRate = rate;
}
AZ::TypeId MotionSamplingRule::GetMotionDataTypeId() const
{
return m_motionDataType;
}
void MotionSamplingRule::SetMotionDataTypeId(const AZ::TypeId& typeId)
{
m_motionDataType = typeId;
}
MotionSamplingRule::SampleRateMethod MotionSamplingRule::GetSampleRateMethod() const
{
return m_sampleRateMethod;
}
void MotionSamplingRule::SetSampleRateMethod(SampleRateMethod method)
{
m_sampleRateMethod = method;
}
bool MotionSamplingRule::GetKeepDuration() const
{
return m_keepDuration;
}
void MotionSamplingRule::SetKeepDuration(bool keepDuration)
{
m_keepDuration = keepDuration;
}
void MotionSamplingRule::SetTranslationQualityPercentage(float value)
{
m_translationQualityPercentage = value;
}
float MotionSamplingRule::GetTranslationQualityPercentage() const
{
return m_translationQualityPercentage;
}
void MotionSamplingRule::SetRotationQualityPercentage(float value)
{
m_rotationQualityPercentage = value;
}
float MotionSamplingRule::GetRotationQualityPercentage() const
{
return m_rotationQualityPercentage;
}
void MotionSamplingRule::SetScaleQualityPercentage(float value)
{
m_scaleQualityPercentage = value;
}
float MotionSamplingRule::GetScaleQualityPercentage() const
{
return m_scaleQualityPercentage;
}
void MotionSamplingRule::SetTranslationQualityByTranslationError(float value)
{
float percentage = (1.0f - value / 0.0225f) * 100.0f;
m_translationQualityPercentage = AZ::GetClamp(percentage, 0.0f, 100.0f);
}
void MotionSamplingRule::SetRotationQualityByRotationError(float value)
{
float percentage = (1.0f - value / 0.0225f) * 100.0f;
m_rotationQualityPercentage = AZ::GetClamp(percentage, 0.0f, 100.0f);
}
void MotionSamplingRule::SetScaleQualityByScaleError(float value)
{
float percentage = (1.0f - value / 0.0225f) * 100.0f;
m_scaleQualityPercentage = AZ::GetClamp(percentage, 0.0f, 100.0f);
}
float MotionSamplingRule::GetAllowedSizePercentage() const
{
return m_allowedSizePercentage;
}
void MotionSamplingRule::SetAllowedSizePercentage(float percentage)
{
m_allowedSizePercentage = percentage;
}
void MotionSamplingRule::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (!serializeContext)
{
return;
}
serializeContext->Class<MotionSamplingRule, IRule>()->Version(4)
->Field("motionDataType", &MotionSamplingRule::m_motionDataType)
->Field("sampleRateMethod", &MotionSamplingRule::m_sampleRateMethod)
->Field("customSampleRate", &MotionSamplingRule::m_customSampleRate)
->Field("translationQualityPercentage", &MotionSamplingRule::m_translationQualityPercentage)
->Field("rotationQualityPercentage", &MotionSamplingRule::m_rotationQualityPercentage)
->Field("scaleQualityPercentage", &MotionSamplingRule::m_scaleQualityPercentage)
->Field("allowedSizePercentage", &MotionSamplingRule::m_allowedSizePercentage)
->Field("keepDuration", &MotionSamplingRule::m_keepDuration);
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<MotionSamplingRule>("Motion sampling", "A collection of settings related to sampling of the motion")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
->DataElement(AZ_CRC("MotionData"), &MotionSamplingRule::m_motionDataType, "Motion data type",
"The motion data type to use. This defines how the motion data is stored. This can have an effect on performance and memory usage.")
->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree)
->DataElement(AZ::Edit::UIHandlers::ComboBox, &MotionSamplingRule::m_sampleRateMethod, "Sample rate", "Either use the Fbx sample rate or use a custom sample rate. The sample rate is automatically limited to the rate from Fbx.")
->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree)
->EnumAttribute(SampleRateMethod::FromSourceScene, "From Source Scene")
->EnumAttribute(SampleRateMethod::Custom, "Custom sample rate")
->DataElement(AZ::Edit::UIHandlers::Default, &MotionSamplingRule::m_keepDuration, "Keep duration", "When enabled this keep the duration the same as the Fbx motion duration, even if no joints are animated. "
"When this option is disabled and the motion doesn't animate any joints then the resulting motion will have a duration of zero seconds.")
->DataElement(AZ::Edit::UIHandlers::Default, &MotionSamplingRule::m_customSampleRate, "Custom sample rate", "Overwrite the sample rate of the motion, in frames per second.")
->Attribute(AZ::Edit::Attributes::Min, 1.0f)
->Attribute(AZ::Edit::Attributes::Max, 240.0f)
->Attribute(AZ::Edit::Attributes::Step, 1.0f)
->Attribute(AZ::Edit::Attributes::Suffix, " FPS")
->Attribute(AZ::Edit::Attributes::Visibility, &MotionSamplingRule::GetVisibilityCustomSampleRate)
->DataElement(AZ::Edit::UIHandlers::Slider, &MotionSamplingRule::m_allowedSizePercentage, "Allowed memory overhead (%)",
"The percentage of extra memory usage allowed compared to the smallest size. For example a value of 10 means we are allowed 10 percent more memory worst case, in trade for extra performance.")
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Max, 100.0f)
->Attribute(AZ::Edit::Attributes::Step, 1.0f)
->Attribute(AZ::Edit::Attributes::Decimals, 0)
->Attribute(AZ::Edit::Attributes::DisplayDecimals, 0)
->Attribute(AZ::Edit::Attributes::Suffix, " Percent")
->Attribute(AZ::Edit::Attributes::Visibility, &MotionSamplingRule::GetVisibilityAllowedSizePercentage)
->DataElement(AZ::Edit::UIHandlers::Slider, &MotionSamplingRule::m_translationQualityPercentage, "Translation quality (%)", "The percentage of quality for translation. Higher values preserve quality, but increase memory usage.")
->Attribute(AZ::Edit::Attributes::Min, 1.0f)
->Attribute(AZ::Edit::Attributes::Max, 100.0f)
->Attribute(AZ::Edit::Attributes::Step, 1.0f)
->Attribute(AZ::Edit::Attributes::Decimals, 0)
->Attribute(AZ::Edit::Attributes::DisplayDecimals, 0)
->Attribute(AZ::Edit::Attributes::Suffix, " Percent")
->Attribute(AZ::Edit::Attributes::Visibility, &MotionSamplingRule::GetVisibilityCompressionSettings)
->DataElement(AZ::Edit::UIHandlers::Slider, &MotionSamplingRule::m_rotationQualityPercentage, "Rotation quality (%)", "The percentage of quality for rotation. Higher values preserve quality, but increase memory usage.")
->Attribute(AZ::Edit::Attributes::Min, 1.0f)
->Attribute(AZ::Edit::Attributes::Max, 100.0f)
->Attribute(AZ::Edit::Attributes::Step, 1.0f)
->Attribute(AZ::Edit::Attributes::Decimals, 0)
->Attribute(AZ::Edit::Attributes::DisplayDecimals, 0)
->Attribute(AZ::Edit::Attributes::Suffix, " Percent")
->Attribute(AZ::Edit::Attributes::Visibility, &MotionSamplingRule::GetVisibilityCompressionSettings)
->DataElement(AZ::Edit::UIHandlers::Slider, &MotionSamplingRule::m_scaleQualityPercentage, "Scale quality (%)", "The percentage of quality for scale. Higher values preserve quality, but increase memory usage.")
->Attribute(AZ::Edit::Attributes::Min, 1.0f)
->Attribute(AZ::Edit::Attributes::Max, 100.0f)
->Attribute(AZ::Edit::Attributes::Step, 1.0f)
->Attribute(AZ::Edit::Attributes::Decimals, 0)
->Attribute(AZ::Edit::Attributes::DisplayDecimals, 0)
->Attribute(AZ::Edit::Attributes::Suffix, " Percent")
->Attribute(AZ::Edit::Attributes::Visibility, &MotionSamplingRule::GetVisibilityCompressionSettings);
}
}
AZ::Crc32 MotionSamplingRule::GetVisibilityCustomSampleRate() const
{
return m_sampleRateMethod == SampleRateMethod::FromSourceScene ? AZ::Edit::PropertyVisibility::Hide : AZ::Edit::PropertyVisibility::Show;
}
AZ::Crc32 MotionSamplingRule::GetVisibilityAllowedSizePercentage() const
{
return m_motionDataType.IsNull() ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
}
AZ::Crc32 MotionSamplingRule::GetVisibilityCompressionSettings() const
{
// We selected the 'Automatic' motion data type.
if (m_motionDataType.IsNull())
{
return AZ::Edit::PropertyVisibility::Show;
}
// Check whether this type supports the compression settings.
const MotionDataFactory& factory = GetMotionManager().GetMotionDataFactory();
if (factory.IsRegisteredTypeId(m_motionDataType))
{
const AZ::Outcome<size_t> index = factory.FindRegisteredIndexByTypeId(m_motionDataType);
if (index.IsSuccess())
{
const MotionData* motionData = factory.GetRegistered(index.GetValue());
AZ_Assert(motionData, "Expected a valid motion data pointer");
return motionData->GetSupportsOptimizeSettings() ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
}
}
return AZ::Edit::PropertyVisibility::Hide;
}
} // Rule
} // Pipeline
} // EMotionFX