Merge remote-tracking branch 'upstream/main' into nvsickle/DebugInfoDisplay

This commit is contained in:
nvsickle
2021-05-12 11:55:51 -07:00
1514 changed files with 30767 additions and 174001 deletions
@@ -761,16 +761,6 @@ namespace AzToolsFramework
/// If the view pane was not registered with the ViewPaneOptions.isDeletable set to true, the view pane will be hidden instead.
virtual void CloseViewPane(const char* /*paneName*/) {}
/// Request generation of all level cubemaps.
virtual void GenerateAllCubemaps() {}
/// Regenerate cubemap for a particular entity.
/// \param entityId ID of the entity that the cubemap is for
/// \param cubemapOutputPath path to a image file to generate
/// \param hideEntity Indicates whether the entity should be hidden during cubemap generation. Controls whether the entity's current cubemap output is baked into the new cubemap.
virtual void GenerateCubemapForEntity(AZ::EntityId /*entityId*/, AZStd::string* /*cubemapOutputPath*/, bool /*hideEntity*/) {}
virtual void GenerateCubemapWithIDForEntity(AZ::EntityId /*entityId*/, AZ::Uuid /*cubemapId*/, AZStd::string* /*cubemapOutputPath*/, bool /*hideEntity*/, bool /*hasCubemapId*/) {}
//! Spawn asset browser for the appropriate asset types.
virtual void BrowseForAssets(AssetBrowser::AssetSelectionModel& /*selection*/) = 0;
@@ -263,8 +263,6 @@ namespace AzToolsFramework
return SourceFileDetails("Icons/AssetBrowser/XML_16.svg");
}
// this is here to prevent having to include IResourceCompilerHelper, which is in CryCommon.
static const char* sourceFormats[] = { ".tif", ".bmp", ".gif", ".jpg", ".jpeg", ".jpe", ".tga", ".png" };
for (unsigned int sourceImageFormatIndex = 0, numSources = AZ_ARRAY_SIZE(sourceFormats); sourceImageFormatIndex < numSources; ++sourceImageFormatIndex)
@@ -52,6 +52,7 @@
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
#include <AzToolsFramework/UI/EditorEntityUi/EditorEntityUiSystemComponent.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerComponent.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerNullComponent.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserComponent.h>
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.h>
@@ -91,6 +92,7 @@ namespace AzToolsFramework
AzToolsFramework::AssetBundleComponent::CreateDescriptor(),
AzToolsFramework::SliceDependencyBrowserComponent::CreateDescriptor(),
AzToolsFramework::Thumbnailer::ThumbnailerComponent::CreateDescriptor(),
AzToolsFramework::Thumbnailer::ThumbnailerNullComponent::CreateDescriptor(),
AzToolsFramework::AssetBrowser::AssetBrowserComponent::CreateDescriptor(),
AzToolsFramework::EditorInteractionSystemComponent::CreateDescriptor(),
AzToolsFramework::Components::EditorComponentAPIComponent::CreateDescriptor(),
@@ -189,9 +189,6 @@ namespace AzToolsFramework
SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusConnect();
EditorLegacyGameModeNotificationBus::Handler::BusConnect();
m_entityVisibilityBoundsUnionSystem.Connect();
}
//=========================================================================
@@ -199,8 +196,6 @@ namespace AzToolsFramework
//=========================================================================
void EditorEntityContextComponent::Deactivate()
{
m_entityVisibilityBoundsUnionSystem.Disconnect();
EditorLegacyGameModeNotificationBus::Handler::BusDisconnect();
SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusDisconnect();
@@ -189,8 +189,6 @@ namespace AzToolsFramework
//! EditorEntityContextRequestBus::Events::AddRequiredComponents()
AZ::ComponentTypeList m_requiredEditorComponentTypes;
//! Edit time visibility management integrating entities with the IVisibilitySystem.
AzFramework::EntityVisibilityBoundsUnionSystem m_entityVisibilityBoundsUnionSystem;
bool m_isLegacySliceService;
UndoSystem::UndoCacheInterface* m_undoCacheInterface = nullptr;
@@ -13,6 +13,7 @@
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Script/ScriptSystemBus.h>
#include <AzCore/Serialization/Utils.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzFramework/Entity/GameEntityContextBus.h>
#include <AzFramework/Spawnable/RootSpawnableInterface.h>
@@ -342,6 +343,65 @@ namespace AzToolsFramework
m_validateEntitiesCallback = AZStd::move(validateEntitiesCallback);
}
void PrefabEditorEntityOwnershipService::LoadReferencedAssets(AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets)
{
// Start our loads on all assets by calling GetAsset from the AssetManager
for (AZ::Data::Asset<AZ::Data::AssetData>& asset : referencedAssets)
{
if (!asset.GetId().IsValid())
{
AZ_Error("Prefab", false, "Invalid asset found referenced in scene while entering game mode");
continue;
}
const AZ::Data::AssetLoadBehavior loadBehavior = asset.GetAutoLoadBehavior();
if (loadBehavior == AZ::Data::AssetLoadBehavior::NoLoad)
{
continue;
}
AZ::Data::AssetId assetId = asset.GetId();
AZ::Data::AssetType assetType = asset.GetType();
asset = AZ::Data::AssetManager::Instance().GetAsset(assetId, assetType, loadBehavior);
if (!asset.GetId().IsValid())
{
AZ_Error("Prefab", false, "Invalid asset found referenced in scene while entering game mode");
continue;
}
}
// For all Preload assets we block until they're ready
// We do this as a seperate pass so that we don't interrupt queuing up all other asset loads
for (AZ::Data::Asset<AZ::Data::AssetData>& asset : referencedAssets)
{
if (!asset.GetId().IsValid())
{
AZ_Error("Prefab", false, "Invalid asset found referenced in scene while entering game mode");
continue;
}
const AZ::Data::AssetLoadBehavior loadBehavior = asset.GetAutoLoadBehavior();
if (loadBehavior != AZ::Data::AssetLoadBehavior::PreLoad)
{
continue;
}
asset.BlockUntilLoadComplete();
if (asset.IsError())
{
AZ_Error("Prefab", false, "Asset with id %s failed to preload while entering game mode",
asset.GetId().ToString<AZStd::string>().c_str());
continue;
}
}
}
void PrefabEditorEntityOwnershipService::StartPlayInEditor()
{
// This is a workaround until the replacement for GameEntityContext is done
@@ -381,16 +441,21 @@ namespace AzToolsFramework
rootSpawnableIndex = m_playInEditorData.m_assets.size();
}
LoadReferencedAssets(product.GetReferencedAssets());
AZ::Data::AssetInfo info;
info.m_assetId = product.GetAsset().GetId();
info.m_assetType = product.GetAssetType();
info.m_relativePath = product.GetId();
AZ::Data::AssetCatalogRequestBus::Broadcast(
&AZ::Data::AssetCatalogRequestBus::Events::RegisterAsset, product.GetAsset().GetId(), info);
&AZ::Data::AssetCatalogRequestBus::Events::RegisterAsset, info.m_assetId, info);
m_playInEditorData.m_assets.emplace_back(product.ReleaseAsset().release(), AZ::Data::AssetLoadBehavior::Default);
}
// make sure that PRE_NOTIFY assets get their notify before we activate, so that we can preserve the order of
// (load asset) -> (notify) -> (init) -> (activate)
AZ::Data::AssetManager::Instance().DispatchEvents();
if (rootSpawnableIndex != NoRootSpawnable)
{
@@ -199,6 +199,8 @@ namespace AzToolsFramework
void OnEntityRemoved(AZ::EntityId entityId);
void LoadReferencedAssets(AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets);
OnEntitiesAddedCallback m_entitiesAddedCallback;
OnEntitiesRemovedCallback m_entitiesRemovedCallback;
ValidateEntitiesCallback m_validateEntitiesCallback;
@@ -85,14 +85,14 @@ namespace AzToolsFramework
// if we're snapping, only increment current radians when we know
// preSnapRadians is greater than the angleStep
if (snapping)
if (snapping && AZStd::abs(angleStepDegrees) > 0.0f)
{
actionInternal.m_current.m_preSnapRadians += rotationAngleRad * rotateSign;
const float angleStepRad = AZ::DegToRad(angleStepDegrees);
const float preSnapRotateSign = Sign(actionInternal.m_current.m_preSnapRadians);
// if we move more than angleStep in a frame, make sure we catch up
while (fabsf(actionInternal.m_current.m_preSnapRadians) >= angleStepRad)
while (AZStd::abs(actionInternal.m_current.m_preSnapRadians) >= angleStepRad)
{
actionInternal.m_current.m_radians += angleStepRad * preSnapRotateSign;
actionInternal.m_current.m_preSnapRadians -= angleStepRad * preSnapRotateSign;
@@ -11,8 +11,10 @@
*/
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Asset/AssetJsonSerializer.h>
#include <AzCore/JSON/prettywriter.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
@@ -115,6 +117,48 @@ namespace AzToolsFramework
return true;
}
bool LoadInstanceFromPrefabDom(
Instance& instance, const PrefabDom& prefabDom, AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets, LoadInstanceFlags 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
// is avoided.
AZ::Data::AssetManager::Instance().SuspendAssetRelease();
InstanceEntityIdMapper entityIdMapper;
entityIdMapper.SetLoadingInstance(instance);
if ((flags & LoadInstanceFlags::AssignRandomEntityId) == LoadInstanceFlags::AssignRandomEntityId)
{
entityIdMapper.SetEntityIdGenerationApproach(InstanceEntityIdMapper::EntityIdGenerationApproach::Random);
}
AZ::JsonDeserializerSettings settings;
// The InstanceEntityIdMapper is registered twice because it's used in several places during deserialization where one is
// specific for the InstanceEntityIdMapper and once for the generic JsonEntityIdMapper. Because the Json Serializer's meta
// data has strict typing and doesn't look for inheritance both have to be explicitly added so they're found both locations.
settings.m_metadata.Add(static_cast<AZ::JsonEntityIdSerializer::JsonEntityIdMapper*>(&entityIdMapper));
settings.m_metadata.Add(&entityIdMapper);
settings.m_metadata.Create<AZ::Data::SerializedAssetTracker>();
AZ::JsonSerializationResult::ResultCode result =
AZ::JsonSerialization::Load(instance, prefabDom, settings);
AZ::Data::AssetManager::Instance().ResumeAssetRelease();
if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted)
{
AZ_Error("Prefab", false,
"Failed to de-serialize Prefab Instance from Prefab DOM. "
"Unable to proceed.");
return false;
}
AZ::Data::SerializedAssetTracker* assetTracker = settings.m_metadata.Find<AZ::Data::SerializedAssetTracker>();
referencedAssets = AZStd::move(assetTracker->GetTrackedAssets());
return true;
}
bool LoadInstanceFromPrefabDom(
Instance& instance, Instance::EntityList& newlyAddedEntities, const PrefabDom& prefabDom, LoadInstanceFlags flags)
{
@@ -13,6 +13,7 @@
#pragma once
#include <AzCore/std/optional.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
#include <AzToolsFramework/Prefab/PrefabDomTypes.h>
@@ -42,7 +43,7 @@ namespace AzToolsFramework
/**
* Stores a valid Prefab Instance within a Prefab Dom. Useful for generating Templates
* @param instance The instance to store
* @param prefabDom the prefabDom that will be used to store the Instance data
* @param prefabDom The prefabDom that will be used to store the Instance data
* @return bool on whether the operation succeeded
*/
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom);
@@ -60,20 +61,32 @@ namespace AzToolsFramework
/**
* Loads a valid Prefab Instance from a Prefab Dom. Useful for generating Instances.
* @param instance The Instance to load.
* @param prefabDom the prefabDom that will be used to load the Instance data.
* @param shouldClearContainers whether to clear containers in Instance while loading.
* @param prefabDom The prefabDom that will be used to load the Instance data.
* @param shouldClearContainers Whether to clear containers in Instance while loading.
* @return bool on whether the operation succeeded.
*/
bool LoadInstanceFromPrefabDom(
Instance& instance, const PrefabDom& prefabDom, LoadInstanceFlags flags = LoadInstanceFlags::None);
/**
* Loads a valid Prefab Instance from a Prefab Dom. Useful for generating Instances.
* @param instance The Instance to load.
* @param referencedAssets AZ::Assets discovered during json load are added to this list
* @param prefabDom The prefabDom that will be used to load the Instance data.
* @param shouldClearContainers Whether to clear containers in Instance while loading.
* @return bool on whether the operation succeeded.
*/
bool LoadInstanceFromPrefabDom(
Instance& instance, const PrefabDom& prefabDom, AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets,
LoadInstanceFlags flags = LoadInstanceFlags::None);
/**
* Loads a valid Prefab Instance from a Prefab Dom. Useful for generating Instances.
* @param instance The Instance to load.
* @param newlyAddedEntities The new instances added during deserializing the instance. These are the entities found
* in the prefabDom.
* @param prefabDom the prefabDom that will be used to load the Instance data.
* @param shouldClearContainers whether to clear containers in Instance while loading.
* @param prefabDom The prefabDom that will be used to load the Instance data.
* @param shouldClearContainers Whether to clear containers in Instance while loading.
* @return bool on whether the operation succeeded.
*/
bool LoadInstanceFromPrefabDom(
@@ -89,7 +89,7 @@ namespace AzToolsFramework
if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances))
{
return AZ::Failure(
AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
AZStd::string("Could not create a new prefab out of the entities provided - invalid selection."));
}
// When we create a prefab with other prefab instances, we have to remove the existing links between the source and
@@ -140,9 +140,13 @@ namespace AzToolsFramework
// Mark them as dirty so this change is correctly applied to the template
for (AZ::Entity* topLevelEntity : topLevelEntities)
{
m_prefabUndoCache.UpdateCache(topLevelEntity->GetId());
undoBatch.MarkEntityDirty(topLevelEntity->GetId());
AZ::TransformBus::Event(topLevelEntity->GetId(), &AZ::TransformBus::Events::SetParent, containerEntityId);
AZ::EntityId topLevelEntityId = topLevelEntity->GetId();
if (topLevelEntityId.IsValid())
{
m_prefabUndoCache.UpdateCache(topLevelEntityId);
undoBatch.MarkEntityDirty(topLevelEntityId);
AZ::TransformBus::Event(topLevelEntityId, &AZ::TransformBus::Events::SetParent, containerEntityId);
}
}
// Select Container Entity
@@ -182,6 +186,22 @@ namespace AzToolsFramework
instanceToParentUnder = prefabEditorEntityOwnershipInterface->GetRootPrefabInstance();
parent = instanceToParentUnder->get().GetContainerEntityId();
}
//Detect whether this instantiation would produce a cyclical dependency
auto relativePath = m_prefabLoaderInterface->GetRelativePathToProject(filePath);
Prefab::TemplateId templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(relativePath);
// If the template isn't currently loaded, there's no way for it to be in the hierarchy so we just skip the check.
if (templateId != Prefab::InvalidTemplateId && IsPrefabInInstanceAncestorHierarchy(templateId, instanceToParentUnder->get()))
{
return AZ::Failure(
AZStd::string::format(
"Instantiate Prefab operation aborted - Cyclical dependency detected\n(%s depends on %s).",
relativePath.Native().c_str(),
instanceToParentUnder->get().GetTemplateSourcePath().Native().c_str()
)
);
}
{
// Initialize Undo Batch object
@@ -192,7 +212,7 @@ namespace AzToolsFramework
instanceToParentUnderDomBeforeCreate, instanceToParentUnder->get());
// Instantiate the Prefab
auto instanceToCreate = prefabEditorEntityOwnershipInterface->InstantiatePrefab(filePath, instanceToParentUnder);
auto instanceToCreate = prefabEditorEntityOwnershipInterface->InstantiatePrefab(relativePath, instanceToParentUnder);
if (!instanceToCreate)
{
@@ -221,6 +241,21 @@ namespace AzToolsFramework
// Retrieve entityList from entityIds
inputEntityList = EntityIdListToEntityList(entityIds);
// Remove Level Container Entity if it's part of the list
AZ::EntityId levelEntityId = GetLevelInstanceContainerEntityId();
if (levelEntityId.IsValid())
{
AZ::Entity* levelEntity = GetEntityById(levelEntityId);
if (levelEntity)
{
auto levelEntityIter = AZStd::find(inputEntityList.begin(), inputEntityList.end(), levelEntity);
if (levelEntityIter != inputEntityList.end())
{
inputEntityList.erase(levelEntityIter);
}
}
}
// Find common root and top level entities
bool entitiesHaveCommonRoot = false;
@@ -242,6 +277,23 @@ namespace AzToolsFramework
return AZ::Success();
}
bool PrefabPublicHandler::IsPrefabInInstanceAncestorHierarchy(TemplateId prefabTemplateId, InstanceOptionalConstReference instance)
{
InstanceOptionalConstReference currentInstance = instance;
while (currentInstance.has_value())
{
if (currentInstance->get().GetTemplateId() == prefabTemplateId)
{
return true;
}
currentInstance = currentInstance->get().GetParentInstance();
}
return false;
}
void PrefabPublicHandler::CreateLink(
const EntityList& topLevelEntities, Instance& sourceInstance, TemplateId targetTemplateId,
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId commonRootEntityId)
@@ -774,6 +826,11 @@ namespace AzToolsFramework
const EntityList& inputEntities, Instance& commonRootEntityOwningInstance,
EntityList& outEntities, AZStd::vector<AZStd::unique_ptr<Instance>>& outInstances) const
{
if (inputEntities.size() == 0)
{
return false;
}
AZStd::queue<AZ::Entity*> entityQueue;
for (auto inputEntity : inputEntities)
@@ -861,7 +918,7 @@ namespace AzToolsFramework
outInstances.push_back(AZStd::move(commonRootEntityOwningInstance.DetachNestedInstance(instancePtr->GetInstanceAlias())));
}
return true;
return (outEntities.size() + outInstances.size()) > 0;
}
bool PrefabPublicHandler::EntitiesBelongToSameInstance(const EntityIdList& entityIds) const
@@ -106,6 +106,14 @@ namespace AzToolsFramework
const AZStd::vector<AZ::EntityId>& entityIds, EntityList& inputEntityList, EntityList& topLevelEntities,
AZ::EntityId& commonRootEntityId, InstanceOptionalReference& commonRootEntityOwningInstance);
/* Detects whether an instance of prefabTemplateId is present in the hierarchy of ancestors of instance.
*
* \param prefabTemplateId The template id to test for
* \param instance The instance whose ancestor hierarchy prefabTemplateId will be tested against.
* \return true if an instance of the template of id prefabTemplateId could be found in the ancestor hierarchy of instance, false otherwise.
*/
bool IsPrefabInInstanceAncestorHierarchy(TemplateId prefabTemplateId, InstanceOptionalConstReference instance);
static Instance* GetParentInstance(Instance* instance);
static Instance* GetAncestorOfInstanceThatIsChildOfRoot(const Instance* ancestor, Instance* descendant);
static void GenerateContainerEntityTransform(const EntityList& topLevelEntities, AZ::Vector3& translation, AZ::Quaternion& rotation);
@@ -721,6 +721,8 @@ namespace AzToolsFramework
TemplateId PrefabSystemComponent::GetTemplateIdFromFilePath(AZ::IO::PathView filePath) const
{
AZ_Assert(!filePath.IsAbsolute(), "Prefab - GetTemplateIdFromFilePath was passed an absolute path. Prefabs use paths relative to the project folder.");
auto found = m_templateFilePathToIdMap.find(filePath);
if (found != m_templateFilePathToIdMap.end())
{
@@ -63,7 +63,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
AZStd::move(uniqueName), context.GetSourceUuid(), AZStd::move(serializer));
AZ_Assert(spawnable, "Failed to create a new spawnable.");
bool result = SpawnableUtils::CreateSpawnable(*spawnable, prefab);
bool result = SpawnableUtils::CreateSpawnable(*spawnable, prefab, object.GetReferencedAssets());
if (result)
{
AzFramework::Spawnable::EntityList& entities = spawnable->GetEntities();
@@ -84,8 +84,6 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
}
SpawnableUtils::SortEntitiesByTransformHierarchy(*spawnable);
context.GetProcessedObjects().push_back(AZStd::move(object));
context.RemovePrefab(prefabName);
}
else
{
@@ -10,6 +10,8 @@
*
*/
#include <AzFramework/Spawnable/Spawnable.h>
#include <AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h>
namespace AzToolsFramework::Prefab::PrefabConversionUtils
@@ -24,37 +26,14 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
return result.second;
}
bool PrefabProcessorContext::RemovePrefab(AZStd::string_view prefabName)
{
if (!m_isIterating)
{
return m_prefabs.erase(prefabName) > 0;
}
else
{
m_delayedDelete.emplace_back(prefabName);
}
return false;
}
void PrefabProcessorContext::ListPrefabs(const AZStd::function<void(AZStd::string_view, PrefabDom&)>& callback)
{
m_isIterating = true;
for (auto& it : m_prefabs)
{
if (AZStd::find(m_delayedDelete.begin(), m_delayedDelete.end(), it.first) == m_delayedDelete.end())
{
callback(it.first, it.second);
}
callback(it.first, it.second);
}
m_isIterating = false;
// Clear out any prefabs that have been deleted.
for (AZStd::string& deleted : m_delayedDelete)
{
m_prefabs.erase(deleted);
}
m_delayedDelete.clear();
}
void PrefabProcessorContext::ListPrefabs(const AZStd::function<void(AZStd::string_view, const PrefabDom&)>& callback) const
@@ -70,6 +49,44 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
return !m_prefabs.empty();
}
bool PrefabProcessorContext::RegisterSpawnableProductAssetDependency(AZStd::string prefabName, AZStd::string dependentPrefabName)
{
using ConversionUtils = PrefabConversionUtils::ProcessedObjectStore;
prefabName += AzFramework::Spawnable::DotFileExtension;
uint32_t spawnableSubId = ConversionUtils::BuildSubId(AZStd::move(prefabName));
dependentPrefabName += AzFramework::Spawnable::DotFileExtension;
uint32_t spawnablePrefabSubId = ConversionUtils::BuildSubId(AZStd::move(dependentPrefabName));
return RegisterSpawnableProductAssetDependency(spawnableSubId, spawnablePrefabSubId);
}
bool PrefabProcessorContext::RegisterSpawnableProductAssetDependency(AZStd::string prefabName, const AZ::Data::AssetId& dependentAssetId)
{
using ConversionUtils = PrefabConversionUtils::ProcessedObjectStore;
prefabName += AzFramework::Spawnable::DotFileExtension;
uint32_t spawnableSubId = ConversionUtils::BuildSubId(AZStd::move(prefabName));
AZ::Data::AssetId spawnableAssetId(GetSourceUuid(), spawnableSubId);
return RegisterProductAssetDependency(spawnableAssetId, dependentAssetId);
}
bool PrefabProcessorContext::RegisterSpawnableProductAssetDependency(uint32_t spawnableAssetSubId, uint32_t dependentSpawnableAssetSubId)
{
AZ::Data::AssetId spawnableAssetId(GetSourceUuid(), spawnableAssetSubId);
AZ::Data::AssetId dependentSpawnableAssetId(GetSourceUuid(), dependentSpawnableAssetSubId);
return RegisterProductAssetDependency(spawnableAssetId, dependentSpawnableAssetId);
}
bool PrefabProcessorContext::RegisterProductAssetDependency(const AZ::Data::AssetId& assetId, const AZ::Data::AssetId& dependentAssetId)
{
return m_registeredProductAssetDependencies[assetId].emplace(dependentAssetId).second;
}
PrefabProcessorContext::ProcessedObjectStoreContainer& PrefabProcessorContext::GetProcessedObjects()
{
return m_products;
@@ -80,6 +97,16 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
return m_products;
}
PrefabProcessorContext::ProductAssetDependencyContainer& PrefabProcessorContext::GetRegisteredProductAssetDependencies()
{
return m_registeredProductAssetDependencies;
}
const PrefabProcessorContext::ProductAssetDependencyContainer& PrefabProcessorContext::GetRegisteredProductAssetDependencies() const
{
return m_registeredProductAssetDependencies;
}
void PrefabProcessorContext::SetPlatformTags(AZ::PlatformTagSet tags)
{
m_platformTags = AZStd::move(tags);
@@ -29,6 +29,8 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
{
public:
using ProcessedObjectStoreContainer = AZStd::vector<ProcessedObjectStore>;
using ProductAssetDependencyContainer =
AZStd::unordered_map<AZ::Data::AssetId, AZStd::unordered_set<AZ::Data::AssetId>>;
AZ_CLASS_ALLOCATOR(PrefabProcessorContext, AZ::SystemAllocator, 0);
AZ_RTTI(PrefabProcessorContext, "{C7D77E3A-C544-486B-B774-7C82C38FE22F}");
@@ -37,14 +39,21 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
virtual ~PrefabProcessorContext() = default;
virtual bool AddPrefab(AZStd::string prefabName, PrefabDom prefab);
virtual bool RemovePrefab(AZStd::string_view prefabName);
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 HasPrefabs() const;
virtual bool RegisterSpawnableProductAssetDependency(AZStd::string prefabName, AZStd::string dependentPrefabName);
virtual bool RegisterSpawnableProductAssetDependency(AZStd::string prefabName, const AZ::Data::AssetId& dependentAssetId);
virtual bool RegisterSpawnableProductAssetDependency(uint32_t spawnableAssetSubId, uint32_t dependentSpawnableAssetSubId);
virtual bool RegisterProductAssetDependency(const AZ::Data::AssetId& assetId, const AZ::Data::AssetId& dependentAssetId);
virtual ProcessedObjectStoreContainer& GetProcessedObjects();
virtual const ProcessedObjectStoreContainer& GetProcessedObjects() const;
virtual ProductAssetDependencyContainer& GetRegisteredProductAssetDependencies();
virtual const ProductAssetDependencyContainer& GetRegisteredProductAssetDependencies() const;
virtual void SetPlatformTags(AZ::PlatformTagSet tags);
virtual const AZ::PlatformTagSet& GetPlatformTags() const;
virtual const AZ::Uuid& GetSourceUuid() const;
@@ -57,7 +66,8 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
NamedPrefabContainer m_prefabs;
ProcessedObjectStoreContainer m_products;
AZStd::vector<AZStd::string> m_delayedDelete;
ProductAssetDependencyContainer m_registeredProductAssetDependencies;
AZ::PlatformTagSet m_platformTags;
AZ::Uuid m_sourceUuid;
bool m_isIterating{ false };
@@ -56,6 +56,16 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
return *m_asset;
}
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& ProcessedObjectStore::GetReferencedAssets()
{
return m_referencedAssets;
}
const AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& ProcessedObjectStore::GetReferencedAssets() const
{
return m_referencedAssets;
}
AZStd::unique_ptr<AZ::Data::AssetData> ProcessedObjectStore::ReleaseAsset()
{
return AZStd::move(m_asset);
@@ -48,6 +48,10 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
AZ::Data::AssetData& GetAsset();
AZStd::unique_ptr<AZ::Data::AssetData> ReleaseAsset();
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& GetReferencedAssets();
const AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& GetReferencedAssets() const;
const AZStd::string& GetId() const;
private:
@@ -55,6 +59,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
SerializerFunction m_assetSerializer;
AZStd::unique_ptr<AZ::Data::AssetData> m_asset;
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>> m_referencedAssets;
AZStd::string m_uniqueId;
};
@@ -28,16 +28,23 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
AzFramework::Spawnable CreateSpawnable(const PrefabDom& prefabDom)
{
AzFramework::Spawnable spawnable;
[[maybe_unused]] bool result = CreateSpawnable(spawnable, prefabDom);
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>> referencedAssets;
[[maybe_unused]] bool result = CreateSpawnable(spawnable, prefabDom, referencedAssets);
AZ_Assert(result,
"Failed to Load Prefab Instance from given Prefab DOM while Spawnable creation.");
return spawnable;
}
bool CreateSpawnable(AzFramework::Spawnable& spawnable, const PrefabDom& prefabDom)
{
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>> referencedAssets;
return CreateSpawnable(spawnable, prefabDom, referencedAssets);
}
bool CreateSpawnable(AzFramework::Spawnable& spawnable, const PrefabDom& prefabDom, AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets)
{
Instance instance;
if (Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(instance, prefabDom,
if (Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(instance, prefabDom, referencedAssets,
Prefab::PrefabDomUtils::LoadInstanceFlags::AssignRandomEntityId)) // Always assign random entity ids because the spawnable is
// going to be used to create clones of the entities.
{
@@ -19,6 +19,7 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
{
AzFramework::Spawnable CreateSpawnable(const PrefabDom& prefabDom);
bool CreateSpawnable(AzFramework::Spawnable& spawnable, const PrefabDom& prefabDom);
bool CreateSpawnable(AzFramework::Spawnable& spawnable, const PrefabDom& prefabDom, AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets);
void SortEntitiesByTransformHierarchy(AzFramework::Spawnable& spawnable);
} // namespace AzToolsFramework::Prefab::SpawnableUtils
@@ -1353,7 +1353,7 @@ namespace AzToolsFramework
// Iterate over the entities left in the instance and if none of them have this
// asset entity as its ancestor, then we want to remove it.
// \todo - Investigate ways to make this non-linear time. Tricky since removed entities
// obviously aren't maintained in any maps. (https://jira.agscollab.com/browse/LY-88218)
// obviously aren't maintained in any maps. (LY-88218)
bool foundAsAncestor = false;
for (const AZ::Entity* instanceEntity : instanceEntities)
{
@@ -0,0 +1,85 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerNullComponent.h>
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
#include <AzToolsFramework/Thumbnails/MissingThumbnail.h>
namespace AzToolsFramework
{
namespace Thumbnailer
{
ThumbnailerNullComponent::ThumbnailerNullComponent() :
m_nullThumbnail()
{
}
ThumbnailerNullComponent::~ThumbnailerNullComponent() = default;
void ThumbnailerNullComponent::Activate()
{
BusConnect();
}
void ThumbnailerNullComponent::Deactivate()
{
BusDisconnect();
}
void ThumbnailerNullComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
if (serialize)
{
serialize->Class<ThumbnailerNullComponent, AZ::Component>();
}
}
void ThumbnailerNullComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
{
services.push_back(AZ_CRC("ThumbnailerService", 0x65422b97));
}
void ThumbnailerNullComponent::RegisterContext(const char* /*contextName*/)
{
}
void ThumbnailerNullComponent::UnregisterContext(const char* /*contextName*/)
{
}
bool ThumbnailerNullComponent::HasContext(const char* /*contextName*/) const
{
return false;
}
void ThumbnailerNullComponent::RegisterThumbnailProvider(AzToolsFramework::Thumbnailer::SharedThumbnailProvider /*provider*/, const char* /*contextName*/)
{
}
void ThumbnailerNullComponent::UnregisterThumbnailProvider(const char* /*providerName*/, const char* /*contextName*/)
{
}
AzToolsFramework::Thumbnailer::SharedThumbnail ThumbnailerNullComponent::GetThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey /*key*/, const char* /*contextName*/)
{
return m_nullThumbnail;
}
bool ThumbnailerNullComponent::IsLoading(AzToolsFramework::Thumbnailer::SharedThumbnailKey /*thumbnailKey*/, const char* /*contextName*/)
{
return false;
}
} // namespace Thumbnailer
} // namespace AzToolsFramework
@@ -0,0 +1,60 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Component/Component.h>
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
// ThumbnailerNullComponent is an alternative to ThumbnailerComponent that can be used by tools that don't use Qt.
// It doesn't do anything (hence "null"), but it allows the system and editor components that rely on the ThumbnailService
// to start up and function.
namespace AzToolsFramework
{
namespace Thumbnailer
{
class ThumbnailContext;
class ThumbnailerNullComponent
: public AZ::Component
, public AzToolsFramework::Thumbnailer::ThumbnailerRequestsBus::Handler
{
public:
AZ_COMPONENT(ThumbnailerNullComponent, "{8009D651-3FAA-9815-B99E-AF174A3B29D4}")
ThumbnailerNullComponent();
virtual ~ThumbnailerNullComponent();
//////////////////////////////////////////////////////////////////////////
// AZ::Component
//////////////////////////////////////////////////////////////////////////
void Activate() override;
void Deactivate() override;
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services);
//////////////////////////////////////////////////////////////////////////
// ThumbnailerRequests
//////////////////////////////////////////////////////////////////////////
void RegisterContext(const char* contextName) override;
void UnregisterContext(const char* contextName) override;
bool HasContext(const char* contextName) const override;
void RegisterThumbnailProvider(AzToolsFramework::Thumbnailer::SharedThumbnailProvider provider, const char* contextName) override;
void UnregisterThumbnailProvider(const char* providerName, const char* contextName) override;
AzToolsFramework::Thumbnailer::SharedThumbnail GetThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, const char* contextName) override;
bool IsLoading(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, const char* contextName) override;
private:
AzToolsFramework::Thumbnailer::SharedThumbnail m_nullThumbnail;
};
} // Thumbnailer
} // namespace AzToolsFramework
@@ -25,6 +25,7 @@
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzFramework/Components/TransformComponent.h>
#include <AzFramework/Visibility/EntityBoundsUnionBus.h>
#include <AzToolsFramework/API/EntityCompositionRequestBus.h>
#include <AzToolsFramework/API/EntityPropertyEditorRequestsBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
@@ -265,7 +266,13 @@ namespace AzToolsFramework
AZ::TransformNotificationBus::Event(
GetEntityId(), &TransformNotification::OnTransformChanged, localTM, worldTM);
m_transformChangedEvent.Signal(localTM, worldTM);
AzFramework::IEntityBoundsUnion* boundsUnion = AZ::Interface<AzFramework::IEntityBoundsUnion>::Get();
if (boundsUnion != nullptr)
{
boundsUnion->OnTransformUpdated(GetEntity());
}
// Fire a property changed notification for this component
if (const AZ::Component* component = entity->FindComponent<Components::TransformComponent>())
{
@@ -950,15 +957,14 @@ namespace AzToolsFramework
{
return nullptr;
}
AZ::Entity* pEntity = nullptr;
EBUS_EVENT_RESULT(pEntity, AZ::ComponentApplicationBus, FindEntity, otherEntityId);
if (!pEntity)
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(otherEntityId);
if (!entity)
{
return nullptr;
}
return pEntity->FindComponent<TransformComponent>();
return entity->FindComponent<TransformComponent>();
}
AZ::TransformInterface* TransformComponent::GetParent()
@@ -1297,7 +1303,6 @@ namespace AzToolsFramework
Field("Cached World Transform Parent", &TransformComponent::m_cachedWorldTransformParent)->
Field("Parent Activation Transform Mode", &TransformComponent::m_parentActivationTransformMode)->
Field("IsStatic", &TransformComponent::m_isStatic)->
Field("Sync Enabled", &TransformComponent::m_netSyncEnabled)->
Field("InterpolatePosition", &TransformComponent::m_interpolatePosition)->
Field("InterpolateRotation", &TransformComponent::m_interpolateRotation)->
Version(9, &Internal::TransformComponentDataConverter);
@@ -1332,21 +1337,7 @@ namespace AzToolsFramework
Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Hide)->
DataElement(AZ::Edit::UIHandlers::Default, &TransformComponent::m_cachedWorldTransform, "Cached World Transform", "")->
Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::NotPushable)->
Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Hide)->
ClassElement(AZ::Edit::ClassElements::Group, "Network Sync")->
Attribute(AZ::Edit::Attributes::AutoExpand, true)->
DataElement(AZ::Edit::UIHandlers::Default, &TransformComponent::m_netSyncEnabled, "Sync to replicas", "Sync to network replicas.")->
DataElement(AZ::Edit::UIHandlers::ComboBox, &TransformComponent::m_interpolatePosition,
"Position Interpolation", "Enable local interpolation of position.")->
EnumAttribute(AZ::InterpolationMode::NoInterpolation, "None")->
EnumAttribute(AZ::InterpolationMode::LinearInterpolation, "Linear")->
DataElement(AZ::Edit::UIHandlers::ComboBox, &TransformComponent::m_interpolateRotation,
"Rotation Interpolation", "Enable local interpolation of rotation.")->
EnumAttribute(AZ::InterpolationMode::NoInterpolation, "None")->
EnumAttribute(AZ::InterpolationMode::LinearInterpolation, "Linear");
Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Hide);
ptrEdit->Class<EditorTransform>("Values", "XYZ PYR")->
DataElement(AZ::Edit::UIHandlers::Default, &EditorTransform::m_translate, "Translate", "Local Position (Relative to parent) in meters.")->
@@ -151,32 +151,36 @@ namespace AzToolsFramework
{
if (!selectedEntities.empty())
{
bool layerInSelection = false;
for (AZ::EntityId entityId : selectedEntities)
// Hide if the only selected entity is the Level Container
if (selectedEntities.size() > 1 || !s_prefabPublicInterface->IsLevelInstanceContainerEntity(selectedEntities[0]))
{
if (!layerInSelection)
{
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
layerInSelection, entityId,
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
bool layerInSelection = false;
if (layerInSelection)
for (AZ::EntityId entityId : selectedEntities)
{
if (!layerInSelection)
{
break;
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
layerInSelection, entityId,
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
if (layerInSelection)
{
break;
}
}
}
}
// Layers can't be in prefabs.
if (!layerInSelection)
{
QAction* createAction = menu->addAction(QObject::tr("Create Prefab..."));
createAction->setToolTip(QObject::tr("Creates a prefab out of the currently selected entities."));
// Layers can't be in prefabs.
if (!layerInSelection)
{
QAction* createAction = menu->addAction(QObject::tr("Create Prefab..."));
createAction->setToolTip(QObject::tr("Creates a prefab out of the currently selected entities."));
QObject::connect(createAction, &QAction::triggered, createAction, [this, selectedEntities] {
ContextMenu_CreatePrefab(selectedEntities);
});
QObject::connect(createAction, &QAction::triggered, createAction, [this, selectedEntities] {
ContextMenu_CreatePrefab(selectedEntities);
});
}
}
}
}
@@ -272,6 +276,15 @@ namespace AzToolsFramework
QWidget* activeWindow = QApplication::activeWindow();
const AZStd::string prefabFilesPath = "@devassets@/Prefabs";
// Remove Level entity if it's part of the list
auto levelContainerIter =
AZStd::find(selectedEntities.begin(), selectedEntities.end(), s_prefabPublicInterface->GetLevelInstanceContainerEntityId());
if (levelContainerIter != selectedEntities.end())
{
selectedEntities.erase(levelContainerIter);
}
// Set default folder for prefabs
AZ::IO::FileIOBase* fileIoBaseInstance = AZ::IO::FileIOBase::GetInstance();
@@ -335,6 +335,7 @@ namespace AzToolsFramework
m_gui->m_entityDetailsLabel->setObjectName("LabelEntityDetails");
m_gui->m_entitySearchBox->setReadOnly(false);
m_gui->m_entitySearchBox->setContextMenuPolicy(Qt::CustomContextMenu);
m_gui->m_entitySearchBox->setClearButtonEnabled(true);
AzQtComponents::LineEdit::applySearchStyle(m_gui->m_entitySearchBox);
AzFramework::ApplicationRequests::Bus::BroadcastResult(
@@ -63,23 +63,40 @@ namespace AzToolsFramework
void PropertyManagerComponent::Deactivate()
{
// Delete all remaining auto-delete or built-in handlers.
for (auto it = m_builtInHandlers.begin(); it != m_builtInHandlers.end(); ++it)
{
UnregisterPropertyType(*it);
#ifdef AZ_DEBUG_BUILD
// For debug builds, we'll take the extra time to delete each handler that we're deleting from m_Handlers.
// We loop through m_Handlers below to ensure that we don't have any other handlers still registered after
// we've deleted these.
AZStd::erase_if(m_Handlers, [it](const auto& item) {
auto const& [key, value] = item;
return (key == (*it)->GetHandlerName()) && (value == (*it));
});
#endif
delete *it;
}
m_builtInHandlers.clear();
#ifdef _DEBUG
#ifdef AZ_DEBUG_BUILD
// Loop through all the remaining registered handlers (if any) and print out an error, as these all are probably memory
// leaks. UnregisterPropertyType should have been called on these already, and their pointers should have been deleted
// by the caller.
auto it = m_Handlers.begin();
while (it != m_Handlers.end())
{
AZ_Error("PropertyManager", false, "Property Handler 0x%08x is still registered during shutdown", it->first);
++it;
}
#endif
#endif
m_Handlers.clear();
m_DefaultHandlers.clear();
PropertyTypeRegistrationMessages::Bus::Handler::BusDisconnect();
}
@@ -142,6 +159,16 @@ namespace AzToolsFramework
}
++defaultIt;
}
if (pHandler->AutoDelete())
{
m_builtInHandlers.erase(AZStd::remove(m_builtInHandlers.begin(), m_builtInHandlers.end(), pHandler),
m_builtInHandlers.end());
AZ_Assert(false,
"Handlers with AutoDelete set should not call UnregisterPropertyType. To fix, do one of the following:\n"
" 1. Set AutoDelete to false in the handler, call UnregisterPropertyType, and the caller should delete the handler.\n"
" 2. Set AutoDelete to true in the handler and do NOT call UnregisterPropertyType or delete the handler.");
}
}
@@ -68,6 +68,7 @@ namespace AzToolsFramework
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
const AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
AzFramework::EntityDebugDisplayEventBus::Event(
entityId, &AzFramework::EntityDebugDisplayEvents::DisplayEntityViewport,
viewportInfo, debugDisplay);
@@ -84,10 +85,9 @@ namespace AzToolsFramework
if (ed_visibility_showAggregateEntityTransformedLocalBounds)
{
AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM);
AZ::Transform worldFromLocal = entity->GetTransform()->GetWorldTM();
if (const AZ::Aabb localAabb = AzFramework::CalculateEntityLocalBoundsUnion(entityId); localAabb.IsValid())
if (const AZ::Aabb localAabb = AzFramework::CalculateEntityLocalBoundsUnion(entity); localAabb.IsValid())
{
const AZ::Aabb worldAabb = localAabb.GetTransformedAabb(worldFromLocal);
debugDisplay.SetColor(AZ::Colors::Turquoise);
@@ -97,7 +97,7 @@ namespace AzToolsFramework
if (ed_visibility_showAggregateEntityWorldBounds)
{
if (const AZ::Aabb worldAabb = AzFramework::CalculateEntityWorldBoundsUnion(entityId); worldAabb.IsValid())
if (const AZ::Aabb worldAabb = AzFramework::CalculateEntityWorldBoundsUnion(entity); worldAabb.IsValid())
{
debugDisplay.SetColor(AZ::Colors::Magenta);
debugDisplay.DrawWireBox(worldAabb.GetMin(), worldAabb.GetMax());
@@ -13,7 +13,9 @@
#include "EditorSelectionUtil.h"
#include <AzCore/Math/Aabb.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/Math/IntersectSegment.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzFramework/Visibility/BoundsBus.h>
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
@@ -28,7 +30,8 @@ namespace AzToolsFramework
{
if (Centered(pivot))
{
if (const AZ::Aabb localBound = AzFramework::CalculateEntityLocalBoundsUnion(entityId);
const AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId);
if (const AZ::Aabb localBound = AzFramework::CalculateEntityLocalBoundsUnion(entity);
localBound.IsValid())
{
return localBound.GetCenter();
@@ -13,6 +13,9 @@
#include "EditorTransformComponentSelection.h"
#include <AzCore/std/algorithm.h>
#include <AzCore/Math/Matrix3x3.h>
#include <AzCore/Math/Matrix3x4.h>
#include <AzCore/Math/Matrix4x4.h>
#include <AzCore/Math/VectorConversions.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzFramework/Viewport/CameraState.h>
@@ -72,6 +72,8 @@ set(FILES
AssetCatalog/PlatformAddressedAssetCatalogManager.cpp
Thumbnails/ThumbnailerComponent.cpp
Thumbnails/ThumbnailerComponent.h
Thumbnails/ThumbnailerNullComponent.cpp
Thumbnails/ThumbnailerNullComponent.h
Thumbnails/LoadingThumbnail.cpp
Thumbnails/LoadingThumbnail.h
Thumbnails/MissingThumbnail.cpp
@@ -211,6 +211,15 @@ namespace UnitTest
EXPECT_EQ(screenPoint, ScreenPoint(45, 170));
}
TEST(ViewportScreen, ScreenVectorLengthReturned)
{
using AzFramework::ScreenVector;
EXPECT_NEAR(AzFramework::ScreenVectorLength(ScreenVector(1, 1)), 1.41421f, 0.001f);
EXPECT_NEAR(AzFramework::ScreenVectorLength(ScreenVector(3, 4)), 5.0f, 0.001f);
EXPECT_NEAR(AzFramework::ScreenVectorLength(ScreenVector(12, 15)), 19.20937f, 0.001f);
}
TEST(ViewportScreen, CanGetCameraTransformFromCameraViewAndBack)
{
const auto screenDimensions = AZ::Vector2(1024.0f, 768.0f);
@@ -62,8 +62,8 @@ namespace UnitTest
SetupRowOfEntities(AZ::Vector3::CreateAxisX(-20.0f), AZ::Vector3::CreateAxisX(2.0f));
// request the entity union bounds system to update
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
// create default camera looking down the negative y-axis moved just back from the origin
AzFramework::CameraState cameraState = AzFramework::CreateDefaultCamera(
@@ -101,8 +101,8 @@ namespace UnitTest
SetupRowOfEntities(AZ::Vector3::CreateAxisX(-20.0f), AZ::Vector3::CreateAxisX(2.0f));
// request the entity union bounds system to update
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
// create default camera looking down the negative x-axis moved along the x-axis and tilted slightly down
AzFramework::CameraState cameraState = AzFramework::CreateDefaultCamera(
@@ -143,15 +143,15 @@ namespace UnitTest
SetupRowOfEntities(AZ::Vector3::CreateAxisX(-20.0f), AZ::Vector3::CreateAxisX(2.0f));
// request the entity union bounds system to update
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
const AZ::EntityId entityIdToMove = m_editorEntityIds[10];
AZ::TransformBus::Event(
entityIdToMove, &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3::CreateAxisZ(100.0f));
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
// create default camera looking down the negative y-axis moved just back from the origin
AzFramework::CameraState cameraState = AzFramework::CreateDefaultCamera(
@@ -241,8 +241,8 @@ namespace UnitTest
{
m_localAabb = localAabb;
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
&AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, GetEntityId());
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
&AzFramework::IEntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, GetEntityId());
}
TEST_F(EditorVisibilityFixture, UpdatedBoundsIntersectingFrustumAddsVisibleEntity)
@@ -264,8 +264,8 @@ namespace UnitTest
entityId, &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3(40.0f, -3.0f, 20.0f));
// request the entity union bounds system to update
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
// create default camera looking down the positive x-axis moved to position offset from world origin
AzFramework::CameraState cameraState = AzFramework::CreateDefaultCamera(
@@ -288,8 +288,8 @@ namespace UnitTest
testBoundComponent->ChangeBounds(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-2.5f), AZ::Vector3(2.5f)));
// perform an 'update' of the visibility system
AzFramework::EntityBoundsUnionRequestBus::Broadcast(
&AzFramework::EntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
AzFramework::IEntityBoundsUnionRequestBus::Broadcast(
&AzFramework::IEntityBoundsUnionRequestBus::Events::ProcessEntityBoundsUnionRequests);
entityVisibilityQuery.UpdateVisibility(cameraState);