Merge remote-tracking branch 'upstream/development' into compiletime_filerequest_code2
This commit is contained in:
+4
-1
@@ -144,7 +144,10 @@ namespace AzToolsFramework
|
||||
{
|
||||
emit ClearStringFilter();
|
||||
emit ClearTypeFilter();
|
||||
m_sourceFilterModel->FilterUpdatedSlotImmediate();
|
||||
if (m_sourceFilterModel)
|
||||
{
|
||||
m_sourceFilterModel->FilterUpdatedSlotImmediate();
|
||||
}
|
||||
}
|
||||
|
||||
void AssetBrowserTableView::Update()
|
||||
|
||||
+2
-2
@@ -415,8 +415,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
// Construct the runtime entities and products
|
||||
bool readyToCreateRootSpawnable = m_playInEditorData.m_assetsCache.IsActivated();
|
||||
if (!readyToCreateRootSpawnable &&
|
||||
!m_playInEditorData.m_assetsCache.Activate(Prefab::PrefabConversionUtils::PlayInEditor))
|
||||
if (!readyToCreateRootSpawnable && !m_playInEditorData.m_assetsCache.Activate(Prefab::PrefabConversionUtils::PlayInEditor))
|
||||
|
||||
{
|
||||
AZ_Error("Prefab", false, "Failed to create a prefab processing stack from key '%.*s'.", AZ_STRING_ARG(Prefab::PrefabConversionUtils::PlayInEditor));
|
||||
return;
|
||||
|
||||
@@ -184,6 +184,10 @@ namespace AzToolsFramework
|
||||
const float halfGridSquareCount = float(gridSquareCount) * 0.5f;
|
||||
const float halfGridSize = halfGridSquareCount * squareSize;
|
||||
const float fadeLineLength = cl_viewportFadeLineDistanceScale * squareSize;
|
||||
|
||||
// ensure AuxGeomDraw::OpacityType::Translucent render state is set
|
||||
debugDisplay.SetAlpha(0.5f);
|
||||
|
||||
for (size_t lineIndex = 0; lineIndex <= gridSquareCount; ++lineIndex)
|
||||
{
|
||||
const float lineOffset = -halfGridSize + (lineIndex * squareSize);
|
||||
|
||||
@@ -142,14 +142,14 @@ namespace AzToolsFramework
|
||||
return m_templateSourcePath;
|
||||
}
|
||||
|
||||
void Instance::SetTemplateSourcePath(AZ::IO::PathView sourcePath)
|
||||
void Instance::SetTemplateSourcePath(AZ::IO::Path sourcePath)
|
||||
{
|
||||
m_templateSourcePath = sourcePath;
|
||||
m_templateSourcePath = AZStd::move(sourcePath);
|
||||
}
|
||||
|
||||
void Instance::SetContainerEntityName(AZStd::string_view containerName)
|
||||
void Instance::SetContainerEntityName(AZStd::string containerName)
|
||||
{
|
||||
m_containerEntity->SetName(containerName);
|
||||
m_containerEntity->SetName(AZStd::move(containerName));
|
||||
}
|
||||
|
||||
bool Instance::AddEntity(AZ::Entity& entity)
|
||||
@@ -608,6 +608,31 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
AZ::EntityId Instance::GetEntityIdFromAliasPath(AliasPathView relativeAliasPath) const
|
||||
{
|
||||
return GetInstanceAndEntityIdFromAliasPath(relativeAliasPath).second;
|
||||
}
|
||||
|
||||
AZStd::pair<Instance*, AZ::EntityId> Instance::GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath)
|
||||
{
|
||||
Instance* instance = this;
|
||||
AliasPathView path = relativeAliasPath.ParentPath();
|
||||
for (auto it : path)
|
||||
{
|
||||
InstanceOptionalReference child = instance->FindNestedInstance(it.Native());
|
||||
if (child.has_value())
|
||||
{
|
||||
instance = &(child->get());
|
||||
}
|
||||
else
|
||||
{
|
||||
return AZStd::pair<Instance*, AZ::EntityId>(nullptr, AZ::EntityId());
|
||||
}
|
||||
}
|
||||
|
||||
return AZStd::pair<Instance*, AZ::EntityId>(instance, instance->GetEntityId(relativeAliasPath.Filename().Native()));
|
||||
}
|
||||
|
||||
AZStd::pair<const Instance*, AZ::EntityId> Instance::GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath) const
|
||||
{
|
||||
const Instance* instance = this;
|
||||
AliasPathView path = relativeAliasPath.ParentPath();
|
||||
@@ -620,11 +645,11 @@ namespace AzToolsFramework
|
||||
}
|
||||
else
|
||||
{
|
||||
return AZ::EntityId();
|
||||
return AZStd::pair<const Instance*, AZ::EntityId>(nullptr, AZ::EntityId());
|
||||
}
|
||||
}
|
||||
|
||||
return instance->GetEntityId(relativeAliasPath.Filename().Native());
|
||||
return AZStd::pair<const Instance*, AZ::EntityId>(instance, instance->GetEntityId(relativeAliasPath.Filename().Native()));
|
||||
}
|
||||
|
||||
AZStd::vector<InstanceAlias> Instance::GetNestedInstanceAliases(TemplateId templateId) const
|
||||
|
||||
@@ -80,8 +80,8 @@ namespace AzToolsFramework
|
||||
void SetTemplateId(TemplateId templateId);
|
||||
|
||||
const AZ::IO::Path& GetTemplateSourcePath() const;
|
||||
void SetTemplateSourcePath(AZ::IO::PathView sourcePath);
|
||||
void SetContainerEntityName(AZStd::string_view containerName);
|
||||
void SetTemplateSourcePath(AZ::IO::Path sourcePath);
|
||||
void SetContainerEntityName(AZStd::string containerName);
|
||||
|
||||
bool AddEntity(AZ::Entity& entity);
|
||||
bool AddEntity(AZStd::unique_ptr<AZ::Entity>&& entity);
|
||||
@@ -169,6 +169,13 @@ namespace AzToolsFramework
|
||||
* @return entityId, invalid ID if not found
|
||||
*/
|
||||
AZ::EntityId GetEntityIdFromAliasPath(AliasPathView relativeAliasPath) const;
|
||||
/**
|
||||
* Retrieves the instance pointer and entity id from an alias path that's relative to this instance.
|
||||
*
|
||||
* @return A pair with the Instance and entity id. The Instance is set to null and entityId is set to invalid if not found.
|
||||
*/
|
||||
AZStd::pair<Instance*, AZ::EntityId> GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath);
|
||||
AZStd::pair<const Instance*, AZ::EntityId> GetInstanceAndEntityIdFromAliasPath(AliasPathView relativeAliasPath) const;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
+9
-38
@@ -37,13 +37,13 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
}
|
||||
|
||||
prefabProcessorContext.ListPrefabs(
|
||||
[this, &serializeContext, &prefabProcessorContext]([[maybe_unused]] AZStd::string_view prefabName, PrefabDom& prefab)
|
||||
[this, &serializeContext, &prefabProcessorContext](PrefabDocument& prefab)
|
||||
{
|
||||
auto result = RemoveEditorInfo(prefab, serializeContext, prefabProcessorContext);
|
||||
if (!result)
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", false, "Converting to runtime Prefab '%.*s' failed, Error: %s .", AZ_STRING_ARG(prefabName),
|
||||
"Prefab", false, "Converting to runtime Prefab '%s' failed, Error: %s .", prefab.GetName().c_str(),
|
||||
result.GetError().c_str());
|
||||
return;
|
||||
}
|
||||
@@ -58,10 +58,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
}
|
||||
}
|
||||
|
||||
void EditorInfoRemover::GetEntitiesFromInstance(
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& instance, EntityList& hierarchyEntities)
|
||||
void EditorInfoRemover::GetEntitiesFromInstance(AzToolsFramework::Prefab::Instance& instance, EntityList& hierarchyEntities)
|
||||
{
|
||||
instance->GetAllEntitiesInHierarchy(
|
||||
instance.GetAllEntitiesInHierarchy(
|
||||
[&hierarchyEntities](const AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
hierarchyEntities.emplace_back(entity.get());
|
||||
@@ -498,7 +497,7 @@ exportComponent, prefabProcessorContext);
|
||||
}
|
||||
|
||||
EditorInfoRemover::RemoveEditorInfoResult EditorInfoRemover::RemoveEditorInfo(
|
||||
PrefabDom& prefab,
|
||||
PrefabDocument& prefab,
|
||||
AZ::SerializeContext* serializeContext,
|
||||
PrefabProcessorContext& prefabProcessorContext)
|
||||
{
|
||||
@@ -510,28 +509,10 @@ exportComponent, prefabProcessorContext);
|
||||
|
||||
m_componentRequirementsValidator.SetPlatformTags(prefabProcessorContext.GetPlatformTags());
|
||||
|
||||
// convert Prefab DOM into Prefab Instance.
|
||||
AZStd::unique_ptr<Instance> instance(aznew Instance());
|
||||
if (!Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*instance, prefab,
|
||||
Prefab::PrefabDomUtils::LoadFlags::AssignRandomEntityId))
|
||||
{
|
||||
PrefabDomValueReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName);
|
||||
|
||||
AZStd::string errorMessage("Failed to Load Prefab Instance from given Prefab Dom during Removal of Editor Info.");
|
||||
if (sourceReference.has_value() &&
|
||||
sourceReference->get().IsString() &&
|
||||
sourceReference->get().GetStringLength() != 0)
|
||||
{
|
||||
AZStd::string_view source(sourceReference->get().GetString(), sourceReference->get().GetStringLength());
|
||||
errorMessage += AZStd::string::format("Prefab Source: %.*s", AZ_STRING_ARG(source));
|
||||
}
|
||||
|
||||
return AZ::Failure(errorMessage);
|
||||
}
|
||||
|
||||
// grab all nested entities from the Instance as source entities.
|
||||
Instance& sourceInstance = prefab.GetInstance();
|
||||
EntityList sourceEntities;
|
||||
GetEntitiesFromInstance(instance, sourceEntities);
|
||||
GetEntitiesFromInstance(sourceInstance, sourceEntities);
|
||||
|
||||
EntityList exportEntities;
|
||||
|
||||
@@ -597,7 +578,7 @@ exportComponent, prefabProcessorContext);
|
||||
exportEntitiesMap.emplace(entity->GetId(), entity);
|
||||
}
|
||||
);
|
||||
instance->RemoveNestedEntities(
|
||||
sourceInstance.RemoveNestedEntities(
|
||||
[&exportEntitiesMap](const AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
return exportEntitiesMap.find(entity->GetId()) == exportEntitiesMap.end();
|
||||
@@ -605,7 +586,7 @@ exportComponent, prefabProcessorContext);
|
||||
);
|
||||
|
||||
// replace entities of instance with exported ones.
|
||||
instance->GetAllEntitiesInHierarchy(
|
||||
sourceInstance.GetAllEntitiesInHierarchy(
|
||||
[&exportEntitiesMap](AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
auto entityId = entity->GetId();
|
||||
@@ -614,16 +595,6 @@ exportComponent, prefabProcessorContext);
|
||||
}
|
||||
);
|
||||
|
||||
// save the final result in the target Prefab DOM.
|
||||
PrefabDom filteredPrefab;
|
||||
if (!PrefabDomUtils::StoreInstanceInPrefabDom(*instance, filteredPrefab))
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format(
|
||||
"Saving exported Prefab Instance within a Prefab Dom failed.")
|
||||
);
|
||||
}
|
||||
prefab.Swap(filteredPrefab);
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
+2
-3
@@ -43,7 +43,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
using RemoveEditorInfoResult = AZ::Outcome<void, AZStd::string>;
|
||||
RemoveEditorInfoResult RemoveEditorInfo(
|
||||
PrefabDom& prefab,
|
||||
PrefabDocument& prefab,
|
||||
AZ::SerializeContext* serializeContext,
|
||||
PrefabProcessorContext& prefabProcessorContext);
|
||||
|
||||
@@ -51,8 +51,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
protected:
|
||||
using EntityList = AZStd::vector<AZ::Entity*>;
|
||||
static void GetEntitiesFromInstance(
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& instance, EntityList& hierarchyEntities);
|
||||
static void GetEntitiesFromInstance(AzToolsFramework::Prefab::Instance& instance, EntityList& hierarchyEntities);
|
||||
|
||||
static bool ReadComponentAttribute(
|
||||
AZ::Component* component,
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 <AzCore/base.h>
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/std/containers/variant.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
enum class EntityAliasType : uint8_t
|
||||
{
|
||||
Disable, //!< No alias is added.
|
||||
OptionalReplace, //!< At runtime the entity might be replaced. If the alias is disabled the original entity will be spawned.
|
||||
//!< The original entity will be left in the spawnable and a copy is returned.
|
||||
Replace, //!< At runtime the entity will be replaced. If the alias is disabled nothing will be spawned. The original
|
||||
//!< entity is returned and a blank entity is left.
|
||||
Additional, //!< At runtime the alias entity will be added as an additional but unrelated entity with a new entity id.
|
||||
//!< An empty entity will be returned.
|
||||
Merge //!< At runtime the components in both entities will be merged. An empty entity will be returned. The added
|
||||
//!< components may no conflict with the entities already in the root entity.
|
||||
};
|
||||
|
||||
enum class EntityAliasSpawnableLoadBehavior : uint8_t
|
||||
{
|
||||
NoLoad, //!< Don't load the spawnable referenced in the entity alias. Loading will be up to the caller.
|
||||
QueueLoad, //!< Queue the spawnable referenced in the entity alias for loading. This will be an async load because asset
|
||||
//!< handlers aren't allowed to start a blocking load as this can lead to deadlocks. This option will allow
|
||||
//!< to disable loading the referenced spawnable through the event fired from the spawnables asset handler.
|
||||
DependentLoad //!< The spawnable referenced in the entity alias is made a dependency of the spawnable that holds the entity
|
||||
//!< alias. This will cause the spawnable to be automatically loaded along with the owning spawnable.
|
||||
};
|
||||
|
||||
struct EntityAliasSpawnableLink
|
||||
{
|
||||
EntityAliasSpawnableLink(AzFramework::Spawnable& spawnable, AZ::EntityId index);
|
||||
|
||||
AzFramework::Spawnable& m_spawnable;
|
||||
AZ::EntityId m_index;
|
||||
};
|
||||
|
||||
struct EntityAliasPrefabLink
|
||||
{
|
||||
EntityAliasPrefabLink(AZStd::string prefabName, AzToolsFramework::Prefab::AliasPath alias);
|
||||
|
||||
AZStd::string m_prefabName;
|
||||
AzToolsFramework::Prefab::AliasPath m_alias;
|
||||
};
|
||||
|
||||
struct EntityAliasStore
|
||||
{
|
||||
using LinkStore = AZStd::variant<AZStd::monostate, EntityAliasSpawnableLink, EntityAliasPrefabLink>;
|
||||
|
||||
LinkStore m_source;
|
||||
LinkStore m_target;
|
||||
uint32_t m_tag;
|
||||
AzFramework::Spawnable::EntityAliasType m_aliasType;
|
||||
EntityAliasSpawnableLoadBehavior m_loadBehavior;
|
||||
};
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
+3
-3
@@ -112,9 +112,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
// Use a random uuid as this is only a temporary source.
|
||||
PrefabConversionUtils::PrefabProcessorContext context(AZ::Uuid::CreateRandom());
|
||||
PrefabDom copy;
|
||||
copy.CopyFrom(templateReference->get().GetPrefabDom(), copy.GetAllocator(), false);
|
||||
context.AddPrefab(spawnableName, AZStd::move(copy));
|
||||
PrefabDocument document(spawnableName);
|
||||
document.SetPrefabDom(templateReference->get().GetPrefabDom());
|
||||
context.AddPrefab(AZStd::move(document));
|
||||
m_converter.ProcessPrefab(context);
|
||||
|
||||
if (!context.HasCompletedSuccessfully() || context.GetProcessedObjects().empty())
|
||||
|
||||
+28
-39
@@ -25,9 +25,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
AZ::DataStream::StreamType serializationFormat = m_serializationFormat == SerializationFormats::Binary ?
|
||||
AZ::DataStream::StreamType::ST_BINARY : AZ::DataStream::StreamType::ST_XML;
|
||||
context.ListPrefabs([&context, serializationFormat](AZStd::string_view prefabName, PrefabDom& prefab)
|
||||
context.ListPrefabs([&context, serializationFormat](PrefabDocument& prefab)
|
||||
{
|
||||
ProcessPrefab(context, prefabName, prefab, serializationFormat);
|
||||
ProcessPrefab(context, prefab, serializationFormat);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -45,12 +45,12 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabCatchmentProcessor::ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab,
|
||||
void PrefabCatchmentProcessor::ProcessPrefab(PrefabProcessorContext& context, PrefabDocument& prefab,
|
||||
AZ::DataStream::StreamType serializationFormat)
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab::SpawnableUtils;
|
||||
|
||||
AZStd::string uniqueName = prefabName;
|
||||
AZStd::string uniqueName = prefab.GetName();
|
||||
uniqueName += AzFramework::Spawnable::DotFileExtension;
|
||||
|
||||
auto serializer = [serializationFormat](AZStd::vector<uint8_t>& output, const ProcessedObjectStore& object) -> bool
|
||||
@@ -64,45 +64,34 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
AZStd::move(uniqueName), context.GetSourceUuid(), AZStd::move(serializer));
|
||||
AZ_Assert(spawnable, "Failed to create a new spawnable.");
|
||||
|
||||
Instance instance;
|
||||
if (Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(
|
||||
instance, prefab, object.GetReferencedAssets(),
|
||||
Prefab::PrefabDomUtils::LoadFlags::AssignRandomEntityId)) // Always assign random entity ids because the spawnable is
|
||||
// going to be used to create clones of the entities.
|
||||
{
|
||||
// Resolve entity aliases that store PrefabDOM information to use the spawnable instead. This is done before the entities are
|
||||
// moved from the instance as they'd otherwise can't be found.
|
||||
context.ResolveSpawnableEntityAliases(prefabName, *spawnable, instance);
|
||||
Instance& instance = prefab.GetInstance();
|
||||
// Resolve entity aliases that store PrefabDOM information to use the spawnable instead. This is done before the entities are
|
||||
// moved from the instance as they'd otherwise can't be found.
|
||||
context.ResolveSpawnableEntityAliases(prefab.GetName(), *spawnable, instance);
|
||||
|
||||
AzFramework::Spawnable::EntityList& entities = spawnable->GetEntities();
|
||||
instance.DetachAllEntitiesInHierarchy(
|
||||
[&entities, &context](AZStd::unique_ptr<AZ::Entity> entity)
|
||||
AzFramework::Spawnable::EntityList& entities = spawnable->GetEntities();
|
||||
instance.DetachAllEntitiesInHierarchy(
|
||||
[&entities, &context](AZStd::unique_ptr<AZ::Entity> entity)
|
||||
{
|
||||
if (entity)
|
||||
{
|
||||
if (entity)
|
||||
entity->InvalidateDependencies();
|
||||
AZ::Entity::DependencySortOutcome evaluation = entity->EvaluateDependenciesGetDetails();
|
||||
if (evaluation.IsSuccess())
|
||||
{
|
||||
entity->InvalidateDependencies();
|
||||
AZ::Entity::DependencySortOutcome evaluation = entity->EvaluateDependenciesGetDetails();
|
||||
if (evaluation.IsSuccess())
|
||||
{
|
||||
entities.emplace_back(AZStd::move(entity));
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefabs", false, "Entity '%s' %s cannot be activated for the following reason: %s",
|
||||
entity->GetName().c_str(), entity->GetId().ToString().c_str(), evaluation.GetError().m_message.c_str());
|
||||
context.ErrorEncountered();
|
||||
}
|
||||
entities.emplace_back(AZStd::move(entity));
|
||||
}
|
||||
});
|
||||
else
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefabs", false, "Entity '%s' %s cannot be activated for the following reason: %s",
|
||||
entity->GetName().c_str(), entity->GetId().ToString().c_str(), evaluation.GetError().m_message.c_str());
|
||||
context.ErrorEncountered();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
SpawnableUtils::SortEntitiesByTransformHierarchy(*spawnable);
|
||||
context.GetProcessedObjects().push_back(AZStd::move(object));
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("Prefabs", false, "Failed to convert prefab '%.*s' to a spawnable.", AZ_STRING_ARG(prefabName));
|
||||
context.ErrorEncountered();
|
||||
}
|
||||
SpawnableUtils::SortEntitiesByTransformHierarchy(*spawnable);
|
||||
context.GetProcessedObjects().push_back(AZStd::move(object));
|
||||
}
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
+1
-2
@@ -40,8 +40,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
protected:
|
||||
static void ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab,
|
||||
AZ::DataStream::StreamType serializationFormat);
|
||||
static void ProcessPrefab(PrefabProcessorContext& context, PrefabDocument& prefab, AZ::DataStream::StreamType serializationFormat);
|
||||
|
||||
SerializationFormats m_serializationFormat{ SerializationFormats::Binary };
|
||||
};
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabDocument.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
PrefabDocument::PrefabDocument(AZStd::string name)
|
||||
: m_name(AZStd::move(name))
|
||||
, m_instance(AZStd::make_unique<AzToolsFramework::Prefab::Instance>())
|
||||
{
|
||||
m_instance->SetTemplateSourcePath(AZ::IO::Path("InMemory") / m_name);
|
||||
}
|
||||
|
||||
bool PrefabDocument::SetPrefabDom(const PrefabDom& prefab)
|
||||
{
|
||||
if (ConstructInstanceFromPrefabDom(prefab))
|
||||
{
|
||||
constexpr bool copyConstStrings = true;
|
||||
m_dom.CopyFrom(prefab, m_dom.GetAllocator(), copyConstStrings);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PrefabDocument::SetPrefabDom(PrefabDom&& prefab)
|
||||
{
|
||||
if (ConstructInstanceFromPrefabDom(prefab))
|
||||
{
|
||||
m_dom = AZStd::move(prefab);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const AZStd::string& PrefabDocument::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const PrefabDom& PrefabDocument::GetDom() const
|
||||
{
|
||||
if (m_isDirty)
|
||||
{
|
||||
m_isDirty = !PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom);
|
||||
}
|
||||
return m_dom;
|
||||
}
|
||||
|
||||
PrefabDom&& PrefabDocument::TakeDom()
|
||||
{
|
||||
if (m_isDirty)
|
||||
{
|
||||
[[maybe_unused]] bool storedSuccessfully = PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom);
|
||||
AZ_Assert(storedSuccessfully, "Failed to store Instance '%s' to PrefabDom.", m_name.c_str());
|
||||
m_isDirty = false;
|
||||
}
|
||||
// After the PrefabDom is moved an empty PrefabDom is left behind. This should be reflected in the Instance,
|
||||
// so reset it so it's empty as well.
|
||||
m_instance->Reset();
|
||||
m_instance->SetTemplateSourcePath(AZ::IO::Path("InMemory") / m_name);
|
||||
return AZStd::move(m_dom);
|
||||
}
|
||||
|
||||
void PrefabDocument::ListEntitiesWithComponentType(
|
||||
AZ::TypeId componentType, const AZStd::function<bool(AzToolsFramework::Prefab::AliasPath&&)>& callback) const
|
||||
{
|
||||
m_instance->GetAllEntitiesInHierarchyConst(
|
||||
[this, &componentType, &callback](const AZ::Entity& entity) -> bool
|
||||
{
|
||||
if (entity.FindComponent(componentType))
|
||||
{
|
||||
return callback(m_instance->GetAliasPathRelativeToInstance(entity.GetId()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AZ::Entity* PrefabDocument::CreateEntityAlias(
|
||||
PrefabDocument& source,
|
||||
AzToolsFramework::Prefab::AliasPathView entity,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context)
|
||||
{
|
||||
auto&& [sourceInstance, entityId] = source.m_instance->GetInstanceAndEntityIdFromAliasPath(entity);
|
||||
if (sourceInstance != nullptr && entityId.IsValid())
|
||||
{
|
||||
return SpawnableUtils::CreateEntityAlias(
|
||||
source.m_name, *sourceInstance, m_name, *m_instance, entityId, aliasType, loadBehavior, tag, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AzToolsFramework::Prefab::Instance& PrefabDocument::GetInstance()
|
||||
{
|
||||
// Assume that changes will be made to the instance.
|
||||
m_isDirty = true;
|
||||
return *m_instance;
|
||||
}
|
||||
|
||||
const AzToolsFramework::Prefab::Instance& PrefabDocument::GetInstance() const
|
||||
{
|
||||
return *m_instance;
|
||||
}
|
||||
|
||||
bool PrefabDocument::ConstructInstanceFromPrefabDom(const PrefabDom& prefab)
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab;
|
||||
|
||||
m_instance->Reset();
|
||||
if (PrefabDomUtils::LoadInstanceFromPrefabDom(*m_instance, prefab, PrefabDomUtils::LoadFlags::AssignRandomEntityId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef AZ_ENABLE_TRACING
|
||||
AZStd::string_view sourceName = m_name;
|
||||
PrefabDomValueConstReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName);
|
||||
if (sourceReference.has_value() && sourceReference->get().IsString() && sourceReference->get().GetStringLength() != 0)
|
||||
{
|
||||
sourceName = AZStd::string_view(sourceReference->get().GetString(), sourceReference->get().GetStringLength());
|
||||
}
|
||||
AZ_Error(
|
||||
"PrefabDocument", false, "Failed to construct Prefab instance from given PrefabDOM '%.*s'.", AZ_STRING_ARG(sourceName));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomTypes.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
class PrefabProcessorContext;
|
||||
|
||||
class PrefabDocument final
|
||||
{
|
||||
public:
|
||||
explicit PrefabDocument(AZStd::string name);
|
||||
PrefabDocument(const PrefabDocument&) = delete;
|
||||
PrefabDocument(PrefabDocument&&) = default;
|
||||
|
||||
PrefabDocument& operator=(const PrefabDocument&) = delete;
|
||||
PrefabDocument& operator=(PrefabDocument&&) = default;
|
||||
|
||||
bool SetPrefabDom(const PrefabDom& prefab);
|
||||
bool SetPrefabDom(PrefabDom&& prefab);
|
||||
|
||||
const AZStd::string& GetName() const;
|
||||
const PrefabDom& GetDom() const;
|
||||
PrefabDom&& TakeDom();
|
||||
|
||||
template<typename Component>
|
||||
void ListEntitiesWithComponentType(const AZStd::function<bool(AzToolsFramework::Prefab::AliasPath&&)>& callback) const;
|
||||
void ListEntitiesWithComponentType(
|
||||
AZ::TypeId componentType, const AZStd::function<bool(AzToolsFramework::Prefab::AliasPath&&)>& callback) const;
|
||||
AZ::Entity* CreateEntityAlias(
|
||||
PrefabDocument& source,
|
||||
AzToolsFramework::Prefab::AliasPathView entity,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context);
|
||||
|
||||
// Where possible, prefer functions directly on the PrefabDocument Instead of using the Instance.
|
||||
AzToolsFramework::Prefab::Instance& GetInstance();
|
||||
const AzToolsFramework::Prefab::Instance& GetInstance() const;
|
||||
|
||||
private:
|
||||
bool ConstructInstanceFromPrefabDom(const PrefabDom& prefab);
|
||||
|
||||
mutable PrefabDom m_dom;
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> m_instance;
|
||||
AZStd::string m_name;
|
||||
mutable bool m_isDirty{ false };
|
||||
};
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabDocument.inl>
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
template<typename Component>
|
||||
void PrefabDocument::ListEntitiesWithComponentType(const AZStd::function<bool(AzToolsFramework::Prefab::AliasPath&&)>& callback) const
|
||||
{
|
||||
ListEntitiesWithComponentType(azrtti_typeid<Component>(), callback);
|
||||
}
|
||||
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
+57
-15
@@ -7,8 +7,10 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Component/EntityUtils.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabDocument.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h>
|
||||
|
||||
@@ -30,27 +32,42 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
: m_sourceUuid(sourceUuid)
|
||||
{}
|
||||
|
||||
bool PrefabProcessorContext::AddPrefab(AZStd::string prefabName, PrefabDom prefab)
|
||||
bool PrefabProcessorContext::AddPrefab(PrefabDocument&& document)
|
||||
{
|
||||
auto result = m_prefabs.emplace(AZStd::move(prefabName), AZStd::move(prefab));
|
||||
return result.second;
|
||||
}
|
||||
|
||||
void PrefabProcessorContext::ListPrefabs(const AZStd::function<void(AZStd::string_view, PrefabDom&)>& callback)
|
||||
{
|
||||
m_isIterating = true;
|
||||
for (auto& it : m_prefabs)
|
||||
AZStd::string name = document.GetName();
|
||||
if (!m_prefabNames.contains(name))
|
||||
{
|
||||
callback(it.first, it.second);
|
||||
m_prefabNames.emplace(AZStd::move(name));
|
||||
// If currently iterating add to pending queue to avoid invalidating the container that's being iterated over.
|
||||
PrefabContainer& container = m_isIterating ? m_pendingPrefabAdditions : m_prefabs;
|
||||
container.push_back(AZStd::move(document));
|
||||
return true;
|
||||
}
|
||||
m_isIterating = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void PrefabProcessorContext::ListPrefabs(const AZStd::function<void(AZStd::string_view, const PrefabDom&)>& callback) const
|
||||
void PrefabProcessorContext::ListPrefabs(const AZStd::function<void(PrefabDocument&)>& callback)
|
||||
{
|
||||
for (const auto& it : m_prefabs)
|
||||
// Enable iterating state so the prefab container doesn't get invalided. Enabling this flag will cause new prefabs
|
||||
// to be stored in a temporary buffer that can be moved into the regular prefab container after iterating.
|
||||
m_isIterating = true;
|
||||
for (PrefabDocument& document : m_prefabs)
|
||||
{
|
||||
callback(it.first, it.second);
|
||||
callback(document);
|
||||
}
|
||||
|
||||
m_isIterating = false;
|
||||
m_prefabs.insert(
|
||||
m_prefabs.end(), AZStd::make_move_iterator(m_pendingPrefabAdditions.begin()),
|
||||
AZStd::make_move_iterator(m_pendingPrefabAdditions.end()));
|
||||
m_pendingPrefabAdditions.clear();
|
||||
}
|
||||
|
||||
void PrefabProcessorContext::ListPrefabs(const AZStd::function<void(const PrefabDocument&)>& callback) const
|
||||
{
|
||||
for (const PrefabDocument& document : m_prefabs)
|
||||
{
|
||||
callback(document);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +149,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab;
|
||||
|
||||
// Resolve prefab links into spawnable links for the provided spawnable.
|
||||
for (EntityAliasStore& entityAlias : m_entityAliases)
|
||||
{
|
||||
auto sourcePrefab = AZStd::get_if<EntityAliasPrefabLink>(&entityAlias.m_source);
|
||||
@@ -224,11 +242,35 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
it = aliasVisitors.emplace(source->m_spawnable.GetId(), AZStd::move(visitor)).first;
|
||||
}
|
||||
it->second.AddAlias(
|
||||
AZ::Data::Asset<AzFramework::Spawnable>(&target->m_spawnable, loadBehavior), alias.m_tag, sourceIndex, targetIndex,
|
||||
AZ::Data::Asset<AzFramework::Spawnable>(target->m_spawnable.GetId(), azrtti_typeid<AzFramework::Spawnable>()), alias.m_tag,
|
||||
sourceIndex, targetIndex,
|
||||
alias.m_aliasType, alias.m_loadBehavior == EntityAliasSpawnableLoadBehavior::QueueLoad);
|
||||
|
||||
// Register the dependency between the two spawnables.
|
||||
RegisterProductAssetDependency(source->m_spawnable.GetId(), target->m_spawnable.GetId(), loadBehavior);
|
||||
|
||||
// Patch up all entity ids so the alias points to the same entity id if needed.
|
||||
switch (alias.m_aliasType)
|
||||
{
|
||||
case AzFramework::Spawnable::EntityAliasType::Original:
|
||||
continue;
|
||||
case AzFramework::Spawnable::EntityAliasType::Disable:
|
||||
continue;
|
||||
case AzFramework::Spawnable::EntityAliasType::Replace:
|
||||
break; // Requires entity id for alias in source and target spawnable matches.
|
||||
case AzFramework::Spawnable::EntityAliasType::Additional:
|
||||
continue;
|
||||
case AzFramework::Spawnable::EntityAliasType::Merge:
|
||||
break; // Requires entity id for alias in source and target spawnable matches.
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
auto entityIdMapper = [source, target](const AZ::EntityId& originalId, bool /*isEntityId*/) -> AZ::EntityId
|
||||
{
|
||||
return originalId == target->m_index ? source->m_index : originalId;
|
||||
};
|
||||
AZ::EntityUtils::ReplaceEntityIdsAndEntityRefs(&target->m_spawnable, entityIdMapper);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-55
@@ -21,60 +21,12 @@
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomTypes.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabDocument.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/ProcesedObjectStore.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
enum class EntityAliasType : uint8_t
|
||||
{
|
||||
Disable, //!< No alias is added.
|
||||
OptionalReplace, //!< At runtime the entity might be replaced. If the alias is disabled the original entity will be spawned.
|
||||
//!< The original entity will be left in the spawnable and a copy is returned.
|
||||
Replace, //!< At runtime the entity will be replaced. If the alias is disabled nothing will be spawned. The original
|
||||
//!< entity is returned and a blank entity is left.
|
||||
Additional, //!< At runtime the alias entity will be added as an additional but unrelated entity with a new entity id.
|
||||
//!< An empty entity will be returned.
|
||||
Merge //!< At runtime the components in both entities will be merged. An empty entity will be returned. The added
|
||||
//!< components may no conflict with the entities already in the root entity.
|
||||
};
|
||||
|
||||
enum class EntityAliasSpawnableLoadBehavior : uint8_t
|
||||
{
|
||||
NoLoad, //!< Don't load the spawnable referenced in the entity alias. Loading will be up to the caller.
|
||||
QueueLoad, //!< Queue the spawnable referenced in the entity alias for loading. This will be an async load because asset
|
||||
//!< handlers aren't allowed to start a blocking load as this can lead to deadlocks. This option will allow
|
||||
//!< to disable loading the referenced spawnable through the event fired from the spawnables asset handler.
|
||||
DependentLoad //!< The spawnable referenced in the entity alias is made a dependency of the spawnable that holds the entity
|
||||
//!< alias. This will cause the spawnable to be automatically loaded along with the owning spawnable.
|
||||
};
|
||||
|
||||
struct EntityAliasSpawnableLink
|
||||
{
|
||||
EntityAliasSpawnableLink(AzFramework::Spawnable& spawnable, AZ::EntityId index);
|
||||
|
||||
AzFramework::Spawnable& m_spawnable;
|
||||
AZ::EntityId m_index;
|
||||
};
|
||||
|
||||
struct EntityAliasPrefabLink
|
||||
{
|
||||
EntityAliasPrefabLink(AZStd::string prefabName, AzToolsFramework::Prefab::AliasPath alias);
|
||||
|
||||
AZStd::string m_prefabName;
|
||||
AzToolsFramework::Prefab::AliasPath m_alias;
|
||||
};
|
||||
|
||||
struct EntityAliasStore
|
||||
{
|
||||
using LinkStore = AZStd::variant<AZStd::monostate, EntityAliasSpawnableLink, EntityAliasPrefabLink>;
|
||||
|
||||
LinkStore m_source;
|
||||
LinkStore m_target;
|
||||
uint32_t m_tag;
|
||||
AzFramework::Spawnable::EntityAliasType m_aliasType;
|
||||
EntityAliasSpawnableLoadBehavior m_loadBehavior;
|
||||
};
|
||||
|
||||
struct AssetDependencyInfo
|
||||
{
|
||||
AZ::Data::AssetId m_assetId;
|
||||
@@ -93,9 +45,9 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
explicit PrefabProcessorContext(const AZ::Uuid& sourceUuid);
|
||||
virtual ~PrefabProcessorContext() = default;
|
||||
|
||||
virtual bool AddPrefab(AZStd::string prefabName, PrefabDom prefab);
|
||||
virtual void ListPrefabs(const AZStd::function<void(AZStd::string_view, PrefabDom&)>& callback);
|
||||
virtual void ListPrefabs(const AZStd::function<void(AZStd::string_view, const PrefabDom&)>& callback) const;
|
||||
virtual bool AddPrefab(PrefabDocument&& document);
|
||||
virtual void ListPrefabs(const AZStd::function<void(PrefabDocument&)>& callback);
|
||||
virtual void ListPrefabs(const AZStd::function<void(const PrefabDocument&)>& callback) const;
|
||||
virtual bool HasPrefabs() const;
|
||||
|
||||
virtual bool RegisterSpawnableProductAssetDependency(
|
||||
@@ -128,12 +80,15 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
virtual void ErrorEncountered();
|
||||
|
||||
protected:
|
||||
using NamedPrefabContainer = AZStd::unordered_map<AZStd::string, PrefabDom>;
|
||||
using PrefabNames = AZStd::unordered_set<AZStd::string>;
|
||||
using PrefabContainer = AZStd::vector<PrefabDocument>;
|
||||
using SpawnableEntityAliasStore = AZStd::vector<EntityAliasStore>;
|
||||
|
||||
AZ::Data::AssetLoadBehavior ToAssetLoadBehavior(EntityAliasSpawnableLoadBehavior loadBehavior) const;
|
||||
|
||||
NamedPrefabContainer m_prefabs;
|
||||
PrefabContainer m_prefabs;
|
||||
PrefabContainer m_pendingPrefabAdditions;
|
||||
PrefabNames m_prefabNames;
|
||||
SpawnableEntityAliasStore m_entityAliases;
|
||||
ProcessedObjectStoreContainer m_products;
|
||||
ProductAssetDependencyContainer m_registeredProductAssetDependencies;
|
||||
|
||||
+43
-110
@@ -16,10 +16,12 @@
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h>
|
||||
|
||||
namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
{
|
||||
@@ -52,14 +54,32 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
return result;
|
||||
}
|
||||
|
||||
const AZ::Entity* FindEntity(AZ::EntityId entityId, const AzToolsFramework::Prefab::Instance& source)
|
||||
{
|
||||
const AZ::Entity* result = nullptr;
|
||||
source.GetConstEntities(
|
||||
[&result, entityId](const AZ::Entity& entity)
|
||||
{
|
||||
if (entity.GetId() != entityId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = &entity;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
AZ::Entity* FindEntity(AZ::EntityId entityId, AzFramework::Spawnable& source)
|
||||
{
|
||||
uint32_t index = AzToolsFramework::Prefab::SpawnableUtils::FindEntityIndex(entityId, source);
|
||||
return index != InvalidEntityIndex ? source.GetEntities()[index].get() : nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
AZStd::unique_ptr<AZ::Entity> CloneEntity(AZ::EntityId entityId, T& source)
|
||||
AZStd::unique_ptr<AZ::Entity> CloneEntity(AZ::EntityId entityId, AzToolsFramework::Prefab::Instance& source)
|
||||
{
|
||||
AZ::Entity* target = Internal::FindEntity(entityId, source);
|
||||
AZ_Assert(
|
||||
@@ -74,41 +94,30 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
return clone;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> ReplaceEntityWithPlaceholder(AZ::EntityId entityId, AzToolsFramework::Prefab::Instance& source)
|
||||
AZStd::unique_ptr<AZ::Entity> ReplaceEntityWithPlaceholder(
|
||||
AZ::EntityId entityId,
|
||||
[[maybe_unused]] AZStd::string_view sourcePrefabName,
|
||||
AzToolsFramework::Prefab::Instance& source)
|
||||
{
|
||||
auto&& [instance, alias] = source.FindInstanceAndAlias(entityId);
|
||||
AZ_Assert(
|
||||
instance, "SpawnbleUtils were unable to locate entity alias with id %zu in Instance '%s' for replacing.",
|
||||
aznumeric_cast<AZ::u64>(entityId), source.GetTemplateSourcePath().c_str());
|
||||
instance, "SpawnbleUtils were unable to locate entity alias with id %zu in Instance '%.*s' for replacing.",
|
||||
aznumeric_cast<AZ::u64>(entityId), AZ_STRING_ARG(sourcePrefabName));
|
||||
|
||||
EntityOptionalReference entityData = instance->GetEntity(alias);
|
||||
AZ_Assert(
|
||||
entityData.has_value(), "SpawnbleUtils were unable to locate entity '%.*s' in Instance '%s' for replacing.",
|
||||
AZ_STRING_ARG(alias), source.GetTemplateSourcePath().c_str());
|
||||
auto placeholder = AZStd::make_unique<AZ::Entity>(entityData->get().GetId(), entityData->get().GetName());
|
||||
entityData.has_value(), "SpawnbleUtils were unable to locate entity '%.*s' in Instance '%.*s' for replacing.",
|
||||
AZ_STRING_ARG(alias), AZ_STRING_ARG(sourcePrefabName));
|
||||
// A new entity id can be used for the placeholder as `ReplaceEntity` will swap the entity ids.
|
||||
auto placeholder = AZStd::make_unique<AZ::Entity>(AZ::Entity::MakeId(), entityData->get().GetName());
|
||||
return instance->ReplaceEntity(AZStd::move(placeholder), alias);
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> ReplaceEntityWithPlaceholder(AZ::EntityId entityId, AzFramework::Spawnable& source)
|
||||
{
|
||||
uint32_t index = AzToolsFramework::Prefab::SpawnableUtils::FindEntityIndex(entityId, source);
|
||||
AZ_Assert(
|
||||
index != InvalidEntityIndex, "SpawnbleUtils were unable to locate entity alias with id %zu in Spawnable for replacing.",
|
||||
aznumeric_cast<AZ::u64>(entityId));
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> original = AZStd::move(source.GetEntities()[index]);
|
||||
AZ_Assert(
|
||||
original, "SpawnbleUtils were unable to locate entity with id %zu in Spawnable for replacing.",
|
||||
aznumeric_cast<AZ::u64>(entityId));
|
||||
|
||||
source.GetEntities()[index] = AZStd::make_unique<AZ::Entity>(original->GetId(), original->GetName());
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
template<typename Source>
|
||||
AZStd::pair<AZStd::unique_ptr<AZ::Entity>, AzFramework::Spawnable::EntityAliasType> ApplyAlias(
|
||||
Source& source, AZ::EntityId entityId, AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType)
|
||||
AZStd::string_view sourcePrefabName,
|
||||
AzToolsFramework::Prefab::Instance& source,
|
||||
AZ::EntityId entityId,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType)
|
||||
{
|
||||
namespace PCU = AzToolsFramework::Prefab::PrefabConversionUtils;
|
||||
using ResultPair = AZStd::pair<AZStd::unique_ptr<AZ::Entity>, AzFramework::Spawnable::EntityAliasType>;
|
||||
@@ -121,12 +130,13 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
case PCU::EntityAliasType::OptionalReplace:
|
||||
return ResultPair(CloneEntity(entityId, source), AzFramework::Spawnable::EntityAliasType::Replace);
|
||||
case PCU::EntityAliasType::Replace:
|
||||
return ResultPair(ReplaceEntityWithPlaceholder(entityId, source), AzFramework::Spawnable::EntityAliasType::Replace);
|
||||
return ResultPair(
|
||||
ReplaceEntityWithPlaceholder(entityId, sourcePrefabName, source),
|
||||
AzFramework::Spawnable::EntityAliasType::Replace);
|
||||
case PCU::EntityAliasType::Additional:
|
||||
ResultPair(AZStd::make_unique<AZ::Entity>(AZ::Entity::MakeId()), AzFramework::Spawnable::EntityAliasType::Additional);
|
||||
return ResultPair(AZStd::make_unique<AZ::Entity>(), AzFramework::Spawnable::EntityAliasType::Additional);
|
||||
case PCU::EntityAliasType::Merge:
|
||||
// Use the same entity id as the original entity so at runtime the entity ids can be verified to match.
|
||||
ResultPair(AZStd::make_unique<AZ::Entity>(entityId), AzFramework::Spawnable::EntityAliasType::Merge);
|
||||
return ResultPair(AZStd::make_unique<AZ::Entity>(), AzFramework::Spawnable::EntityAliasType::Merge);
|
||||
default:
|
||||
AZ_Assert(
|
||||
false, "Invalid PrefabProcessorContext::EntityAliasType type (%i) provided.", aznumeric_cast<uint64_t>(aliasType));
|
||||
@@ -182,7 +192,8 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
AliasPath alias = source.GetAliasPathRelativeToInstance(entityId);
|
||||
if (!alias.empty())
|
||||
{
|
||||
auto&& [replacement, storedAliasType] = Internal::ApplyAlias(source, entityId, aliasType);
|
||||
auto&& [replacement, storedAliasType] =
|
||||
Internal::ApplyAlias(sourcePrefabName, source, entityId, aliasType);
|
||||
if (replacement)
|
||||
{
|
||||
AZ::Entity* result = replacement.get();
|
||||
@@ -212,84 +223,6 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Entity* CreateEntityAlias(
|
||||
AZStd::string sourcePrefabName,
|
||||
AzToolsFramework::Prefab::Instance& source,
|
||||
AzFramework::Spawnable& target,
|
||||
AZ::EntityId entityId,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context)
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab::PrefabConversionUtils;
|
||||
|
||||
AliasPath alias = source.GetAliasPathRelativeToInstance(entityId);
|
||||
if (!alias.empty())
|
||||
{
|
||||
auto&& [replacement, storedAliasType] = Internal::ApplyAlias(source, entityId, aliasType);
|
||||
if (replacement)
|
||||
{
|
||||
AZ::Entity* result = replacement.get();
|
||||
target.GetEntities().push_back(AZStd::move(replacement));
|
||||
|
||||
EntityAliasStore store;
|
||||
store.m_aliasType = storedAliasType;
|
||||
store.m_source.emplace<EntityAliasPrefabLink>(AZStd::move(sourcePrefabName), AZStd::move(alias));
|
||||
store.m_target.emplace<EntityAliasSpawnableLink>(target, result->GetId());
|
||||
store.m_tag = tag;
|
||||
store.m_loadBehavior = loadBehavior;
|
||||
context.RegisterSpawnableEntityAlias(AZStd::move(store));
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "A replacement for entity with id %zu could not be created.", static_cast<AZ::u64>(entityId));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "Entity with id %llu was not found in the source prefab.", static_cast<AZ::u64>(entityId));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Entity* CreateEntityAlias(
|
||||
AzFramework::Spawnable& source,
|
||||
AzFramework::Spawnable& target,
|
||||
AZ::EntityId entityId,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context)
|
||||
{
|
||||
using namespace AzToolsFramework::Prefab::PrefabConversionUtils;
|
||||
|
||||
auto&& [replacement, storedAliasType] = Internal::ApplyAlias(source, entityId, aliasType);
|
||||
if (replacement)
|
||||
{
|
||||
AZ::Entity* result = replacement.get();
|
||||
target.GetEntities().push_back(AZStd::move(replacement));
|
||||
|
||||
EntityAliasStore store;
|
||||
store.m_aliasType = storedAliasType;
|
||||
store.m_source.emplace<EntityAliasSpawnableLink>(source, entityId);
|
||||
store.m_target.emplace<EntityAliasSpawnableLink>(target, result->GetId());
|
||||
store.m_tag = tag;
|
||||
store.m_loadBehavior = loadBehavior;
|
||||
context.RegisterSpawnableEntityAlias(AZStd::move(store));
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "A replacement for entity with id %zu could not be created.", static_cast<AZ::u64>(entityId));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t FindEntityIndex(AZ::EntityId entity, const AzFramework::Spawnable& spawnable)
|
||||
{
|
||||
auto begin = spawnable.GetEntities().begin();
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <AzCore/std/limits.h>
|
||||
#include <AzFramework/Spawnable/Spawnable.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomTypes.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/EntityAliasTypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -24,6 +24,11 @@ namespace AzToolsFramework::Prefab
|
||||
class Instance;
|
||||
}
|
||||
|
||||
namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
{
|
||||
class PrefabProcessorContext;
|
||||
}
|
||||
|
||||
namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
{
|
||||
static constexpr uint32_t InvalidEntityIndex = AZStd::numeric_limits<uint32_t>::max();
|
||||
@@ -41,24 +46,7 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context);
|
||||
AZ::Entity* CreateEntityAlias(
|
||||
AZStd::string sourcePrefabName,
|
||||
AzToolsFramework::Prefab::Instance& source,
|
||||
AzFramework::Spawnable& target,
|
||||
AZ::EntityId entityId,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context);
|
||||
AZ::Entity* CreateEntityAlias(
|
||||
AzFramework::Spawnable& source,
|
||||
AzFramework::Spawnable& target,
|
||||
AZ::EntityId entityId,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasType aliasType,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EntityAliasSpawnableLoadBehavior loadBehavior,
|
||||
uint32_t tag,
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext& context);
|
||||
|
||||
|
||||
uint32_t FindEntityIndex(AZ::EntityId entity, const AzFramework::Spawnable& spawnable);
|
||||
|
||||
void SortEntitiesByTransformHierarchy(AzFramework::Spawnable& spawnable);
|
||||
|
||||
@@ -2666,19 +2666,15 @@ namespace AzToolsFramework
|
||||
if (!isPathSafeForAssets)
|
||||
{
|
||||
// Put an error in the console, so the log files have info about this error, or the user can look up the error after dismissing it.
|
||||
AZStd::string errorMessage = "You can save slices only to your game project folder or the Gems folder. Update the location and try again.\n\n"
|
||||
"You can also review and update your save locations in the AssetProcessorPlatformConfig.ini file.";
|
||||
AZStd::string errorMessage = "You can save slices only to your game project folder or the Gems folder. Update the location and try again.\n\n";
|
||||
AZ_Error("Slice", false, errorMessage.c_str());
|
||||
|
||||
QString learnMoreLink(QObject::tr(""));
|
||||
QString learnMoreDescription(QObject::tr(" <a href='%1'>Learn more</a>").arg(learnMoreLink));
|
||||
|
||||
// Display a pop-up, the logs are easy to miss. This will make sure a user who encounters this error immediately knows their slice save has failed.
|
||||
QMessageBox msgBox(activeWindow);
|
||||
msgBox.setIcon(QMessageBox::Icon::Warning);
|
||||
msgBox.setTextFormat(Qt::RichText);
|
||||
msgBox.setWindowTitle(QObject::tr("Invalid save location"));
|
||||
msgBox.setText(QString("%1 %2").arg(QObject::tr(errorMessage.c_str())).arg(learnMoreDescription));
|
||||
msgBox.setText(QString("%1").arg(QObject::tr(errorMessage.c_str())));
|
||||
msgBox.setStandardButtons(QMessageBox::Cancel | QMessageBox::Retry);
|
||||
msgBox.setDefaultButton(QMessageBox::Retry);
|
||||
const int response = msgBox.exec();
|
||||
@@ -2689,7 +2685,16 @@ namespace AzToolsFramework
|
||||
// so set the suggested save path to a known valid location.
|
||||
if (assetSafeFolders.size() > 0)
|
||||
{
|
||||
retrySavePath = assetSafeFolders[0];
|
||||
QStringList strList = slicePath.split("/");
|
||||
if (strList.size() > 0)
|
||||
{
|
||||
retrySavePath = assetSafeFolders[0] + ("/" + strList[strList.size() - 1]).toUtf8().data();
|
||||
}
|
||||
else
|
||||
{
|
||||
retrySavePath = assetSafeFolders[0];
|
||||
}
|
||||
|
||||
}
|
||||
return SliceSaveResult::Retry;
|
||||
case QMessageBox::Cancel:
|
||||
|
||||
@@ -840,8 +840,6 @@ namespace AzToolsFramework
|
||||
richLabel->setTextFormat(Qt::RichText);
|
||||
}
|
||||
|
||||
richLabel->setText(data);
|
||||
|
||||
richLabel->setGeometry(options.rect);
|
||||
richLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
|
||||
richLabel->setPalette(options.palette);
|
||||
|
||||
@@ -1117,6 +1117,8 @@ namespace AzToolsFramework
|
||||
|
||||
m_listModel->SearchStringChanged(filterString);
|
||||
m_proxyModel->UpdateFilter();
|
||||
|
||||
m_gui->m_objectTree->expandAll();
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::OnFilterChanged(const AzQtComponents::SearchTypeFilterList& activeTypeFilters)
|
||||
|
||||
+1
@@ -421,6 +421,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
QString label{ text };
|
||||
m_nameLabel->setText(label);
|
||||
m_nameLabel->setOpenExternalLinks(true);
|
||||
m_nameLabel->setVisible(!label.isEmpty());
|
||||
// setting the stretches to 0 in case of an empty label really hides the label (i.e. even the reserved space)
|
||||
m_mainLayout->setStretch(0, label.isEmpty() ? 0 : LabelColumnStretch);
|
||||
|
||||
+24
-5
@@ -30,8 +30,7 @@ namespace UnitTest
|
||||
void MousePressAndMove(
|
||||
QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, const Qt::MouseButton mouseButton)
|
||||
{
|
||||
QPoint position = widget->mapToGlobal(initialPositionWidget);
|
||||
QTest::mousePress(widget, mouseButton, Qt::NoModifier, position);
|
||||
QTest::mousePress(widget, mouseButton, Qt::NoModifier, initialPositionWidget);
|
||||
|
||||
MouseMove(widget, initialPositionWidget, mouseDelta, mouseButton);
|
||||
}
|
||||
@@ -45,14 +44,15 @@ namespace UnitTest
|
||||
// - https://lists.qt-project.org/pipermail/development/2019-July/036873.html
|
||||
void MouseMove(QWidget* widget, const QPoint& initialPositionWidget, const QPoint& mouseDelta, const Qt::MouseButton mouseButton)
|
||||
{
|
||||
QPoint nextPosition = widget->mapToGlobal(initialPositionWidget + mouseDelta);
|
||||
const QPoint nextLocalPosition = initialPositionWidget + mouseDelta;
|
||||
const QPoint nextGlobalPosition = widget->mapToGlobal(nextLocalPosition);
|
||||
|
||||
// ^1 To ensure a mouse move event is fired we must call the test mouse move function
|
||||
// and also send a mouse move event that matches. Each on their own do not appear to
|
||||
// work - please see the links above for more context.
|
||||
QTest::mouseMove(widget, nextPosition);
|
||||
QTest::mouseMove(widget, nextLocalPosition);
|
||||
QMouseEvent mouseMoveEvent(
|
||||
QEvent::MouseMove, QPointF(nextPosition), QPointF(nextPosition), Qt::NoButton, mouseButton, Qt::NoModifier);
|
||||
QEvent::MouseMove, QPointF(nextLocalPosition), QPointF(nextGlobalPosition), Qt::NoButton, mouseButton, Qt::NoModifier);
|
||||
QApplication::sendEvent(widget, &mouseMoveEvent);
|
||||
}
|
||||
|
||||
@@ -157,6 +157,23 @@ namespace UnitTest
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
MouseMoveDetector::MouseMoveDetector(QWidget* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool MouseMoveDetector::eventFilter(QObject* watched, QEvent* event)
|
||||
{
|
||||
if (const auto eventType = event->type(); eventType == QEvent::Type::MouseMove)
|
||||
{
|
||||
auto mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
m_mouseGlobalPosition = mouseEvent->globalPos();
|
||||
m_mouseLocalPosition = mouseEvent->pos();
|
||||
}
|
||||
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
void TestEditorActions::Connect()
|
||||
{
|
||||
using AzToolsFramework::GetEntityContextId;
|
||||
@@ -571,3 +588,5 @@ namespace UnitTest
|
||||
sliceAssets.clear();
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
#include <moc_AzToolsFrameworkTestHelpers.cpp>
|
||||
|
||||
+20
-1
@@ -111,10 +111,29 @@ namespace UnitTest
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FocusInteractionWidget(QWidget* parent = nullptr) : QWidget(parent) {}
|
||||
FocusInteractionWidget(QWidget* parent = nullptr)
|
||||
: QWidget(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool event(QEvent* event) override;
|
||||
};
|
||||
|
||||
/// Records mouse move events and stores the local and global position of the cursor.
|
||||
/// @note To use, install as an event filter for the widget being interacted with
|
||||
/// e.g. m_testWidget->installEventFilter(&m_mouseMoveDetector);
|
||||
class MouseMoveDetector : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MouseMoveDetector(QWidget* parent = nullptr);
|
||||
|
||||
bool eventFilter([[maybe_unused]] QObject* watched, QEvent* event) override;
|
||||
|
||||
QPoint m_mouseGlobalPosition;
|
||||
QPoint m_mouseLocalPosition;
|
||||
};
|
||||
|
||||
/// Stores actions registered for either normal mode (regular viewport) editing and
|
||||
/// component mode editing.
|
||||
class TestEditorActions
|
||||
|
||||
@@ -723,6 +723,7 @@ set(FILES
|
||||
Prefab/Spawnable/EditorOnlyEntityHandler/UiEditorOnlyEntityHandler.cpp
|
||||
Prefab/Spawnable/EditorOnlyEntityHandler/WorldEditorOnlyEntityHandler.h
|
||||
Prefab/Spawnable/EditorOnlyEntityHandler/WorldEditorOnlyEntityHandler.cpp
|
||||
Prefab/Spawnable/EntityAliasTypes.h
|
||||
Prefab/Spawnable/InMemorySpawnableAssetContainer.h
|
||||
Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp
|
||||
Prefab/Spawnable/PrefabCatchmentProcessor.h
|
||||
@@ -730,6 +731,9 @@ set(FILES
|
||||
Prefab/Spawnable/PrefabConversionPipeline.h
|
||||
Prefab/Spawnable/PrefabConversionPipeline.cpp
|
||||
Prefab/Spawnable/PrefabConverterStackProfileNames.h
|
||||
Prefab/Spawnable/PrefabDocument.h
|
||||
Prefab/Spawnable/PrefabDocument.inl
|
||||
Prefab/Spawnable/PrefabDocument.cpp
|
||||
Prefab/Spawnable/ProcesedObjectStore.h
|
||||
Prefab/Spawnable/ProcesedObjectStore.cpp
|
||||
Prefab/Spawnable/PrefabProcessor.h
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
class AzToolsFrameworkTestHelpersFixture : public AllocatorsTestFixture
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
AllocatorsTestFixture::SetUp();
|
||||
|
||||
m_rootWidget = AZStd::make_unique<QWidget>();
|
||||
m_rootWidget->setFixedSize(0, 0);
|
||||
m_rootWidget->setMouseTracking(true);
|
||||
m_rootWidget->move(0, 0); // explicitly set the widget to be in the upper left corner
|
||||
|
||||
m_mouseMoveDetector = AZStd::make_unique<MouseMoveDetector>();
|
||||
m_rootWidget->installEventFilter(m_mouseMoveDetector.get());
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_rootWidget->removeEventFilter(m_mouseMoveDetector.get());
|
||||
m_rootWidget.reset();
|
||||
m_mouseMoveDetector.reset();
|
||||
|
||||
AllocatorsTestFixture::TearDown();
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<QWidget> m_rootWidget;
|
||||
AZStd::unique_ptr<MouseMoveDetector> m_mouseMoveDetector;
|
||||
};
|
||||
|
||||
struct MouseMoveParams
|
||||
{
|
||||
QSize m_widgetSize;
|
||||
QPoint m_widgetPosition;
|
||||
QPoint m_localCursorPosition;
|
||||
QPoint m_cursorDelta;
|
||||
};
|
||||
|
||||
class MouseMoveAzToolsFrameworkTestHelperFixture
|
||||
: public AzToolsFrameworkTestHelpersFixture
|
||||
, public ::testing::WithParamInterface<MouseMoveParams>
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(MouseMoveAzToolsFrameworkTestHelperFixture, MouseMoveCorrectlyTransformsCursorPositionInGlobalAndLocalSpace)
|
||||
{
|
||||
// given
|
||||
const MouseMoveParams mouseMoveParams = GetParam();
|
||||
m_rootWidget->move(mouseMoveParams.m_widgetPosition);
|
||||
m_rootWidget->setFixedSize(mouseMoveParams.m_widgetSize);
|
||||
|
||||
// when
|
||||
MouseMove(m_rootWidget.get(), mouseMoveParams.m_localCursorPosition, mouseMoveParams.m_cursorDelta);
|
||||
|
||||
// then
|
||||
const QPoint mouseLocalPosition = m_mouseMoveDetector->m_mouseLocalPosition;
|
||||
const QPoint mouseLocalPositionFromGlobal = m_rootWidget->mapFromGlobal(m_mouseMoveDetector->m_mouseGlobalPosition);
|
||||
const QPoint expectedPosition = mouseMoveParams.m_localCursorPosition + mouseMoveParams.m_cursorDelta;
|
||||
|
||||
using ::testing::Eq;
|
||||
EXPECT_THAT(mouseLocalPosition.x(), Eq(expectedPosition.x()));
|
||||
EXPECT_THAT(mouseLocalPosition.y(), Eq(expectedPosition.y()));
|
||||
EXPECT_THAT(mouseLocalPositionFromGlobal.x(), Eq(expectedPosition.x()));
|
||||
EXPECT_THAT(mouseLocalPositionFromGlobal.y(), Eq(expectedPosition.y()));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
All,
|
||||
MouseMoveAzToolsFrameworkTestHelperFixture,
|
||||
testing::Values(
|
||||
MouseMoveParams{ QSize(100, 100), QPoint(0, 0), QPoint(0, 0), QPoint(10, 10) },
|
||||
MouseMoveParams{ QSize(100, 100), QPoint(100, 100), QPoint(0, 0), QPoint(10, 10) },
|
||||
MouseMoveParams{ QSize(100, 100), QPoint(20, 20), QPoint(50, 50), QPoint(20, 20) }));
|
||||
} // namespace UnitTest
|
||||
+5
-4
@@ -25,7 +25,7 @@ namespace Benchmark
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
m_spawnTicket = aznew AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
state.ResumeTiming();
|
||||
|
||||
for (uint64_t spwanableCounter = 0; spwanableCounter < spawnAllEntitiesCallCount; spwanableCounter++)
|
||||
@@ -62,7 +62,7 @@ namespace Benchmark
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
m_spawnTicket = aznew AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
state.ResumeTiming();
|
||||
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket);
|
||||
@@ -93,15 +93,16 @@ namespace Benchmark
|
||||
|
||||
SetUpSpawnableAsset(entityCountInSpawnable);
|
||||
|
||||
auto spawner = AzFramework::SpawnableEntitiesInterface::Get();
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
m_spawnTicket = aznew AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
state.ResumeTiming();
|
||||
|
||||
for (uint64_t spawnCallCounter = 0; spawnCallCounter < spawnCallCount; spawnCallCounter++)
|
||||
{
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket);
|
||||
spawner->SpawnAllEntities(*m_spawnTicket);
|
||||
}
|
||||
|
||||
m_rootSpawnableInterface->ProcessSpawnableQueue();
|
||||
|
||||
+5
-5
@@ -9,6 +9,7 @@
|
||||
#include <Prefab/SpawnableRemoveEditorInfoTestFixture.h>
|
||||
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/PrefabDocument.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorOnlyEntityComponent.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorOnlyEntityComponentBus.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
@@ -201,15 +202,14 @@ namespace UnitTest
|
||||
{
|
||||
ConvertSourceEntitiesToPrefab();
|
||||
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabDocument prefab("Test");
|
||||
prefab.SetPrefabDom(m_prefabDom);
|
||||
const bool actualResult =
|
||||
m_editorInfoRemover.RemoveEditorInfo(m_prefabDom, m_serializeContext, m_prefabProcessorContext).IsSuccess();
|
||||
m_editorInfoRemover.RemoveEditorInfo(prefab, m_serializeContext, m_prefabProcessorContext).IsSuccess();
|
||||
|
||||
EXPECT_EQ(expectedResult, actualResult);
|
||||
|
||||
AZStd::unique_ptr<Instance> convertedInstance(aznew Instance());
|
||||
ASSERT_TRUE(AzToolsFramework::Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*convertedInstance, m_prefabDom));
|
||||
|
||||
convertedInstance->DetachAllEntitiesInHierarchy(
|
||||
prefab.GetInstance().DetachAllEntitiesInHierarchy(
|
||||
[this](AZStd::unique_ptr<AZ::Entity> entity)
|
||||
{
|
||||
m_runtimeEntities.emplace_back(entity.release());
|
||||
|
||||
@@ -74,10 +74,6 @@ namespace UnitTest
|
||||
AZStd::unique_ptr<AzToolsFramework::AssetBrowser::AssetBrowserFilterModel> m_filterModel;
|
||||
AZStd::unique_ptr<AzToolsFramework::AssetBrowser::AssetBrowserTableModel> m_tableModel;
|
||||
|
||||
AZStd::unique_ptr<QAbstractItemModelTester> m_modelTesterAssetBrowser;
|
||||
AZStd::unique_ptr<QAbstractItemModelTester> m_modelTesterFilterModel;
|
||||
AZStd::unique_ptr<QAbstractItemModelTester> m_modelTesterTableModel;
|
||||
|
||||
QVector<int> m_folderIds = { 13, 14, 15 };
|
||||
QVector<int> m_sourceIDs = { 1, 2, 3, 4, 5 };
|
||||
QVector<int> m_productIDs = { 1, 2, 3, 4, 5 };
|
||||
@@ -96,9 +92,6 @@ namespace UnitTest
|
||||
m_filterModel->setSourceModel(m_assetBrowserComponent->GetAssetBrowserModel());
|
||||
m_tableModel->setSourceModel(m_filterModel.get());
|
||||
|
||||
m_modelTesterAssetBrowser = AZStd::make_unique<QAbstractItemModelTester>(m_assetBrowserComponent->GetAssetBrowserModel());
|
||||
m_modelTesterFilterModel = AZStd::make_unique<QAbstractItemModelTester>(m_filterModel.get());
|
||||
m_modelTesterTableModel = AZStd::make_unique<QAbstractItemModelTester>(m_tableModel.get());
|
||||
m_searchWidget = AZStd::make_unique<AzToolsFramework::AssetBrowser::SearchWidget>();
|
||||
|
||||
// Setup String filters
|
||||
@@ -110,10 +103,6 @@ namespace UnitTest
|
||||
|
||||
void AssetBrowserTest::TearDownEditorFixtureImpl()
|
||||
{
|
||||
m_modelTesterAssetBrowser.reset();
|
||||
m_modelTesterFilterModel.reset();
|
||||
m_modelTesterTableModel.reset();
|
||||
|
||||
m_tableModel.reset();
|
||||
m_filterModel.reset();
|
||||
m_assetBrowserComponent->Deactivate();
|
||||
|
||||
@@ -12,6 +12,7 @@ set(FILES
|
||||
AssetFileInfoListComparison.cpp
|
||||
AssetSeedManager.cpp
|
||||
AssetSystemMocks.h
|
||||
AzToolsFrameworkTestHelpersTest.cpp
|
||||
BoundsTestComponent.cpp
|
||||
BoundsTestComponent.h
|
||||
ComponentAdapterTests.cpp
|
||||
|
||||
Reference in New Issue
Block a user