Merge branch 'main' into LYN-1767-AB

This commit is contained in:
igarri
2021-05-14 13:12:29 +01:00
1936 changed files with 32205 additions and 195249 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>
@@ -281,14 +282,6 @@ namespace AzToolsFramework
containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent());
HandleEntitiesAdded({containerEntity});
HandleEntitiesAdded(entities);
// Update the template of the instance since we modified the entities of the instance by calling HandleEntitiesAdded.
Prefab::PrefabDom serializedInstance;
if (Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(addedInstance, serializedInstance))
{
m_prefabSystemComponent->UpdatePrefabTemplate(addedInstance.GetTemplateId(), serializedInstance);
}
return addedInstance;
}
@@ -342,6 +335,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 +433,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;
@@ -270,7 +270,7 @@ namespace AzToolsFramework
return parentInstance;
}
void InstanceToTemplatePropagator::AddPatchesToLink(PrefabDom& patches, Link& link)
void InstanceToTemplatePropagator::AddPatchesToLink(const PrefabDom& patches, Link& link)
{
PrefabDom& linkDom = link.GetLinkDom();
PrefabDomValueReference linkPatchesReference =
@@ -279,7 +279,14 @@ namespace AzToolsFramework
// This logic only covers addition of patches. If patches already exists, the given list of patches must be appended to them.
if (!linkPatchesReference.has_value())
{
linkDom.AddMember(rapidjson::StringRef(PrefabDomUtils::PatchesName), patches, linkDom.GetAllocator());
/*
If the original allocator the patches were created with gets destroyed, then the patches would become garbage in the
linkDom. Since we cannot guarantee the lifecycle of the patch allocators, we are doing a copy of the patches here to
associate them with the linkDom's allocator.
*/
PrefabDom patchesCopy;
patchesCopy.CopyFrom(patches, linkDom.GetAllocator());
linkDom.AddMember(rapidjson::StringRef(PrefabDomUtils::PatchesName), patchesCopy, linkDom.GetAllocator());
}
}
}
@@ -41,7 +41,7 @@ namespace AzToolsFramework
void ApplyPatchesToInstance(const AZ::EntityId& entityId, PrefabDom& patches, const Instance& instanceToAddPatches) override;
void AddPatchesToLink(PrefabDom& patches, Link& link);
void AddPatchesToLink(const PrefabDom& patches, Link& link);
private:
@@ -27,6 +27,7 @@ namespace AzToolsFramework
using PrefabDomList = AZStd::vector<PrefabDom>;
using PrefabDomReference = AZStd::optional<AZStd::reference_wrapper<PrefabDom>>;
using PrefabDomConstReference = AZStd::optional<AZStd::reference_wrapper<const PrefabDom>>;
using PrefabDomValueReference = AZStd::optional<AZStd::reference_wrapper<PrefabDomValue>>;
using PrefabDomValueConstReference = AZStd::optional<AZStd::reference_wrapper<const PrefabDomValue>>;
@@ -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
@@ -122,27 +122,50 @@ namespace AzToolsFramework
AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId();
// Parent the entities to the container entity. Parenting the container entities of the instances passed to createPrefab
// will be done during the creation of links below.
for (AZ::Entity* topLevelEntity : entities)
{
AZ::TransformBus::Event(topLevelEntity->GetId(), &AZ::TransformBus::Events::SetParent, containerEntityId);
}
// Update the template of the instance since the entities are modified since the template creation.
Prefab::PrefabDom serializedInstance;
if (Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(instanceToCreate->get(), serializedInstance))
{
m_prefabSystemComponentInterface->UpdatePrefabTemplate(instanceToCreate->get().GetTemplateId(), serializedInstance);
}
instanceToCreate->get().GetNestedInstances([&](AZStd::unique_ptr<Instance>& nestedInstance) {
AZ_Assert(nestedInstance, "Invalid nested instance found in the new prefab created.");
EntityOptionalReference nestedInstanceContainerEntity = nestedInstance->GetContainerEntity();
AZ_Assert(
nestedInstanceContainerEntity, "Invalid container entity found for the nested instance used in prefab creation.");
// These link creations shouldn't be undone because that would put the template in a non-usable state if a user
// chooses to instantiate the template after undoing the creation.
CreateLink(
{&nestedInstanceContainerEntity->get()}, *nestedInstance, instanceToCreate->get().GetTemplateId(),
undoBatch.GetUndoBatch(), containerEntityId);
undoBatch.GetUndoBatch(), containerEntityId, false);
});
// Create a link between the templates of the newly created instance and the instance it's being parented under.
CreateLink(
topLevelEntities, instanceToCreate->get(), commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch(),
commonRootEntityId);
topLevelEntities, instanceToCreate->get(), commonRootEntityOwningInstance->get().GetTemplateId(),
undoBatch.GetUndoBatch(), commonRootEntityId);
// Change top level entities to be parented to the container entity
// 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(topLevelEntity->GetId());
// Parenting entities would mark entities as dirty. But we want to unmark the top level entities as dirty because
// if we don't, the template created would be updated and cause issues with undo operation followed by instantiation.
ToolsApplicationRequests::Bus::Broadcast(
&ToolsApplicationRequests::Bus::Events::RemoveDirtyEntity, topLevelEntity->GetId());
}
}
// Select Container Entity
@@ -237,6 +260,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;
@@ -277,7 +315,7 @@ namespace AzToolsFramework
void PrefabPublicHandler::CreateLink(
const EntityList& topLevelEntities, Instance& sourceInstance, TemplateId targetTemplateId,
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId commonRootEntityId)
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId commonRootEntityId, const bool isUndoRedoSupportNeeded)
{
AZ::EntityId containerEntityId = sourceInstance.GetContainerEntityId();
AZ::Entity* containerEntity = GetEntityById(containerEntityId);
@@ -303,9 +341,19 @@ namespace AzToolsFramework
m_instanceToTemplateInterface->GeneratePatch(patch, containerEntityDomBefore, containerEntityDomAfter);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, containerEntityId);
LinkId linkId = PrefabUndoHelpers::CreateLink(
sourceInstance.GetTemplateId(), targetTemplateId, patch, sourceInstance.GetInstanceAlias(),
undoBatch);
LinkId linkId;
if (isUndoRedoSupportNeeded)
{
linkId = PrefabUndoHelpers::CreateLink(
sourceInstance.GetTemplateId(), targetTemplateId, AZStd::move(patch), sourceInstance.GetInstanceAlias(), undoBatch);
}
else
{
linkId = m_prefabSystemComponentInterface->CreateLink(
targetTemplateId, sourceInstance.GetTemplateId(), sourceInstance.GetInstanceAlias(), patch,
InvalidLinkId);
m_prefabSystemComponentInterface->PropagateTemplateChanges(targetTemplateId);
}
sourceInstance.SetLinkId(linkId);
@@ -338,7 +386,7 @@ namespace AzToolsFramework
patchesCopyForUndoSupport.CopyFrom(nestedInstanceLinkPatches->get(), patchesCopyForUndoSupport.GetAllocator());
PrefabUndoHelpers::RemoveLink(
sourceInstance->GetTemplateId(), targetTemplateId, sourceInstance->GetInstanceAlias(), sourceInstance->GetLinkId(),
patchesCopyForUndoSupport, undoBatch);
AZStd::move(patchesCopyForUndoSupport), undoBatch);
}
PrefabOperationResult PrefabPublicHandler::SavePrefab(AZ::IO::Path filePath)
@@ -807,6 +855,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)
@@ -894,7 +947,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
@@ -77,10 +77,11 @@ namespace AzToolsFramework
* \param targetInstance The id of the target template.
* \param undoBatch The undo batch to set as parent for this create link action.
* \param commonRootEntityId The id of the entity that the source instance should be parented under.
* \param isUndoRedoSupportNeeded The flag indicating whether the link should be created with undo/redo support or not.
*/
void CreateLink(
const EntityList& topLevelEntities, Instance& sourceInstance, TemplateId targetTemplateId,
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId commonRootEntityId);
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId commonRootEntityId, const bool isUndoRedoSupportNeeded = true);
/**
* Removes the link between template of the sourceInstance and the template corresponding to targetTemplateId.
@@ -583,7 +583,7 @@ namespace AzToolsFramework
const TemplateId& linkTargetId,
const TemplateId& linkSourceId,
const InstanceAlias& instanceAlias,
const PrefabDomReference linkPatch,
const PrefabDomConstReference linkPatches,
const LinkId& linkId)
{
if (linkTargetId == InvalidTemplateId)
@@ -667,9 +667,9 @@ namespace AzToolsFramework
rapidjson::StringRef(PrefabDomUtils::SourceName), rapidjson::StringRef(sourceTemplate.GetFilePath().c_str()),
newLink.GetLinkDom().GetAllocator());
if (linkPatch && linkPatch->get().IsArray() && !(linkPatch->get().Empty()))
if (linkPatches && linkPatches->get().IsArray() && !(linkPatches->get().Empty()))
{
m_instanceToTemplatePropagator.AddPatchesToLink(linkPatch.value(), newLink);
m_instanceToTemplatePropagator.AddPatchesToLink(linkPatches.value(), newLink);
}
//update the target template dom to have the proper values for the source template dom
@@ -156,7 +156,7 @@ namespace AzToolsFramework
const TemplateId& linkTargetId,
const TemplateId& linkSourceId,
const InstanceAlias& instanceAlias,
const PrefabDomReference linkPatch,
const PrefabDomConstReference linkPatches,
const LinkId& linkId = InvalidLinkId) override;
/**
@@ -43,9 +43,9 @@ namespace AzToolsFramework
PrefabDomValue::MemberIterator& instanceIterator, InstanceOptionalReference instance) = 0;
//creates a new Link
virtual LinkId CreateLink(const TemplateId& linkTargetId, const TemplateId& linkSourceId,
const InstanceAlias& instanceAlias, const PrefabDomReference linkPatch,
const LinkId& linkId = InvalidLinkId) = 0;
virtual LinkId CreateLink(
const TemplateId& linkTargetId, const TemplateId& linkSourceId, const InstanceAlias& instanceAlias,
const PrefabDomConstReference linkPatches, const LinkId& linkId = InvalidLinkId) = 0;
virtual void RemoveLink(const LinkId& linkId) = 0;
@@ -124,7 +124,7 @@ namespace AzToolsFramework
const TemplateId& targetId,
const TemplateId& sourceId,
const InstanceAlias& instanceAlias,
PrefabDomReference linkPatches,
PrefabDom linkPatches,
const LinkId linkId)
{
m_targetId = targetId;
@@ -132,10 +132,7 @@ namespace AzToolsFramework
m_instanceAlias = instanceAlias;
m_linkId = linkId;
if (linkPatches.has_value())
{
m_linkPatches = AZStd::move(linkPatches->get());
}
m_linkPatches = AZStd::move(linkPatches);
//if linkId is invalid, set as ADD
if (m_linkId == InvalidLinkId)
@@ -228,7 +225,7 @@ namespace AzToolsFramework
if (link.has_value())
{
m_linkDomPrevious = AZStd::move(link->get().GetLinkDom());
m_linkDomPrevious.CopyFrom(link->get().GetLinkDom(), m_linkDomPrevious.GetAllocator());
}
//get source templateDom
@@ -275,7 +272,7 @@ namespace AzToolsFramework
if (patchesIter == m_linkDomNext.MemberEnd())
{
m_linkDomNext.AddMember(
rapidjson::GenericStringRef(PrefabDomUtils::PatchesName), patchLinkCopy, m_linkDomNext.GetAllocator());
rapidjson::GenericStringRef(PrefabDomUtils::PatchesName), AZStd::move(patchLinkCopy), m_linkDomNext.GetAllocator());
}
else
{
@@ -303,9 +300,7 @@ namespace AzToolsFramework
return;
}
PrefabDom moveLink;
moveLink.CopyFrom(linkDom, linkDom.GetAllocator());
link->get().GetLinkDom() = AZStd::move(moveLink);
link->get().SetLinkDom(linkDom);
//propagate the link changes
link->get().UpdateTarget();
@@ -101,7 +101,7 @@ namespace AzToolsFramework
const TemplateId& targetId,
const TemplateId& sourceId,
const InstanceAlias& instanceAlias,
PrefabDomReference linkPatches = PrefabDomReference(),
PrefabDom linkPatches = PrefabDom(),
const LinkId linkId = InvalidLinkId);
void Undo() override;
@@ -34,11 +34,11 @@ namespace AzToolsFramework
}
LinkId CreateLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDomReference patch,
TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDom patch,
const InstanceAlias& instanceAlias, UndoSystem::URSequencePoint* undoBatch)
{
auto linkAddUndo = aznew PrefabUndoInstanceLink("Create Link");
linkAddUndo->Capture(targetTemplateId, sourceTemplateId, instanceAlias, patch, InvalidLinkId);
linkAddUndo->Capture(targetTemplateId, sourceTemplateId, instanceAlias, AZStd::move(patch), InvalidLinkId);
linkAddUndo->SetParent(undoBatch);
linkAddUndo->Redo();
@@ -47,10 +47,10 @@ namespace AzToolsFramework
void RemoveLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, const InstanceAlias& instanceAlias, LinkId linkId,
PrefabDomReference linkPatches, UndoSystem::URSequencePoint* undoBatch)
PrefabDom linkPatches, UndoSystem::URSequencePoint* undoBatch)
{
auto linkRemoveUndo = aznew PrefabUndoInstanceLink("Remove Link");
linkRemoveUndo->Capture(targetTemplateId, sourceTemplateId, instanceAlias, linkPatches, linkId);
linkRemoveUndo->Capture(targetTemplateId, sourceTemplateId, instanceAlias, AZStd::move(linkPatches), linkId);
linkRemoveUndo->SetParent(undoBatch);
linkRemoveUndo->Redo();
}
@@ -22,11 +22,11 @@ namespace AzToolsFramework
const Instance& instance, AZStd::string_view undoMessage, const PrefabDom& instanceDomBeforeUpdate,
UndoSystem::URSequencePoint* undoBatch);
LinkId CreateLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDomReference patch,
TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDom patch,
const InstanceAlias& instanceAlias, UndoSystem::URSequencePoint* undoBatch);
void RemoveLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, const InstanceAlias& instanceAlias, LinkId linkId,
PrefabDomReference linkPatches, UndoSystem::URSequencePoint* undoBatch);
PrefabDom linkPatches, UndoSystem::URSequencePoint* undoBatch);
}
} // namespace Prefab
} // namespace AzToolsFramework
@@ -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
@@ -63,29 +63,6 @@ namespace AzToolsFramework
void EditorNonUniformScaleComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
incompatible.push_back(AZ_CRC_CE("DebugDrawObbService"));
incompatible.push_back(AZ_CRC_CE("DebugDrawService"));
incompatible.push_back(AZ_CRC_CE("EMotionFXActorService"));
incompatible.push_back(AZ_CRC_CE("EMotionFXSimpleMotionService"));
incompatible.push_back(AZ_CRC_CE("GradientTransformService"));
incompatible.push_back(AZ_CRC_CE("LegacyMeshService"));
incompatible.push_back(AZ_CRC_CE("LookAtService"));
incompatible.push_back(AZ_CRC_CE("SequenceService"));
incompatible.push_back(AZ_CRC_CE("ClothMeshService"));
incompatible.push_back(AZ_CRC_CE("PhysXJointService"));
incompatible.push_back(AZ_CRC_CE("PhysXCharacterControllerService"));
incompatible.push_back(AZ_CRC_CE("PhysXRagdollService"));
incompatible.push_back(AZ_CRC_CE("WhiteBoxService"));
incompatible.push_back(AZ_CRC_CE("NavigationAreaService"));
incompatible.push_back(AZ_CRC_CE("GeometryService"));
incompatible.push_back(AZ_CRC_CE("CapsuleShapeService"));
incompatible.push_back(AZ_CRC_CE("CompoundShapeService"));
incompatible.push_back(AZ_CRC_CE("CylinderShapeService"));
incompatible.push_back(AZ_CRC_CE("DiskShapeService"));
incompatible.push_back(AZ_CRC_CE("SphereShapeService"));
incompatible.push_back(AZ_CRC_CE("SplineService"));
incompatible.push_back(AZ_CRC_CE("TubeShapeService"));
}
void EditorNonUniformScaleComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
@@ -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,6 +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());
}
}
}
@@ -933,15 +941,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()
@@ -1280,7 +1287,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);
@@ -1315,21 +1321,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>
@@ -234,16 +237,15 @@ namespace AzToolsFramework
mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Alt();
}
static bool IndividualSelect(const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
static bool IndividualSelect(const AzFramework::ClickDetector::ClickOutcome clickOutcome)
{
return mouseInteraction.m_mouseInteraction.m_mouseButtons.Left() &&
mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down;
return clickOutcome == AzFramework::ClickDetector::ClickOutcome::Click;
}
static bool AdditiveIndividualSelect(const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
static bool AdditiveIndividualSelect(
const AzFramework::ClickDetector::ClickOutcome clickOutcome, const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
{
return mouseInteraction.m_mouseInteraction.m_mouseButtons.Left() &&
mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down &&
return clickOutcome == AzFramework::ClickDetector::ClickOutcome::Click &&
mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Ctrl() &&
!mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Alt();
}
@@ -1780,6 +1782,25 @@ namespace AzToolsFramework
m_cachedEntityIdUnderCursor = m_editorHelpers->HandleMouseInteraction(cameraState, mouseInteraction);
const AzFramework::ClickDetector::ClickEvent selectClickEvent = [&mouseInteraction] {
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
{
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
{
return AzFramework::ClickDetector::ClickEvent::Down;
}
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up)
{
return AzFramework::ClickDetector::ClickEvent::Up;
}
}
return AzFramework::ClickDetector::ClickEvent::Nil;
}();
m_cursorState.SetCurrentPosition(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
const auto clickOutcome = m_clickDetector.DetectClick(selectClickEvent, m_cursorState.CursorDelta());
// for entities selected with no bounds of their own (just TransformComponent)
// check selection against the selection indicator aabb
for (AZ::EntityId entityId : m_selectedEntityIds)
@@ -1838,7 +1859,7 @@ namespace AzToolsFramework
if (!m_selectedEntityIds.empty())
{
// select/deselect (add/remove) entities with ctrl held
if (Input::AdditiveIndividualSelect(mouseInteraction))
if (Input::AdditiveIndividualSelect(clickOutcome, mouseInteraction))
{
if (SelectDeselect(entityIdUnderCursor))
{
@@ -2020,7 +2041,7 @@ namespace AzToolsFramework
}
// standard toggle selection
if (Input::IndividualSelect(mouseInteraction))
if (Input::IndividualSelect(clickOutcome))
{
SelectDeselect(entityIdUnderCursor);
}
@@ -2523,7 +2544,7 @@ namespace AzToolsFramework
// create the cluster for changing transform mode
ViewportUi::ViewportUiRequestBus::EventResult(
m_transformModeClusterId, ViewportUi::DefaultViewportId,
&ViewportUi::ViewportUiRequestBus::Events::CreateCluster);
&ViewportUi::ViewportUiRequestBus::Events::CreateCluster, ViewportUi::Alignment::TopLeft);
// create and register the buttons (strings correspond to icons even if the values appear different)
m_translateButtonId = RegisterClusterButton(m_transformModeClusterId, "Move");
@@ -3264,6 +3285,8 @@ namespace AzToolsFramework
const auto modifiers = ViewportInteraction::KeyboardModifiers(
ViewportInteraction::TranslateKeyboardModifiers(QApplication::queryKeyboardModifiers()));
m_cursorState.Update();
HandleAccents(
!m_selectedEntityIds.empty(), m_cachedEntityIdUnderCursor,
modifiers.Ctrl(), m_hoveredEntityId,
@@ -17,6 +17,8 @@
#include <AzCore/std/optional.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzFramework/Components/CameraBus.h>
#include <AzFramework/Viewport/ClickDetector.h>
#include <AzFramework/Viewport/CursorState.h>
#include <AzToolsFramework/API/EditorCameraBus.h>
#include <AzToolsFramework/Commands/EntityManipulatorCommand.h>
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
@@ -35,37 +37,37 @@ namespace AzToolsFramework
{
class EditorVisibleEntityDataCache;
using EntityIdSet = AZStd::unordered_set<AZ::EntityId>; ///< Alias for unordered_set of EntityIds.
using EntityIdSet = AZStd::unordered_set<AZ::EntityId>; //!< Alias for unordered_set of EntityIds.
/// Entity related data required by manipulators during action.
//! Entity related data required by manipulators during action.
struct EntityIdManipulatorLookup
{
AZ::Transform m_initial; /// Transform of Entity at mouse down on manipulator.
AZ::Transform m_initial; //!< Transform of Entity at mouse down on manipulator.
};
/// Alias for a mapping between EntityIds and Entity related data required by manipulators.
//! Alias for a mapping between EntityIds and Entity related data required by manipulators.
using EntityIdManipulatorLookups = AZStd::unordered_map<AZ::EntityId, EntityIdManipulatorLookup>;
/// Generic wrapper to handle specific manipulators controlling 1-* entities.
//! Generic wrapper to handle specific manipulators controlling 1-* entities.
struct EntityIdManipulators
{
EntityIdManipulatorLookups m_lookups; ///< Mapping between the EntityId and the transform of the Entity at
///< the point a manipulator started adjusting it.
AZStd::unique_ptr<Manipulators> m_manipulators; ///< The aggregate manipulator currently in use.
EntityIdManipulatorLookups m_lookups; //!< Mapping between the EntityId and the transform of the Entity at
//!< the point a manipulator started adjusting it.
AZStd::unique_ptr<Manipulators> m_manipulators; //!< The aggregate manipulator currently in use.
};
/// Store translation and orientation only (no scale).
//! Store translation and orientation only (no scale).
struct Frame
{
AZ::Vector3 m_translation = AZ::Vector3::CreateZero(); ///< Position of frame.
AZ::Quaternion m_orientation = AZ::Quaternion::CreateIdentity(); ///< Orientation of frame.
AZ::Vector3 m_translation = AZ::Vector3::CreateZero(); //!< Position of frame.
AZ::Quaternion m_orientation = AZ::Quaternion::CreateIdentity(); //!< Orientation of frame.
};
/// Temporary manipulator frame used during selection.
//! Temporary manipulator frame used during selection.
struct OptionalFrame
{
/// What part of the transform did we pick (when using ditto on
/// the manipulator). This will depend on the transform mode we're in.
//! What part of the transform did we pick (when using ditto on
//! the manipulator). This will depend on the transform mode we're in.
struct PickType
{
enum : AZ::u8
@@ -83,29 +85,29 @@ namespace AzToolsFramework
bool PickedTranslation() const;
bool PickedOrientation() const;
/// Clear all state associated with the frame.
//! Clear all state associated with the frame.
void Reset();
/// Clear only picked translation state.
//! Clear only picked translation state.
void ResetPickedTranslation();
/// Clear only picked orientation state.
//! Clear only picked orientation state.
void ResetPickedOrientation();
AZ::EntityId m_pickedEntityIdOverride; ///< 'Picked' Entity - frame and parent space relative to this if active.
AZStd::optional<AZ::Vector3> m_translationOverride; ///< Translation override, if set, reset when selection is empty.
AZStd::optional<AZ::Quaternion> m_orientationOverride; ///< Orientation override, if set, reset when selection is empty.
AZ::u8 m_pickTypes = PickType::None; ///< What mode(s) were we in when picking an EntityId override.
AZ::EntityId m_pickedEntityIdOverride; //!< 'Picked' Entity - frame and parent space relative to this if active.
AZStd::optional<AZ::Vector3> m_translationOverride; //!< Translation override, if set, reset when selection is empty.
AZStd::optional<AZ::Quaternion> m_orientationOverride; //!< Orientation override, if set, reset when selection is empty.
AZ::u8 m_pickTypes = PickType::None; //!< What mode(s) were we in when picking an EntityId override.
};
/// What frame/space is the manipulator currently operating in.
//! What frame/space is the manipulator currently operating in.
enum class ReferenceFrame
{
Local, /// The local space of the individual entity.
Parent, /// The parent space of the individual entity (world space if no parent exists).
World, /// World space (space aligned to world axes - identity).
Local, //!< The local space of the individual entity.
Parent, //!< The parent space of the individual entity (world space if no parent exists).
World, //!< World space (space aligned to world axes - identity).
};
/// Entity selection/interaction handling.
/// Provide a suite of functionality for manipulating entities, primarily through their TransformComponent.
//! Entity selection/interaction handling.
//! Provide a suite of functionality for manipulating entities, primarily through their TransformComponent.
class EditorTransformComponentSelection
: public ViewportInteraction::ViewportSelectionRequests
, private EditorEventsBus::Handler
@@ -127,15 +129,15 @@ namespace AzToolsFramework
EditorTransformComponentSelection& operator=(const EditorTransformComponentSelection&) = delete;
virtual ~EditorTransformComponentSelection();
/// Register entity manipulators with the ManipulatorManager.
/// After being registered, the entity manipulators will draw and check for input.
//! Register entity manipulators with the ManipulatorManager.
//! After being registered, the entity manipulators will draw and check for input.
void RegisterManipulator();
/// Unregister entity manipulators with the ManipulatorManager.
/// No longer draw or respond to input.
//! Unregister entity manipulators with the ManipulatorManager.
//! No longer draw or respond to input.
void UnregisterManipulator();
/// ViewportInteraction::ViewportSelectionRequests
/// Intercept all viewport mouse events and respond to inputs.
//! ViewportInteraction::ViewportSelectionRequests
//! Intercept all viewport mouse events and respond to inputs.
bool HandleMouseInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
void DisplayViewportSelection(
@@ -145,9 +147,9 @@ namespace AzToolsFramework
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
/// Add an entity to the current selection
//! Add an entity to the current selection
void AddEntityToSelection(AZ::EntityId entityId);
/// Remove an entity from the current selection
//! Remove an entity from the current selection
void RemoveEntityFromSelection(AZ::EntityId entityId);
private:
@@ -161,8 +163,8 @@ namespace AzToolsFramework
void ClearManipulatorTranslationOverride();
void ClearManipulatorOrientationOverride();
/// Handle an event triggered by the user to clear any manipulator overrides.
/// Delegate to either translation or orientation reset/clear depending on the state we're in.
//! Handle an event triggered by the user to clear any manipulator overrides.
//! Delegate to either translation or orientation reset/clear depending on the state we're in.
void DelegateClearManipulatorOverride();
void ToggleCenterPivotSelection();
@@ -251,63 +253,65 @@ namespace AzToolsFramework
void SetEntityLocalScale(AZ::EntityId entityId, const AZ::Vector3& localScale);
void SetEntityLocalRotation(AZ::EntityId entityId, const AZ::Vector3& localRotation);
AZ::EntityId m_hoveredEntityId; ///< What EntityId is the mouse currently hovering over (if any).
AZ::EntityId m_cachedEntityIdUnderCursor; ///< Store the EntityId on each mouse move for use in Display.
AZ::EntityId m_editorCameraComponentEntityId; ///< The EditorCameraComponent EntityId if it is set.
EntityIdSet m_selectedEntityIds; ///< Represents the current entities in the selection.
AZ::EntityId m_hoveredEntityId; //!< What EntityId is the mouse currently hovering over (if any).
AZ::EntityId m_cachedEntityIdUnderCursor; //!< Store the EntityId on each mouse move for use in Display.
AZ::EntityId m_editorCameraComponentEntityId; //!< The EditorCameraComponent EntityId if it is set.
EntityIdSet m_selectedEntityIds; //!< Represents the current entities in the selection.
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; ///< A cache of packed EntityData that can be
///< iterated over efficiently without the need
///< to make individual EBus calls.
AZStd::unique_ptr<EditorHelpers> m_editorHelpers; ///< Editor visualization of entities (icons, shapes, debug visuals etc).
EntityIdManipulators m_entityIdManipulators; ///< Mapping from a Manipulator to potentially many EntityIds.
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< A cache of packed EntityData that can be
//!< iterated over efficiently without the need
//!< to make individual EBus calls.
AZStd::unique_ptr<EditorHelpers> m_editorHelpers; //!< Editor visualization of entities (icons, shapes, debug visuals etc).
EntityIdManipulators m_entityIdManipulators; //!< Mapping from a Manipulator to potentially many EntityIds.
EditorBoxSelect m_boxSelect; ///< Type responsible for handling box select.
AZStd::unique_ptr<EntityManipulatorCommand> m_manipulatorMoveCommand; ///< Track adjustments to manipulator translation and orientation (during mouse press/move).
AZStd::vector<AZStd::unique_ptr<QAction>> m_actions; ///< What actions are tied to this handler.
ViewportInteraction::KeyboardModifiers m_previousModifiers; ///< What modifiers were held last frame.
EditorContextMenu m_contextMenu; ///< Viewport right click context menu.
OptionalFrame m_pivotOverrideFrame; ///< Has a pivot override been set.
Mode m_mode = Mode::Translation; ///< Manipulator mode - default to translation.
Pivot m_pivotMode = Pivot::Object; ///< Entity pivot mode - default to object (authored root).
ReferenceFrame m_referenceFrame = ReferenceFrame::Parent; ///< What reference frame is the Manipulator currently operating in.
Frame m_axisPreview; ///< Axes of entity at the time of mouse down to indicate delta of translation.
bool m_triedToRefresh = false; ///< Did a refresh event occur to recalculate the current Manipulator transform.
bool m_didSetSelectedEntities = false; ///< Was EditorTransformComponentSelection responsible for the most recent entity selection change.
bool m_selectedEntityIdsAndManipulatorsDirty = false; ///< Do the active manipulators need to recalculated after a modification (lock/visibility etc).
bool m_transformChangedInternally = false; ///< Was an OnTransformChanged event triggered internally or not.
ViewportUi::ClusterId m_transformModeClusterId; ///< Id of the Viewport UI cluster for changing transform mode.
ViewportUi::ButtonId m_translateButtonId; ///< Id of the Viewport UI button for translate mode.
ViewportUi::ButtonId m_rotateButtonId; ///< Id of the Viewport UI button for rotate mode.
ViewportUi::ButtonId m_scaleButtonId; ///< Id of the Viewport UI button for scale mode.
AZ::Event<ViewportUi::ButtonId>::Handler m_transformModeSelectionHandler; ///< Event handler for the Viewport UI cluster.
EditorBoxSelect m_boxSelect; //!< Type responsible for handling box select.
AZStd::unique_ptr<EntityManipulatorCommand> m_manipulatorMoveCommand; //!< Track adjustments to manipulator translation and orientation (during mouse press/move).
AZStd::vector<AZStd::unique_ptr<QAction>> m_actions; //!< What actions are tied to this handler.
ViewportInteraction::KeyboardModifiers m_previousModifiers; //!< What modifiers were held last frame.
EditorContextMenu m_contextMenu; //!< Viewport right click context menu.
OptionalFrame m_pivotOverrideFrame; //!< Has a pivot override been set.
Mode m_mode = Mode::Translation; //!< Manipulator mode - default to translation.
Pivot m_pivotMode = Pivot::Object; //!< Entity pivot mode - default to object (authored root).
ReferenceFrame m_referenceFrame = ReferenceFrame::Parent; //!< What reference frame is the Manipulator currently operating in.
Frame m_axisPreview; //!< Axes of entity at the time of mouse down to indicate delta of translation.
bool m_triedToRefresh = false; //!< Did a refresh event occur to recalculate the current Manipulator transform.
bool m_didSetSelectedEntities = false; //!< Was EditorTransformComponentSelection responsible for the most recent entity selection change.
bool m_selectedEntityIdsAndManipulatorsDirty = false; //!< Do the active manipulators need to recalculated after a modification (lock/visibility etc).
bool m_transformChangedInternally = false; //!< Was an OnTransformChanged event triggered internally or not.
ViewportUi::ClusterId m_transformModeClusterId; //!< Id of the Viewport UI cluster for changing transform mode.
ViewportUi::ButtonId m_translateButtonId; //!< Id of the Viewport UI button for translate mode.
ViewportUi::ButtonId m_rotateButtonId; //!< Id of the Viewport UI button for rotate mode.
ViewportUi::ButtonId m_scaleButtonId; //!< Id of the Viewport UI button for scale mode.
AZ::Event<ViewportUi::ButtonId>::Handler m_transformModeSelectionHandler; //!< Event handler for the Viewport UI cluster.
AzFramework::ClickDetector m_clickDetector; //!< Detect different types of mouse click.
AzFramework::CursorState m_cursorState; //!< Track the mouse position and delta movement each frame.
};
/// The ETCS (EntityTransformComponentSelection) namespace contains functions and data used exclusively by
/// the EditorTransformComponentSelection type. Functions in this namespace are exposed to facilitate testing
/// and should not be used outside of EditorTransformComponentSelection or EditorTransformComponentSelectionTests.
//! The ETCS (EntityTransformComponentSelection) namespace contains functions and data used exclusively by
//! the EditorTransformComponentSelection type. Functions in this namespace are exposed to facilitate testing
//! and should not be used outside of EditorTransformComponentSelection or EditorTransformComponentSelectionTests.
namespace ETCS
{
/// The result from calculating the entity (transform component) orientation.
/// Does the entity have a parent or not, and what orientation should the manipulator have when
/// displayed at the object pivot (determined by the entity hierarchy and what modifiers are held).
//! The result from calculating the entity (transform component) orientation.
//! Does the entity have a parent or not, and what orientation should the manipulator have when
//! displayed at the object pivot (determined by the entity hierarchy and what modifiers are held).
struct PivotOrientationResult
{
AZ::Quaternion m_worldOrientation;
AZ::EntityId m_parentId;
};
/// Calculate the orientation for an individual entity based on the incoming reference frame.
/// Note: If the entity is in a hierarchy the Parent reference frame will return the orientation of the parent.
//! Calculate the orientation for an individual entity based on the incoming reference frame.
//! Note: If the entity is in a hierarchy the Parent reference frame will return the orientation of the parent.
PivotOrientationResult CalculatePivotOrientation(AZ::EntityId entityId, ReferenceFrame referenceFrame);
/// Calculate the orientation for a group of entities based on the incoming reference frame.
//! Calculate the orientation for a group of entities based on the incoming reference frame.
template<typename EntityIdMap>
PivotOrientationResult CalculatePivotOrientationForEntityIds(
const EntityIdMap& entityIdMap, const ReferenceFrame referenceFrame);
/// Calculate the orientation for a group of entities based on the incoming
/// reference frame with possible pivot override.
//! Calculate the orientation for a group of entities based on the incoming
//! reference frame with possible pivot override.
template<typename EntityIdMap>
PivotOrientationResult CalculateSelectionPivotOrientation(
const EntityIdMap& entityIdMap, const OptionalFrame& pivotOverrideFrame,
@@ -41,6 +41,28 @@ namespace AzToolsFramework::ViewportUi::Internal
}
}
static Qt::Alignment GetQtAlignment(Alignment align)
{
switch (align)
{
case Alignment::TopRight:
return Qt::AlignTop | Qt::AlignRight;
case Alignment::TopLeft:
return Qt::AlignTop | Qt::AlignLeft;
case Alignment::BottomRight:
return Qt::AlignBottom | Qt::AlignRight;
case Alignment::BottomLeft:
return Qt::AlignBottom | Qt::AlignLeft;
case Alignment::Top:
return Qt::AlignTop;
case Alignment::Bottom:
return Qt::AlignBottom;
}
AZ_Assert(false, "ViewportUI", "Unhandled ViewportUI Alignment %d", static_cast<int>(align));
return Qt::AlignTop;
}
ViewportUiDisplay::ViewportUiDisplay(QWidget* parent, QWidget* renderOverlay)
: m_renderOverlay(renderOverlay)
, m_uiMainWindow(parent)
@@ -56,7 +78,7 @@ namespace AzToolsFramework::ViewportUi::Internal
UnparentWidgets(m_viewportUiElements);
}
void ViewportUiDisplay::AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup)
void ViewportUiDisplay::AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup, const Alignment align)
{
if (!buttonGroup.get())
{
@@ -66,7 +88,7 @@ namespace AzToolsFramework::ViewportUi::Internal
auto viewportUiCluster = AZStd::make_shared<ViewportUiCluster>(buttonGroup);
auto id = AddViewportUiElement(viewportUiCluster);
buttonGroup->SetViewportUiElementId(id);
PositionViewportUiElementAnchored(id, Qt::AlignTop | Qt::AlignLeft);
PositionViewportUiElementAnchored(id, GetQtAlignment(align));
}
void ViewportUiDisplay::AddClusterButton(
@@ -94,7 +116,7 @@ namespace AzToolsFramework::ViewportUi::Internal
}
}
void ViewportUiDisplay::AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup)
void ViewportUiDisplay::AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup, const Alignment align)
{
if (!buttonGroup.get())
{
@@ -104,7 +126,7 @@ namespace AzToolsFramework::ViewportUi::Internal
auto viewportUiSwitcher = AZStd::make_shared<ViewportUiSwitcher>(buttonGroup);
auto id = AddViewportUiElement(viewportUiSwitcher);
buttonGroup->SetViewportUiElementId(id);
PositionViewportUiElementAnchored(id, Qt::AlignTop | Qt::AlignLeft);
PositionViewportUiElementAnchored(id, GetQtAlignment(align));
}
void ViewportUiDisplay::AddSwitcherButton(const ViewportUiElementId clusterId, Button* button)
@@ -56,12 +56,12 @@ namespace AzToolsFramework::ViewportUi::Internal
ViewportUiDisplay(QWidget* parent, QWidget* renderOverlay);
~ViewportUiDisplay();
void AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup);
void AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup, Alignment align);
void AddClusterButton(ViewportUiElementId clusterId, Button* button);
void RemoveClusterButton(ViewportUiElementId clusterId, ButtonId buttonId);
void UpdateCluster(const ViewportUiElementId clusterId);
void AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup);
void AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup, Alignment align);
void AddSwitcherButton(ViewportUiElementId switcherId, Button* button);
void RemoveSwitcherButton(ViewportUiElementId switcherId, ButtonId buttonId);
void UpdateSwitcher(ViewportUiElementId switcherId);
@@ -30,18 +30,18 @@ namespace AzToolsFramework::ViewportUi
ViewportUiRequestBus::Handler::BusDisconnect();
}
const ClusterId ViewportUiManager::CreateCluster()
const ClusterId ViewportUiManager::CreateCluster(const Alignment align)
{
auto buttonGroup = AZStd::make_shared<Internal::ButtonGroup>();
m_viewportUi->AddCluster(buttonGroup);
m_viewportUi->AddCluster(buttonGroup, align);
return RegisterNewCluster(buttonGroup);
}
const SwitcherId ViewportUiManager::CreateSwitcher()
const SwitcherId ViewportUiManager::CreateSwitcher(const Alignment align)
{
auto buttonGroup = AZStd::make_shared<Internal::ButtonGroup>();
m_viewportUi->AddSwitcher(buttonGroup);
m_viewportUi->AddSwitcher(buttonGroup, align);
return RegisterNewSwitcher(buttonGroup);
}
@@ -31,8 +31,8 @@ namespace AzToolsFramework::ViewportUi
~ViewportUiManager() = default;
// ViewportUiRequestBus ...
const ClusterId CreateCluster() override;
const SwitcherId CreateSwitcher() override;
const ClusterId CreateCluster(Alignment align) override;
const SwitcherId CreateSwitcher(Alignment align) override;
void SetClusterActiveButton(ClusterId clusterId, ButtonId buttonId) override;
void SetSwitcherActiveButton(SwitcherId switcherId, ButtonId buttonId) override;
const ButtonId CreateClusterButton(ClusterId clusterId, const AZStd::string& icon) override;
@@ -41,15 +41,26 @@ namespace AzToolsFramework::ViewportUi
String
};
//! Used to anchor widgets to a specific side of the viewport.
enum class Alignment
{
TopRight,
TopLeft,
BottomRight,
BottomLeft,
Top,
Bottom
};
//! Viewport requests to interact with the Viewport UI. Viewport UI refers to the entire UI overlay (one per viewport).
//! Each widget on the Viewport UI is referred to as an element.
class ViewportUiRequests
{
public:
//! Creates and registers a cluster with the Viewport UI system.
virtual const ClusterId CreateCluster() = 0;
virtual const ClusterId CreateCluster(Alignment align) = 0;
//! Creates and registers a switcher with the Viewport UI system.
virtual const SwitcherId CreateSwitcher() = 0;
virtual const SwitcherId CreateSwitcher(Alignment align) = 0;
//! Sets the active button of the cluster. This is the button which will display as highlighted.
virtual void SetClusterActiveButton(ClusterId clusterId, ButtonId buttonId) = 0;
//! Sets the active button of the switcher. This is the button which has a text label.
@@ -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
@@ -120,7 +120,7 @@ namespace UnitTest
//create an undo node to apply the patch and prep for undo
PrefabUndoInstanceLink undoInstanceLinkNode("Undo Link Patch");
undoInstanceLinkNode.Capture(rootTemplateId, nestedTemplateId, aliases[0], patch, InvalidLinkId);
undoInstanceLinkNode.Capture(rootTemplateId, nestedTemplateId, aliases[0], AZStd::move(patch), InvalidLinkId);
undoInstanceLinkNode.Redo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
@@ -196,7 +196,7 @@ namespace UnitTest
//create an undo node to apply the patch and prep for undo
PrefabUndoInstanceLink undoInstanceLinkNode("Undo Link Patch");
undoInstanceLinkNode.Capture(rootTemplateId, nestedTemplateId, aliases[0], linkPatch, InvalidLinkId);
undoInstanceLinkNode.Capture(rootTemplateId, nestedTemplateId, aliases[0], AZStd::move(linkPatch), InvalidLinkId);
undoInstanceLinkNode.Redo();
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
@@ -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);
@@ -72,7 +72,7 @@ namespace UnitTest
TEST_F(ViewportUiDisplayTestFixture, RemoveViewportUiElementRemovesElementFromViewportUi)
{
ViewportUiDisplay viewportUi(m_parentWidget, m_mockRenderOverlay);
viewportUi.AddCluster(m_buttonGroup);
viewportUi.AddCluster(m_buttonGroup, AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto widget = viewportUi.GetViewportUiElement(m_buttonGroup->GetViewportUiElementId());
EXPECT_TRUE(widget.get() != nullptr);
@@ -89,7 +89,7 @@ namespace UnitTest
ViewportUiDisplay viewportUi(m_parentWidget, m_mockRenderOverlay);
viewportUi.InitializeUiOverlay();
viewportUi.AddCluster(m_buttonGroup);
viewportUi.AddCluster(m_buttonGroup, AzToolsFramework::ViewportUi::Alignment::TopLeft);
viewportUi.Update();
viewportUi.ShowViewportUiElement(m_buttonGroup->GetViewportUiElementId());
@@ -102,7 +102,7 @@ namespace UnitTest
ViewportUiDisplay viewportUi(m_parentWidget, m_mockRenderOverlay);
viewportUi.InitializeUiOverlay();
viewportUi.AddCluster(m_buttonGroup);
viewportUi.AddCluster(m_buttonGroup, AzToolsFramework::ViewportUi::Alignment::TopLeft);
viewportUi.HideViewportUiElement(m_buttonGroup->GetViewportUiElementId());
EXPECT_FALSE(viewportUi.IsViewportUiElementVisible(m_buttonGroup->GetViewportUiElementId()));
@@ -112,7 +112,7 @@ namespace UnitTest
{
ViewportUiDisplay viewportUi(m_parentWidget, m_mockRenderOverlay);
viewportUi.InitializeUiOverlay();
viewportUi.AddCluster(m_buttonGroup);
viewportUi.AddCluster(m_buttonGroup, AzToolsFramework::ViewportUi::Alignment::TopLeft);
viewportUi.Update();
auto widget = viewportUi.GetViewportUiElement(m_buttonGroup->GetViewportUiElementId());
@@ -129,7 +129,7 @@ namespace UnitTest
auto buttonGroup = AZStd::make_shared<ButtonGroup>();
buttonGroup->AddButton("");
viewportUi.AddCluster(buttonGroup);
viewportUi.AddCluster(buttonGroup, AzToolsFramework::ViewportUi::Alignment::TopLeft);
viewportUi.Update();
EXPECT_TRUE(viewportUi.GetUiMainWindow()->isVisible());
@@ -101,7 +101,7 @@ namespace UnitTest
TEST_F(ViewportUiManagerTestFixture, CreateClusterAddsNewClusterAndReturnsId)
{
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto clusterEntry = m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().find(clusterId);
EXPECT_TRUE(clusterEntry != m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().end());
@@ -110,7 +110,7 @@ namespace UnitTest
TEST_F(ViewportUiManagerTestFixture, CreateClusterButtonAddsNewButtonAndReturnsId)
{
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto buttonId = m_viewportManagerWrapper.GetViewportManager()->CreateClusterButton(clusterId, "");
auto clusterEntry = m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().find(clusterId);
@@ -120,7 +120,7 @@ namespace UnitTest
TEST_F(ViewportUiManagerTestFixture, SetClusterActiveButtonSetsButtonStateToActive)
{
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto buttonId = m_viewportManagerWrapper.GetViewportManager()->CreateClusterButton(clusterId, "");
auto clusterEntry = m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().find(clusterId);
@@ -133,7 +133,7 @@ namespace UnitTest
TEST_F(ViewportUiManagerTestFixture, RegisterClusterEventHandlerConnectsHandlerToClusterEvent)
{
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto buttonId = m_viewportManagerWrapper.GetViewportManager()->CreateClusterButton(clusterId, "");
// create a handler which will be triggered by the cluster
@@ -159,7 +159,7 @@ namespace UnitTest
TEST_F(ViewportUiManagerTestFixture, RemoveClusterRemovesClusterFromViewportUi)
{
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
m_viewportManagerWrapper.GetViewportManager()->RemoveCluster(clusterId);
auto clusterEntry = m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().find(clusterId);
@@ -171,7 +171,7 @@ namespace UnitTest
{
m_viewportManagerWrapper.GetMockRenderOverlay()->setVisible(true);
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto buttonId = m_viewportManagerWrapper.GetViewportManager()->CreateClusterButton(clusterId, "");
m_viewportManagerWrapper.GetViewportManager()->Update();
@@ -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);