Update storage of Prefab Dom info to be best effort (#2862)
* Update storage of Prefab Dom info to be best effort Signed-off-by: sconel <sconel@amazon.com> * Update IssueReporter to Skipped instead of PartialSkip Signed-off-by: sconel <sconel@amazon.com> * Address PR feedback Signed-off-by: sconel <sconel@amazon.com> * Fix failing Prefab Unit Test that expected default values to be stripped Signed-off-by: sconel <sconel@amazon.com>
This commit is contained in:
+5
-15
@@ -46,7 +46,6 @@ namespace AzToolsFramework
|
||||
|
||||
bool InstanceToTemplatePropagator::GenerateDomForEntity(PrefabDom& generatedEntityDom, const AZ::Entity& entity)
|
||||
{
|
||||
//grab the owning instance so we can use the entityIdMapper in settings
|
||||
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entity.GetId());
|
||||
|
||||
if (!owningInstance)
|
||||
@@ -54,19 +53,8 @@ namespace AzToolsFramework
|
||||
AZ_Error("Prefab", false, "Entity does not belong to an instance");
|
||||
return false;
|
||||
}
|
||||
|
||||
InstanceEntityIdMapper entityIdMapper;
|
||||
entityIdMapper.SetStoringInstance(owningInstance->get());
|
||||
|
||||
//create settings so that the serialized entity dom undergoes mapping from entity id to entity alias
|
||||
AZ::JsonSerializerSettings settings;
|
||||
settings.m_metadata.Add(static_cast<AZ::JsonEntityIdSerializer::JsonEntityIdMapper*>(&entityIdMapper));
|
||||
|
||||
//generate PrefabDom using Json serialization system
|
||||
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::Store(
|
||||
generatedEntityDom, generatedEntityDom.GetAllocator(), entity, settings);
|
||||
|
||||
return result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success;
|
||||
return PrefabDomUtils::StoreEntityInPrefabDomFormat(entity, owningInstance->get(), generatedEntityDom);
|
||||
}
|
||||
|
||||
bool InstanceToTemplatePropagator::GenerateDomForInstance(PrefabDom& generatedInstanceDom, const Prefab::Instance& instance)
|
||||
@@ -185,8 +173,10 @@ namespace AzToolsFramework
|
||||
else
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip,
|
||||
"Some of the patches are not successfully applied.");
|
||||
"Prefab",
|
||||
(result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::Skipped) &&
|
||||
(result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip),
|
||||
"Some of the patches were not successfully applied.");
|
||||
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true);
|
||||
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId, instanceToExclude);
|
||||
return true;
|
||||
|
||||
@@ -196,7 +196,8 @@ namespace AzToolsFramework
|
||||
m_sourceTemplateId, m_targetTemplateId);
|
||||
return false;
|
||||
}
|
||||
if (applyPatchResult.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip)
|
||||
if (applyPatchResult.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip ||
|
||||
applyPatchResult.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Skipped)
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", false,
|
||||
|
||||
@@ -26,6 +26,30 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace PrefabDomUtils
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
AZ::JsonSerializationResult::ResultCode JsonIssueReporter(AZStd::string& scratchBuffer,
|
||||
AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
if (result.GetProcessing() == JSR::Processing::Halted)
|
||||
{
|
||||
scratchBuffer.append(message.begin(), message.end());
|
||||
scratchBuffer.append("\n Reason: ");
|
||||
result.AppendToString(scratchBuffer, path);
|
||||
scratchBuffer.append(".");
|
||||
AZ_Warning("Prefab Serialization", false, "%s", scratchBuffer.c_str());
|
||||
|
||||
scratchBuffer.clear();
|
||||
|
||||
return JSR::ResultCode(result.GetTask(), JSR::Outcomes::Skipped);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
PrefabDomValueReference FindPrefabDomValue(PrefabDomValue& parentValue, const char* valueName)
|
||||
{
|
||||
PrefabDomValue::MemberIterator valueIterator = parentValue.FindMember(valueName);
|
||||
@@ -48,7 +72,7 @@ namespace AzToolsFramework
|
||||
return valueIterator->value;
|
||||
}
|
||||
|
||||
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreInstanceFlags flags)
|
||||
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreFlags flags)
|
||||
{
|
||||
InstanceEntityIdMapper entityIdMapper;
|
||||
entityIdMapper.SetStoringInstance(instance);
|
||||
@@ -59,11 +83,21 @@ namespace AzToolsFramework
|
||||
settings.m_metadata.Add(static_cast<AZ::JsonEntityIdSerializer::JsonEntityIdMapper*>(&entityIdMapper));
|
||||
settings.m_metadata.Add(&entityIdMapper);
|
||||
|
||||
if ((flags & StoreInstanceFlags::StripDefaultValues) != StoreInstanceFlags::StripDefaultValues)
|
||||
if ((flags & StoreFlags::StripDefaultValues) != StoreFlags::StripDefaultValues)
|
||||
{
|
||||
settings.m_keepDefaults = true;
|
||||
}
|
||||
|
||||
AZStd::string scratchBuffer;
|
||||
auto issueReportingCallback = [&scratchBuffer]
|
||||
(AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result,
|
||||
AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode
|
||||
{
|
||||
return Internal::JsonIssueReporter(scratchBuffer, message, result, path);
|
||||
};
|
||||
|
||||
settings.m_reporting = AZStd::move(issueReportingCallback);
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode result =
|
||||
AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings);
|
||||
|
||||
@@ -80,7 +114,38 @@ namespace AzToolsFramework
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadInstanceFromPrefabDom(Instance& instance, const PrefabDom& prefabDom, LoadInstanceFlags flags)
|
||||
bool StoreEntityInPrefabDomFormat(const AZ::Entity& entity, Instance& owningInstance, PrefabDom& prefabDom, StoreFlags flags)
|
||||
{
|
||||
InstanceEntityIdMapper entityIdMapper;
|
||||
entityIdMapper.SetStoringInstance(owningInstance);
|
||||
|
||||
//create settings so that the serialized entity dom undergoes mapping from entity id to entity alias
|
||||
AZ::JsonSerializerSettings settings;
|
||||
settings.m_metadata.Add(static_cast<AZ::JsonEntityIdSerializer::JsonEntityIdMapper*>(&entityIdMapper));
|
||||
|
||||
if ((flags & StoreFlags::StripDefaultValues) != StoreFlags::StripDefaultValues)
|
||||
{
|
||||
settings.m_keepDefaults = true;
|
||||
}
|
||||
|
||||
AZStd::string scratchBuffer;
|
||||
auto issueReportingCallback = [&scratchBuffer]
|
||||
(AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result,
|
||||
AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode
|
||||
{
|
||||
return Internal::JsonIssueReporter(scratchBuffer, message, result, path);
|
||||
};
|
||||
|
||||
settings.m_reporting = AZStd::move(issueReportingCallback);
|
||||
|
||||
//generate PrefabDom using Json serialization system
|
||||
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::Store(
|
||||
prefabDom, prefabDom.GetAllocator(), entity, settings);
|
||||
|
||||
return result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success;
|
||||
}
|
||||
|
||||
bool LoadInstanceFromPrefabDom(Instance& instance, const PrefabDom& prefabDom, LoadFlags flags)
|
||||
{
|
||||
// When entities are rebuilt they are first destroyed. As a result any assets they were exclusively holding on to will
|
||||
// be released and reloaded once the entities are built up again. By suspending asset release temporarily the asset reload
|
||||
@@ -89,7 +154,7 @@ namespace AzToolsFramework
|
||||
|
||||
InstanceEntityIdMapper entityIdMapper;
|
||||
entityIdMapper.SetLoadingInstance(instance);
|
||||
if ((flags & LoadInstanceFlags::AssignRandomEntityId) == LoadInstanceFlags::AssignRandomEntityId)
|
||||
if ((flags & LoadFlags::AssignRandomEntityId) == LoadFlags::AssignRandomEntityId)
|
||||
{
|
||||
entityIdMapper.SetEntityIdGenerationApproach(InstanceEntityIdMapper::EntityIdGenerationApproach::Random);
|
||||
}
|
||||
@@ -119,7 +184,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
bool LoadInstanceFromPrefabDom(
|
||||
Instance& instance, const PrefabDom& prefabDom, AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets, LoadInstanceFlags flags)
|
||||
Instance& instance, const PrefabDom& prefabDom, AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets, LoadFlags flags)
|
||||
{
|
||||
// When entities are rebuilt they are first destroyed. As a result any assets they were exclusively holding on to will
|
||||
// be released and reloaded once the entities are built up again. By suspending asset release temporarily the asset reload
|
||||
@@ -128,7 +193,7 @@ namespace AzToolsFramework
|
||||
|
||||
InstanceEntityIdMapper entityIdMapper;
|
||||
entityIdMapper.SetLoadingInstance(instance);
|
||||
if ((flags & LoadInstanceFlags::AssignRandomEntityId) == LoadInstanceFlags::AssignRandomEntityId)
|
||||
if ((flags & LoadFlags::AssignRandomEntityId) == LoadFlags::AssignRandomEntityId)
|
||||
{
|
||||
entityIdMapper.SetEntityIdGenerationApproach(InstanceEntityIdMapper::EntityIdGenerationApproach::Random);
|
||||
}
|
||||
@@ -161,7 +226,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
bool LoadInstanceFromPrefabDom(
|
||||
Instance& instance, Instance::EntityList& newlyAddedEntities, const PrefabDom& prefabDom, LoadInstanceFlags flags)
|
||||
Instance& instance, Instance::EntityList& newlyAddedEntities, const PrefabDom& prefabDom, LoadFlags flags)
|
||||
{
|
||||
// When entities are rebuilt they are first destroyed. As a result any assets they were exclusively holding on to will
|
||||
// be released and reloaded once the entities are built up again. By suspending asset release temporarily the asset reload
|
||||
@@ -170,7 +235,7 @@ namespace AzToolsFramework
|
||||
|
||||
InstanceEntityIdMapper entityIdMapper;
|
||||
entityIdMapper.SetLoadingInstance(instance);
|
||||
if ((flags & LoadInstanceFlags::AssignRandomEntityId) == LoadInstanceFlags::AssignRandomEntityId)
|
||||
if ((flags & LoadFlags::AssignRandomEntityId) == LoadFlags::AssignRandomEntityId)
|
||||
{
|
||||
entityIdMapper.SetEntityIdGenerationApproach(InstanceEntityIdMapper::EntityIdGenerationApproach::Random);
|
||||
}
|
||||
@@ -240,15 +305,12 @@ namespace AzToolsFramework
|
||||
AZ::JsonSerializationResult::ResultCode ApplyPatches(
|
||||
PrefabDomValue& prefabDomToApplyPatchesOn, PrefabDom::AllocatorType& allocator, const PrefabDomValue& patches)
|
||||
{
|
||||
auto issueReportingCallback = [](AZStd::string_view, AZ::JsonSerializationResult::ResultCode result,
|
||||
AZStd::string_view) -> AZ::JsonSerializationResult::ResultCode
|
||||
AZStd::string scratchBuffer;
|
||||
auto issueReportingCallback = [&scratchBuffer]
|
||||
(AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result,
|
||||
AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
if (result.GetProcessing() == Processing::Halted)
|
||||
{
|
||||
return ResultCode(result.GetTask(), Outcomes::PartialSkip);
|
||||
}
|
||||
return result;
|
||||
return Internal::JsonIssueReporter(scratchBuffer, message, result, path);
|
||||
};
|
||||
|
||||
AZ::JsonApplyPatchSettings applyPatchSettings;
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace AzToolsFramework
|
||||
PrefabDomValueReference FindPrefabDomValue(PrefabDomValue& parentValue, const char* valueName);
|
||||
PrefabDomValueConstReference FindPrefabDomValue(const PrefabDomValue& parentValue, const char* valueName);
|
||||
|
||||
enum class StoreInstanceFlags : uint8_t
|
||||
enum class StoreFlags : uint8_t
|
||||
{
|
||||
//! No flags used during the call to LoadInstanceFromPrefabDom.
|
||||
None = 0,
|
||||
@@ -47,7 +47,7 @@ namespace AzToolsFramework
|
||||
//! such as saving to disk, this flag will control that behavior.
|
||||
StripDefaultValues = 1 << 0
|
||||
};
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(StoreInstanceFlags);
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(StoreFlags);
|
||||
|
||||
/**
|
||||
* Stores a valid Prefab Instance within a Prefab Dom. Useful for generating Templates
|
||||
@@ -56,9 +56,21 @@ namespace AzToolsFramework
|
||||
* @param flags Controls behavior such as whether to store default values
|
||||
* @return bool on whether the operation succeeded
|
||||
*/
|
||||
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreInstanceFlags flags = StoreInstanceFlags::None);
|
||||
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreFlags flags = StoreFlags::None);
|
||||
|
||||
enum class LoadInstanceFlags : uint8_t
|
||||
/**
|
||||
* Stores a valid entity in Prefab Dom format.
|
||||
* @param entity The entity to store
|
||||
* @param owningInstance The instance owning the passed in entity.
|
||||
* Used for contextualizing the entity's place in a Prefab hierarchy.
|
||||
* @param prefabDom The prefabDom that will be used to store the entity data
|
||||
* @param flags controls behavior such as whether to store default values
|
||||
* @return bool on whether the operation succeeded
|
||||
*/
|
||||
bool StoreEntityInPrefabDomFormat(const AZ::Entity& entity, Instance& owningInstance, PrefabDom& prefabDom,
|
||||
StoreFlags flags = StoreFlags::None);
|
||||
|
||||
enum class LoadFlags : uint8_t
|
||||
{
|
||||
//! No flags used during the call to LoadInstanceFromPrefabDom.
|
||||
None = 0,
|
||||
@@ -66,7 +78,7 @@ namespace AzToolsFramework
|
||||
//! unique, e.g. when they are duplicates of live entities, this flag will assign them a random new id.
|
||||
AssignRandomEntityId = 1 << 0
|
||||
};
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(LoadInstanceFlags);
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(LoadFlags);
|
||||
|
||||
/**
|
||||
* Loads a valid Prefab Instance from a Prefab Dom. Useful for generating Instances.
|
||||
@@ -76,7 +88,7 @@ namespace AzToolsFramework
|
||||
* @return bool on whether the operation succeeded.
|
||||
*/
|
||||
bool LoadInstanceFromPrefabDom(
|
||||
Instance& instance, const PrefabDom& prefabDom, LoadInstanceFlags flags = LoadInstanceFlags::None);
|
||||
Instance& instance, const PrefabDom& prefabDom, LoadFlags flags = LoadFlags::None);
|
||||
|
||||
/**
|
||||
* Loads a valid Prefab Instance from a Prefab Dom. Useful for generating Instances.
|
||||
@@ -88,7 +100,7 @@ namespace AzToolsFramework
|
||||
*/
|
||||
bool LoadInstanceFromPrefabDom(
|
||||
Instance& instance, const PrefabDom& prefabDom, AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets,
|
||||
LoadInstanceFlags flags = LoadInstanceFlags::None);
|
||||
LoadFlags flags = LoadFlags::None);
|
||||
|
||||
/**
|
||||
* Loads a valid Prefab Instance from a Prefab Dom. Useful for generating Instances.
|
||||
@@ -101,7 +113,7 @@ namespace AzToolsFramework
|
||||
*/
|
||||
bool LoadInstanceFromPrefabDom(
|
||||
Instance& instance, Instance::EntityList& newlyAddedEntities, const PrefabDom& prefabDom,
|
||||
LoadInstanceFlags flags = LoadInstanceFlags::None);
|
||||
LoadFlags flags = LoadFlags::None);
|
||||
|
||||
inline PrefabDomPath GetPrefabDomInstancePath(const char* instanceName)
|
||||
{
|
||||
|
||||
@@ -328,7 +328,7 @@ namespace AzToolsFramework
|
||||
|
||||
PrefabDom storedPrefabDom(&savingTemplateDom->get().GetAllocator());
|
||||
if (!PrefabDomUtils::StoreInstanceInPrefabDom(savingPrefabInstance, storedPrefabDom,
|
||||
PrefabDomUtils::StoreInstanceFlags::StripDefaultValues))
|
||||
PrefabDomUtils::StoreFlags::StripDefaultValues))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -266,8 +266,8 @@ namespace AzToolsFramework
|
||||
|
||||
AZ_Error(
|
||||
"Prefab",
|
||||
result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip ||
|
||||
result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success,
|
||||
(result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::Skipped) &&
|
||||
(result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip),
|
||||
"Some of the patches are not successfully applied.");
|
||||
|
||||
//remove the link id placed into the instance
|
||||
|
||||
+1
-1
@@ -513,7 +513,7 @@ exportComponent, prefabProcessorContext);
|
||||
// convert Prefab DOM into Prefab Instance.
|
||||
AZStd::unique_ptr<Instance> instance(aznew Instance());
|
||||
if (!Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*instance, prefab,
|
||||
Prefab::PrefabDomUtils::LoadInstanceFlags::AssignRandomEntityId))
|
||||
Prefab::PrefabDomUtils::LoadFlags::AssignRandomEntityId))
|
||||
{
|
||||
PrefabDomValueReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName);
|
||||
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
{
|
||||
Instance instance;
|
||||
if (Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(instance, prefabDom, referencedAssets,
|
||||
Prefab::PrefabDomUtils::LoadInstanceFlags::AssignRandomEntityId)) // Always assign random entity ids because the spawnable is
|
||||
Prefab::PrefabDomUtils::LoadFlags::AssignRandomEntityId)) // Always assign random entity ids because the spawnable is
|
||||
// going to be used to create clones of the entities.
|
||||
{
|
||||
AzFramework::Spawnable::EntityList& entities = spawnable.GetEntities();
|
||||
|
||||
+93
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <Prefab/PrefabTestDomUtils.h>
|
||||
#include <Prefab/PrefabTestFixture.h>
|
||||
#include <Prefab/PrefabTestComponent.h>
|
||||
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
@@ -18,6 +19,98 @@ namespace UnitTest
|
||||
{
|
||||
using PrefabInstanceToTemplateTests = PrefabTestFixture;
|
||||
|
||||
TEST_F(PrefabInstanceToTemplateTests, GenerateEntityDom_InvalidType_InvalidTypeSkipped)
|
||||
{
|
||||
const char* newEntityName = "New Entity";
|
||||
AZ::Entity* newEntity = CreateEntity(newEntityName, false);
|
||||
ASSERT_TRUE(newEntity);
|
||||
|
||||
// Add a component with a member that is missing reflection info
|
||||
// and a member that is properly reflected
|
||||
PrefabTestComponentWithUnReflectedTypeMember* newComponent =
|
||||
newEntity->CreateComponent<PrefabTestComponentWithUnReflectedTypeMember>();
|
||||
|
||||
ASSERT_TRUE(newComponent);
|
||||
|
||||
AZStd::unique_ptr<Instance> prefabInstance = m_prefabSystemComponent->CreatePrefab({ newEntity }, {}, "test/path");
|
||||
ASSERT_TRUE(prefabInstance);
|
||||
|
||||
PrefabDom entityDom;
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(entityDom, *newEntity);
|
||||
|
||||
auto componentListDom = entityDom.FindMember("Components");
|
||||
|
||||
// Confirm that there is only one component in the entityDom
|
||||
ASSERT_NE(componentListDom, entityDom.MemberEnd());
|
||||
ASSERT_TRUE(componentListDom->value.IsObject());
|
||||
ASSERT_EQ(componentListDom->value.MemberCount(), 1);
|
||||
|
||||
auto testComponentDom = componentListDom->value.MemberBegin();
|
||||
ASSERT_TRUE(testComponentDom->value.IsObject());
|
||||
|
||||
// Confirm that the componentDom does not contained the invalid UnReflectedType
|
||||
// We want to skip over it and produce a best effort entityDom
|
||||
auto unReflectedTypeDom = testComponentDom->value.FindMember("UnReflectedType");
|
||||
ASSERT_EQ(unReflectedTypeDom, testComponentDom->value.MemberEnd());
|
||||
|
||||
// Confirm the presence of the valid ReflectedType
|
||||
auto reflectedTypeDom = testComponentDom->value.FindMember("ReflectedType");
|
||||
ASSERT_NE(reflectedTypeDom, testComponentDom->value.MemberEnd());
|
||||
|
||||
// Confirm the reflected type has the correct type and value
|
||||
ASSERT_TRUE(reflectedTypeDom->value.IsInt());
|
||||
EXPECT_EQ(reflectedTypeDom->value.GetInt(), newComponent->m_reflectedType);
|
||||
}
|
||||
|
||||
TEST_F(PrefabInstanceToTemplateTests, GenerateInstanceDom_InvalidType_InvalidTypeSkipped)
|
||||
{
|
||||
const char* newEntityName = "New Entity";
|
||||
AZ::Entity* newEntity = CreateEntity(newEntityName, false);
|
||||
ASSERT_TRUE(newEntity);
|
||||
|
||||
// Add a component with a member that is missing reflection info
|
||||
// and a member that is properly reflected
|
||||
PrefabTestComponentWithUnReflectedTypeMember* newComponent =
|
||||
newEntity->CreateComponent<PrefabTestComponentWithUnReflectedTypeMember>();
|
||||
|
||||
ASSERT_TRUE(newComponent);
|
||||
|
||||
AZStd::unique_ptr<Instance> prefabInstance = m_prefabSystemComponent->CreatePrefab({ newEntity }, {}, "test/path");
|
||||
ASSERT_TRUE(prefabInstance);
|
||||
|
||||
PrefabDom instanceDom;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDom, *prefabInstance);
|
||||
|
||||
// Acquire the entity out of the instanceDom
|
||||
auto entitiesDom = instanceDom.FindMember(PrefabDomUtils::EntitiesName);
|
||||
ASSERT_NE(entitiesDom, instanceDom.MemberEnd());
|
||||
ASSERT_EQ(entitiesDom->value.MemberCount(), 1);
|
||||
|
||||
auto entityDom = entitiesDom->value.MemberBegin();
|
||||
auto componentListDom = entityDom->value.FindMember("Components");
|
||||
|
||||
// Confirm that there is only one component in the entityDom
|
||||
ASSERT_NE(componentListDom, entityDom->value.MemberEnd());
|
||||
ASSERT_TRUE(componentListDom->value.IsObject());
|
||||
ASSERT_EQ(componentListDom->value.MemberCount(), 1);
|
||||
|
||||
auto testComponentDom = componentListDom->value.MemberBegin();
|
||||
ASSERT_TRUE(testComponentDom->value.IsObject());
|
||||
|
||||
// Confirm that the componentDom does not contained the invalid UnReflectedType
|
||||
// We want to skip over it and produce a best effort entityDom
|
||||
auto unReflectedTypeDom = testComponentDom->value.FindMember("UnReflectedType");
|
||||
ASSERT_EQ(unReflectedTypeDom, testComponentDom->value.MemberEnd());
|
||||
|
||||
// Confirm the presence of the valid ReflectedType
|
||||
auto reflectedTypeDom = testComponentDom->value.FindMember("ReflectedType");
|
||||
ASSERT_NE(reflectedTypeDom, testComponentDom->value.MemberEnd());
|
||||
|
||||
// Confirm the reflected type has the correct type and value
|
||||
ASSERT_TRUE(reflectedTypeDom->value.IsInt());
|
||||
EXPECT_EQ(reflectedTypeDom->value.GetInt(), newComponent->m_reflectedType);
|
||||
}
|
||||
|
||||
TEST_F(PrefabInstanceToTemplateTests, PrefabUpdateTemplate_UpdateEntityOnInstance)
|
||||
{
|
||||
//create template with single entity
|
||||
|
||||
@@ -28,4 +28,18 @@ namespace UnitTest
|
||||
: m_boolProperty(boolProperty)
|
||||
{
|
||||
}
|
||||
|
||||
void PrefabTestComponentWithUnReflectedTypeMember::Reflect(AZ::ReflectContext* reflection)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = AZ::RttiCast<AZ::SerializeContext*>(reflection);
|
||||
|
||||
// We reflect our member but not its type this will result in missing reflection data
|
||||
// when we try to store or load this field
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<PrefabTestComponentWithUnReflectedTypeMember, AzToolsFramework::Components::EditorComponentBase>()
|
||||
->Field("UnReflectedType", &PrefabTestComponentWithUnReflectedTypeMember::m_unReflectedType)
|
||||
->Field("ReflectedType", &PrefabTestComponentWithUnReflectedTypeMember::m_reflectedType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,4 +27,22 @@ namespace UnitTest
|
||||
int m_intProperty = 0;
|
||||
AZ::EntityId m_entityIdProperty;
|
||||
};
|
||||
|
||||
class UnReflectedType
|
||||
{
|
||||
public:
|
||||
AZ_TYPE_INFO(UnReflectedType, "{FB65262C-CE9A-45CA-99EB-4DDCB19B32DB}");
|
||||
int m_unReflectedInt = 42;
|
||||
};
|
||||
|
||||
class PrefabTestComponentWithUnReflectedTypeMember
|
||||
: public AzToolsFramework::Components::EditorComponentBase
|
||||
{
|
||||
public:
|
||||
AZ_EDITOR_COMPONENT(PrefabTestComponentWithUnReflectedTypeMember, "{726281E1-8E47-46AB-8018-D3F4BA823D74}");
|
||||
static void Reflect(AZ::ReflectContext* reflection);
|
||||
|
||||
UnReflectedType m_unReflectedType;
|
||||
int m_reflectedType = 52;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace UnitTest
|
||||
EXPECT_TRUE(m_instanceToTemplateInterface);
|
||||
|
||||
GetApplication()->RegisterComponentDescriptor(PrefabTestComponent::CreateDescriptor());
|
||||
GetApplication()->RegisterComponentDescriptor(PrefabTestComponentWithUnReflectedTypeMember::CreateDescriptor());
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<ToolsTestApplication> PrefabTestFixture::CreateTestApplication()
|
||||
|
||||
@@ -136,7 +136,10 @@ namespace UnitTest
|
||||
|
||||
PrefabDomValueReference wheelEntityComponentBoolPropertyValue =
|
||||
PrefabDomUtils::FindPrefabDomValue(wheelEntityComponentValue->get(), PrefabTestDomUtils::BoolPropertyName);
|
||||
ASSERT_FALSE(wheelEntityComponentBoolPropertyValue.has_value());
|
||||
|
||||
ASSERT_TRUE(wheelEntityComponentBoolPropertyValue.has_value());
|
||||
ASSERT_TRUE(wheelEntityComponentBoolPropertyValue->get().IsBool());
|
||||
ASSERT_FALSE(wheelEntityComponentBoolPropertyValue->get().GetBool());
|
||||
|
||||
// Validate that the axles under the car have the same DOM as the axle template.
|
||||
PrefabTestDomUtils::ValidatePrefabDomInstances(axleInstanceAliasesUnderCar, carTemplateDom, axleTemplateDom);
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Multiplayer
|
||||
|
||||
// convert Prefab DOM into Prefab Instance.
|
||||
AZStd::unique_ptr<Instance> sourceInstance(aznew Instance());
|
||||
if (!PrefabDomUtils::LoadInstanceFromPrefabDom(*sourceInstance, prefab, PrefabDomUtils::LoadInstanceFlags::AssignRandomEntityId))
|
||||
if (!PrefabDomUtils::LoadInstanceFromPrefabDom(*sourceInstance, prefab, PrefabDomUtils::LoadFlags::AssignRandomEntityId))
|
||||
{
|
||||
PrefabDomValueConstReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user