You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
10 KiB
C++
303 lines
10 KiB
C++
/*
|
|
* 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/IO/FileIO.h>
|
|
#include <AzCore/IO/Path/PathReflect.h>
|
|
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
|
|
#include <AzCore/Serialization/Json/RegistrationContext.h>
|
|
#include <AzCore/Settings/SettingsRegistryImpl.h>
|
|
#include <AzFramework/IO/LocalFileIO.h>
|
|
#include <Prefab/PrefabTestFixture.h>
|
|
#include <Prefab/ProceduralPrefabSystemComponent.h>
|
|
#include <Utils/Utils.h>
|
|
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
|
|
|
namespace UnitTest
|
|
{
|
|
struct ProceduralPrefabSystemComponentTests
|
|
: AllocatorsTestFixture
|
|
, AZ::ComponentApplicationBus::Handler
|
|
{
|
|
void SetUp() override
|
|
{
|
|
TestRunner::Instance().m_suppressOutput = false;
|
|
TestRunner::Instance().m_suppressPrintf = false;
|
|
TestRunner::Instance().m_suppressWarnings = false;
|
|
TestRunner::Instance().m_suppressErrors = false;
|
|
TestRunner::Instance().m_suppressAsserts = false;
|
|
|
|
AllocatorsTestFixture::SetUp();
|
|
|
|
AZ::ComponentApplicationBus::Handler::BusConnect();
|
|
|
|
ASSERT_TRUE(m_temporaryDirectory.IsValid());
|
|
|
|
m_localFileIo = AZStd::make_unique<AZ::IO::LocalFileIO>();
|
|
|
|
m_prevIoBase = AZ::IO::FileIOBase::GetInstance();
|
|
AZ::IO::FileIOBase::SetInstance(nullptr); // Need to clear the previous instance first
|
|
AZ::IO::FileIOBase::SetInstance(m_localFileIo.get());
|
|
|
|
AZ::JsonSystemComponent::Reflect(&m_jsonContext);
|
|
|
|
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
|
|
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
|
|
|
|
m_settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath, m_temporaryDirectory.GetDirectory());
|
|
|
|
m_prefabSystem = PrefabSystemComponent::CreateDescriptor();
|
|
m_procSystem = ProceduralPrefabSystemComponent::CreateDescriptor();
|
|
|
|
m_prefabSystem->Reflect(&m_context);
|
|
m_prefabSystem->Reflect(&m_jsonContext);
|
|
m_procSystem->Reflect(&m_context);
|
|
m_procSystem->Reflect(&m_jsonContext);
|
|
|
|
AZ::Entity::Reflect(&m_context);
|
|
AZ::Entity::Reflect(&m_jsonContext);
|
|
AZ::IO::PathReflect(&m_context);
|
|
|
|
m_systemEntity = AZStd::make_unique<AZ::Entity>();
|
|
m_systemEntity->CreateComponent<PrefabSystemComponent>();
|
|
m_systemEntity->CreateComponent<ProceduralPrefabSystemComponent>();
|
|
|
|
m_systemEntity->Init();
|
|
m_systemEntity->Activate();
|
|
|
|
AZ::Data::AssetManager::Create({});
|
|
}
|
|
|
|
void TearDown() override
|
|
{
|
|
AZ::Data::AssetManager::Destroy();
|
|
|
|
m_systemEntity->Deactivate();
|
|
m_systemEntity = nullptr;
|
|
|
|
m_jsonContext.EnableRemoveReflection();
|
|
AZ::JsonSystemComponent::Reflect(&m_jsonContext);
|
|
m_prefabSystem->Reflect(&m_jsonContext);
|
|
m_procSystem->Reflect(&m_jsonContext);
|
|
AZ::Entity::Reflect(&m_jsonContext);
|
|
m_jsonContext.DisableRemoveReflection();
|
|
|
|
AZ::IO::FileIOBase::SetInstance(nullptr); // Clear the previous instance first
|
|
AZ::IO::FileIOBase::SetInstance(m_prevIoBase);
|
|
|
|
m_prevIoBase = nullptr;
|
|
|
|
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
|
|
|
|
AZ::ComponentApplicationBus::Handler::BusDisconnect();
|
|
AllocatorsTestFixture::TearDown();
|
|
|
|
TestRunner::Instance().ResetSuppressionSettingsToDefault();
|
|
}
|
|
|
|
// ComponentApplicationBus
|
|
AZ::ComponentApplication* GetApplication() override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
void RegisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
|
|
void UnregisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
|
|
void RegisterEntityAddedEventHandler(AZ::EntityAddedEvent::Handler&) override { }
|
|
void RegisterEntityRemovedEventHandler(AZ::EntityRemovedEvent::Handler&) override { }
|
|
void RegisterEntityActivatedEventHandler(AZ::EntityActivatedEvent::Handler&) override { }
|
|
void RegisterEntityDeactivatedEventHandler(AZ::EntityDeactivatedEvent::Handler&) override { }
|
|
void SignalEntityActivated(AZ::Entity*) override { }
|
|
void SignalEntityDeactivated(AZ::Entity*) override { }
|
|
|
|
bool AddEntity(AZ::Entity*) override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool RemoveEntity(AZ::Entity*) override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool DeleteEntity(const AZ::EntityId&) override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
AZ::Entity* FindEntity(const AZ::EntityId&) override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
AZ::SerializeContext* GetSerializeContext() override
|
|
{
|
|
return &m_context;
|
|
}
|
|
|
|
AZ::BehaviorContext* GetBehaviorContext() override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
AZ::JsonRegistrationContext* GetJsonRegistrationContext() override
|
|
{
|
|
return &m_jsonContext;
|
|
}
|
|
|
|
const char* GetEngineRoot() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
const char* GetExecutableFolder() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
void EnumerateEntities(const EntityCallback& /*callback*/) override { }
|
|
void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override { }
|
|
////
|
|
|
|
AZ::ComponentDescriptor* m_prefabSystem{};
|
|
AZ::ComponentDescriptor* m_procSystem{};
|
|
AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
|
|
AZ::SerializeContext m_context;
|
|
AZ::JsonRegistrationContext m_jsonContext;
|
|
AZStd::unique_ptr<AZ::IO::LocalFileIO> m_localFileIo;
|
|
ScopedTemporaryDirectory m_temporaryDirectory;
|
|
AZStd::unique_ptr<AZ::Entity> m_systemEntity;
|
|
|
|
AZ::IO::FileIOBase* m_prevIoBase{};
|
|
};
|
|
|
|
struct MockCatalog : AZ::Data::AssetCatalogRequestBus::Handler
|
|
{
|
|
static const inline AZ::Data::AssetId TestId{ AZ::Uuid::CreateRandom(), 1234 };
|
|
|
|
MockCatalog(AZStd::string testFile)
|
|
: m_testFile(AZStd::move(testFile))
|
|
{
|
|
BusConnect();
|
|
}
|
|
|
|
~MockCatalog() override
|
|
{
|
|
BusDisconnect();
|
|
}
|
|
|
|
AZStd::string GetAssetPathById(const AZ::Data::AssetId& assetId) override
|
|
{
|
|
if (assetId == TestId)
|
|
{
|
|
return m_testFile;
|
|
}
|
|
|
|
return "InvalidAssetId";
|
|
}
|
|
|
|
AZ::Data::AssetId GetAssetIdByPath(const char* path, const AZ::Data::AssetType&, bool) override
|
|
{
|
|
AZ::IO::PathView pathView{ AZStd::string_view(path) };
|
|
|
|
if (AZ::IO::PathView(m_testFile) == pathView)
|
|
{
|
|
return TestId;
|
|
}
|
|
|
|
AZ_Error("MockCatalog", false, "Requested path %s does not match expected asset path of %s", path, m_testFile.c_str());
|
|
ADD_FAILURE();
|
|
|
|
return {};
|
|
}
|
|
|
|
AZStd::string m_testFile;
|
|
};
|
|
|
|
struct PrefabPublicNotificationsListener : PrefabPublicNotificationBus::Handler
|
|
{
|
|
PrefabPublicNotificationsListener()
|
|
{
|
|
BusConnect();
|
|
}
|
|
|
|
~PrefabPublicNotificationsListener() override
|
|
{
|
|
BusDisconnect();
|
|
}
|
|
|
|
void OnPrefabInstancePropagationBegin() override
|
|
{
|
|
m_updated = true;
|
|
}
|
|
|
|
bool m_updated = false;
|
|
};
|
|
|
|
TEST_F(ProceduralPrefabSystemComponentTests, RegisteredPrefabUpdates)
|
|
{
|
|
const AZStd::string prefabFile = (AZ::IO::Path(m_temporaryDirectory.GetDirectory()) / "test.prefab").Native();
|
|
MockCatalog catalog(prefabFile.c_str());
|
|
|
|
auto proceduralPrefabSystemComponentInterface = AZ::Interface<ProceduralPrefabSystemComponentInterface>::Get();
|
|
auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
|
|
auto prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
|
|
|
|
ASSERT_NE(proceduralPrefabSystemComponentInterface, nullptr);
|
|
ASSERT_NE(prefabSystemComponentInterface, nullptr);
|
|
ASSERT_NE(prefabLoaderInterface, nullptr);
|
|
|
|
auto entity = aznew AZ::Entity();
|
|
|
|
AZStd::unique_ptr<Instance> instance = prefabSystemComponentInterface->CreatePrefab({ entity }, {}, prefabFile.c_str());
|
|
|
|
ASSERT_NE(instance, nullptr);
|
|
|
|
prefabLoaderInterface->SaveTemplateToFile(instance->GetTemplateId(), prefabFile.c_str());
|
|
|
|
proceduralPrefabSystemComponentInterface->RegisterProceduralPrefab(prefabFile, instance->GetTemplateId());
|
|
|
|
AzFramework::AssetCatalogEventBus::Broadcast(&AzFramework::AssetCatalogEventBus::Events::OnCatalogAssetChanged, MockCatalog::TestId);
|
|
|
|
PrefabPublicNotificationsListener listener;
|
|
AZ::SystemTickBus::Broadcast(&AZ::SystemTickBus::Events::OnSystemTick);
|
|
|
|
EXPECT_TRUE(listener.m_updated);
|
|
}
|
|
|
|
TEST_F(ProceduralPrefabSystemComponentTests, UnregisteredPrefabDoesNotUpdate)
|
|
{
|
|
PrefabPublicNotificationsListener listener;
|
|
|
|
const AZStd::string prefabFile = (AZ::IO::Path(m_temporaryDirectory.GetDirectory()) / "test.prefab").Native();
|
|
MockCatalog catalog(prefabFile.c_str());
|
|
|
|
auto proceduralPrefabSystemComponentInterface = AZ::Interface<ProceduralPrefabSystemComponentInterface>::Get();
|
|
auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
|
|
auto prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
|
|
|
|
ASSERT_NE(proceduralPrefabSystemComponentInterface, nullptr);
|
|
ASSERT_NE(prefabSystemComponentInterface, nullptr);
|
|
ASSERT_NE(prefabLoaderInterface, nullptr);
|
|
|
|
auto entity = aznew AZ::Entity();
|
|
|
|
AZStd::unique_ptr<Instance> instance = prefabSystemComponentInterface->CreatePrefab({ entity }, {}, prefabFile.c_str());
|
|
|
|
ASSERT_NE(instance, nullptr);
|
|
|
|
prefabLoaderInterface->SaveTemplateToFile(instance->GetTemplateId(), prefabFile.c_str());
|
|
|
|
AzFramework::AssetCatalogEventBus::Broadcast(
|
|
&AzFramework::AssetCatalogEventBus::Events::OnCatalogAssetChanged, MockCatalog::TestId);
|
|
|
|
AZ::SystemTickBus::Broadcast(&AZ::SystemTickBus::Events::OnSystemTick);
|
|
|
|
EXPECT_FALSE(listener.m_updated);
|
|
}
|
|
}
|