Integrating up through commit 90f050496
This commit is contained in:
+6
-1
@@ -63,7 +63,12 @@ namespace AzToolsFramework
|
||||
void EditorEntityUiHandlerBase::PaintDescendantBackground(QPainter* /*painter*/, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/,
|
||||
const QModelIndex& /*descendantIndex*/) const
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void EditorEntityUiHandlerBase::PaintDescendantBranchBackground(QPainter* /*painter*/, const QTreeView* /*view*/, const QRect& /*rect*/,
|
||||
const QModelIndex& /*index*/, const QModelIndex& /*descendantIndex*/) const
|
||||
{
|
||||
}
|
||||
|
||||
void EditorEntityUiHandlerBase::PaintItemForeground(QPainter* /*painter*/, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const
|
||||
{
|
||||
|
||||
+4
@@ -20,6 +20,7 @@
|
||||
#include <QStyleOptionViewItem>
|
||||
|
||||
class QPainter;
|
||||
class QTreeView;
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
@@ -50,6 +51,9 @@ namespace AzToolsFramework
|
||||
//! Paints the background of the descendants of the item in the Outliner.
|
||||
virtual void PaintDescendantBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
|
||||
const QModelIndex& descendantIndex) const;
|
||||
//! Paints the background of the descendant branches of the item in the Outliner.
|
||||
virtual void PaintDescendantBranchBackground(QPainter* painter, const QTreeView* view, const QRect& rect,
|
||||
const QModelIndex& index, const QModelIndex& descendantIndex) const;
|
||||
|
||||
//! Paints visual elements on the foreground of the item in the Outliner.
|
||||
virtual void PaintItemForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
|
||||
@@ -21,29 +21,17 @@
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
const int LayerUiHandler::m_layerSquareSize = 20;
|
||||
const int LayerUiHandler::m_layerStripeWidth = 1;
|
||||
const int LayerUiHandler::m_layerDividerLineHeight = 1;
|
||||
const int LayerUiHandler::m_lastEntityInLayerDividerLineHeight = 1;
|
||||
const QColor LayerUiHandler::m_layerBackgroundColor = QColor("#2F2F2F");
|
||||
const QColor LayerUiHandler::m_layerDescendantBackgroundColor = QColor("#333333");
|
||||
const QColor LayerUiHandler::m_layerBorderTopColor = QColor("#515151");
|
||||
const QColor LayerUiHandler::m_layerBorderBottomColor = QColor("#252525");
|
||||
const QString LayerUiHandler::m_layerIconPath = QString(":/Icons/layer_icon.svg");
|
||||
const QString LayerUiHandler::m_layerIconPath = QString(":/Entity/layer.svg");
|
||||
|
||||
QString LayerUiHandler::GenerateItemInfoString(AZ::EntityId entityId) const
|
||||
{
|
||||
QString result;
|
||||
bool isLayerEntity = false;
|
||||
AZ::Outcome<AZStd::string, AZStd::string> layerBaseNameResult;
|
||||
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
isLayerEntity,
|
||||
entityId,
|
||||
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
|
||||
|
||||
if (!isLayerEntity)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
layerBaseNameResult, entityId, &AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::GetLayerBaseFileName);
|
||||
|
||||
bool hasUnsavedLayerChanges = false;
|
||||
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
@@ -51,16 +39,28 @@ namespace AzToolsFramework
|
||||
entityId,
|
||||
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasUnsavedChanges);
|
||||
|
||||
QString result = "<span style=\"font-style: italic; font-weight: 400;\">";
|
||||
|
||||
if (layerBaseNameResult.IsSuccess())
|
||||
{
|
||||
result += QString("(%1.layer").arg(layerBaseNameResult.GetValue().c_str());
|
||||
}
|
||||
|
||||
if (hasUnsavedLayerChanges)
|
||||
{
|
||||
result = QObject::tr("*");
|
||||
result += QString("*");
|
||||
}
|
||||
|
||||
if (layerBaseNameResult.IsSuccess())
|
||||
{
|
||||
result += QString(")");
|
||||
}
|
||||
|
||||
result += "</span>";
|
||||
|
||||
bool isLayerNameValid = false;
|
||||
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
isLayerNameValid,
|
||||
entityId,
|
||||
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::IsLayerNameValid);
|
||||
isLayerNameValid, entityId, &AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::IsLayerNameValid);
|
||||
|
||||
if (!isLayerNameValid)
|
||||
{
|
||||
@@ -75,22 +75,7 @@ namespace AzToolsFramework
|
||||
return QPixmap(m_layerIconPath);
|
||||
}
|
||||
|
||||
void LayerUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const
|
||||
{
|
||||
QPainterPath backgroundPath;
|
||||
backgroundPath.addRect(option.rect);
|
||||
painter->fillPath(backgroundPath, m_layerBackgroundColor);
|
||||
}
|
||||
|
||||
void LayerUiHandler::PaintDescendantBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& /*index*/,
|
||||
const QModelIndex& /*descendantIndex*/) const
|
||||
{
|
||||
QPainterPath backgroundPath;
|
||||
backgroundPath.addRect(option.rect);
|
||||
painter->fillPath(backgroundPath, m_layerDescendantBackgroundColor);
|
||||
}
|
||||
|
||||
void LayerUiHandler::PaintItemForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
void LayerUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value<AZ::u64>());
|
||||
|
||||
@@ -99,11 +84,18 @@ namespace AzToolsFramework
|
||||
return;
|
||||
}
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
// Dark Grey Background
|
||||
QPainterPath backgroundPath;
|
||||
backgroundPath.addRect(option.rect);
|
||||
painter->fillPath(backgroundPath, m_layerBackgroundColor);
|
||||
|
||||
// Left rect with the layer color
|
||||
QColor layerColor;
|
||||
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
layerColor,
|
||||
entityId,
|
||||
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::GetLayerColor);
|
||||
layerColor, entityId, &AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::GetLayerColor);
|
||||
|
||||
const QTreeView* outlinerTreeView(qobject_cast<const QTreeView*>(option.widget));
|
||||
int indentation = outlinerTreeView->indentation();
|
||||
@@ -114,39 +106,31 @@ namespace AzToolsFramework
|
||||
if (isFirstColumn)
|
||||
{
|
||||
// Layer colored box
|
||||
QPainterPath layerIconPath;
|
||||
QPainterPath iconBackgroundPath;
|
||||
QPoint layerBoxOffset(0, (option.rect.height() - m_layerSquareSize) / 2);
|
||||
QRect layerIconRect(option.rect.topLeft() + layerBoxOffset, QSize(m_layerSquareSize, m_layerSquareSize));
|
||||
layerIconPath.addRect(layerIconRect);
|
||||
painter->fillPath(layerIconPath, layerColor);
|
||||
iconBackgroundPath.addRect(layerIconRect);
|
||||
painter->fillPath(iconBackgroundPath, layerColor);
|
||||
|
||||
// Left border
|
||||
PaintLayerStripeAndBorder(
|
||||
painter,
|
||||
option.rect.left(),
|
||||
option.rect.top(),
|
||||
option.rect.bottom(),
|
||||
m_layerBorderBottomColor,
|
||||
layerColor);
|
||||
painter, option.rect.left() - 1, option.rect.top(), option.rect.bottom(), m_layerBorderBottomColor, layerColor);
|
||||
}
|
||||
|
||||
QModelIndex nameColumn = index.sibling(index.row(), EntityOutlinerListModel::Column::ColumnName);
|
||||
QModelIndex sibling = index.sibling(index.row() + 1, index.column());
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
QPoint lineBottomLeft(option.rect.bottomLeft());
|
||||
QPoint lineTopLeft(option.rect.topLeft());
|
||||
|
||||
if (isFirstColumn)
|
||||
{
|
||||
lineTopLeft.setX(lineTopLeft.x() + m_layerStripeWidth);
|
||||
lineTopLeft.setX(lineTopLeft.x() + m_layerStripeWidth - 1);
|
||||
}
|
||||
QPen topLinePen(m_layerBorderTopColor, m_layerDividerLineHeight);
|
||||
painter->setPen(topLinePen);
|
||||
painter->drawLine(lineTopLeft, option.rect.topRight());
|
||||
|
||||
|
||||
if (isFirstColumn)
|
||||
{
|
||||
lineBottomLeft.setX(lineBottomLeft.x());
|
||||
@@ -156,11 +140,43 @@ namespace AzToolsFramework
|
||||
lineBottomLeft.setX(lineBottomLeft.x() + m_layerStripeWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QPen bottomLinePen(m_layerBorderBottomColor, m_layerDividerLineHeight);
|
||||
painter->setPen(bottomLinePen);
|
||||
painter->drawLine(lineBottomLeft, option.rect.bottomRight());
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void LayerUiHandler::PaintDescendantBackground(QPainter* painter, const QStyleOptionViewItem& option,
|
||||
const QModelIndex& /*index*/, const QModelIndex& /*descendantIndex*/) const
|
||||
{
|
||||
QPainterPath backgroundPath;
|
||||
backgroundPath.addRect(option.rect);
|
||||
painter->fillPath(backgroundPath, m_layerDescendantBackgroundColor);
|
||||
}
|
||||
|
||||
void LayerUiHandler::PaintDescendantBranchBackground(QPainter* painter, const QTreeView* view, const QRect& rect,
|
||||
const QModelIndex& index, const QModelIndex& /*descendantIndex*/) const
|
||||
{
|
||||
if (!painter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
QPainterPath backgroundPath;
|
||||
|
||||
const int ancestorLeft = view->visualRect(index).left();
|
||||
|
||||
// Find the rect that extends fully to the left
|
||||
QRect fullRect = rect;
|
||||
fullRect.setLeft(ancestorLeft);
|
||||
backgroundPath.addRect(fullRect);
|
||||
|
||||
painter->fillPath(backgroundPath, m_layerDescendantBackgroundColor);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
@@ -182,7 +198,7 @@ namespace AzToolsFramework
|
||||
const QTreeView* outlinerTreeView(qobject_cast<const QTreeView*>(option.widget));
|
||||
bool isFirstColumn = descendantIndex.column() == EntityOutlinerListModel::ColumnName;
|
||||
bool isLastColumn = descendantIndex.column() == EntityOutlinerListModel::ColumnLockToggle;
|
||||
int ancestorLeft = outlinerTreeView->visualRect(index).left();
|
||||
int ancestorLeft = outlinerTreeView->visualRect(index).left() - 1;
|
||||
|
||||
// Draw the left stripe for this layer on the descendant's rect
|
||||
if (isFirstColumn)
|
||||
|
||||
@@ -32,7 +32,8 @@ 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 PaintItemForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
void PaintDescendantBranchBackground(QPainter* painter, const QTreeView* view, const QRect& rect,
|
||||
const QModelIndex& index, const QModelIndex& descendantIndex) const override;
|
||||
void PaintDescendantForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
|
||||
const QModelIndex& descendantIndex) const override;
|
||||
|
||||
@@ -43,12 +44,16 @@ namespace AzToolsFramework
|
||||
static QModelIndex GetLastVisibleChild(const QModelIndex& parent);
|
||||
static QModelIndex Internal_GetLastVisibleChild(const QAbstractItemModel* model, const QModelIndex& index);
|
||||
|
||||
static const int m_layerSquareSize;
|
||||
static const int m_layerStripeWidth;
|
||||
static const int m_layerDividerLineHeight;
|
||||
static const int m_lastEntityInLayerDividerLineHeight;
|
||||
static constexpr int m_layerSquareSize = 22;
|
||||
static constexpr int m_layerStripeWidth = 1;
|
||||
static constexpr int m_layerDividerLineHeight = 1;
|
||||
static constexpr int m_lastEntityInLayerDividerLineHeight = 1;
|
||||
static const QColor m_layerBackgroundColor;
|
||||
static const QColor m_layerBackgroundHoveredColor;
|
||||
static const QColor m_layerBackgroundSelectedColor;
|
||||
static const QColor m_layerDescendantBackgroundColor;
|
||||
static const QColor m_layerDescendantBackgroundHoveredColor;
|
||||
static const QColor m_layerDescendantBackgroundSelectedColor;
|
||||
static const QColor m_layerBorderTopColor;
|
||||
static const QColor m_layerBorderBottomColor;
|
||||
static const QString m_layerIconPath;
|
||||
|
||||
@@ -44,11 +44,11 @@ AzToolsFramework--EntityOutlinerCheckBox
|
||||
border: 0px solid transparent;
|
||||
border-radius: 0px;
|
||||
spacing: 0px;
|
||||
padding: 0px;
|
||||
padding: 0;
|
||||
padding-right: 2px;
|
||||
line-height: 0px;
|
||||
font-size: 0px;
|
||||
margin: 0px;
|
||||
background-color: transparent;
|
||||
max-height: 20px;
|
||||
max-width: 18px;
|
||||
}
|
||||
@@ -58,14 +58,15 @@ AzToolsFramework--EntityOutlinerCheckBox::indicator
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
image-position:center;
|
||||
|
||||
border: 1px solid transparent;
|
||||
image: none;
|
||||
spacing: 0px;
|
||||
padding: 0px;
|
||||
line-height: 0px;
|
||||
font-size: 0px;
|
||||
margin: 0;
|
||||
margin: 3px 0 0 0;
|
||||
max-width: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
AzToolsFramework--EntityOutlinerCheckBox#VisibilityMixed::indicator:checked
|
||||
@@ -83,7 +84,6 @@ AzToolsFramework--EntityOutlinerCheckBox#VisibilityMixed::indicator:checked
|
||||
{
|
||||
background: rgba(0, 0, 0, 80);
|
||||
border-radius: 5px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ AzToolsFramework--EntityOutlinerCheckBox#Visibility::indicator:unchecked
|
||||
, AzToolsFramework--EntityOutlinerCheckBox#VisibilityMixed::indicator:unchecked
|
||||
{
|
||||
image: url(:/visibility_on.svg);
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
AzToolsFramework--EntityOutlinerCheckBox#VisibilityOverridden::indicator:checked
|
||||
@@ -109,6 +110,7 @@ AzToolsFramework--EntityOutlinerCheckBox#VisibilityOverridden::indicator:checked
|
||||
AzToolsFramework--EntityOutlinerCheckBox#VisibilityOverridden::indicator:unchecked
|
||||
{
|
||||
image: url(:/visibility_on_transparent.svg);
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
AzToolsFramework--EntityOutlinerCheckBox#VisibilityHover::indicator:checked
|
||||
@@ -116,6 +118,7 @@ AzToolsFramework--EntityOutlinerCheckBox#VisibilityHover::indicator:checked
|
||||
, AzToolsFramework--EntityOutlinerCheckBox#VisibilityOverriddenHover::indicator:checked
|
||||
{
|
||||
image: url(:/visibility_default_hover.svg);
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
AzToolsFramework--EntityOutlinerCheckBox#VisibilityHover::indicator:unchecked
|
||||
@@ -123,6 +126,7 @@ AzToolsFramework--EntityOutlinerCheckBox#VisibilityHover::indicator:unchecked
|
||||
, AzToolsFramework--EntityOutlinerCheckBox#VisibilityOverriddenHover::indicator:unchecked
|
||||
{
|
||||
image: url(:/visibility_on_hover.svg);
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +136,7 @@ AzToolsFramework--EntityOutlinerCheckBox#Lock::indicator:checked
|
||||
, AzToolsFramework--EntityOutlinerCheckBox#LockMixed::indicator:checked
|
||||
{
|
||||
image: url(:/lock_on.svg);
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
AzToolsFramework--EntityOutlinerCheckBox#Lock::indicator:unchecked
|
||||
@@ -148,6 +153,7 @@ AzToolsFramework--EntityOutlinerCheckBox#LockOverridden::indicator:checked
|
||||
AzToolsFramework--EntityOutlinerCheckBox#LockOverridden::indicator:unchecked
|
||||
{
|
||||
image: url(:/lock_default_transparent.svg);
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
AzToolsFramework--EntityOutlinerCheckBox#LockHover::indicator:checked
|
||||
@@ -155,6 +161,7 @@ AzToolsFramework--EntityOutlinerCheckBox#LockHover::indicator:checked
|
||||
, AzToolsFramework--EntityOutlinerCheckBox#LockOverriddenHover::indicator:checked
|
||||
{
|
||||
image: url(:/lock_on_hover.svg);
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
AzToolsFramework--EntityOutlinerCheckBox#LockHover::indicator:unchecked
|
||||
@@ -162,4 +169,5 @@ AzToolsFramework--EntityOutlinerCheckBox#LockHover::indicator:unchecked
|
||||
, AzToolsFramework--EntityOutlinerCheckBox#LockOverriddenHover::indicator:unchecked
|
||||
{
|
||||
image: url(:/lock_default_hover.svg);
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
+36
-41
@@ -1970,6 +1970,13 @@ namespace AzToolsFramework
|
||||
|
||||
void EntityOutlinerItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
// Customize option to prevent Qt from painting the default focus rectangle
|
||||
QStyleOptionViewItem customOption{option};
|
||||
if (customOption.state & QStyle::State_HasFocus)
|
||||
{
|
||||
customOption.state ^= QStyle::State_HasFocus;
|
||||
}
|
||||
|
||||
// Retrieve the Entity UI Handler
|
||||
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value<AZ::u64>());
|
||||
auto entityUiHandler = m_editorEntityFrameworkInterface->GetHandler(entityId);
|
||||
@@ -1977,6 +1984,9 @@ namespace AzToolsFramework
|
||||
const bool isSelected = (option.state & QStyle::State_Selected);
|
||||
const bool isHovered = (option.state & QStyle::State_MouseOver) && (option.state & QStyle::State_Enabled);
|
||||
|
||||
// Paint the Selection/Hover Rect
|
||||
PaintSelectionHoverRect(painter, option, index, isSelected, isHovered);
|
||||
|
||||
// Paint Ancestor Backgrounds
|
||||
PaintAncestorBackgrounds(painter, option, index);
|
||||
|
||||
@@ -1986,25 +1996,6 @@ namespace AzToolsFramework
|
||||
entityUiHandler->PaintItemBackground(painter, option, index);
|
||||
}
|
||||
|
||||
// Paint the Selection/Hover Rect
|
||||
PaintSelectionHoverRect(painter, option, index, isSelected, isHovered);
|
||||
|
||||
// Paint Ancestor Foregrounds
|
||||
PaintAncestorForegrounds(painter, option, index);
|
||||
|
||||
// Paint the Foreground
|
||||
if (entityUiHandler != nullptr)
|
||||
{
|
||||
entityUiHandler->PaintItemForeground(painter, option, index);
|
||||
}
|
||||
|
||||
// Customize option to prevent Qt from painting the default focus rectangle
|
||||
QStyleOptionViewItem customOption{ option };
|
||||
if (customOption.state & QStyle::State_HasFocus)
|
||||
{
|
||||
customOption.state ^= QStyle::State_HasFocus;
|
||||
}
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case EntityOutlinerListModel::ColumnVisibilityToggle:
|
||||
@@ -2033,6 +2024,15 @@ namespace AzToolsFramework
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Paint Ancestor Foregrounds
|
||||
PaintAncestorForegrounds(painter, option, index);
|
||||
|
||||
// Paint the Foreground
|
||||
if (entityUiHandler != nullptr)
|
||||
{
|
||||
entityUiHandler->PaintItemForeground(painter, option, index);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityOutlinerItemDelegate::PaintAncestorBackgrounds(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
@@ -2069,17 +2069,18 @@ namespace AzToolsFramework
|
||||
|
||||
if (isSelected || isHovered)
|
||||
{
|
||||
QPainterPath layerBGPath;
|
||||
QRect layerBGRect(option.rect);
|
||||
layerBGPath.addRect(layerBGRect);
|
||||
QPainterPath backgroundPath;
|
||||
QRect backgroundRect(option.rect);
|
||||
|
||||
QColor layerBG = m_hoverColor;
|
||||
backgroundPath.addRect(backgroundRect);
|
||||
|
||||
QColor backgroundColor = m_hoverColor;
|
||||
if (isSelected)
|
||||
{
|
||||
layerBG = m_selectedColor;
|
||||
backgroundColor = m_selectedColor;
|
||||
}
|
||||
|
||||
painter->fillPath(layerBGPath, layerBG);
|
||||
painter->fillPath(backgroundPath, backgroundColor);
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
@@ -2212,13 +2213,9 @@ namespace AzToolsFramework
|
||||
textWidthAvailable -= fontMetrics.horizontalAdvance(QObject::tr("..."));
|
||||
if (!infoString.isEmpty())
|
||||
{
|
||||
// The info string includes HTML markup, which can cause an issue computing the width.
|
||||
// The markup on the text is light (just color, italic or bold), so an approximate width
|
||||
// is computed by taking the width of the non-HTML portion of the string and padding it a bit.
|
||||
QString htmlStripped = infoString;
|
||||
htmlStripped.remove(htmlMarkupRegex);
|
||||
const float layerInfoPadding = 1.2f;
|
||||
textWidthAvailable -= fontMetrics.horizontalAdvance(htmlStripped) * layerInfoPadding;
|
||||
textWidthAvailable -= fontMetrics.horizontalAdvance(htmlStripped) + 5;
|
||||
}
|
||||
|
||||
entityNameRichText = fontMetrics.elidedText(optionV4.text, Qt::TextElideMode::ElideRight, textWidthAvailable);
|
||||
@@ -2226,7 +2223,12 @@ namespace AzToolsFramework
|
||||
|
||||
if (!infoString.isEmpty())
|
||||
{
|
||||
entityNameRichText = QObject::tr("%1%2").arg(entityNameRichText).arg(infoString);
|
||||
entityNameRichText = QString("<table width=\"100%\" style=\"border-collapse: collapse; border-spacing: 0;\">")
|
||||
+ QString("<tr><td>")
|
||||
+ QString(entityNameRichText)
|
||||
+ QString("</td><td align=\"right\">")
|
||||
+ QString(infoString)
|
||||
+ QString("</td></tr></table>");
|
||||
}
|
||||
|
||||
// delete the text from the item so we can use the standard painter to draw the icon
|
||||
@@ -2238,7 +2240,7 @@ namespace AzToolsFramework
|
||||
textDoc.setDefaultFont(optionV4.font);
|
||||
textDoc.setDefaultStyleSheet("body {color: white}");
|
||||
textDoc.setHtml("<body>" + entityNameRichText + "</body>");
|
||||
painter->translate(textRect.topLeft() + QPoint(0, -1));
|
||||
painter->translate(textRect.topLeft());
|
||||
textDoc.setTextWidth(textRect.width());
|
||||
textDoc.drawContents(painter, QRectF(0, 0, textRect.width(), textRect.height()));
|
||||
|
||||
@@ -2246,7 +2248,7 @@ namespace AzToolsFramework
|
||||
EntityOutlinerListModel::s_paintingName = false;
|
||||
}
|
||||
|
||||
QSize EntityOutlinerItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
QSize EntityOutlinerItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const
|
||||
{
|
||||
// Get the height of a tall character...
|
||||
// we do this only once per 'tick'
|
||||
@@ -2262,14 +2264,7 @@ namespace AzToolsFramework
|
||||
QTimer::singleShot(0, resetFunction);
|
||||
}
|
||||
|
||||
QSize sh = QSize(0, m_cachedBoundingRectOfTallCharacter.height() + EntityOutlinerListModel::s_OutlinerSpacing);
|
||||
|
||||
if (index.column() == EntityOutlinerListModel::ColumnVisibilityToggle || index.column() == EntityOutlinerListModel::ColumnLockToggle)
|
||||
{
|
||||
sh.setWidth(m_toggleColumnWidth);
|
||||
}
|
||||
|
||||
return sh;
|
||||
return QSize(0, m_cachedBoundingRectOfTallCharacter.height() + EntityOutlinerListModel::s_OutlinerSpacing);
|
||||
}
|
||||
|
||||
bool EntityOutlinerItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
|
||||
|
||||
+1
-3
@@ -107,7 +107,7 @@ namespace AzToolsFramework
|
||||
};
|
||||
|
||||
// Spacing is appropriate and matches the outliner concept work from the UI team.
|
||||
static const int s_OutlinerSpacing = 5;
|
||||
static const int s_OutlinerSpacing = 7;
|
||||
|
||||
static bool s_paintingName;
|
||||
|
||||
@@ -358,8 +358,6 @@ namespace AzToolsFramework
|
||||
mutable CheckboxGroup m_visibilityCheckBoxes;
|
||||
mutable CheckboxGroup m_lockCheckBoxes;
|
||||
|
||||
const int m_toggleColumnWidth = 16;
|
||||
|
||||
// this is a cache, and is hence mutable
|
||||
mutable QRect m_cachedBoundingRectOfTallCharacter;
|
||||
|
||||
|
||||
+1
-8
@@ -183,8 +183,6 @@ namespace AzToolsFramework
|
||||
// Paint the branch background as defined by the entity's handler, or its closes ancestor's.
|
||||
PaintBranchBackground(painter, rect, index);
|
||||
|
||||
// Make sure the base class is called after the layer rect is drawn,
|
||||
// so that the foldout arrow draws on top of the layer color.
|
||||
QTreeView::drawBranches(painter, rect, index);
|
||||
}
|
||||
|
||||
@@ -209,12 +207,7 @@ namespace AzToolsFramework
|
||||
|
||||
if (ancestorUiHandler != nullptr)
|
||||
{
|
||||
int ancestorLeft = visualRect(ancestorIndex).left();
|
||||
QStyleOptionViewItem option;
|
||||
option.rect = rect;
|
||||
option.rect.setLeft(ancestorLeft);
|
||||
|
||||
ancestorUiHandler->PaintDescendantBackground(painter, option, ancestorIndex, index);
|
||||
ancestorUiHandler->PaintDescendantBranchBackground(painter, this, rect, ancestorIndex, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+41
-2
@@ -171,7 +171,7 @@ namespace AzToolsFramework
|
||||
|
||||
const int autoExpandDelayMilliseconds = 2500;
|
||||
m_gui->m_objectTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
m_gui->m_objectTree->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
|
||||
m_gui->m_objectTree->setEditTriggers(QAbstractItemView::EditKeyPressed);
|
||||
m_gui->m_objectTree->setAutoExpandDelay(autoExpandDelayMilliseconds);
|
||||
m_gui->m_objectTree->setDragEnabled(true);
|
||||
m_gui->m_objectTree->setDropIndicatorShown(true);
|
||||
@@ -179,9 +179,11 @@ namespace AzToolsFramework
|
||||
m_gui->m_objectTree->setDragDropOverwriteMode(false);
|
||||
m_gui->m_objectTree->setDragDropMode(QAbstractItemView::DragDrop);
|
||||
m_gui->m_objectTree->setDefaultDropAction(Qt::CopyAction);
|
||||
m_gui->m_objectTree->setExpandsOnDoubleClick(false);
|
||||
m_gui->m_objectTree->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_gui->m_objectTree->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
m_gui->m_objectTree->setAutoScrollMargin(20);
|
||||
m_gui->m_objectTree->setIndentation(24);
|
||||
connect(m_gui->m_objectTree, &QTreeView::customContextMenuRequested, this, &EntityOutlinerWidget::OnOpenTreeContextMenu);
|
||||
|
||||
// custom item delegate
|
||||
@@ -193,6 +195,7 @@ namespace AzToolsFramework
|
||||
|
||||
// Link up signals for informing the model of tree changes using the proxy as an intermediary
|
||||
connect(m_gui->m_objectTree, &QTreeView::clicked, this, &EntityOutlinerWidget::OnTreeItemClicked);
|
||||
connect(m_gui->m_objectTree, &QTreeView::doubleClicked, this, &EntityOutlinerWidget::OnTreeItemDoubleClicked);
|
||||
connect(m_gui->m_objectTree, &QTreeView::expanded, this, &EntityOutlinerWidget::OnTreeItemExpanded);
|
||||
connect(m_gui->m_objectTree, &QTreeView::collapsed, this, &EntityOutlinerWidget::OnTreeItemCollapsed);
|
||||
connect(m_gui->m_objectTree, &EntityOutlinerTreeView::ItemDropped, this, &EntityOutlinerWidget::OnDropEvent);
|
||||
@@ -223,8 +226,12 @@ namespace AzToolsFramework
|
||||
m_gui->m_objectTree->header()->setStretchLastSection(false);
|
||||
|
||||
// resize the icon columns so that the Visibility and Lock toggle icon columns stay right-justified
|
||||
m_gui->m_objectTree->header()->setStretchLastSection(false);
|
||||
m_gui->m_objectTree->header()->setMinimumSectionSize(0);
|
||||
m_gui->m_objectTree->header()->setSectionResizeMode(EntityOutlinerListModel::ColumnName, QHeaderView::Stretch);
|
||||
m_gui->m_objectTree->header()->setSectionResizeMode(EntityOutlinerListModel::ColumnVisibilityToggle, QHeaderView::ResizeToContents);
|
||||
m_gui->m_objectTree->header()->setSectionResizeMode(EntityOutlinerListModel::ColumnVisibilityToggle, QHeaderView::Fixed);
|
||||
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);
|
||||
|
||||
connect(m_gui->m_objectTree->selectionModel(),
|
||||
@@ -271,10 +278,12 @@ namespace AzToolsFramework
|
||||
ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
|
||||
GetEntityContextId());
|
||||
EditorEntityInfoNotificationBus::Handler::BusConnect();
|
||||
AZ::Interface<EntityOutlinerWidgetInterface>::Register(this);
|
||||
}
|
||||
|
||||
EntityOutlinerWidget::~EntityOutlinerWidget()
|
||||
{
|
||||
AZ::Interface<EntityOutlinerWidgetInterface>::Unregister(this);
|
||||
ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
|
||||
EditorEntityInfoNotificationBus::Handler::BusDisconnect();
|
||||
EditorPickModeNotificationBus::Handler::BusDisconnect();
|
||||
@@ -798,6 +807,8 @@ namespace AzToolsFramework
|
||||
#ifdef Q_OS_MAC
|
||||
// "Alt+Return" translates to Option+Return on macOS
|
||||
m_actionToRenameSelection->setShortcut(tr("Alt+Return"));
|
||||
#elseif Q_OS_WIN
|
||||
m_actionToRenameSelection->setShortcut(tr("F2"));
|
||||
#endif
|
||||
m_actionToRenameSelection->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||
connect(m_actionToRenameSelection, &QAction::triggered, this, &EntityOutlinerWidget::DoRenameSelection);
|
||||
@@ -860,6 +871,10 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::OnTreeItemDoubleClicked(const QModelIndex& /*index*/)
|
||||
{
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::OnTreeItemExpanded(const QModelIndex& index)
|
||||
{
|
||||
m_listModel->OnEntityExpanded(GetEntityIdFromIndex(index));
|
||||
@@ -1075,6 +1090,30 @@ namespace AzToolsFramework
|
||||
SetEntityOutlinerState(m_gui, true);
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::SetRootEntity(AZ::EntityId rootEntityId)
|
||||
{
|
||||
// The proxy model needs a tick to initialize, else it will return an invalid index in mapFromSource.
|
||||
QTimer::singleShot(0, this, [rootEntityId, this]() {
|
||||
QModelIndex rootIndex = m_listModel->GetIndexFromEntity(rootEntityId);
|
||||
QModelIndex proxyIndex = m_proxyModel->mapFromSource(rootIndex);
|
||||
m_gui->m_objectTree->setRootIndex(proxyIndex);
|
||||
});
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::SetUpdatesEnabled(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
QTimer::singleShot(1, this, [this]() {
|
||||
m_gui->m_objectTree->setUpdatesEnabled(true);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gui->m_objectTree->setUpdatesEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::OnEntityInfoUpdatedAddChildEnd(AZ::EntityId /*parentId*/, AZ::EntityId childId)
|
||||
{
|
||||
QueueContentUpdateSort(childId);
|
||||
|
||||
+9
-2
@@ -21,8 +21,9 @@
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/ToolsMessaging/EntityHighlightBus.h>
|
||||
#include <AzToolsFramework/UI/Outliner/EntityOutlinerSearchWidget.h>
|
||||
#include <AzToolsFramework/UI/Outliner/EntityOutlinerCacheBus.h>
|
||||
#include <AzToolsFramework/UI/Outliner/EntityOutlinerSearchWidget.h>
|
||||
#include <AzToolsFramework/UI/Outliner/EntityOutlinerWidgetInterface.h>
|
||||
#include <AzToolsFramework/UI/SearchWidget/SearchWidgetTypes.hxx>
|
||||
|
||||
#include <QIcon>
|
||||
@@ -60,12 +61,13 @@ namespace AzToolsFramework
|
||||
, private EditorEntityContextNotificationBus::Handler
|
||||
, private EditorEntityInfoNotificationBus::Handler
|
||||
, private ComponentModeFramework::EditorComponentModeNotificationBus::Handler
|
||||
, private EntityOutlinerWidgetInterface
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(EntityOutlinerWidget, AZ::SystemAllocator, 0)
|
||||
|
||||
EntityOutlinerWidget(QWidget* pParent = NULL, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
explicit EntityOutlinerWidget(QWidget* pParent = NULL, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
virtual ~EntityOutlinerWidget();
|
||||
|
||||
private Q_SLOTS:
|
||||
@@ -103,6 +105,10 @@ namespace AzToolsFramework
|
||||
void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
|
||||
// EntityOutlinerWidgetInterface
|
||||
void SetRootEntity(AZ::EntityId rootEntityId) override;
|
||||
void SetUpdatesEnabled(bool enable) override;
|
||||
|
||||
// Build a selection object from the given entities. Entities already in the Widget's selection buffers are ignored.
|
||||
template <class EntityIdCollection>
|
||||
QItemSelection BuildSelectionFromEntities(const EntityIdCollection& entityIds);
|
||||
@@ -138,6 +144,7 @@ namespace AzToolsFramework
|
||||
QAction* m_actionGoToEntitiesInViewport;
|
||||
|
||||
void OnTreeItemClicked(const QModelIndex& index);
|
||||
void OnTreeItemDoubleClicked(const QModelIndex& index);
|
||||
void OnTreeItemExpanded(const QModelIndex& index);
|
||||
void OnTreeItemCollapsed(const QModelIndex& index);
|
||||
void OnExpandEntity(const AZ::EntityId& entityId, bool expand);
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
class EntityOutlinerWidgetInterface
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(EntityOutlinerWidgetInterface, "{30C0F252-EC84-4196-BF59-EB9E73B8ADCB}");
|
||||
|
||||
virtual void SetRootEntity(AZ::EntityId rootEntityId) = 0;
|
||||
virtual void SetUpdatesEnabled(bool enable) = 0;
|
||||
};
|
||||
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Entity.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
{
|
||||
class PrefabInstanceContainerNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
virtual ~PrefabInstanceContainerNotifications() = default;
|
||||
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
|
||||
virtual void OnPrefabComponentActivate(AZ::EntityId entityId) = 0;
|
||||
virtual void OnPrefabComponentDeactivate(AZ::EntityId entityId) = 0;
|
||||
};
|
||||
using PrefabInstanceContainerNotificationBus = AZ::EBus<PrefabInstanceContainerNotifications>;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
{
|
||||
class PrefabIntegrationInterface
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(PrefabIntegrationInterface, "{B88AE045-7711-49BC-8336-45003D1C9116}");
|
||||
|
||||
/**
|
||||
* Create a new entity at the position provided.
|
||||
* @param position The position the new entity will be created at.
|
||||
* @param parentId The id of the parent of the newly created entity.
|
||||
* @return The id of the newly created entity.
|
||||
*/
|
||||
virtual AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) = 0;
|
||||
};
|
||||
|
||||
} // namespace Prefab
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+150
-47
@@ -16,6 +16,7 @@
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
|
||||
@@ -24,6 +25,8 @@
|
||||
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorLayerComponentBus.h>
|
||||
#include <AzToolsFramework/UI/EditorEntityUi/EditorEntityUiInterface.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFileDialog>
|
||||
@@ -36,6 +39,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
{
|
||||
EditorEntityUiInterface* PrefabIntegrationManager::s_editorEntityUiInterface = nullptr;
|
||||
PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr;
|
||||
PrefabEditInterface* PrefabIntegrationManager::s_prefabEditInterface = nullptr;
|
||||
const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab";
|
||||
@@ -54,8 +58,14 @@ namespace AzToolsFramework
|
||||
|
||||
PrefabIntegrationManager::PrefabIntegrationManager()
|
||||
{
|
||||
s_prefabPublicInterface = AZ::Interface<PrefabPublicInterface>::Get();
|
||||
s_editorEntityUiInterface = AZ::Interface<EditorEntityUiInterface>::Get();
|
||||
if (s_editorEntityUiInterface == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "Prefab - could not get EditorEntityUiInterface on PrefabIntegrationManager construction.");
|
||||
return;
|
||||
}
|
||||
|
||||
s_prefabPublicInterface = AZ::Interface<PrefabPublicInterface>::Get();
|
||||
if (s_prefabPublicInterface == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "Prefab - could not get PrefabPublicInterface on PrefabIntegrationManager construction.");
|
||||
@@ -63,7 +73,6 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
s_prefabEditInterface = AZ::Interface<PrefabEditInterface>::Get();
|
||||
|
||||
if (s_prefabEditInterface == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "Prefab - could not get PrefabEditInterface on PrefabIntegrationManager construction.");
|
||||
@@ -71,12 +80,32 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
EditorContextMenuBus::Handler::BusConnect();
|
||||
AssetBrowser::AssetBrowserSourceDropBus::Handler::BusConnect(s_prefabFileExtension);
|
||||
PrefabInstanceContainerNotificationBus::Handler::BusConnect();
|
||||
AZ::Interface<PrefabIntegrationInterface>::Register(this);
|
||||
|
||||
bool prefabWipFeaturesEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
prefabWipFeaturesEnabled, &AzFramework::ApplicationRequests::ArePrefabWipFeaturesEnabled);
|
||||
|
||||
if (prefabWipFeaturesEnabled)
|
||||
{
|
||||
AssetBrowser::AssetBrowserSourceDropBus::Handler::BusConnect(s_prefabFileExtension);
|
||||
}
|
||||
}
|
||||
|
||||
PrefabIntegrationManager::~PrefabIntegrationManager()
|
||||
{
|
||||
AssetBrowser::AssetBrowserSourceDropBus::Handler::BusDisconnect();
|
||||
bool prefabWipFeaturesEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
prefabWipFeaturesEnabled, &AzFramework::ApplicationRequests::ArePrefabWipFeaturesEnabled);
|
||||
|
||||
if (prefabWipFeaturesEnabled)
|
||||
{
|
||||
AssetBrowser::AssetBrowserSourceDropBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
AZ::Interface<PrefabIntegrationInterface>::Unregister(this);
|
||||
PrefabInstanceContainerNotificationBus::Handler::BusDisconnect();
|
||||
EditorContextMenuBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
@@ -97,57 +126,65 @@ namespace AzToolsFramework
|
||||
|
||||
void PrefabIntegrationManager::PopulateEditorGlobalContextMenu(QMenu* menu) const
|
||||
{
|
||||
// Create Prefab
|
||||
bool prefabWipFeaturesEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
prefabWipFeaturesEnabled, &AzFramework::ApplicationRequests::ArePrefabWipFeaturesEnabled);
|
||||
|
||||
if (prefabWipFeaturesEnabled)
|
||||
{
|
||||
AzToolsFramework::EntityIdList selectedEntities;
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(selectedEntities, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
|
||||
|
||||
if (!selectedEntities.empty())
|
||||
// Create Prefab
|
||||
{
|
||||
bool layerInSelection = false;
|
||||
AzToolsFramework::EntityIdList selectedEntities;
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
|
||||
selectedEntities, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
|
||||
|
||||
for (AZ::EntityId entityId : selectedEntities)
|
||||
if (!selectedEntities.empty())
|
||||
{
|
||||
if (!layerInSelection)
|
||||
{
|
||||
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
layerInSelection,
|
||||
entityId,
|
||||
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
|
||||
bool layerInSelection = false;
|
||||
|
||||
if (layerInSelection)
|
||||
for (AZ::EntityId entityId : selectedEntities)
|
||||
{
|
||||
if (!layerInSelection)
|
||||
{
|
||||
break;
|
||||
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
layerInSelection, entityId,
|
||||
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
|
||||
|
||||
if (layerInSelection)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Layers can't be in prefabs.
|
||||
if (!layerInSelection)
|
||||
{
|
||||
QAction* createAction = menu->addAction(QObject::tr("Create Prefab..."));
|
||||
createAction->setToolTip(QObject::tr("Creates a prefab out of the currently selected entities."));
|
||||
// Layers can't be in prefabs.
|
||||
if (!layerInSelection)
|
||||
{
|
||||
QAction* createAction = menu->addAction(QObject::tr("Create Prefab..."));
|
||||
createAction->setToolTip(QObject::tr("Creates a prefab out of the currently selected entities."));
|
||||
|
||||
QObject::connect(createAction, &QAction::triggered, createAction, [this, selectedEntities] {
|
||||
ContextMenu_CreatePrefab(selectedEntities);
|
||||
});
|
||||
QObject::connect(createAction, &QAction::triggered, createAction, [this, selectedEntities] {
|
||||
ContextMenu_CreatePrefab(selectedEntities);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate Prefab
|
||||
{
|
||||
QAction* instantiateAction = menu->addAction(QObject::tr("Instantiate Prefab..."));
|
||||
instantiateAction->setToolTip(QObject::tr("Instantiates a prefab file in the scene."));
|
||||
|
||||
QObject::connect(
|
||||
instantiateAction, &QAction::triggered, instantiateAction, [this] { ContextMenu_InstantiatePrefab(); });
|
||||
}
|
||||
|
||||
menu->addSeparator();
|
||||
}
|
||||
|
||||
// Instantiate Prefab
|
||||
{
|
||||
QAction* instantiateAction = menu->addAction(QObject::tr("Instantiate Prefab..."));
|
||||
instantiateAction->setToolTip(QObject::tr("Instantiates a prefab file in the scene."));
|
||||
bool itemWasShown = false;
|
||||
|
||||
QObject::connect(instantiateAction, &QAction::triggered, instantiateAction, [this] {
|
||||
ContextMenu_InstantiatePrefab();
|
||||
});
|
||||
}
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
// Edit Prefab
|
||||
// Edit/Save Prefab
|
||||
{
|
||||
AzToolsFramework::EntityIdList selectedEntities;
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
|
||||
@@ -159,17 +196,47 @@ namespace AzToolsFramework
|
||||
|
||||
if (s_prefabPublicInterface->IsInstanceContainerEntity(selectedEntity))
|
||||
{
|
||||
QAction* editAction = menu->addAction(QObject::tr("Edit Prefab"));
|
||||
editAction->setToolTip(QObject::tr("Edit the prefab in focus mode."));
|
||||
// Edit Prefab
|
||||
if (prefabWipFeaturesEnabled)
|
||||
{
|
||||
bool beingEdited = s_prefabEditInterface->IsOwningPrefabBeingEdited(selectedEntity);
|
||||
|
||||
QObject::connect(editAction, &QAction::triggered, editAction, [this, selectedEntity] {
|
||||
ContextMenu_EditPrefab(selectedEntity);
|
||||
});
|
||||
if (!beingEdited)
|
||||
{
|
||||
QAction* editAction = menu->addAction(QObject::tr("Edit Prefab"));
|
||||
editAction->setToolTip(QObject::tr("Edit the prefab in focus mode."));
|
||||
|
||||
QObject::connect(editAction, &QAction::triggered, editAction, [this, selectedEntity] {
|
||||
ContextMenu_EditPrefab(selectedEntity);
|
||||
});
|
||||
|
||||
itemWasShown = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Save Prefab
|
||||
AZ::IO::Path prefabFilePath = s_prefabPublicInterface->GetOwningInstancePrefabPath(selectedEntity);
|
||||
auto dirtyOutcome = s_prefabPublicInterface->HasUnsavedChanges(prefabFilePath);
|
||||
|
||||
if (dirtyOutcome.IsSuccess() && dirtyOutcome.GetValue() == true)
|
||||
{
|
||||
QAction* saveAction = menu->addAction(QObject::tr("Save Prefab to file"));
|
||||
saveAction->setToolTip(QObject::tr("Save the changes to the prefab to disk."));
|
||||
|
||||
QObject::connect(saveAction, &QAction::triggered, saveAction, [this, selectedEntity] {
|
||||
ContextMenu_SavePrefab(selectedEntity);
|
||||
});
|
||||
|
||||
itemWasShown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menu->addSeparator();
|
||||
if (itemWasShown)
|
||||
{
|
||||
menu->addSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabIntegrationManager::HandleSourceFileType(AZStd::string_view sourceFilePath, AZ::EntityId parentId, AZ::Vector3 position) const
|
||||
@@ -289,7 +356,18 @@ namespace AzToolsFramework
|
||||
{
|
||||
s_prefabEditInterface->EditOwningPrefab(containerEntity);
|
||||
}
|
||||
|
||||
|
||||
void PrefabIntegrationManager::ContextMenu_SavePrefab(AZ::EntityId containerEntity)
|
||||
{
|
||||
auto prefabPath = s_prefabPublicInterface->GetOwningInstancePrefabPath(containerEntity);
|
||||
|
||||
auto savePrefabOutcome = s_prefabPublicInterface->SavePrefab(prefabPath);
|
||||
|
||||
if (!savePrefabOutcome.IsSuccess())
|
||||
{
|
||||
WarnUserOfError("Prefab Save Error", savePrefabOutcome.GetError());
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabIntegrationManager::GenerateSuggestedFilenameFromEntities(const EntityIdList& entityIds, AZStd::string& outName)
|
||||
{
|
||||
@@ -891,5 +969,30 @@ namespace AzToolsFramework
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrefabIntegrationManager::OnPrefabComponentActivate(AZ::EntityId entityId)
|
||||
{
|
||||
s_editorEntityUiInterface->RegisterEntity(entityId, m_prefabUiHandler.GetHandlerId());
|
||||
}
|
||||
|
||||
void PrefabIntegrationManager::OnPrefabComponentDeactivate(AZ::EntityId entityId)
|
||||
{
|
||||
s_editorEntityUiInterface->UnregisterEntity(entityId);
|
||||
}
|
||||
|
||||
AZ::EntityId PrefabIntegrationManager::CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId)
|
||||
{
|
||||
Prefab::PrefabPublicInterface* prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
|
||||
auto createResult = prefabPublicInterface->CreateEntity(parentId, position);
|
||||
if (createResult.IsSuccess())
|
||||
{
|
||||
return createResult.GetValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
WarnUserOfError("Entity Creation Error", createResult.GetError());
|
||||
return AZ::EntityId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <AzToolsFramework/Editor/EditorContextMenuBus.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabEditManager.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationBus.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabUiHandler.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
@@ -45,6 +47,8 @@ namespace AzToolsFramework
|
||||
class PrefabIntegrationManager final
|
||||
: public EditorContextMenuBus::Handler
|
||||
, public AssetBrowser::AssetBrowserSourceDropBus::Handler
|
||||
, public PrefabInstanceContainerNotificationBus::Handler
|
||||
, public PrefabIntegrationInterface
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(PrefabIntegrationManager, AZ::SystemAllocator, 0);
|
||||
@@ -62,6 +66,13 @@ namespace AzToolsFramework
|
||||
// EntityOutlinerSourceDropHandlingBus...
|
||||
void HandleSourceFileType(AZStd::string_view sourceFilePath, AZ::EntityId parentId, AZ::Vector3 position) const override;
|
||||
|
||||
// PrefabInstanceContainerNotificationBus...
|
||||
void OnPrefabComponentActivate(AZ::EntityId entityId) override;
|
||||
void OnPrefabComponentDeactivate(AZ::EntityId entityId) override;
|
||||
|
||||
// PrefabIntegrationInterface...
|
||||
AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) override;
|
||||
|
||||
private:
|
||||
// Manages the Edit Mode UI for prefabs
|
||||
PrefabEditManager m_prefabEditManager;
|
||||
@@ -73,6 +84,7 @@ namespace AzToolsFramework
|
||||
static void ContextMenu_CreatePrefab(AzToolsFramework::EntityIdList selectedEntities);
|
||||
static void ContextMenu_InstantiatePrefab();
|
||||
static void ContextMenu_EditPrefab(AZ::EntityId containerEntity);
|
||||
static void ContextMenu_SavePrefab(AZ::EntityId containerEntity);
|
||||
|
||||
// Prompt and resolve dialogs
|
||||
static bool QueryUserForPrefabSaveLocation(
|
||||
@@ -109,6 +121,7 @@ namespace AzToolsFramework
|
||||
|
||||
static const AZStd::string s_prefabFileExtension;
|
||||
|
||||
static EditorEntityUiInterface* s_editorEntityUiInterface;
|
||||
static PrefabPublicInterface* s_prefabPublicInterface;
|
||||
static PrefabEditInterface* s_prefabEditInterface;
|
||||
};
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabUiHandler.h>
|
||||
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabEditInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||
#include <AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx>
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
@@ -23,6 +25,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
const QColor PrefabUiHandler::m_prefabCapsuleColor = QColor("#1E252F");
|
||||
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");
|
||||
|
||||
PrefabUiHandler::PrefabUiHandler()
|
||||
{
|
||||
@@ -33,6 +37,62 @@ namespace AzToolsFramework
|
||||
AZ_Assert(false, "PrefabUiHandler - could not get PrefabEditInterface on PrefabUiHandler construction.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
|
||||
|
||||
if (m_prefabPublicInterface == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "PrefabUiHandler - could not get PrefabPublicInterface on PrefabUiHandler construction.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QString PrefabUiHandler::GenerateItemInfoString(AZ::EntityId entityId) const
|
||||
{
|
||||
QString infoString;
|
||||
|
||||
AZ::IO::Path path = m_prefabPublicInterface->GetOwningInstancePrefabPath(entityId);
|
||||
|
||||
if (!path.empty())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
QString PrefabUiHandler::GenerateItemTooltip(AZ::EntityId entityId) const
|
||||
{
|
||||
QString tooltip;
|
||||
|
||||
AZ::IO::Path path = m_prefabPublicInterface->GetOwningInstancePrefabPath(entityId);
|
||||
|
||||
if (!path.empty())
|
||||
{
|
||||
tooltip = QObject::tr("%1").arg(path.Native().data());
|
||||
}
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
QPixmap PrefabUiHandler::GenerateItemIcon(AZ::EntityId entityId) const
|
||||
{
|
||||
if (m_prefabEditInterface->IsOwningPrefabBeingEdited(entityId))
|
||||
{
|
||||
return QPixmap(m_prefabEditIconPath);
|
||||
}
|
||||
|
||||
return QPixmap(m_prefabIconPath);
|
||||
}
|
||||
|
||||
void PrefabUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
@@ -57,40 +117,61 @@ namespace AzToolsFramework
|
||||
QPainterPath backgroundPath;
|
||||
backgroundPath.setFillRule(Qt::WindingFill);
|
||||
|
||||
QRect tempRect = option.rect;
|
||||
tempRect.setTop(tempRect.top() + 1);
|
||||
|
||||
if (!hasVisibleChildren)
|
||||
{
|
||||
tempRect.setBottom(tempRect.bottom() - 1);
|
||||
}
|
||||
|
||||
if (isFirstColumn)
|
||||
{
|
||||
tempRect.setLeft(tempRect.left() - 1);
|
||||
}
|
||||
|
||||
if (isLastColumn)
|
||||
{
|
||||
tempRect.setWidth(tempRect.width() - 1);
|
||||
}
|
||||
|
||||
if (isFirstColumn || isLastColumn)
|
||||
{
|
||||
// Rounded rect to have rounded borders on top
|
||||
backgroundPath.addRoundedRect(option.rect, m_prefabCapsuleRadius, m_prefabCapsuleRadius);
|
||||
backgroundPath.addRoundedRect(tempRect, m_prefabCapsuleRadius, m_prefabCapsuleRadius);
|
||||
|
||||
if (hasVisibleChildren)
|
||||
{
|
||||
// Regular rect, half height, to square the bottom borders
|
||||
QRect bottomRect = option.rect;
|
||||
QRect bottomRect = tempRect;
|
||||
bottomRect.setTop(bottomRect.top() + (bottomRect.height() / 2));
|
||||
backgroundPath.addRect(bottomRect);
|
||||
}
|
||||
|
||||
// Regular rect, half height, to square the opposite border
|
||||
QRect squareRect = option.rect;
|
||||
QRect squareRect = tempRect;
|
||||
if (isFirstColumn)
|
||||
{
|
||||
squareRect.setLeft(option.rect.left() + (option.rect.width() / 2));
|
||||
squareRect.setLeft(tempRect.left() + (tempRect.width() / 2));
|
||||
}
|
||||
else if (isLastColumn)
|
||||
{
|
||||
squareRect.setWidth(option.rect.width() / 2);
|
||||
squareRect.setWidth(tempRect.width() / 2);
|
||||
}
|
||||
backgroundPath.addRect(squareRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
backgroundPath.addRect(option.rect);
|
||||
backgroundPath.addRect(tempRect);
|
||||
}
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
painter->fillPath(backgroundPath.simplified(), backgroundColor);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void PrefabUiHandler::PaintDescendantForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
|
||||
void PrefabUiHandler::PaintDescendantBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
|
||||
const QModelIndex& descendantIndex) const
|
||||
{
|
||||
if (!painter)
|
||||
@@ -100,8 +181,15 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value<AZ::u64>());
|
||||
|
||||
// We hide the root instance container entity from the Outliner, so avoid drawing its full container on children
|
||||
if (m_prefabPublicInterface->IsLevelInstanceContainerEntity(entityId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const QTreeView* outlinerTreeView(qobject_cast<const QTreeView*>(option.widget));
|
||||
const int ancestorLeft = outlinerTreeView->visualRect(index).left() + (m_prefabBorderThickness / 2);
|
||||
const int ancestorLeft = outlinerTreeView->visualRect(index).left() + (m_prefabBorderThickness / 2) - 1;
|
||||
const int curveRectSize = m_prefabCapsuleRadius * 2;
|
||||
const bool isFirstColumn = descendantIndex.column() == EntityOutlinerListModel::ColumnName;
|
||||
const bool isLastColumn = descendantIndex.column() == EntityOutlinerListModel::ColumnLockToggle;
|
||||
@@ -117,12 +205,17 @@ namespace AzToolsFramework
|
||||
// Find the rect that extends fully to the left
|
||||
QRect fullRect = option.rect;
|
||||
fullRect.setLeft(ancestorLeft);
|
||||
if (isLastColumn)
|
||||
{
|
||||
fullRect.setWidth(fullRect.width() - 1);
|
||||
}
|
||||
|
||||
// Adjust option.rect to account for the border thickness
|
||||
QRect rect = option.rect;
|
||||
rect.setLeft(rect.left() + (m_prefabBorderThickness / 2));
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
painter->setPen(borderLinePen);
|
||||
|
||||
if (IsLastVisibleChild(index, descendantIndex))
|
||||
|
||||
@@ -13,10 +13,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabEditInterface.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
{
|
||||
class PrefabEditInterface;
|
||||
class PrefabPublicInterface;
|
||||
};
|
||||
|
||||
class PrefabUiHandler
|
||||
: public EditorEntityUiHandlerBase
|
||||
{
|
||||
@@ -28,11 +33,17 @@ namespace AzToolsFramework
|
||||
~PrefabUiHandler() override = default;
|
||||
|
||||
// EditorEntityUiHandler...
|
||||
QString GenerateItemInfoString(AZ::EntityId entityId) const override;
|
||||
QString GenerateItemTooltip(AZ::EntityId entityId) const override;
|
||||
QPixmap GenerateItemIcon(AZ::EntityId entityId) const override;
|
||||
void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
void PaintDescendantForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
|
||||
void PaintDescendantBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
|
||||
const QModelIndex& descendantIndex) const override;
|
||||
|
||||
private:
|
||||
Prefab::PrefabEditInterface* m_prefabEditInterface = nullptr;
|
||||
Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr;
|
||||
|
||||
static bool IsLastVisibleChild(const QModelIndex& parent, const QModelIndex& child);
|
||||
static QModelIndex GetLastVisibleChild(const QModelIndex& parent);
|
||||
static QModelIndex Internal_GetLastVisibleChild(const QAbstractItemModel* model, const QModelIndex& index);
|
||||
@@ -41,7 +52,7 @@ namespace AzToolsFramework
|
||||
static constexpr int m_prefabBorderThickness = 2;
|
||||
static const QColor m_prefabCapsuleColor;
|
||||
static const QColor m_prefabCapsuleEditColor;
|
||||
|
||||
Prefab::PrefabEditInterface* m_prefabEditInterface = nullptr;
|
||||
static const QString m_prefabIconPath;
|
||||
static const QString m_prefabEditIconPath;
|
||||
};
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+111
-21
@@ -31,6 +31,7 @@ AZ_POP_DISABLE_WARNING
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/std/sort.h>
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/Entity/EntityContextBus.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzQtComponents/Components/Style.h>
|
||||
@@ -47,6 +48,7 @@ AZ_POP_DISABLE_WARNING
|
||||
#include <AzToolsFramework/AssetBrowser/EBusFindAssetTypeByName.h>
|
||||
#include <AzToolsFramework/ComponentMode/ComponentModeDelegate.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||
#include <AzToolsFramework/Slice/SliceDataFlagsCommand.h>
|
||||
#include <AzToolsFramework/Slice/SliceMetadataEntityContextBus.h>
|
||||
#include <AzToolsFramework/Slice/SliceUtilities.h>
|
||||
@@ -331,8 +333,14 @@ namespace AzToolsFramework
|
||||
m_gui->m_entitySearchBox->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
AzQtComponents::LineEdit::applySearchStyle(m_gui->m_entitySearchBox);
|
||||
|
||||
QStandardItemModel*model = new QStandardItemModel(3, 1);
|
||||
for (int row = 0; row < 3; ++row)
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
m_prefabsAreEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
|
||||
m_itemNames =
|
||||
m_prefabsAreEnabled ? QStringList{"Universal", "Editor only"} : QStringList{"Start active", "Start inactive", "Editor only"};
|
||||
int itemNameCount = m_itemNames.size();
|
||||
QStandardItemModel* model = new QStandardItemModel(itemNameCount, 1);
|
||||
for (int row = 0; row < itemNameCount; ++row)
|
||||
{
|
||||
m_comboItems[row] = new QStandardItem(m_itemNames[row]);
|
||||
m_comboItems[row]->setCheckable(true);
|
||||
@@ -397,6 +405,8 @@ namespace AzToolsFramework
|
||||
CreateActions();
|
||||
UpdateContents();
|
||||
|
||||
m_prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
|
||||
|
||||
EditorEntityContextNotificationBus::Handler::BusConnect();
|
||||
|
||||
//forced to register global event filter with application for selection
|
||||
@@ -741,26 +751,42 @@ namespace AzToolsFramework
|
||||
isLayerEntity,
|
||||
selectedEntityId,
|
||||
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
|
||||
|
||||
bool isPrefabEntity = (m_prefabPublicInterface) ? m_prefabPublicInterface->IsInstanceContainerEntity(selectedEntityId) : false;
|
||||
|
||||
if (isLayerEntity)
|
||||
{
|
||||
if (result == SelectionEntityTypeInfo::None)
|
||||
{
|
||||
result = SelectionEntityTypeInfo::OnlyLayerEntities;
|
||||
}
|
||||
else if(result == SelectionEntityTypeInfo::OnlyStandardEntities)
|
||||
else if (result == SelectionEntityTypeInfo::OnlyStandardEntities)
|
||||
{
|
||||
result = SelectionEntityTypeInfo::Mixed;
|
||||
// An entity of both layer and non-layer type have been found, so break out of the loop.
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (isPrefabEntity)
|
||||
{
|
||||
if (result == SelectionEntityTypeInfo::None)
|
||||
{
|
||||
result = SelectionEntityTypeInfo::OnlyPrefabEntities;
|
||||
}
|
||||
else if (result == SelectionEntityTypeInfo::OnlyStandardEntities)
|
||||
{
|
||||
result = SelectionEntityTypeInfo::Mixed;
|
||||
// An entity of both prefab and non-prefab type have been found, so break out of the loop.
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result == SelectionEntityTypeInfo::None)
|
||||
{
|
||||
result = SelectionEntityTypeInfo::OnlyStandardEntities;
|
||||
}
|
||||
else if (result == SelectionEntityTypeInfo::OnlyLayerEntities)
|
||||
else if (result == SelectionEntityTypeInfo::OnlyLayerEntities || result == SelectionEntityTypeInfo::OnlyPrefabEntities)
|
||||
{
|
||||
result = SelectionEntityTypeInfo::Mixed;
|
||||
// An entity of both layer and non-layer type have been found, so break out of the loop.
|
||||
@@ -857,7 +883,7 @@ namespace AzToolsFramework
|
||||
entityDetailsVisible = true;
|
||||
entityDetailsLabelText = GetEntityDetailsLabelText();
|
||||
}
|
||||
else if (selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyLayerEntities)
|
||||
else if (selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyLayerEntities || selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyPrefabEntities)
|
||||
{
|
||||
// If a customer filter is not already in use, only show layer components.
|
||||
if (!m_customFilterSet)
|
||||
@@ -2477,9 +2503,10 @@ namespace AzToolsFramework
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& comboItem : m_comboItems)
|
||||
size_t comboItemCount = StatusTypeToIndex(StatusItems);
|
||||
for (size_t i=0; i<comboItemCount; ++i)
|
||||
{
|
||||
comboItem->setCheckState(Qt::Unchecked);
|
||||
m_comboItems[i]->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
|
||||
bool allActive = true;
|
||||
@@ -2519,26 +2546,41 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
if (m_prefabsAreEnabled)
|
||||
{
|
||||
if (allInactive)
|
||||
{
|
||||
AZ_Warning("Prefab", false, "All entities found to be inactive. This is an option that's not supported with Prefabs.");
|
||||
allInactive = false;
|
||||
allEditorOnly = true;
|
||||
}
|
||||
if (someInactive)
|
||||
{
|
||||
AZ_Warning("Prefab", false, "Some inactive entities found. This is an option that's not supported with Prefabs.");
|
||||
someInactive = false;
|
||||
}
|
||||
}
|
||||
|
||||
m_gui->m_statusComboBox->setItalic(false);
|
||||
if (allActive)
|
||||
{
|
||||
m_gui->m_statusComboBox->setHeaderOverride(m_itemNames[StatusType::StatusStartActive]);
|
||||
m_gui->m_statusComboBox->setCurrentIndex(StatusType::StatusStartActive);
|
||||
m_comboItems[StatusType::StatusStartActive]->setCheckState(Qt::Checked);
|
||||
m_gui->m_statusComboBox->setHeaderOverride(m_itemNames[StatusTypeToIndex(StatusType::StatusStartActive)]);
|
||||
m_gui->m_statusComboBox->setCurrentIndex(StatusTypeToIndex(StatusType::StatusStartActive));
|
||||
m_comboItems[StatusTypeToIndex(StatusType::StatusStartActive)]->setCheckState(Qt::Checked);
|
||||
}
|
||||
else
|
||||
if (allInactive)
|
||||
{
|
||||
m_gui->m_statusComboBox->setHeaderOverride(m_itemNames[StatusType::StatusStartInactive]);
|
||||
m_gui->m_statusComboBox->setCurrentIndex(StatusType::StatusStartInactive);
|
||||
m_comboItems[StatusType::StatusStartInactive]->setCheckState(Qt::Checked);
|
||||
m_gui->m_statusComboBox->setHeaderOverride(m_itemNames[StatusTypeToIndex(StatusType::StatusStartInactive)]);
|
||||
m_gui->m_statusComboBox->setCurrentIndex(StatusTypeToIndex(StatusType::StatusStartInactive));
|
||||
m_comboItems[StatusTypeToIndex(StatusType::StatusStartInactive)]->setCheckState(Qt::Checked);
|
||||
}
|
||||
else
|
||||
if (allEditorOnly)
|
||||
{
|
||||
m_gui->m_statusComboBox->setHeaderOverride(m_itemNames[StatusType::StatusEditorOnly]);
|
||||
m_gui->m_statusComboBox->setCurrentIndex(StatusType::StatusEditorOnly);
|
||||
m_comboItems[StatusType::StatusEditorOnly]->setCheckState(Qt::Checked);
|
||||
m_gui->m_statusComboBox->setHeaderOverride(m_itemNames[StatusTypeToIndex(StatusType::StatusEditorOnly)]);
|
||||
m_gui->m_statusComboBox->setCurrentIndex(StatusTypeToIndex(StatusType::StatusEditorOnly));
|
||||
m_comboItems[StatusTypeToIndex(StatusType::StatusEditorOnly)]->setCheckState(Qt::Checked);
|
||||
}
|
||||
else // Some marked active, some not
|
||||
{
|
||||
@@ -2546,15 +2588,15 @@ namespace AzToolsFramework
|
||||
m_gui->m_statusComboBox->setHeaderOverride("- Multiple selected -");
|
||||
if (someActive)
|
||||
{
|
||||
m_comboItems[StatusType::StatusStartActive]->setCheckState(Qt::PartiallyChecked);
|
||||
m_comboItems[StatusTypeToIndex(StatusType::StatusStartActive)]->setCheckState(Qt::PartiallyChecked);
|
||||
}
|
||||
if (someInactive)
|
||||
{
|
||||
m_comboItems[StatusType::StatusStartInactive]->setCheckState(Qt::PartiallyChecked);
|
||||
m_comboItems[StatusTypeToIndex(StatusType::StatusStartInactive)]->setCheckState(Qt::PartiallyChecked);
|
||||
}
|
||||
if (someEditorOnly)
|
||||
{
|
||||
m_comboItems[StatusType::StatusEditorOnly]->setCheckState(Qt::PartiallyChecked);
|
||||
m_comboItems[StatusTypeToIndex(StatusType::StatusEditorOnly)]->setCheckState(Qt::PartiallyChecked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2563,6 +2605,54 @@ namespace AzToolsFramework
|
||||
m_gui->m_statusComboBox->style()->polish(m_gui->m_statusComboBox);
|
||||
}
|
||||
|
||||
size_t EntityPropertyEditor::StatusTypeToIndex(StatusType statusType) const
|
||||
{
|
||||
if (m_prefabsAreEnabled)
|
||||
{
|
||||
switch (statusType)
|
||||
{
|
||||
case StatusStartActive:
|
||||
return 0;
|
||||
case StatusStartInactive:
|
||||
AZ_Assert(false, "StatusStartInactive is not supported when Prefabs are enabled.");
|
||||
return 0;
|
||||
case StatusEditorOnly:
|
||||
return 1;
|
||||
case StatusItems:
|
||||
return 2;
|
||||
default:
|
||||
AZ_Assert(false, "StatusType for EntityPropertyEditor is out of bounds.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return statusType;
|
||||
}
|
||||
}
|
||||
|
||||
EntityPropertyEditor::StatusType EntityPropertyEditor::IndexToStatusType(size_t index) const
|
||||
{
|
||||
if (m_prefabsAreEnabled)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return StatusStartActive;
|
||||
case 1:
|
||||
return StatusEditorOnly;
|
||||
default:
|
||||
AZ_Assert(index < StatusType::StatusItems, "Index for EntityPropertyEditor::IndexToStatusType is out of bounds");
|
||||
return StatusEditorOnly;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(index < StatusType::StatusItems, "Index for EntityPropertyEditor::IndexToStatusType is out of bounds");
|
||||
return aznumeric_cast<StatusType>(index);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityPropertyEditor::OnDisplayComponentEditorMenu(const QPoint& position)
|
||||
{
|
||||
if (m_disabled)
|
||||
@@ -3649,12 +3739,12 @@ namespace AzToolsFramework
|
||||
{
|
||||
ScopedUndoBatch undo("Change Status");
|
||||
|
||||
switch (index)
|
||||
switch (IndexToStatusType(index))
|
||||
{
|
||||
case StatusType::StatusStartActive:
|
||||
case StatusType::StatusStartInactive:
|
||||
{
|
||||
bool entityIsStartingActive = index == StatusType::StatusStartActive;
|
||||
bool entityIsStartingActive = index == StatusTypeToIndex(StatusType::StatusStartActive);
|
||||
|
||||
for (AZ::EntityId entityId : m_selectedEntityIds)
|
||||
{
|
||||
|
||||
+12
-1
@@ -68,6 +68,11 @@ namespace AzToolsFramework
|
||||
class ProductAssetBrowserEntry;
|
||||
}
|
||||
|
||||
namespace Prefab
|
||||
{
|
||||
class PrefabPublicInterface;
|
||||
};
|
||||
|
||||
namespace UndoSystem
|
||||
{
|
||||
class URSequencePoint;
|
||||
@@ -299,6 +304,7 @@ namespace AzToolsFramework
|
||||
None,
|
||||
OnlyStandardEntities,
|
||||
OnlyLayerEntities,
|
||||
OnlyPrefabEntities,
|
||||
Mixed,
|
||||
LevelEntity
|
||||
};
|
||||
@@ -480,9 +486,11 @@ namespace AzToolsFramework
|
||||
StatusItems
|
||||
};
|
||||
|
||||
QStringList m_itemNames{ "Start active","Start inactive","Editor only" };
|
||||
QStringList m_itemNames;
|
||||
|
||||
void UpdateStatusComboBox();
|
||||
size_t StatusTypeToIndex(StatusType statusType) const;
|
||||
StatusType IndexToStatusType(size_t index) const;
|
||||
|
||||
bool m_isBuildingProperties;
|
||||
|
||||
@@ -541,6 +549,9 @@ namespace AzToolsFramework
|
||||
QStandardItem* m_comboItems[StatusItems];
|
||||
EntityIdSet m_overrideSelectedEntityIds;
|
||||
|
||||
Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr;
|
||||
bool m_prefabsAreEnabled = false;
|
||||
|
||||
// When m_initiatingPropertyChangeNotification is set to true, it means this EntityPropertyEditor is
|
||||
// broadcasting a change to all listeners about a property change for a given entity. This is needed
|
||||
// so that we don't update the values twice for this inspector
|
||||
|
||||
+3
-5
@@ -53,7 +53,7 @@ AZ_POP_DISABLE_WARNING
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailWidget.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailContext.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Thumbnails/ProductThumbnail.h>
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
|
||||
@@ -1093,13 +1093,11 @@ namespace AzToolsFramework
|
||||
AZ::Data::AssetType assetType;
|
||||
const AZStd::string platformName = ""; // Empty for default
|
||||
AZStd::string rootFilePath;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetAssetInfoById,
|
||||
assetID, assetType, platformName, assetInfo, rootFilePath);
|
||||
AssetSystemRequestBus::BroadcastResult(result, &AssetSystemRequestBus::Events::GetAssetInfoById, assetID, assetType, platformName, assetInfo, rootFilePath);
|
||||
|
||||
if (result)
|
||||
{
|
||||
AZStd::string fullSourcePath = AZStd::string::format("%s/%s", rootFilePath.c_str(), assetInfo.m_relativePath.c_str());
|
||||
SharedThumbnailKey thumbnailKey = MAKE_TKEY(AzToolsFramework::AssetBrowser::SourceThumbnailKey, fullSourcePath.c_str());
|
||||
SharedThumbnailKey thumbnailKey = MAKE_TKEY(AzToolsFramework::AssetBrowser::ProductThumbnailKey, assetID);
|
||||
m_thumbnail->SetThumbnailKey(thumbnailKey, Thumbnailer::ThumbnailContext::DefaultContext);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user