AnimationContext.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "EditorDefs.h"
  9. #include "UiEditorAnimationBus.h"
  10. #include "AnimationContext.h"
  11. #include <LyShine/Animation/IUiAnimation.h>
  12. #include "GameEngine.h"
  13. #include "Objects/EntityObject.h"
  14. #include "Animation/UiAnimViewSequence.h"
  15. #include "Animation/UiAnimViewDialog.h"
  16. #include "Animation/UiAnimViewUndo.h"
  17. #include "Viewport.h"
  18. #include "ViewManager.h"
  19. #include "IPostRenderer.h"
  20. #include "UiEditorAnimationBus.h"
  21. #include <AzCore/Time/ITime.h>
  22. namespace Internal
  23. {
  24. float GetFrameDeltaTime()
  25. {
  26. const AZ::TimeUs frameDeltaTimeMs = AZ::GetSimulationTickDeltaTimeUs();
  27. return AZ::TimeUsToSeconds(frameDeltaTimeMs);
  28. }
  29. float GetFrameRate()
  30. {
  31. const float deltaTime = GetFrameDeltaTime();
  32. if (AZ::IsClose(deltaTime, 0.0f))
  33. {
  34. return 0.0f;
  35. }
  36. return 1.0f / deltaTime;
  37. }
  38. }
  39. //////////////////////////////////////////////////////////////////////////
  40. // Animation Callback.
  41. //////////////////////////////////////////////////////////////////////////
  42. class CUiAnimationCallback
  43. : public IUiAnimationCallback
  44. {
  45. protected:
  46. void OnUiAnimationCallback(ECallbackReason reason, [[maybe_unused]] IUiAnimNode* pNode) override
  47. {
  48. switch (reason)
  49. {
  50. case CBR_CHANGENODE:
  51. // Invalidate nodes
  52. break;
  53. case CBR_CHANGETRACK:
  54. {
  55. // Invalidate tracks
  56. CUiAnimViewDialog* pUiAnimViewDialog = CUiAnimViewDialog::GetCurrentInstance();
  57. if (pUiAnimViewDialog)
  58. {
  59. pUiAnimViewDialog->InvalidateDopeSheet();
  60. }
  61. }
  62. break;
  63. }
  64. }
  65. };
  66. static CUiAnimationCallback s_uiAnimationCallback;
  67. //////////////////////////////////////////////////////////////////////////
  68. //-----------------------------------------------------------------------------
  69. //!
  70. class CAnimationContextPostRender
  71. : public IPostRenderer
  72. {
  73. public:
  74. CAnimationContextPostRender(CUiAnimationContext* pAC)
  75. : m_pAC(pAC){}
  76. void OnPostRender() const { assert(m_pAC); m_pAC->OnPostRender(); }
  77. protected:
  78. CUiAnimationContext* m_pAC;
  79. };
  80. //////////////////////////////////////////////////////////////////////////
  81. CUiAnimationContext::CUiAnimationContext()
  82. {
  83. m_paused = 0;
  84. m_playing = false;
  85. m_recording = false;
  86. m_bSavedRecordingState = false;
  87. m_timeRange.Set(0, 0);
  88. m_timeMarker.Set(0, 0);
  89. m_currTime = 0.0f;
  90. m_bForceUpdateInNextFrame = false;
  91. m_fTimeScale = 1.0f;
  92. m_pSequence = nullptr;
  93. m_bLooping = false;
  94. m_bSingleFrame = false;
  95. m_bPostRenderRegistered = false;
  96. m_bForcingAnimation = false;
  97. UiAnimUndoManager::Get()->AddListener(this);
  98. CUiAnimViewSequenceManager::GetSequenceManager()->AddListener(this);
  99. GetIEditor()->RegisterNotifyListener(this);
  100. }
  101. //////////////////////////////////////////////////////////////////////////
  102. CUiAnimationContext::~CUiAnimationContext()
  103. {
  104. CUiAnimViewSequenceManager::GetSequenceManager()->RemoveListener(this);
  105. UiAnimUndoManager::Get()->RemoveListener(this);
  106. GetIEditor()->UnregisterNotifyListener(this);
  107. }
  108. //////////////////////////////////////////////////////////////////////////
  109. void CUiAnimationContext::Init()
  110. {
  111. IUiAnimationSystem* pUiAnimationSystem = GetUiAnimationSystem();
  112. pUiAnimationSystem->SetCallback(&s_uiAnimationCallback);
  113. }
  114. //////////////////////////////////////////////////////////////////////////
  115. void CUiAnimationContext::AddListener(IUiAnimationContextListener* pListener)
  116. {
  117. stl::push_back_unique(m_contextListeners, pListener);
  118. }
  119. //////////////////////////////////////////////////////////////////////////
  120. void CUiAnimationContext::RemoveListener(IUiAnimationContextListener* pListener)
  121. {
  122. stl::find_and_erase(m_contextListeners, pListener);
  123. }
  124. //////////////////////////////////////////////////////////////////////////
  125. IUiAnimationSystem* CUiAnimationContext::GetUiAnimationSystem() const
  126. {
  127. IUiAnimationSystem* animationSystem = nullptr;
  128. UiEditorAnimationBus::BroadcastResult(animationSystem, &UiEditorAnimationBus::Events::GetAnimationSystem);
  129. return animationSystem;
  130. }
  131. //////////////////////////////////////////////////////////////////////////
  132. void CUiAnimationContext::ActiveCanvasChanged()
  133. {
  134. m_sequenceName = "";
  135. m_sequenceTime = GetTime();
  136. m_paused = 0;
  137. m_recording = m_bSavedRecordingState = false;
  138. m_playing = false;
  139. SetSequence(nullptr, true, true);
  140. }
  141. //////////////////////////////////////////////////////////////////////////
  142. void CUiAnimationContext::SetSequence(CUiAnimViewSequence* pSequence, bool bForce, bool bNoNotify, bool recordUndo)
  143. {
  144. CUiAnimViewSequence* pCurrentSequence = m_pSequence;
  145. if (!bForce && pSequence == pCurrentSequence)
  146. {
  147. return;
  148. }
  149. if (!GetUiAnimationSystem())
  150. {
  151. // There is no canvas loaded in editor
  152. m_pSequence = pSequence;
  153. if (!bNoNotify)
  154. {
  155. for (size_t i = 0; i < m_contextListeners.size(); ++i)
  156. {
  157. m_contextListeners[i]->OnTimeChanged(0.0f);
  158. m_contextListeners[i]->OnSequenceChanged(m_pSequence);
  159. }
  160. }
  161. return;
  162. }
  163. // Prevent keys being created from time change
  164. const bool bRecording = m_recording;
  165. m_recording = false;
  166. GetUiAnimationSystem()->SetRecording(false);
  167. m_currTime = m_fRecordingCurrTime = 0.0f;
  168. if (m_pSequence)
  169. {
  170. m_pSequence->Deactivate();
  171. if (m_playing)
  172. {
  173. m_pSequence->EndCutScene();
  174. }
  175. m_pSequence->UnBindFromEditorObjects();
  176. }
  177. m_pSequence = pSequence;
  178. if (m_pSequence)
  179. {
  180. if (m_playing)
  181. {
  182. m_pSequence->BeginCutScene(true);
  183. }
  184. m_timeRange = m_pSequence->GetTimeRange();
  185. m_timeMarker = m_timeRange;
  186. m_pSequence->Activate();
  187. m_pSequence->PrecacheData(0.0f);
  188. m_pSequence->BindToEditorObjects();
  189. }
  190. ForceAnimation();
  191. if (!bNoNotify)
  192. {
  193. for (size_t i = 0; i < m_contextListeners.size(); ++i)
  194. {
  195. m_contextListeners[i]->OnTimeChanged(0.0f);
  196. m_contextListeners[i]->OnSequenceChanged(m_pSequence);
  197. }
  198. }
  199. if (recordUndo)
  200. {
  201. // Safely track sequence changes for clean undos
  202. UiAnimUndo undo("Change Sequence");
  203. UiAnimUndo::Record(new CUndoSequenceChange(pCurrentSequence, pSequence));
  204. }
  205. m_recording = bRecording;
  206. GetUiAnimationSystem()->SetRecording(bRecording);
  207. }
  208. //////////////////////////////////////////////////////////////////////////
  209. void CUiAnimationContext::UpdateTimeRange()
  210. {
  211. if (m_pSequence)
  212. {
  213. m_timeRange = m_pSequence->GetTimeRange();
  214. }
  215. }
  216. //////////////////////////////////////////////////////////////////////////
  217. void CUiAnimationContext::SetTime(float t)
  218. {
  219. if (t < m_timeRange.start)
  220. {
  221. t = m_timeRange.start;
  222. }
  223. if (t > m_timeRange.end)
  224. {
  225. t = m_timeRange.end;
  226. }
  227. if (fabs(m_currTime - t) < 0.001f)
  228. {
  229. return;
  230. }
  231. m_currTime = t;
  232. m_fRecordingCurrTime = t;
  233. ForceAnimation();
  234. for (size_t i = 0; i < m_contextListeners.size(); ++i)
  235. {
  236. m_contextListeners[i]->OnTimeChanged(m_currTime);
  237. }
  238. }
  239. //////////////////////////////////////////////////////////////////////////
  240. void CUiAnimationContext::Pause()
  241. {
  242. assert(m_paused >= 0);
  243. m_paused++;
  244. if (m_recording)
  245. {
  246. GetUiAnimationSystem()->SetRecording(false);
  247. }
  248. GetUiAnimationSystem()->Pause();
  249. if (m_pSequence)
  250. {
  251. m_pSequence->Pause();
  252. }
  253. }
  254. //////////////////////////////////////////////////////////////////////////
  255. void CUiAnimationContext::Resume()
  256. {
  257. assert(m_paused > 0);
  258. m_paused--;
  259. if (m_recording && m_paused == 0)
  260. {
  261. GetUiAnimationSystem()->SetRecording(true);
  262. }
  263. GetUiAnimationSystem()->Resume();
  264. if (m_pSequence)
  265. {
  266. m_pSequence->Resume();
  267. }
  268. }
  269. //////////////////////////////////////////////////////////////////////////
  270. void CUiAnimationContext::SetRecording(bool recording)
  271. {
  272. if (recording == m_recording)
  273. {
  274. return;
  275. }
  276. m_paused = 0;
  277. m_recording = recording;
  278. m_playing = false;
  279. GetUiAnimationSystem()->SetRecording(recording);
  280. }
  281. //////////////////////////////////////////////////////////////////////////
  282. //////////////////////////////////////////////////////////////////////////
  283. void CUiAnimationContext::SetPlaying(bool playing)
  284. {
  285. if (playing == m_playing)
  286. {
  287. return;
  288. }
  289. m_paused = 0;
  290. m_playing = playing;
  291. m_recording = false;
  292. GetUiAnimationSystem()->SetRecording(false);
  293. if (playing)
  294. {
  295. IUiAnimationSystem* pUiAnimationSystem = GetUiAnimationSystem();
  296. pUiAnimationSystem->Resume();
  297. if (m_pSequence)
  298. {
  299. m_pSequence->Resume();
  300. }
  301. }
  302. else
  303. {
  304. IUiAnimationSystem* pUiAnimationSystem = GetUiAnimationSystem();
  305. pUiAnimationSystem->Pause();
  306. if (m_pSequence)
  307. {
  308. m_pSequence->Pause();
  309. }
  310. }
  311. }
  312. //////////////////////////////////////////////////////////////////////////
  313. void CUiAnimationContext::Update()
  314. {
  315. if (!GetUiAnimationSystem())
  316. {
  317. return;
  318. }
  319. const float lastTime = m_currTime;
  320. if (m_bForceUpdateInNextFrame)
  321. {
  322. ForceAnimation();
  323. m_bForceUpdateInNextFrame = false;
  324. }
  325. if (m_paused > 0 || !m_playing)
  326. {
  327. if (m_pSequence)
  328. {
  329. m_pSequence->StillUpdate();
  330. }
  331. if (!m_recording)
  332. {
  333. GetUiAnimationSystem()->StillUpdate();
  334. }
  335. return;
  336. }
  337. AnimateActiveSequence();
  338. const float frameDeltaTime = Internal::GetFrameDeltaTime();
  339. m_currTime += frameDeltaTime * m_fTimeScale;
  340. if (!m_recording)
  341. {
  342. GetUiAnimationSystem()->PreUpdate(frameDeltaTime);
  343. GetUiAnimationSystem()->PostUpdate(frameDeltaTime);
  344. }
  345. if (m_currTime > m_timeMarker.end)
  346. {
  347. if (m_bLooping)
  348. {
  349. m_currTime = m_timeMarker.start;
  350. if (m_pSequence)
  351. {
  352. m_pSequence->OnLoop();
  353. }
  354. }
  355. else
  356. {
  357. SetPlaying(false);
  358. m_currTime = m_timeMarker.end;
  359. }
  360. }
  361. if (fabs(lastTime - m_currTime) > 0.001f)
  362. {
  363. for (size_t i = 0; i < m_contextListeners.size(); ++i)
  364. {
  365. m_contextListeners[i]->OnTimeChanged(m_currTime);
  366. }
  367. }
  368. }
  369. //////////////////////////////////////////////////////////////////////////
  370. void CUiAnimationContext::ForceAnimation()
  371. {
  372. if (m_bForcingAnimation)
  373. {
  374. // reentrant calls are possible when using subsequences
  375. return;
  376. }
  377. m_bForcingAnimation = true;
  378. AnimateActiveSequence();
  379. // Animate a second time to properly update camera DoF
  380. AnimateActiveSequence();
  381. m_bForcingAnimation = false;
  382. }
  383. //////////////////////////////////////////////////////////////////////////
  384. void CUiAnimationContext::OnPostRender()
  385. {
  386. if (m_pSequence)
  387. {
  388. SUiAnimContext ac;
  389. ac.dt = 0;
  390. ac.fps = Internal::GetFrameRate();
  391. ac.time = m_currTime;
  392. ac.bSingleFrame = true;
  393. ac.bForcePlay = true;
  394. m_pSequence->Render(ac);
  395. }
  396. }
  397. //////////////////////////////////////////////////////////////////////////
  398. void CUiAnimationContext::BeginUndoTransaction()
  399. {
  400. m_bSavedRecordingState = m_recording;
  401. IUiAnimationSystem* uiAnimationSystem = GetUiAnimationSystem();
  402. if (uiAnimationSystem)
  403. {
  404. uiAnimationSystem->SetRecording(false);
  405. }
  406. }
  407. //////////////////////////////////////////////////////////////////////////
  408. void CUiAnimationContext::EndUndoTransaction()
  409. {
  410. if (m_pSequence)
  411. {
  412. m_pSequence->BindToEditorObjects();
  413. }
  414. IUiAnimationSystem* uiAnimationSystem = GetUiAnimationSystem();
  415. if (uiAnimationSystem)
  416. {
  417. uiAnimationSystem->SetRecording(m_bSavedRecordingState);
  418. }
  419. }
  420. //////////////////////////////////////////////////////////////////////////
  421. void CUiAnimationContext::TogglePlay()
  422. {
  423. if (!IsPlaying())
  424. {
  425. SetPlaying(true);
  426. }
  427. else
  428. {
  429. SetPlaying(false);
  430. }
  431. }
  432. //////////////////////////////////////////////////////////////////////////
  433. void CUiAnimationContext::OnSequenceRemoved(CUiAnimViewSequence* pSequence)
  434. {
  435. if (m_pSequence == pSequence)
  436. {
  437. SetSequence(nullptr, true, false);
  438. }
  439. }
  440. //////////////////////////////////////////////////////////////////////////
  441. void CUiAnimationContext::OnEditorNotifyEvent(EEditorNotifyEvent event)
  442. {
  443. // If the UI Animation window is open but there is no canvas loaded in editor
  444. // then just return.
  445. if (!GetUiAnimationSystem())
  446. {
  447. return;
  448. }
  449. switch (event)
  450. {
  451. case eNotify_OnBeginGameMode:
  452. if (m_pSequence)
  453. {
  454. m_pSequence->Resume();
  455. }
  456. case eNotify_OnBeginSceneSave:
  457. case eNotify_OnBeginLayerExport:
  458. if (m_pSequence)
  459. {
  460. m_sequenceName = QString::fromUtf8(m_pSequence->GetName().c_str());
  461. }
  462. else
  463. {
  464. m_sequenceName = "";
  465. }
  466. m_sequenceTime = GetTime();
  467. m_bSavedRecordingState = m_recording;
  468. GetUiAnimationSystem()->SetRecording(false);
  469. SetSequence(nullptr, true, true);
  470. break;
  471. case eNotify_OnEndGameMode:
  472. case eNotify_OnEndSceneSave:
  473. case eNotify_OnEndLayerExport:
  474. m_currTime = m_sequenceTime;
  475. SetSequence(CUiAnimViewSequenceManager::GetSequenceManager()->GetSequenceByName(m_sequenceName), true, true);
  476. SetTime(m_sequenceTime);
  477. GetUiAnimationSystem()->SetRecording(m_bSavedRecordingState);
  478. break;
  479. case eNotify_OnCloseScene:
  480. SetSequence(nullptr, true, false);
  481. break;
  482. case eNotify_OnBeginNewScene:
  483. SetSequence(nullptr, false, false);
  484. break;
  485. case eNotify_OnBeginLoad:
  486. {
  487. m_bSavedRecordingState = m_recording;
  488. GetUiAnimationSystem()->SetRecording(false);
  489. CUiAnimationContext* ac = nullptr;
  490. UiEditorAnimationBus::BroadcastResult(ac, &UiEditorAnimationBus::Events::GetAnimationContext);
  491. ac->SetSequence(nullptr, false, false);
  492. break;
  493. }
  494. case eNotify_OnEndLoad:
  495. GetUiAnimationSystem()->SetRecording(m_bSavedRecordingState);
  496. break;
  497. case eNotify_CameraChanged:
  498. ForceAnimation();
  499. break;
  500. case eNotify_OnIdleUpdate:
  501. Update();
  502. break;
  503. }
  504. }
  505. void CUiAnimationContext::AnimateActiveSequence()
  506. {
  507. if (!m_pSequence)
  508. {
  509. return;
  510. }
  511. SUiAnimContext ac;
  512. ac.dt = 0;
  513. ac.fps = Internal::GetFrameRate();
  514. ac.time = m_currTime;
  515. ac.bSingleFrame = true;
  516. ac.bForcePlay = true;
  517. m_pSequence->Animate(ac);
  518. }