123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128 |
- /*
- * 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/Component/ComponentApplication.h>
- #include <AzCore/Math/MathUtils.h>
- #include <AzCore/Math/Matrix3x3.h>
- #include <AzCore/Math/Random.h>
- #include <AzCore/Serialization/Utils.h>
- #include <AzCore/UnitTest/TestTypes.h>
- #include <AzCore/UserSettings/UserSettingsComponent.h>
- #include <AzFramework/Application/Application.h>
- #include <AzFramework/Components/TransformComponent.h>
- #include <AzToolsFramework/Application/ToolsApplication.h>
- #include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
- #include <AzToolsFramework/ToolsComponents/TransformComponent.h>
- #include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
- #include <Prefab/PrefabTestFixture.h>
- #include <AZTestShared/Math/MathTestHelpers.h>
- using namespace AZ;
- using namespace AzFramework;
- namespace UnitTest
- {
- // Fixture base class for AzFramework::TransformComponent tests.
- class TransformComponentApplication
- : public LeakDetectionFixture
- {
- protected:
- void SetUp() override
- {
- LeakDetectionFixture::SetUp();
- ComponentApplication::Descriptor desc;
- desc.m_useExistingAllocator = true;
- AZ::ComponentApplication::StartupParameters startupParameters;
- startupParameters.m_loadSettingsRegistry = false;
- m_app.Start(desc, startupParameters);
- // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
- // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
- // in the unit tests.
- AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
- }
- void TearDown() override
- {
- m_app.Stop();
- LeakDetectionFixture::TearDown();
- }
- AzFramework::Application m_app;
- };
- // Runs a series of tests on TransformComponent.
- class TransformComponentUberTest
- : public TransformComponentApplication
- , public TransformNotificationBus::Handler
- {
- public:
- //////////////////////////////////////////////////////////////////////////////
- // TransformNotificationBus
- void OnTransformChanged(const Transform& local, const Transform& world) override
- {
- AZ_TEST_ASSERT(m_checkWorldTM == world);
- AZ_TEST_ASSERT(m_checkLocalTM == local);
- }
- /// Called when the parent of an entity has changed. When the old/new parent are invalid the !EntityId.IsValid
- void OnParentChanged(EntityId oldParent, EntityId newParent) override
- {
- AZ_TEST_ASSERT(m_checkOldParentId == oldParent);
- AZ_TEST_ASSERT(m_checkNewParentId == newParent);
- }
- //////////////////////////////////////////////////////////////////////////////
- void run()
- {
- m_checkWorldTM = Transform::CreateIdentity();
- m_checkLocalTM = Transform::CreateIdentity();
- // Create test entity
- Entity childEntity, parentEntity;
- TransformComponent* childTransformComponent = childEntity.CreateComponent<TransformComponent>();
- TransformComponent* parentTranformComponent = parentEntity.CreateComponent<TransformComponent>();
- (void)parentTranformComponent;
- TransformNotificationBus::Handler::BusConnect(childEntity.GetId());
- childEntity.Init();
- parentEntity.Init();
- // We bind transform interface only when entity is activated
- AZ_TEST_ASSERT(childEntity.GetTransform() == nullptr);
- childEntity.Activate();
- TransformInterface* childTransform = childEntity.GetTransform();
- parentEntity.Activate();
- TransformInterface* parentTransform = parentEntity.GetTransform();
- parentTransform->SetWorldTM(Transform::CreateTranslation(Vector3(1.0f, 0.0f, 0.0f)));
- // Check validity of transform interface and initial transforms
- AZ_TEST_ASSERT(childTransform == static_cast<TransformInterface*>(childTransformComponent));
- AZ_TEST_ASSERT(childTransform->GetWorldTM() == m_checkWorldTM);
- AZ_TEST_ASSERT(childTransform->GetLocalTM() == m_checkLocalTM);
- AZ_TEST_ASSERT(childTransform->GetParentId() == m_checkNewParentId);
- // Modify the local (and world) matrix
- m_checkLocalTM = Transform::CreateTranslation(Vector3(5.0f, 0.0f, 0.0f));
- m_checkWorldTM = m_checkLocalTM;
- childTransform->SetWorldTM(m_checkWorldTM);
- // Parent the child object
- m_checkNewParentId = parentEntity.GetId();
- m_checkLocalTM *= parentTransform->GetWorldTM().GetInverse(); // the set parent will move the child object into parent space
- childTransform->SetParent(m_checkNewParentId);
- // Deactivate the parent (this essentially removes the parent)
- m_checkNewParentId.SetInvalid();
- m_checkOldParentId = parentEntity.GetId();
- m_checkLocalTM = m_checkWorldTM; // we will remove the parent
- parentEntity.Deactivate();
- TransformNotificationBus::Handler::BusDisconnect(childEntity.GetId());
- // now we should we without a parent
- childEntity.Deactivate();
- }
- Transform m_checkWorldTM;
- Transform m_checkLocalTM;
- EntityId m_checkOldParentId;
- EntityId m_checkNewParentId;
- };
- TEST_F(TransformComponentUberTest, Test)
- {
- run();
- }
- class TransformComponentChildNotificationTest
- : public TransformComponentApplication
- , public TransformNotificationBus::Handler
- {
- public:
- void OnChildAdded(EntityId child) override
- {
- AZ_TEST_ASSERT(child == m_checkChildId);
- m_onChildAddedCount++;
- }
- void OnChildRemoved(EntityId child) override
- {
- AZ_TEST_ASSERT(child == m_checkChildId);
- m_onChildRemovedCount++;
- }
- void run()
- {
- // Create ID for parent and begin listening for child add/remove notifications
- AZ::EntityId parentId = Entity::MakeId();
- TransformNotificationBus::Handler::BusConnect(parentId);
- Entity childEntity;
- AZ::TransformConfig transformConfig;
- transformConfig.m_isStatic = false;
- childEntity.CreateComponent<TransformComponent>()->SetConfiguration(transformConfig);
- m_checkChildId = childEntity.GetId();
- childEntity.Init();
- childEntity.Activate();
- TransformInterface* childTransform = childEntity.GetTransform();
- // Expected number of notifications to OnChildAdded and OnChildRemoved
- int checkAddCount = 0;
- int checkRemoveCount = 0;
- // Changing to target parentId should notify add
- AZ_TEST_ASSERT(m_onChildAddedCount == checkAddCount);
- childTransform->SetParent(parentId);
- checkAddCount++;
- AZ_TEST_ASSERT(m_onChildAddedCount == checkAddCount);
- // Deactivating child should notify removal
- AZ_TEST_ASSERT(m_onChildRemovedCount == checkRemoveCount);
- childEntity.Deactivate();
- checkRemoveCount++;
- AZ_TEST_ASSERT(m_onChildRemovedCount == checkRemoveCount);
- // Activating child (while parentId is set) should notify add
- AZ_TEST_ASSERT(m_onChildAddedCount == checkAddCount);
- childEntity.Activate();
- checkAddCount++;
- AZ_TEST_ASSERT(m_onChildAddedCount == checkAddCount);
- // Setting parent invalid should notify removal
- AZ_TEST_ASSERT(m_onChildRemovedCount == checkRemoveCount);
- childTransform->SetParent(EntityId());
- checkRemoveCount++;
- AZ_TEST_ASSERT(m_onChildRemovedCount == checkRemoveCount);
- TransformNotificationBus::Handler::BusDisconnect(parentId);
- childEntity.Deactivate();
- }
- EntityId m_checkChildId;
- int m_onChildAddedCount = 0;
- int m_onChildRemovedCount = 0;
- };
- TEST_F(TransformComponentChildNotificationTest, Test)
- {
- run();
- }
- class LookAtTransformTest
- : public ::testing::Test
- {
- public:
- void run()
- {
- // CreateLookAt
- AZ::Vector3 lookAtEye(1.0f, 2.0f, 3.0f);
- AZ::Vector3 lookAtTarget(10.0f, 5.0f, -5.0f);
- AZ::Transform t1 = AZ::Transform::CreateLookAt(lookAtEye, lookAtTarget);
- AZ_TEST_ASSERT(t1.GetBasisY().IsClose((lookAtTarget - lookAtEye).GetNormalized()));
- AZ_TEST_ASSERT(t1.GetTranslation() == lookAtEye);
- AZ_TEST_ASSERT(t1.IsOrthogonal());
- AZ_TEST_START_TRACE_SUPPRESSION;
- t1 = AZ::Transform::CreateLookAt(lookAtEye, lookAtEye); //degenerate direction
- AZ_TEST_STOP_TRACE_SUPPRESSION(1);
- AZ_TEST_ASSERT(t1.IsOrthogonal());
- AZ_TEST_ASSERT(t1 == AZ::Transform::CreateIdentity());
- t1 = AZ::Transform::CreateLookAt(lookAtEye, lookAtEye + AZ::Vector3::CreateAxisZ()); //degenerate with up direction
- AZ_TEST_ASSERT(t1.GetBasisY().IsClose(AZ::Vector3::CreateAxisZ()));
- AZ_TEST_ASSERT(t1.GetTranslation() == lookAtEye);
- AZ_TEST_ASSERT(t1.IsOrthogonal());
- }
- };
- TEST_F(LookAtTransformTest, Test)
- {
- run();
- }
- // Test TransformComponent's methods of modifying/retrieving underlying translation, rotation and scale transform component.
- class TransformComponentTransformMatrixSetGet
- : public TransformComponentApplication
- {
- protected:
- void SetUp() override
- {
- TransformComponentApplication::SetUp();
- m_parentEntity = aznew Entity("Parent");
- m_parentId = m_parentEntity->GetId();
- m_parentEntity->Init();
- m_parentEntity->CreateComponent<TransformComponent>();
- m_childEntity = aznew Entity("Child");
- m_childId = m_childEntity->GetId();
- m_childEntity->Init();
- m_childEntity->CreateComponent<TransformComponent>();
- m_parentEntity->Activate();
- m_childEntity->Activate();
- TransformBus::Event(m_childId, &TransformBus::Events::SetParent, m_parentId);
- }
- void TearDown() override
- {
- m_childEntity->Deactivate();
- m_parentEntity->Deactivate();
- delete m_childEntity;
- delete m_parentEntity;
- TransformComponentApplication::TearDown();
- }
- Entity* m_parentEntity = nullptr;
- EntityId m_parentId = EntityId();
- Entity* m_childEntity = nullptr;
- EntityId m_childId = EntityId();
- };
- TEST_F(TransformComponentTransformMatrixSetGet, SetLocalX_SimpleValues_Set)
- {
- float tx = 123.123f;
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalX, tx);
- Transform tm;
- TransformBus::EventResult(tm, m_childId, &TransformBus::Events::GetLocalTM);
- EXPECT_NEAR(tx, tm.GetTranslation().GetX(), AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, GetLocalX_SimpleValues_Set)
- {
- Transform tm;
- tm.SetTranslation(AZ::Vector3::CreateAxisX(432.456f));
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTM, tm);
- float tx = 0;
- TransformBus::EventResult(tx, m_childId, &TransformBus::Events::GetLocalX);
- EXPECT_NEAR(tx, tm.GetTranslation().GetX(), AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, SetLocalY_SimpleValues_Set)
- {
- float ty = 435.676f;
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalY, ty);
- Transform tm;
- TransformBus::EventResult(tm, m_childId, &TransformBus::Events::GetLocalTM);
- EXPECT_NEAR(ty, tm.GetTranslation().GetY(), AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, GetLocalY_SimpleValues_Set)
- {
- Transform tm;
- tm.SetTranslation(AZ::Vector3::CreateAxisY(154.754f));
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTM, tm);
- float ty = 0;
- TransformBus::EventResult(ty, m_childId, &TransformBus::Events::GetLocalY);
- EXPECT_NEAR(ty, tm.GetTranslation().GetY(), AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, SetLocalZ_SimpleValues_Set)
- {
- float tz = 987.456f;
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalZ, tz);
- Transform tm;
- TransformBus::EventResult(tm, m_childId, &TransformBus::Events::GetLocalTM);
- EXPECT_NEAR(tz, tm.GetTranslation().GetZ(), AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, GetLocalZ_SimpleValues_Set)
- {
- Transform tm;
- tm.SetTranslation(AZ::Vector3::CreateAxisZ(453.894f));
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTM, tm);
- float tz = 0;
- TransformBus::EventResult(tz, m_childId, &TransformBus::Events::GetLocalZ);
- EXPECT_NEAR(tz, tm.GetTranslation().GetZ(), AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, SetLocalRotation_SimpleValues_Set)
- {
- // add some scale first
- float scale = 1.23f;
- Transform tm = Transform::CreateUniformScale(scale);
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTM, tm);
- float rx = 42.435f;
- float ry = 19.454f;
- float rz = 98.356f;
- Vector3 angles(rx, ry, rz);
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalRotation, angles);
- TransformBus::EventResult(tm, m_childId, &TransformBus::Events::GetLocalTM);
- Matrix3x3 rotateZ = Matrix3x3::CreateRotationZ(rz);
- Matrix3x3 rotateY = Matrix3x3::CreateRotationY(ry);
- Matrix3x3 rotateX = Matrix3x3::CreateRotationX(rx);
- Matrix3x3 finalRotate = rotateX * rotateY * rotateZ;
- Vector3 basisX = tm.GetBasisX();
- Vector3 expectedBasisX = finalRotate.GetBasisX() * scale;
- EXPECT_TRUE(basisX.IsClose(expectedBasisX));
- Vector3 basisY = tm.GetBasisY();
- Vector3 expectedBasisY = finalRotate.GetBasisY() * scale;
- EXPECT_TRUE(basisY.IsClose(expectedBasisY));
- Vector3 basisZ = tm.GetBasisZ();
- Vector3 expectedBasisZ = finalRotate.GetBasisZ() * scale;
- EXPECT_TRUE(basisZ.IsClose(expectedBasisZ));
- }
- TEST_F(TransformComponentTransformMatrixSetGet, GetLocalRotation_SimpleValues_Return)
- {
- float rx = 0.66f;
- float ry = 1.23f;
- float rz = 0.23f;
- Matrix3x3 rotateZ = Matrix3x3::CreateRotationZ(rz);
- Matrix3x3 rotateY = Matrix3x3::CreateRotationY(ry);
- Matrix3x3 rotateX = Matrix3x3::CreateRotationX(rx);
- Matrix3x3 finalRotate = rotateX * rotateY * rotateZ;
- Transform tm = Transform::CreateFromMatrix3x3(finalRotate);
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTM, tm);
- Vector3 angles;
- TransformBus::EventResult(angles, m_childId, &TransformBus::Events::GetLocalRotation);
- EXPECT_TRUE(angles.IsClose(Vector3(rx, ry, rz)));
- }
- TEST_F(TransformComponentTransformMatrixSetGet, SetLocalRotationQuaternion_SimpleValues_Set)
- {
- float rx = 42.435f;
- float ry = 19.454f;
- float rz = 98.356f;
- Quaternion quatX = Quaternion::CreateRotationX(rx);
- Quaternion quatY = Quaternion::CreateRotationY(ry);
- Quaternion quatZ = Quaternion::CreateRotationZ(rz);
- Quaternion finalQuat = quatX * quatY * quatZ;
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalRotationQuaternion, finalQuat);
- Transform tm;
- TransformBus::EventResult(tm, m_childId, &TransformBus::Events::GetLocalTM);
- Matrix3x3 rotateZ = Matrix3x3::CreateRotationZ(rz);
- Matrix3x3 rotateY = Matrix3x3::CreateRotationY(ry);
- Matrix3x3 rotateX = Matrix3x3::CreateRotationX(rx);
- Matrix3x3 finalRotate = rotateX * rotateY * rotateZ;
- Vector3 basisX = tm.GetBasisX();
- Vector3 expectedBasisX = finalRotate.GetBasisX();
- EXPECT_TRUE(basisX.IsClose(expectedBasisX));
- Vector3 basisY = tm.GetBasisY();
- Vector3 expectedBasisY = finalRotate.GetBasisY();
- EXPECT_TRUE(basisY.IsClose(expectedBasisY));
- Vector3 basisZ = tm.GetBasisZ();
- Vector3 expectedBasisZ = finalRotate.GetBasisZ();
- EXPECT_TRUE(basisZ.IsClose(expectedBasisZ));
- }
- TEST_F(TransformComponentTransformMatrixSetGet, GetLocalRotationQuaternion_SimpleValues_Return)
- {
- float rx = 0.66f;
- float ry = 1.23f;
- float rz = 0.23f;
- Matrix3x3 rotateZ = Matrix3x3::CreateRotationZ(rz);
- Matrix3x3 rotateY = Matrix3x3::CreateRotationY(ry);
- Matrix3x3 rotateX = Matrix3x3::CreateRotationX(rx);
- Matrix3x3 finalRotate = rotateX * rotateY * rotateZ;
- Transform tm = Transform::CreateFromMatrix3x3(finalRotate);
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTM, tm);
- Quaternion quatX = Quaternion::CreateRotationX(rx);
- Quaternion quatY = Quaternion::CreateRotationY(ry);
- Quaternion quatZ = Quaternion::CreateRotationZ(rz);
- Quaternion expectedQuat = quatX * quatY * quatZ;
- Quaternion resultQuat;
- TransformBus::EventResult(resultQuat, m_childId, &TransformBus::Events::GetLocalRotationQuaternion);
- EXPECT_TRUE(resultQuat.IsClose(expectedQuat));
- }
- TEST_F(TransformComponentTransformMatrixSetGet, RotateAroundLocalX_SimpleValues_Set)
- {
- float rx = 1.43f;
- TransformBus::Event(m_childId, &TransformBus::Events::RotateAroundLocalX, rx);
- Vector3 localRotation;
- TransformBus::EventResult(localRotation, m_childId, &TransformBus::Events::GetLocalRotation);
- EXPECT_TRUE(localRotation.IsClose(Vector3(rx, 0.0f, 0.0f)));
- }
- TEST_F(TransformComponentTransformMatrixSetGet, RotateAroundLocalX_RepeatCallingThisFunctionDoesNotSkewScale)
- {
- // test numeric stability
- float rx = 1.43f;
- for (int i = 0; i < 100; ++i)
- {
- TransformBus::Event(m_childId, &TransformBus::Events::RotateAroundLocalX, rx);
- }
- float localScale = FLT_MAX;
- TransformBus::EventResult(localScale, m_childId, &TransformBus::Events::GetLocalUniformScale);
- EXPECT_NEAR(localScale, 1.0f, AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, RotateAroundLocalX_ScaleDoesNotSkewRotation)
- {
- float expectedScale = 42.564f;
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalUniformScale, expectedScale);
- float rx = 1.43f;
- TransformBus::Event(m_childId, &TransformBus::Events::RotateAroundLocalX, rx);
- Vector3 localRotation;
- TransformBus::EventResult(localRotation, m_childId, &TransformBus::Events::GetLocalRotation);
- EXPECT_TRUE(localRotation.IsClose(Vector3(rx, 0.0f, 0.0f)));
- }
- TEST_F(TransformComponentTransformMatrixSetGet, RotateAroundLocalY_SimpleValue_Set)
- {
- float ry = 1.43f;
- TransformBus::Event(m_childId, &TransformBus::Events::RotateAroundLocalY, ry);
- Vector3 localRotation;
- TransformBus::EventResult(localRotation, m_childId, &TransformBus::Events::GetLocalRotation);
- EXPECT_TRUE(localRotation.IsClose(Vector3(0.0f, ry, 0.0f)));
- }
- TEST_F(TransformComponentTransformMatrixSetGet, RotateAroundLocalY_RepeatCallingThisFunctionDoesNotSkewScale)
- {
- // test numeric stability
- float ry = 1.43f;
- for (int i = 0; i < 100; ++i)
- {
- TransformBus::Event(m_childId, &TransformBus::Events::RotateAroundLocalY, ry);
- }
- float localScale = FLT_MAX;
- TransformBus::EventResult(localScale, m_childId, &TransformBus::Events::GetLocalUniformScale);
- EXPECT_NEAR(localScale, 1.0f, AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, RotateAroundLocalY_ScaleDoesNotSkewRotation)
- {
- float expectedScale = 42.564f;
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalUniformScale, expectedScale);
- float ry = 1.43f;
- TransformBus::Event(m_childId, &TransformBus::Events::RotateAroundLocalY, ry);
- Vector3 localRotation;
- TransformBus::EventResult(localRotation, m_childId, &TransformBus::Events::GetLocalRotation);
- EXPECT_TRUE(localRotation.IsClose(Vector3(0.0f, ry, 0.0f)));
- }
- TEST_F(TransformComponentTransformMatrixSetGet, RotateAroundLocalZ_SimpleValues_Set)
- {
- float rz = 1.43f;
- TransformBus::Event(m_childId, &TransformBus::Events::RotateAroundLocalZ, rz);
- Vector3 localRotation;
- TransformBus::EventResult(localRotation, m_childId, &TransformBus::Events::GetLocalRotation);
- EXPECT_TRUE(localRotation.IsClose(Vector3(0.0f, 0.0f, rz)));
- }
- TEST_F(TransformComponentTransformMatrixSetGet, RotateAroundLocalZ_RepeatCallingThisFunctionDoesNotSkewScale)
- {
- // test numeric stability
- float rz = 1.43f;
- for (int i = 0; i < 100; ++i)
- {
- TransformBus::Event(m_childId, &TransformBus::Events::RotateAroundLocalZ, rz);
- }
- float localScale = FLT_MAX;
- TransformBus::EventResult(localScale, m_childId, &TransformBus::Events::GetLocalUniformScale);
- EXPECT_NEAR(localScale, 1.0f, AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, RotateAroundLocalZ_ScaleDoesNotSkewRotation)
- {
- float expectedScale = 42.564f;
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalUniformScale, expectedScale);
- float rz = 1.43f;
- TransformBus::Event(m_childId, &TransformBus::Events::RotateAroundLocalZ, rz);
- Vector3 localRotation;
- TransformBus::EventResult(localRotation, m_childId, &TransformBus::Events::GetLocalRotation);
- EXPECT_TRUE(localRotation.IsClose(Vector3(0.0f, 0.0f, rz)));
- }
- TEST_F(TransformComponentTransformMatrixSetGet, SetLocalScale_SimpleValues_Set)
- {
- float expectedScale = 42.564f;
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalUniformScale, expectedScale);
- Transform tm;
- TransformBus::EventResult(tm, m_childId, &TransformBus::Events::GetLocalTM);
- float scale = tm.GetUniformScale();
- EXPECT_NEAR(scale, expectedScale, AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, GetLocalScale_SimpleValues_Return)
- {
- float expectedScale = 43.463f;
- Transform scaleTM = Transform::CreateUniformScale(expectedScale);
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTM, scaleTM);
- float scale;
- TransformBus::EventResult(scale, m_childId, &TransformBus::Events::GetLocalUniformScale);
- EXPECT_NEAR(scale, expectedScale, AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, GetWorldScale_ChildHasNoScale_ReturnScaleSameAsParent)
- {
- float expectedScale = 43.463f;
- Transform scaleTM = Transform::CreateUniformScale(expectedScale);
- TransformBus::Event(m_parentId, &TransformBus::Events::SetLocalTM, scaleTM);
- float scale = FLT_MAX;
- TransformBus::EventResult(scale, m_childId, &TransformBus::Events::GetWorldUniformScale);
- EXPECT_NEAR(scale, expectedScale, AZ::Constants::Tolerance);
- }
- TEST_F(TransformComponentTransformMatrixSetGet, GetWorldScale_ChildHasScale_ReturnCompoundScale)
- {
- float parentScale = 4.463f;
- Transform parentScaleTM = Transform::CreateUniformScale(parentScale);
- TransformBus::Event(m_parentId, &TransformBus::Events::SetLocalTM, parentScaleTM);
- float childScale = 1.64f;
- Transform childScaleTM = Transform::CreateUniformScale(childScale);
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTM, childScaleTM);
- float scale = FLT_MAX;
- TransformBus::EventResult(scale, m_childId, &TransformBus::Events::GetWorldUniformScale);
- EXPECT_NEAR(scale, parentScale * childScale, AZ::Constants::Tolerance);
- }
- class TransformComponentHierarchy
- : public TransformComponentApplication
- {
- protected:
- void SetUp() override
- {
- TransformComponentApplication::SetUp();
- m_parentEntity = aznew Entity("Parent");
- m_parentId = m_parentEntity->GetId();
- m_parentEntity->Init();
- m_parentEntity->CreateComponent<TransformComponent>();
- m_childEntity = aznew Entity("Child");
- m_childId = m_childEntity->GetId();
- m_childEntity->Init();
- m_childEntity->CreateComponent<TransformComponent>();
- m_parentEntity->Activate();
- m_childEntity->Activate();
- }
- void TearDown() override
- {
- m_childEntity->Deactivate();
- m_parentEntity->Deactivate();
- delete m_childEntity;
- delete m_parentEntity;
- TransformComponentApplication::TearDown();
- }
- Entity* m_parentEntity = nullptr;
- EntityId m_parentId = EntityId();
- Entity* m_childEntity = nullptr;
- EntityId m_childId = EntityId();
- };
- TEST_F(TransformComponentHierarchy, SetParent_NormalValue_SetKeepWorldTransform)
- {
- AZ::Vector3 childLocalPos(20.45f, 46.14f, 93.65f);
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTranslation, childLocalPos);
- AZ::Vector3 expectedChildWorldPos = childLocalPos;
- AZ::Vector3 parentLocalPos(65.24f, 10.65f, 37.87f);
- TransformBus::Event(m_parentId, &TransformBus::Events::SetLocalTranslation, parentLocalPos);
- TransformBus::Event(m_childId, &TransformBus::Events::SetParent, m_parentId);
- AZ::Vector3 childWorldPos;
- TransformBus::EventResult(childWorldPos, m_childId, &TransformBus::Events::GetWorldTranslation);
- EXPECT_TRUE(childWorldPos == expectedChildWorldPos);
- }
- TEST_F(TransformComponentHierarchy, SetParentRelative_NormalValue_SetKeepLocalTransform)
- {
- AZ::Vector3 expectedChildLocalPos(22.45f, 42.14f, 97.45f);
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTranslation, expectedChildLocalPos);
- AZ::Vector3 parentLocalPos(15.64f, 12.65f, 29.87f);
- TransformBus::Event(m_parentId, &TransformBus::Events::SetLocalTranslation, parentLocalPos);
- TransformBus::Event(m_childId, &TransformBus::Events::SetParentRelative, m_parentId);
- AZ::Vector3 childLocalPos;
- TransformBus::EventResult(childLocalPos, m_childId, &TransformBus::Events::GetLocalTranslation);
- EXPECT_TRUE(childLocalPos == expectedChildLocalPos);
- }
- TEST_F(TransformComponentHierarchy, SetParent_Null_SetKeepWorldTransform)
- {
- AZ::Vector3 childLocalPos(28.45f, 56.14f, 43.65f);
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTranslation, childLocalPos);
- AZ::Vector3 parentLocalPos(85.24f, 12.65f, 33.87f);
- TransformBus::Event(m_parentId, &TransformBus::Events::SetLocalTranslation, parentLocalPos);
- TransformBus::Event(m_childId, &TransformBus::Events::SetParentRelative, m_parentId);
- AZ::Vector3 expectedChildWorldPos;
- TransformBus::EventResult(expectedChildWorldPos, m_childId, &TransformBus::Events::GetWorldTranslation);
- TransformBus::Event(m_childId, &TransformBus::Events::SetParent, AZ::EntityId());
- AZ::Vector3 childWorldPos;
- TransformBus::EventResult(childWorldPos, m_childId, &TransformBus::Events::GetWorldTranslation);
- EXPECT_TRUE(childWorldPos == expectedChildWorldPos);
- // child entity doesn't have a parent now, its world position should equal its local one
- AZ::Vector3 actualChildLocalPos;
- TransformBus::EventResult(actualChildLocalPos, m_childId, &TransformBus::Events::GetLocalTranslation);
- EXPECT_TRUE(actualChildLocalPos == expectedChildWorldPos);
- }
- TEST_F(TransformComponentHierarchy, SetParentRelative_Null_SetKeepLocalTransform)
- {
- AZ::Vector3 childLocalPos(28.45f, 49.14f, 94.65f);
- TransformBus::Event(m_childId, &TransformBus::Events::SetLocalTranslation, childLocalPos);
- AZ::Vector3 parentLocalPos(66.24f, 19.65f, 32.87f);
- TransformBus::Event(m_parentId, &TransformBus::Events::SetLocalTranslation, parentLocalPos);
- TransformBus::Event(m_childId, &TransformBus::Events::SetParent, m_parentId);
- AZ::Vector3 expectedChildLocalPos;
- TransformBus::EventResult(expectedChildLocalPos, m_childId, &TransformBus::Events::GetLocalTranslation);
- TransformBus::Event(m_childId, &TransformBus::Events::SetParentRelative, AZ::EntityId());
- TransformBus::EventResult(childLocalPos, m_childId, &TransformBus::Events::GetLocalTranslation);
- EXPECT_TRUE(childLocalPos == expectedChildLocalPos);
- // child entity doesn't have a parent now, its world position should equal its local one
- AZ::Vector3 actualChildWorldPos;
- TransformBus::EventResult(actualChildWorldPos, m_childId, &TransformBus::Events::GetWorldTranslation);
- EXPECT_TRUE(actualChildWorldPos == expectedChildLocalPos);
- }
- // Fixture provides TransformComponent that is static (or not static) on an entity that has been activated.
- template<bool IsStatic>
- class StaticOrMovableTransformComponent
- : public TransformComponentApplication
- {
- protected:
- void SetUp() override
- {
- TransformComponentApplication::SetUp();
- m_entity = aznew Entity(IsStatic ? "Static Entity" : "Movable Entity");
- AZ::TransformConfig transformConfig;
- transformConfig.m_isStatic = IsStatic;
- auto transformComponent = m_entity->CreateComponent<TransformComponent>();
- transformComponent->SetConfiguration(transformConfig);
- m_transformInterface = transformComponent;
- m_entity->Init();
- m_entity->Activate();
- }
- Entity* m_entity;
- TransformInterface* m_transformInterface = nullptr;
- };
- class MovableTransformComponent : public StaticOrMovableTransformComponent<false> {};
- class StaticTransformComponent : public StaticOrMovableTransformComponent<true> {};
- TEST_F(StaticTransformComponent, SanityCheck)
- {
- ASSERT_NE(m_entity, nullptr);
- ASSERT_NE(m_transformInterface, nullptr);
- EXPECT_EQ(m_entity->GetState(), Entity::State::Active);
- }
- TEST_F(MovableTransformComponent, IsStaticTransform_False)
- {
- EXPECT_FALSE(m_transformInterface->IsStaticTransform());
- }
- TEST_F(StaticTransformComponent, IsStaticTransform_True)
- {
- EXPECT_TRUE(m_transformInterface->IsStaticTransform());
- }
- TEST_F(MovableTransformComponent, SetWorldTM_MovesEntity)
- {
- [[maybe_unused]] Transform previousTM = m_transformInterface->GetWorldTM();
- Transform nextTM = Transform::CreateTranslation(Vector3(1.f, 2.f, 3.f));
- m_transformInterface->SetWorldTM(nextTM);
- EXPECT_TRUE(m_transformInterface->GetWorldTM().IsClose(nextTM));
- }
- TEST_F(StaticTransformComponent, SetWorldTM_DoesNothing)
- {
- Transform previousTM = m_transformInterface->GetWorldTM();
- Transform nextTM = Transform::CreateTranslation(Vector3(1.f, 2.f, 3.f));
- m_transformInterface->SetWorldTM(nextTM);
- EXPECT_TRUE(m_transformInterface->GetWorldTM().IsClose(previousTM));
- }
- TEST_F(MovableTransformComponent, SetLocalTM_MovesEntity)
- {
- [[maybe_unused]] Transform previousTM = m_transformInterface->GetLocalTM();
- Transform nextTM = Transform::CreateTranslation(Vector3(1.f, 2.f, 3.f));
- m_transformInterface->SetLocalTM(nextTM);
- EXPECT_TRUE(m_transformInterface->GetLocalTM().IsClose(nextTM));
- }
- TEST_F(StaticTransformComponent, SetLocalTM_DoesNothing)
- {
- Transform previousTM = m_transformInterface->GetLocalTM();
- Transform nextTM = Transform::CreateTranslation(Vector3(1.f, 2.f, 3.f));
- m_transformInterface->SetLocalTM(nextTM);
- EXPECT_TRUE(m_transformInterface->GetLocalTM().IsClose(previousTM));
- }
- TEST_F(StaticTransformComponent, SetLocalTmOnDeactivatedEntity_MovesEntity)
- {
- // when static transform component is deactivated, it should allow movement
- [[maybe_unused]] Transform previousTM = m_transformInterface->GetLocalTM();
- m_entity->Deactivate();
- Transform nextTM = Transform::CreateTranslation(Vector3(1.f, 2.f, 3.f));
- m_transformInterface->SetLocalTM(nextTM);
- EXPECT_TRUE(m_transformInterface->GetLocalTM().IsClose(nextTM));
- }
- // Sets up a parent/child relationship between two static transform components
- class ParentedStaticTransformComponent
- : public TransformComponentApplication
- {
- protected:
- void SetUp() override
- {
- TransformComponentApplication::SetUp();
- m_parentEntity = aznew Entity("Parent");
- m_parentEntity->Init();
- AZ::TransformConfig parentConfig{ AZ::Transform::CreateTranslation(AZ::Vector3(5.f, 5.f, 5.f)) };
- parentConfig.m_isStatic = true;
- m_parentEntity->CreateComponent<TransformComponent>()->SetConfiguration(parentConfig);
- m_childEntity = aznew Entity("Child");
- m_childEntity->Init();
- AZ::TransformConfig childConfig{ AZ::Transform::CreateTranslation(AZ::Vector3(5.f, 5.f, 5.f)) };
- childConfig.m_isStatic = true;
- childConfig.m_parentId = m_parentEntity->GetId();
- childConfig.m_parentActivationTransformMode = AZ::TransformConfig::ParentActivationTransformMode::MaintainOriginalRelativeTransform;
- m_childEntity->CreateComponent<TransformComponent>()->SetConfiguration(childConfig);
- }
- Entity* m_parentEntity = nullptr;
- Entity* m_childEntity = nullptr;
- };
- // we do expect a static entity to move if its parent is activated after itself
- TEST_F(ParentedStaticTransformComponent, ParentActivatesLast_OffsetObeyed)
- {
- m_childEntity->Activate();
- Transform previousWorldTM;
- TransformBus::EventResult(previousWorldTM, m_childEntity->GetId(), &TransformBus::Events::GetWorldTM);
- m_parentEntity->Activate();
- Transform nextWorldTM;
- TransformBus::EventResult(nextWorldTM, m_childEntity->GetId(), &TransformBus::Events::GetWorldTM);
- EXPECT_FALSE(previousWorldTM.IsClose(nextWorldTM));
- }
- // Fixture that loads a TransformComponent from a buffer.
- // Useful for testing version converters.
- class TransformComponentVersionConverter
- : public TransformComponentApplication
- {
- public:
- void SetUp() override
- {
- TransformComponentApplication::SetUp();
- m_transformComponent.reset(AZ::Utils::LoadObjectFromBuffer<TransformComponent>(m_objectStreamBuffer, strlen(m_objectStreamBuffer) + 1));
- m_transformInterface = m_transformComponent.get();
- }
- void TearDown() override
- {
- m_transformComponent.reset();
- TransformComponentApplication::TearDown();
- }
- AZStd::unique_ptr<TransformComponent> m_transformComponent;
- TransformInterface* m_transformInterface = nullptr;
- const char* m_objectStreamBuffer = nullptr;
- };
- ///////////////////////////////////////////////////////////////////////////
- // TransformConfig
- static bool operator==(const TransformConfig& lhs, const TransformConfig& rhs)
- {
- return lhs.m_parentId == rhs.m_parentId
- && lhs.m_parentActivationTransformMode == rhs.m_parentActivationTransformMode
- && lhs.m_isStatic == rhs.m_isStatic
- && lhs.m_localTransform == rhs.m_localTransform
- && lhs.m_worldTransform == rhs.m_worldTransform
- ;
- }
- class TransformConfigTest
- : public TransformComponentApplication
- {
- public:
- // creates a transform with a random rotation and a translation with each component uniformly sampled in the
- // range [0, 1)
- AZ::Transform CreateRandomTransform()
- {
- AZ::Vector3 translation(m_random.GetRandomFloat(), m_random.GetRandomFloat(), m_random.GetRandomFloat());
- return AZ::Transform::CreateFromQuaternionAndTranslation(CreateRandomQuaternion(m_random), translation);
- }
- TransformConfig GetRandomConfig()
- {
- TransformConfig config;
- config.m_worldTransform = CreateRandomTransform();
- config.m_localTransform = CreateRandomTransform();
- config.m_parentId = Entity::MakeId();
- config.m_parentActivationTransformMode = (TransformConfig::ParentActivationTransformMode)(m_random.GetRandom() % 2);
- config.m_netSyncEnabled = (m_random.GetRandom() % 2) == 1;
- config.m_interpolatePosition = (m_random.GetRandom() % 2) == 1 ? InterpolationMode::NoInterpolation : InterpolationMode::LinearInterpolation;
- config.m_interpolateRotation = (m_random.GetRandom() % 2) == 1 ? InterpolationMode::NoInterpolation : InterpolationMode::LinearInterpolation;
- config.m_isStatic = (m_random.GetRandom() % 2) == 1;
- return config;
- }
- void SetUp() override
- {
- TransformComponentApplication::SetUp();
- m_random.SetSeed(static_cast<AZ::u64>(m_app.GetTimeAtCurrentTick().GetMilliseconds()));
- }
- AZ::SimpleLcgRandom m_random;
- };
- TEST_F(TransformConfigTest, SetConfiguration_Succeeds)
- {
- TransformComponent component;
- TransformConfig config = GetRandomConfig();
- EXPECT_TRUE(component.SetConfiguration(config));
- }
- TEST_F(TransformConfigTest, GetConfiguration_Succeeds)
- {
- TransformComponent component;
- TransformConfig config;
- EXPECT_TRUE(component.GetConfiguration(config));
- }
- TEST_F(TransformConfigTest, SetThenGet_ConfigsMatches)
- {
- TransformComponent component;
- TransformConfig originalConfig = GetRandomConfig();
- EXPECT_TRUE(component.SetConfiguration(originalConfig));
- TransformConfig retrievedConfig;
- EXPECT_TRUE(component.GetConfiguration(retrievedConfig));
- EXPECT_TRUE(originalConfig == retrievedConfig);
- }
- TEST_F(TransformConfigTest, ConfigDefaultsComparedToComponentDefaults_Same)
- {
- // A default-constructed TransformConfig should be equivalent
- // to a configuration fetched from a default-constructed TransformComponent.
- TransformConfig defaultConfig;
- TransformConfig retrievedConfig;
- TransformComponent component;
- EXPECT_TRUE(component.GetConfiguration(retrievedConfig));
- EXPECT_TRUE(defaultConfig == retrievedConfig);
- }
- ///////////////////////////////////////////////////////////////////////////
- // AzToolsFramework::Components::TransformComponent
- // Fixture base class for AzToolsFramework::Components::TransformComponent tests
- class OldEditorTransformComponentTest
- : public UnitTest::LeakDetectionFixture
- {
- protected:
- void SetUp() override
- {
- AZ::ComponentApplication::StartupParameters startupParameters;
- startupParameters.m_loadSettingsRegistry = false;
- m_app.Start(AZ::ComponentApplication::Descriptor(), startupParameters);
- // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
- // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
- // in the unit tests.
- AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
- }
- void TearDown() override
- {
- m_app.Stop();
- }
- AzToolsFramework::ToolsApplication m_app;
- };
- // Old TransformComponents used to store "Slice Root" entity Id, which could be its own Id.
- // The version-converter could end up making an entity into its own transform parent.
- // The EditorEntityFixupComponent should fix this up during slice instantiation.
- TEST_F(OldEditorTransformComponentTest, OldSliceRoots_ShouldHaveNoParent)
- {
- const char kSliceData[] =
- R"DELIMITER(<ObjectStream version="1">
- <Class name="PrefabComponent" field="element" version="1" type="{AFD304E4-1773-47C8-855A-8B622398934F}">
- <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
- <Class name="AZ::u64" field="Id" value="3561916384376604258" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
- </Class>
- <Class name="AZStd::vector" field="Entities" type="{2BADE35A-6F1B-4698-B2BC-3373D010020C}">
- <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
- <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
- <Class name="AZ::u64" field="id" value="15464031792689993220" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
- </Class>
- <Class name="AZStd::string" field="Name" value="MrRootEntity" type="{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}"/>
- <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
- <Class name="AZStd::vector" field="Components" type="{2BADE35A-6F1B-4698-B2BC-3373D010020C}">
- <Class name="TransformComponent" field="element" version="5" type="{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0}">
- <Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
- <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
- <Class name="AZ::u64" field="Id" value="3107681419974783222" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
- </Class>
- </Class>
- <Class name="EntityId" field="Parent Entity" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
- <Class name="AZ::u64" field="id" value="4294967295" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
- </Class>
- <Class name="EditorTransform" field="Transform Data" version="1" type="{B02B7063-D238-4F40-A724-405F7A6D68CB}">
- <Class name="Vector3" field="Translate" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
- <Class name="Vector3" field="Rotate" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
- <Class name="Vector3" field="Scale" value="1.0000000 1.0000000 1.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
- </Class>
- <Class name="Transform" field="Slice Transform" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000" type="{5D9958E9-9F1E-4985-B532-FFFDE75FEDFD}"/>
- <Class name="EntityId" field="Slice Root" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
- <Class name="AZ::u64" field="id" value="15464031792689993220" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
- </Class>
- <Class name="Transform" field="Cached World Transform" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000" type="{5D9958E9-9F1E-4985-B532-FFFDE75FEDFD}"/>
- </Class>
- </Class>
- </Class>
- </Class>
- <Class name="AZStd::list" field="Prefabs" type="{B845AD64-B5A0-4CCD-A86B-3477A36779BE}"/>
- <Class name="bool" field="IsDynamic" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
- </Class>
- </ObjectStream>)DELIMITER";
- AZStd::unique_ptr<SliceComponent> slice{ AZ::Utils::LoadObjectFromBuffer<AZ::SliceComponent>(kSliceData, strlen(kSliceData) + 1) };
- EXPECT_NE(slice.get(), nullptr);
- if (slice)
- {
- AZStd::vector<AZ::Entity*> entities;
- slice->GetEntities(entities);
- EXPECT_FALSE(entities.empty());
- if (!entities.empty())
- {
- auto editorTransformComponent = entities[0]->FindComponent<AzToolsFramework::Components::TransformComponent>();
- EXPECT_NE(editorTransformComponent, nullptr);
- if (editorTransformComponent)
- {
- // EditorEntityFixupComponent should have fixed this
- EXPECT_EQ(editorTransformComponent->GetParentId(), AZ::EntityId());
- }
- }
- }
- }
- // Fixture provides a root prefab with Transform component and listens for TransformNotificationBus.
- class TransformComponentActivationTest
- : public PrefabTestFixture
- , public TransformNotificationBus::Handler
- {
- protected:
- void SetUpEditorFixtureImpl() override
- {
- PrefabTestFixture::SetUpEditorFixtureImpl();
- }
- void TearDownEditorFixtureImpl() override
- {
- AZ::TransformNotificationBus::Handler::BusDisconnect();
-
- PrefabTestFixture::TearDownEditorFixtureImpl();
- }
-
- void OnTransformChanged(const Transform& /*local*/, const Transform& /*world*/) override
- {
- m_transformUpdated = true;
- }
- void MoveEntity(AZ::EntityId entityId)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Move Entity");
- TransformBus::Event(entityId, &TransformInterface::SetWorldTranslation, Vector3(1.f, 0.f, 0.f));
- }
-
- bool m_transformUpdated = false;
- };
-
- TEST_F(TransformComponentActivationTest, TransformChangedEventIsSentWhenEntityIsActivatedViaUndoRedo)
- {
- AZ::EntityId entityId = CreateEditorEntityUnderRoot("Entity");
- MoveEntity(entityId);
- ProcessDeferredUpdates();
- AZ::TransformNotificationBus::Handler::BusConnect(entityId);
- // verify that undoing/redoing move operations fires TransformChanged event
- Undo();
- EXPECT_TRUE(m_transformUpdated);
- m_transformUpdated = false;
- Redo();
- EXPECT_TRUE(m_transformUpdated);
- m_transformUpdated = false;
- }
- TEST_F(TransformComponentActivationTest, TransformChangedEventIsNotSentWhenEntityIsDeactivatedAndActivated)
- {
- AZ::EntityId entityId = CreateEditorEntityUnderRoot("Entity");
- AZ::TransformNotificationBus::Handler::BusConnect(entityId);
- // verify that simply activating/deactivating an entity does not fire TransformChanged event
- Entity* entity = nullptr;
- ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId);
- entity->Deactivate();
- entity->Activate();
- EXPECT_FALSE(m_transformUpdated);
- }
- } // namespace UnitTest
|