@ -11,7 +11,6 @@
# include <AzToolsFramework/Commands/SelectionCommand.h>
# 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>
@ -112,15 +111,24 @@ namespace AzToolsFramework::Prefab
[[maybe_unused]] AzFramework : : EntityContextId entityContextId )
{
// If only one instance is in the hierarchy, this operation is invalid
size_t hierarchySize = m_instanceFocusHierarchy . size ( ) ;
if ( hierarchySize < = 1 )
if ( m_rootAliasFocusPathLength < = 1 )
{
return AZ : : Failure (
AZStd : : string ( " Prefab Focus Handler: Could not complete FocusOnParentOfFocusedPrefab operation while focusing on the root. " ) ) ;
return AZ : : Failure ( AZStd : : string (
" Prefab Focus Handler: Could not complete FocusOnParentOfFocusedPrefab operation while focusing on the root. " ) ) ;
}
RootAliasPath parentPath = m_rootAliasFocusPath ;
parentPath . RemoveFilename ( ) ;
// Retrieve parent of currently focused prefab.
InstanceOptionalReference parentInstance = GetInstanceReferenceFromRootAliasPath ( m_instanceFocusHierarchy [ hierarchySize - 2 ] ) ;
InstanceOptionalReference parentInstance = GetInstanceReference ( parentPath ) ;
// If only one instance is in the hierarchy, this operation is invalid
if ( ! parentInstance . has_value ( ) )
{
return AZ : : Failure ( AZStd : : string (
" Prefab Focus Handler: Could not retrieve parent of current focus in FocusOnParentOfFocusedPrefab. " ) ) ;
}
// Use container entity of parent Instance for focus operations.
AZ : : EntityId entityId = parentInstance - > get ( ) . GetContainerEntityId ( ) ;
@ -149,12 +157,26 @@ namespace AzToolsFramework::Prefab
PrefabFocusOperationResult PrefabFocusHandler : : FocusOnPathIndex ( [[maybe_unused]] AzFramework : : EntityContextId entityContextId , int index )
{
if ( index < 0 | | index > = m_ instanceFocusHierarchy. size ( ) )
if ( index < 0 | | index > = m_ rootAliasFocusPathLength )
{
return AZ : : Failure ( AZStd : : string ( " Prefab Focus Handler: Invalid index on FocusOnPathIndex. " ) ) ;
}
InstanceOptionalReference focusedInstance = GetInstanceReferenceFromRootAliasPath ( m_instanceFocusHierarchy [ index ] ) ;
int i = 0 ;
RootAliasPath indexedPath ;
for ( const auto & pathElement : m_rootAliasFocusPath )
{
indexedPath . Append ( pathElement ) ;
if ( i = = index )
{
break ;
}
+ + i ;
}
InstanceOptionalReference focusedInstance = GetInstanceReference ( indexedPath ) ;
if ( ! focusedInstance . has_value ( ) )
{
@ -197,13 +219,14 @@ namespace AzToolsFramework::Prefab
}
// Close all container entities in the old path.
SetInstanceContainersOpenState ( m_ instanceFocusHierarchy , false ) ;
SetInstanceContainersOpenState ( m_ rootAliasFocusPath , false ) ;
const RootAliasPath previousContainerRootAliasPath = m_ focusedInstanceRootAlia sPath;
const InstanceOptionalConstReference previousFocusedInstance = GetInstanceReference FromRootAliasPath ( previousContainerRootAliasPath ) ;
const RootAliasPath previousContainerRootAliasPath = m_ rootAliasFocu sPath;
const InstanceOptionalConstReference previousFocusedInstance = GetInstanceReference ( previousContainerRootAliasPath ) ;
m_ focusedInstanceRootAlia sPath = focusedInstance - > get ( ) . GetAbsoluteInstanceAliasPath ( ) ;
m_ rootAliasFocu sPath = focusedInstance - > get ( ) . GetAbsoluteInstanceAliasPath ( ) ;
m_focusedTemplateId = focusedInstance - > get ( ) . GetTemplateId ( ) ;
m_rootAliasFocusPathLength = aznumeric_cast < int > ( AZStd : : distance ( m_rootAliasFocusPath . begin ( ) , m_rootAliasFocusPath . end ( ) ) ) ;
// Focus on the descendants of the container entity in the Editor, if the interface is initialized.
if ( m_focusModeInterface )
@ -231,11 +254,10 @@ namespace AzToolsFramework::Prefab
}
// Refresh path variables.
RefreshInstanceFocusList ( ) ;
RefreshInstanceFocusPath ( ) ;
// Open all container entities in the new path.
SetInstanceContainersOpenState ( m_ instanceFocusHierarchy , true ) ;
SetInstanceContainersOpenState ( m_ rootAliasFocusPath , true ) ;
PrefabFocusNotificationBus : : Broadcast ( & PrefabFocusNotifications : : OnPrefabFocusChanged ) ;
@ -250,12 +272,12 @@ namespace AzToolsFramework::Prefab
InstanceOptionalReference PrefabFocusHandler : : GetFocusedPrefabInstance (
[[maybe_unused]] AzFramework : : EntityContextId entityContextId ) const
{
return GetInstanceReference FromRootAliasPath( m_focusedInstanceRootAlia sPath) ;
return GetInstanceReference ( m_rootAliasFocu sPath) ;
}
AZ : : EntityId PrefabFocusHandler : : GetFocusedPrefabContainerEntityId ( [[maybe_unused]] AzFramework : : EntityContextId entityContextId ) const
{
if ( const InstanceOptionalConstReference instance = GetInstanceReference FromRootAliasPath( m_focusedInstanceRootAlia sPath) ; instance . has_value ( ) )
if ( const InstanceOptionalConstReference instance = GetInstanceReference ( m_rootAliasFocu sPath) ; instance . has_value ( ) )
{
return instance - > get ( ) . GetContainerEntityId ( ) ;
}
@ -276,7 +298,7 @@ namespace AzToolsFramework::Prefab
return false ;
}
return ( instance - > get ( ) . GetAbsoluteInstanceAliasPath ( ) = = m_ focusedInstanceRootAlia sPath) ;
return ( instance - > get ( ) . GetAbsoluteInstanceAliasPath ( ) = = m_ rootAliasFocu sPath) ;
}
bool PrefabFocusHandler : : IsOwningPrefabInFocusHierarchy ( AZ : : EntityId entityId ) const
@ -289,7 +311,7 @@ namespace AzToolsFramework::Prefab
InstanceOptionalConstReference instance = m_instanceEntityMapperInterface - > FindOwningInstance ( entityId ) ;
while ( instance . has_value ( ) )
{
if ( instance - > get ( ) . GetAbsoluteInstanceAliasPath ( ) = = m_ focusedInstanceRootAlia sPath)
if ( instance - > get ( ) . GetAbsoluteInstanceAliasPath ( ) = = m_ rootAliasFocu sPath)
{
return true ;
}
@ -302,42 +324,49 @@ namespace AzToolsFramework::Prefab
const AZ : : IO : : Path & PrefabFocusHandler : : GetPrefabFocusPath ( [[maybe_unused]] AzFramework : : EntityContextId entityContextId ) const
{
return m_ instanc eFocusPath;
return m_ filenam eFocusPath;
}
const int PrefabFocusHandler : : GetPrefabFocusPathLength ( [[maybe_unused]] AzFramework : : EntityContextId entityContextId ) const
{
return aznumeric_cast< int > ( m_instanceFocusHierarchy . size ( ) ) ;
return m_rootAliasFocusPathLength ;
}
void PrefabFocusHandler : : OnContextReset ( )
{
// Clear the old focus vector
m_instanceFocusHierarchy . clear ( ) ;
// Focus on the root prefab (AZ::EntityId() will default to it)
FocusOnPrefabInstanceOwningEntityId ( AZ : : EntityId ( ) ) ;
}
void PrefabFocusHandler : : OnEntityInfoUpdatedName ( AZ : : EntityId entityId , [[maybe_unused]] const AZStd : : string & name )
{
PrefabEditorEntityOwnershipInterface * prefabEditorEntityOwnershipInterface =
AZ : : Interface < PrefabEditorEntityOwnershipInterface > : : Get ( ) ;
if ( prefabEditorEntityOwnershipInterface )
{
// Determine if the entityId is the container for any of the instances in the vector.
auto result = AZStd : : find_if (
m_instanceFocusHierarchy . begin ( ) , m_instanceFocusHierarchy . end ( ) ,
[ & , entityId ] ( const RootAliasPath & rootAliasPath )
bool match = prefabEditorEntityOwnershipInterface - > GetInstancesInRootAliasPath (
m_rootAliasFocusPath ,
[ & ] ( const Prefab : : InstanceOptionalReference instance )
{
InstanceOptionalReference instance = GetInstanceReferenceFromRootAliasPath ( rootAliasPath ) ;
return ( instance - > get ( ) . GetContainerEntityId ( ) = = entityId ) ;
if ( instance - > get ( ) . GetContainerEntityId ( ) = = entityId )
{
return true ;
}
return false ;
}
) ;
if ( result ! = m_instanceFocusHierarchy . end ( ) )
if ( match )
{
// Refresh the path and notify changes.
RefreshInstanceFocusPath ( ) ;
PrefabFocusNotificationBus : : Broadcast ( & PrefabFocusNotifications : : OnPrefabFocusChanged ) ;
}
}
}
void PrefabFocusHandler : : OnPrefabInstancePropagationEnd ( )
{
@ -347,65 +376,64 @@ namespace AzToolsFramework::Prefab
}
void PrefabFocusHandler : : OnPrefabTemplateDirtyFlagUpdated ( TemplateId templateId , [[maybe_unused]] bool status )
{
PrefabEditorEntityOwnershipInterface * prefabEditorEntityOwnershipInterface =
AZ : : Interface < PrefabEditorEntityOwnershipInterface > : : Get ( ) ;
if ( prefabEditorEntityOwnershipInterface )
{
// 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 RootAliasPath & rootAliasPath )
bool match = prefabEditorEntityOwnershipInterface - > GetInstancesInRootAliasPath (
m_rootAliasFocusPath ,
[ & ] ( const Prefab : : InstanceOptionalReference instance )
{
if ( instance - > get ( ) . GetTemplateId ( ) = = templateId )
{
InstanceOptionalReference instance = GetInstanceReferenceFromRootAliasPath ( rootAliasPath ) ;
return ( instance - > get ( ) . GetTemplateId ( ) = = templateId ) ;
return true ;
}
return false ;
}
) ;
if ( result ! = m_instanceFocusHierarchy . end ( ) )
if ( match )
{
// Refresh the path and notify changes.
RefreshInstanceFocusPath ( ) ;
PrefabFocusNotificationBus : : Broadcast ( & PrefabFocusNotifications : : OnPrefabFocusChanged ) ;
}
}
void PrefabFocusHandler : : RefreshInstanceFocusList ( )
{
m_instanceFocusHierarchy . clear ( ) ;
InstanceOptionalConstReference currentInstance = GetInstanceReferenceFromRootAliasPath ( m_focusedInstanceRootAliasPath ) ;
while ( currentInstance . has_value ( ) )
{
m_instanceFocusHierarchy . emplace_back ( currentInstance - > get ( ) . GetAbsoluteInstanceAliasPath ( ) ) ;
currentInstance = currentInstance - > get ( ) . GetParentInstance ( ) ;
}
// Invert the vector, since we need the top instance to be at index 0.
AZStd : : reverse ( m_instanceFocusHierarchy . begin ( ) , m_instanceFocusHierarchy . end ( ) ) ;
}
void PrefabFocusHandler : : RefreshInstanceFocusPath ( )
{
auto prefabSystemComponentInterface = AZ : : Interface < PrefabSystemComponentInterface > : : Get ( ) ;
m_filenameFocusPath . clear ( ) ;
m_instanceFocusPath . clear ( ) ;
PrefabEditorEntityOwnershipInterface * prefabEditorEntityOwnershipInterface =
AZ : : Interface < PrefabEditorEntityOwnershipInterface > : : Get ( ) ;
PrefabSystemComponentInterface * prefabSystemComponentInterface = AZ : : Interface < PrefabSystemComponentInterface > : : Get ( ) ;
size_t index = 0 ;
size_t maxIndex = m_instanceFocusHierarchy . size ( ) - 1 ;
if ( prefabEditorEntityOwnershipInterface & & prefabSystemComponentInterface )
{
int i = 0 ;
for ( const RootAliasPath & rootAliasPath : m_instanceFocusHierarchy )
prefabEditorEntityOwnershipInterface - > GetInstancesInRootAliasPath (
m_rootAliasFocusPath ,
[ & ] ( const Prefab : : InstanceOptionalReference instance )
{
const InstanceOptionalConstReference instance = GetInstanceReferenceFromRootAliasPath ( rootAliasPath ) ;
if ( instance . has_value ( ) )
{
AZStd : : string prefabName ;
if ( index < maxIndex )
if ( i = = m_rootAliasFocusPathLength - 1 )
{
// Get the f ilename without the extension (stem) .
prefabName = instance - > get ( ) . GetTemplateSourcePath ( ) . Stem ( ) . Native ( ) ;
// Get the f ull f ilename.
prefabName = instance - > get ( ) . GetTemplateSourcePath ( ) . Filename ( ) . Native ( ) ;
}
else
{
// Get the f ull f ilename.
prefabName = instance - > get ( ) . GetTemplateSourcePath ( ) . Filename ( ) . Native ( ) ;
// Get the f ilename without the extension (stem) .
prefabName = instance - > get ( ) . GetTemplateSourcePath ( ) . Stem ( ) . Native ( ) ;
}
if ( prefabSystemComponentInterface - > IsTemplateDirty ( instance - > get ( ) . GetTemplateId ( ) ) )
@ -413,14 +441,17 @@ namespace AzToolsFramework::Prefab
prefabName + = " * " ;
}
m_instanc eFocusPath. Append ( prefabName ) ;
m_filenam eFocusPath. Append ( prefabName ) ;
}
+ + index ;
+ + i ;
return false ;
}
) ;
}
}
void PrefabFocusHandler : : SetInstanceContainersOpenState ( const AZStd: : vector < RootAliasPath> & inst ance s, bool openState ) const
void PrefabFocusHandler : : SetInstanceContainersOpenState ( const RootAliasPath & rootAl iasPath , bool openState ) const
{
// If this is called outside the Editor, this interface won't be initialized.
if ( ! m_containerEntityInterface )
@ -428,51 +459,34 @@ namespace AzToolsFramework::Prefab
return ;
}
for ( const RootAliasPath & rootAliasPath : instances )
{
InstanceOptionalReference instance = GetInstanceReferenceFromRootAliasPath ( rootAliasPath ) ;
PrefabEditorEntityOwnershipInterface * prefabEditorEntityOwnershipInterface =
AZ : : Interface < PrefabEditorEntityOwnershipInterface > : : Get ( ) ;
if ( instance . has_value ( ) )
if ( prefabEditorEntityOwnershipInterface )
{
prefabEditorEntityOwnershipInterface - > GetInstancesInRootAliasPath (
rootAliasPath ,
[ & ] ( const Prefab : : InstanceOptionalReference instance )
{
m_containerEntityInterface - > SetContainerOpen ( instance - > get ( ) . GetContainerEntityId ( ) , openState ) ;
return false ;
}
) ;
}
}
InstanceOptionalReference PrefabFocusHandler : : GetInstanceReference FromRootAliasPath ( RootAliasPath rootAliasPath ) const
InstanceOptionalReference PrefabFocusHandler : : GetInstanceReference ( RootAliasPath rootAliasPath ) const
{
PrefabEditorEntityOwnershipInterface * prefabEditorEntityOwnershipInterface =
AZ : : Interface < PrefabEditorEntityOwnershipInterface > : : Get ( ) ;
if ( prefabEditorEntityOwnershipInterface )
{
InstanceOptionalReference instance = prefabEditorEntityOwnershipInterface - > GetRootPrefabInstance ( ) ;
for ( const auto & pathElement : rootAliasPath )
{
if ( pathElement . Native ( ) = = rootAliasPath . begin ( ) - > Native ( ) )
{
// If the root is not the root Instance, the rootAliasPath is invalid.
if ( pathElement . Native ( ) ! = instance - > get ( ) . GetInstanceAlias ( ) )
{
return InstanceOptionalReference ( ) ;
}
}
else
{
// If the instance alias can't be found, the rootAliasPath is invalid.
instance = instance - > get ( ) . FindNestedInstance ( pathElement . Native ( ) ) ;
if ( ! instance . has_value ( ) )
{
return InstanceOptionalReference ( ) ;
}
}
}
return instance ;
return prefabEditorEntityOwnershipInterface - > GetInstanceReferenceFromRootAliasPath ( rootAliasPath ) ;
}
return InstanceOptionalReference ( ) ;
return AZStd : : nullopt ;
}
} // namespace AzToolsFramework::Prefab