3
0

MotionEventTrackTests.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  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 "SystemComponentFixture.h"
  9. #include "TestAssetCode/MotionEvent.h"
  10. #include <EMotionFX/Source/EventManager.h>
  11. #include <EMotionFX/Source/EventHandler.h>
  12. #include <EMotionFX/Source/MotionEventTable.h>
  13. #include <EMotionFX/Source/MotionEventTrack.h>
  14. #include <EMotionFX/Source/MotionManager.h>
  15. #include <EMotionFX/Source/Motion.h>
  16. #include <EMotionFX/Source/MotionData/NonUniformMotionData.h>
  17. #include <EMotionFX/Source/Node.h>
  18. #include <EMotionFX/Source/TwoStringEventData.h>
  19. #include <Integration/System/SystemCommon.h>
  20. #include <Tests/TestAssetCode/SimpleActors.h>
  21. #include <Tests/TestAssetCode/ActorFactory.h>
  22. #include <AzCore/std/algorithm.h>
  23. namespace EMotionFX
  24. {
  25. struct ExtractEventsParams
  26. {
  27. void (*m_eventFactory)(MotionEventTrack* track);
  28. float m_startTime;
  29. float m_endTime;
  30. EPlayMode m_playMode;
  31. std::vector<EventInfo> m_expectedEvents;
  32. };
  33. void PrintTo(const EMotionFX::EventInfo::EventState& state, ::std::ostream* os)
  34. {
  35. if (state == EMotionFX::EventInfo::EventState::START)
  36. {
  37. *os << "EMotionFX::EventInfo::EventState::START";
  38. }
  39. else if (state == EMotionFX::EventInfo::EventState::ACTIVE)
  40. {
  41. *os << "EMotionFX::EventInfo::EventState::ACTIVE";
  42. }
  43. else if (state == EMotionFX::EventInfo::EventState::END)
  44. {
  45. *os << "EMotionFX::EventInfo::EventState::END";
  46. }
  47. }
  48. void PrintTo(const EMotionFX::EventInfo& event, ::std::ostream* os)
  49. {
  50. *os << "Time: " << event.m_timeValue
  51. << " State: "
  52. ;
  53. PrintTo(event.m_eventState, os);
  54. }
  55. void PrintTo(const ExtractEventsParams& object, ::std::ostream* os)
  56. {
  57. if (object.m_eventFactory == &MakeNoEvents)
  58. {
  59. *os << "Events: 0";
  60. }
  61. else if (object.m_eventFactory == &MakeOneEvent)
  62. {
  63. *os << "Events: 1";
  64. }
  65. else if (object.m_eventFactory == &MakeTwoEvents)
  66. {
  67. *os << "Events: 2";
  68. }
  69. else if (object.m_eventFactory == &MakeThreeEvents)
  70. {
  71. *os << "Events: 3";
  72. }
  73. else if (object.m_eventFactory == &MakeThreeRangedEvents)
  74. {
  75. *os << "Events: 3 (ranged)";
  76. }
  77. else
  78. {
  79. *os << "Events: Unknown";
  80. }
  81. *os << " Start time: " << object.m_startTime
  82. << " End time: " << object.m_endTime
  83. << " Play mode: " << ((object.m_playMode == EPlayMode::PLAYMODE_FORWARD) ? "Forward" : "Backward")
  84. << " Expected events: ["
  85. ;
  86. for (const auto& entry : object.m_expectedEvents)
  87. {
  88. PrintTo(entry, os);
  89. if (&entry != &(*(object.m_expectedEvents.end() - 1)))
  90. {
  91. *os << ", ";
  92. }
  93. }
  94. *os << ']';
  95. }
  96. // This fixture is used for both MotionEventTrack::ProcessEvents and
  97. // MotionEventTrack::ExtractEvents. Both calls should have similar results,
  98. // with the exception that ProcessEvents filters out events whose state is
  99. // ACTIVE.
  100. class TestExtractProcessEventsFixture
  101. : public SystemComponentFixture
  102. , public ::testing::WithParamInterface<ExtractEventsParams>
  103. {
  104. // This event handler exists to capture events and put them in a
  105. // AnimGraphEventBuffer, so that the ExtractEvents and ProcessEvents
  106. // tests can test the results in a similar fashion
  107. class TestProcessEventsEventHandler
  108. : public EMotionFX::EventHandler
  109. {
  110. public:
  111. AZ_CLASS_ALLOCATOR(TestProcessEventsEventHandler, Integration::EMotionFXAllocator);
  112. TestProcessEventsEventHandler(AnimGraphEventBuffer* buffer)
  113. : m_buffer(buffer)
  114. {
  115. }
  116. const AZStd::vector<EventTypes> GetHandledEventTypes() const override
  117. {
  118. return { EVENT_TYPE_ON_EVENT };
  119. }
  120. void OnEvent(const EMotionFX::EventInfo& emfxInfo) override
  121. {
  122. m_buffer->AddEvent(emfxInfo);
  123. }
  124. private:
  125. AnimGraphEventBuffer* m_buffer;
  126. };
  127. public:
  128. void SetUp() override
  129. {
  130. SystemComponentFixture::SetUp();
  131. m_motion = aznew Motion("TestExtractEventsMotion");
  132. m_motion->SetMotionData(aznew NonUniformMotionData());
  133. m_motion->GetMotionData()->SetDuration(2.0f);
  134. m_motion->GetEventTable()->AutoCreateSyncTrack(m_motion);
  135. m_track = m_motion->GetEventTable()->GetSyncTrack();
  136. GetParam().m_eventFactory(m_track);
  137. m_actor = ActorFactory::CreateAndInit<SimpleJointChainActor>(5);
  138. m_actorInstance = ActorInstance::Create(m_actor.get());
  139. m_motionInstance = MotionInstance::Create(m_motion, m_actorInstance);
  140. m_buffer = new AnimGraphEventBuffer();
  141. m_eventHandler = aznew TestProcessEventsEventHandler(m_buffer);
  142. GetEMotionFX().GetEventManager()->AddEventHandler(m_eventHandler);
  143. }
  144. void TearDown() override
  145. {
  146. GetEMotionFX().GetEventManager()->RemoveEventHandler(m_eventHandler);
  147. delete m_buffer;
  148. delete m_eventHandler;
  149. m_motionInstance->Destroy();
  150. m_motion->Destroy();
  151. m_actorInstance->Destroy();
  152. m_actor.reset();
  153. SystemComponentFixture::TearDown();
  154. }
  155. void TestEvents(AZStd::function<void(float, float, EPlayMode playMode, MotionInstance*)> func)
  156. {
  157. const ExtractEventsParams& params = GetParam();
  158. // Call the function being tested
  159. func(params.m_startTime, params.m_endTime, params.m_playMode, m_motionInstance);
  160. // ProcessEvents filters out the ACTIVE events, remove those from our expected results
  161. AZStd::vector<EventInfo> expectedEvents;
  162. for (const EventInfo& event : params.m_expectedEvents)
  163. {
  164. if (event.m_eventState != EventInfo::ACTIVE || m_shouldContainActiveEvents)
  165. {
  166. expectedEvents.emplace_back(event);
  167. }
  168. }
  169. EXPECT_EQ(m_buffer->GetNumEvents(), expectedEvents.size()) << "Number of events is incorrect";
  170. for (size_t i = 0; i < AZStd::min(m_buffer->GetNumEvents(), expectedEvents.size()); ++i)
  171. {
  172. const EventInfo& gotEvent = m_buffer->GetEvent(i);
  173. const EventInfo& expectedEvent = expectedEvents[i];
  174. EXPECT_EQ(gotEvent.m_timeValue, expectedEvent.m_timeValue);
  175. EXPECT_EQ(gotEvent.m_eventState, expectedEvent.m_eventState);
  176. }
  177. }
  178. protected:
  179. AnimGraphEventBuffer* m_buffer = nullptr;
  180. Motion* m_motion = nullptr;
  181. MotionInstance* m_motionInstance = nullptr;
  182. MotionEventTrack* m_track = nullptr;
  183. AZStd::unique_ptr<Actor> m_actor{};
  184. ActorInstance* m_actorInstance = nullptr;
  185. TestProcessEventsEventHandler* m_eventHandler = nullptr;
  186. // ProcessEvents filters out ACTIVE events. For the ProcessEvents
  187. // tests, this will be set to false.
  188. bool m_shouldContainActiveEvents;
  189. };
  190. TEST_P(TestExtractProcessEventsFixture, TestExtractEvents)
  191. {
  192. m_shouldContainActiveEvents = true;
  193. TestEvents([this](float startTime, float endTime, EPlayMode playMode, MotionInstance* motionInstance)
  194. {
  195. motionInstance->SetPlayMode(playMode);
  196. return this->m_track->ExtractEvents(startTime, endTime, motionInstance, m_buffer);
  197. });
  198. }
  199. TEST_P(TestExtractProcessEventsFixture, TestProcessEvents)
  200. {
  201. m_shouldContainActiveEvents = false;
  202. TestEvents([this](float startTime, float endTime, EPlayMode playMode, MotionInstance* motionInstance)
  203. {
  204. motionInstance->SetPlayMode(playMode);
  205. return this->m_track->ProcessEvents(startTime, endTime, motionInstance);
  206. });
  207. }
  208. std::vector<ExtractEventsParams> extractEventTestData {
  209. {
  210. MakeThreeEvents,
  211. 0.0f,
  212. 1.0f,
  213. EPlayMode::PLAYMODE_FORWARD,
  214. std::vector<EventInfo> {
  215. EventInfo {
  216. 0.25f,
  217. nullptr, nullptr, nullptr,
  218. EMotionFX::EventInfo::EventState::START
  219. },
  220. EventInfo {
  221. 0.75f,
  222. nullptr, nullptr, nullptr,
  223. EMotionFX::EventInfo::EventState::START
  224. }
  225. }
  226. },
  227. {
  228. MakeThreeEvents,
  229. 0.0f,
  230. 1.5f,
  231. EPlayMode::PLAYMODE_FORWARD,
  232. std::vector<EventInfo> {
  233. EventInfo {
  234. 0.25f,
  235. nullptr, nullptr, nullptr,
  236. EMotionFX::EventInfo::EventState::START
  237. },
  238. EventInfo {
  239. 0.75f,
  240. nullptr, nullptr, nullptr,
  241. EMotionFX::EventInfo::EventState::START
  242. },
  243. EventInfo {
  244. 1.25f,
  245. nullptr, nullptr, nullptr,
  246. EMotionFX::EventInfo::EventState::START
  247. }
  248. }
  249. },
  250. {
  251. // Processing from before a ranged event begins to the middle of
  252. // that event should give a start event and an active event
  253. MakeThreeRangedEvents,
  254. 0.0f,
  255. 0.3f,
  256. EPlayMode::PLAYMODE_FORWARD,
  257. std::vector<EventInfo> {
  258. EventInfo {
  259. 0.25f,
  260. nullptr, nullptr, nullptr,
  261. EMotionFX::EventInfo::EventState::START
  262. }
  263. }
  264. },
  265. {
  266. // Processing from before a ranged event begins to after the end of
  267. // that event should give a start event and an end event
  268. MakeThreeRangedEvents,
  269. 0.0f,
  270. 0.6f,
  271. EPlayMode::PLAYMODE_FORWARD,
  272. std::vector<EventInfo> {
  273. EventInfo {
  274. 0.25f,
  275. nullptr, nullptr, nullptr,
  276. EMotionFX::EventInfo::EventState::START
  277. },
  278. EventInfo {
  279. 0.5f,
  280. nullptr, nullptr, nullptr,
  281. EMotionFX::EventInfo::EventState::END
  282. }
  283. }
  284. },
  285. {
  286. // Processing from the middle of a ranged event to after the end of
  287. // that event should give just an end event
  288. MakeThreeRangedEvents,
  289. 0.3f,
  290. 0.6f,
  291. EPlayMode::PLAYMODE_FORWARD,
  292. std::vector<EventInfo> {
  293. EventInfo {
  294. 0.5f,
  295. nullptr, nullptr, nullptr,
  296. EMotionFX::EventInfo::EventState::END
  297. }
  298. }
  299. },
  300. {
  301. // Each ranged event processed whose start time is traversed
  302. // generates 2 event infos
  303. MakeThreeRangedEvents,
  304. 0.0f,
  305. 0.9f,
  306. EPlayMode::PLAYMODE_FORWARD,
  307. std::vector<EventInfo> {
  308. EventInfo {
  309. 0.25f,
  310. nullptr, nullptr, nullptr,
  311. EMotionFX::EventInfo::EventState::START
  312. },
  313. EventInfo {
  314. 0.5f,
  315. nullptr, nullptr, nullptr,
  316. EMotionFX::EventInfo::EventState::END
  317. },
  318. EventInfo {
  319. 0.75f,
  320. nullptr, nullptr, nullptr,
  321. EMotionFX::EventInfo::EventState::START
  322. }
  323. }
  324. },
  325. // Now the backwards playback cases
  326. {
  327. MakeThreeEvents,
  328. 1.0f,
  329. 0.0f,
  330. EPlayMode::PLAYMODE_BACKWARD,
  331. std::vector<EventInfo> {
  332. EventInfo {
  333. 0.75f,
  334. nullptr, nullptr, nullptr,
  335. EMotionFX::EventInfo::EventState::START
  336. },
  337. EventInfo {
  338. 0.25f,
  339. nullptr, nullptr, nullptr,
  340. EMotionFX::EventInfo::EventState::START
  341. }
  342. }
  343. },
  344. {
  345. MakeThreeEvents,
  346. 1.5f,
  347. 0.0f,
  348. EPlayMode::PLAYMODE_BACKWARD,
  349. std::vector<EventInfo> {
  350. EventInfo {
  351. 1.25f,
  352. nullptr, nullptr, nullptr,
  353. EMotionFX::EventInfo::EventState::START
  354. },
  355. EventInfo {
  356. 0.75f,
  357. nullptr, nullptr, nullptr,
  358. EMotionFX::EventInfo::EventState::START
  359. },
  360. EventInfo {
  361. 0.25f,
  362. nullptr, nullptr, nullptr,
  363. EMotionFX::EventInfo::EventState::START
  364. }
  365. }
  366. },
  367. {
  368. // Processing from the middle of a ranged event to before that
  369. // event begins should give an end event
  370. MakeThreeRangedEvents,
  371. 0.3f,
  372. 0.0f,
  373. EPlayMode::PLAYMODE_BACKWARD,
  374. std::vector<EventInfo> {
  375. EventInfo {
  376. 0.25f,
  377. nullptr, nullptr, nullptr,
  378. EMotionFX::EventInfo::EventState::END
  379. }
  380. }
  381. },
  382. {
  383. // Processing from after a ranged event ends to before the
  384. // beginning of that event should give a start event and an end
  385. // event
  386. MakeThreeRangedEvents,
  387. 0.6f,
  388. 0.0f,
  389. EPlayMode::PLAYMODE_BACKWARD,
  390. std::vector<EventInfo> {
  391. EventInfo {
  392. 0.5f,
  393. nullptr, nullptr, nullptr,
  394. EMotionFX::EventInfo::EventState::START
  395. },
  396. EventInfo {
  397. 0.25f,
  398. nullptr, nullptr, nullptr,
  399. EMotionFX::EventInfo::EventState::END
  400. }
  401. }
  402. },
  403. {
  404. // Processing from after the end of an event to the middle of a
  405. // ranged event should give a start event and an active event
  406. MakeThreeRangedEvents,
  407. 0.6f,
  408. 0.3f,
  409. EPlayMode::PLAYMODE_BACKWARD,
  410. std::vector<EventInfo> {
  411. EventInfo {
  412. 0.5f,
  413. nullptr, nullptr, nullptr,
  414. EMotionFX::EventInfo::EventState::START
  415. }
  416. }
  417. },
  418. {
  419. // Start in the middle of a ranged event while playing backwards
  420. MakeThreeRangedEvents,
  421. 0.9f,
  422. 0.0f,
  423. EPlayMode::PLAYMODE_BACKWARD,
  424. std::vector<EventInfo> {
  425. EventInfo {
  426. 0.75f,
  427. nullptr, nullptr, nullptr,
  428. EMotionFX::EventInfo::EventState::END
  429. },
  430. EventInfo {
  431. 0.5f,
  432. nullptr, nullptr, nullptr,
  433. EMotionFX::EventInfo::EventState::START
  434. },
  435. EventInfo {
  436. 0.25f,
  437. nullptr, nullptr, nullptr,
  438. EMotionFX::EventInfo::EventState::END
  439. }
  440. }
  441. },
  442. {
  443. // Loop, but in a way where no events should be triggered.
  444. MakeTwoEvents,
  445. 1.9f,
  446. 0.1f,
  447. EPlayMode::PLAYMODE_FORWARD,
  448. {
  449. }
  450. },
  451. {
  452. // Loop, but in a way where no events should be triggered, but play backward.
  453. MakeTwoEvents,
  454. 0.1f,
  455. 1.9f,
  456. EPlayMode::PLAYMODE_BACKWARD,
  457. {
  458. }
  459. },
  460. {
  461. // Loop, forward, and overlap one event.
  462. MakeTwoEvents,
  463. 1.9f,
  464. 0.5f,
  465. EPlayMode::PLAYMODE_FORWARD,
  466. std::vector<EventInfo> {
  467. EventInfo {
  468. 0.25f,
  469. nullptr, nullptr, nullptr,
  470. EMotionFX::EventInfo::EventState::START
  471. }
  472. }
  473. },
  474. {
  475. // Loop, backwards, and overlap one event.
  476. MakeTwoEvents,
  477. 0.5f,
  478. 1.9f,
  479. EPlayMode::PLAYMODE_BACKWARD,
  480. std::vector<EventInfo> {
  481. EventInfo {
  482. 0.25f,
  483. nullptr, nullptr, nullptr,
  484. EMotionFX::EventInfo::EventState::START
  485. }
  486. }
  487. },
  488. {
  489. // Loop, forward, and overlap two events.
  490. MakeTwoEvents,
  491. 1.9f,
  492. 1.0f,
  493. EPlayMode::PLAYMODE_FORWARD,
  494. std::vector<EventInfo> {
  495. EventInfo {
  496. 0.25f,
  497. nullptr, nullptr, nullptr,
  498. EMotionFX::EventInfo::EventState::START
  499. },
  500. EventInfo {
  501. 0.75f,
  502. nullptr, nullptr, nullptr,
  503. EMotionFX::EventInfo::EventState::START
  504. }
  505. }
  506. },
  507. {
  508. // Loop, backwards, and overlap two events.
  509. MakeTwoEvents,
  510. 1.0f,
  511. 1.9f,
  512. EPlayMode::PLAYMODE_BACKWARD,
  513. std::vector<EventInfo> {
  514. EventInfo {
  515. 0.75f,
  516. nullptr, nullptr, nullptr,
  517. EMotionFX::EventInfo::EventState::START
  518. },
  519. EventInfo {
  520. 0.25f,
  521. nullptr, nullptr, nullptr,
  522. EMotionFX::EventInfo::EventState::START
  523. }
  524. }
  525. },
  526. {
  527. // Start exactly at a given motion event's time value.
  528. MakeTwoEvents,
  529. 0.25f,
  530. 0.3f,
  531. EPlayMode::PLAYMODE_FORWARD,
  532. std::vector<EventInfo> {
  533. EventInfo {
  534. 0.25f,
  535. nullptr, nullptr, nullptr,
  536. EMotionFX::EventInfo::EventState::START
  537. }
  538. }
  539. },
  540. {
  541. // End exactly at a given motion event's time value.
  542. MakeTwoEvents,
  543. 0.0f,
  544. 0.25f,
  545. EPlayMode::PLAYMODE_FORWARD,
  546. {
  547. }
  548. },
  549. {
  550. // Double check both cases at the same time.
  551. MakeTwoEvents,
  552. 0.25f,
  553. 0.75f,
  554. EPlayMode::PLAYMODE_FORWARD,
  555. std::vector<EventInfo> {
  556. EventInfo {
  557. 0.25f,
  558. nullptr, nullptr, nullptr,
  559. EMotionFX::EventInfo::EventState::START
  560. }
  561. }
  562. },
  563. {
  564. // Start exactly at a given motion event's time value.
  565. // Playing backward.
  566. MakeTwoEvents,
  567. 0.25f,
  568. 0.0f,
  569. EPlayMode::PLAYMODE_BACKWARD,
  570. std::vector<EventInfo> {
  571. EventInfo {
  572. 0.25f,
  573. nullptr, nullptr, nullptr,
  574. EMotionFX::EventInfo::EventState::START
  575. }
  576. }
  577. },
  578. {
  579. // End exactly at a given motion event's time value.
  580. // Playing backward.
  581. MakeTwoEvents,
  582. 0.5f,
  583. 0.25f,
  584. EPlayMode::PLAYMODE_BACKWARD,
  585. {
  586. }
  587. },
  588. {
  589. // Double check both cases at the same time.
  590. // Playing backward.
  591. MakeTwoEvents,
  592. 0.75f,
  593. 0.25f,
  594. EPlayMode::PLAYMODE_BACKWARD,
  595. std::vector<EventInfo> {
  596. EventInfo {
  597. 0.75f,
  598. nullptr, nullptr, nullptr,
  599. EMotionFX::EventInfo::EventState::START
  600. }
  601. }
  602. },
  603. {
  604. // Start exactly at a given motion event's time value.
  605. MakeOneRangedEvent,
  606. 0.25f,
  607. 0.75f,
  608. EPlayMode::PLAYMODE_FORWARD,
  609. std::vector<EventInfo> {
  610. EventInfo {
  611. 0.25f,
  612. nullptr, nullptr, nullptr,
  613. EMotionFX::EventInfo::EventState::START
  614. }
  615. }
  616. },
  617. {
  618. // End exactly at a given motion event's time value.
  619. MakeOneRangedEvent,
  620. 0.0f,
  621. 0.25f,
  622. EPlayMode::PLAYMODE_FORWARD,
  623. {
  624. }
  625. },
  626. {
  627. // Double check both cases at the same time.
  628. MakeOneRangedEvent,
  629. 0.25f,
  630. 0.75f,
  631. EPlayMode::PLAYMODE_FORWARD,
  632. std::vector<EventInfo> {
  633. EventInfo {
  634. 0.25f,
  635. nullptr, nullptr, nullptr,
  636. EMotionFX::EventInfo::EventState::START
  637. }
  638. }
  639. },
  640. {
  641. // Start exactly at a given motion event's time value.
  642. // Playing backward.
  643. MakeOneRangedEvent,
  644. 0.25f,
  645. 0.0f,
  646. EPlayMode::PLAYMODE_BACKWARD,
  647. std::vector<EventInfo> {
  648. EventInfo {
  649. 0.25f,
  650. nullptr, nullptr, nullptr,
  651. EMotionFX::EventInfo::EventState::END // Originally the start, but in backward it turns into end.
  652. }
  653. }
  654. },
  655. {
  656. // End exactly at a given motion event's time value.
  657. // Playing backward.
  658. MakeOneRangedEvent,
  659. 0.5f,
  660. 0.25f,
  661. EPlayMode::PLAYMODE_BACKWARD,
  662. std::vector<EventInfo> {
  663. EventInfo {
  664. 0.25f,
  665. nullptr, nullptr, nullptr,
  666. EMotionFX::EventInfo::EventState::ACTIVE
  667. }
  668. },
  669. },
  670. {
  671. // Double check both cases at the same time.
  672. // Playing backward.
  673. MakeOneRangedEvent,
  674. 0.75f,
  675. 0.25f,
  676. EPlayMode::PLAYMODE_BACKWARD,
  677. std::vector<EventInfo> {
  678. EventInfo {
  679. 0.75f,
  680. nullptr, nullptr, nullptr,
  681. EMotionFX::EventInfo::EventState::START // End became start in backward playback.
  682. }
  683. }
  684. },
  685. {
  686. // Process the full motion in one go.
  687. MakeOneRangedEvent,
  688. 0.0f,
  689. 2.0f,
  690. EPlayMode::PLAYMODE_FORWARD,
  691. std::vector<EventInfo> {
  692. EventInfo {
  693. 0.25f,
  694. nullptr, nullptr, nullptr,
  695. EMotionFX::EventInfo::EventState::START
  696. },
  697. EventInfo {
  698. 0.75f,
  699. nullptr, nullptr, nullptr,
  700. EMotionFX::EventInfo::EventState::END
  701. }
  702. }
  703. },
  704. {
  705. // Reverse it, processin the whole motion.
  706. MakeOneRangedEvent,
  707. 2.0f,
  708. 0.0f,
  709. EPlayMode::PLAYMODE_BACKWARD,
  710. std::vector<EventInfo> {
  711. EventInfo {
  712. 0.75f,
  713. nullptr, nullptr, nullptr,
  714. EMotionFX::EventInfo::EventState::START // Event end became start, because of backward playback.
  715. },
  716. EventInfo {
  717. 0.25f,
  718. nullptr, nullptr, nullptr,
  719. EMotionFX::EventInfo::EventState::END // Start became end, because of backward playback.
  720. }
  721. }
  722. },
  723. {
  724. // Use a time delta that is 5x as large as the motion.
  725. // NOTE: wrapping isn't supported at this time, so we expect it to just act like all events will be emitted once.
  726. MakeOneRangedEvent,
  727. 0.0f,
  728. 10.0f,
  729. EPlayMode::PLAYMODE_FORWARD,
  730. std::vector<EventInfo> {
  731. EventInfo {
  732. 0.25f,
  733. nullptr, nullptr, nullptr,
  734. EMotionFX::EventInfo::EventState::START
  735. },
  736. EventInfo {
  737. 0.75f,
  738. nullptr, nullptr, nullptr,
  739. EMotionFX::EventInfo::EventState::END
  740. }
  741. }
  742. },
  743. {
  744. // Use some negative time delta, fitting the motion 5x, in reverse.
  745. // NOTE: wrapping isn't supported at this time, so we expect it to just act like all events will be emitted once.
  746. MakeOneRangedEvent,
  747. 2.0f,
  748. -10.0f,
  749. EPlayMode::PLAYMODE_BACKWARD,
  750. std::vector<EventInfo> {
  751. EventInfo {
  752. 0.75f,
  753. nullptr, nullptr, nullptr,
  754. EMotionFX::EventInfo::EventState::START // Event end became start, because of backward playback.
  755. },
  756. EventInfo {
  757. 0.25f,
  758. nullptr, nullptr, nullptr,
  759. EMotionFX::EventInfo::EventState::END // Start became end, because of backward playback.
  760. }
  761. }
  762. },
  763. {
  764. // Play longer than the motion duration and if wrapping is supported, end up half way in the range event.
  765. // NOTE: wrapping isn't supported at this time, so we expect it to just act like all events will be emitted once.
  766. MakeOneRangedEvent,
  767. 0.0f,
  768. 2.5f,
  769. EPlayMode::PLAYMODE_FORWARD,
  770. std::vector<EventInfo> {
  771. EventInfo {
  772. 0.25f,
  773. nullptr, nullptr, nullptr,
  774. EMotionFX::EventInfo::EventState::START
  775. },
  776. EventInfo {
  777. 0.75f,
  778. nullptr, nullptr, nullptr,
  779. EMotionFX::EventInfo::EventState::END
  780. }
  781. }
  782. },
  783. {
  784. // Use some negative time delta, fitting the motion 5x, in reverse.
  785. // NOTE: wrapping isn't supported at this time, so we expect it to just act like all events will be emitted once.
  786. MakeOneRangedEvent,
  787. 2.0f,
  788. -1.5f,
  789. EPlayMode::PLAYMODE_BACKWARD,
  790. std::vector<EventInfo> {
  791. EventInfo {
  792. 0.75f,
  793. nullptr, nullptr, nullptr,
  794. EMotionFX::EventInfo::EventState::START // Event end became start, because of backward playback.
  795. },
  796. EventInfo {
  797. 0.25f,
  798. nullptr, nullptr, nullptr,
  799. EMotionFX::EventInfo::EventState::END // Start became end, because of backward playback.
  800. }
  801. }
  802. },
  803. {
  804. // Play longer than the motion duration and if wrapping is supported, end up half way in the range event.
  805. // NOTE: wrapping isn't supported at this time, so we expect it to just act like all events will be emitted once.
  806. MakeOneRangedEvent,
  807. 0.5f,
  808. 2.5f,
  809. EPlayMode::PLAYMODE_FORWARD,
  810. std::vector<EventInfo> {
  811. EventInfo {
  812. 0.75f,
  813. nullptr, nullptr, nullptr,
  814. EMotionFX::EventInfo::EventState::END
  815. }
  816. }
  817. },
  818. {
  819. // Use some negative time delta, fitting the motion 5x, in reverse.
  820. // NOTE: wrapping isn't supported at this time, so we expect it to just act like all events will be emitted once.
  821. MakeOneRangedEvent,
  822. 0.5f,
  823. -1.5f,
  824. EPlayMode::PLAYMODE_BACKWARD,
  825. std::vector<EventInfo> {
  826. EventInfo {
  827. 0.25f,
  828. nullptr, nullptr, nullptr,
  829. EMotionFX::EventInfo::EventState::END // Start became end, because of backward playback.
  830. }
  831. }
  832. },
  833. { // When we start out of the range of the motion, while playing forward, and we suddenly go to somewhere inside the play time of the motion, we basically go from time 0 to the current play position.
  834. MakeOneEvent,
  835. 3.0f,
  836. 0.5f,
  837. EPlayMode::PLAYMODE_FORWARD,
  838. std::vector<EventInfo> {
  839. EventInfo {
  840. 0.25f,
  841. nullptr, nullptr, nullptr,
  842. EMotionFX::EventInfo::EventState::START
  843. }
  844. }
  845. },
  846. { // When we start out of the range of the motion, while playing backward, and we suddenly go to somewhere inside the play time of the motion. We will trigger events between the end of the motion and 0.5 seconds, which is nothing.
  847. MakeOneEvent,
  848. -1.0f,
  849. 0.5f,
  850. EPlayMode::PLAYMODE_BACKWARD,
  851. std::vector<EventInfo>
  852. {
  853. }
  854. }
  855. };
  856. INSTANTIATE_TEST_CASE_P(TestExtractProcessEvents, TestExtractProcessEventsFixture,
  857. ::testing::ValuesIn(extractEventTestData));
  858. } // end namespace EMotionFX