From 31fb5322edb575024ddb2bf834f60123d6668773 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:32:22 -0800 Subject: [PATCH] Refactor the Outliner drag&drop and selection to fix UX and technical issues. (#7559) * Prototype - refactor the selection system for the Outliner (WIP) Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * WIP - unify custom drag, still trying to find a way to make it so that the selection isn't affected by drag/drop of unselected entity Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Wrap up changes Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Minor refactor - move from enum to bool Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Prevent clicks on the spacing column from selecting the entity; better refresh the hover state. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Fix weird flicker introduced by latest commit Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Change color for the drag select rectangle. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Add more thorough comments, and also make some helper variables const. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Fixed incorrect variable types (Qt uses ints for on-screen dimensions) Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../UI/Outliner/EntityOutlinerListModel.cpp | 8 +- .../UI/Outliner/EntityOutlinerListModel.hxx | 1 + .../UI/Outliner/EntityOutlinerTreeView.cpp | 336 +++++++++++------- .../UI/Outliner/EntityOutlinerTreeView.hxx | 19 +- .../UI/Outliner/EntityOutlinerWidget.cpp | 4 +- 5 files changed, 240 insertions(+), 128 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp index 45363f4bb5..ac7d832c66 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp @@ -2091,8 +2091,14 @@ namespace AzToolsFramework customOption.state ^= QStyle::State_HasFocus; } + // Don't allow to paint on the spacing column + if (index.column() == EntityOutlinerListModel::ColumnSpacing) + { + return; + } + // Retrieve the Entity UI Handler - auto firstColumnIndex = index.siblingAtColumn(0); + auto firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName); AZ::EntityId entityId(firstColumnIndex.data(EntityOutlinerListModel::EntityIdRole).value()); auto entityUiHandler = m_editorEntityFrameworkInterface->GetHandler(entityId); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx index 51d047e81a..5c93d11c37 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx @@ -69,6 +69,7 @@ namespace AzToolsFramework ColumnName, //!< Entity name ColumnVisibilityToggle, //!< Visibility Icons ColumnLockToggle, //!< Lock Icons + ColumnSpacing, //!< Spacing to allow for drag select ColumnSortIndex, //!< Index of sort order ColumnCount //!< Total number of columns }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp index c2bbebb72e..8f0d541017 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp @@ -30,7 +30,6 @@ namespace AzToolsFramework EntityOutlinerTreeView::EntityOutlinerTreeView(QWidget* pParent) : AzQtComponents::StyledTreeView(pParent) , m_queuedMouseEvent(nullptr) - , m_draggingUnselectedItem(false) { setUniformRowHeights(true); setHeaderHidden(true); @@ -65,22 +64,6 @@ namespace AzToolsFramework m_expandOnlyDelay = delay; } - void EntityOutlinerTreeView::ClearQueuedMouseEvent() - { - if (m_queuedMouseEvent) - { - delete m_queuedMouseEvent; - m_queuedMouseEvent = nullptr; - } - } - - void EntityOutlinerTreeView::leaveEvent([[maybe_unused]] QEvent* event) - { - m_mousePosition = QPoint(-1, -1); - m_currentHoveredIndex = QModelIndex(); - update(); - } - void EntityOutlinerTreeView::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles) { AzQtComponents::StyledTreeView::dataChanged(topLeft, bottomRight, roles); @@ -93,7 +76,7 @@ namespace AzToolsFramework auto modelRow = topLeft.sibling(i, EntityOutlinerListModel::ColumnName); if (modelRow.isValid()) { - checkExpandedState(modelRow); + CheckExpandedState(modelRow); } } } @@ -108,15 +91,15 @@ namespace AzToolsFramework auto modelRow = model()->index(i, EntityOutlinerListModel::ColumnName, parent); if (modelRow.isValid()) { - checkExpandedState(modelRow); - recursiveCheckExpandedStates(modelRow); + CheckExpandedState(modelRow); + RecursiveCheckExpandedStates(modelRow); } } } AzQtComponents::StyledTreeView::rowsInserted(parent, start, end); } - void EntityOutlinerTreeView::recursiveCheckExpandedStates(const QModelIndex& current) + void EntityOutlinerTreeView::RecursiveCheckExpandedStates(const QModelIndex& current) { const int rowCount = model()->rowCount(current); for (int i = 0; i < rowCount; i++) @@ -124,13 +107,13 @@ namespace AzToolsFramework auto modelRow = model()->index(i, EntityOutlinerListModel::ColumnName, current); if (modelRow.isValid()) { - checkExpandedState(modelRow); - recursiveCheckExpandedStates(modelRow); + CheckExpandedState(modelRow); + RecursiveCheckExpandedStates(modelRow); } } } - void EntityOutlinerTreeView::checkExpandedState(const QModelIndex& current) + void EntityOutlinerTreeView::CheckExpandedState(const QModelIndex& current) { const bool expandState = current.data(EntityOutlinerListModel::ExpandedRole).template value(); setExpanded(current, expandState); @@ -138,116 +121,102 @@ namespace AzToolsFramework void EntityOutlinerTreeView::mousePressEvent(QMouseEvent* event) { - //postponing normal mouse pressed logic until mouse is released or dragged - //this means selection occurs on mouse released now - //this is to support drag/drop of non-selected items + // Postponing normal mouse press logic until mouse is released or dragged. + // This allows drag/drop of non-selected items. ClearQueuedMouseEvent(); m_queuedMouseEvent = new QMouseEvent(*event); } + void EntityOutlinerTreeView::mouseMoveEvent(QMouseEvent* event) + { + // Prevent multiple updates throughout the function for changing UIs. + bool forceUpdate = false; + + QModelIndex previousHoveredIndex = m_currentHoveredIndex; + m_mousePosition = event->pos(); + + if (QModelIndex hoveredIndex = indexAt(m_mousePosition); + m_currentHoveredIndex != hoveredIndex) + { + m_currentHoveredIndex = hoveredIndex; + } + + if (m_queuedMouseEvent) + { + if (!m_isDragSelectActive) + { + // Determine whether the mouse move should trigger a rect selection or an entity drag. + QModelIndex clickedIndex = indexAt(m_queuedMouseEvent->pos()); + // Even though the drag started on an index, we want to trigger a drag select from the last column. + // This is to allow drag selection to be triggered from anywhere in the hierarchy. + if (clickedIndex.isValid() && clickedIndex.column() != EntityOutlinerListModel::ColumnSpacing) + { + HandleDrag(); + } + else + { + m_isDragSelectActive = true; + forceUpdate = true; + } + } + else + { + SelectAllEntitiesInSelectionRect(); + forceUpdate = true; + } + } + + if (previousHoveredIndex != m_currentHoveredIndex) + { + forceUpdate = true; + } + + if (forceUpdate) + { + update(); + } + } + void EntityOutlinerTreeView::mouseReleaseEvent(QMouseEvent* event) { - if (m_queuedMouseEvent && !m_draggingUnselectedItem) + if (m_isDragSelectActive) { - // mouseMoveEvent will set the state to be DraggingState, which will make Qt ignore - // mousePressEvent in QTreeViewPrivate::expandOrCollapseItemAtPos. So we manually - // and temporarily set it to EditingState. - QAbstractItemView::State stateBefore = QAbstractItemView::state(); - QAbstractItemView::setState(QAbstractItemView::State::EditingState); - - //treat this as a mouse pressed event to process selection etc - processQueuedMousePressedEvent(m_queuedMouseEvent); - - QAbstractItemView::setState(stateBefore); + SelectAllEntitiesInSelectionRect(); + update(); + } + else if (m_queuedMouseEvent) + { + ProcessQueuedMousePressedEvent(m_queuedMouseEvent); } ClearQueuedMouseEvent(); - m_draggingUnselectedItem = false; + m_isDragSelectActive = false; QTreeView::mouseReleaseEvent(event); } void EntityOutlinerTreeView::mouseDoubleClickEvent(QMouseEvent* event) { - //cancel pending mouse press + // Cancel pending mouse press. ClearQueuedMouseEvent(); QTreeView::mouseDoubleClickEvent(event); } - void EntityOutlinerTreeView::mouseMoveEvent(QMouseEvent* event) - { - if (m_queuedMouseEvent) - { - //disable selection for the pending click if the mouse moved so selection is maintained for dragging - QAbstractItemView::SelectionMode selectionModeBefore = selectionMode(); - setSelectionMode(QAbstractItemView::NoSelection); - - //treat this as a mouse pressed event to process everything but selection, but use the position data from the mousePress message - processQueuedMousePressedEvent(m_queuedMouseEvent); - - //restore selection state - setSelectionMode(selectionModeBefore); - } - - m_mousePosition = event->pos(); - if (QModelIndex hoveredIndex = indexAt(m_mousePosition); m_currentHoveredIndex != indexAt(m_mousePosition)) - { - m_currentHoveredIndex = hoveredIndex; - update(); - } - - //process mouse movement as normal, potentially triggering drag and drop - QTreeView::mouseMoveEvent(event); - } - void EntityOutlinerTreeView::focusInEvent(QFocusEvent* event) { - //cancel pending mouse press + // Cancel pending mouse press. ClearQueuedMouseEvent(); QTreeView::focusInEvent(event); } void EntityOutlinerTreeView::focusOutEvent(QFocusEvent* event) { - //cancel pending mouse press + // Cancel pending mouse press. ClearQueuedMouseEvent(); QTreeView::focusOutEvent(event); } - void EntityOutlinerTreeView::startDrag(Qt::DropActions supportedActions) - { - QModelIndex index = indexAt(m_queuedMouseEvent->pos()); - AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); - - AZ::EntityId parentEntityId; - EditorEntityInfoRequestBus::EventResult(parentEntityId, entityId, &EditorEntityInfoRequestBus::Events::GetParent); - - // If the entity is parented to a read-only entity, cancel the drag operation. - if (m_readOnlyEntityPublicInterface->IsReadOnly(parentEntityId)) - { - return; - } - - //if we are attempting to drag an unselected item then we must special case drag and drop logic - //QAbstractItemView::startDrag only supports selected items - if (m_queuedMouseEvent) - { - if (!index.isValid() || index.column() != 0) - { - return; - } - - if (!selectionModel()->isSelected(index)) - { - StartCustomDrag({ index }, supportedActions); - return; - } - } - - StyledTreeView::startDrag(supportedActions); - } - - void EntityOutlinerTreeView::dragMoveEvent(QDragMoveEvent* event) + void EntityOutlinerTreeView::dragMoveEvent([[maybe_unused]] QDragMoveEvent* event) { if (m_expandOnlyDelay >= 0) { @@ -257,12 +226,139 @@ namespace AzToolsFramework QTreeView::dragMoveEvent(event); } - void EntityOutlinerTreeView::dropEvent(QDropEvent* event) + void EntityOutlinerTreeView::dropEvent([[maybe_unused]] QDropEvent* event) { emit ItemDropped(); QTreeView::dropEvent(event); - m_draggingUnselectedItem = false; + ClearQueuedMouseEvent(); + } + + void EntityOutlinerTreeView::HandleDrag() + { + // Retrieve the index at the click position. + QModelIndex indexAtClick = indexAt(m_queuedMouseEvent->pos()).siblingAtColumn(EntityOutlinerListModel::ColumnName); + + AZ::EntityId entityId(indexAtClick.data(EntityOutlinerListModel::EntityIdRole).value()); + AZ::EntityId parentEntityId; + EditorEntityInfoRequestBus::EventResult(parentEntityId, entityId, &EditorEntityInfoRequestBus::Events::GetParent); + + // If the entity is parented to a read-only entity, cancel the drag operation. + if (m_readOnlyEntityPublicInterface->IsReadOnly(parentEntityId)) + { + return; + } + + // If the index is selected, we should move the whole selection. + if (selectionModel()->isSelected(indexAtClick)) + { + StartCustomDrag(selectionModel()->selectedIndexes(), defaultDropAction()); + } + else + { + StartCustomDrag(QModelIndexList{ indexAtClick }, defaultDropAction()); + } + } + + void EntityOutlinerTreeView::SelectAllEntitiesInSelectionRect() + { + if (!m_queuedMouseEvent) + { + return; + } + + // Retrieve the two opposing corners of the rect. + const QPoint point1 = (m_queuedMouseEvent->pos()); // The position the drag operation started at. + const QPoint point2 = (m_mousePosition); // The current mouse position. + + // Determine which point's y is the top and which is the bottom. + const int top(AZStd::min(point1.y(), point2.y())); + const int bottom(AZStd::max(point1.y(), point2.y())); + // We don't really need the x values for the rect, just use the center of the viewport. + const int middle(viewport()->rect().center().x()); + + // Find the extremes of the range of indices that are in the selection rect. + QModelIndex topIndex = indexAt(QPoint(middle, top)); + const QModelIndex bottomIndex = indexAt(QPoint(middle, bottom)); + + // If we have no top index, the mouse may have been dragged above the top item. Let's try to course correct. + const int topDistanceForFirstItem = 10; // A reasonable distance from the top we're sure to encounter the first item. + const QModelIndex firstIndex = indexAt(QPoint(middle, topDistanceForFirstItem)); + + if (!topIndex.isValid() && top < topDistanceForFirstItem) + { + topIndex = firstIndex; + } + + // We can assume that if topIndex is still invalid, it was below the last item in the hierarchy, hence no selection is made. + if (!topIndex.isValid()) + { + return; + } + + QItemSelection selection; + + // Starting from the top index, traverse all visible elements of the list and select them until the bottom index is hit. + // If the bottom index is undefined, just keep going to the end. + QModelIndex iter = topIndex; + selection.select(iter, iter); + + while (iter.isValid() && iter != bottomIndex) + { + iter = indexBelow(iter); + selection.select(iter, iter); + } + + selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + } + + void EntityOutlinerTreeView::ClearQueuedMouseEvent() + { + if (m_queuedMouseEvent) + { + delete m_queuedMouseEvent; + m_queuedMouseEvent = nullptr; + } + } + + void EntityOutlinerTreeView::leaveEvent([[maybe_unused]] QEvent* event) + { + ClearQueuedMouseEvent(); + + // Only clear the mouse position if the last mouse position registered is inside. + // This allows drag to select to work correctly in all situations. + if(this->viewport()->rect().contains(m_mousePosition)) + { + m_mousePosition = QPoint(-1, -1); + } + m_currentHoveredIndex = QModelIndex(); + update(); + } + + void EntityOutlinerTreeView::paintEvent(QPaintEvent* event) + { + AzQtComponents::StyledTreeView::paintEvent(event); + + // Draw the drag selection rect. + if (m_isDragSelectActive && m_queuedMouseEvent) + { + // Create a painter to draw on the viewport. + QPainter painter(viewport()); + + // Retrieve the two corners of the rect. + const QPoint point1 = (m_queuedMouseEvent->pos()); // The position the drag operation started at. + const QPoint point2 = (m_mousePosition); // The current mouse position. + + // We need the top left and bottom right corners, which may not be the two corners we got above. + // So we composite the corners based on the coordinates of the points. + const QPoint topLeft(AZStd::min(point1.x(), point2.x()), AZStd::min(point1.y(), point2.y())); + const QPoint bottomRight(AZStd::max(point1.x(), point2.x()), AZStd::max(point1.y(), point2.y())); + + // Paint the rect. + painter.setBrush(m_dragSelectRectColor); + painter.setPen(m_dragSelectBorderColor); + painter.drawRect(QRect(topLeft, bottomRight)); + } } void EntityOutlinerTreeView::drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const @@ -270,7 +366,7 @@ namespace AzToolsFramework const bool isEnabled = (this->model()->flags(index) & Qt::ItemIsEnabled); const bool isSelected = selectionModel()->isSelected(index); - const bool isHovered = (index == indexAt(m_mousePosition).siblingAtColumn(0)) && isEnabled; + const bool isHovered = (index == m_currentHoveredIndex.siblingAtColumn(0)) && isEnabled; // Paint the branch Selection/Hover Rect PaintBranchSelectionHoverRect(painter, rect, isSelected, isHovered); @@ -352,25 +448,27 @@ namespace AzToolsFramework QTreeView::timerEvent(event); } - void EntityOutlinerTreeView::processQueuedMousePressedEvent(QMouseEvent* event) + void EntityOutlinerTreeView::ProcessQueuedMousePressedEvent(QMouseEvent* event) { - //interpret the mouse event as a button press - QMouseEvent mousePressedEvent( - QEvent::MouseButtonPress, - event->localPos(), - event->windowPos(), - event->screenPos(), - event->button(), - event->buttons(), - event->modifiers(), - event->source()); - QTreeView::mousePressEvent(&mousePressedEvent); + QModelIndex clickedIndex = indexAt(m_queuedMouseEvent->pos()); + if (!clickedIndex.isValid() || clickedIndex.column() != EntityOutlinerListModel::ColumnSpacing) + { + //interpret the mouse event as a button press + QMouseEvent mousePressedEvent( + QEvent::MouseButtonPress, + event->localPos(), + event->windowPos(), + event->screenPos(), + event->button(), + event->buttons(), + event->modifiers(), + event->source()); + QTreeView::mousePressEvent(&mousePressedEvent); + } } void EntityOutlinerTreeView::StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) { - m_draggingUnselectedItem = true; - //sort by container entity depth and order in hierarchy for proper drag image and drop order QModelIndexList indexListSorted = indexList; AZStd::unordered_map> locations; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx index 014bb7bd48..6b4fa656e5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx @@ -63,7 +63,6 @@ namespace AzToolsFramework void mouseMoveEvent(QMouseEvent* event) override; void focusInEvent(QFocusEvent* event) override; void focusOutEvent(QFocusEvent* event) override; - void startDrag(Qt::DropActions supportedActions) override; void dragMoveEvent(QDragMoveEvent* event) override; void dropEvent(QDropEvent* event) override; void leaveEvent(QEvent* event) override; @@ -71,33 +70,39 @@ namespace AzToolsFramework // FocusModeNotificationBus overrides ... void OnEditorFocusChanged(AZ::EntityId previousFocusEntityId, AZ::EntityId newFocusEntityId) override; + void paintEvent(QPaintEvent* event) override; + //! Renders the left side of the item: appropriate background, branch lines, icons. void drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const override; void timerEvent(QTimerEvent* event) override; private: void ClearQueuedMouseEvent(); + void ProcessQueuedMousePressedEvent(QMouseEvent* event); - void processQueuedMousePressedEvent(QMouseEvent* event); - void recursiveCheckExpandedStates(const QModelIndex& parent); - void checkExpandedState(const QModelIndex& current); + void SelectAllEntitiesInSelectionRect(); + void HandleDrag(); void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) override; + void RecursiveCheckExpandedStates(const QModelIndex& parent); + void CheckExpandedState(const QModelIndex& current); + void PaintBranchBackground(QPainter* painter, const QRect& rect, const QModelIndex& index) const; void PaintBranchSelectionHoverRect(QPainter* painter, const QRect& rect, bool isSelected, bool isHovered) const; QMouseEvent* m_queuedMouseEvent; + QModelIndex m_currentHoveredIndex; QPoint m_mousePosition; - bool m_draggingUnselectedItem; // This is set when an item is dragged outside its bounding box. + bool m_isDragSelectActive = false; int m_expandOnlyDelay = -1; QBasicTimer m_expandTimer; const QColor m_selectedColor = QColor(255, 255, 255, 45); const QColor m_hoverColor = QColor(255, 255, 255, 30); - - QModelIndex m_currentHoveredIndex; + const QColor m_dragSelectRectColor = QColor(255, 255, 255, 20); + const QColor m_dragSelectBorderColor = QColor(255, 255, 255); EditorEntityUiInterface* m_editorEntityFrameworkInterface = nullptr; ReadOnlyEntityPublicInterface* m_readOnlyEntityPublicInterface = nullptr; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp index f4855cb715..604c3660e6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp @@ -193,7 +193,6 @@ namespace AzToolsFramework m_listModel->SetSortMode(m_sortMode); const int autoExpandDelayMilliseconds = 2500; - m_gui->m_objectTree->setSelectionMode(QAbstractItemView::ExtendedSelection); SetDefaultTreeViewEditTriggers(); m_gui->m_objectTree->setAutoExpandDelay(autoExpandDelayMilliseconds); m_gui->m_objectTree->setDragEnabled(true); @@ -208,6 +207,7 @@ namespace AzToolsFramework m_gui->m_objectTree->setAutoScrollMargin(20); m_gui->m_objectTree->setIndentation(24); m_gui->m_objectTree->setRootIsDecorated(false); + m_gui->m_objectTree->setSelectionMode(QAbstractItemView::ExtendedSelection); connect(m_gui->m_objectTree, &QTreeView::customContextMenuRequested, this, &EntityOutlinerWidget::OnOpenTreeContextMenu); // custom item delegate @@ -260,6 +260,8 @@ namespace AzToolsFramework m_gui->m_objectTree->header()->resizeSection(EntityOutlinerListModel::ColumnVisibilityToggle, 20); m_gui->m_objectTree->header()->setSectionResizeMode(EntityOutlinerListModel::ColumnLockToggle, QHeaderView::Fixed); m_gui->m_objectTree->header()->resizeSection(EntityOutlinerListModel::ColumnLockToggle, 24); + m_gui->m_objectTree->header()->setSectionResizeMode(EntityOutlinerListModel::ColumnSpacing, QHeaderView::Fixed); + m_gui->m_objectTree->header()->resizeSection(EntityOutlinerListModel::ColumnSpacing, 16); connect(m_gui->m_objectTree->selectionModel(), &QItemSelectionModel::selectionChanged,