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.
1138 lines
39 KiB
C++
1138 lines
39 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/SerializeContext.h>
|
|
#include <AzCore/Math/Quaternion.h>
|
|
#include <AzCore/Math/Transform.h>
|
|
#include <AzCore/Component/ComponentApplicationBus.h>
|
|
#include <AzCore/Component/TransformBus.h>
|
|
#include <AzFramework/Components/CameraBus.h>
|
|
|
|
#include "MathConversion.h"
|
|
#include "SceneNode.h"
|
|
#include "AnimSequence.h"
|
|
#include "AnimTrack.h"
|
|
#include "EventTrack.h"
|
|
#include "ConsoleTrack.h"
|
|
#include "SequenceTrack.h"
|
|
#include "GotoTrack.h"
|
|
#include "CaptureTrack.h"
|
|
#include "ISystem.h"
|
|
#include "ITimer.h"
|
|
#include "AnimAZEntityNode.h"
|
|
#include "AnimComponentNode.h"
|
|
#include "Movie.h"
|
|
#include "Maestro/Types/AnimNodeType.h"
|
|
#include "Maestro/Types/AnimValueType.h"
|
|
#include "Maestro/Types/AnimParamType.h"
|
|
|
|
#include <AzCore/Math/MathUtils.h>
|
|
|
|
#include <IAudioSystem.h>
|
|
#include <IConsole.h>
|
|
#include <IViewSystem.h>
|
|
|
|
#define s_nodeParamsInitialized s_nodeParamsInitializedScene
|
|
#define s_nodeParams s_nodeParamsSene
|
|
#define AddSupportedParam AddSupportedParamScene
|
|
|
|
float const kDefaultCameraFOV = 60.0f;
|
|
|
|
namespace {
|
|
bool s_nodeParamsInitialized = false;
|
|
StaticInstance<std::vector<CAnimNode::SParamInfo>> s_nodeParams;
|
|
|
|
void AddSupportedParam(const char* sName, AnimParamType paramId, AnimValueType valueType, int flags = 0)
|
|
{
|
|
CAnimNode::SParamInfo param;
|
|
param.name = sName;
|
|
param.paramType = paramId;
|
|
param.valueType = valueType;
|
|
param.flags = (IAnimNode::ESupportedParamFlags)flags;
|
|
s_nodeParams.push_back(param);
|
|
}
|
|
|
|
class CComponentEntitySceneCamera
|
|
: public CAnimSceneNode::ISceneCamera
|
|
{
|
|
public:
|
|
CComponentEntitySceneCamera(const AZ::EntityId& entityId)
|
|
: m_cameraEntityId(entityId) {}
|
|
|
|
virtual ~CComponentEntitySceneCamera() = default;
|
|
|
|
const Vec3& GetPosition() const override
|
|
{
|
|
AZ::Vector3 pos;
|
|
AZ::TransformBus::EventResult(pos, m_cameraEntityId, &AZ::TransformBus::Events::GetWorldTranslation);
|
|
m_vec3Buffer.Set(pos.GetX(), pos.GetY(), pos.GetZ());
|
|
return m_vec3Buffer;
|
|
}
|
|
const Quat& GetRotation() const override
|
|
{
|
|
AZ::Quaternion quat(AZ::Quaternion::CreateIdentity());
|
|
AZ::TransformBus::EventResult(quat, m_cameraEntityId, &AZ::TransformBus::Events::GetWorldRotationQuaternion);
|
|
m_quatBuffer = AZQuaternionToLYQuaternion(quat);
|
|
return m_quatBuffer;
|
|
}
|
|
void SetPosition(const Vec3& localPosition) override
|
|
{
|
|
AZ::Vector3 pos(localPosition.x, localPosition.y, localPosition.z);
|
|
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetWorldTranslation, pos);
|
|
}
|
|
void SetRotation(const Quat& localRotation) override
|
|
{
|
|
AZ::Quaternion quat = LYQuaternionToAZQuaternion(localRotation);
|
|
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, quat);
|
|
}
|
|
float GetFoV() const
|
|
{
|
|
float retFoV = DEFAULT_FOV;
|
|
Camera::CameraRequestBus::EventResult(retFoV, m_cameraEntityId, &Camera::CameraComponentRequests::GetFovDegrees);
|
|
return retFoV;
|
|
}
|
|
float GetNearZ() const
|
|
{
|
|
float retNearZ = DEFAULT_NEAR;
|
|
Camera::CameraRequestBus::EventResult(retNearZ, m_cameraEntityId, &Camera::CameraComponentRequests::GetNearClipDistance);
|
|
return retNearZ;
|
|
}
|
|
void SetNearZAndFOVIfChanged(float fov, float nearZ) override
|
|
{
|
|
float degFoV = AZ::RadToDeg(fov);
|
|
if (!AZ::IsClose(GetFoV(), degFoV, FLT_EPSILON))
|
|
{
|
|
Camera::CameraRequestBus::Event(m_cameraEntityId, &Camera::CameraComponentRequests::SetFovDegrees, degFoV);
|
|
}
|
|
if (!AZ::IsClose(GetNearZ(), nearZ, FLT_EPSILON))
|
|
{
|
|
Camera::CameraRequestBus::Event(m_cameraEntityId, &Camera::CameraComponentRequests::SetNearClipDistance, nearZ);
|
|
}
|
|
}
|
|
void TransformPositionFromLocalToWorldSpace(Vec3& position) override
|
|
{
|
|
AZ::EntityId parentId;
|
|
AZ::TransformBus::EventResult(parentId, m_cameraEntityId, &AZ::TransformBus::Events::GetParentId);
|
|
if (parentId.IsValid())
|
|
{
|
|
AZ::Vector3 pos(position.x, position.y, position.z);
|
|
AZ::Transform worldTM;
|
|
AZ::TransformBus::EventResult(worldTM, parentId, &AZ::TransformBus::Events::GetWorldTM);
|
|
pos = worldTM.TransformPoint(pos);
|
|
position.Set(pos.GetX(), pos.GetY(), pos.GetZ());
|
|
}
|
|
}
|
|
void TransformPositionFromWorldToLocalSpace(Vec3& position) override
|
|
{
|
|
AZ::EntityId parentId;
|
|
AZ::TransformBus::EventResult(parentId, m_cameraEntityId, &AZ::TransformBus::Events::GetParentId);
|
|
if (parentId.IsValid())
|
|
{
|
|
AZ::Vector3 pos(position.x, position.y, position.z);
|
|
AZ::Transform worldTM;
|
|
AZ::TransformBus::EventResult(worldTM, parentId, &AZ::TransformBus::Events::GetWorldTM);
|
|
worldTM = worldTM.GetInverse();
|
|
pos = worldTM.TransformPoint(pos);
|
|
position.Set(pos.GetX(), pos.GetY(), pos.GetZ());
|
|
}
|
|
}
|
|
void TransformRotationFromLocalToWorldSpace(Quat& rotation) override
|
|
{
|
|
AZ::EntityId parentId;
|
|
AZ::TransformBus::EventResult(parentId, m_cameraEntityId, &AZ::TransformBus::Events::GetParentId);
|
|
if (parentId.IsValid())
|
|
{
|
|
AZ::Quaternion rot = LYQuaternionToAZQuaternion(rotation);
|
|
AZ::Transform worldTM;
|
|
AZ::TransformBus::EventResult(worldTM, parentId, &AZ::TransformBus::Events::GetWorldTM);
|
|
AZ::Quaternion worldRot = worldTM.GetRotation();
|
|
rot = worldRot * rot;
|
|
rotation = AZQuaternionToLYQuaternion(rot);
|
|
}
|
|
}
|
|
void SetWorldRotation(const Quat& rotation) override
|
|
{
|
|
AZ::EntityId parentId;
|
|
AZ::TransformBus::EventResult(parentId, m_cameraEntityId, &AZ::TransformBus::Events::GetParentId);
|
|
if (parentId.IsValid())
|
|
{
|
|
AZ::Quaternion rot = LYQuaternionToAZQuaternion(rotation);
|
|
AZ::Transform parentWorldTM;
|
|
AZ::Transform worldTM;
|
|
AZ::TransformBus::EventResult(parentWorldTM, parentId, &AZ::TransformBus::Events::GetWorldTM);
|
|
AZ::TransformBus::EventResult(worldTM, m_cameraEntityId, &AZ::TransformBus::Events::GetWorldTM);
|
|
parentWorldTM.SetRotation(rot);
|
|
parentWorldTM.SetTranslation(worldTM.GetTranslation());
|
|
AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetWorldTM, parentWorldTM);
|
|
}
|
|
else
|
|
{
|
|
SetRotation(rotation);
|
|
}
|
|
}
|
|
bool HasParent() const override
|
|
{
|
|
AZ::EntityId parentId;
|
|
AZ::TransformBus::EventResult(parentId, m_cameraEntityId, &AZ::TransformBus::Events::GetParentId);
|
|
return parentId.IsValid();
|
|
}
|
|
private:
|
|
AZ::EntityId m_cameraEntityId;
|
|
mutable Vec3 m_vec3Buffer; // buffer for returning references
|
|
mutable Quat m_quatBuffer; // buffer for returning references
|
|
};
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimSceneNode::CAnimSceneNode(const int id)
|
|
: CAnimNode(id, AnimNodeType::Director)
|
|
{
|
|
m_lastCameraKey = -1;
|
|
m_lastEventKey = -1;
|
|
m_lastConsoleKey = -1;
|
|
m_lastSequenceKey = -1;
|
|
m_nLastGotoKey = -1;
|
|
m_lastCaptureKey = -1;
|
|
m_bLastCapturingEnded = true;
|
|
m_captureFrameCount = 0;
|
|
m_cvar_t_FixedStep = NULL;
|
|
m_pCamNodeOnHoldForInterp = 0;
|
|
m_CurrentSelectTrack = 0;
|
|
m_CurrentSelectTrackKeyNumber = 0;
|
|
m_lastPrecachePoint = -1.f;
|
|
SetName("Scene");
|
|
|
|
CAnimSceneNode::Initialize();
|
|
|
|
SetFlags(GetFlags() | eAnimNodeFlags_CanChangeName);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimSceneNode::CAnimSceneNode()
|
|
: CAnimSceneNode(0)
|
|
{
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimSceneNode::~CAnimSceneNode()
|
|
{
|
|
ReleaseSounds();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::Initialize()
|
|
{
|
|
if (!s_nodeParamsInitialized)
|
|
{
|
|
s_nodeParamsInitialized = true;
|
|
s_nodeParams.reserve(9);
|
|
AddSupportedParam("Camera", AnimParamType::Camera, AnimValueType::Select);
|
|
AddSupportedParam("Event", AnimParamType::Event, AnimValueType::Unknown);
|
|
AddSupportedParam("Sound", AnimParamType::Sound, AnimValueType::Unknown);
|
|
AddSupportedParam("Sequence", AnimParamType::Sequence, AnimValueType::Unknown);
|
|
AddSupportedParam("Console", AnimParamType::Console, AnimValueType::Unknown);
|
|
AddSupportedParam("GoTo", AnimParamType::Goto, AnimValueType::DiscreteFloat);
|
|
AddSupportedParam("Capture", AnimParamType::Capture, AnimValueType::Unknown);
|
|
AddSupportedParam("Timewarp", AnimParamType::TimeWarp, AnimValueType::Float);
|
|
AddSupportedParam("FixedTimeStep", AnimParamType::FixedTimeStep, AnimValueType::Float);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::CreateDefaultTracks()
|
|
{
|
|
CreateTrack(AnimParamType::Camera);
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
unsigned int CAnimSceneNode::GetParamCount() const
|
|
{
|
|
return s_nodeParams.size();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimParamType CAnimSceneNode::GetParamType(unsigned int nIndex) const
|
|
{
|
|
if (nIndex >= 0 && nIndex < (int)s_nodeParams.size())
|
|
{
|
|
return s_nodeParams[nIndex].paramType;
|
|
}
|
|
|
|
return AnimParamType::Invalid;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CAnimSceneNode::GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const
|
|
{
|
|
for (int i = 0; i < (int)s_nodeParams.size(); i++)
|
|
{
|
|
if (s_nodeParams[i].paramType == paramId)
|
|
{
|
|
info = s_nodeParams[i];
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::Activate(bool bActivate)
|
|
{
|
|
CAnimNode::Activate(bActivate);
|
|
|
|
int trackCount = NumTracks();
|
|
for (int paramIndex = 0; paramIndex < trackCount; paramIndex++)
|
|
{
|
|
CAnimParamType paramId = m_tracks[paramIndex]->GetParameterType();
|
|
IAnimTrack* pTrack = m_tracks[paramIndex].get();
|
|
|
|
if (paramId.GetType() != AnimParamType::Sequence)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
CSequenceTrack* pSequenceTrack = (CSequenceTrack*)pTrack;
|
|
|
|
for (int currKey = 0; currKey < pSequenceTrack->GetNumKeys(); currKey++)
|
|
{
|
|
ISequenceKey key;
|
|
pSequenceTrack->GetKey(currKey, &key);
|
|
|
|
IAnimSequence* pSequence = GetSequenceFromSequenceKey(key);
|
|
|
|
if (pSequence)
|
|
{
|
|
if (bActivate)
|
|
{
|
|
pSequence->Activate();
|
|
|
|
if (key.bOverrideTimes)
|
|
{
|
|
key.fDuration = (key.fEndTime - key.fStartTime) > 0.0f ? (key.fEndTime - key.fStartTime) : 0.0f;
|
|
}
|
|
else
|
|
{
|
|
key.fDuration = pSequence->GetTimeRange().Length();
|
|
}
|
|
|
|
pTrack->SetKey(currKey, &key);
|
|
}
|
|
else
|
|
{
|
|
pSequence->Deactivate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_cvar_t_FixedStep == NULL)
|
|
{
|
|
m_cvar_t_FixedStep = gEnv->pConsole->GetCVar("t_FixedStep");
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::Animate(SAnimContext& ec)
|
|
{
|
|
if (ec.resetting)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CSelectTrack* cameraTrack = NULL;
|
|
CEventTrack* pEventTrack = NULL;
|
|
CSequenceTrack* pSequenceTrack = NULL;
|
|
CConsoleTrack* pConsoleTrack = NULL;
|
|
CGotoTrack* pGotoTrack = NULL;
|
|
CCaptureTrack* pCaptureTrack = NULL;
|
|
/*
|
|
bool bTimeJump = false;
|
|
if (ec.time < m_time)
|
|
bTimeJump = true;
|
|
*/
|
|
|
|
if (gEnv->IsEditor() && m_time > ec.time)
|
|
{
|
|
m_lastPrecachePoint = -1.f;
|
|
}
|
|
|
|
PrecacheDynamic(ec.time);
|
|
|
|
size_t nNumAudioTracks = 0;
|
|
int trackCount = NumTracks();
|
|
for (int paramIndex = 0; paramIndex < trackCount; paramIndex++)
|
|
{
|
|
CAnimParamType paramId = m_tracks[paramIndex]->GetParameterType();
|
|
IAnimTrack* pTrack = m_tracks[paramIndex].get();
|
|
|
|
if (pTrack->GetFlags() & IAnimTrack::eAnimTrackFlags_Disabled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (pTrack->IsMasked(ec.trackMask))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
switch (paramId.GetType())
|
|
{
|
|
case AnimParamType::Camera:
|
|
cameraTrack = (CSelectTrack*)pTrack;
|
|
break;
|
|
case AnimParamType::Event:
|
|
pEventTrack = (CEventTrack*)pTrack;
|
|
break;
|
|
case AnimParamType::Sequence:
|
|
pSequenceTrack = (CSequenceTrack*)pTrack;
|
|
break;
|
|
case AnimParamType::Console:
|
|
pConsoleTrack = (CConsoleTrack*)pTrack;
|
|
break;
|
|
case AnimParamType::Capture:
|
|
pCaptureTrack = (CCaptureTrack*)pTrack;
|
|
break;
|
|
case AnimParamType::Goto:
|
|
pGotoTrack = (CGotoTrack*)pTrack;
|
|
break;
|
|
|
|
case AnimParamType::Sound:
|
|
|
|
++nNumAudioTracks;
|
|
if (nNumAudioTracks > m_SoundInfo.size())
|
|
{
|
|
m_SoundInfo.resize(nNumAudioTracks);
|
|
}
|
|
|
|
AnimateSound(m_SoundInfo, ec, pTrack, nNumAudioTracks);
|
|
|
|
break;
|
|
|
|
case AnimParamType::TimeWarp:
|
|
{
|
|
float timeScale = 1.0f;
|
|
pTrack->GetValue(ec.time, timeScale);
|
|
if (timeScale < .0f)
|
|
{
|
|
timeScale = .0f;
|
|
}
|
|
|
|
// if set, disable fixed time step cvar so timewarping will have an affect. We never set it back though - that is
|
|
// likely a bug!
|
|
if (m_cvar_t_FixedStep && m_cvar_t_FixedStep->GetFVal() != .0f)
|
|
{
|
|
m_cvar_t_FixedStep->Set(.0f);
|
|
}
|
|
gEnv->pTimer->SetTimeScale(timeScale, ITimer::eTSC_Trackview);
|
|
|
|
}
|
|
break;
|
|
case AnimParamType::FixedTimeStep:
|
|
{
|
|
float timeStep = 0;
|
|
pTrack->GetValue(ec.time, timeStep);
|
|
if (timeStep < 0)
|
|
{
|
|
timeStep = 0;
|
|
}
|
|
if (m_cvar_t_FixedStep)
|
|
{
|
|
m_cvar_t_FixedStep->Set(timeStep);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Animate Camera Track (aka Select Track)
|
|
|
|
// Check if a camera override is set by CVar
|
|
const char* overrideCamName = gEnv->pMovieSystem->GetOverrideCamName();
|
|
AZ::EntityId overrideCamId;
|
|
if (overrideCamName != 0 && strlen(overrideCamName) > 0)
|
|
{
|
|
// overriding with a Camera Component entity is done by entityId (as names are not unique among AZ::Entities) - try to convert string to u64 to see if it's an id
|
|
AZ::u64 u64Id = strtoull(overrideCamName, nullptr, /*base (radix)*/ 10);
|
|
if (u64Id)
|
|
{
|
|
overrideCamId = AZ::EntityId(u64Id);
|
|
}
|
|
}
|
|
|
|
if (overrideCamId.IsValid()) // There is a valid overridden camera.
|
|
{
|
|
if (overrideCamId != gEnv->pMovieSystem->GetCameraParams().cameraEntityId)
|
|
{
|
|
ISelectKey key;
|
|
key.szSelection = overrideCamName;
|
|
key.cameraAzEntityId = overrideCamId;
|
|
ApplyCameraKey(key, ec);
|
|
}
|
|
}
|
|
else if (cameraTrack) // No camera override by CVar, use the camera track
|
|
{
|
|
ISelectKey key;
|
|
int cameraKey = cameraTrack->GetActiveKey(ec.time, &key);
|
|
m_CurrentSelectTrackKeyNumber = cameraKey;
|
|
m_CurrentSelectTrack = cameraTrack;
|
|
ApplyCameraKey(key, ec);
|
|
m_lastCameraKey = cameraKey;
|
|
}
|
|
|
|
if (pEventTrack)
|
|
{
|
|
IEventKey key;
|
|
int nEventKey = pEventTrack->GetActiveKey(ec.time, &key);
|
|
if (nEventKey != m_lastEventKey && nEventKey >= 0)
|
|
{
|
|
bool bNotTrigger = key.bNoTriggerInScrubbing && ec.singleFrame && key.time != ec.time;
|
|
if (!bNotTrigger)
|
|
{
|
|
ApplyEventKey(key, ec);
|
|
}
|
|
}
|
|
m_lastEventKey = nEventKey;
|
|
}
|
|
|
|
if (pConsoleTrack)
|
|
{
|
|
IConsoleKey key;
|
|
int nConsoleKey = pConsoleTrack->GetActiveKey(ec.time, &key);
|
|
if (nConsoleKey != m_lastConsoleKey && nConsoleKey >= 0)
|
|
{
|
|
if (!ec.singleFrame || key.time == ec.time) // If Single frame update key time must match current time.
|
|
{
|
|
ApplyConsoleKey(key, ec);
|
|
}
|
|
}
|
|
m_lastConsoleKey = nConsoleKey;
|
|
}
|
|
|
|
if (pSequenceTrack)
|
|
{
|
|
ISequenceKey key;
|
|
int nSequenceKey = pSequenceTrack->GetActiveKey(ec.time, &key);
|
|
IAnimSequence* pSequence = GetSequenceFromSequenceKey(key);
|
|
|
|
if (!gEnv->IsEditing() && (nSequenceKey != m_lastSequenceKey || !GetMovieSystem()->IsPlaying(pSequence)))
|
|
{
|
|
ApplySequenceKey(pSequenceTrack, m_lastSequenceKey, nSequenceKey, key, ec);
|
|
}
|
|
m_lastSequenceKey = nSequenceKey;
|
|
}
|
|
|
|
if (pGotoTrack)
|
|
{
|
|
ApplyGotoKey(pGotoTrack, ec);
|
|
}
|
|
|
|
if (pCaptureTrack && gEnv->pMovieSystem->IsInBatchRenderMode() == false)
|
|
{
|
|
ICaptureKey key;
|
|
int nCaptureKey = pCaptureTrack->GetActiveKey(ec.time, &key);
|
|
bool justEnded = false;
|
|
if (!m_bLastCapturingEnded && key.time + key.duration < ec.time)
|
|
{
|
|
justEnded = true;
|
|
}
|
|
|
|
if (!ec.singleFrame && !(gEnv->IsEditor() && gEnv->IsEditing()))
|
|
{
|
|
if (nCaptureKey != m_lastCaptureKey && nCaptureKey >= 0)
|
|
{
|
|
if (m_bLastCapturingEnded == false)
|
|
{
|
|
assert(0);
|
|
gEnv->pMovieSystem->EndCapture();
|
|
m_bLastCapturingEnded = true;
|
|
}
|
|
gEnv->pMovieSystem->EnableFixedStepForCapture(key.timeStep);
|
|
gEnv->pMovieSystem->StartCapture(key, m_captureFrameCount);
|
|
if (key.once == false)
|
|
{
|
|
m_bLastCapturingEnded = false;
|
|
}
|
|
m_lastCaptureKey = nCaptureKey;
|
|
}
|
|
else if (justEnded)
|
|
{
|
|
gEnv->pMovieSystem->DisableFixedStepForCapture();
|
|
gEnv->pMovieSystem->EndCapture();
|
|
m_bLastCapturingEnded = true;
|
|
}
|
|
}
|
|
|
|
m_captureFrameCount++;
|
|
}
|
|
|
|
m_time = ec.time;
|
|
if (m_pOwner)
|
|
{
|
|
m_pOwner->OnNodeAnimated(this);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::OnReset()
|
|
{
|
|
if (m_lastSequenceKey >= 0)
|
|
{
|
|
{
|
|
int trackCount = NumTracks();
|
|
for (int paramIndex = 0; paramIndex < trackCount; paramIndex++)
|
|
{
|
|
CAnimParamType paramId = m_tracks[paramIndex]->GetParameterType();
|
|
IAnimTrack* pTrack = m_tracks[paramIndex].get();
|
|
|
|
if (paramId.GetType() != AnimParamType::Sequence)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
CSequenceTrack* pSequenceTrack = (CSequenceTrack*)pTrack;
|
|
ISequenceKey prevKey;
|
|
|
|
pSequenceTrack->GetKey(m_lastSequenceKey, &prevKey);
|
|
IAnimSequence* sequence = GetSequenceFromSequenceKey(prevKey);
|
|
if (sequence)
|
|
{
|
|
GetMovieSystem()->StopSequence(sequence);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the last capturing hasn't finished properly, end it here.
|
|
if (m_bLastCapturingEnded == false)
|
|
{
|
|
GetMovieSystem()->EndCapture();
|
|
m_bLastCapturingEnded = true;
|
|
}
|
|
|
|
m_lastEventKey = -1;
|
|
m_lastConsoleKey = -1;
|
|
m_lastSequenceKey = -1;
|
|
m_nLastGotoKey = -1;
|
|
m_lastCaptureKey = -1;
|
|
m_bLastCapturingEnded = true;
|
|
m_captureFrameCount = 0;
|
|
|
|
if (GetTrackForParameter(AnimParamType::TimeWarp))
|
|
{
|
|
gEnv->pTimer->SetTimeScale(1.0f, ITimer::eTSC_Trackview);
|
|
if (m_cvar_t_FixedStep)
|
|
{
|
|
m_cvar_t_FixedStep->Set(0);
|
|
}
|
|
}
|
|
if (GetTrackForParameter(AnimParamType::FixedTimeStep) && m_cvar_t_FixedStep)
|
|
{
|
|
m_cvar_t_FixedStep->Set(0);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::OnStart()
|
|
{
|
|
ResetSounds();
|
|
}
|
|
|
|
void CAnimSceneNode::OnPause()
|
|
{
|
|
}
|
|
|
|
void CAnimSceneNode::OnLoop()
|
|
{
|
|
ResetSounds();
|
|
}
|
|
|
|
void CAnimSceneNode::OnStop()
|
|
{
|
|
ReleaseSounds();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::ResetSounds()
|
|
{
|
|
for (int i = m_SoundInfo.size(); --i >= 0; )
|
|
{
|
|
m_SoundInfo[i].Reset();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::ReleaseSounds()
|
|
{
|
|
// Stop all sounds on the global audio object,
|
|
// but we want to have it filter based on the owner (this)
|
|
// so we don't stop sounds that didn't originate with track view.
|
|
Audio::SAudioRequest request;
|
|
request.nFlags = Audio::eARF_PRIORITY_HIGH;
|
|
request.pOwner = this;
|
|
|
|
Audio::SAudioObjectRequestData<Audio::eAORT_STOP_ALL_TRIGGERS> requestData(/*filterByOwner = */ true);
|
|
request.pData = &requestData;
|
|
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, request);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// InterpolateCameras()
|
|
//
|
|
// This rather long function takes care of the interpolation (or blending) of
|
|
// two camera keys, specifically FoV, nearZ, position and rotation blending.
|
|
//
|
|
void CAnimSceneNode::InterpolateCameras(SCameraParams& retInterpolatedCameraParams, ISceneCamera* firstCamera,
|
|
ISelectKey& firstKey, ISelectKey& secondKey, float time)
|
|
{
|
|
if (!secondKey.cameraAzEntityId.IsValid())
|
|
{
|
|
// abort - can't interpolate if there isn't a valid Id for a component entity camera
|
|
return;
|
|
}
|
|
|
|
static const float EPSILON_TIME = 0.01f; // consider times within EPSILON_TIME of beginning of blend time to be at the beginning of blend time
|
|
float interpolatedFoV;
|
|
|
|
ISceneCamera* secondCamera = static_cast<ISceneCamera*>(new CComponentEntitySceneCamera(secondKey.cameraAzEntityId));
|
|
|
|
float t = 1 - ((secondKey.time - time) / firstKey.fBlendTime);
|
|
t = min(t, 1.0f);
|
|
t = aznumeric_cast<float>(pow(t, 3) * (t * (t * 6 - 15) + 10)); // use a cubic curve for the camera blend
|
|
|
|
bool haveStashedInterpData = (m_InterpolatingCameraStartStates.find(m_CurrentSelectTrackKeyNumber) != m_InterpolatingCameraStartStates.end());
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// at the start of the blend, stash the starting point first camera data to use throughout the interpolation
|
|
if (!haveStashedInterpData)
|
|
{
|
|
InterpolatingCameraStartState camData;
|
|
|
|
camData.m_interpolatedCamFirstPos = firstCamera->GetPosition();
|
|
camData.m_interpolatedCamFirstRot = firstCamera->GetRotation();
|
|
|
|
// stash FoV from the first camera entity
|
|
camData.m_FoV = firstCamera->GetFoV();
|
|
|
|
// stash nearZ
|
|
camData.m_nearZ = firstCamera->GetNearZ();
|
|
|
|
m_InterpolatingCameraStartStates.insert(AZStd::make_pair(m_CurrentSelectTrackKeyNumber, camData));
|
|
}
|
|
|
|
const auto& retStashedInterpCamData = m_InterpolatingCameraStartStates.find(m_CurrentSelectTrackKeyNumber);
|
|
InterpolatingCameraStartState stashedInterpCamData = retStashedInterpCamData->second;
|
|
|
|
// interpolate FOV
|
|
float secondCameraFOV = secondCamera->GetFoV();
|
|
|
|
interpolatedFoV = stashedInterpCamData.m_FoV + (secondCameraFOV - stashedInterpCamData.m_FoV) * t;
|
|
// store the interpolated FoV to be returned, in radians
|
|
retInterpolatedCameraParams.fov = DEG2RAD(interpolatedFoV);
|
|
|
|
// interpolate NearZ
|
|
float secondCameraNearZ = secondCamera->GetNearZ();
|
|
|
|
retInterpolatedCameraParams.nearZ = stashedInterpCamData.m_nearZ + (secondCameraNearZ - stashedInterpCamData.m_nearZ) * t;
|
|
|
|
// update the Camera entity's component FOV and nearZ directly if needed (if they weren't set via anim node SetParamValue() above)
|
|
firstCamera->SetNearZAndFOVIfChanged(retInterpolatedCameraParams.fov, retInterpolatedCameraParams.nearZ);
|
|
|
|
////////////////////////
|
|
// interpolate Position
|
|
Vec3 vFirstCamPos = stashedInterpCamData.m_interpolatedCamFirstPos;
|
|
Vec3 secondKeyPos = secondCamera->GetPosition();
|
|
Vec3 interpolatedPos = vFirstCamPos + (secondKeyPos - vFirstCamPos) * t;
|
|
|
|
firstCamera->SetPosition(interpolatedPos);
|
|
|
|
////////////////////////
|
|
// interpolate Rotation
|
|
Quat firstCameraRotation = stashedInterpCamData.m_interpolatedCamFirstRot;
|
|
Quat secondCameraRotation = secondCamera->GetRotation();
|
|
|
|
Quat interpolatedRotation;
|
|
interpolatedRotation.SetSlerp(firstCameraRotation, secondCameraRotation, t);
|
|
|
|
firstCamera->SetWorldRotation(interpolatedRotation);
|
|
|
|
// clean-up
|
|
if (secondCamera)
|
|
{
|
|
delete secondCamera;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::ApplyCameraKey(ISelectKey& key, SAnimContext& ec)
|
|
{
|
|
ISelectKey nextKey;
|
|
int nextCameraKeyNumber = m_CurrentSelectTrackKeyNumber + 1;
|
|
bool bInterpolateCamera = false;
|
|
|
|
if (nextCameraKeyNumber < m_CurrentSelectTrack->GetNumKeys())
|
|
{
|
|
m_CurrentSelectTrack->GetKey(nextCameraKeyNumber, &nextKey);
|
|
|
|
float fInterTime = nextKey.time - ec.time;
|
|
if (fInterTime >= 0 && fInterTime <= key.fBlendTime)
|
|
{
|
|
bInterpolateCamera = true;
|
|
}
|
|
}
|
|
|
|
// check if we're finished interpolating and there is a camera node on hold for interpolation. If so, unset it from hold.
|
|
if (!bInterpolateCamera && m_pCamNodeOnHoldForInterp)
|
|
{
|
|
m_pCamNodeOnHoldForInterp->SetSkipInterpolatedCameraNode(false);
|
|
m_pCamNodeOnHoldForInterp = 0;
|
|
}
|
|
|
|
SCameraParams cameraParams;
|
|
cameraParams.cameraEntityId.SetInvalid();
|
|
cameraParams.fov = 0;
|
|
cameraParams.justActivated = true;
|
|
|
|
// Init the defaults with the current view settings.
|
|
// With component entities, the fov and near plane may be animated on an
|
|
// entity with a Camera component. Don't stomp the values if this update happens
|
|
// after those properties are animated.
|
|
AZ_Assert(gEnv && gEnv->pSystem, "Expected valid gEnv->pSystem");
|
|
IViewSystem* viewSystem = gEnv->pSystem->GetIViewSystem();
|
|
if (viewSystem)
|
|
{
|
|
IView* view = viewSystem->GetActiveView();
|
|
if (view)
|
|
{
|
|
SViewParams params = *view->GetCurrentParams();
|
|
cameraParams.fov = params.fov;
|
|
cameraParams.nearZ = params.nearplane;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// find the Scene Camera (Camera Component Camera)
|
|
ISceneCamera* firstSceneCamera = nullptr;
|
|
|
|
if (key.cameraAzEntityId.IsValid())
|
|
{
|
|
// camera component entity
|
|
cameraParams.cameraEntityId = key.cameraAzEntityId;
|
|
firstSceneCamera = static_cast<ISceneCamera*>(new CComponentEntitySceneCamera(key.cameraAzEntityId));
|
|
}
|
|
|
|
if (firstSceneCamera)
|
|
{
|
|
cameraParams.fov = DEG2RAD(firstSceneCamera->GetFoV());
|
|
}
|
|
|
|
if (bInterpolateCamera && firstSceneCamera)
|
|
{
|
|
InterpolateCameras(cameraParams, firstSceneCamera, key, nextKey, ec.time);
|
|
}
|
|
|
|
// Broadcast camera changes
|
|
const SCameraParams& lastCameraParams = gEnv->pMovieSystem->GetCameraParams();
|
|
if (lastCameraParams.cameraEntityId != cameraParams.cameraEntityId)
|
|
{
|
|
Maestro::SequenceComponentNotificationBus::Event(
|
|
m_pSequence->GetSequenceEntityId(), &Maestro::SequenceComponentNotificationBus::Events::OnCameraChanged,
|
|
lastCameraParams.cameraEntityId, cameraParams.cameraEntityId);
|
|
|
|
// note: only update the active view if we're currently exporting/capturing a sequence
|
|
if (gEnv->pMovieSystem->IsInBatchRenderMode())
|
|
{
|
|
Camera::CameraRequestBus::Event(
|
|
cameraParams.cameraEntityId, &Camera::CameraRequestBus::Events::MakeActiveView);
|
|
}
|
|
}
|
|
|
|
gEnv->pMovieSystem->SetCameraParams(cameraParams);
|
|
|
|
// This detects when we've switched from one Camera to another on the Camera Track
|
|
// If cameras were interpolated (blended), reset cameras to their pre-interpolated positions and
|
|
// clean up cached data used for the interpolation
|
|
if (m_lastCameraKey != m_CurrentSelectTrackKeyNumber && m_lastCameraKey >= 0)
|
|
{
|
|
const auto& retStashedData = m_InterpolatingCameraStartStates.find(m_lastCameraKey);
|
|
if (retStashedData != m_InterpolatingCameraStartStates.end())
|
|
{
|
|
InterpolatingCameraStartState stashedData = retStashedData->second;
|
|
ISelectKey prevKey;
|
|
ISceneCamera* prevSceneCamera = nullptr;
|
|
|
|
m_CurrentSelectTrack->GetKey(m_lastCameraKey, &prevKey);
|
|
|
|
if (prevKey.cameraAzEntityId.IsValid())
|
|
{
|
|
prevSceneCamera = static_cast<ISceneCamera*>(new CComponentEntitySceneCamera(prevKey.cameraAzEntityId));
|
|
}
|
|
|
|
if (prevSceneCamera)
|
|
{
|
|
prevSceneCamera->SetPosition(stashedData.m_interpolatedCamFirstPos);
|
|
prevSceneCamera->SetRotation(stashedData.m_interpolatedCamFirstRot);
|
|
}
|
|
|
|
IAnimNode* prevCameraAnimNode = m_pSequence->FindNodeByName(prevKey.szSelection.c_str(), this);
|
|
if (prevCameraAnimNode == NULL)
|
|
{
|
|
prevCameraAnimNode = m_pSequence->FindNodeByName(prevKey.szSelection.c_str(), NULL);
|
|
}
|
|
|
|
if (prevCameraAnimNode && prevCameraAnimNode->GetType() == AnimNodeType::Camera && prevCameraAnimNode->GetTrackForParameter(AnimParamType::FOV))
|
|
{
|
|
prevCameraAnimNode->SetParamValue(ec.time, AnimParamType::FOV, stashedData.m_FoV);
|
|
}
|
|
else if (prevSceneCamera)
|
|
{
|
|
prevSceneCamera->SetNearZAndFOVIfChanged(DEG2RAD(stashedData.m_FoV), stashedData.m_nearZ);
|
|
}
|
|
|
|
m_InterpolatingCameraStartStates.erase(m_lastCameraKey);
|
|
|
|
// clean up
|
|
if (prevSceneCamera)
|
|
{
|
|
delete prevSceneCamera;
|
|
}
|
|
}
|
|
}
|
|
|
|
// clean up
|
|
if (firstSceneCamera)
|
|
{
|
|
delete firstSceneCamera;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::ApplyEventKey(IEventKey& key, [[maybe_unused]] SAnimContext& ec)
|
|
{
|
|
char funcName[1024];
|
|
azstrcpy(funcName, "Event_");
|
|
cry_strcat(funcName, key.event.c_str());
|
|
gEnv->pMovieSystem->SendGlobalEvent(funcName);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::ApplyAudioKey(char const* const sTriggerName, bool const bPlay /* = true */)
|
|
{
|
|
Audio::TAudioControlID nAudioTriggerID = INVALID_AUDIO_CONTROL_ID;
|
|
Audio::AudioSystemRequestBus::BroadcastResult(nAudioTriggerID, &Audio::AudioSystemRequestBus::Events::GetAudioTriggerID, sTriggerName);
|
|
if (nAudioTriggerID != INVALID_AUDIO_CONTROL_ID)
|
|
{
|
|
Audio::SAudioRequest oRequest;
|
|
oRequest.nFlags = Audio::eARF_PRIORITY_HIGH;
|
|
oRequest.pOwner = this;
|
|
|
|
if (bPlay)
|
|
{
|
|
Audio::SAudioObjectRequestData<Audio::eAORT_EXECUTE_TRIGGER> oRequestData(nAudioTriggerID, 0.0f);
|
|
oRequest.pData = &oRequestData;
|
|
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, oRequest);
|
|
}
|
|
else
|
|
{
|
|
Audio::SAudioObjectRequestData<Audio::eAORT_STOP_TRIGGER> oRequestData(nAudioTriggerID);
|
|
oRequest.pData = &oRequestData;
|
|
Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, oRequest);
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::ApplySequenceKey(IAnimTrack* pTrack, [[maybe_unused]] int nPrevKey, int nCurrKey, ISequenceKey& key, SAnimContext& ec)
|
|
{
|
|
if (nCurrKey >= 0)
|
|
{
|
|
IAnimSequence* pSequence = GetSequenceFromSequenceKey(key);
|
|
if (pSequence)
|
|
{
|
|
float startTime = -FLT_MAX;
|
|
float endTime = -FLT_MAX;
|
|
|
|
if (key.bOverrideTimes)
|
|
{
|
|
key.fDuration = (key.fEndTime - key.fStartTime) > 0.0f ? (key.fEndTime - key.fStartTime) : 0.0f;
|
|
startTime = key.fStartTime;
|
|
endTime = key.fEndTime;
|
|
}
|
|
else
|
|
{
|
|
key.fDuration = pSequence->GetTimeRange().Length();
|
|
}
|
|
|
|
pTrack->SetKey(nCurrKey, &key);
|
|
|
|
SAnimContext newAnimContext = ec;
|
|
newAnimContext.time = std::min(ec.time - key.time + key.fStartTime, key.fDuration + key.fStartTime);
|
|
|
|
if (static_cast<CAnimSequence*>(pSequence)->GetTime() != newAnimContext.time)
|
|
{
|
|
pSequence->Animate(newAnimContext);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimSceneNode::ApplyConsoleKey(IConsoleKey& key, [[maybe_unused]] SAnimContext& ec)
|
|
{
|
|
if (!key.command.empty())
|
|
{
|
|
gEnv->pConsole->ExecuteString(key.command.c_str());
|
|
}
|
|
}
|
|
|
|
void CAnimSceneNode::ApplyGotoKey(CGotoTrack* poGotoTrack, SAnimContext& ec)
|
|
{
|
|
IDiscreteFloatKey stDiscreteFloadKey;
|
|
int nCurrentActiveKeyIndex(-1);
|
|
|
|
nCurrentActiveKeyIndex = poGotoTrack->GetActiveKey(ec.time, &stDiscreteFloadKey);
|
|
if (nCurrentActiveKeyIndex != m_nLastGotoKey && nCurrentActiveKeyIndex >= 0)
|
|
{
|
|
if (!ec.singleFrame)
|
|
{
|
|
if (stDiscreteFloadKey.m_fValue >= 0)
|
|
{
|
|
string fullname = m_pSequence->GetName();
|
|
GetMovieSystem()->GoToFrame(fullname.c_str(), stDiscreteFloadKey.m_fValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
m_nLastGotoKey = nCurrentActiveKeyIndex;
|
|
}
|
|
|
|
/// @deprecated Serialization for Sequence data in Component Entity Sequences now occurs through AZ::SerializeContext and the Sequence Component
|
|
void CAnimSceneNode::Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks)
|
|
{
|
|
CAnimNode::Serialize(xmlNode, bLoading, bLoadEmptyTracks);
|
|
|
|
// To enable renaming even for previously saved director nodes
|
|
SetFlags(GetFlags() | eAnimNodeFlags_CanChangeName);
|
|
}
|
|
|
|
void CAnimSceneNode::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
|
{
|
|
serializeContext->Class<CAnimSceneNode, CAnimNode>()
|
|
->Version(1);
|
|
}
|
|
}
|
|
|
|
void CAnimSceneNode::PrecacheStatic(float startTime)
|
|
{
|
|
m_lastPrecachePoint = -1.f;
|
|
|
|
const uint numTracks = GetTrackCount();
|
|
for (uint trackIndex = 0; trackIndex < numTracks; ++trackIndex)
|
|
{
|
|
IAnimTrack* pAnimTrack = GetTrackByIndex(trackIndex);
|
|
if (pAnimTrack->GetParameterType() == AnimParamType::Sequence)
|
|
{
|
|
CSequenceTrack* pSequenceTrack = static_cast<CSequenceTrack*>(pAnimTrack);
|
|
|
|
const uint numKeys = pSequenceTrack->GetNumKeys();
|
|
for (uint keyIndex = 0; keyIndex < numKeys; ++keyIndex)
|
|
{
|
|
ISequenceKey key;
|
|
pSequenceTrack->GetKey(keyIndex, &key);
|
|
|
|
CAnimSequence* pSubSequence = static_cast<CAnimSequence*>(GetSequenceFromSequenceKey(key));
|
|
if (pSubSequence)
|
|
{
|
|
pSubSequence->PrecacheStatic(startTime - (key.fStartTime + key.time));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CAnimSceneNode::PrecacheDynamic(float time)
|
|
{
|
|
const uint numTracks = GetTrackCount();
|
|
float fLastPrecachePoint = m_lastPrecachePoint;
|
|
|
|
for (uint trackIndex = 0; trackIndex < numTracks; ++trackIndex)
|
|
{
|
|
IAnimTrack* pAnimTrack = GetTrackByIndex(trackIndex);
|
|
if (pAnimTrack->GetParameterType() == AnimParamType::Sequence)
|
|
{
|
|
CSequenceTrack* pSequenceTrack = static_cast<CSequenceTrack*>(pAnimTrack);
|
|
|
|
const uint numKeys = pSequenceTrack->GetNumKeys();
|
|
for (uint keyIndex = 0; keyIndex < numKeys; ++keyIndex)
|
|
{
|
|
ISequenceKey key;
|
|
pSequenceTrack->GetKey(keyIndex, &key);
|
|
|
|
CAnimSequence* pSubSequence = static_cast<CAnimSequence*>(GetSequenceFromSequenceKey(key));
|
|
if (pSubSequence)
|
|
{
|
|
pSubSequence->PrecacheDynamic(time - (key.fStartTime + key.time));
|
|
}
|
|
}
|
|
}
|
|
else if (pAnimTrack->GetParameterType() == AnimParamType::Camera)
|
|
{
|
|
const float fPrecacheCameraTime = CMovieSystem::m_mov_cameraPrecacheTime;
|
|
if (fPrecacheCameraTime > 0.f)
|
|
{
|
|
CSelectTrack* pCameraTrack = static_cast<CSelectTrack*>(pAnimTrack);
|
|
|
|
ISelectKey key;
|
|
pCameraTrack->GetActiveKey(time + fPrecacheCameraTime, &key);
|
|
|
|
if (time < key.time && (time + fPrecacheCameraTime) > key.time && key.time > m_lastPrecachePoint)
|
|
{
|
|
fLastPrecachePoint = max(key.time, fLastPrecachePoint);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_lastPrecachePoint = fLastPrecachePoint;
|
|
}
|
|
|
|
void CAnimSceneNode::InitializeTrackDefaultValue(IAnimTrack* pTrack, const CAnimParamType& paramType)
|
|
{
|
|
if (paramType.GetType() == AnimParamType::TimeWarp)
|
|
{
|
|
pTrack->SetValue(0.0f, 1.0f, true);
|
|
}
|
|
}
|
|
|
|
/*static*/ IAnimSequence* CAnimSceneNode::GetSequenceFromSequenceKey(const ISequenceKey& sequenceKey)
|
|
{
|
|
IAnimSequence* retSequence = nullptr;
|
|
if (gEnv && gEnv->pMovieSystem)
|
|
{
|
|
if (sequenceKey.sequenceEntityId.IsValid())
|
|
{
|
|
retSequence = gEnv->pMovieSystem->FindSequence(sequenceKey.sequenceEntityId);
|
|
}
|
|
else if (!sequenceKey.szSelection.empty())
|
|
{
|
|
// legacy Deprecate ISequenceKey used names to identify sequences
|
|
retSequence = gEnv->pMovieSystem->FindLegacySequenceByName(sequenceKey.szSelection.c_str());
|
|
}
|
|
}
|
|
|
|
return retSequence;
|
|
}
|
|
|
|
#undef s_nodeParamsInitialized
|
|
#undef s_nodeParams
|
|
#undef AddSupportedParam
|
|
|