LYN-8631 + LYN-8632 | Display appropriate read-only icons and procedural prefabs ui in the Outliner (#6160)

* First step of procedural prefab styling and read-only registration.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* WIP - Introduce read-only handler for procedural prefabs (not hooked up)

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Introduce read-only entity interface, handler and unit tests.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Introduce temp read-only icon, use new icon hierarchy in Outliner.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Switch from a push paradigm to a pull paradigm - handlers get to implement logic to determine if an entity should be read-only. This allows multiple systems to weigh into whether an entity is read-only.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Fixed to missing call in test

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Post-rebase fixes to class name changes

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Display a lock icon on top of the entity icon in the Entity Outliner. This icon is added programmatically, which prevents having to alter all Outliner icons and future-proofs this functionality.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Minor style changes to procedural prefabs in the Outliner (use white icon)

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Ensure cache is refreshed when the handler is created, and also whenever the focus changes.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Remove Procedural Prefab setreg that was added in the wrong place

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Remove redundant function

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Fix spacing issue caused by rebase

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Change tooltip so that it accurately says "inspect" instead of "edit" for procedural prefabs.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>

* Address minor styling issues mentioned in PR.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
This commit is contained in:
Danilo Aimini
2021-12-06 12:16:16 -08:00
committed by GitHub
parent d583256b17
commit 476e66d902
21 changed files with 325 additions and 38 deletions
@@ -37,9 +37,9 @@ namespace AzToolsFramework
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
// ReadOnlyEntityPublicNotifications overrides ...
// ReadOnlyEntityPublicInterface overrides ...
bool IsReadOnly(const AZ::EntityId& entityId) override;
// ReadOnlyEntityQueryInterface overrides ...
void RefreshReadOnlyState(const EntityIdList& entityIds) override;
void RefreshReadOnlyStateForAllEntities() override;
@@ -12,6 +12,7 @@
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusNotificationBus.h>
@@ -74,6 +75,13 @@ namespace AzToolsFramework::Prefab
"Prefab - PrefabFocusHandler - "
"Focus Mode Interface could not be found. "
"Check that it is being correctly initialized.");
m_readOnlyEntityQueryInterface = AZ::Interface<ReadOnlyEntityQueryInterface>::Get();
AZ_Assert(
m_readOnlyEntityQueryInterface,
"Prefab - PrefabFocusHandler - "
"ReadOnly Entity Query Interface could not be found. "
"Check that it is being correctly initialized.");
}
PrefabFocusOperationResult PrefabFocusHandler::FocusOnOwningPrefab(AZ::EntityId entityId)
@@ -186,6 +194,8 @@ namespace AzToolsFramework::Prefab
// Close all container entities in the old path.
CloseInstanceContainers(m_instanceFocusHierarchy);
AZ::EntityId previousContainerEntityId = m_focusedInstanceContainerEntityId;
// Do not store the container for the root instance, use an invalid EntityId instead.
m_focusedInstanceContainerEntityId = focusedInstance->get().GetParentInstance().has_value() ? focusedInstance->get().GetContainerEntityId() : AZ::EntityId();
m_focusedTemplateId = focusedInstance->get().GetTemplateId();
@@ -201,6 +211,12 @@ namespace AzToolsFramework::Prefab
m_focusModeInterface->SetFocusRoot(containerEntityId);
}
// Refresh the read-only cache, if the interface is initialized.
if (m_readOnlyEntityQueryInterface)
{
m_readOnlyEntityQueryInterface->RefreshReadOnlyState({ previousContainerEntityId, m_focusedInstanceContainerEntityId });
}
// Refresh path variables.
RefreshInstanceFocusList();
RefreshInstanceFocusPath();
@@ -22,6 +22,7 @@ namespace AzToolsFramework
{
class ContainerEntityInterface;
class FocusModeInterface;
class ReadOnlyEntityQueryInterface;
}
namespace AzToolsFramework::Prefab
@@ -93,6 +94,7 @@ namespace AzToolsFramework::Prefab
ContainerEntityInterface* m_containerEntityInterface = nullptr;
FocusModeInterface* m_focusModeInterface = nullptr;
InstanceEntityMapperInterface* m_instanceEntityMapperInterface = nullptr;
ReadOnlyEntityQueryInterface* m_readOnlyEntityQueryInterface = nullptr;
};
} // namespace AzToolsFramework::Prefab
@@ -918,6 +918,18 @@ namespace AzToolsFramework
}
}
bool PrefabPublicHandler::IsOwnedByProceduralPrefabInstance(AZ::EntityId entityId) const
{
if (InstanceOptionalReference instanceReference = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
instanceReference.has_value())
{
TemplateReference templateReference = m_prefabSystemComponentInterface->FindTemplate(instanceReference->get().GetTemplateId());
return (templateReference.has_value()) && (templateReference->get().IsProcedural());
}
return false;
}
bool PrefabPublicHandler::IsInstanceContainerEntity(AZ::EntityId entityId) const
{
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
@@ -54,6 +54,7 @@ namespace AzToolsFramework
PrefabOperationResult GenerateUndoNodesForEntityChangeAndUpdateCache(AZ::EntityId entityId, UndoSystem::URSequencePoint* parentUndoBatch) override;
bool IsOwnedByProceduralPrefabInstance(AZ::EntityId entityId) const override;
bool IsInstanceContainerEntity(AZ::EntityId entityId) const override;
bool IsLevelInstanceContainerEntity(AZ::EntityId entityId) const override;
AZ::EntityId GetInstanceContainerEntityId(AZ::EntityId entityId) const override;
@@ -101,6 +101,13 @@ namespace AzToolsFramework
*/
virtual PrefabOperationResult GenerateUndoNodesForEntityChangeAndUpdateCache(
AZ::EntityId entityId, UndoSystem::URSequencePoint* parentUndoBatch) = 0;
/**
* Detects if an entity is owned by a procedural prefab.
* @param entityId The entity to query.
* @return True if the entity is owned by a procedural prefab instance, false otherwise.
*/
virtual bool IsOwnedByProceduralPrefabInstance(AZ::EntityId entityId) const = 0;
/**
* Detects if an entity is the container entity for its owning prefab instance.
@@ -47,6 +47,7 @@
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
#include <AzToolsFramework/ToolsComponents/ComponentAssetMimeDataContainer.h>
#include <AzToolsFramework/ToolsComponents/ComponentMimeData.h>
@@ -313,7 +314,7 @@ namespace AzToolsFramework
if (isEditorOnly)
{
return QIcon(QString(":/Icons/Entity_Editor_Only.svg"));
return QIcon(QString(":/Entity/entity_editoronly.svg"));
}
AZ::Entity* entity = nullptr;
@@ -322,10 +323,10 @@ namespace AzToolsFramework
if (!isInitiallyActive)
{
return QIcon(QString(":/Icons/Entity_Not_Active.svg"));
return QIcon(QString(":/Entity/entity_notactive.svg"));
}
return QIcon(QString(":/Icons/Entity.svg"));
return QIcon(QString(":/Entity/entity.svg"));
}
QVariant EntityOutlinerListModel::GetEntityTooltip(const AZ::EntityId& id) const
@@ -1994,9 +1995,13 @@ namespace AzToolsFramework
, m_lockCheckBoxes(parent, "Lock", EntityOutlinerListModel::PartiallyLockedRole, EntityOutlinerListModel::LockedAncestorRole)
{
m_editorEntityFrameworkInterface = AZ::Interface<AzToolsFramework::EditorEntityUiInterface>::Get();
AZ_Assert((m_editorEntityFrameworkInterface != nullptr),
"EntityOutlinerItemDelegate requires a EditorEntityFrameworkInterface instance on Construction.");
m_readOnlyEntityPublicInterface = AZ::Interface<AzToolsFramework::ReadOnlyEntityPublicInterface>::Get();
AZ_Assert(
(m_readOnlyEntityPublicInterface != nullptr),
"EntityOutlinerItemDelegate requires a ReadOnlyEntityPublicInterface instance on Construction.");
}
EntityOutlinerItemDelegate::CheckboxGroup::CheckboxGroup(QWidget* parent, AZStd::string prefix,
@@ -2108,6 +2113,12 @@ namespace AzToolsFramework
}
PaintEntityNameAsRichText(painter, customOption, index);
// Paint Read-Only icon if necessary
if (m_readOnlyEntityPublicInterface->IsReadOnly(entityId))
{
PaintReadOnlyIcon(painter, option, index);
}
}
break;
default:
@@ -2166,10 +2177,10 @@ namespace AzToolsFramework
backgroundPath.addRect(backgroundRect);
QColor backgroundColor = m_hoverColor;
QColor backgroundColor = s_hoverColor;
if (isSelected)
{
backgroundColor = m_selectedColor;
backgroundColor = s_selectedColor;
}
painter->fillPath(backgroundPath, backgroundColor);
@@ -2336,6 +2347,20 @@ namespace AzToolsFramework
EntityOutlinerListModel::s_paintingName = false;
}
void EntityOutlinerItemDelegate::PaintReadOnlyIcon(QPainter* painter, const QStyleOptionViewItem& option, [[maybe_unused]] const QModelIndex& index) const
{
// Build the rect that will be used to paint the icon
QRect readOnlyRect = QRect(option.rect.topLeft() + s_readOnlyOffset, QSize(s_readOnlyRadius * 2, s_readOnlyRadius * 2));
painter->save();
painter->setRenderHint(QPainter::Antialiasing, true);
painter->setPen(Qt::NoPen);
painter->setBrush(s_readOnlyBackgroundColor);
painter->drawEllipse(readOnlyRect.center(), s_readOnlyRadius, s_readOnlyRadius);
s_readOnlyIcon.paint(painter, readOnlyRect);
painter->restore();
}
QSize EntityOutlinerItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const
{
// Get the height of a tall character...
@@ -38,6 +38,7 @@ namespace AzToolsFramework
{
class EditorEntityUiInterface;
class FocusModeInterface;
class ReadOnlyEntityPublicInterface;
namespace EntityOutliner
{
@@ -344,6 +345,9 @@ namespace AzToolsFramework
// Paint the entity name using rich text
void PaintEntityNameAsRichText(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
// Paint the read-only icon on the entity
void PaintReadOnlyIcon(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
struct CheckboxGroup
{
EntityOutlinerCheckBox m_default;
@@ -372,10 +376,17 @@ namespace AzToolsFramework
// this is a cache, and is hence mutable
mutable QRect m_cachedBoundingRectOfTallCharacter;
const QColor m_selectedColor = QColor(255, 255, 255, 45);
const QColor m_hoverColor = QColor(255, 255, 255, 30);
inline static const QColor s_selectedColor = QColor(255, 255, 255, 45);
inline static const QColor s_hoverColor = QColor(255, 255, 255, 30);
inline static const QColor s_readOnlyBackgroundColor = QColor("#444444");
inline static const QPoint s_readOnlyOffset = QPoint(10, 10);
inline static const int s_readOnlyRadius = 6;
QIcon s_readOnlyIcon = QIcon(QString(":/Entity/readonly.svg"));
EditorEntityUiInterface* m_editorEntityFrameworkInterface = nullptr;
ReadOnlyEntityPublicInterface* m_readOnlyEntityPublicInterface = nullptr;
};
}
@@ -27,6 +27,7 @@
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
#include <AzToolsFramework/Prefab/Instance/InstanceToTemplateInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
@@ -1264,7 +1265,14 @@ namespace AzToolsFramework
}
else
{
s_editorEntityUiInterface->RegisterEntity(entityId, m_prefabUiHandler.GetHandlerId());
if (s_prefabPublicInterface->IsOwnedByProceduralPrefabInstance(entityId))
{
s_editorEntityUiInterface->RegisterEntity(entityId, m_proceduralPrefabUiHandler.GetHandlerId());
}
else
{
s_editorEntityUiInterface->RegisterEntity(entityId, m_prefabUiHandler.GetHandlerId());
}
// Register entity as a container
s_containerEntityInterface->RegisterEntityAsContainer(entityId);
@@ -18,10 +18,11 @@
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
#include <AzToolsFramework/UI/Prefab/LevelRootUiHandler.h>
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationBus.h>
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h>
#include <AzToolsFramework/UI/Prefab/PrefabUiHandler.h>
#include <AzToolsFramework/UI/Prefab/Procedural/ProceduralPrefabReadOnlyHandler.h>
#include <AzToolsFramework/UI/Prefab/Procedural/ProceduralPrefabUiHandler.h>
#include <AzQtComponents/Components/Widgets/Card.h>
@@ -92,12 +93,18 @@ namespace AzToolsFramework
void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) override;
private:
// Used to handle the UI for the level root
// Used to handle the UI for the level root.
LevelRootUiHandler m_levelRootUiHandler;
// Used to handle the UI for prefab entities
// Used to handle the UI for prefab entities.
PrefabUiHandler m_prefabUiHandler;
// Used to handle the UI for procedural prefab entities.
ProceduralPrefabUiHandler m_proceduralPrefabUiHandler;
// Ensures entities owned by procedural prefab instances are marked as read-only correctly.
ProceduralPrefabReadOnlyHandler m_proceduralPrefabReadOnlyHandler;
// Context menu item handlers
static void ContextMenu_CreatePrefab(AzToolsFramework::EntityIdList selectedEntities);
static void ContextMenu_InstantiatePrefab();
@@ -23,17 +23,6 @@ namespace AzToolsFramework
{
AzFramework::EntityContextId PrefabUiHandler::s_editorEntityContextId = AzFramework::EntityContextId::CreateNull();
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()
{
m_prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
@@ -46,7 +46,7 @@ namespace AzToolsFramework
void OnOutlinerItemCollapse(const QModelIndex& index) const override;
bool OnEntityDoubleClick(AZ::EntityId entityId) const override;
private:
protected:
Prefab::PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr;
@@ -56,17 +56,17 @@ namespace AzToolsFramework
static AzFramework::EntityContextId s_editorEntityContextId;
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;
int m_prefabCapsuleRadius = 6;
int m_prefabBorderThickness = 2;
QColor m_backgroundColor = QColor("#444444");
QColor m_backgroundHoverColor = QColor("#5A5A5A");
QColor m_backgroundSelectedColor = QColor("#656565");
QColor m_prefabCapsuleColor = QColor("#1E252F");
QColor m_prefabCapsuleDisabledColor = QColor("#35383C");
QColor m_prefabCapsuleEditColor = QColor("#4A90E2");
QString m_prefabIconPath = QString(":/Entity/prefab.svg");
QString m_prefabEditIconPath = QString(":/Entity/prefab_edit.svg");
QString m_prefabEditOpenIconPath = QString(":/Entity/prefab_edit_open.svg");
QString m_prefabEditCloseIconPath = QString(":/Entity/prefab_edit_close.svg");
};
} // namespace AzToolsFramework
@@ -0,0 +1,68 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/UI/Prefab/Procedural/ProceduralPrefabReadOnlyHandler.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
namespace AzToolsFramework
{
namespace Prefab
{
ProceduralPrefabReadOnlyHandler::ProceduralPrefabReadOnlyHandler()
{
m_prefabPublicInterface = AZ::Interface<PrefabPublicInterface>::Get();
AZ_Assert(
m_prefabPublicInterface != nullptr,
"ProceduralPrefabReadOnlyHandler requires a PrefabPublicInterface instance on Initialize.");
m_prefabFocusPublicInterface = AZ::Interface<PrefabFocusPublicInterface>::Get();
AZ_Assert(
m_prefabFocusPublicInterface != nullptr,
"ProceduralPrefabReadOnlyHandler requires a PrefabFocusPublicInterface instance on Initialize.");
AzFramework::EntityContextId editorEntityContextId = AzFramework::EntityContextId::CreateNull();
EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
ReadOnlyEntityQueryRequestBus::Handler::BusConnect(editorEntityContextId);
// Refresh the whole read-only cache
if (auto readOnlyEntityQueryInterface = AZ::Interface<ReadOnlyEntityQueryInterface>::Get())
{
readOnlyEntityQueryInterface->RefreshReadOnlyStateForAllEntities();
}
}
ProceduralPrefabReadOnlyHandler ::~ProceduralPrefabReadOnlyHandler()
{
ReadOnlyEntityQueryRequestBus::Handler::BusDisconnect();
}
void ProceduralPrefabReadOnlyHandler::IsReadOnly(const AZ::EntityId& entityId, bool& isReadOnly)
{
if(m_prefabPublicInterface->IsOwnedByProceduralPrefabInstance(entityId))
{
// All entities nested inside a procedural prefabs should always be marked as read-only.
if (!m_prefabPublicInterface->IsInstanceContainerEntity(entityId))
{
isReadOnly = true;
}
// The container entity of a procedural prefab should only be marked as read-only when the prefab is being edited.
if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
{
isReadOnly = true;
}
}
}
} // namespace Prefab
} // namespace AzToolsFramework
@@ -0,0 +1,43 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityBus.h>
namespace AzToolsFramework
{
namespace Prefab
{
class PrefabFocusPublicInterface;
class PrefabPublicInterface;
//! Ensures entities in a procedural prefab are correctly reported as read-only.
class ProceduralPrefabReadOnlyHandler
: public ReadOnlyEntityQueryRequestBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(ProceduralPrefabReadOnlyHandler, AZ::SystemAllocator, 0);
AZ_RTTI(AzToolsFramework::ProceduralPrefabReadOnlyHandler, "{A2D72461-8CA3-45EE-81D2-4976BC0B6AE9}");
ProceduralPrefabReadOnlyHandler();
~ProceduralPrefabReadOnlyHandler() override;
// ReadOnlyEntityQueryRequestBus overrides ...
void IsReadOnly(const AZ::EntityId& entityId, bool& isReadOnly) override;
private:
PrefabPublicInterface* m_prefabPublicInterface = nullptr;
PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
};
} // namespace Prefab
} // namespace AzToolsFramework
@@ -0,0 +1,32 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/UI/Prefab/Procedural/ProceduralPrefabUiHandler.h>
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
namespace AzToolsFramework
{
ProceduralPrefabUiHandler::ProceduralPrefabUiHandler()
{
m_prefabCapsuleColor = QColor("#361561");
m_prefabCapsuleDisabledColor = QColor("#4B3455");
m_prefabCapsuleEditColor = QColor("#361561");
m_prefabIconPath = QString(":/Entity/prefab_edit.svg");
m_prefabEditOpenIconPath = QString(":/Entity/prefab_edit_open_readonly.svg");
}
QString ProceduralPrefabUiHandler::GenerateItemTooltip(AZ::EntityId entityId) const
{
if (AZ::IO::Path path = m_prefabPublicInterface->GetOwningInstancePrefabPath(entityId); !path.empty())
{
return QObject::tr("Double click to inspect.\n%1").arg(path.Native().data());
}
return QString();
}
}
@@ -0,0 +1,36 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzToolsFramework/UI/Prefab/PrefabUiHandler.h>
#include <AzFramework/Entity/EntityContextBus.h>
namespace AzToolsFramework
{
namespace Prefab
{
class PrefabFocusPublicInterface;
class PrefabPublicInterface;
};
//! Implements the Editor UI for Procedural Prefabs.
class ProceduralPrefabUiHandler
: public PrefabUiHandler
{
public:
AZ_CLASS_ALLOCATOR(ProceduralPrefabUiHandler, AZ::SystemAllocator, 0);
AZ_RTTI(AzToolsFramework::ProceduralPrefabUiHandler, "{3A3DF9FF-9C2E-4439-B7B4-72173B5A3502}", PrefabUiHandler);
ProceduralPrefabUiHandler();
~ProceduralPrefabUiHandler() override = default;
QString GenerateItemTooltip(AZ::EntityId entityId) const override;
};
} // namespace AzToolsFramework
@@ -768,6 +768,10 @@ set(FILES
UI/Prefab/PrefabUiHandler.cpp
UI/Prefab/PrefabViewportFocusPathHandler.h
UI/Prefab/PrefabViewportFocusPathHandler.cpp
UI/Prefab/Procedural/ProceduralPrefabReadOnlyHandler.h
UI/Prefab/Procedural/ProceduralPrefabReadOnlyHandler.cpp
UI/Prefab/Procedural/ProceduralPrefabUiHandler.h
UI/Prefab/Procedural/ProceduralPrefabUiHandler.cpp
UI/Notifications/ToastNotificationsView.cpp
UI/Notifications/ToastNotificationsView.h
UI/Notifications/ToastBus.h
@@ -96,4 +96,22 @@ namespace AzToolsFramework
// Verify the child entity is no longer marked as read-only
EXPECT_FALSE(m_readOnlyEntityPublicInterface->IsReadOnly(m_entityMap[ChildEntityName]));
}
TEST_F(ReadOnlyEntityFixture, EnsureCacheIsClearedCorrectlyEvenIfUnchanged)
{
// Create a handler that sets all entities to read-only.
ReadOnlyHandlerAlwaysTrue alwaysTrueHandler;
{
// Create a handler that sets the child entity to read-only.
ReadOnlyHandlerEntityId entityIdHandler(m_entityMap[ChildEntityName]);
// Verify the child entity is marked as read-only
EXPECT_TRUE(m_readOnlyEntityPublicInterface->IsReadOnly(m_entityMap[ChildEntityName]));
}
// When the handler goes out of scope, it calls RefreshReadOnlyStateForAllEntities and refreshes the cache.
// Verify the child entity is still marked as read-only
EXPECT_TRUE(m_readOnlyEntityPublicInterface->IsReadOnly(m_entityMap[ChildEntityName]));
}
}