Merge branch 'develop' into LYN-1767-AB

This commit is contained in:
igarri
2021-06-16 12:30:10 +01:00
875 changed files with 200447 additions and 106012 deletions
@@ -916,9 +916,6 @@ namespace AzToolsFramework
eECMF_USE_VIEWPORT_CENTER = 0x2,
};
/// Populate global edit-time context menu.
virtual void PopulateEditorGlobalContextMenu(QMenu * /*menu*/, const AZ::Vector2& /*point*/, int /*flags*/) {}
/// Populate slice portion of edit-time context menu
virtual void PopulateEditorGlobalContextMenu_SliceSection(QMenu * /*menu*/, const AZ::Vector2& /*point*/, int /*flags*/) {}
@@ -230,7 +230,7 @@ namespace AzToolsFramework::AssetUtils
AZStd::vector<AzFramework::GemInfo> gemInfoList;
if (!AzFramework::GetGemsInfo(gemInfoList, *settingsRegistry))
{
AZ_Error("AzToolsFramework::AssetUtils", false, "Failed to read gems from project folder(%s).\n", projectPath);
AZ_Error("AzToolsFramework::AssetUtils", false, "Failed to read gems from project folder(%.*s).\n", AZ_STRING_ARG(projectPath));
return {};
}
@@ -79,7 +79,7 @@ namespace AzToolsFramework
* This is the menu that appears when right clicking the main editor window,
* including the Entity Outliner and the Viewport.
*/
virtual void PopulateEditorGlobalContextMenu(QMenu* menu) const = 0;
virtual void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) = 0;
};
using EditorContextMenuBus = AZ::EBus<EditorContextMenuEvents>;
@@ -159,12 +159,23 @@ namespace AzToolsFramework
void PrefabEditorEntityOwnershipService::GetNonPrefabEntities(EntityList& entities)
{
m_rootInstance->GetEntities(entities, false);
m_rootInstance->GetEntities(
[&entities](const AZStd::unique_ptr<AZ::Entity>& entity)
{
entities.emplace_back(entity.get());
return true;
});
}
bool PrefabEditorEntityOwnershipService::GetAllEntities(EntityList& entities)
{
m_rootInstance->GetEntities(entities, true);
m_rootInstance->GetAllEntitiesInHierarchy(
[&entities](const AZStd::unique_ptr<AZ::Entity>& entity)
{
entities.emplace_back(entity.get());
return true;
});
return true;
}
@@ -185,13 +196,7 @@ namespace AzToolsFramework
bool PrefabEditorEntityOwnershipService::LoadFromStream(AZ::IO::GenericStream& stream, AZStd::string_view filename)
{
Reset();
// Make loading from stream to behave the same in terms of filesize as regular loading of prefabs
// This may need to be revisited in the future for supporting higher sizes along with prefab loading
if (stream.GetLength() > Prefab::MaxPrefabFileSize)
{
AZ_Error("Prefab", false, "'%.*s' prefab content is bigger than the max supported size (%f MB)", AZ_STRING_ARG(filename), Prefab::MaxPrefabFileSize / (1024.f * 1024.f));
return false;
}
const size_t bufSize = stream.GetLength();
AZStd::unique_ptr<char[]> buf(new char[bufSize]);
AZ::IO::SizeType bytes = stream.Read(bufSize, buf.get());
@@ -258,13 +263,20 @@ namespace AzToolsFramework
}
AZStd::string out;
if (m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out))
if (!m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out))
{
const size_t bytesToWrite = out.size();
const size_t bytesWritten = stream.Write(bytesToWrite, out.data());
return bytesWritten == bytesToWrite;
return false;
}
return false;
const size_t bytesToWrite = out.size();
const size_t bytesWritten = stream.Write(bytesToWrite, out.data());
if(bytesWritten != bytesToWrite)
{
return false;
}
m_prefabSystemComponent->SetTemplateDirtyFlag(templateId, false);
return true;
}
void PrefabEditorEntityOwnershipService::CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename)
@@ -550,7 +562,7 @@ namespace AzToolsFramework
return;
}
m_rootInstance->GetNestedEntities([this](AZStd::unique_ptr<AZ::Entity>& entity)
m_rootInstance->GetAllEntitiesInHierarchy([this](AZStd::unique_ptr<AZ::Entity>& entity)
{
AZ_Assert(entity, "Invalid entity found in root instance while starting play in editor.");
if (entity->GetState() == AZ::Entity::State::Active)
@@ -187,13 +187,14 @@ namespace AzToolsFramework
return removedEntity;
}
void Instance::DetachNestedEntities(const AZStd::function<void(AZStd::unique_ptr<AZ::Entity>)>& callback)
void Instance::DetachAllEntitiesInHierarchy(const AZStd::function<void(AZStd::unique_ptr<AZ::Entity>)>& callback)
{
callback(AZStd::move(DetachContainerEntity()));
DetachEntities(callback);
for (const auto& [instanceAlias, instance] : m_nestedInstances)
{
instance->DetachNestedEntities(callback);
instance->DetachAllEntitiesInHierarchy(callback);
}
}
@@ -372,17 +373,25 @@ namespace AzToolsFramework
}
}
void Instance::GetConstNestedEntities(const AZStd::function<bool(const AZ::Entity&)>& callback)
bool Instance::GetEntities_Impl(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
{
GetConstEntities(callback);
for (const auto& [instanceAlias, instance] : m_nestedInstances)
for (auto& [entityAlias, entity] : m_entities)
{
instance->GetConstNestedEntities(callback);
if (!entity)
{
continue;
}
if (!callback(entity))
{
return false;
}
}
return true;
}
void Instance::GetConstEntities(const AZStd::function<bool(const AZ::Entity&)>& callback)
bool Instance::GetConstEntities_Impl(const AZStd::function<bool(const AZ::Entity&)>& callback) const
{
for (const auto& [entityAlias, entity] : m_entities)
{
@@ -393,19 +402,83 @@ namespace AzToolsFramework
if (!callback(*entity))
{
break;
return false;
}
}
return true;
}
void Instance::GetNestedEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
bool Instance::GetAllEntitiesInHierarchy_Impl(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
{
GetEntities(callback);
if (HasContainerEntity())
{
if (!callback(m_containerEntity))
{
return false;
}
}
if (!GetEntities_Impl(callback))
{
return false;
}
for (auto& [instanceAlias, instance] : m_nestedInstances)
{
instance->GetNestedEntities(callback);
if (!instance->GetAllEntitiesInHierarchy_Impl(callback))
{
return false;
}
}
return true;
}
bool Instance::GetAllEntitiesInHierarchyConst_Impl(const AZStd::function<bool(const AZ::Entity&)>& callback) const
{
if (HasContainerEntity())
{
if (!callback(*m_containerEntity))
{
return false;
}
}
if (!GetConstEntities_Impl(callback))
{
return false;
}
for (const auto& [instanceAlias, instance] : m_nestedInstances)
{
if (!instance->GetAllEntitiesInHierarchyConst_Impl(callback))
{
return false;
}
}
return true;
}
void Instance::GetEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
{
GetEntities_Impl(callback);
}
void Instance::GetConstEntities(const AZStd::function<bool(const AZ::Entity&)>& callback) const
{
GetConstEntities_Impl(callback);
}
void Instance::GetAllEntitiesInHierarchy(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
{
GetAllEntitiesInHierarchy_Impl(callback);
}
void Instance::GetAllEntitiesInHierarchyConst(const AZStd::function<bool(const AZ::Entity&)>& callback) const
{
GetAllEntitiesInHierarchyConst_Impl(callback);
}
void Instance::GetNestedInstances(const AZStd::function<void(AZStd::unique_ptr<Instance>&)>& callback)
@@ -416,44 +489,6 @@ namespace AzToolsFramework
}
}
void Instance::GetEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
{
for (auto& [entityAlias, entity] : m_entities)
{
if (!callback(entity))
{
break;
}
}
}
void Instance::GetEntities(EntityList& entities, bool includeNestedEntities)
{
// Non-recursive traversal of instances
AZStd::vector<Instance*> instancesToTraverse = { this };
while (!instancesToTraverse.empty())
{
Instance* currentInstance = instancesToTraverse.back();
instancesToTraverse.pop_back();
if (includeNestedEntities)
{
instancesToTraverse.reserve(instancesToTraverse.size() + currentInstance->m_nestedInstances.size());
for (const auto& instanceByAlias : currentInstance->m_nestedInstances)
{
instancesToTraverse.push_back(instanceByAlias.second.get());
}
}
// Size increases by 1 for each instance because we have to count the container entity also.
entities.reserve(entities.size() + currentInstance->m_entities.size() + 1);
entities.push_back(m_containerEntity.get());
for (const auto& entityByAlias : currentInstance->m_entities)
{
entities.push_back(entityByAlias.second.get());
}
}
}
EntityAliasOptionalReference Instance::GetEntityAlias(const AZ::EntityId& id)
{
if (m_instanceToTemplateEntityIdMap.count(id))
@@ -87,7 +87,15 @@ namespace AzToolsFramework
bool AddEntity(AZ::Entity& entity, EntityAlias entityAlias);
AZStd::unique_ptr<AZ::Entity> DetachEntity(const AZ::EntityId& entityId);
void DetachEntities(const AZStd::function<void(AZStd::unique_ptr<AZ::Entity>)>& callback);
void DetachNestedEntities(const AZStd::function<void(AZStd::unique_ptr<AZ::Entity>)>& callback);
/**
* Detaches all entities in the instance hierarchy.
* Includes all direct entities, all nested entities, and all container entities.
* Note that without container entities the hierarchy that remains cannot be used further without restoring new ones.
* @param callback A user provided callback that can be used to capture ownership and manipulate the detached entities.
*/
void DetachAllEntitiesInHierarchy(const AZStd::function<void(AZStd::unique_ptr<AZ::Entity>)>& callback);
void RemoveNestedEntities(const AZStd::function<bool(const AZStd::unique_ptr<AZ::Entity>&)>& filter);
void Reset();
@@ -113,10 +121,10 @@ namespace AzToolsFramework
/**
* Gets the entities in the Instance DOM. Can recursively trace all nested instances.
*/
void GetConstNestedEntities(const AZStd::function<bool(const AZ::Entity&)>& callback);
void GetConstEntities(const AZStd::function<bool(const AZ::Entity&)>& callback);
void GetNestedEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
void GetEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
void GetConstEntities(const AZStd::function<bool(const AZ::Entity&)>& callback) const;
void GetAllEntitiesInHierarchy(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
void GetAllEntitiesInHierarchyConst(const AZStd::function<bool(const AZ::Entity&)>& callback) const;
void GetNestedInstances(const AZStd::function<void(AZStd::unique_ptr<Instance>&)>& callback);
/**
@@ -176,12 +184,6 @@ namespace AzToolsFramework
static InstanceAlias GenerateInstanceAlias();
protected:
/**
* Gets the entities owned by this instance
*/
void GetEntities(EntityList& entities, bool includeNestedEntities = false);
private:
static constexpr const char s_aliasPathSeparator = '/';
@@ -189,6 +191,11 @@ namespace AzToolsFramework
void RemoveEntities(const AZStd::function<bool(const AZStd::unique_ptr<AZ::Entity>&)>& filter);
bool GetEntities_Impl(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
bool GetConstEntities_Impl(const AZStd::function<bool(const AZ::Entity&)>& callback) const;
bool GetAllEntitiesInHierarchy_Impl(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
bool GetAllEntitiesInHierarchyConst_Impl(const AZStd::function<bool(const AZ::Entity&)>& callback) const;
bool RegisterEntity(const AZ::EntityId& entityId, const EntityAlias& entityAlias);
AZStd::unique_ptr<AZ::Entity> DetachEntity(const EntityAlias& entityAlias);
@@ -154,7 +154,7 @@ namespace AzToolsFramework
InstanceOptionalReference owningInstanceReference = m_storingInstance->m_instanceEntityMapper->FindOwningInstance(entityId);
// Start with an empty alias to build out our reference path
// If we can't resolve this id we'll return a random new alias instead of a reference path
// If we can't resolve this id we'll return a new alias based on the entity ID instead of a reference path
AliasPath relativeEntityAliasPath;
if (!owningInstanceReference)
{
@@ -162,7 +162,7 @@ namespace AzToolsFramework
"Prefab - EntityIdMapper: Entity with Id %s has no registered owning instance",
entityId.ToString().c_str());
return Instance::GenerateEntityAlias();
return AZStd::string::format("Entity_%s", entityId.ToString().c_str());
}
Instance* owningInstance = &(owningInstanceReference->get());
@@ -74,7 +74,7 @@ namespace AzToolsFramework
return InvalidTemplateId;
}
auto readResult = AZ::Utils::ReadFile(GetFullPath(filePath).Native(), MaxPrefabFileSize);
auto readResult = AZ::Utils::ReadFile(GetFullPath(filePath).Native(), AZStd::numeric_limits<size_t>::max());
if (!readResult.IsSuccess())
{
AZ_Error(
@@ -21,8 +21,6 @@ namespace AzToolsFramework
{
namespace Prefab
{
constexpr size_t MaxPrefabFileSize = 1024 * 1024;
/*!
* PrefabLoaderInterface
* Interface for saving/loading Prefab files.
@@ -336,7 +336,7 @@ namespace AzToolsFramework
{
// Load the template from the file
templateId = m_prefabLoaderInterface->LoadTemplateFromFile(filePath);
AZ_Assert(templateId != InvalidTemplateId, "Template with source path %s couldn't be loaded correctly.", filePath);
AZ_Assert(templateId != InvalidTemplateId, "Template with source path %.*s couldn't be loaded correctly.", AZ_STRING_ARG(filePath));
}
const PrefabDom& templateDom = m_prefabSystemComponentInterface->FindTemplateDom(templateId);
@@ -901,7 +901,13 @@ namespace AzToolsFramework
return AZ::Failure(AZStd::string("No entities to duplicate."));
}
if (!EntitiesBelongToSameInstance(entityIds))
const EntityIdList entityIdsNoLevelInstance = GenerateEntityIdListWithoutLevelInstance(entityIds);
if (entityIdsNoLevelInstance.empty())
{
return AZ::Failure(AZStd::string("No entities to duplicate because only instance selected is the level instance."));
}
if (!EntitiesBelongToSameInstance(entityIdsNoLevelInstance))
{
return AZ::Failure(AZStd::string("Cannot duplicate multiple entities belonging to different instances with one operation."
"Change your selection to contain entities in the same instance."));
@@ -909,7 +915,7 @@ namespace AzToolsFramework
// We've already verified the entities are all owned by the same instance,
// so we can just retrieve our instance from the first entity in the list.
AZ::EntityId firstEntityIdToDuplicate = entityIds[0];
AZ::EntityId firstEntityIdToDuplicate = entityIdsNoLevelInstance[0];
InstanceOptionalReference commonOwningInstance = GetOwnerInstanceByEntityId(firstEntityIdToDuplicate);
if (!commonOwningInstance.has_value())
{
@@ -929,7 +935,7 @@ namespace AzToolsFramework
// This will cull out any entities that have ancestors in the list, since we will end up duplicating
// the full nested hierarchy with what is returned from RetrieveAndSortPrefabEntitiesAndInstances
AzToolsFramework::EntityIdSet duplicationSet = AzToolsFramework::GetCulledEntityHierarchy(entityIds);
AzToolsFramework::EntityIdSet duplicationSet = AzToolsFramework::GetCulledEntityHierarchy(entityIdsNoLevelInstance);
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -1004,17 +1010,19 @@ namespace AzToolsFramework
PrefabOperationResult PrefabPublicHandler::DeleteFromInstance(const EntityIdList& entityIds, bool deleteDescendants)
{
if (entityIds.empty())
const EntityIdList entityIdsNoLevelInstance = GenerateEntityIdListWithoutLevelInstance(entityIds);
if (entityIdsNoLevelInstance.empty())
{
return AZ::Success();
}
if (!EntitiesBelongToSameInstance(entityIds))
if (!EntitiesBelongToSameInstance(entityIdsNoLevelInstance))
{
return AZ::Failure(AZStd::string("Cannot delete multiple entities belonging to different instances with one operation."));
}
AZ::EntityId firstEntityIdToDelete = entityIds[0];
AZ::EntityId firstEntityIdToDelete = entityIdsNoLevelInstance[0];
InstanceOptionalReference commonOwningInstance = GetOwnerInstanceByEntityId(firstEntityIdToDelete);
// If the first entity id is a container entity id, then we need to mark its parent as the common owning instance because you
@@ -1025,7 +1033,7 @@ namespace AzToolsFramework
}
// Retrieve entityList from entityIds
EntityList inputEntityList = EntityIdListToEntityList(entityIds);
EntityList inputEntityList = EntityIdListToEntityList(entityIdsNoLevelInstance);
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -1081,7 +1089,7 @@ namespace AzToolsFramework
}
else
{
for (AZ::EntityId entityId : entityIds)
for (AZ::EntityId entityId : entityIdsNoLevelInstance)
{
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
// If this is the container entity, it actually represents the instance so get its owner
@@ -1437,6 +1445,22 @@ namespace AzToolsFramework
return (outEntities.size() + outInstances.size()) > 0;
}
EntityIdList PrefabPublicHandler::GenerateEntityIdListWithoutLevelInstance(
const EntityIdList& entityIds) const
{
EntityIdList outEntityIds;
outEntityIds.reserve(entityIds.size()); // Actual size could be smaller.
for (const AZ::EntityId& entityId : entityIds)
{
if (!IsLevelInstanceContainerEntity(entityId))
{
outEntityIds.emplace_back(entityId);
}
}
return outEntityIds;
}
bool PrefabPublicHandler::EntitiesBelongToSameInstance(const EntityIdList& entityIds) const
{
if (entityIds.size() <= 1)
@@ -70,6 +70,7 @@ namespace AzToolsFramework
PrefabOperationResult DeleteFromInstance(const EntityIdList& entityIds, bool deleteDescendants);
bool RetrieveAndSortPrefabEntitiesAndInstances(const EntityList& inputEntities, Instance& commonRootEntityOwningInstance,
EntityList& outEntities, AZStd::vector<Instance*>& outInstances) const;
EntityIdList GenerateEntityIdListWithoutLevelInstance(const EntityIdList& entityIds) const;
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
@@ -62,25 +62,16 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
}
}
AZStd::vector<AZ::Entity*> EditorInfoRemover::GetEntitiesFromInstance(AZStd::unique_ptr<Instance>& instance)
void EditorInfoRemover::GetEntitiesFromInstance(
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& instance, EntityList& hierarchyEntities)
{
AZStd::vector<AZ::Entity*> result;
instance->GetNestedEntities(
[&result](const AZStd::unique_ptr<AZ::Entity>& entity)
instance->GetAllEntitiesInHierarchy(
[&hierarchyEntities](const AZStd::unique_ptr<AZ::Entity>& entity)
{
result.emplace_back(entity.get());
hierarchyEntities.emplace_back(entity.get());
return true;
}
);
if (instance->HasContainerEntity())
{
auto containerEntityReference = instance->GetContainerEntity();
result.emplace_back(&containerEntityReference->get());
}
return result;
}
void EditorInfoRemover::SetEditorOnlyEntityHandlerFromCandidates(const EntityList& entities)
@@ -543,7 +534,9 @@ exportComponent, prefabProcessorContext);
}
// grab all nested entities from the Instance as source entities.
EntityList sourceEntities = GetEntitiesFromInstance(instance);
EntityList sourceEntities;
GetEntitiesFromInstance(instance, sourceEntities);
EntityList exportEntities;
// prepare for validation of component requirements.
@@ -616,7 +609,7 @@ exportComponent, prefabProcessorContext);
);
// replace entities of instance with exported ones.
instance->GetNestedEntities(
instance->GetAllEntitiesInHierarchy(
[&exportEntitiesMap](AZStd::unique_ptr<AZ::Entity>& entity)
{
auto entityId = entity->GetId();
@@ -625,14 +618,6 @@ exportComponent, prefabProcessorContext);
}
);
if (instance->HasContainerEntity())
{
if (auto found = exportEntitiesMap.find(instance->GetContainerEntityId()); found != exportEntitiesMap.end())
{
instance->SetContainerEntity(*found->second);
}
}
// save the final result in the target Prefab DOM.
PrefabDom filteredPrefab;
if (!PrefabDomUtils::StoreInstanceInPrefabDom(*instance, filteredPrefab))
@@ -55,8 +55,8 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
protected:
using EntityList = AZStd::vector<AZ::Entity*>;
static EntityList GetEntitiesFromInstance(
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& instance);
static void GetEntitiesFromInstance(
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& instance, EntityList& hierarchyEntities);
static bool ReadComponentAttribute(
AZ::Component* component,
@@ -38,11 +38,7 @@ namespace AzToolsFramework::Prefab::SpawnableUtils
// going to be used to create clones of the entities.
{
AzFramework::Spawnable::EntityList& entities = spawnable.GetEntities();
if (instance.HasContainerEntity())
{
entities.emplace_back(AZStd::move(instance.DetachContainerEntity()));
}
instance.DetachNestedEntities(
instance.DetachAllEntitiesInHierarchy(
[&entities](AZStd::unique_ptr<AZ::Entity> entity)
{
entities.emplace_back(AZStd::move(entity));
@@ -1206,7 +1206,7 @@ namespace AzToolsFramework
Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::NotPushableOnSliceRoot)->
Attribute(AZ::Edit::Attributes::ReadOnly, &EditorTransform::m_locked)->
DataElement(AZ::Edit::UIHandlers::Default, &EditorTransform::m_rotate, "Rotate", "Local Rotation (Relative to parent) in degrees.")->
Attribute(AZ::Edit::Attributes::Step, 0.1f)->
Attribute(AZ::Edit::Attributes::Step, 1.0f)->
Attribute(AZ::Edit::Attributes::Suffix, " deg")->
Attribute(AZ::Edit::Attributes::ReadOnly, &EditorTransform::m_locked)->
Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::NotPushableOnSliceRoot)->
@@ -26,6 +26,7 @@
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Commands/SelectionCommand.h>
#include <AzToolsFramework/Editor/EditorContextMenuBus.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
@@ -544,8 +545,7 @@ namespace AzToolsFramework
QMenu* contextMenu = new QMenu(this);
// Populate global context menu.
EBUS_EVENT(EditorEvents::Bus,
PopulateEditorGlobalContextMenu,
AzToolsFramework::EditorContextMenuBus::Broadcast(&AzToolsFramework::EditorContextMenuEvents::PopulateEditorGlobalContextMenu,
contextMenu,
AZ::Vector2::CreateZero(),
EditorEvents::eECMF_HIDE_ENTITY_CREATION | EditorEvents::eECMF_USE_VIEWPORT_CENTER);
@@ -58,8 +58,17 @@ namespace AzToolsFramework
if (!path.empty())
{
infoString =
QObject::tr("<span style=\"font-style: italic; font-weight: 400;\">(%1)</span>").arg(path.Filename().Native().data());
QString saveFlag = "";
auto dirtyOutcome = m_prefabPublicInterface->HasUnsavedChanges(path);
if (dirtyOutcome.IsSuccess() && dirtyOutcome.GetValue() == true)
{
saveFlag = "*";
}
infoString = QObject::tr("<span style=\"font-style: italic; font-weight: 400;\">(%1%2)</span>")
.arg(path.Filename().Native().data())
.arg(saveFlag);
}
return infoString;
@@ -28,6 +28,7 @@
#include <AzToolsFramework/ToolsComponents/EditorLayerComponentBus.h>
#include <AzToolsFramework/UI/EditorEntityUi/EditorEntityUiInterface.h>
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h>
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
#include <QApplication>
#include <QFileDialog>
@@ -119,7 +120,7 @@ namespace AzToolsFramework
return "Prefabs";
}
void PrefabIntegrationManager::PopulateEditorGlobalContextMenu(QMenu* menu) const
void PrefabIntegrationManager::PopulateEditorGlobalContextMenu(QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags)
{
AzToolsFramework::EntityIdList selectedEntities;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
@@ -588,15 +589,6 @@ namespace AzToolsFramework
bool PrefabIntegrationManager::QueryUserForPrefabFilePath(AZStd::string& outPrefabFilePath)
{
QWidget* mainWindow = nullptr;
EditorRequests::Bus::BroadcastResult(mainWindow, &EditorRequests::Bus::Events::GetMainWindow);
if (mainWindow == nullptr)
{
AZ_Assert(false, "Prefab - Could not detect Editor main window to generate the asset picker.");
return false;
}
AssetSelectionModel selection;
// Note, stringfilter will match every source file CONTAINING ".prefab".
@@ -624,7 +616,7 @@ namespace AzToolsFramework
selection.SetDisplayFilter(compositeFilterPtr);
selection.SetSelectionFilter(compositeFilterPtr);
AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, mainWindow);
AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, AzToolsFramework::GetActiveWindow());
if (!selection.IsValid())
{
@@ -983,12 +975,7 @@ namespace AzToolsFramework
includedEntities.c_str(),
referencedEntities.c_str());
QWidget* mainWindow = nullptr;
AzToolsFramework::EditorRequests::Bus::BroadcastResult(
mainWindow,
&AzToolsFramework::EditorRequests::Bus::Events::GetMainWindow);
QMessageBox msgBox(mainWindow);
QMessageBox msgBox(AzToolsFramework::GetActiveWindow());
msgBox.setWindowTitle("External Entity References");
msgBox.setText("The prefab contains references to external entities that are not selected.");
msgBox.setInformativeText("You can move the referenced entities into this prefab or retain the external references.");
@@ -65,7 +65,7 @@ namespace AzToolsFramework
// EditorContextMenuBus...
int GetMenuPosition() const override;
AZStd::string GetMenuIdentifier() const override;
void PopulateEditorGlobalContextMenu(QMenu* menu) const override;
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override;
// EntityOutlinerSourceDropHandlingBus...
void HandleSourceFileType(AZStd::string_view sourceFilePath, AZ::EntityId parentId, AZ::Vector3 position) const override;
@@ -1130,6 +1130,16 @@ namespace AzToolsFramework
m_browseEdit->setAttachedButtonIcon(icon);
}
void PropertyAssetCtrl::SetBrowseButtonEnabled(bool enabled)
{
m_browseEdit->setEnabled(enabled);
}
void PropertyAssetCtrl::SetBrowseButtonVisible(bool visible)
{
m_browseEdit->setVisible(visible);
}
const QModelIndex PropertyAssetCtrl::GetSourceIndex(const QModelIndex& index)
{
if (!index.isValid())
@@ -1360,6 +1370,22 @@ namespace AzToolsFramework
GUI->SetBrowseButtonIcon(QIcon(iconPath.c_str()));
}
}
else if (attrib == AZ_CRC_CE("BrowseButtonEnabled"))
{
bool enabled = true;
if (attrValue->Read<bool>(enabled))
{
GUI->SetBrowseButtonEnabled(enabled);
}
}
else if (attrib == AZ_CRC_CE("BrowseButtonVisible"))
{
bool visible = true;
if (attrValue->Read<bool>(visible))
{
GUI->SetBrowseButtonVisible(visible);
}
}
else if (attrib == AZ_CRC_CE("Thumbnail"))
{
bool showThumbnail = false;
@@ -1447,6 +1473,49 @@ namespace AzToolsFramework
GUI->SetBrowseButtonIcon(QIcon(iconPath.c_str()));
}
}
else if (attrib == AZ_CRC("EditCallback", 0xb74f2ee1))
{
PropertyAssetCtrl::EditCallbackType* func = azdynamic_cast<PropertyAssetCtrl::EditCallbackType*>(attrValue->GetAttribute());
if (func)
{
GUI->SetEditButtonVisible(true);
GUI->SetEditNotifyCallback(func);
}
else
{
GUI->SetEditNotifyCallback(nullptr);
}
}
else if (attrib == AZ_CRC("EditButton", 0x898c35dc))
{
GUI->SetEditButtonVisible(true);
AZStd::string iconPath;
attrValue->Read<AZStd::string>(iconPath);
if (!iconPath.empty())
{
QString path(iconPath.c_str());
if (!QFile::exists(path))
{
AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath();
QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current();
path = engineDir.absoluteFilePath(iconPath.c_str());
}
GUI->SetEditButtonIcon(QIcon(path));
}
}
else if (attrib == AZ_CRC("EditDescription", 0x9b52634a))
{
AZStd::string buttonTooltip;
if (attrValue->Read<AZStd::string>(buttonTooltip))
{
GUI->SetEditButtonTooltip(tr(buttonTooltip.c_str()));
}
}
}
void SimpleAssetPropertyHandlerDefault::WriteGUIValuesIntoProperty(size_t index, PropertyAssetCtrl* GUI, property_t& instance, InstanceDataNode* node)
@@ -1476,6 +1545,7 @@ namespace AzToolsFramework
// Set the hint in case the asset is not able to be found by assetId
GUI->SetCurrentAssetHint(instance.GetAssetPath());
GUI->SetSelectedAssetID(assetId, instance.GetAssetType());
GUI->SetEditNotifyTarget(node->GetParent()->GetInstance(0));
GUI->blockSignals(false);
return false;
@@ -208,6 +208,8 @@ namespace AzToolsFramework
void SetEditButtonIcon(const QIcon& icon);
void SetEditButtonTooltip(QString tooltip);
void SetBrowseButtonIcon(const QIcon& icon);
void SetBrowseButtonEnabled(bool enabled);
void SetBrowseButtonVisible(bool visible);
void SetClearButtonEnabled(bool enable);
void SetClearButtonVisible(bool visible);
@@ -188,7 +188,7 @@ namespace AzToolsFramework
virtual void AddEditMenuAction(QAction* action) = 0;
/// Add an action to the Editor menu.
virtual void AddMenuAction(AZStd::string_view categoryId, QAction* action) = 0;
virtual void AddMenuAction(AZStd::string_view categoryId, QAction* action, bool addToToolsToolbar) = 0;
/// (Re)populate the default EditMenu.
/// Restore the EditMenu to its default state (the options available when first opening a level).
@@ -13,6 +13,7 @@
#include "EditorContextMenu.h"
#include "AzToolsFramework/Viewport/ViewportMessages.h"
#include "Editor/EditorContextMenuBus.h"
namespace AzToolsFramework
{
@@ -55,8 +56,7 @@ namespace AzToolsFramework
// Populate global context menu.
const int contextMenuFlag = 0;
EditorEvents::Bus::BroadcastReverse(
&EditorEvents::PopulateEditorGlobalContextMenu, contextMenu.m_menu.data(),
AzToolsFramework::EditorContextMenuBus::Broadcast(&AzToolsFramework::EditorContextMenuEvents::PopulateEditorGlobalContextMenu, contextMenu.m_menu.data(),
AzFramework::Vector2FromScreenPoint(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates),
contextMenuFlag);
@@ -136,6 +136,13 @@ namespace AzToolsFramework
static const char* const s_duplicateUndoRedoDesc = s_duplicateTitle;
static const char* const s_deleteUndoRedoDesc = s_deleteTitle;
static const char* const TransformModeClusterTranslateTooltip = "Switch to translate mode";
static const char* const TransformModeClusterRotateTooltip = "Switch to rotate mode";
static const char* const TransformModeClusterScaleTooltip = "Switch to scale mode";
static const char* const SpaceClusterWorldTooltip = "Toggle world space lock";
static const char* const SpaceClusterParentTooltip = "Toggle parent space lock";
static const char* const SpaceClusterLocalTooltip = "Toggle local space lock";
static const AZ::Color s_fadedXAxisColor = AZ::Color(AZ::u8(200), AZ::u8(127), AZ::u8(127), AZ::u8(255));
static const AZ::Color s_fadedYAxisColor = AZ::Color(AZ::u8(127), AZ::u8(190), AZ::u8(127), AZ::u8(255));
static const AZ::Color s_fadedZAxisColor = AZ::Color(AZ::u8(120), AZ::u8(120), AZ::u8(180), AZ::u8(255));
@@ -493,6 +500,13 @@ namespace AzToolsFramework
return worldFromLocal.TransformPoint(CalculateCenterOffset(entityId, pivot));
}
void EditorTransformComponentSelection::SetAllViewportUiVisible(const bool visible)
{
SetViewportUiClusterVisible(m_transformModeClusterId, visible);
SetViewportUiClusterVisible(m_spaceCluster.m_spaceClusterId, visible);
m_viewportUiVisible = visible;
}
void EditorTransformComponentSelection::UpdateSpaceCluster(const ReferenceFrame referenceFrame)
{
auto buttonIdFromFrameFn = [this](const ReferenceFrame referenceFrame)
@@ -1015,9 +1029,11 @@ namespace AzToolsFramework
ToolsApplicationNotificationBus::Handler::BusConnect();
Camera::EditorCameraNotificationBus::Handler::BusConnect();
ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(entityContextId);
EditorEntityContextNotificationBus::Handler::BusConnect();
EditorEntityVisibilityNotificationBus::Router::BusRouterConnect();
EditorEntityLockComponentNotificationBus::Router::BusRouterConnect();
EditorManipulatorCommandUndoRedoRequestBus::Handler::BusConnect(entityContextId);
EditorContextMenuBus::Handler::BusConnect();
CreateTransformModeSelectionCluster();
CreateSpaceSelectionCluster();
@@ -1038,9 +1054,11 @@ namespace AzToolsFramework
m_pivotOverrideFrame.Reset();
EditorContextMenuBus::Handler::BusConnect();
EditorManipulatorCommandUndoRedoRequestBus::Handler::BusDisconnect();
EditorEntityLockComponentNotificationBus::Router::BusRouterDisconnect();
EditorEntityVisibilityNotificationBus::Router::BusRouterDisconnect();
EditorEntityContextNotificationBus::Handler::BusDisconnect();
ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
Camera::EditorCameraNotificationBus::Handler::BusDisconnect();
ToolsApplicationNotificationBus::Handler::BusDisconnect();
@@ -2371,9 +2389,7 @@ namespace AzToolsFramework
/*ID_VIEWPORTUI_VISIBLE=*/50040, "Toggle ViewportUI", "Hide/Unhide Viewport UI",
[this]()
{
SetViewportUiClusterVisible(m_transformModeClusterId, !m_viewportUiVisible);
SetViewportUiClusterVisible(m_spaceCluster.m_spaceClusterId, !m_viewportUiVisible);
m_viewportUiVisible = !m_viewportUiVisible;
SetAllViewportUiVisible(!m_viewportUiVisible);
});
EditorMenuRequestBus::Broadcast(&EditorMenuRequests::RestoreEditMenuToDefault);
@@ -2460,6 +2476,17 @@ namespace AzToolsFramework
m_rotateButtonId = RegisterClusterButton(m_transformModeClusterId, "Translate");
m_scaleButtonId = RegisterClusterButton(m_transformModeClusterId, "Scale");
// set button tooltips
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip, m_transformModeClusterId,
m_translateButtonId, TransformModeClusterTranslateTooltip);
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip, m_transformModeClusterId,
m_rotateButtonId, TransformModeClusterRotateTooltip);
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip, m_transformModeClusterId,
m_scaleButtonId, TransformModeClusterScaleTooltip);
auto onButtonClicked = [this](ViewportUi::ButtonId buttonId)
{
if (buttonId == m_translateButtonId)
@@ -2498,6 +2525,17 @@ namespace AzToolsFramework
m_spaceCluster.m_parentButtonId = RegisterClusterButton(m_spaceCluster.m_spaceClusterId, "Parent");
m_spaceCluster.m_localButtonId = RegisterClusterButton(m_spaceCluster.m_spaceClusterId, "Local");
// set button tooltips
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip,
m_spaceCluster.m_spaceClusterId, m_spaceCluster.m_worldButtonId, SpaceClusterWorldTooltip);
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip,
m_spaceCluster.m_spaceClusterId, m_spaceCluster.m_parentButtonId, SpaceClusterParentTooltip);
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip,
m_spaceCluster.m_spaceClusterId, m_spaceCluster.m_localButtonId, SpaceClusterLocalTooltip);
auto onButtonClicked = [this](ViewportUi::ButtonId buttonId)
{
if (buttonId == m_spaceCluster.m_localButtonId)
@@ -3097,15 +3135,25 @@ namespace AzToolsFramework
}
}
void EditorTransformComponentSelection::PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& /*point*/, const int /*flags*/)
int EditorTransformComponentSelection::GetMenuPosition() const
{
QAction* action = menu->addAction(QObject::tr(s_togglePivotTitleRightClick));
QObject::connect(
action, &QAction::triggered, action,
[this]()
{
ToggleCenterPivotSelection();
});
return aznumeric_cast<int>(EditorContextMenuOrdering::BOTTOM);
}
AZStd::string EditorTransformComponentSelection::GetMenuIdentifier() const
{
return "Transform Component";
}
void EditorTransformComponentSelection::PopulateEditorGlobalContextMenu(QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags)
{
QAction* action = menu->addAction(QObject::tr(s_togglePivotTitleRightClick));
QObject::connect(
action, &QAction::triggered, action,
[this]()
{
ToggleCenterPivotSelection();
});
}
void EditorTransformComponentSelection::BeforeEntitySelectionChanged()
@@ -3534,7 +3582,7 @@ namespace AzToolsFramework
void EditorTransformComponentSelection::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
{
SetViewportUiClusterVisible(m_transformModeClusterId, false);
SetAllViewportUiVisible(false);
EditorEntityLockComponentNotificationBus::Router::BusRouterDisconnect();
EditorEntityVisibilityNotificationBus::Router::BusRouterDisconnect();
@@ -3543,7 +3591,7 @@ namespace AzToolsFramework
void EditorTransformComponentSelection::LeftComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
{
SetViewportUiClusterVisible(m_transformModeClusterId, true);
SetAllViewportUiVisible(true);
ToolsApplicationNotificationBus::Handler::BusConnect();
EditorEntityVisibilityNotificationBus::Router::BusRouterConnect();
@@ -3599,6 +3647,16 @@ namespace AzToolsFramework
ETCS::SetEntityLocalRotation(entityId, localRotation, m_transformChangedInternally);
}
void EditorTransformComponentSelection::OnStartPlayInEditor()
{
SetAllViewportUiVisible(false);
}
void EditorTransformComponentSelection::OnStopPlayInEditor()
{
SetAllViewportUiVisible(true);
}
namespace ETCS
{
// little raii wrapper to switch a value from true to false and back
@@ -22,6 +22,7 @@
#include <AzToolsFramework/API/EditorCameraBus.h>
#include <AzToolsFramework/Commands/EntityManipulatorCommand.h>
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
#include <AzToolsFramework/Editor/EditorContextMenuBus.h>
#include <AzToolsFramework/Manipulators/BaseManipulator.h>
#include <AzToolsFramework/ToolsComponents/EditorLockComponentBus.h>
#include <AzToolsFramework/ToolsComponents/EditorVisibilityBus.h>
@@ -126,11 +127,13 @@ namespace AzToolsFramework
//! Provide a suite of functionality for manipulating entities, primarily through their TransformComponent.
class EditorTransformComponentSelection
: public ViewportInteraction::ViewportSelectionRequests
, public EditorContextMenuBus::Handler
, private EditorEventsBus::Handler
, private EditorTransformComponentSelectionRequestBus::Handler
, private ToolsApplicationNotificationBus::Handler
, private Camera::EditorCameraNotificationBus::Handler
, private ComponentModeFramework::EditorComponentModeNotificationBus::Handler
, private EditorEntityContextNotificationBus::Handler
, private EditorEntityVisibilityNotificationBus::Router
, private EditorEntityLockComponentNotificationBus::Router
, private EditorManipulatorCommandUndoRedoRequestBus::Handler
@@ -238,8 +241,12 @@ namespace AzToolsFramework
void UndoRedoEntityManipulatorCommand(
AZ::u8 pivotOverride, const AZ::Transform& transform, AZ::EntityId entityId) override;
// EditorContextMenuBus...
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2 & point, int flags) override;
int GetMenuPosition() const override;
AZStd::string GetMenuIdentifier() const override;
// EditorEventsBus ...
void PopulateEditorGlobalContextMenu(QMenu *menu, const AZ::Vector2& point, int flags) override;
void OnEscape() override;
// ToolsApplicationNotificationBus ...
@@ -263,6 +270,10 @@ namespace AzToolsFramework
void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
// EditorEntityContextNotificationBus overrides ...
void OnStartPlayInEditor() override;
void OnStopPlayInEditor() override;
// Helpers to safely interact with the TransformBus (requests).
void SetEntityWorldTranslation(AZ::EntityId entityId, const AZ::Vector3& worldTranslation);
void SetEntityLocalTranslation(AZ::EntityId entityId, const AZ::Vector3& localTranslation);
@@ -270,9 +281,12 @@ namespace AzToolsFramework
void SetEntityLocalScale(AZ::EntityId entityId, float localScale);
void SetEntityLocalRotation(AZ::EntityId entityId, const AZ::Vector3& localRotation);
// Responsible for keeping the space cluster in sync with the current reference frame.
//! Responsible for keeping the space cluster in sync with the current reference frame.
void UpdateSpaceCluster(ReferenceFrame referenceFrame);
//! Hides/Shows all viewportUi toolbars.
void SetAllViewportUiVisible(bool visible);
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.
@@ -163,6 +163,17 @@ namespace AzToolsFramework::ViewportUi::Internal
}
}
void ViewportUiCluster::SetButtonTooltip(const ButtonId buttonId, const AZStd::string& tooltip)
{
// get the action corresponding to the buttonId
if (auto actionEntry = m_buttonActionMap.find(buttonId); actionEntry != m_buttonActionMap.end())
{
// update the tooltip
auto action = actionEntry->second;
action->setToolTip(QString((tooltip).c_str()));
}
}
ViewportUiWidgetCallbacks ViewportUiCluster::GetWidgetCallbacks()
{
return m_widgetCallbacks;
@@ -41,6 +41,8 @@ namespace AzToolsFramework::ViewportUi::Internal
void Update();
//! Adds a locked overlay to the button's icon.
void SetButtonLocked(ButtonId buttonId, bool isLocked);
//! Updates the button's tooltip to the passed string.
void SetButtonTooltip(ButtonId buttonId, const AZStd::string& tooltip);
//! Returns the widget manager.
ViewportUiWidgetCallbacks GetWidgetCallbacks();
@@ -108,6 +108,14 @@ namespace AzToolsFramework::ViewportUi::Internal
}
}
void ViewportUiDisplay::SetClusterButtonTooltip(const ViewportUiElementId clusterId, const ButtonId buttonId, const AZStd::string& tooltip)
{
if (auto viewportUiCluster = qobject_cast<ViewportUiCluster*>(GetViewportUiElement(clusterId).get()))
{
viewportUiCluster->SetButtonTooltip(buttonId, tooltip);
}
}
void ViewportUiDisplay::RemoveClusterButton(ViewportUiElementId clusterId, ButtonId buttonId)
{
if (auto cluster = qobject_cast<ViewportUiCluster*>(GetViewportUiElement(clusterId).get()))
@@ -59,6 +59,7 @@ namespace AzToolsFramework::ViewportUi::Internal
void AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup, Alignment align);
void AddClusterButton(ViewportUiElementId clusterId, Button* button);
void SetClusterButtonLocked(ViewportUiElementId clusterId, ButtonId buttonId, bool isLocked);
void SetClusterButtonTooltip(ViewportUiElementId clusterId, ButtonId buttonId, const AZStd::string& tooltip);
void RemoveClusterButton(ViewportUiElementId clusterId, ButtonId buttonId);
void UpdateCluster(const ViewportUiElementId clusterId);
@@ -77,6 +77,16 @@ namespace AzToolsFramework::ViewportUi
}
}
void ViewportUiManager::SetClusterButtonTooltip(const ClusterId clusterId, const ButtonId buttonId, const AZStd::string& tooltip)
{
if (auto clusterIt = m_clusterButtonGroups.find(clusterId); clusterIt != m_clusterButtonGroups.end())
{
auto cluster = clusterIt->second;
m_viewportUi->SetClusterButtonTooltip(cluster->GetViewportUiElementId(), buttonId, tooltip);
UpdateButtonGroupUi(cluster.get());
}
}
void ViewportUiManager::RegisterClusterEventHandler(const ClusterId clusterId, AZ::Event<ButtonId>::Handler& handler)
{
if (auto clusterIt = m_clusterButtonGroups.find(clusterId); clusterIt != m_clusterButtonGroups.end())
@@ -36,6 +36,7 @@ namespace AzToolsFramework::ViewportUi
void SetClusterActiveButton(ClusterId clusterId, ButtonId buttonId) override;
void SetSwitcherActiveButton(SwitcherId switcherId, ButtonId buttonId) override;
void SetClusterButtonLocked(ClusterId clusterId, ButtonId buttonId, bool isLocked) override;
void SetClusterButtonTooltip(ClusterId clusterId, ButtonId buttonId, const AZStd::string& tooltip) override;
const ButtonId CreateClusterButton(ClusterId clusterId, const AZStd::string& icon) override;
const ButtonId CreateSwitcherButton(
SwitcherId switcherId, const AZStd::string& icon, const AZStd::string& name = AZStd::string()) override;
@@ -67,6 +67,8 @@ namespace AzToolsFramework::ViewportUi
virtual void SetSwitcherActiveButton(SwitcherId clusterId, ButtonId buttonId) = 0;
//! Adds a locked overlay to the cluster button's icon.
virtual void SetClusterButtonLocked(ClusterId clusterId, ButtonId buttonId, bool isLocked) = 0;
//! Updates/sets the cluster button's tooltip to the passed string.
virtual void SetClusterButtonTooltip(ClusterId clusterId, ButtonId buttonId, const AZStd::string& tooltip) = 0;
//! Registers a new button onto a cluster.
virtual const ButtonId CreateClusterButton(const ClusterId clusterId, const AZStd::string& icon) = 0;
//! Registers a new button onto a switcher.
@@ -93,7 +93,7 @@ namespace UnitTest
// Retrieve the entity pointer from the component application bus.
AZ::Entity* wheelEntityUnderAxle = nullptr;
axleInstance->GetNestedEntities([&wheelEntityUnderAxle, wheelEntityIdUnderAxle](AZStd::unique_ptr<AZ::Entity>& entity)
axleInstance->GetAllEntitiesInHierarchy([&wheelEntityUnderAxle, wheelEntityIdUnderAxle](AZStd::unique_ptr<AZ::Entity>& entity)
{
if (entity->GetId() == wheelEntityIdUnderAxle)
{
@@ -71,24 +71,29 @@ namespace UnitTest
m_prefabSystemComponent->CreatePrefab({ entitiesCreated[0] }, {}, "test/path1"));
ASSERT_TRUE(firstInstance);
ASSERT_TRUE(firstInstance->HasContainerEntity());
expectedEntityNameSet.insert(firstInstance->GetContainerEntity()->get().GetName());
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> secondInstance(
m_prefabSystemComponent->CreatePrefab({ entitiesCreated[1] }, MakeInstanceList(AZStd::move(firstInstance)), "test/path2"));
ASSERT_TRUE(secondInstance);
ASSERT_TRUE(secondInstance->HasContainerEntity());
expectedEntityNameSet.insert(secondInstance->GetContainerEntity()->get().GetName());
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> thirdInstance(
m_prefabSystemComponent->CreatePrefab({ entitiesCreated[2] }, MakeInstanceList(AZStd::move(secondInstance)), "test/path3"));
ASSERT_TRUE(thirdInstance);
ASSERT_TRUE(thirdInstance->HasContainerEntity());
auto& containerEntity = thirdInstance->GetContainerEntity()->get();
expectedEntityNameSet.insert(containerEntity.GetName());
expectedEntityNameSet.insert(thirdInstance->GetContainerEntity()->get().GetName());
//Create Spawnable
auto& prefabDom = m_prefabSystemComponent->FindTemplateDom(thirdInstance->GetTemplateId());
AzFramework::Spawnable spawnable;
AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(spawnable, prefabDom);
EXPECT_EQ(spawnable.GetEntities().size() - 1, normalEntityCount); // 1 for container entity
EXPECT_EQ(spawnable.GetEntities().size(), normalEntityCount + 3); // +1 for each container entity
const auto& spawnableEntities = spawnable.GetEntities();
AZStd::unordered_set<AZStd::string> actualEntityNameSet;
@@ -97,6 +102,6 @@ namespace UnitTest
actualEntityNameSet.insert(spawnableEntity->GetName());
}
EXPECT_EQ(expectedEntityNameSet, actualEntityNameSet);
EXPECT_EQ(actualEntityNameSet, expectedEntityNameSet);
}
}
@@ -213,7 +213,7 @@ namespace UnitTest
AZStd::unique_ptr<Instance> convertedInstance(aznew Instance());
ASSERT_TRUE(AzToolsFramework::Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(*convertedInstance, m_prefabDom));
convertedInstance->DetachNestedEntities(
convertedInstance->DetachAllEntitiesInHierarchy(
[this](AZStd::unique_ptr<AZ::Entity> entity)
{
m_runtimeEntities.emplace_back(entity.release());