From 52112be1acaa4c10c5dbc3e7e2a0f5d87ea34148 Mon Sep 17 00:00:00 2001
From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
Date: Thu, 21 Oct 2021 13:43:21 -0700
Subject: [PATCH] LYN-7448 + LYN-7542 + LYN-7543 | Focus Mode - UX Improvements
(#4837)
* Introduce Outliner button to simplify Prefab editing
Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
* Fix Focus Mode and disabled entities colors
Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
* Fix - propagate the event if the OnOutlinerItemClick function returns false.
This does not change current behavior but makes more sense in the context of future handlers.
Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
* Adjust disabled colors to match UX recommendations.
Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
* Display the edit button even if the prefab is disabled. Remove prefabWip check (it will be removed for focus mode by the time this goes in). Default to disabled capsule color for borders to save on checks.
Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
* Disable edit button on disabled prefabs as it caused conflicts in nested prefabs. May explore that possibility later.
Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
* Change disabled text color to be darker, as asked by UX.
Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
---
.../Images/Entity/prefab_edit_close.svg | 4 +
.../Images/Entity/prefab_edit_open.svg | 4 +
.../AzQtComponents/Images/resources.qrc | 2 +
.../Prefab/PrefabFocusHandler.cpp | 28 ++++
.../Prefab/PrefabFocusHandler.h | 1 +
.../Prefab/PrefabFocusPublicInterface.h | 7 +-
.../EditorEntityUiHandlerBase.cpp | 19 ++-
.../EditorEntityUiHandlerBase.h | 13 +-
.../UI/Outliner/EntityOutlinerListModel.cpp | 28 +++-
.../UI/Outliner/EntityOutlinerTreeView.cpp | 7 +
.../UI/Outliner/EntityOutlinerTreeView.hxx | 2 +
.../UI/Outliner/EntityOutlinerWidget.cpp | 21 ++-
.../UI/Prefab/PrefabUiHandler.cpp | 131 +++++++++++++++++-
.../UI/Prefab/PrefabUiHandler.h | 11 +-
.../ViewportUi/ViewportUiDisplay.cpp | 2 +-
15 files changed, 265 insertions(+), 15 deletions(-)
create mode 100644 Code/Framework/AzQtComponents/AzQtComponents/Images/Entity/prefab_edit_close.svg
create mode 100644 Code/Framework/AzQtComponents/AzQtComponents/Images/Entity/prefab_edit_open.svg
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Images/Entity/prefab_edit_close.svg b/Code/Framework/AzQtComponents/AzQtComponents/Images/Entity/prefab_edit_close.svg
new file mode 100644
index 0000000000..3fccf0e716
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Images/Entity/prefab_edit_close.svg
@@ -0,0 +1,4 @@
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Images/Entity/prefab_edit_open.svg b/Code/Framework/AzQtComponents/AzQtComponents/Images/Entity/prefab_edit_open.svg
new file mode 100644
index 0000000000..55704ec230
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Images/Entity/prefab_edit_open.svg
@@ -0,0 +1,4 @@
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc
index 0c8fedc79d..15049aeb69 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc
@@ -6,6 +6,8 @@
Entity/layer.svg
Entity/prefab.svg
Entity/prefab_edit.svg
+ Entity/prefab_edit_open.svg
+ Entity/prefab_edit_close.svg
Level/level.svg
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp
index 09b5745a90..8bc258fef9 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp
@@ -206,6 +206,34 @@ namespace AzToolsFramework::Prefab
return instance.has_value() && (&instance->get() == &m_focusedInstance->get());
}
+ bool PrefabFocusHandler::IsOwningPrefabInFocusHierarchy(AZ::EntityId entityId) const
+ {
+ if (!m_focusedInstance.has_value())
+ {
+ // PrefabFocusHandler has not been initialized yet.
+ return false;
+ }
+
+ if (!entityId.IsValid())
+ {
+ return false;
+ }
+
+ InstanceOptionalReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
+
+ while (instance.has_value())
+ {
+ if (&instance->get() == &m_focusedInstance->get())
+ {
+ return true;
+ }
+
+ instance = instance->get().GetParentInstance();
+ }
+
+ return false;
+ }
+
const AZ::IO::Path& PrefabFocusHandler::GetPrefabFocusPath([[maybe_unused]] AzFramework::EntityContextId entityContextId) const
{
return m_instanceFocusPath;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h
index 6a71365d8e..cb8165e7f0 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h
@@ -53,6 +53,7 @@ namespace AzToolsFramework::Prefab
PrefabFocusOperationResult FocusOnPathIndex(AzFramework::EntityContextId entityContextId, int index) override;
AZ::EntityId GetFocusedPrefabContainerEntityId(AzFramework::EntityContextId entityContextId) const override;
bool IsOwningPrefabBeingFocused(AZ::EntityId entityId) const override;
+ bool IsOwningPrefabInFocusHierarchy(AZ::EntityId entityId) const override;
const AZ::IO::Path& GetPrefabFocusPath(AzFramework::EntityContextId entityContextId) const override;
const int GetPrefabFocusPathLength(AzFramework::EntityContextId entityContextId) const override;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h
index 86e476b56f..5bd4c6b0f6 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h
@@ -37,10 +37,15 @@ namespace AzToolsFramework::Prefab
//! Returns the entity id of the container entity for the instance the prefab system is focusing on.
virtual AZ::EntityId GetFocusedPrefabContainerEntityId(AzFramework::EntityContextId entityContextId) const = 0;
+ //! Returns whether the entity belongs to the instance that is being focused on.
+ //! @param entityId The entityId of the queried entity.
+ //! @return true if the entity belongs to the focused instance, false otherwise.
+ virtual bool IsOwningPrefabBeingFocused(AZ::EntityId entityId) const = 0;
+
//! Returns whether the entity belongs to the instance that is being focused on, or one of its descendants.
//! @param entityId The entityId of the queried entity.
//! @return true if the entity belongs to the focused instance or one of its descendants, false otherwise.
- virtual bool IsOwningPrefabBeingFocused(AZ::EntityId entityId) const = 0;
+ virtual bool IsOwningPrefabInFocusHierarchy(AZ::EntityId entityId) const = 0;
//! Returns the path from the root instance to the currently focused instance.
//! @return A path composed from the names of the container entities for the instance path.
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp
index 3cdcade1b0..866080a83f 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp
@@ -101,8 +101,25 @@ namespace AzToolsFramework
{
}
- void EditorEntityUiHandlerBase::OnDoubleClick([[maybe_unused]] AZ::EntityId entityId) const
+ bool EditorEntityUiHandlerBase::OnOutlinerItemClick(
+ [[maybe_unused]] const QPoint& position,
+ [[maybe_unused]] const QStyleOptionViewItem& option,
+ [[maybe_unused]] const QModelIndex& index) const
+ {
+ return false;
+ }
+
+ void EditorEntityUiHandlerBase::OnOutlinerItemExpand([[maybe_unused]] const QModelIndex& index) const
+ {
+ }
+
+ void EditorEntityUiHandlerBase::OnOutlinerItemCollapse([[maybe_unused]] const QModelIndex& index) const
+ {
+ }
+
+ bool EditorEntityUiHandlerBase::OnEntityDoubleClick([[maybe_unused]] AZ::EntityId entityId) const
{
+ return false;
}
} // namespace AzToolsFramework
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h
index 9554ad01fc..96d393efa1 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h
@@ -61,8 +61,17 @@ namespace AzToolsFramework
virtual void PaintDescendantForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
const QModelIndex& descendantIndex) const;
- //! Triggered when the entity is double clicked in the Outliner.
- virtual void OnDoubleClick(AZ::EntityId entityId) const;
+ //! Triggered when the entity is clicked in the Outliner.
+ //! @return True if the click has been handled and should not be propagated, false otherwise.
+ virtual bool OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const;
+ //! Triggered when an entity's children are expanded in the Outliner.
+ virtual void OnOutlinerItemExpand(const QModelIndex& index) const;
+ //! Triggered when an entity's children are collapsed in the Outliner.
+ virtual void OnOutlinerItemCollapse(const QModelIndex& index) const;
+
+ //! Triggered when the entity is double clicked in the Outliner or in the Viewport.
+ //! @return True if the double click has been handled and should not be propagated, false otherwise.
+ virtual bool OnEntityDoubleClick(AZ::EntityId entityId) const;
private:
EditorEntityUiHandlerId m_handlerId = 0;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp
index 3f8023c1e3..a5f1e29942 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp
@@ -11,10 +11,12 @@
#include
#include
#include
+#include
#include
#include
#include
#include
+#include
#include
#include
#include
@@ -2287,7 +2289,14 @@ namespace AzToolsFramework
// Now we setup a Text Document so it can draw the rich text
QTextDocument textDoc;
textDoc.setDefaultFont(optionV4.font);
- textDoc.setDefaultStyleSheet("body {color: white}");
+ if (option.state & QStyle::State_Enabled)
+ {
+ textDoc.setDefaultStyleSheet("body {color: white}");
+ }
+ else
+ {
+ textDoc.setDefaultStyleSheet("body {color: #7C7C7C}");
+ }
textDoc.setHtml("" + entityNameRichText + "");
painter->translate(textRect.topLeft());
textDoc.setTextWidth(textRect.width());
@@ -2326,6 +2335,23 @@ namespace AzToolsFramework
return true;
}
+ if (event->type() == QEvent::MouseButtonPress)
+ {
+ AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value());
+
+ if (auto editorEntityUiInterface = AZ::Interface::Get(); editorEntityUiInterface != nullptr)
+ {
+ auto mouseEvent = static_cast(event);
+
+ auto entityUiHandler = editorEntityUiInterface->GetHandler(entityId);
+
+ if (entityUiHandler && entityUiHandler->OnOutlinerItemClick(mouseEvent->pos(), option, index))
+ {
+ return true;
+ }
+ }
+ }
+
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp
index d3138f5139..d94ced392c 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp
@@ -73,6 +73,8 @@ namespace AzToolsFramework
void EntityOutlinerTreeView::leaveEvent([[maybe_unused]] QEvent* event)
{
m_mousePosition = QPoint();
+ m_currentHoveredIndex = QModelIndex();
+ update();
}
void EntityOutlinerTreeView::mousePressEvent(QMouseEvent* event)
@@ -129,6 +131,11 @@ namespace AzToolsFramework
}
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);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx
index 5d76ec6db2..42b42a59b4 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx
@@ -90,6 +90,8 @@ namespace AzToolsFramework
const QColor m_selectedColor = QColor(255, 255, 255, 45);
const QColor m_hoverColor = QColor(255, 255, 255, 30);
+ QModelIndex m_currentHoveredIndex;
+
EditorEntityUiInterface* m_editorEntityFrameworkInterface;
};
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
index 4d53102edb..3e97f967fc 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
@@ -902,6 +902,7 @@ namespace AzToolsFramework
EditorPickModeRequestBus::Broadcast(
&EditorPickModeRequests::StopEntityPickMode);
+ return;
}
switch (index.column())
@@ -918,18 +919,30 @@ namespace AzToolsFramework
{
if (AZ::EntityId entityId = GetEntityIdFromIndex(index); auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId))
{
- entityUiHandler->OnDoubleClick(entityId);
+ entityUiHandler->OnEntityDoubleClick(entityId);
}
}
void EntityOutlinerWidget::OnTreeItemExpanded(const QModelIndex& index)
{
- m_listModel->OnEntityExpanded(GetEntityIdFromIndex(index));
+ AZ::EntityId entityId = GetEntityIdFromIndex(index);
+ if (auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId))
+ {
+ entityUiHandler->OnOutlinerItemExpand(index);
+ }
+
+ m_listModel->OnEntityExpanded(entityId);
}
void EntityOutlinerWidget::OnTreeItemCollapsed(const QModelIndex& index)
{
- m_listModel->OnEntityCollapsed(GetEntityIdFromIndex(index));
+ AZ::EntityId entityId = GetEntityIdFromIndex(index);
+ if (auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId))
+ {
+ entityUiHandler->OnOutlinerItemCollapse(index);
+ }
+
+ m_listModel->OnEntityCollapsed(entityId);
}
void EntityOutlinerWidget::OnExpandEntity(const AZ::EntityId& entityId, bool expand)
@@ -1163,7 +1176,7 @@ namespace AzToolsFramework
{
QTimer::singleShot(1, this, [this]() {
m_gui->m_objectTree->setUpdatesEnabled(true);
- m_gui->m_objectTree->expandToDepth(0);
+ m_gui->m_objectTree->expand(m_proxyModel->index(0,0));
});
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp
index 7c2c65d204..447f94fc15 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp
@@ -21,10 +21,16 @@
namespace AzToolsFramework
{
+ const QColor PrefabUiHandler::m_backgroundColor = QColor("#444444");
+ const QColor PrefabUiHandler::m_backgroundHoverColor = QColor("#5A5A5A");
+ const QColor PrefabUiHandler::m_backgroundSelectedColor = QColor("#656565");
const QColor PrefabUiHandler::m_prefabCapsuleColor = QColor("#1E252F");
+ const QColor PrefabUiHandler::m_prefabCapsuleDisabledColor = QColor("#35383C");
const QColor PrefabUiHandler::m_prefabCapsuleEditColor = QColor("#4A90E2");
const QString PrefabUiHandler::m_prefabIconPath = QString(":/Entity/prefab.svg");
const QString PrefabUiHandler::m_prefabEditIconPath = QString(":/Entity/prefab_edit.svg");
+ const QString PrefabUiHandler::m_prefabEditOpenIconPath = QString(":/Entity/prefab_edit_open.svg");
+ const QString PrefabUiHandler::m_prefabEditCloseIconPath = QString(":/Entity/prefab_edit_close.svg");
PrefabUiHandler::PrefabUiHandler()
{
@@ -75,7 +81,7 @@ namespace AzToolsFramework
if (!path.empty())
{
- tooltip = QObject::tr("%1").arg(path.Native().data());
+ tooltip = QObject::tr("Double click to edit.\n%1").arg(path.Native().data());
}
return tooltip;
@@ -102,13 +108,20 @@ namespace AzToolsFramework
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value());
const bool isFirstColumn = index.column() == EntityOutlinerListModel::ColumnName;
const bool isLastColumn = index.column() == EntityOutlinerListModel::ColumnLockToggle;
- const bool hasVisibleChildren = index.data(EntityOutlinerListModel::ExpandedRole).value() && index.model()->hasChildren(index);
+ QModelIndex firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName);
+ const bool hasVisibleChildren =
+ firstColumnIndex.data(EntityOutlinerListModel::ExpandedRole).value() &&
+ firstColumnIndex.model()->hasChildren(firstColumnIndex);
QColor backgroundColor = m_prefabCapsuleColor;
if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
{
backgroundColor = m_prefabCapsuleEditColor;
}
+ else if (!(option.state & QStyle::State_Enabled))
+ {
+ backgroundColor = m_prefabCapsuleDisabledColor;
+ }
QPainterPath backgroundPath;
backgroundPath.setFillRule(Qt::WindingFill);
@@ -184,7 +197,8 @@ namespace AzToolsFramework
const bool isFirstColumn = descendantIndex.column() == EntityOutlinerListModel::ColumnName;
const bool isLastColumn = descendantIndex.column() == EntityOutlinerListModel::ColumnLockToggle;
- QColor borderColor = m_prefabCapsuleColor;
+ // There is no legal way of opening prefabs in their default state, so default to disabled.
+ QColor borderColor = m_prefabCapsuleDisabledColor;
if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
{
borderColor = m_prefabCapsuleEditColor;
@@ -273,6 +287,71 @@ namespace AzToolsFramework
painter->restore();
}
+ void PrefabUiHandler::PaintItemForeground(QPainter* painter, const QStyleOptionViewItem& option, [[maybe_unused]] const QModelIndex& index) const
+ {
+ AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value());
+ const QPoint offset = QPoint(-18, 3);
+ QModelIndex firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName);
+ const int iconSize = 16;
+ const bool isHovered = (option.state & QStyle::State_MouseOver);
+ const bool isSelected = index.data(EntityOutlinerListModel::SelectedRole).template value();
+ const bool isFirstColumn = index.column() == EntityOutlinerListModel::ColumnName;
+ const bool isExpanded =
+ firstColumnIndex.data(EntityOutlinerListModel::ExpandedRole).value() &&
+ firstColumnIndex.model()->hasChildren(firstColumnIndex);
+
+ if (!isFirstColumn || !(option.state & QStyle::State_Enabled))
+ {
+ return;
+ }
+
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing, true);
+
+ if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
+ {
+ // Only show the close icon if the prefab is expanded.
+ // This allows the prefab container to be opened if it was collapsed during propagation.
+ if (!isExpanded)
+ {
+ return;
+ }
+
+ // Use the same color as the background.
+ QColor backgroundColor = m_backgroundColor;
+ if (isSelected)
+ {
+ backgroundColor = m_backgroundSelectedColor;
+ }
+ else if (isHovered)
+ {
+ backgroundColor = m_backgroundHoverColor;
+ }
+
+ // Paint a rect to cover up the expander.
+ QRect rect = QRect(0, 0, 16, 16);
+ rect.translate(option.rect.topLeft() + offset);
+ painter->fillRect(rect, backgroundColor);
+
+ // Paint the icon.
+ QIcon closeIcon = QIcon(m_prefabEditCloseIconPath);
+ painter->drawPixmap(option.rect.topLeft() + offset, closeIcon.pixmap(iconSize));
+ }
+ else
+ {
+ // Only show the edit icon on hover.
+ if (!isHovered)
+ {
+ return;
+ }
+
+ QIcon openIcon = QIcon(m_prefabEditOpenIconPath);
+ painter->drawPixmap(option.rect.topLeft() + offset, openIcon.pixmap(iconSize));
+ }
+
+ painter->restore();
+ }
+
bool PrefabUiHandler::IsLastVisibleChild(const QModelIndex& parent, const QModelIndex& child)
{
QModelIndex lastVisibleItemIndex = GetLastVisibleChild(parent);
@@ -314,9 +393,53 @@ namespace AzToolsFramework
return Internal_GetLastVisibleChild(model, lastChild);
}
- void PrefabUiHandler::OnDoubleClick(AZ::EntityId entityId) const
+ bool PrefabUiHandler::OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const
+ {
+ AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value());
+ const QPoint offset = QPoint(-18, 3);
+
+ if (m_prefabFocusPublicInterface->IsOwningPrefabInFocusHierarchy(entityId))
+ {
+ QRect iconRect = QRect(0, 0, 16, 16);
+ iconRect.translate(option.rect.topLeft() + offset);
+
+ if (iconRect.contains(position))
+ {
+ if (!m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
+ {
+ // Focus on this prefab.
+ m_prefabFocusPublicInterface->FocusOnOwningPrefab(entityId);
+ }
+
+ // Don't propagate event.
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ void PrefabUiHandler::OnOutlinerItemCollapse(const QModelIndex& index) const
+ {
+ AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value());
+
+ if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
+ {
+ auto editorEntityContextId = AzFramework::EntityContextId::CreateNull();
+ EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
+
+ // Go one level up.
+ int length = m_prefabFocusPublicInterface->GetPrefabFocusPathLength(editorEntityContextId);
+ m_prefabFocusPublicInterface->FocusOnPathIndex(editorEntityContextId, length - 2);
+ }
+ }
+
+ bool PrefabUiHandler::OnEntityDoubleClick(AZ::EntityId entityId) const
{
// Focus on this prefab
m_prefabFocusPublicInterface->FocusOnOwningPrefab(entityId);
+
+ // Don't propagate event.
+ return true;
}
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h
index 7c68d9fd95..6c78afc5b7 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h
@@ -36,7 +36,10 @@ namespace AzToolsFramework
void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
void PaintDescendantBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
const QModelIndex& descendantIndex) const override;
- void OnDoubleClick(AZ::EntityId entityId) const override;
+ void PaintItemForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+ bool OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+ void OnOutlinerItemCollapse(const QModelIndex& index) const override;
+ bool OnEntityDoubleClick(AZ::EntityId entityId) const override;
private:
Prefab::PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
@@ -48,9 +51,15 @@ namespace AzToolsFramework
static constexpr int m_prefabCapsuleRadius = 6;
static constexpr int m_prefabBorderThickness = 2;
+ static const QColor m_backgroundColor;
+ static const QColor m_backgroundHoverColor;
+ static const QColor m_backgroundSelectedColor;
static const QColor m_prefabCapsuleColor;
+ static const QColor m_prefabCapsuleDisabledColor;
static const QColor m_prefabCapsuleEditColor;
static const QString m_prefabIconPath;
static const QString m_prefabEditIconPath;
+ static const QString m_prefabEditOpenIconPath;
+ static const QString m_prefabEditCloseIconPath;
};
} // namespace AzToolsFramework
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp
index a289d914d6..43e2a6793f 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp
@@ -20,7 +20,7 @@ namespace AzToolsFramework::ViewportUi::Internal
{
const static int HighlightBorderSize = 5;
const static int TopHighlightBorderSize = 25;
- const static char* HighlightBorderColor = "#44B2F8";
+ const static char* HighlightBorderColor = "#4A90E2";
static void UnparentWidgets(ViewportUiElementIdInfoLookup& viewportUiElementIdInfoLookup)
{