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/Source/Motion.cpp

333 lines
7.8 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
// include the required headers
#include "EMotionFXConfig.h"
#include "Motion.h"
#include <MCore/Source/IDGenerator.h>
#include "Pose.h"
#include "MotionInstance.h"
#include "Actor.h"
#include "ActorInstance.h"
#include "MotionManager.h"
#include "EventManager.h"
#include "EventHandler.h"
#include "MotionEventTable.h"
#include <EMotionFX/Source/Allocators.h>
#include <EMotionFX/Source/MotionData/MotionData.h>
#include <EMotionFX/Source/Node.h>
#include <EMotionFX/Source/TransformData.h>
namespace EMotionFX
{
AZ_CLASS_ALLOCATOR_IMPL(Motion, MotionAllocator, 0)
Motion::Motion(const char* name)
: BaseObject()
{
mID = MCore::GetIDGenerator().GenerateID();
m_eventTable = AZStd::make_unique<MotionEventTable>();
mUnitType = GetEMotionFX().GetUnitType();
mFileUnitType = mUnitType;
mExtractionFlags = static_cast<EMotionExtractionFlags>(0);
if (name)
{
SetName(name);
}
#if defined(EMFX_DEVELOPMENT_BUILD)
mIsOwnedByRuntime = false;
#endif // EMFX_DEVELOPMENT_BUILD
// automatically register the motion
GetMotionManager().AddMotion(this);
}
Motion::~Motion()
{
// trigger the OnDeleteMotion event
GetEventManager().OnDeleteMotion(this);
// automatically unregister the motion
if (mAutoUnregister)
{
GetMotionManager().RemoveMotion(this, false);
}
delete m_motionData;
}
// set the name of the motion
void Motion::SetName(const char* name)
{
// calculate the ID
mNameID = MCore::GetStringIdPool().GenerateIdForString(name);
}
// set the filename of the motion
void Motion::SetFileName(const char* filename)
{
mFileName = filename;
}
// adjust the dirty flag
void Motion::SetDirtyFlag(bool dirty)
{
mDirtyFlag = dirty;
}
// adjust the auto unregistering from the motion manager on delete
void Motion::SetAutoUnregister(bool enabled)
{
mAutoUnregister = enabled;
}
// do we auto unregister from the motion manager on delete?
bool Motion::GetAutoUnregister() const
{
return mAutoUnregister;
}
void Motion::SetIsOwnedByRuntime(bool isOwnedByRuntime)
{
#if defined(EMFX_DEVELOPMENT_BUILD)
mIsOwnedByRuntime = isOwnedByRuntime;
#else
AZ_UNUSED(isOwnedByRuntime);
#endif
}
bool Motion::GetIsOwnedByRuntime() const
{
#if defined(EMFX_DEVELOPMENT_BUILD)
return mIsOwnedByRuntime;
#else
return true;
#endif
}
const char* Motion::GetName() const
{
return MCore::GetStringIdPool().GetName(mNameID).c_str();
}
const AZStd::string& Motion::GetNameString() const
{
return MCore::GetStringIdPool().GetName(mNameID);
}
void Motion::SetMotionFPS(float motionFPS)
{
mMotionFPS = motionFPS;
}
float Motion::GetMotionFPS() const
{
return mMotionFPS;
}
void Motion::SetDefaultPlayBackInfo(const PlayBackInfo& playBackInfo)
{
m_defaultPlayBackInfo = playBackInfo;
}
PlayBackInfo* Motion::GetDefaultPlayBackInfo()
{
return &m_defaultPlayBackInfo;
}
const PlayBackInfo* Motion::GetDefaultPlayBackInfo() const
{
return &m_defaultPlayBackInfo;
}
bool Motion::GetDirtyFlag() const
{
return mDirtyFlag;
}
void Motion::SetMotionExtractionFlags(EMotionExtractionFlags flags)
{
mExtractionFlags = flags;
}
EMotionExtractionFlags Motion::GetMotionExtractionFlags() const
{
return mExtractionFlags;
}
void Motion::SetCustomData(void* dataPointer)
{
mCustomData = dataPointer;
}
void* Motion::GetCustomData() const
{
return mCustomData;
}
MotionEventTable* Motion::GetEventTable() const
{
return m_eventTable.get();
}
void Motion::SetEventTable(AZStd::unique_ptr<MotionEventTable> eventTable)
{
m_eventTable = AZStd::move(eventTable);
}
void Motion::SetID(uint32 id)
{
mID = id;
}
const char* Motion::GetFileName() const
{
return mFileName.c_str();
}
const AZStd::string& Motion::GetFileNameString() const
{
return mFileName;
}
uint32 Motion::GetID() const
{
return mID;
}
void Motion::SetUnitType(MCore::Distance::EUnitType unitType)
{
mUnitType = unitType;
}
MCore::Distance::EUnitType Motion::GetUnitType() const
{
return mUnitType;
}
void Motion::SetFileUnitType(MCore::Distance::EUnitType unitType)
{
mFileUnitType = unitType;
}
MCore::Distance::EUnitType Motion::GetFileUnitType() const
{
return mFileUnitType;
}
void Motion::Scale(float scaleFactor)
{
AZ_Assert(m_motionData, "Expecting motion data");
m_motionData->Scale(scaleFactor);
GetEventManager().OnScaleMotionData(this, scaleFactor);
}
// scale everything to the given unit type
void Motion::ScaleToUnitType(MCore::Distance::EUnitType targetUnitType)
{
if (mUnitType == targetUnitType)
{
return;
}
// calculate the scale factor and scale
const float scaleFactor = static_cast<float>(MCore::Distance::GetConversionFactor(mUnitType, targetUnitType));
Scale(scaleFactor);
// update the unit type
mUnitType = targetUnitType;
}
void Motion::UpdateDuration()
{
AZ_Assert(m_motionData, "Expecting motion data");
m_motionData->UpdateDuration();
}
float Motion::GetDuration() const
{
AZ_Assert(m_motionData, "Expecting motion data");
return m_motionData->GetDuration();
}
void Motion::CalcNodeTransform(const MotionInstance* instance, Transform* outTransform, [[maybe_unused]] Actor* actor, Node* node, float timeValue, bool enableRetargeting)
{
AZ_Assert(m_motionData, "Expecting motion data");
MotionData::SampleSettings sampleSettings;
sampleSettings.m_actorInstance = instance->GetActorInstance();
sampleSettings.m_inPlace = instance->GetIsInPlace();
sampleSettings.m_mirror = instance->GetMirrorMotion();
sampleSettings.m_retarget = enableRetargeting;
sampleSettings.m_sampleTime = timeValue;
sampleSettings.m_inputPose = sampleSettings.m_actorInstance->GetTransformData()->GetBindPose();
*outTransform = m_motionData->SampleJointTransform(sampleSettings, node->GetNodeIndex());
}
void Motion::Update(const Pose* inputPose, Pose* outputPose, MotionInstance* instance)
{
AZ_Assert(m_motionData, "Expecting motion data");
MotionData::SampleSettings sampleSettings;
sampleSettings.m_actorInstance = instance->GetActorInstance();
sampleSettings.m_inPlace = instance->GetIsInPlace();
sampleSettings.m_mirror = instance->GetMirrorMotion();
sampleSettings.m_retarget = instance->GetRetargetingEnabled();
sampleSettings.m_sampleTime = instance->GetCurrentTime();
sampleSettings.m_inputPose = inputPose ? inputPose : sampleSettings.m_actorInstance->GetTransformData()->GetBindPose();
m_motionData->SamplePose(sampleSettings, outputPose);
}
const MotionData* Motion::GetMotionData() const
{
return m_motionData;
}
MotionData* Motion::GetMotionData()
{
return m_motionData;
}
void Motion::SetMotionData(MotionData* motionData, bool delOldFromMem)
{
if (delOldFromMem)
{
delete m_motionData;
}
m_motionData = motionData;
}
} // namespace EMotionFX