Files
o3de/Gems/LyShine/Code/Editor/HierarchyHelpers.cpp
T
Esteban Papp 1f9b284de2 Merge branch 'development' into cmake/SPEC-7179
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>

# Conflicts:
#	Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h
#	Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h
#	Code/Editor/Plugins/EditorCommon/stdafx.cpp
#	Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h
#	Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h
#	Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h
#	Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h
#	Code/Tools/AssetProcessor/native/precompiled.h
#	Code/Tools/Standalone/StandaloneTools_precompiled.h
#	Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h
#	Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h
#	Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h
#	Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake
#	Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h
#	Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h
#	Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
#	Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake
#	Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h
#	Gems/Blast/Code/Source/StdAfx.cpp
#	Gems/Camera/Code/Source/Camera_precompiled.h
#	Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h
#	Gems/FastNoise/Code/Source/FastNoise_precompiled.h
#	Gems/Gestures/Code/Source/Gestures_precompiled.h
#	Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h
#	Gems/GraphCanvas/Code/precompiled.h
#	Gems/ImGui/Code/Source/ImGui_precompiled.h
#	Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h
#	Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h
#	Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp
#	Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h
#	Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h
#	Gems/LyShine/Code/Source/LyShine_precompiled.h
#	Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h
#	Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h
#	Gems/Maestro/Code/Source/Maestro_precompiled.h
#	Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h
#	Gems/Metastream/Code/Source/Metastream_precompiled.h
#	Gems/Microphone/Code/Source/Microphone_precompiled.h
#	Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h
#	Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h
#	Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h
#	Gems/PhysX/Code/Source/PhysX_precompiled.h
#	Gems/PhysX/Code/physx_unsupported_files.cmake
#	Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h
#	Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h
#	Gems/ScriptCanvas/Code/Editor/precompiled.h
#	Gems/ScriptCanvas/Code/Source/precompiled.h
#	Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h
#	Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h
#	Gems/ScriptEvents/Code/Source/precompiled.h
#	Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp
#	Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h
#	Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h
#	Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h
#	Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h
#	Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h
#	Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h
#	Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h
#	Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h
#	Gems/Twitch/Code/Source/Twitch_precompiled.h
#	Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
2021-07-16 15:42:37 -07:00

302 lines
11 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "EditorCommon.h"
#include <QMessageBox>
//-------------------------------------------------------------------------------
namespace
{
void CreateItems(HierarchyWidget* widget,
LyShine::EntityArray& completeListOfNewlyCreatedTopLevelElements)
{
// Create items for all new elements.
widget->CreateItems(completeListOfNewlyCreatedTopLevelElements);
// IMPORTANT: The CTRL key is down when we paste items.
// This has the side effect of ADDING to the selection,
// instead of replacing it. The solution is to explicitely
// UNSELECT the previously selected items BEFORE selecting
// the newly created items.
widget->clearSelection();
// Expand and select.
{
HierarchyHelpers::ExpandParents(widget, completeListOfNewlyCreatedTopLevelElements);
HierarchyHelpers::SetSelectedItems(widget, &completeListOfNewlyCreatedTopLevelElements);
}
}
} // anonymous namespace.
//-------------------------------------------------------------------------------
namespace HierarchyHelpers
{
//-------------------------------------------------------------------------------
void Delete(HierarchyWidget* hierarchy,
SerializeHelpers::SerializedEntryList& entries)
{
hierarchy->SetIsDeleting(true);
{
for (auto& e : entries)
{
// IMPORTANT: It's SAFE to delete a HierarchyItem. Its
// destructor will take care of removing the item from
// the parent container, AND deleting all child items.
// There's no risk of leaking memory. We just have to
// make sure we don't have any dangling pointers.
delete HierarchyHelpers::ElementToItem(hierarchy, e.m_id, false);
}
}
hierarchy->SetIsDeleting(false);
hierarchy->SignalUserSelectionHasChanged(hierarchy->selectedItems());
hierarchy->GetEditorWindow()->EntitiesAddedOrRemoved();
}
bool HandleDeselect(QTreeWidgetItem* widgetItem, const bool controlKeyPressed)
{
if (widgetItem && widgetItem->isSelected())
{
// Ctrl+clicking a selected element should de-select it
if (controlKeyPressed)
{
widgetItem->setSelected(false);
return true;
}
}
return false;
}
//-------------------------------------------------------------------------------
QAction* CreateAddElementAction(HierarchyWidget* hierarchy,
const QTreeWidgetItemRawPtrQList& selectedItems,
bool addAtRoot,
const QPoint* optionalPos)
{
QAction* action = new QAction(QIcon(":/Icons/Eye_Open.png"),
QString("&Empty element%1").arg(!addAtRoot && selectedItems.size() > 1 ? "s" : ""),
hierarchy);
QObject::connect(action,
&QAction::triggered,
hierarchy,
[hierarchy, addAtRoot, optionalPos]([[maybe_unused]] bool checked)
{
if (addAtRoot)
{
hierarchy->clearSelection();
}
hierarchy->AddElement(hierarchy->selectedItems(), optionalPos);
});
return action;
}
//-------------------------------------------------------------------------------
void CreateItemsAndElements(HierarchyWidget* widget,
const SerializeHelpers::SerializedEntryList& entryList)
{
LyShine::EntityArray completeListOfNewlyCreatedTopLevelElements;
// Create elements
{
// Because the entries use m_insertAboveThisId to correctly insert elements
// in the right place and two siblings can be in the list of entries, the later
// sibling has to be inserted first so that the earlier one can find the element
// it should be before. We know that the SerializedEntryList is created in the order
// that elements are in the element hierarchy. So we iterate in reverse order over the
// SerializedEntryList while inserting the elements.
for (auto iter = entryList.rbegin(); iter != entryList.rend(); ++iter)
{
auto& e = *iter;
SerializeHelpers::RestoreSerializedElements(widget->GetEditorWindow()->GetCanvas(),
EntityHelpers::GetEntity(e.m_parentId),
EntityHelpers::GetEntity(e.m_insertAboveThisId),
widget->GetEditorWindow()->GetEntityContext(),
e.m_undoXml.c_str(),
false,
&completeListOfNewlyCreatedTopLevelElements);
}
}
// because we iterated backward above the completeListOfNewlyCreatedTopLevelElements is now
// in the reverse order of what the items should be in the HierarchyWidget. CreateItems
// relies on them being in the correct order so we reverse the list.
std::reverse(completeListOfNewlyCreatedTopLevelElements.begin(), completeListOfNewlyCreatedTopLevelElements.end());
// Now create the items in the QTreeWidget
CreateItems(widget, completeListOfNewlyCreatedTopLevelElements);
widget->GetEditorWindow()->EntitiesAddedOrRemoved();
}
//-------------------------------------------------------------------------------
LyShine::EntityArray CreateItemsAndElements(HierarchyWidget* widget,
const QTreeWidgetItemRawPtrQList& selectedItems,
bool createAsChildOfSelection,
Creator creator)
{
LyShine::EntityArray completeListOfNewlyCreatedTopLevelElements;
// Create elements
{
HierarchyItem* parent = nullptr;
{
HierarchyItem* selectedItem = nullptr;
{
HierarchyItemRawPtrList items;
SelectionHelpers::GetListOfTopLevelSelectedItems(widget,
selectedItems,
widget->invisibleRootItem(),
items);
selectedItem = (items.empty() ? nullptr : items.front());
}
// It's ok for parent to be nullptr.
if (createAsChildOfSelection)
{
// Create as a child of the selectedItem.
parent = selectedItem;
}
else
{
// Create as a sibling of the selectedItem.
parent = selectedItem ? selectedItem->Parent() : nullptr;
}
}
// Create.
{
LyShine::EntityArray listOfNewlyCreatedTopLevelElements;
creator(parent, listOfNewlyCreatedTopLevelElements);
if (listOfNewlyCreatedTopLevelElements.empty())
{
// This happens when the serialization version numbers DON'T match.
QMessageBox(QMessageBox::Critical,
"Error",
QString("Failed to load elements. The serialization format is incompatible."),
QMessageBox::Ok, widget->GetEditorWindow()).exec();
// Nothing more to do.
return LyShine::EntityArray();
}
completeListOfNewlyCreatedTopLevelElements.push_back(listOfNewlyCreatedTopLevelElements);
}
}
// Create the items to go along the elements created above.
CreateItems(widget, completeListOfNewlyCreatedTopLevelElements);
widget->GetEditorWindow()->EntitiesAddedOrRemoved();
return completeListOfNewlyCreatedTopLevelElements;
}
//-------------------------------------------------------------------------------
QTreeWidgetItem* ElementToItem(HierarchyWidget* widget, const AZ::Entity* element, bool defaultToInvisibleRootItem)
{
if (!element)
{
return (defaultToInvisibleRootItem ? widget->invisibleRootItem() : nullptr);
}
return ElementToItem(widget, element->GetId(), defaultToInvisibleRootItem);
}
QTreeWidgetItem* ElementToItem(HierarchyWidget* widget, AZ::EntityId elementId, bool defaultToInvisibleRootItem)
{
if (!elementId.IsValid())
{
return (defaultToInvisibleRootItem ? widget->invisibleRootItem() : nullptr);
}
auto i = widget->GetEntityItemMap().find(elementId);
if (i == widget->GetEntityItemMap().end())
{
// Not found.
return (defaultToInvisibleRootItem ? widget->invisibleRootItem() : nullptr);
}
else
{
// Found.
return i->second;
}
}
//-------------------------------------------------------------------------------
QTreeWidgetItem* _GetItem([[maybe_unused]] HierarchyWidget* widget,
QTreeWidgetItem* i)
{
return i;
}
QTreeWidgetItem* _GetItem([[maybe_unused]] HierarchyWidget* widget,
HierarchyItem* i)
{
return i;
}
QTreeWidgetItem* _GetItem(HierarchyWidget* widget,
SerializeHelpers::SerializedEntry& e)
{
return HierarchyHelpers::ElementToItem(widget, e.m_id, false);
}
QTreeWidgetItem* _GetItem(HierarchyWidget* widget,
AZ::Entity* e)
{
return HierarchyHelpers::ElementToItem(widget, e, false);
}
QTreeWidgetItem* _GetItem(HierarchyWidget* widget,
AZ::EntityId e)
{
return HierarchyHelpers::ElementToItem(widget, e, false);
}
//-------------------------------------------------------------------------------
void SetSelectedItem(HierarchyWidget* widget,
AZ::Entity* element)
{
LyShine::EntityArray elementUnderCursor;
if (element)
{
elementUnderCursor.push_back(element);
}
SetSelectedItems(widget, &elementUnderCursor);
}
bool CompareOrderInElementHierarchy(HierarchyItem* item1, HierarchyItem* item2)
{
AZ::Entity* entity1 = item1->GetElement();
AZ::Entity* entity2 = item2->GetElement();
return EntityHelpers::CompareOrderInElementHierarchy(entity1, entity2);
}
void SortByHierarchyOrder(HierarchyItemRawPtrList &itemList)
{
itemList.sort(CompareOrderInElementHierarchy);
}
//-------------------------------------------------------------------------------
} // namespace HierarchyHelpers