Procedural Prefabs: Stable transform component ID (#6227)

* Set Procedural Prefab Transform ComponentId to the hash of the file path.

Procedural prefabs needs to have a deterministic transform component ID in order for saved patches still work when the prefab is regenerated.

Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com>

* Switch to Cityhash instead of XXHash since prefab system is using that elsewhere

Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com>

* Added unit test

Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com>

* Fix missing include

Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com>
This commit is contained in:
amzn-mike
2021-12-10 13:20:31 -06:00
committed by GitHub
parent ca49eedc5f
commit 8f134a82d1
2 changed files with 55 additions and 8 deletions
@@ -10,6 +10,7 @@
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Utils/TypeHash.h>
#include <AzToolsFramework/ToolsComponents/EditorLockComponent.h>
#include <AzToolsFramework/ToolsComponents/EditorVisibilityComponent.h>
#include <Prefab/PrefabSystemComponentInterface.h>
@@ -73,12 +74,24 @@ namespace AzToolsFramework::Prefab
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(result, &AzToolsFramework::ToolsApplicationRequestBus::Events::FindCommonRootInactive,
entities, commonRoot, &topLevelEntities);
auto containerEntity = AZStd::make_unique<AZ::Entity>();
containerEntity->CreateComponent<Components::TransformComponent>();
containerEntity->CreateComponent<Components::EditorLockComponent>();
containerEntity->CreateComponent<Components::EditorVisibilityComponent>();
containerEntity->CreateComponent<Prefab::EditorPrefabComponent>();
{
auto transformComponent = containerEntity->CreateComponent<Components::TransformComponent>();
// Because procedural prefabs need to be deterministic we need to set the component ID to something unique and non-random
// The prefab that references the proc prefab will store a patch that references the transform component by it's component ID
// If this ID is not stable, the proc prefab will lose its position, parenting, etc data next time it is regenerated
auto hash = TypeHash64(reinterpret_cast<const uint8_t*>(filePath.data()), filePath.length(), AZ::HashValue64{0});
transformComponent->SetId(static_cast<AZ::ComponentId>(hash));
}
for (AZ::Entity* entity : topLevelEntities)
{
AzToolsFramework::Components::TransformComponent* transformComponent =
@@ -92,7 +105,7 @@ namespace AzToolsFramework::Prefab
auto prefab = m_prefabSystemComponentInterface->CreatePrefab(
entities, {}, AZ::IO::PathView(AZStd::string_view(filePath)), AZStd::move(containerEntity));
if (!prefab)
{
AZ_Error("PrefabSystemComponenent", false, "Failed to create prefab %s", filePath.c_str());