Merge remote-tracking branch 'upstream/development' into nvsickle/OutlinerDuplicateEntryFixes

This commit is contained in:
nvsickle
2021-10-13 13:24:24 -07:00
1722 changed files with 154722 additions and 22915 deletions
@@ -131,13 +131,13 @@ namespace UnitTest
m_app.reset(aznew ToolsTestApplication("ArchiveComponentTest"));
m_app->Start(AzFramework::Application::Descriptor());
// 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
// 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);
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
{
fileIoBase->SetAlias("@assets@", m_tempDir.GetDirectory());
fileIoBase->SetAlias("@products@", m_tempDir.GetDirectory());
}
}
@@ -37,10 +37,10 @@ namespace // anonymous
bool Search(const AzToolsFramework::AssetFileInfoList& assetList, const AZ::Data::AssetId& assetId)
{
return AZStd::find_if(assetList.m_fileInfoList.begin(), assetList.m_fileInfoList.end(),
[&](AzToolsFramework::AssetFileInfo fileInfo)
{
return fileInfo.m_assetId == assetId;
return AZStd::find_if(assetList.m_fileInfoList.begin(), assetList.m_fileInfoList.end(),
[&](AzToolsFramework::AssetFileInfo fileInfo)
{
return fileInfo.m_assetId == assetId;
});
}
}
@@ -74,11 +74,11 @@ namespace UnitTest
m_application->Start(AzFramework::Application::Descriptor());
// By default @assets@ is setup to include the platform at the end. But this test is going to
// By default @products@ is setup to include the platform at the end. But this test is going to
// loop over platforms and it will be included as part of the relative path of the file.
// So the asset folder for these tests have to point to the cache project root folder, which
// doesn't include the platform.
AZ::IO::FileIOBase::GetInstance()->SetAlias("@assets@", cacheProjectRootFolder.c_str());
AZ::IO::FileIOBase::GetInstance()->SetAlias("@products@", cacheProjectRootFolder.c_str());
for (int idx = 0; idx < s_totalAssets; idx++)
{
@@ -158,17 +158,17 @@ namespace UnitTest
m_assetRegistry->RegisterAssetDependency(assets[5], AZ::Data::ProductDependency(assets[6], 0));
m_assetRegistry->RegisterAssetDependency(assets[6], AZ::Data::ProductDependency(assets[7], 0));
// asset8 -> asset6
// asset8 -> asset6
m_assetRegistry->RegisterAssetDependency(assets[8], AZ::Data::ProductDependency(assets[6], 0));
// asset10 -> asset11
// asset10 -> asset11
m_assetRegistry->RegisterAssetDependency(assets[10], AZ::Data::ProductDependency(assets[11], 0));
// asset11 -> asset10
// asset11 -> asset10
m_assetRegistry->RegisterAssetDependency(assets[11], AZ::Data::ProductDependency(assets[10], 0));
// 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
// 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);
@@ -203,10 +203,6 @@ namespace UnitTest
const AZStd::string engroot = AZ::Test::GetEngineRootPath();
AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engroot.c_str());
AZ::IO::Path assetRoot(AZ::Utils::GetProjectPath());
assetRoot /= "Cache";
AZ::IO::FileIOBase::GetInstance()->SetAlias("@root@", assetRoot.c_str());
}
void TearDown() override
@@ -219,7 +215,7 @@ namespace UnitTest
delete m_application;
}
AZ::Data::AssetInfo GetAssetInfoById(const AZ::Data::AssetId& id) override
AZ::Data::AssetInfo GetAssetInfoById(const AZ::Data::AssetId& id) override
{
auto foundIter = m_assetRegistry->m_assetIdToInfo.find(id);
if (foundIter != m_assetRegistry->m_assetIdToInfo.end())
@@ -540,7 +536,7 @@ namespace UnitTest
EXPECT_TRUE(Search(assetList, assets[7]));
EXPECT_TRUE(Search(assetList, assets[8]));
// Removing the android flag from the asset should still produce the same result
// Removing the android flag from the asset should still produce the same result
m_assetSeedManager->RemoveSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_ANDROID);
assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::PC);
@@ -564,7 +560,7 @@ namespace UnitTest
EXPECT_TRUE(Search(assetList, assets[3]));
EXPECT_TRUE(Search(assetList, assets[4]));
// Adding the android flag again to the asset
// Adding the android flag again to the asset
m_assetSeedManager->AddSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_ANDROID);
assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::ANDROID_ID);
@@ -624,7 +620,7 @@ namespace UnitTest
EXPECT_EQ(assetList1.m_fileInfoList[0].m_assetId, assetList2.m_fileInfoList[0].m_assetId);
EXPECT_GE(assetList2.m_fileInfoList[0].m_modificationTime, assetList1.m_fileInfoList[0].m_modificationTime); // file mod time should change
// file hash should not change
for (int idx = 0; idx < 5; idx++)
{
@@ -680,7 +676,7 @@ namespace UnitTest
m_assetSeedManager->AddSeedAsset(assets[validFileIndex], AzFramework::PlatformFlags::Platform_PC, m_assetsPath[invalidFileIndex]);
const AzFramework::AssetSeedList& oldSeedList = m_assetSeedManager->GetAssetSeedList();
for (const auto& seedInfo : oldSeedList)
{
if (seedInfo.m_assetId == assets[validFileIndex])
@@ -18,8 +18,6 @@ namespace UnitTests
{
public:
MOCK_METHOD1(GetAbsoluteAssetDatabaseLocation, bool(AZStd::string&));
MOCK_METHOD0(GetAbsoluteDevGameFolderPath, const char* ());
MOCK_METHOD0(GetAbsoluteDevRootFolderPath, const char* ());
MOCK_METHOD2(GetRelativeProductPathFromFullSourceOrProductPath, bool(const AZStd::string& fullPath, AZStd::string& relativeProductPath));
MOCK_METHOD3(GenerateRelativeSourcePath,
bool(const AZStd::string& sourcePath, AZStd::string& relativePath, AZStd::string& watchFolder));
@@ -0,0 +1,252 @@
/*
* 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 <AzFramework/Entity/BehaviorEntity.h>
#include <AzTest/AzTest.h>
#include <AzToolsFramework/Application/ToolsApplication.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
#include <Entity/EntityUtilityComponent.h>
#include <ToolsComponents/TransformComponent.h>
namespace UnitTest
{
// Global variables for communicating between Lua test code and C++
AZ::EntityId g_globalEntityId = AZ::EntityId{};
AZStd::string g_globalString = "";
AzFramework::BehaviorComponentId g_globalComponentId = {};
AZStd::vector<AzToolsFramework::ComponentDetails> g_globalComponentDetails = {};
bool g_globalBool = false;
class EntityUtilityComponentTests
: public ToolsApplicationFixture
{
void InitProperties()
{
AZ::ComponentApplicationRequests* componentApplicationRequests = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
ASSERT_NE(componentApplicationRequests, nullptr);
auto behaviorContext = componentApplicationRequests->GetBehaviorContext();
ASSERT_NE(behaviorContext, nullptr);
behaviorContext->Property("g_globalEntityId", BehaviorValueProperty(&g_globalEntityId));
behaviorContext->Property("g_globalString", BehaviorValueProperty(&g_globalString));
behaviorContext->Property("g_globalComponentId", BehaviorValueProperty(&g_globalComponentId));
behaviorContext->Property("g_globalBool", BehaviorValueProperty(&g_globalBool));
behaviorContext->Property("g_globalComponentDetails", BehaviorValueProperty(&g_globalComponentDetails));
g_globalEntityId = AZ::EntityId{};
g_globalString = AZStd::string{};
g_globalComponentId = AzFramework::BehaviorComponentId{};
g_globalBool = false;
g_globalComponentDetails = AZStd::vector<AzToolsFramework::ComponentDetails>{};
}
void SetUpEditorFixtureImpl() override
{
InitProperties();
}
void TearDownEditorFixtureImpl() override
{
g_globalString.set_capacity(0); // Free all memory
g_globalComponentDetails.set_capacity(0);
}
};
TEST_F(EntityUtilityComponentTests, CreateEntity)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
sc.Execute(R"LUA(
g_globalEntityId = EntityUtilityBus.Broadcast.CreateEditorReadyEntity("test")
my_entity = Entity(g_globalEntityId)
g_globalString = my_entity:GetName()
)LUA");
EXPECT_NE(g_globalEntityId, AZ::EntityId{});
EXPECT_STREQ(g_globalString.c_str(), "test");
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(g_globalEntityId);
ASSERT_NE(entity, nullptr);
// Test cleaning up, make sure the entity is destroyed
AzToolsFramework::EntityUtilityBus::Broadcast(&AzToolsFramework::EntityUtilityBus::Events::ResetEntityContext);
entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(g_globalEntityId);
ASSERT_EQ(entity, nullptr);
}
TEST_F(EntityUtilityComponentTests, CreateEntityEmptyName)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
sc.Execute(R"LUA(
g_globalEntityId = EntityUtilityBus.Broadcast.CreateEditorReadyEntity("")
)LUA");
EXPECT_NE(g_globalEntityId, AZ::EntityId{});
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(g_globalEntityId);
ASSERT_NE(entity, nullptr);
}
TEST_F(EntityUtilityComponentTests, FindComponent)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
sc.Execute(R"LUA(
ent_id = EntityUtilityBus.Broadcast.CreateEditorReadyEntity("test")
g_globalComponentId = EntityUtilityBus.Broadcast.GetOrAddComponentByTypeName(ent_id, "27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0 TransformComponent")
)LUA");
EXPECT_TRUE(g_globalComponentId.IsValid());
}
TEST_F(EntityUtilityComponentTests, InvalidComponentName)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
AZ_TEST_START_TRACE_SUPPRESSION;
sc.Execute(R"LUA(
ent_id = EntityUtilityBus.Broadcast.CreateEditorReadyEntity("test")
g_globalComponentId = EntityUtilityBus.Broadcast.GetOrAddComponentByTypeName(ent_id, "ThisIsNotAComponent-Error")
)LUA");
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
EXPECT_FALSE(g_globalComponentId.IsValid());
}
TEST_F(EntityUtilityComponentTests, InvalidComponentId)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
AZ_TEST_START_TRACE_SUPPRESSION;
sc.Execute(R"LUA(
ent_id = EntityUtilityBus.Broadcast.CreateEditorReadyEntity("test")
g_globalComponentId = EntityUtilityBus.Broadcast.GetOrAddComponentByTypeName(ent_id, "{1234-hello-world-this-is-not-an-id}")
)LUA");
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // Should get 1 error stating the type id is not valid
EXPECT_FALSE(g_globalComponentId.IsValid());
}
TEST_F(EntityUtilityComponentTests, CreateComponent)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
sc.Execute(R"LUA(
ent_id = EntityUtilityBus.Broadcast.CreateEditorReadyEntity("test")
g_globalComponentId = EntityUtilityBus.Broadcast.GetOrAddComponentByTypeName(ent_id, "ScriptEditorComponent")
)LUA");
EXPECT_TRUE(g_globalComponentId.IsValid());
}
TEST_F(EntityUtilityComponentTests, UpdateComponent)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
sc.Execute(R"LUA(
g_globalEntityId = EntityUtilityBus.Broadcast.CreateEditorReadyEntity("test")
comp_id = EntityUtilityBus.Broadcast.GetOrAddComponentByTypeName(g_globalEntityId, "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent")
json_update = [[
{
"Transform Data": { "Rotate": [0.0, 0.1, 180.0] }
}
]]
g_globalBool = EntityUtilityBus.Broadcast.UpdateComponentForEntity(g_globalEntityId, comp_id, json_update);
)LUA");
EXPECT_TRUE(g_globalBool);
EXPECT_NE(g_globalEntityId, AZ::EntityId(AZ::EntityId::InvalidEntityId));
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(g_globalEntityId);
auto* transformComponent = entity->FindComponent<AzToolsFramework::Components::TransformComponent>();
ASSERT_NE(transformComponent, nullptr);
AZ::Vector3 localRotation = transformComponent->GetLocalRotationQuaternion().GetEulerDegrees();
EXPECT_EQ(localRotation, AZ::Vector3(.0f, 0.1f, 180.0f));
}
TEST_F(EntityUtilityComponentTests, GetComponentJson)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
sc.Execute(R"LUA(
g_globalString = EntityUtilityBus.Broadcast.GetComponentDefaultJson("ScriptEditorComponent")
)LUA");
EXPECT_STRNE(g_globalString.c_str(), "");
}
TEST_F(EntityUtilityComponentTests, GetComponentJsonDoesNotExist)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
AZ_TEST_START_TRACE_SUPPRESSION;
sc.Execute(R"LUA(
g_globalString = EntityUtilityBus.Broadcast.GetComponentDefaultJson("404")
)LUA");
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // 1 error: Failed to find component id for type name 404
EXPECT_STREQ(g_globalString.c_str(), "");
}
TEST_F(EntityUtilityComponentTests, SearchComponents)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
sc.Execute(R"LUA(
g_globalComponentDetails = EntityUtilityBus.Broadcast.FindMatchingComponents("Transform*")
)LUA");
// There should be 2 transform components
EXPECT_EQ(g_globalComponentDetails.size(), 2);
}
TEST_F(EntityUtilityComponentTests, SearchComponentsNotFound)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
sc.Execute(R"LUA(
g_globalComponentDetails = EntityUtilityBus.Broadcast.FindMatchingComponents("404")
)LUA");
EXPECT_EQ(g_globalComponentDetails.size(), 0);
}
}
@@ -181,8 +181,8 @@ namespace UnitTest
const char* dir = m_componentApplication->GetExecutableFolder();
m_localFileIO.SetAlias("@assets@", dir);
m_localFileIO.SetAlias("@devassets@", dir);
m_localFileIO.SetAlias("@products@", dir);
m_localFileIO.SetAlias("@projectroot@", dir);
}
void Destroy()
@@ -0,0 +1,99 @@
/*
* 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 <Tests/FocusMode/EditorFocusModeSelectionFixture.h>
namespace AzToolsFramework
{
TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithNoContainers)
{
// When no containers are in the way, the function will just return the entityId of the entity that was clicked.
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify the correct entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 1);
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
}
TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithClosedContainer)
{
// If a closed container is an ancestor of the queried entity, the closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); // Containers are closed by default
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify the correct entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 1);
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[StreetEntityName]);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
}
TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithOpenContainer)
{
// If a closed container is an ancestor of the queried entity, the closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify the correct entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 1);
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
}
TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithMultipleClosedContainers)
{
// If multiple closed containers are ancestors of the queried entity, the highest closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify the correct entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 1);
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CityEntityName]);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
}
TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithMultipleContainers)
{
// If multiple containers are ancestors of the queried entity, the highest closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true);
// Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify the correct entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 1);
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[StreetEntityName]);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
}
}
@@ -0,0 +1,293 @@
/*
* 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 <Tests/FocusMode/EditorFocusModeFixture.h>
namespace AzToolsFramework
{
TEST_F(EditorFocusModeFixture, ContainerEntityTests_Register)
{
// Registering an entity is successful.
auto outcome = m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]);
EXPECT_TRUE(outcome.IsSuccess());
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_RegisterTwice)
{
// Registering an entity twice fails.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]);
auto outcome = m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]);
EXPECT_FALSE(outcome.IsSuccess());
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_Unregister)
{
// Unregistering a container entity is successful.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]);
auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
EXPECT_TRUE(outcome.IsSuccess());
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_UnregisterRegularEntity)
{
// Unregistering an entity that was not previously registered fails.
auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
EXPECT_FALSE(outcome.IsSuccess());
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_UnregisterTwice)
{
// Unregistering a container entity twice fails.
auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
EXPECT_FALSE(outcome.IsSuccess());
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnRegularEntity)
{
// If a regular entity is passed, IsContainer returns false.
// Note that we use a different entity than the tests above to validate a completely new EntityId.
bool isContainer = m_containerEntityInterface->IsContainer(m_entityMap[SportsCarEntityName]);
EXPECT_FALSE(isContainer);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnRegisteredContainer)
{
// If a container entity is passed, IsContainer returns true.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
bool isContainer = m_containerEntityInterface->IsContainer(m_entityMap[SportsCarEntityName]);
EXPECT_TRUE(isContainer);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnUnRegisteredContainer)
{
// If an entity that was previously a container but was then unregistered is passed, IsContainer returns false.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
bool isContainer = m_containerEntityInterface->IsContainer(m_entityMap[SportsCarEntityName]);
EXPECT_FALSE(isContainer);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpenOnRegularEntity)
{
// Setting a regular entity to open should return a failure.
auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
EXPECT_FALSE(outcome.IsSuccess());
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpen)
{
// Set a container entity to open, and verify the operation was successful.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
EXPECT_TRUE(outcome.IsSuccess());
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpenTwice)
{
// Set a container entity to open twice, and verify that does not cause a failure (as intended).
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
EXPECT_TRUE(outcome.IsSuccess());
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerClosed)
{
// Set a container entity to closed, and verify the operation was successful.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
EXPECT_TRUE(outcome.IsSuccess());
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnRegularEntity)
{
// Query open state on a regular entity, and verify it returns true.
// Open containers behave exactly as regular entities, so this is the expected return value.
bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]);
EXPECT_TRUE(isOpen);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnDefaultContainerEntity)
{
// Query open state on a newly registered container entity, and verify it returns false.
// Containers are registered closed by default.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]);
EXPECT_FALSE(isOpen);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnOpenContainerEntity)
{
// Query open state on a container entity that was opened, and verify it returns true.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true);
bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]);
EXPECT_TRUE(isOpen);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnClosedContainerEntity)
{
// Query open state on a container entity that was opened and then closed, and verify it returns false.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true);
m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], false);
bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]);
EXPECT_FALSE(isOpen);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_ContainerOpenStateIsPreserved)
{
// Register an entity as container, open it, then unregister it.
// When the entity is registered again, the open state should be preserved.
// This behavior is necessary for the system to work alongside Prefab propagation refreshes.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true);
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]);
EXPECT_TRUE(isOpen);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearSucceeds)
{
// The Clear function works if no container is registered.
auto outcome = m_containerEntityInterface->Clear(m_editorEntityContextId);
EXPECT_TRUE(outcome.IsSuccess());
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearFailsIfContainersAreStillRegistered)
{
// The Clear function fails if a container is registered.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
auto outcome = m_containerEntityInterface->Clear(m_editorEntityContextId);
EXPECT_FALSE(outcome.IsSuccess());
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearSucceedsIfContainersAreUnregistered)
{
// The Clear function fails if a container is registered.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
auto outcome = m_containerEntityInterface->Clear(m_editorEntityContextId);
EXPECT_TRUE(outcome.IsSuccess());
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearDeletesPreservedOpenStates)
{
// Register an entity as container, open it, unregister it, then call clear.
// When the entity is registered again, the open state should not be preserved.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
m_containerEntityInterface->SetContainerOpen(m_entityMap[Passenger1EntityName], true);
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
m_containerEntityInterface->Clear(m_editorEntityContextId);
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[Passenger1EntityName]);
EXPECT_FALSE(isOpen);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithNoContainers)
{
// When no containers are in the way, the function will just return the entityId that was passed to it.
AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]);
EXPECT_EQ(selectedEntityId, m_entityMap[Passenger2EntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithClosedContainer)
{
// If a closed container is an ancestor of the queried entity, the closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); // Containers are closed by default
AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]);
EXPECT_EQ(selectedEntityId, m_entityMap[SportsCarEntityName]);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithOpenContainer)
{
// If an open container is an ancestor of the queried entity, it is ignored.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
m_containerEntityInterface->SetContainerOpen(m_entityMap[SportsCarEntityName], true);
AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]);
EXPECT_EQ(selectedEntityId, m_entityMap[Passenger2EntityName]);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithMultipleClosedContainers)
{
// If multiple closed containers are ancestors of the queried entity, the highest closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]);
EXPECT_EQ(selectedEntityId, m_entityMap[StreetEntityName]);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
}
TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithMultipleContainers)
{
// If multiple containers are ancestors of the queried entity, the highest closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]);
EXPECT_EQ(selectedEntityId, m_entityMap[SportsCarEntityName]);
// Restore default state for other tests.
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
}
}
@@ -14,6 +14,20 @@
namespace AzToolsFramework
{
void ClearSelectedEntities()
{
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
&AzToolsFramework::ToolsApplicationRequestBus::Events::SetSelectedEntities, AzToolsFramework::EntityIdList());
}
AzToolsFramework::EntityIdList EditorFocusModeFixture::GetSelectedEntities()
{
AzToolsFramework::EntityIdList selectedEntities;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
selectedEntities, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetSelectedEntities);
return selectedEntities;
}
void EditorFocusModeFixture::SetUpEditorFixtureImpl()
{
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
@@ -21,6 +35,9 @@ namespace AzToolsFramework
// in the unit tests.
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
m_containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get();
ASSERT_TRUE(m_containerEntityInterface != nullptr);
m_focusModeInterface = AZ::Interface<FocusModeInterface>::Get();
ASSERT_TRUE(m_focusModeInterface != nullptr);
@@ -31,6 +48,24 @@ namespace AzToolsFramework
m_editorEntityContextId, &AzToolsFramework::EditorEntityContextRequestBus::Events::GetEditorEntityContextId);
GenerateTestHierarchy();
// Clear the focus, disabling focus mode
m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
// Clear selection
ClearSelectedEntities();
}
void EditorFocusModeFixture::TearDownEditorFixtureImpl()
{
// Clear Container Entity preserved open states
m_containerEntityInterface->Clear(m_editorEntityContextId);
// Clear the focus, disabling focus mode
m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
// Clear selection
ClearSelectedEntities();
}
void EditorFocusModeFixture::GenerateTestHierarchy()
@@ -59,7 +94,7 @@ namespace AzToolsFramework
entity->Activate();
// Move the CarEntity so it's out of the way.
AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, CarEntityPosition);
AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, WorldCarEntityPosition);
// Setup the camera so the Car entity is in view.
AzFramework::SetCameraTransform(
@@ -14,6 +14,7 @@
#include <AzTest/AzTest.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
@@ -24,16 +25,20 @@ namespace AzToolsFramework
{
protected:
void SetUpEditorFixtureImpl() override;
void TearDownEditorFixtureImpl() override;
void GenerateTestHierarchy();
AZ::EntityId CreateEditorEntity(const char* name, AZ::EntityId parentId);
AZStd::unordered_map<AZStd::string, AZ::EntityId> m_entityMap;
ContainerEntityInterface* m_containerEntityInterface = nullptr;
FocusModeInterface* m_focusModeInterface = nullptr;
public:
AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull();
AzToolsFramework::EntityIdList GetSelectedEntities();
AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull();
AzFramework::CameraState m_cameraState;
inline static const AZ::Vector3 CameraPosition = AZ::Vector3(10.0f, 15.0f, 10.0f);
@@ -45,6 +50,7 @@ namespace AzToolsFramework
inline static const char* Passenger1EntityName = "Passenger1";
inline static const char* Passenger2EntityName = "Passenger2";
inline static AZ::Vector3 CarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f);
inline static AZ::Vector3 WorldCarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f);
};
}
@@ -0,0 +1,43 @@
/*
* 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
*
*/
#pragma once
#include <Tests/FocusMode/EditorFocusModeFixture.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/std/string/string.h>
#include <AzFramework/Viewport/ViewportScreen.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h>
#include <AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h>
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
#include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
#include <AzToolsFramework/Component/EditorComponentAPIBus.h>
#include <AzToolsFramework/Manipulators/LinearManipulator.h>
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
namespace AzToolsFramework
{
class EditorFocusModeSelectionFixture : public UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin<EditorFocusModeFixture>
{
public:
void ClickAtWorldPositionOnViewport(const AZ::Vector3& worldPosition)
{
// Calculate the world position in screen space
const auto carScreenPosition = AzFramework::WorldToScreen(worldPosition, m_cameraState);
// Click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp();
}
};
} // namespace AzToolsFramework
@@ -6,64 +6,14 @@
*
*/
#include <Tests/FocusMode/EditorFocusModeFixture.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/std/string/string.h>
#include <AzFramework/Viewport/ViewportScreen.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h>
#include <AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h>
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
#include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
#include <AzToolsFramework/Component/EditorComponentAPIBus.h>
#include <AzToolsFramework/Manipulators/LinearManipulator.h>
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
#include <Tests/FocusMode/EditorFocusModeSelectionFixture.h>
namespace AzToolsFramework
{
class EditorFocusModeSelectionFixture
: public UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin<EditorFocusModeFixture>
{
public:
void ClickAtWorldPositionOnViewport(const AZ::Vector3& worldPosition)
{
// Calculate the world position in screen space
const auto carScreenPosition = AzFramework::WorldToScreen(worldPosition, m_cameraState);
// Click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp();
}
};
void ClearSelectedEntities()
{
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
&AzToolsFramework::ToolsApplicationRequestBus::Events::SetSelectedEntities, AzToolsFramework::EntityIdList());
}
AzToolsFramework::EntityIdList GetSelectedEntities()
{
AzToolsFramework::EntityIdList selectedEntities;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
selectedEntities, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetSelectedEntities);
return selectedEntities;
}
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnLevel)
{
// Clear the focus, disabling focus mode
m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull());
// Clear selection
ClearSelectedEntities();
// Click on Car Entity
ClickAtWorldPositionOnViewport(CarEntityPosition);
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
@@ -75,73 +25,53 @@ namespace AzToolsFramework
{
// Set the focus on the Street Entity (parent of the test entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
// Clear selection
ClearSelectedEntities();
// Click on Car Entity
ClickAtWorldPositionOnViewport(CarEntityPosition);
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 1);
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
// Clear the focus, disabling focus mode
m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull());
}
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnItself)
{
// Set the focus on the Car Entity (test entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]);
// Clear selection
ClearSelectedEntities();
// Click on Car Entity
ClickAtWorldPositionOnViewport(CarEntityPosition);
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 1);
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
// Clear the focus, disabling focus mode
m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull());
}
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnSibling)
{
// Set the focus on the SportsCar Entity (sibling of the test entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[SportsCarEntityName]);
// Clear selection
ClearSelectedEntities();
// Click on Car Entity
ClickAtWorldPositionOnViewport(CarEntityPosition);
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 0);
// Clear the focus, disabling focus mode
m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull());
}
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnDescendant)
{
// Set the focus on the Passenger1 Entity (child of the entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]);
// Clear selection
ClearSelectedEntities();
// Click on Car Entity
ClickAtWorldPositionOnViewport(CarEntityPosition);
ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 0);
// Clear the focus, disabling focus mode
m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull());
}
}
@@ -33,55 +33,40 @@ namespace AzToolsFramework
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_AncestorsDescendants)
{
// When the focus is set to an entity, all its descendants are in the focus subtree while the ancestors aren't.
{
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
}
// Restore default expected focus.
m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
}
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Siblings)
{
// If the root entity has siblings, they are also outside of the focus subtree.
{
m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]);
m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), false);
}
// Restore default expected focus.
m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), false);
}
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Leaf)
{
// If the root is a leaf, then the focus subtree will consists of just that entity.
{
m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger2EntityName]);
m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger2EntityName]);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
}
// Restore default expected focus.
m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
}
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Clear)
@@ -90,15 +75,13 @@ namespace AzToolsFramework
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
// When the focus is cleared, the whole level is in the focus subtree; so we expect all entities to return true.
{
m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
}
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
}
}
@@ -25,7 +25,7 @@ namespace UnitTest
R"X(Executing RC.EXE: '"E:\lyengine\dev\windows\bin\profile\rc.exe" "E:/Directory/File.tga")X",
R"X(Executing RC.EXE with working directory : '')X",
R"X(ResourceCompiler 64 - bit DEBUG)X",
R"X(Platform support : PC, PowerVR, etc2Comp)X",
R"X(Platform support : PC, PowerVR)X",
R"X(Version 1.1.8.6 Nov 5 2018 13 : 28 : 28)X"
};
@@ -22,7 +22,7 @@
#include <AzCore/UserSettings/UserSettingsComponent.h>
#include <Utils/Utils.h>
namespace
namespace
{
static const int s_totalAssets = 12;
}
@@ -53,15 +53,15 @@ namespace UnitTest
m_application->Start(AzFramework::Application::Descriptor());
// 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
// 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);
// By default @assets@ is setup to include the platform at the end. But this test is going to
// By default @products@ is setup to include the platform at the end. But this test is going to
// loop over all platforms and it will be included as part of the relative path of the file.
// So the asset folder for these tests have to point to the cache project root folder, which
// doesn't include the platform.
AZ::IO::FileIOBase::GetInstance()->SetAlias("@assets@", cacheProjectRootFolder.c_str());
AZ::IO::FileIOBase::GetInstance()->SetAlias("@products@", cacheProjectRootFolder.c_str());
for (int platformNum = AzFramework::PlatformId::PC; platformNum < AzFramework::PlatformId::NumPlatformIds; ++platformNum)
{
@@ -10,6 +10,7 @@
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <Prefab/PrefabTestFixture.h>
namespace UnitTest
@@ -72,6 +73,9 @@ namespace UnitTest
m_prefabFocusInterface = AZ::Interface<PrefabFocusInterface>::Get();
ASSERT_TRUE(m_prefabFocusInterface != nullptr);
m_prefabFocusPublicInterface = AZ::Interface<PrefabFocusPublicInterface>::Get();
ASSERT_TRUE(m_prefabFocusPublicInterface != nullptr);
AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult(
m_editorEntityContextId, &AzToolsFramework::EditorEntityContextRequestBus::Events::GetEditorEntityContextId);
@@ -91,6 +95,7 @@ namespace UnitTest
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> m_rootInstance;
PrefabFocusInterface* m_prefabFocusInterface = nullptr;
PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull();
inline static const char* CityEntityName = "City";
@@ -105,7 +110,7 @@ namespace UnitTest
{
// Verify FocusOnOwningPrefab works when passing the container entity of the root prefab.
{
m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId());
m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId());
EXPECT_EQ(
m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId),
m_instanceMap[CityEntityName]->GetTemplateId());
@@ -120,7 +125,7 @@ namespace UnitTest
{
// Verify FocusOnOwningPrefab works when passing a nested entity of the root prefab.
{
m_prefabFocusInterface->FocusOnOwningPrefab(m_entityMap[CityEntityName]->GetId());
m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_entityMap[CityEntityName]->GetId());
EXPECT_EQ(
m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId),
m_instanceMap[CityEntityName]->GetTemplateId());
@@ -135,7 +140,7 @@ namespace UnitTest
{
// Verify FocusOnOwningPrefab works when passing the container entity of a nested prefab.
{
m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CarEntityName]->GetContainerEntityId());
m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[CarEntityName]->GetContainerEntityId());
EXPECT_EQ(
m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId), m_instanceMap[CarEntityName]->GetTemplateId());
@@ -149,7 +154,7 @@ namespace UnitTest
{
// Verify FocusOnOwningPrefab works when passing a nested entity of the a nested prefab.
{
m_prefabFocusInterface->FocusOnOwningPrefab(m_entityMap[Passenger1EntityName]->GetId());
m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_entityMap[Passenger1EntityName]->GetId());
EXPECT_EQ(
m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId), m_instanceMap[CarEntityName]->GetTemplateId());
@@ -169,7 +174,7 @@ namespace UnitTest
prefabEditorEntityOwnershipInterface->GetRootPrefabInstance();
EXPECT_TRUE(rootPrefabInstance.has_value());
m_prefabFocusInterface->FocusOnOwningPrefab(AZ::EntityId());
m_prefabFocusPublicInterface->FocusOnOwningPrefab(AZ::EntityId());
EXPECT_EQ(
m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId), rootPrefabInstance->get().GetTemplateId());
@@ -183,10 +188,10 @@ namespace UnitTest
{
// Verify IsOwningPrefabBeingFocused returns true for all entities in a focused prefab (container/nested)
{
m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId());
m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId());
EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId()));
EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId()));
EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId()));
EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId()));
}
}
@@ -194,13 +199,13 @@ namespace UnitTest
{
// Verify IsOwningPrefabBeingFocused returns false for all entities not in a focused prefab (ancestors/descendants)
{
m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[StreetEntityName]->GetContainerEntityId());
m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[StreetEntityName]->GetContainerEntityId());
EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[StreetEntityName]->GetContainerEntityId()));
EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId()));
EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId()));
EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId()));
EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId()));
EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[StreetEntityName]->GetContainerEntityId()));
EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId()));
EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId()));
EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId()));
EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId()));
}
}
@@ -208,12 +213,12 @@ namespace UnitTest
{
// Verify IsOwningPrefabBeingFocused returns false for all entities not in a focused prefab (siblings)
{
m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[SportsCarEntityName]->GetContainerEntityId());
m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[SportsCarEntityName]->GetContainerEntityId());
EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[SportsCarEntityName]->GetContainerEntityId()));
EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger2EntityName]->GetId()));
EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId()));
EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId()));
EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[SportsCarEntityName]->GetContainerEntityId()));
EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger2EntityName]->GetId()));
EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId()));
EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId()));
}
}
@@ -0,0 +1,173 @@
/*
* 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 <AzToolsFramework/ToolsComponents/TransformComponent.h>
#include <Entity/EntityUtilityComponent.h>
#include <Prefab/PrefabTestComponent.h>
#include <Prefab/PrefabTestDomUtils.h>
#include <Prefab/PrefabTestFixture.h>
namespace UnitTest
{
TemplateId g_globalTemplateId = {};
AZStd::string g_globalPrefabString = "";
class PrefabScriptingTest : public PrefabTestFixture
{
void InitProperties() const
{
AZ::ComponentApplicationRequests* componentApplicationRequests = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
ASSERT_NE(componentApplicationRequests, nullptr);
auto behaviorContext = componentApplicationRequests->GetBehaviorContext();
ASSERT_NE(behaviorContext, nullptr);
behaviorContext->Property("g_globalTemplateId", BehaviorValueProperty(&g_globalTemplateId));
behaviorContext->Property("g_globalPrefabString", BehaviorValueProperty(&g_globalPrefabString));
g_globalTemplateId = TemplateId{};
g_globalPrefabString = AZStd::string{};
}
void SetUpEditorFixtureImpl() override
{
InitProperties();
}
void TearDownEditorFixtureImpl() override
{
g_globalPrefabString.set_capacity(0); // Free all memory
}
};
TEST_F(PrefabScriptingTest, PrefabScripting_CreatePrefab)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
sc.Execute(R"LUA(
my_id = EntityUtilityBus.Broadcast.CreateEditorReadyEntity("test")
entities = vector_EntityId()
entities:push_back(my_id)
g_globalTemplateId = PrefabSystemScriptingBus.Broadcast.CreatePrefab(entities, "test.prefab")
)LUA");
EXPECT_NE(g_globalTemplateId, TemplateId{});
auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
ASSERT_NE(prefabSystemComponentInterface, nullptr);
TemplateReference templateRef = prefabSystemComponentInterface->FindTemplate(g_globalTemplateId);
EXPECT_TRUE(templateRef);
}
TEST_F(PrefabScriptingTest, PrefabScripting_CreatePrefab_NoEntities)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
sc.Execute(R"LUA(
my_id = EntityUtilityBus.Broadcast.CreateEditorReadyEntity("test")
entities = vector_EntityId()
g_globalTemplateId = PrefabSystemScriptingBus.Broadcast.CreatePrefab(entities, "test.prefab")
)LUA");
EXPECT_NE(g_globalTemplateId, TemplateId{});
auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
ASSERT_NE(prefabSystemComponentInterface, nullptr);
TemplateReference templateRef = prefabSystemComponentInterface->FindTemplate(g_globalTemplateId);
EXPECT_TRUE(templateRef);
}
TEST_F(PrefabScriptingTest, PrefabScripting_CreatePrefab_NoPath)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
AZ_TEST_START_TRACE_SUPPRESSION;
sc.Execute(R"LUA(
my_id = EntityUtilityBus.Broadcast.CreateEditorReadyEntity("test")
entities = vector_EntityId()
template_id = PrefabSystemScriptingBus.Broadcast.CreatePrefab(entities, "")
)LUA");
/*
error: PrefabSystemComponent::CreateTemplateFromInstance - Attempted to create a prefab template from an instance without a source file path. Unable to proceed.
error: Failed to create a Template associated with file path during CreatePrefab.
error: Failed to create prefab
*/
AZ_TEST_STOP_TRACE_SUPPRESSION(3);
}
TEST_F(PrefabScriptingTest, PrefabScripting_SaveToString)
{
AZ::ScriptContext sc;
auto behaviorContext = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->GetBehaviorContext();
sc.BindTo(behaviorContext);
sc.Execute(R"LUA(
my_id = EntityUtilityBus.Broadcast.CreateEditorReadyEntity("test")
entities = vector_EntityId()
entities:push_back(my_id)
template_id = PrefabSystemScriptingBus.Broadcast.CreatePrefab(entities, "test.prefab")
my_result = PrefabLoaderScriptingBus.Broadcast.SaveTemplateToString(template_id)
if my_result:IsSuccess() then
g_globalPrefabString = my_result:GetValue()
end
)LUA");
auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
prefabSystemComponentInterface->RemoveAllTemplates();
EXPECT_STRNE(g_globalPrefabString.c_str(), "");
TemplateId templateFromString = AZ::Interface<PrefabLoaderInterface>::Get()->LoadTemplateFromString(g_globalPrefabString);
EXPECT_NE(templateFromString, InvalidTemplateId);
// Create another entity for comparison purposes
AZ::EntityId entityId;
AzToolsFramework::EntityUtilityBus::BroadcastResult(
entityId, &AzToolsFramework::EntityUtilityBus::Events::CreateEditorReadyEntity, "test");
AZ::Entity* testEntity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
// Instantiate the prefab we saved
AZStd::unique_ptr<Instance> instance = prefabSystemComponentInterface->InstantiatePrefab(templateFromString);
EXPECT_NE(instance, nullptr);
AZStd::vector<const AZ::Entity*> loadedEntities;
// Get the entities from the instance
instance->GetConstEntities(
[&loadedEntities](const AZ::Entity& entity)
{
loadedEntities.push_back(&entity);
return true;
});
// Make sure the instance has an entity with the same number of components as our test entity
EXPECT_EQ(loadedEntities.size(), 1);
EXPECT_EQ(loadedEntities[0]->GetComponents().size(), testEntity->GetComponents().size());
g_globalPrefabString.set_capacity(0); // Free all memory
}
}
@@ -0,0 +1,135 @@
/*
* 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 <AzToolsFramework/ToolsComponents/TransformComponent.h>
#include <Entity/EntityUtilityComponent.h>
#include <Prefab/PrefabTestComponent.h>
#include <Prefab/PrefabTestDomUtils.h>
#include <Prefab/PrefabTestFixture.h>
#include <Prefab/Procedural/ProceduralPrefabAsset.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
namespace UnitTest
{
class ProceduralPrefabAssetTest
: public PrefabTestFixture
{
void SetUpEditorFixtureImpl() override
{
AZ::ComponentApplicationRequests* componentApplicationRequests = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
ASSERT_NE(componentApplicationRequests, nullptr);
auto* behaviorContext = componentApplicationRequests->GetBehaviorContext();
ASSERT_NE(behaviorContext, nullptr);
auto* jsonRegistrationContext = componentApplicationRequests->GetJsonRegistrationContext();
ASSERT_NE(jsonRegistrationContext, nullptr);
auto* serializeContext = componentApplicationRequests->GetSerializeContext();
ASSERT_NE(serializeContext, nullptr);
AZ::Prefab::ProceduralPrefabAsset::Reflect(serializeContext);
AZ::Prefab::ProceduralPrefabAsset::Reflect(behaviorContext);
AZ::Prefab::ProceduralPrefabAsset::Reflect(jsonRegistrationContext);
}
void TearDownEditorFixtureImpl() override
{
AZ::ComponentApplicationRequests* componentApplicationRequests = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
componentApplicationRequests->GetJsonRegistrationContext()->EnableRemoveReflection();
AZ::Prefab::ProceduralPrefabAsset::Reflect(componentApplicationRequests->GetJsonRegistrationContext());
}
};
TEST_F(ProceduralPrefabAssetTest, ReflectContext_AccessMethods_Works)
{
AZ::ComponentApplicationRequests* componentApplicationRequests = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
auto* serializeContext = componentApplicationRequests->GetSerializeContext();
EXPECT_TRUE(!serializeContext->CreateAny(azrtti_typeid<AZ::Prefab::ProceduralPrefabAsset>()).empty());
EXPECT_TRUE(!serializeContext->CreateAny(azrtti_typeid<AZ::Prefab::PrefabDomData>()).empty());
auto* jsonRegistrationContext = componentApplicationRequests->GetJsonRegistrationContext();
EXPECT_TRUE(jsonRegistrationContext->GetSerializerForSerializerType(azrtti_typeid<AZ::Prefab::PrefabDomDataJsonSerializer>()));
}
TEST_F(ProceduralPrefabAssetTest, ProceduralPrefabAsset_AccessMethods_Works)
{
const auto templateId = TemplateId(1);
const auto prefabString = "fake.prefab";
AZ::Prefab::ProceduralPrefabAsset asset{};
asset.SetTemplateId(templateId);
EXPECT_EQ(asset.GetTemplateId(), templateId);
asset.SetTemplateName(prefabString);
EXPECT_EQ(asset.GetTemplateName(), prefabString);
}
TEST_F(ProceduralPrefabAssetTest, PrefabDomData_AccessMethods_Works)
{
AzToolsFramework::Prefab::PrefabDom dom;
dom.SetObject();
dom.AddMember("boolValue", true, dom.GetAllocator());
AZ::Prefab::PrefabDomData prefabDomData;
prefabDomData.CopyValue(dom);
const AzToolsFramework::Prefab::PrefabDom& result = prefabDomData.GetValue();
EXPECT_TRUE(result.HasMember("boolValue"));
EXPECT_TRUE(result.FindMember("boolValue")->value.GetBool());
}
TEST_F(ProceduralPrefabAssetTest, PrefabDomDataJsonSerializer_Load_Works)
{
AZ::Prefab::PrefabDomData prefabDomData;
AzToolsFramework::Prefab::PrefabDom dom;
dom.SetObject();
dom.AddMember("member", "value", dom.GetAllocator());
AZ::Prefab::PrefabDomDataJsonSerializer prefabDomDataJsonSerializer;
AZ::JsonDeserializerSettings settings;
settings.m_reporting = [](auto, auto, auto)
{
AZ::JsonSerializationResult::ResultCode result(AZ::JsonSerializationResult::Tasks::ReadField);
return result;
};
AZ::JsonDeserializerContext context{ settings };
auto result = prefabDomDataJsonSerializer.Load(&prefabDomData, azrtti_typeid(prefabDomData), dom, context);
EXPECT_EQ(result.GetResultCode().GetOutcome(), AZ::JsonSerializationResult::Outcomes::DefaultsUsed);
EXPECT_TRUE(prefabDomData.GetValue().HasMember("member"));
EXPECT_STREQ(prefabDomData.GetValue().FindMember("member")->value.GetString(), "value");
}
TEST_F(ProceduralPrefabAssetTest, PrefabDomDataJsonSerializer_Store_Works)
{
AzToolsFramework::Prefab::PrefabDom dom;
dom.SetObject();
dom.AddMember("member", "value", dom.GetAllocator());
AZ::Prefab::PrefabDomData prefabDomData;
prefabDomData.CopyValue(dom);
AZ::Prefab::PrefabDomDataJsonSerializer prefabDomDataJsonSerializer;
AzToolsFramework::Prefab::PrefabDom outputValue;
AZ::JsonSerializerSettings settings;
settings.m_reporting = [](auto, auto, auto)
{
AZ::JsonSerializationResult::ResultCode result(AZ::JsonSerializationResult::Tasks::WriteValue);
return result;
};
AZ::JsonSerializerContext context{ settings, outputValue.GetAllocator() };
auto result = prefabDomDataJsonSerializer.Store(outputValue, &prefabDomData, nullptr, azrtti_typeid(prefabDomData), context);
EXPECT_EQ(result.GetResultCode().GetOutcome(), AZ::JsonSerializationResult::Outcomes::DefaultsUsed);
EXPECT_TRUE(outputValue.HasMember("member"));
EXPECT_STREQ(outputValue.FindMember("member")->value.GetString(), "value");
}
}
@@ -142,8 +142,6 @@ namespace UnitTest
/*
* AssetSystemRequestBus
*/
const char* GetAbsoluteDevGameFolderPath() override { return ""; }
const char* GetAbsoluteDevRootFolderPath() override { return ""; }
bool GetRelativeProductPathFromFullSourceOrProductPath([[maybe_unused]] const AZStd::string& fullPath, [[maybe_unused]] AZStd::string& relativeProductPath) override { return false; }
bool GenerateRelativeSourcePath(
[[maybe_unused]] const AZStd::string& sourcePath, [[maybe_unused]] AZStd::string& relativePath,
@@ -9,6 +9,7 @@
#include <AzTest/AzTest.h>
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h>
#include <AzToolsFramework/ViewportSelection/ViewportEditorModeTracker.h>
@@ -17,8 +18,8 @@ namespace UnitTest
using ViewportEditorMode = AzToolsFramework::ViewportEditorMode;
using ViewportEditorModes = AzToolsFramework::ViewportEditorModes;
using ViewportEditorModeTracker = AzToolsFramework::ViewportEditorModeTracker;
using ViewportEditorModeInfo = AzToolsFramework::ViewportEditorModeInfo;
using ViewportId = ViewportEditorModeInfo::IdType;
using ViewportEditorModeTrackerInfo = AzToolsFramework::ViewportEditorModeTrackerInfo;
using TrackerId = ViewportEditorModeTrackerInfo::IdType;
using ViewportEditorModesInterface = AzToolsFramework::ViewportEditorModesInterface;
using ViewportEditorModeTrackerInterface = AzToolsFramework::ViewportEditorModeTrackerInterface;
@@ -113,10 +114,10 @@ namespace UnitTest
using EditModeTracker = AZStd::unordered_map<ViewportEditorMode, ReceivedEvents>;
ViewportEditorModeNotificationsBusHandler(ViewportId viewportId)
: m_viewportSubscription(viewportId)
ViewportEditorModeNotificationsBusHandler(TrackerId id)
: m_trackerSubscription(id)
{
AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusConnect(m_viewportSubscription);
AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusConnect(m_trackerSubscription);
}
~ViewportEditorModeNotificationsBusHandler()
@@ -124,11 +125,6 @@ namespace UnitTest
AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
}
ViewportId GetViewportSubscription() const
{
return m_viewportSubscription;
}
const EditModeTracker& GetEditorModes() const
{
return m_editorModes;
@@ -145,7 +141,7 @@ namespace UnitTest
}
private:
ViewportId m_viewportSubscription;
TrackerId m_trackerSubscription;
EditModeTracker m_editorModes;
};
@@ -158,10 +154,14 @@ namespace UnitTest
void SetUpEditorFixtureImpl() override
{
m_handlerIds.resize(ViewportEditorModes::NumEditorModes);
for (auto mode = 0; mode < ViewportEditorModes::NumEditorModes; mode++)
{
m_editorModeHandlers[mode] = AZStd::make_unique<ViewportEditorModeNotificationsBusHandler>(mode);
// Create a random GUID for each handler and associate that GUID with an index derived from one of the possible editor modes
m_handlerIds[mode] = TrackerId::CreateRandom();
m_editorModeHandlers[mode] = AZStd::make_unique<ViewportEditorModeNotificationsBusHandler>(m_handlerIds[mode]);
}
}
void TearDownEditorFixtureImpl() override
@@ -173,6 +173,7 @@ namespace UnitTest
}
AZStd::array<AZStd::unique_ptr<ViewportEditorModeNotificationsBusHandler>, ViewportEditorModes::NumEditorModes> m_editorModeHandlers;
AZStd::vector<TrackerId> m_handlerIds;
};
// Fixture for testing the integration of viewport editor mode state tracker
@@ -184,7 +185,8 @@ namespace UnitTest
{
m_viewportEditorModeTracker = AZ::Interface<ViewportEditorModeTrackerInterface>::Get();
ASSERT_NE(m_viewportEditorModeTracker, nullptr);
m_viewportEditorModes = m_viewportEditorModeTracker->GetViewportEditorModes({});
m_viewportEditorModes = m_viewportEditorModeTracker->GetViewportEditorModes({AzToolsFramework::GetEntityContextId()});
ASSERT_NE(m_viewportEditorModes, nullptr);
}
ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr;
@@ -316,17 +318,17 @@ namespace UnitTest
TEST_F(ViewportEditorModeTrackerTestFixture, ActivatingViewportEditorModeForNonExistentIdCreatesViewportEditorModesForThatId)
{
// Given a viewport not currently being tracked
const ViewportId viewportid = 0;
EXPECT_FALSE(m_viewportEditorModeTracker.IsViewportModeTracked({ viewportid }));
EXPECT_EQ(m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid }), nullptr);
const TrackerId id = 0;
EXPECT_FALSE(m_viewportEditorModeTracker.IsViewportModeTracked({ id }));
EXPECT_EQ(m_viewportEditorModeTracker.GetViewportEditorModes({ id }), nullptr);
// When a mode is activated for that viewport
const auto editorMode = ViewportEditorMode::Default;
m_viewportEditorModeTracker.ActivateMode({ viewportid }, editorMode);
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid });
m_viewportEditorModeTracker.ActivateMode({ id }, editorMode);
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ id });
// Expect that viewport to now be tracked
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ viewportid }));
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ id }));
EXPECT_NE(viewportEditorModeState, nullptr);
// Expect the mode for that viewport to be active
@@ -336,23 +338,24 @@ namespace UnitTest
TEST_F(ViewportEditorModeTrackerTestFixture, DeactivatingViewportEditorModeForNonExistentIdCreatesViewportEditorModesForThatIdButReturnsError)
{
// Given a viewport not currently being tracked
const ViewportId viewportid = 0;
EXPECT_FALSE(m_viewportEditorModeTracker.IsViewportModeTracked({ viewportid }));
EXPECT_EQ(m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid }), nullptr);
const TrackerId id = 0;
EXPECT_FALSE(m_viewportEditorModeTracker.IsViewportModeTracked({ id }));
EXPECT_EQ(m_viewportEditorModeTracker.GetViewportEditorModes({ id }), nullptr);
// When a mode is deactivated for that viewport
const auto editorMode = ViewportEditorMode::Default;
const auto expectedErrorMsg = AZStd::string::format(
"Call to DeactivateMode for mode '%u' on id '%i' without precursor call to ActivateMode", static_cast<AZ::u32>(editorMode), viewportid);
const auto result = m_viewportEditorModeTracker.DeactivateMode({ viewportid }, editorMode);
"Call to DeactivateMode for mode '%u' on id '%s' without precursor call to ActivateMode", static_cast<AZ::u32>(editorMode),
id.ToString<AZStd::string>().c_str());
const auto result = m_viewportEditorModeTracker.DeactivateMode({ id }, editorMode);
// Expect an error due to no precursor activation of that mode
EXPECT_FALSE(result.IsSuccess());
EXPECT_EQ(result.GetError(), expectedErrorMsg);
// Expect that viewport to now be tracked
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid });
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ viewportid }));
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ id });
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ id }));
// Expect the mode for that viewport to be inactive
EXPECT_NE(viewportEditorModeState, nullptr);
@@ -361,45 +364,46 @@ namespace UnitTest
TEST_F(ViewportEditorModeTrackerTestFixture, GettingNonExistentViewportEditorModesForIdReturnsNull)
{
const ViewportId viewportid = 0;
EXPECT_FALSE(m_viewportEditorModeTracker.IsViewportModeTracked({ viewportid }));
EXPECT_EQ(m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid }), nullptr);
const TrackerId id = 0;
EXPECT_FALSE(m_viewportEditorModeTracker.IsViewportModeTracked({ id }));
EXPECT_EQ(m_viewportEditorModeTracker.GetViewportEditorModes({ id }), nullptr);
}
TEST_F(ViewportEditorModeTrackerTestFixture, ActivatingViewportEditorModesForExistingIdInThatStateReturnsError)
{
// Given a viewport not currently tracked
const ViewportId viewportid = 0;
EXPECT_FALSE(m_viewportEditorModeTracker.IsViewportModeTracked({ viewportid }));
EXPECT_EQ(m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid }), nullptr);
const TrackerId id = 0;
EXPECT_FALSE(m_viewportEditorModeTracker.IsViewportModeTracked({ id }));
EXPECT_EQ(m_viewportEditorModeTracker.GetViewportEditorModes({ id }), nullptr);
const auto editorMode = ViewportEditorMode::Default;
{
// When the mode is activated for the viewport
const auto result = m_viewportEditorModeTracker.ActivateMode({ viewportid }, editorMode);
const auto result = m_viewportEditorModeTracker.ActivateMode({ id }, editorMode);
// Expect no error as there is no duplicate activation
EXPECT_TRUE(result.IsSuccess());
// Expect the mode to be active for the viewport
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid });
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ viewportid }));
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ id });
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ id }));
EXPECT_NE(viewportEditorModeState, nullptr);
EXPECT_TRUE(viewportEditorModeState->IsModeActive(editorMode));
}
{
// When the mode is activated again for the viewport
const auto result = m_viewportEditorModeTracker.ActivateMode({ viewportid }, editorMode);
const auto result = m_viewportEditorModeTracker.ActivateMode({ id }, editorMode);
// Expect an error for the duplicate activation
const auto expectedErrorMsg = AZStd::string::format(
"Duplicate call to ActivateMode for mode '%u' on id '%i'", static_cast<AZ::u32>(editorMode), viewportid);
"Duplicate call to ActivateMode for mode '%u' on id '%s'", static_cast<AZ::u32>(editorMode),
id.ToString<AZStd::string>().c_str());
EXPECT_FALSE(result.IsSuccess());
EXPECT_EQ(result.GetError(), expectedErrorMsg);
// Expect the mode to still be active for the viewport
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid });
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ viewportid }));
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ id });
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ id }));
EXPECT_NE(viewportEditorModeState, nullptr);
EXPECT_TRUE(viewportEditorModeState->IsModeActive(editorMode));
}
@@ -408,38 +412,39 @@ namespace UnitTest
TEST_F(ViewportEditorModeTrackerTestFixture, DeactivatingViewportEditorModesForExistingIdNotInThatStateReturnssError)
{
// Given a viewport not currently tracked
const ViewportId viewportid = 0;
EXPECT_FALSE(m_viewportEditorModeTracker.IsViewportModeTracked({ viewportid }));
EXPECT_EQ(m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid }), nullptr);
const TrackerId id = 0;
EXPECT_FALSE(m_viewportEditorModeTracker.IsViewportModeTracked({ id }));
EXPECT_EQ(m_viewportEditorModeTracker.GetViewportEditorModes({ id }), nullptr);
const auto editorMode = ViewportEditorMode::Default;
{
// When the mode is activated and then deactivated for the viewport
m_viewportEditorModeTracker.ActivateMode({ viewportid }, editorMode);
const auto result = m_viewportEditorModeTracker.DeactivateMode({ viewportid }, editorMode);
m_viewportEditorModeTracker.ActivateMode({ id }, editorMode);
const auto result = m_viewportEditorModeTracker.DeactivateMode({ id }, editorMode);
// Expect no error as there is no duplicate deactivation
EXPECT_TRUE(result.IsSuccess());
// Expect the mode to be inctive for the viewport
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid });
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ viewportid }));
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ id });
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ id }));
EXPECT_NE(viewportEditorModeState, nullptr);
EXPECT_FALSE(viewportEditorModeState->IsModeActive(editorMode));
}
{
// When the mode is deactivated again for the viewport
const auto result = m_viewportEditorModeTracker.DeactivateMode({ viewportid }, editorMode);
const auto result = m_viewportEditorModeTracker.DeactivateMode({ id }, editorMode);
// Expect an error for the duplicate deactivation
const auto expectedErrorMsg = AZStd::string::format(
"Duplicate call to DeactivateMode for mode '%u' on id '%i'", static_cast<AZ::u32>(editorMode), viewportid);
"Duplicate call to DeactivateMode for mode '%u' on id '%s'", static_cast<AZ::u32>(editorMode),
id.ToString<AZStd::string>().c_str());
EXPECT_FALSE(result.IsSuccess());
EXPECT_EQ(result.GetError(), expectedErrorMsg);
// Expect the mode to still be inactive for the viewport
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ viewportid });
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ viewportid }));
const auto* viewportEditorModeState = m_viewportEditorModeTracker.GetViewportEditorModes({ id });
EXPECT_TRUE(m_viewportEditorModeTracker.IsViewportModeTracked({ id }));
EXPECT_NE(viewportEditorModeState, nullptr);
EXPECT_FALSE(viewportEditorModeState->IsModeActive(editorMode));
}
@@ -459,9 +464,9 @@ namespace UnitTest
// When each editor mode is activated by the state tracker for a specific viewport
for (auto mode = 0; mode < ViewportEditorModes::NumEditorModes; mode++)
{
const ViewportId viewportId = mode;
const TrackerId id = m_handlerIds[mode];
const ViewportEditorMode editorMode = static_cast<ViewportEditorMode>(mode);
m_viewportEditorModeTracker.ActivateMode({ viewportId }, editorMode);
m_viewportEditorModeTracker.ActivateMode({ id }, editorMode);
}
for (auto mode = 0; mode < ViewportEditorModes::NumEditorModes; mode++)
@@ -491,10 +496,10 @@ namespace UnitTest
// When each editor mode is activated deactivated by the state tracker for a specific viewport
for (auto mode = 0; mode < ViewportEditorModes::NumEditorModes; mode++)
{
const ViewportId viewportId = mode;
const TrackerId id = m_handlerIds[mode];
const ViewportEditorMode editorMode = static_cast<ViewportEditorMode>(mode);
m_viewportEditorModeTracker.ActivateMode({ viewportId }, editorMode);
m_viewportEditorModeTracker.DeactivateMode({ viewportId }, editorMode);
m_viewportEditorModeTracker.ActivateMode({ id }, editorMode);
m_viewportEditorModeTracker.DeactivateMode({ id }, editorMode);
}
for (auto mode = 0; mode < ViewportEditorModes::NumEditorModes; mode++)
@@ -27,6 +27,7 @@ set(FILES
Entity/EditorEntityHelpersTests.cpp
Entity/EditorEntitySearchComponentTests.cpp
Entity/EditorEntitySelectionTests.cpp
Entity/EntityUtilityComponentTests.cpp
EntityIdQLabelTests.cpp
EntityInspectorTests.cpp
EntityOwnershipService/EntityOwnershipServiceTestFixture.cpp
@@ -36,8 +37,11 @@ set(FILES
EntityTestbed.h
FileFunc.cpp
FingerprintingTests.cpp
FocusMode/ContainerEntitySelectionTests.cpp
FocusMode/ContainerEntityTests.cpp
FocusMode/EditorFocusModeFixture.cpp
FocusMode/EditorFocusModeFixture.h
FocusMode/EditorFocusModeSelectionFixture.h
FocusMode/EditorFocusModeSelectionTests.cpp
FocusMode/EditorFocusModeTests.cpp
GenericComponentWrapperTest.cpp
@@ -91,6 +95,8 @@ set(FILES
Prefab/SpawnableSortEntitiesTestFixture.cpp
Prefab/SpawnableSortEntitiesTestFixture.h
Prefab/SpawnableSortEntitiesTests.cpp
Prefab/PrefabScriptingTests.cpp
Prefab/ProceduralPrefabAssetTests.cpp
PropertyIntCtrlCommonTests.h
PropertyIntSliderCtrlTests.cpp
PropertyIntSpinCtrlTests.cpp