Merge branch 'development' into cmake/SPEC-2513_w4267

This commit is contained in:
Esteban Papp
2021-08-02 18:03:04 -07:00
493 changed files with 7775 additions and 12867 deletions
@@ -177,7 +177,7 @@ namespace AzToolsFramework
PrefabDomUtils::ApplyPatches(templateDomReference, templateDomReference.GetAllocator(), providedPatch);
//trigger propagation
if (result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::Success)
if (result.GetProcessing() != AZ::JsonSerializationResult::Processing::Completed)
{
AZ_Error("Prefab", false, "Patch was not successfully applied.");
return false;
@@ -90,10 +90,11 @@ namespace AzToolsFramework
AZStd::unordered_map<Instance*, PrefabDom> nestedInstanceLinkPatchesMap;
// Retrieve all entities affected and identify Instances
if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances))
PrefabOperationResult retrieveEntitiesAndInstancesOutcome = RetrieveAndSortPrefabEntitiesAndInstances(
inputEntityList, commonRootEntityOwningInstance->get(), entities, instances);
if (!retrieveEntitiesAndInstancesOutcome.IsSuccess())
{
return AZ::Failure(
AZStd::string("Could not create a new prefab out of the entities provided - invalid selection."));
return retrieveEntitiesAndInstancesOutcome;
}
AZStd::unordered_map<AZ::EntityId, AZStd::string> oldEntityAliases;
@@ -646,7 +647,12 @@ namespace AzToolsFramework
{
// Retrieve all nested instances that are part of the subtree under the current entity.
EntityList entities;
RetrieveAndSortPrefabEntitiesAndInstances({ entity }, beforeOwningInstance->get(), entities, instancesInvolved);
PrefabOperationResult retrieveEntitiesAndInstancesOutcome = RetrieveAndSortPrefabEntitiesAndInstances(
{ entity }, beforeOwningInstance->get(), entities, instancesInvolved);
if (!retrieveEntitiesAndInstancesOutcome.IsSuccess())
{
return retrieveEntitiesAndInstancesOutcome;
}
}
for (Instance* instance : instancesInvolved)
@@ -748,7 +754,9 @@ namespace AzToolsFramework
AZStd::vector<Instance*> instances;
// Retrieve all descendant entities and instances of this entity that belonged to the same owning instance.
RetrieveAndSortPrefabEntitiesAndInstances({ entity }, beforeOwningInstance->get(), entities, instances);
PrefabOperationResult retrieveEntitiesAndInstancesOutcome = RetrieveAndSortPrefabEntitiesAndInstances(
{ entity }, beforeOwningInstance->get(), entities, instances);
AZ_Error("Prefab", retrieveEntitiesAndInstancesOutcome.IsSuccess(), retrieveEntitiesAndInstancesOutcome.GetError().data());
AZStd::vector<AZStd::unique_ptr<Instance>> instanceUniquePtrs;
AZStd::vector<AZStd::pair<Instance*, PrefabDom>> instancePatches;
@@ -981,11 +989,12 @@ namespace AzToolsFramework
AZStd::vector<Instance*> instances;
EntityList inputEntityList = EntityIdSetToEntityList(duplicationSet);
bool success = RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances);
PrefabOperationResult retrieveEntitiesAndInstancesOutcome =
RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances);
if (!success)
if (!retrieveEntitiesAndInstancesOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string("Failed to retrieve entities and instances from the given list of entity ids for duplication"));
return AZStd::move(retrieveEntitiesAndInstancesOutcome);
}
// Take a snapshot of the instance DOM before we manipulate it
@@ -1128,11 +1137,12 @@ namespace AzToolsFramework
AZStd::vector<AZ::Entity*> entities;
AZStd::vector<Instance*> instances;
bool success = RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances);
PrefabOperationResult retrieveEntitiesAndInstancesOutcome =
RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances);
if (!success)
if (!retrieveEntitiesAndInstancesOutcome.IsSuccess())
{
return AZ::Failure(AZStd::string("DeleteEntitiesAndAllDescendantsInInstance"));
return AZStd::move(retrieveEntitiesAndInstancesOutcome);
}
for (AZ::Entity* entity : entities)
@@ -1405,13 +1415,16 @@ namespace AzToolsFramework
return nullptr;
}
bool PrefabPublicHandler::RetrieveAndSortPrefabEntitiesAndInstances(
const EntityList& inputEntities, Instance& commonRootEntityOwningInstance,
EntityList& outEntities, AZStd::vector<Instance*>& outInstances) const
PrefabOperationResult PrefabPublicHandler::RetrieveAndSortPrefabEntitiesAndInstances(
const EntityList& inputEntities,
Instance& commonRootEntityOwningInstance,
EntityList& outEntities,
AZStd::vector<Instance*>& outInstances) const
{
if (inputEntities.size() == 0)
{
return false;
return AZ::Failure(
AZStd::string("An empty list of input entities is provided to retrieve the prefab entities and instances."));
}
AZStd::queue<AZ::Entity*> entityQueue;
@@ -1438,8 +1451,8 @@ namespace AzToolsFramework
AZ_Assert(
owningInstance.has_value(),
"An error occurred while retrieving entities and prefab instances : "
"Owning instance of entity with id '%llu' couldn't be found",
entity->GetId());
"Owning instance of entity with name '%s' and id '%llu' couldn't be found",
entity->GetName().c_str(), static_cast<AZ::u64>(entity->GetId()));
// Check if this entity is owned by the same instance owning the root.
if (&owningInstance->get() == &commonRootEntityOwningInstance)
@@ -1480,7 +1493,10 @@ namespace AzToolsFramework
else
{
// This can only happen if one entity does not share the common root!
return false;
return AZ::Failure(AZStd::string::format(
"Entity with name '%s' and id '%llu' has an owning instance that doesn't belong to the instance "
"hierarchy of the selected entities.",
entity->GetName().c_str(), static_cast<AZ::u64>(entity->GetId())));
}
}
}
@@ -1501,7 +1517,12 @@ namespace AzToolsFramework
outInstances.push_back(instancePtr);
}
return (outEntities.size() + outInstances.size()) > 0;
if ((outEntities.size() + outInstances.size()) == 0)
{
return AZ::Failure(
AZStd::string("An empty list of entities and prefab instances were retrieved from the selected entities"));
}
return AZ::Success();
}
EntityIdList PrefabPublicHandler::GenerateEntityIdListWithoutLevelInstance(
@@ -64,8 +64,11 @@ namespace AzToolsFramework
private:
PrefabOperationResult DeleteFromInstance(const EntityIdList& entityIds, bool deleteDescendants);
bool RetrieveAndSortPrefabEntitiesAndInstances(const EntityList& inputEntities, Instance& commonRootEntityOwningInstance,
EntityList& outEntities, AZStd::vector<Instance*>& outInstances) const;
PrefabOperationResult 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;
@@ -546,7 +546,7 @@ namespace AzToolsFramework
for (auto& element : nodeEditData->m_elements)
{
if (element.IsClassElement() && element.m_elementId == AZ::Edit::ClassElements::Group)
if (element.m_elementId == AZ::Edit::ClassElements::Group)
{
groupData = (element.m_description && element.m_description[0]) ? &element : nullptr;
continue;
@@ -1112,13 +1112,14 @@ namespace AzToolsFramework
const AZ::Edit::ElementData* groupData = nullptr;
for (const AZ::Edit::ElementData& elementData : parentEditData->m_elements)
{
if (node->m_elementEditData == &elementData) // this element matches this node
// this element matches this node
if ((node->m_elementEditData == &elementData) && (elementData.m_elementId != AZ::Edit::ClassElements::Group))
{
// Record the last found group data
node->m_groupElementData = groupData;
break;
}
else if (elementData.IsClassElement() && elementData.m_elementId == AZ::Edit::ClassElements::Group)
else if (elementData.m_elementId == AZ::Edit::ClassElements::Group)
{
if (!elementData.m_description || !elementData.m_description[0])
{ // close the group
@@ -12,6 +12,7 @@
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyCheckBoxCtrl.hxx>
AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") // 4244: conversion from 'int' to 'float', possible loss of data
// 4251: class '...' needs to have dll-interface to be used by clients of class 'QInputEvent'
@@ -141,6 +142,11 @@ namespace AzToolsFramework
m_treeDepth = 0;
delete m_dropDownArrow;
if (m_toggleSwitch != nullptr)
{
m_handler->DestroyGUI(m_toggleSwitch);
m_toggleSwitch = nullptr;
}
if (m_childWidget)
{
@@ -387,6 +393,13 @@ namespace AzToolsFramework
setUpdatesEnabled(true);
}
void PropertyRowWidget::InitializeToggleGroup(const char* groupName, PropertyRowWidget* pParent, int depth, InstanceDataNode* node, int labelWidth)
{
Initialize(groupName, pParent, depth, labelWidth);
ChangeSourceNode(node);
CreateGroupToggleSwitch();
}
void PropertyRowWidget::Initialize(const char* groupName, PropertyRowWidget* pParent, int depth, int labelWidth)
{
Initialize(pParent, nullptr, depth, labelWidth);
@@ -1102,6 +1115,19 @@ namespace AzToolsFramework
}
}
void PropertyRowWidget::CreateGroupToggleSwitch()
{
if (m_toggleSwitch == nullptr)
{
m_handlerName = AZ::Edit::UIHandlers::CheckBox;
PropertyTypeRegistrationMessages::Bus::BroadcastResult(m_handler, &PropertyTypeRegistrationMessages::Bus::Events::ResolvePropertyHandler, m_handlerName, azrtti_typeid<bool>());
m_toggleSwitch = m_handler->CreateGUI(this);
m_middleLayout->insertWidget(0, m_toggleSwitch, 1);
auto checkBoxCtrl = static_cast<AzToolsFramework::PropertyCheckBoxCtrl*>(m_toggleSwitch);
QObject::connect(checkBoxCtrl, &AzToolsFramework::PropertyCheckBoxCtrl::valueChanged, this, &PropertyRowWidget::OnClickedToggleButton);
}
}
void PropertyRowWidget::SetIndentSize(int w)
{
m_indent->changeSize(w, 1, QSizePolicy::Fixed, QSizePolicy::Fixed);
@@ -1110,6 +1136,18 @@ namespace AzToolsFramework
m_leftHandSideLayout->activate();
}
void PropertyRowWidget::OnClickedToggleButton(bool checked)
{
if (m_expanded != checked)
{
DoExpandOrContract(!IsExpanded(), 0 != (QGuiApplication::keyboardModifiers() & Qt::ControlModifier));
}
}
void PropertyRowWidget::ChangeSourceNode(InstanceDataNode* node)
{
m_sourceNode = node;
}
void PropertyRowWidget::SetExpanded(bool expanded)
{
@@ -50,6 +50,7 @@ namespace AzToolsFramework
virtual void Initialize(PropertyRowWidget* pParent, InstanceDataNode* dataNode, int depth, int labelWidth = 200);
virtual void Initialize(const char* groupName, PropertyRowWidget* pParent, int depth, int labelWidth = 200);
virtual void InitializeToggleGroup(const char* groupName, PropertyRowWidget* pParent, int depth, InstanceDataNode* node, int labelWidth = 200);
virtual void Clear(); // for pooling
// --- NOT A UNIQUE IDENTIFIER ---
@@ -143,11 +144,14 @@ namespace AzToolsFramework
QVBoxLayout* GetLeftHandSideLayoutParent() { return m_leftHandSideLayoutParent; }
QToolButton* GetIndicatorButton() { return m_indicatorButton; }
QLabel* GetNameLabel() { return m_nameLabel; }
QWidget* GetToggle() { return m_toggleSwitch; }
const QWidget* GetToggle() const { return m_toggleSwitch; }
void SetIndentSize(int w);
void SetAsCustom(bool custom) { m_custom = custom; }
bool CanChildrenBeReordered() const;
bool CanBeReordered() const;
protected:
int CalculateLabelWidth() const;
@@ -177,6 +181,8 @@ namespace AzToolsFramework
QLabel* m_defaultLabel; // if there is no handler, we use a m_defaultLabel label
InstanceDataNode* m_sourceNode;
QWidget* m_toggleSwitch = nullptr;
QString m_currentFilterString;
struct ChangeNotification
@@ -241,6 +247,8 @@ namespace AzToolsFramework
void mouseDoubleClickEvent(QMouseEvent* event) override;
void UpdateDropDownArrow();
void CreateGroupToggleSwitch();
void ChangeSourceNode(InstanceDataNode* node);
void UpdateDefaultLabel(InstanceDataNode* node);
void createContainerButtons();
@@ -259,6 +267,7 @@ namespace AzToolsFramework
private slots:
void OnClickedExpansionButton();
void OnClickedToggleButton(bool checked);
void OnClickedAddElementButton();
void OnClickedRemoveElementButton();
void OnClickedClearContainerButton();
@@ -169,6 +169,8 @@ namespace AzToolsFramework
InstanceDataHierarchyList m_instances; ///< List of instance sets to display, other one can aggregate other instances.
InstanceDataHierarchy::ValueComparisonFunction m_valueComparisonFunction;
ReflectedPropertyEditor::WidgetList m_widgets;
ReflectedPropertyEditor::WidgetList m_specialGroupWidgets;
InstanceDataNode* groupSourceNode = nullptr;
RowContainerType m_widgetsInDisplayOrder;
UserWidgetToDataMap m_userWidgetsToData;
VisibilityCallback m_visibilityCallback;
@@ -501,6 +503,7 @@ namespace AzToolsFramework
// if the node is in a group then create the widget for the group
if (groupElementData)
{
bool isToggleGroup = false;
const char* groupName = groupElementData->m_description;
PropertyRowWidget*& widgetEntry = m_groupWidgets[{parent, groupName}];
@@ -509,14 +512,34 @@ namespace AzToolsFramework
{
widgetEntry = CreateOrPullFromPool();
widgetEntry->SetFilterString(m_editor->GetFilterString());
widgetEntry->Initialize(groupName, parent, depth, m_propertyLabelWidth);
// Initialized normally if the group does not have a member variable attached to it,
// otherwise initialize it as a group that will have a toggle switch.
if (groupElementData->IsClassElement())
{
widgetEntry->Initialize(groupName, parent, depth, m_propertyLabelWidth);
}
else
{
widgetEntry->InitializeToggleGroup(groupName, parent, depth, groupSourceNode, m_propertyLabelWidth);
QWidget* toggleSwitch = widgetEntry->GetToggle();
PropertyHandlerBase* pHandler = widgetEntry->GetHandler();
m_userWidgetsToData[toggleSwitch] = groupSourceNode;
m_specialGroupWidgets[groupSourceNode] = widgetEntry;
pHandler->ConsumeAttributes_Internal(toggleSwitch, groupSourceNode);
pHandler->ReadValuesIntoGUI_Internal(toggleSwitch, groupSourceNode);
widgetEntry->OnValuesUpdated();
isToggleGroup = true;
}
widgetEntry->SetLeafIndentation(m_leafIndentation);
widgetEntry->SetTreeIndentation(m_treeIndentation);
widgetEntry->setObjectName(groupName);
for (const AZ::Edit::AttributePair& attribute : groupElementData->m_attributes)
{
PropertyAttributeReader reader(node->GetParent()->FirstInstance(), attribute.second);
InstanceDataNode* readerNode = (isToggleGroup) ? groupSourceNode : node;
PropertyAttributeReader reader(readerNode->GetParent()->FirstInstance(), attribute.second);
QString descriptionOut;
bool foundDescription = false;
widgetEntry->ConsumeAttribute(attribute.first, reader, true, &descriptionOut, &foundDescription);
@@ -608,7 +631,7 @@ namespace AzToolsFramework
// creates and populates the GUI to edit the property if not already created
void ReflectedPropertyEditor::Impl::CreateEditorWidget(PropertyRowWidget* pWidget)
{
if (!pWidget->HasChildWidgetAlready())
if (!pWidget->HasChildWidgetAlready() && !pWidget->GetToggle())
{
PropertyHandlerBase* pHandler = pWidget->GetHandler();
if (pHandler)
@@ -735,36 +758,44 @@ namespace AzToolsFramework
}
}
}
pWidget = CreateOrPullFromPool();
pWidget->show();
pWidget->SetFilterString(m_editor->GetFilterString());
pWidget->Initialize(pParent, node, depth, m_propertyLabelWidth);
if (labelOverride != "")
if (!node->GetElementEditMetadata() || (node->GetElementEditMetadata()->m_elementId != AZ::Edit::ClassElements::Group))
{
pWidget->SetNameLabel(labelOverride.data());
pWidget = CreateOrPullFromPool();
pWidget->show();
pWidget->SetFilterString(m_editor->GetFilterString());
pWidget->Initialize(pParent, node, depth, m_propertyLabelWidth);
if (labelOverride != "")
{
pWidget->SetNameLabel(labelOverride.data());
}
pWidget->setObjectName(pWidget->label());
pWidget->SetSelectionEnabled(m_selectionEnabled);
pWidget->SetLeafIndentation(m_leafIndentation);
pWidget->SetTreeIndentation(m_treeIndentation);
m_widgets[node] = pWidget;
m_widgetsInDisplayOrder.insert(widgetDisplayOrder, pWidget);
if (pParent)
{
pParent->AddedChild(pWidget);
}
if (pParent || !m_hideRootProperties)
{
depth += 1;
}
pParent = pWidget;
}
pWidget->setObjectName(pWidget->label());
pWidget->SetSelectionEnabled(m_selectionEnabled);
pWidget->SetLeafIndentation(m_leafIndentation);
pWidget->SetTreeIndentation(m_treeIndentation);
m_widgets[node] = pWidget;
m_widgetsInDisplayOrder.insert(widgetDisplayOrder, pWidget);
if (pParent)
// Save the last InstanceDataNode that is a Group ClassElement so that we can use it as the source node for its widget.
if (node->GetElementEditMetadata() && (node->GetElementEditMetadata()->m_elementId == AZ::Edit::ClassElements::Group))
{
pParent->AddedChild(pWidget);
groupSourceNode = node;
}
if (pParent || !m_hideRootProperties)
{
depth += 1;
}
pParent = pWidget;
}
}
@@ -1356,9 +1387,13 @@ namespace AzToolsFramework
return;
}
// get the property editor
// Get the property editor from either the widget map or the special toggle group widgets
auto rowWidget = m_widgets.find(it->second);
if (rowWidget != m_widgets.end())
if (rowWidget == m_widgets.end())
{
rowWidget = m_specialGroupWidgets.find(it->second);
}
if (rowWidget != m_widgets.end() || rowWidget != m_specialGroupWidgets.end())
{
InstanceDataNode* node = rowWidget->first;
PropertyRowWidget* widget = rowWidget->second;
@@ -51,6 +51,8 @@ namespace AzToolsFramework
typedef AZStd::unordered_map<InstanceDataNode*, PropertyRowWidget*> WidgetList;
ReflectedPropertyEditor::WidgetList m_specialGroupWidgets;
ReflectedPropertyEditor(QWidget* pParent);
virtual ~ReflectedPropertyEditor();
@@ -62,6 +64,7 @@ namespace AzToolsFramework
bool AddInstance(void* instance, const AZ::Uuid& classId, void* aggregateInstance = nullptr, void* compareInstance = nullptr);
void SetCompareInstance(void* instance, const AZ::Uuid& classId);
void ClearInstances();
void ReadValuesIntoGui(QWidget* widget, InstanceDataNode* node);
template<class T>
bool AddInstance(T* instance, void* aggregateInstance = nullptr, void* compareInstance = nullptr)
{