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.
817 lines
22 KiB
C++
817 lines
22 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
|
|
#include "EditorDefs.h"
|
|
|
|
#include "AnimationContext.h"
|
|
|
|
// CryCommon
|
|
#include <CryCommon/Maestro/Bus/EditorSequenceBus.h>
|
|
|
|
// Editor
|
|
#include "TrackView/TrackViewDialog.h"
|
|
#include "RenderViewport.h"
|
|
#include "ViewManager.h"
|
|
#include "Objects/SelectionGroup.h"
|
|
#include "Include/IObjectManager.h"
|
|
#include "Objects/EntityObject.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Movie Callback.
|
|
//////////////////////////////////////////////////////////////////////////
|
|
class CMovieCallback
|
|
: public IMovieCallback
|
|
{
|
|
protected:
|
|
virtual void OnMovieCallback(ECallbackReason reason, [[maybe_unused]] IAnimNode* pNode)
|
|
{
|
|
switch (reason)
|
|
{
|
|
case CBR_CHANGENODE:
|
|
// Invalidate nodes
|
|
break;
|
|
case CBR_CHANGETRACK:
|
|
{
|
|
// Invalidate tracks
|
|
CTrackViewDialog* pTrackViewDialog = CTrackViewDialog::GetCurrentInstance();
|
|
if (pTrackViewDialog)
|
|
{
|
|
pTrackViewDialog->InvalidateDopeSheet();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void OnSetCamera(const SCameraParams& Params)
|
|
{
|
|
// Only switch camera when in Play mode.
|
|
GUID camObjId = GUID_NULL;
|
|
if (Params.cameraEntityId.IsValid())
|
|
{
|
|
// Find owner editor entity.
|
|
CEntityObject* pEditorEntity = CEntityObject::FindFromEntityId(Params.cameraEntityId);
|
|
if (pEditorEntity)
|
|
{
|
|
camObjId = pEditorEntity->GetId();
|
|
}
|
|
|
|
CViewport* pViewport = GetIEditor()->GetViewManager()->GetSelectedViewport();
|
|
if (CRenderViewport* rvp = viewport_cast<CRenderViewport*>(pViewport))
|
|
{
|
|
if (!rvp->IsSequenceCamera())
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Switch camera in active rendering view.
|
|
if (GetIEditor()->GetViewManager())
|
|
{
|
|
GetIEditor()->GetViewManager()->SetCameraObjectId(camObjId);
|
|
}
|
|
};
|
|
|
|
bool IsSequenceCamUsed() const
|
|
{
|
|
if (gEnv->IsEditorGameMode() == true)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (GetIEditor()->GetViewManager() == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
CViewport* pRendView = GetIEditor()->GetViewManager()->GetViewport(ET_ViewportCamera);
|
|
if (pRendView)
|
|
{
|
|
return pRendView->IsSequenceCamera();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
};
|
|
|
|
static CMovieCallback s_movieCallback;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//-----------------------------------------------------------------------------
|
|
//!
|
|
class CAnimationContextPostRender
|
|
: public IPostRenderer
|
|
{
|
|
public:
|
|
CAnimationContextPostRender(CAnimationContext* pAC)
|
|
: m_pAC(pAC){}
|
|
|
|
void OnPostRender() const { assert(m_pAC); m_pAC->OnPostRender(); }
|
|
|
|
protected:
|
|
CAnimationContext* m_pAC;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimationContext::CAnimationContext()
|
|
{
|
|
m_paused = 0;
|
|
m_playing = false;
|
|
m_recording = false;
|
|
m_bSavedRecordingState = false;
|
|
m_timeRange.Set(0, 0);
|
|
m_timeMarker.Set(0, 0);
|
|
m_currTime = 0.0f;
|
|
m_lastTimeChangedNotificationTime = .0f;
|
|
m_bForceUpdateInNextFrame = false;
|
|
m_fTimeScale = 1.0f;
|
|
m_pSequence = nullptr;
|
|
m_mostRecentSequenceId.SetInvalid();
|
|
m_mostRecentSequenceTime = 0.0f;
|
|
m_bLooping = false;
|
|
m_bAutoRecording = false;
|
|
m_fRecordingTimeStep = 0;
|
|
m_bSingleFrame = false;
|
|
m_bPostRenderRegistered = false;
|
|
m_bForcingAnimation = false;
|
|
GetIEditor()->GetUndoManager()->AddListener(this);
|
|
GetIEditor()->GetSequenceManager()->AddListener(this);
|
|
GetIEditor()->RegisterNotifyListener(this);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAnimationContext::~CAnimationContext()
|
|
{
|
|
GetIEditor()->GetSequenceManager()->RemoveListener(this);
|
|
GetIEditor()->GetUndoManager()->RemoveListener(this);
|
|
GetIEditor()->UnregisterNotifyListener(this);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::Init()
|
|
{
|
|
gEnv->pMovieSystem->SetCallback(&s_movieCallback);
|
|
|
|
REGISTER_COMMAND("mov_goToFrameEditor", (ConsoleCommandFunc)GoToFrameCmd, 0, "Make a specified sequence go to a given frame time in the editor.");
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::AddListener(IAnimationContextListener* pListener)
|
|
{
|
|
stl::push_back_unique(m_contextListeners, pListener);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::RemoveListener(IAnimationContextListener* pListener)
|
|
{
|
|
stl::find_and_erase(m_contextListeners, pListener);
|
|
}
|
|
|
|
void CAnimationContext::NotifyTimeChangedListenersUsingCurrTime() const
|
|
{
|
|
for (size_t i = 0; i < m_contextListeners.size(); ++i)
|
|
{
|
|
m_contextListeners[i]->OnTimeChanged(m_currTime);
|
|
}
|
|
m_lastTimeChangedNotificationTime = m_currTime;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::SetSequence(CTrackViewSequence* sequence, bool force, bool noNotify, bool user)
|
|
{
|
|
float newSeqStartTime = .0f;
|
|
CTrackViewSequence* pCurrentSequence = m_pSequence;
|
|
|
|
if (!force && sequence == pCurrentSequence)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Prevent keys being created from time change
|
|
const bool bRecording = m_recording;
|
|
m_recording = false;
|
|
SetRecordingInternal(false);
|
|
|
|
if (sequence)
|
|
{
|
|
newSeqStartTime = sequence->GetTimeRange().start;
|
|
}
|
|
|
|
m_currTime = newSeqStartTime;
|
|
m_fRecordingCurrTime = newSeqStartTime;
|
|
|
|
if (!m_bPostRenderRegistered)
|
|
{
|
|
if (GetIEditor() && GetIEditor()->GetViewManager())
|
|
{
|
|
CViewport* pViewport = GetIEditor()->GetViewManager()->GetViewport(ET_ViewportCamera);
|
|
if (pViewport)
|
|
{
|
|
pViewport->AddPostRenderer(new CAnimationContextPostRender(this));
|
|
m_bPostRenderRegistered = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_pSequence)
|
|
{
|
|
m_pSequence->Deactivate();
|
|
if (m_playing)
|
|
{
|
|
m_pSequence->EndCutScene();
|
|
}
|
|
|
|
m_pSequence->UnBindFromEditorObjects();
|
|
}
|
|
m_pSequence = sequence;
|
|
|
|
// Notify a new sequence was just selected.
|
|
Maestro::EditorSequenceNotificationBus::Broadcast(&Maestro::EditorSequenceNotificationBus::Events::OnSequenceSelected, m_pSequence ? m_pSequence->GetSequenceComponentEntityId() : AZ::EntityId());
|
|
|
|
if (m_pSequence)
|
|
{
|
|
// Set the last valid sequence that was selected.
|
|
m_mostRecentSequenceId = m_pSequence->GetSequenceComponentEntityId();
|
|
|
|
if (m_playing)
|
|
{
|
|
m_pSequence->BeginCutScene(true);
|
|
}
|
|
|
|
m_timeRange = m_pSequence->GetTimeRange();
|
|
m_timeMarker = m_timeRange;
|
|
|
|
m_pSequence->Activate();
|
|
m_pSequence->PrecacheData(newSeqStartTime);
|
|
|
|
m_pSequence->BindToEditorObjects();
|
|
}
|
|
else if (user)
|
|
{
|
|
// If this was a sequence that was selected by the user in Track View
|
|
// and it was "No Sequence" clear the m_mostRecentSequenceId so the sequence
|
|
// will not be reselected at unwanted events like a slice reload or an undo operation.
|
|
m_mostRecentSequenceId.SetInvalid();
|
|
}
|
|
|
|
ForceAnimation();
|
|
|
|
if (!noNotify)
|
|
{
|
|
NotifyTimeChangedListenersUsingCurrTime();
|
|
for (size_t i = 0; i < m_contextListeners.size(); ++i)
|
|
{
|
|
m_contextListeners[i]->OnSequenceChanged(m_pSequence);
|
|
}
|
|
}
|
|
|
|
TimeChanged(newSeqStartTime);
|
|
|
|
m_recording = bRecording;
|
|
SetRecordingInternal(bRecording);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::UpdateTimeRange()
|
|
{
|
|
if (m_pSequence)
|
|
{
|
|
m_timeRange = m_pSequence->GetTimeRange();
|
|
|
|
// reset the current time to make sure it is clamped
|
|
// to the new range.
|
|
SetTime(m_currTime);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::SetTime(float t)
|
|
{
|
|
if (t < m_timeRange.start)
|
|
{
|
|
t = m_timeRange.start;
|
|
}
|
|
|
|
if (t > m_timeRange.end)
|
|
{
|
|
t = m_timeRange.end;
|
|
}
|
|
|
|
if (fabs(m_currTime - t) < 0.001f)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_currTime = t;
|
|
m_fRecordingCurrTime = t;
|
|
ForceAnimation();
|
|
UpdateAnimatedLights();
|
|
|
|
NotifyTimeChangedListenersUsingCurrTime();
|
|
}
|
|
|
|
void CAnimationContext::TimeChanged(float newTime)
|
|
{
|
|
if (m_pSequence)
|
|
{
|
|
m_mostRecentSequenceTime = newTime;
|
|
m_pSequence->TimeChanged(newTime);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::OnSequenceActivated(AZ::EntityId entityId)
|
|
{
|
|
// If nothing is selected and there is a valid most recent selected
|
|
// try to find that sequence by id and select it. This is useful
|
|
// for restoring the selected sequence during undo and redo.
|
|
if (m_pSequence == nullptr && m_mostRecentSequenceId.IsValid())
|
|
{
|
|
if (entityId == m_mostRecentSequenceId)
|
|
{
|
|
auto editor = GetIEditor();
|
|
if (editor != nullptr)
|
|
{
|
|
auto manager = editor->GetSequenceManager();
|
|
if (manager != nullptr)
|
|
{
|
|
auto sequence = manager->GetSequenceByEntityId(m_mostRecentSequenceId);
|
|
if (sequence != nullptr)
|
|
{
|
|
// Hang onto this because SetSequence() will reset it.
|
|
float lastTime = m_mostRecentSequenceTime;
|
|
|
|
SetSequence(sequence, false, false);
|
|
|
|
// Restore the current time.
|
|
SetTime(lastTime);
|
|
|
|
// Notify time may have changed, use m_currTime incase it was clamped by SetTime()
|
|
TimeChanged(m_currTime);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::Pause()
|
|
{
|
|
assert(m_paused >= 0);
|
|
m_paused++;
|
|
|
|
if (m_recording)
|
|
{
|
|
SetRecordingInternal(false);
|
|
}
|
|
|
|
GetIEditor()->GetMovieSystem()->Pause();
|
|
if (m_pSequence)
|
|
{
|
|
m_pSequence->Pause();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::Resume()
|
|
{
|
|
assert(m_paused > 0);
|
|
m_paused--;
|
|
if (m_recording && m_paused == 0)
|
|
{
|
|
SetRecordingInternal(true);
|
|
}
|
|
GetIEditor()->GetMovieSystem()->Resume();
|
|
|
|
if (m_pSequence)
|
|
{
|
|
m_pSequence->Resume();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::SetRecording(bool recording)
|
|
{
|
|
if (recording == m_recording)
|
|
{
|
|
return;
|
|
}
|
|
m_paused = 0;
|
|
m_recording = recording;
|
|
m_playing = false;
|
|
|
|
if (!recording && m_fRecordingTimeStep != 0)
|
|
{
|
|
SetAutoRecording(false, 0);
|
|
}
|
|
|
|
// If started recording, assume we have modified the document.
|
|
GetIEditor()->SetModifiedFlag();
|
|
|
|
SetRecordingInternal(recording);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::SetPlaying(bool playing)
|
|
{
|
|
if (playing == m_playing)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_paused = 0;
|
|
m_playing = playing;
|
|
m_recording = false;
|
|
SetRecordingInternal(false);
|
|
|
|
if (playing)
|
|
{
|
|
IMovieSystem* pMovieSystem = GetIEditor()->GetMovieSystem();
|
|
|
|
pMovieSystem->Resume();
|
|
if (m_pSequence)
|
|
{
|
|
m_pSequence->Resume();
|
|
|
|
IMovieUser* pMovieUser = pMovieSystem->GetUser();
|
|
|
|
if (pMovieUser)
|
|
{
|
|
m_pSequence->BeginCutScene(true);
|
|
}
|
|
}
|
|
pMovieSystem->ResumeCutScenes();
|
|
}
|
|
else
|
|
{
|
|
IMovieSystem* pMovieSystem = GetIEditor()->GetMovieSystem();
|
|
|
|
pMovieSystem->Pause();
|
|
|
|
if (m_pSequence)
|
|
{
|
|
m_pSequence->Pause();
|
|
}
|
|
|
|
pMovieSystem->PauseCutScenes();
|
|
if (m_pSequence)
|
|
{
|
|
IMovieUser* pMovieUser = pMovieSystem->GetUser();
|
|
|
|
if (pMovieUser)
|
|
{
|
|
m_pSequence->EndCutScene();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::Update()
|
|
{
|
|
if (m_bForceUpdateInNextFrame)
|
|
{
|
|
ForceAnimation();
|
|
m_bForceUpdateInNextFrame = false;
|
|
}
|
|
|
|
// If looking through camera object and recording animation, do not allow camera shake
|
|
if ((GetIEditor()->GetViewManager()->GetCameraObjectId() != GUID_NULL) && GetIEditor()->GetAnimation()->IsRecording())
|
|
{
|
|
GetIEditor()->GetMovieSystem()->EnableCameraShake(false);
|
|
}
|
|
else
|
|
{
|
|
GetIEditor()->GetMovieSystem()->EnableCameraShake(true);
|
|
}
|
|
|
|
if (m_paused > 0 || !(m_playing || m_bAutoRecording))
|
|
{
|
|
if (m_pSequence)
|
|
{
|
|
m_pSequence->StillUpdate();
|
|
}
|
|
|
|
if (!m_recording)
|
|
{
|
|
GetIEditor()->GetMovieSystem()->StillUpdate();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
ITimer* pTimer = GetIEditor()->GetSystem()->GetITimer();
|
|
|
|
if (!m_bAutoRecording)
|
|
{
|
|
AnimateActiveSequence();
|
|
|
|
float dt = pTimer->GetFrameTime();
|
|
m_currTime += dt * m_fTimeScale;
|
|
|
|
if (!m_recording)
|
|
{
|
|
GetIEditor()->GetMovieSystem()->PreUpdate(dt);
|
|
GetIEditor()->GetMovieSystem()->PostUpdate(dt);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
float dt = pTimer->GetFrameTime();
|
|
m_fRecordingCurrTime += dt * m_fTimeScale;
|
|
if (fabs(m_fRecordingCurrTime - m_currTime) > m_fRecordingTimeStep)
|
|
{
|
|
m_currTime += m_fRecordingTimeStep;
|
|
}
|
|
}
|
|
|
|
if (m_currTime > m_timeMarker.end)
|
|
{
|
|
if (m_bAutoRecording)
|
|
{
|
|
SetAutoRecording(false, 0);
|
|
}
|
|
else
|
|
{
|
|
if (m_bLooping)
|
|
{
|
|
m_currTime = m_timeMarker.start;
|
|
if (m_pSequence)
|
|
{
|
|
m_pSequence->OnLoop();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetPlaying(false);
|
|
m_currTime = m_timeMarker.end;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_bAutoRecording)
|
|
{
|
|
// This is auto recording mode.
|
|
// Send sync with physics event to all selected entities.
|
|
GetIEditor()->GetSelection()->SendEvent(EVENT_PHYSICS_GETSTATE);
|
|
}
|
|
|
|
if (fabs(m_lastTimeChangedNotificationTime - m_currTime) > 0.001f)
|
|
{
|
|
NotifyTimeChangedListenersUsingCurrTime();
|
|
}
|
|
|
|
UpdateAnimatedLights();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::ForceAnimation()
|
|
{
|
|
if (m_bForcingAnimation)
|
|
{
|
|
// reentrant calls are possible when using subsequences
|
|
return;
|
|
}
|
|
|
|
m_bForcingAnimation = true;
|
|
|
|
// Before animating node, pause recording.
|
|
if (m_bAutoRecording)
|
|
{
|
|
Pause();
|
|
}
|
|
|
|
AnimateActiveSequence();
|
|
// Animate a second time to properly update camera DoF
|
|
AnimateActiveSequence();
|
|
|
|
if (m_bAutoRecording)
|
|
{
|
|
Resume();
|
|
}
|
|
|
|
m_bForcingAnimation = false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::SetAutoRecording(bool bEnable, float fTimeStep)
|
|
{
|
|
if (bEnable)
|
|
{
|
|
m_bAutoRecording = true;
|
|
m_fRecordingTimeStep = fTimeStep;
|
|
SetRecording(bEnable);
|
|
}
|
|
else
|
|
{
|
|
m_bAutoRecording = false;
|
|
m_fRecordingTimeStep = 0;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::GoToFrameCmd(IConsoleCmdArgs* pArgs)
|
|
{
|
|
if (pArgs->GetArgCount() < 2)
|
|
{
|
|
gEnv->pLog->LogError("GoToFrame: You must provide a 'frame time' to go to");
|
|
return;
|
|
}
|
|
|
|
assert(GetIEditor()->GetAnimation());
|
|
CTrackViewSequence* pSeq = GetIEditor()->GetAnimation()->GetSequence();
|
|
if (!pSeq)
|
|
{
|
|
gEnv->pLog->LogError("GoToFrame: No active animation sequence");
|
|
return;
|
|
}
|
|
|
|
float targetFrame = (float)atof(pArgs->GetArg(1));
|
|
if (pSeq->GetTimeRange().start > targetFrame || targetFrame > pSeq->GetTimeRange().end)
|
|
{
|
|
gEnv->pLog->LogError("GoToFrame: requested time %f is outside the range of sequence %s (%f, %f)", targetFrame, pSeq->GetName(), pSeq->GetTimeRange().start, pSeq->GetTimeRange().end);
|
|
return;
|
|
}
|
|
GetIEditor()->GetAnimation()->m_currTime = targetFrame;
|
|
GetIEditor()->GetAnimation()->m_bSingleFrame = true;
|
|
|
|
GetIEditor()->GetAnimation()->ForceAnimation();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::OnPostRender()
|
|
{
|
|
if (m_pSequence)
|
|
{
|
|
SAnimContext ac;
|
|
ac.dt = 0;
|
|
ac.fps = GetIEditor()->GetSystem()->GetITimer()->GetFrameRate();
|
|
ac.time = m_currTime;
|
|
ac.singleFrame = true;
|
|
ac.forcePlay = true;
|
|
m_pSequence->Render(ac);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::UpdateAnimatedLights()
|
|
{
|
|
bool bLightAnimationSetActive = m_pSequence && (m_pSequence->GetFlags() & IAnimSequence::eSeqFlags_LightAnimationSet);
|
|
if (bLightAnimationSetActive == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
std::vector<CBaseObject*> entityObjects;
|
|
GetIEditor()->GetObjectManager()->FindObjectsOfType(&CEntityObject::staticMetaObject, entityObjects);
|
|
std::for_each(std::begin(entityObjects), std::end(entityObjects),
|
|
[this](CBaseObject* pBaseObject)
|
|
{
|
|
CEntityObject* pEntityObject = static_cast<CEntityObject*>(pBaseObject);
|
|
bool bLight = pEntityObject && pEntityObject->GetEntityClass().compare("Light") == 0;
|
|
if (bLight)
|
|
{
|
|
bool bTimeScrubbing = pEntityObject->GetEntityPropertyBool("bTimeScrubbingInTrackView");
|
|
if (bTimeScrubbing)
|
|
{
|
|
pEntityObject->SetEntityPropertyFloat("_fTimeScrubbed", m_currTime);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::BeginUndoTransaction()
|
|
{
|
|
m_bSavedRecordingState = m_recording;
|
|
SetRecordingInternal(false);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::EndUndoTransaction()
|
|
{
|
|
if (m_pSequence)
|
|
{
|
|
m_pSequence->BindToEditorObjects();
|
|
}
|
|
|
|
SetRecordingInternal(m_bSavedRecordingState);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::TogglePlay()
|
|
{
|
|
if (!IsPlaying())
|
|
{
|
|
SetPlaying(true);
|
|
}
|
|
else
|
|
{
|
|
SetPlaying(false);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::OnSequenceRemoved(CTrackViewSequence* pSequence)
|
|
{
|
|
if (m_pSequence == pSequence)
|
|
{
|
|
SetSequence(nullptr, true, false);
|
|
}
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAnimationContext::OnEditorNotifyEvent(EEditorNotifyEvent event)
|
|
{
|
|
switch (event)
|
|
{
|
|
case eNotify_OnBeginGameMode:
|
|
if (m_pSequence)
|
|
{
|
|
m_pSequence->Resume();
|
|
}
|
|
case eNotify_OnBeginSceneSave:
|
|
case eNotify_OnBeginLayerExport:
|
|
if (m_pSequence)
|
|
{
|
|
m_sequenceToRestore = m_pSequence->GetSequenceComponentEntityId();
|
|
}
|
|
else
|
|
{
|
|
m_sequenceToRestore.SetInvalid();
|
|
}
|
|
|
|
m_sequenceRestoreTime = GetTime();
|
|
|
|
m_bSavedRecordingState = m_recording;
|
|
SetRecordingInternal(false);
|
|
SetSequence(nullptr, true, true);
|
|
break;
|
|
|
|
case eNotify_OnEndGameMode:
|
|
case eNotify_OnEndSceneSave:
|
|
case eNotify_OnEndLayerExport:
|
|
m_currTime = m_sequenceRestoreTime;
|
|
SetSequence(GetIEditor()->GetSequenceManager()->GetSequenceByEntityId(m_sequenceToRestore), true, true);
|
|
SetTime(m_sequenceRestoreTime);
|
|
|
|
SetRecordingInternal(m_bSavedRecordingState);
|
|
break;
|
|
|
|
case eNotify_OnQuit:
|
|
case eNotify_OnCloseScene:
|
|
SetSequence(nullptr, true, false);
|
|
break;
|
|
|
|
case eNotify_OnBeginNewScene:
|
|
SetSequence(nullptr, false, false);
|
|
break;
|
|
|
|
case eNotify_OnBeginLoad:
|
|
m_mostRecentSequenceId.SetInvalid();
|
|
m_mostRecentSequenceTime = 0.0f;
|
|
m_bSavedRecordingState = m_recording;
|
|
SetRecordingInternal(false);
|
|
GetIEditor()->GetAnimation()->SetSequence(nullptr, false, false);
|
|
break;
|
|
|
|
case eNotify_OnEndLoad:
|
|
SetRecordingInternal(m_bSavedRecordingState);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CAnimationContext::SetRecordingInternal(bool enableRecording)
|
|
{
|
|
GetIEditor()->GetMovieSystem()->SetRecording(enableRecording);
|
|
if (m_pSequence)
|
|
{
|
|
m_pSequence->SetRecording(enableRecording);
|
|
}
|
|
}
|
|
|
|
void CAnimationContext::AnimateActiveSequence()
|
|
{
|
|
if (!m_pSequence)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SAnimContext ac;
|
|
ac.dt = 0;
|
|
ac.fps = GetIEditor()->GetSystem()->GetITimer()->GetFrameRate();
|
|
ac.time = m_currTime;
|
|
ac.singleFrame = true;
|
|
ac.forcePlay = true;
|
|
|
|
m_pSequence->Animate(ac);
|
|
m_pSequence->SyncToConsole(ac);
|
|
}
|