2021-03-10 12:35:33 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "ActorDescTreeItem.h"
2022-08-29 18:44:52 -04:00
# include "WorldPartition/ActorDescContainer.h"
2022-01-21 14:29:12 -05:00
# include "WorldPartition/WorldPartition.h"
2021-03-10 12:35:33 -04:00
# include "WorldPartition/WorldPartitionActorDesc.h"
2022-12-15 15:55:53 -05:00
# include "WorldPartition/LoaderAdapter/LoaderAdapterPinnedActors.h"
2021-03-10 12:35:33 -04:00
# include "Widgets/DeclarativeSyntaxSupport.h"
# include "Layout/WidgetPath.h"
# include "Framework/Application/MenuStack.h"
# include "Framework/Application/SlateApplication.h"
# include "Editor.h"
# include "ScopedTransaction.h"
# include "SceneOutlinerPublicTypes.h"
# include "SceneOutlinerDragDrop.h"
# include "SceneOutlinerStandaloneTypes.h"
# include "Widgets/Text/SInlineEditableTextBlock.h"
# include "ActorEditorUtils.h"
# include "ClassIconFinder.h"
# include "ISceneOutliner.h"
# include "ISceneOutlinerMode.h"
# include "Logging/MessageLog.h"
# include "SSocketChooser.h"
2021-03-30 11:16:04 -04:00
# include "ToolMenus.h"
# include "LevelEditorViewport.h"
2022-06-29 18:59:28 -04:00
# include "HAL/PlatformApplicationMisc.h"
2023-01-26 15:05:37 -05:00
# include "Misc/ArchiveMD5.h"
# include "Misc/SecureHash.h"
# include "UObject/ObjectKey.h"
2021-03-10 12:35:33 -04:00
# define LOCTEXT_NAMESPACE "SceneOutliner_ActorDescTreeItem"
2022-05-20 10:13:02 -04:00
const FSceneOutlinerTreeItemType FActorDescTreeItem : : Type ( & IActorBaseTreeItem : : Type ) ;
2021-03-10 12:35:33 -04:00
struct SActorDescTreeLabel : FSceneOutlinerCommonLabelData , public SCompoundWidget
{
SLATE_BEGIN_ARGS ( SActorDescTreeLabel ) { }
SLATE_END_ARGS ( )
2021-03-30 11:16:04 -04:00
void Construct ( const FArguments & InArgs , FActorDescTreeItem & ActorDescItem , ISceneOutliner & SceneOutliner , const STableRow < FSceneOutlinerTreeItemPtr > & InRow )
2021-03-10 12:35:33 -04:00
{
WeakSceneOutliner = StaticCastSharedRef < ISceneOutliner > ( SceneOutliner . AsShared ( ) ) ;
TreeItemPtr = StaticCastSharedRef < FActorDescTreeItem > ( ActorDescItem . AsShared ( ) ) ;
HighlightText = SceneOutliner . GetFilterHighlightText ( ) ;
TSharedPtr < SInlineEditableTextBlock > InlineTextBlock ;
auto MainContent = SNew ( SHorizontalBox )
// Main actor desc label
+ SHorizontalBox : : Slot ( )
. VAlign ( VAlign_Center )
[
SAssignNew ( InlineTextBlock , SInlineEditableTextBlock )
. Text ( this , & SActorDescTreeLabel : : GetDisplayText )
2021-03-30 11:16:04 -04:00
. ToolTipText ( this , & SActorDescTreeLabel : : GetTooltipText )
. HighlightText ( HighlightText )
. ColorAndOpacity ( this , & SActorDescTreeLabel : : GetForegroundColor )
. OnTextCommitted ( this , & SActorDescTreeLabel : : OnLabelCommitted )
. OnVerifyTextChanged ( this , & SActorDescTreeLabel : : OnVerifyItemLabelChanged )
. IsSelected ( FIsSelected : : CreateSP ( & InRow , & STableRow < FSceneOutlinerTreeItemPtr > : : IsSelectedExclusively ) )
. IsReadOnly_Lambda ( [ Item = ActorDescItem . AsShared ( ) , this ] ( )
{
return ! CanExecuteRenameRequest ( Item . Get ( ) ) ;
} )
2021-03-10 12:35:33 -04:00
]
+ SHorizontalBox : : Slot ( )
. VAlign ( VAlign_Center )
. AutoWidth ( )
. Padding ( 0.0f , 0.f , 3.0f , 0.0f )
[
SNew ( STextBlock )
. Text ( this , & SActorDescTreeLabel : : GetTypeText )
2021-03-30 11:16:04 -04:00
. Visibility ( this , & SActorDescTreeLabel : : GetTypeTextVisibility )
. HighlightText ( HighlightText )
2021-03-10 12:35:33 -04:00
] ;
if ( WeakSceneOutliner . Pin ( ) - > GetMode ( ) - > IsInteractive ( ) )
{
ActorDescItem . RenameRequestEvent . BindSP ( InlineTextBlock . Get ( ) , & SInlineEditableTextBlock : : EnterEditingMode ) ;
}
ChildSlot
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
2021-03-30 11:16:04 -04:00
. AutoWidth ( )
. VAlign ( VAlign_Center )
. Padding ( FSceneOutlinerDefaultTreeItemMetrics : : IconPadding ( ) )
[
SNew ( SBox )
. WidthOverride ( FSceneOutlinerDefaultTreeItemMetrics : : IconSize ( ) )
. HeightOverride ( FSceneOutlinerDefaultTreeItemMetrics : : IconSize ( ) )
[
SNew ( SImage )
. Image ( this , & SActorDescTreeLabel : : GetIcon )
. ToolTipText ( this , & SActorDescTreeLabel : : GetIconTooltip )
. ColorAndOpacity ( FSlateColor : : UseForeground ( ) )
]
]
2021-03-10 12:35:33 -04:00
2021-03-30 11:16:04 -04:00
+ SHorizontalBox : : Slot ( )
. FillWidth ( 1.0f )
. VAlign ( VAlign_Center )
. Padding ( 0.0f , 0.0f )
[
MainContent
]
2021-03-10 12:35:33 -04:00
] ;
}
private :
TWeakPtr < FActorDescTreeItem > TreeItemPtr ;
TAttribute < FText > HighlightText ;
FText GetDisplayText ( ) const
{
if ( TSharedPtr < FActorDescTreeItem > TreeItem = TreeItemPtr . Pin ( ) )
{
2022-12-15 15:55:53 -05:00
if ( FWorldPartitionActorDesc * ActorDesc = TreeItem - > ActorDescHandle . Get ( ) )
2021-03-10 12:35:33 -04:00
{
FFormatNamedArguments Args ;
2022-05-10 10:22:54 -04:00
Args . Add ( TEXT ( " ActorLabel " ) , FText : : FromString ( TreeItem - > GetDisplayString ( ) ) ) ;
2023-03-10 11:01:34 -05:00
Args . Add ( TEXT ( " UnloadState " ) , ActorDesc - > GetUnloadedReason ( ) ) ;
2022-05-20 10:13:02 -04:00
2022-12-15 15:55:53 -05:00
return FText : : Format ( LOCTEXT ( " UnloadedActorDisplay " , " {ActorLabel} ({UnloadState}) " ) , Args ) ;
2021-03-10 12:35:33 -04:00
}
}
return FText ( ) ;
}
FText GetTooltipText ( ) const
{
return FText ( ) ;
}
FText GetTypeText ( ) const
{
if ( TSharedPtr < FActorDescTreeItem > TreeItem = TreeItemPtr . Pin ( ) )
{
2022-01-12 13:39:39 -05:00
if ( const FWorldPartitionActorDesc * ActorDesc = TreeItem - > ActorDescHandle . Get ( ) )
2021-03-10 12:35:33 -04:00
{
2022-05-05 14:10:10 -04:00
return FText : : FromName ( ActorDesc - > GetDisplayClassName ( ) ) ;
2021-03-10 12:35:33 -04:00
}
}
return FText ( ) ;
}
EVisibility GetTypeTextVisibility ( ) const
{
return HighlightText . Get ( ) . IsEmpty ( ) ? EVisibility : : Collapsed : EVisibility : : Visible ;
}
const FSlateBrush * GetIcon ( ) const
{
TSharedPtr < FActorDescTreeItem > TreeItem = TreeItemPtr . Pin ( ) ;
if ( TreeItem . IsValid ( ) & & WeakSceneOutliner . IsValid ( ) )
{
2022-01-12 13:39:39 -05:00
if ( const FWorldPartitionActorDesc * ActorDesc = TreeItem - > ActorDescHandle . Get ( ) )
2021-03-10 12:35:33 -04:00
{
2022-07-12 14:42:32 -04:00
const FName IconName = ActorDesc - > GetDisplayClassName ( ) ;
2021-03-10 12:35:33 -04:00
const FSlateBrush * CachedBrush = WeakSceneOutliner . Pin ( ) - > GetCachedIconForClass ( IconName ) ;
if ( CachedBrush ! = nullptr )
{
return CachedBrush ;
}
else if ( IconName ! = NAME_None )
{
2022-05-05 14:10:10 -04:00
const FSlateBrush * FoundSlateBrush = FSlateIconFinder : : FindIconForClass ( ActorDesc - > GetActorNativeClass ( ) ) . GetIcon ( ) ;
2021-03-10 12:35:33 -04:00
WeakSceneOutliner . Pin ( ) - > CacheIconForClass ( IconName , FoundSlateBrush ) ;
return FoundSlateBrush ;
}
}
}
return nullptr ;
}
const FSlateBrush * GetIconOverlay ( ) const
{
return nullptr ;
}
FText GetIconTooltip ( ) const
{
return FText ( ) ;
}
virtual FSlateColor GetForegroundColor ( ) const override
{
if ( const auto TreeItem = TreeItemPtr . Pin ( ) )
{
if ( auto BaseColor = FSceneOutlinerCommonLabelData : : GetForegroundColor ( * TreeItem ) )
{
return BaseColor . GetValue ( ) ;
}
2022-08-19 13:43:56 -04:00
if ( WeakSceneOutliner . IsValid ( ) )
{
// Use the normal foreground color for selected items to make them readable
if ( WeakSceneOutliner . Pin ( ) - > GetTree ( ) . IsItemSelected ( TreeItem ) )
{
return FSlateColor : : UseSubduedForeground ( ) ;
}
}
2021-03-10 12:35:33 -04:00
}
2022-08-19 13:43:56 -04:00
2021-03-10 12:35:33 -04:00
return FSceneOutlinerCommonLabelData : : DarkColor ;
}
bool OnVerifyItemLabelChanged ( const FText & , FText & )
{
// don't allow label change for unloaded actor items
return false ;
}
void OnLabelCommitted ( const FText & InLabel , ETextCommit : : Type InCommitInfo )
{
// not supported.
}
} ;
2023-01-26 15:05:37 -05:00
FActorDescTreeItem : : FActorDescTreeItem ( const FGuid & InActorGuid , UActorDescContainer * InContainer )
2022-05-20 10:13:02 -04:00
: IActorBaseTreeItem ( Type )
2023-01-26 15:05:37 -05:00
, ActorDescHandle ( InContainer , InActorGuid )
, ID ( ComputeTreeItemID ( InActorGuid , InContainer ) )
2021-04-29 14:57:23 -04:00
, ActorGuid ( InActorGuid )
2021-03-10 12:35:33 -04:00
{
2022-01-12 13:39:39 -05:00
if ( const FWorldPartitionActorDesc * const ActorDesc = ActorDescHandle . Get ( ) )
2021-04-28 10:56:38 -04:00
{
DisplayString = ActorDesc - > GetActorLabel ( ) . ToString ( ) ;
}
else
{
DisplayString = LOCTEXT ( " ActorLabelForMissingActor " , " (Deleted Actor) " ) . ToString ( ) ;
}
2021-03-10 12:35:33 -04:00
}
2023-01-26 15:05:37 -05:00
FSceneOutlinerTreeItemID FActorDescTreeItem : : ComputeTreeItemID ( FGuid InActorGuid , UActorDescContainer * InContainer )
{
FArchiveMD5 Ar ;
Ar < < InActorGuid ;
FObjectKey ContainerKey ( InContainer ) ;
Ar < < ContainerKey ;
2023-05-08 09:08:07 -04:00
return FSceneOutlinerTreeItemID ( Ar . GetGuidFromHash ( ) ) ;
2023-01-26 15:05:37 -05:00
}
2023-03-08 10:55:55 -05:00
bool FActorDescTreeItem : : ShouldDisplayInOutliner ( const FWorldPartitionActorDesc * ActorDesc )
{
2023-07-27 07:07:59 -04:00
return ActorDesc & & ActorDesc - > IsListedInSceneOutliner ( ) & & ( ActorDesc - > GetActorIsRuntimeOnly ( ) | | ActorDesc - > IsEditorRelevant ( ) ) ;
2023-03-08 10:55:55 -05:00
}
2021-03-10 12:35:33 -04:00
FSceneOutlinerTreeItemID FActorDescTreeItem : : GetID ( ) const
{
return ID ;
}
FString FActorDescTreeItem : : GetDisplayString ( ) const
{
2021-04-28 10:56:38 -04:00
return DisplayString ;
2021-03-10 12:35:33 -04:00
}
bool FActorDescTreeItem : : CanInteract ( ) const
{
2021-03-30 11:16:04 -04:00
return ActorDescHandle . IsValid ( ) ;
2021-03-10 12:35:33 -04:00
}
TSharedRef < SWidget > FActorDescTreeItem : : GenerateLabelWidget ( ISceneOutliner & Outliner , const STableRow < FSceneOutlinerTreeItemPtr > & InRow )
{
return SNew ( SActorDescTreeLabel , * this , Outliner , InRow ) ;
}
2021-03-30 11:16:04 -04:00
void FActorDescTreeItem : : FocusActorBounds ( ) const
{
2022-01-12 13:39:39 -05:00
if ( FWorldPartitionActorDesc const * ActorDesc = ActorDescHandle . Get ( ) )
2021-03-30 11:16:04 -04:00
{
2022-08-26 11:04:20 -04:00
const bool bActiveViewportOnly = true ;
2023-04-26 10:11:09 -04:00
const FBox EditorBounds = ActorDesc - > GetEditorBounds ( ) ;
if ( EditorBounds . IsValid )
{
GEditor - > MoveViewportCamerasToBox ( EditorBounds , bActiveViewportOnly , 0.5f ) ;
}
2021-03-30 11:16:04 -04:00
}
}
2022-06-29 18:59:28 -04:00
void FActorDescTreeItem : : CopyActorFilePathtoClipboard ( ) const
{
if ( FWorldPartitionActorDesc const * ActorDesc = ActorDescHandle . Get ( ) )
{
FString PackageFilename ;
if ( FPackageName : : TryConvertLongPackageNameToFilename ( ActorDesc - > GetActorPackage ( ) . ToString ( ) , PackageFilename , FPackageName : : GetAssetPackageExtension ( ) ) )
{
FString Result = FPaths : : ConvertRelativePathToFull ( PackageFilename ) ;
FPlatformApplicationMisc : : ClipboardCopy ( * Result ) ;
}
}
}
2021-03-30 11:16:04 -04:00
void FActorDescTreeItem : : GenerateContextMenu ( UToolMenu * Menu , SSceneOutliner & )
{
FToolMenuSection & Section = Menu - > AddSection ( " Section " ) ;
Section . AddMenuEntry ( " FocusActorBounds " , LOCTEXT ( " FocusActorBounds " , " Focus Actor Bounds " ) , FText ( ) , FSlateIcon ( ) , FUIAction ( FExecuteAction : : CreateSP ( this , & FActorDescTreeItem : : FocusActorBounds ) ) ) ;
2022-06-29 18:59:28 -04:00
Section . AddMenuEntry ( " CopyActorFilePath " , LOCTEXT ( " CopyActorFilePath " , " Copy Actor File Path " ) , LOCTEXT ( " CopyActorFilePathTooltip " , " Copy the file path where this actor is saved " ) , FSlateIcon ( FAppStyle : : GetAppStyleSetName ( ) , " GenericCommands.Copy " ) , FUIAction ( FExecuteAction : : CreateSP ( this , & FActorDescTreeItem : : CopyActorFilePathtoClipboard ) ) ) ;
2021-03-30 11:16:04 -04:00
}
2021-03-10 12:35:33 -04:00
bool FActorDescTreeItem : : GetVisibility ( ) const
{
2023-02-01 19:27:23 -05:00
return false ;
2021-03-10 12:35:33 -04:00
}
2022-10-14 21:14:54 -04:00
bool FActorDescTreeItem : : ShouldShowPinnedState ( ) const
{
2022-12-15 15:55:53 -05:00
return FLoaderAdapterPinnedActors : : SupportsPinning ( ActorDescHandle . Get ( ) ) ;
2022-10-14 21:14:54 -04:00
}
2021-05-03 15:49:00 -04:00
bool FActorDescTreeItem : : GetPinnedState ( ) const
{
2022-12-05 10:35:51 -05:00
if ( ActorDescHandle . IsValid ( ) & & ActorDescHandle - > GetContainer ( ) )
2021-05-03 15:49:00 -04:00
{
2023-01-31 17:03:25 -05:00
UWorldPartition * WorldPartition = ActorDescHandle - > GetContainer ( ) - > GetWorldPartition ( ) ;
2022-10-27 12:19:07 -04:00
return WorldPartition ? WorldPartition - > IsActorPinned ( GetGuid ( ) ) : false ;
2021-05-03 15:49:00 -04:00
}
return false ;
}
2021-03-10 12:35:33 -04:00
# undef LOCTEXT_NAMESPACE