LYN-7539 + LYN-7541 | Focus Mode - Show prefab names and dirty markers instead of instance names in breadcrumbs (#4850)

* Change Prefab Focus breadcrumb widget to display template filename instead of instance container entity name. Also display dirty state for the template (*) and refresh it in real time.

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

* Streamline path creation code; fix stem retrieval to ensure extension is cut correctly; delay refresh one frame when path is clicked to correctly refresh it.

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

* Remove test code.

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

* Simplify code to use Native directly.

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

* Minor variable renaming and comment adjustments to make them clearer.

Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
This commit is contained in:
Danilo Aimini
2021-10-22 12:37:43 -07:00
committed by GitHub
parent 243532c5de
commit 45926d0dbd
5 changed files with 68 additions and 14 deletions
@@ -16,6 +16,7 @@
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h> #include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusNotificationBus.h> #include <AzToolsFramework/Prefab/PrefabFocusNotificationBus.h>
#include <AzToolsFramework/Prefab/PrefabFocusUndo.h> #include <AzToolsFramework/Prefab/PrefabFocusUndo.h>
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
namespace AzToolsFramework::Prefab namespace AzToolsFramework::Prefab
{ {
@@ -79,7 +80,7 @@ namespace AzToolsFramework::Prefab
auto editUndo = aznew PrefabFocusUndo("Edit Prefab"); auto editUndo = aznew PrefabFocusUndo("Edit Prefab");
editUndo->Capture(entityId); editUndo->Capture(entityId);
editUndo->SetParent(undoBatch.GetUndoBatch()); editUndo->SetParent(undoBatch.GetUndoBatch());
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, editUndo); FocusOnPrefabInstanceOwningEntityId(entityId);
} }
return AZ::Success(); return AZ::Success();
@@ -94,9 +95,7 @@ namespace AzToolsFramework::Prefab
InstanceOptionalReference focusedInstance = m_instanceFocusHierarchy[index]; InstanceOptionalReference focusedInstance = m_instanceFocusHierarchy[index];
FocusOnOwningPrefab(focusedInstance->get().GetContainerEntityId()); return FocusOnOwningPrefab(focusedInstance->get().GetContainerEntityId());
return AZ::Success();
} }
PrefabFocusOperationResult PrefabFocusHandler::FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId) PrefabFocusOperationResult PrefabFocusHandler::FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId)
@@ -255,7 +254,7 @@ namespace AzToolsFramework::Prefab
void PrefabFocusHandler::OnEntityInfoUpdatedName(AZ::EntityId entityId, [[maybe_unused]]const AZStd::string& name) void PrefabFocusHandler::OnEntityInfoUpdatedName(AZ::EntityId entityId, [[maybe_unused]]const AZStd::string& name)
{ {
// Determine if the entityId is the container for any of the instances in the vector // Determine if the entityId is the container for any of the instances in the vector.
auto result = AZStd::find_if( auto result = AZStd::find_if(
m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end(), m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end(),
[entityId](const InstanceOptionalReference& instance) [entityId](const InstanceOptionalReference& instance)
@@ -279,6 +278,25 @@ namespace AzToolsFramework::Prefab
PrefabFocusNotificationBus::Broadcast(&PrefabFocusNotifications::OnPrefabFocusChanged); PrefabFocusNotificationBus::Broadcast(&PrefabFocusNotifications::OnPrefabFocusChanged);
} }
void PrefabFocusHandler::OnPrefabTemplateDirtyFlagUpdated(TemplateId templateId, [[maybe_unused]] bool status)
{
// Determine if the templateId matches any of the instances in the vector.
auto result = AZStd::find_if(
m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end(),
[templateId](const InstanceOptionalReference& instance)
{
return (instance->get().GetTemplateId() == templateId);
}
);
if (result != m_instanceFocusHierarchy.end())
{
// Refresh the path and notify changes.
RefreshInstanceFocusPath();
PrefabFocusNotificationBus::Broadcast(&PrefabFocusNotifications::OnPrefabFocusChanged);
}
}
void PrefabFocusHandler::RefreshInstanceFocusList() void PrefabFocusHandler::RefreshInstanceFocusList()
{ {
m_instanceFocusHierarchy.clear(); m_instanceFocusHierarchy.clear();
@@ -293,17 +311,42 @@ namespace AzToolsFramework::Prefab
currentInstance = currentInstance->get().GetParentInstance(); currentInstance = currentInstance->get().GetParentInstance();
} }
// Invert the vector, since we need the top instance to be at index 0 // Invert the vector, since we need the top instance to be at index 0.
AZStd::reverse(m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end()); AZStd::reverse(m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end());
} }
void PrefabFocusHandler::RefreshInstanceFocusPath() void PrefabFocusHandler::RefreshInstanceFocusPath()
{ {
auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
m_instanceFocusPath.clear(); m_instanceFocusPath.clear();
size_t index = 0;
size_t maxIndex = m_instanceFocusHierarchy.size() - 1;
for (const InstanceOptionalReference& instance : m_instanceFocusHierarchy) for (const InstanceOptionalReference& instance : m_instanceFocusHierarchy)
{ {
m_instanceFocusPath.Append(instance->get().GetContainerEntity()->get().GetName()); AZStd::string prefabName;
if (index < maxIndex)
{
// Get the filename without the extension (stem).
prefabName = instance->get().GetTemplateSourcePath().Stem().Native();
}
else
{
// Get the full filename.
prefabName = instance->get().GetTemplateSourcePath().Filename().Native();
}
if (prefabSystemComponentInterface->IsTemplateDirty(instance->get().GetTemplateId()))
{
prefabName += "*";
}
m_instanceFocusPath.Append(prefabName);
++index;
} }
} }
@@ -64,8 +64,9 @@ namespace AzToolsFramework::Prefab
void OnEntityInfoUpdatedName(AZ::EntityId entityId, const AZStd::string& name) override; void OnEntityInfoUpdatedName(AZ::EntityId entityId, const AZStd::string& name) override;
// PrefabPublicNotifications overrides ... // PrefabPublicNotifications overrides ...
void OnPrefabInstancePropagationEnd(); void OnPrefabInstancePropagationEnd() override;
void OnPrefabTemplateDirtyFlagUpdated(TemplateId templateId, bool status) override;
private: private:
PrefabFocusOperationResult FocusOnPrefabInstance(InstanceOptionalReference focusedInstance); PrefabFocusOperationResult FocusOnPrefabInstance(InstanceOptionalReference focusedInstance);
void RefreshInstanceFocusList(); void RefreshInstanceFocusList();
@@ -9,6 +9,7 @@
#pragma once #pragma once
#include <AzCore/EBus/EBus.h> #include <AzCore/EBus/EBus.h>
#include <AzToolsFramework/Prefab/PrefabIdTypes.h>
namespace AzToolsFramework namespace AzToolsFramework
{ {
@@ -22,6 +23,9 @@ namespace AzToolsFramework
virtual void OnPrefabInstancePropagationBegin() {} virtual void OnPrefabInstancePropagationBegin() {}
virtual void OnPrefabInstancePropagationEnd() {} virtual void OnPrefabInstancePropagationEnd() {}
virtual void OnPrefabTemplateDirtyFlagUpdated(
[[maybe_unused]] TemplateId templateId, [[maybe_unused]] bool status) {}
}; };
using PrefabPublicNotificationBus = AZ::EBus<PrefabPublicNotifications>; using PrefabPublicNotificationBus = AZ::EBus<PrefabPublicNotifications>;
@@ -185,7 +185,7 @@ namespace AzToolsFramework
if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal) if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal)
{ {
templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator()); templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator());
templateToUpdate->get().MarkAsDirty(true); SetTemplateDirtyFlag(templateId, true);
PropagateTemplateChanges(templateId); PropagateTemplateChanges(templateId);
} }
} }
@@ -813,11 +813,12 @@ namespace AzToolsFramework
void PrefabSystemComponent::SetTemplateDirtyFlag(TemplateId templateId, bool dirty) void PrefabSystemComponent::SetTemplateDirtyFlag(TemplateId templateId, bool dirty)
{ {
auto templateRef = FindTemplate(templateId); if (auto templateReference = FindTemplate(templateId); templateReference.has_value())
if (templateRef.has_value())
{ {
templateRef->get().MarkAsDirty(dirty); templateReference->get().MarkAsDirty(dirty);
PrefabPublicNotificationBus::Broadcast(
&PrefabPublicNotificationBus::Events::OnPrefabTemplateDirtyFlagUpdated, templateId, dirty);
} }
} }
@@ -10,6 +10,8 @@
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h> #include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <QTimer>
namespace AzToolsFramework::Prefab namespace AzToolsFramework::Prefab
{ {
PrefabViewportFocusPathHandler::PrefabViewportFocusPathHandler() PrefabViewportFocusPathHandler::PrefabViewportFocusPathHandler()
@@ -47,6 +49,9 @@ namespace AzToolsFramework::Prefab
[&](const QString&, int linkIndex) [&](const QString&, int linkIndex)
{ {
m_prefabFocusPublicInterface->FocusOnPathIndex(m_editorEntityContextId, linkIndex); m_prefabFocusPublicInterface->FocusOnPathIndex(m_editorEntityContextId, linkIndex);
// Manually refresh path
QTimer::singleShot(0, [&]() { OnPrefabFocusChanged(); });
} }
); );