You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Using AddSP to bind onto a multicast delegate that's removed in a class's destructor is dangerous because the weak pointer used to compare against the 'this' pointer passed to .RemoveAll() will be invalid by the time it is compared. This causes "HasSameObject" to fail as the object cannot be pinned. I've have changed these to be raw bindings so that the ownership is explicit and thus force the call to RemoveAll to succeed correctly without leaving behind a null delegate instance. Previously, with a null delegate instance still in the list when the module is reloaded, that memory becomes invalid causing a crash when the event attempts to purge invalid delegate instances from its invocation list. Also fixed one place where OnTakeHighResScreenShots was being bound but never removed (this looked like a copy paste error) This addresses TTP#337596 - CRASH: EDITOR: Reload after Recompile causes crash #codereview Max.Preussner [CL 2108007 by Andrew Rodham in Main branch]
207 lines
6.4 KiB
C++
207 lines
6.4 KiB
C++
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "LevelEditor.h"
|
|
#include "LevelEditorActions.h"
|
|
#include "SLevelEditorToolBox.h"
|
|
#include "LevelEditorActions.h"
|
|
#include "SToolkitDisplay.h"
|
|
#include "Editor/PropertyEditor/Public/PropertyEditorModule.h"
|
|
#include "Editor/PropertyEditor/Public/IDetailsView.h"
|
|
#include "LevelEditorModesActions.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "SLevelEditorToolBox"
|
|
|
|
SLevelEditorToolBox::~SLevelEditorToolBox()
|
|
{
|
|
GEditor->AccessEditorUserSettings().OnUserSettingChanged().RemoveAll( this );
|
|
}
|
|
|
|
void SLevelEditorToolBox::Construct( const FArguments& InArgs, const TSharedRef< class ILevelEditor >& OwningLevelEditor )
|
|
{
|
|
LevelEditor = OwningLevelEditor;
|
|
|
|
// Important: We use a raw binding here because we are releasing our binding in our destructor (where a weak pointer would be invalid)
|
|
// It's imperative that our delegate is removed in the destructor for the level editor module to play nicely with reloading.
|
|
|
|
GEditor->AccessEditorUserSettings().OnUserSettingChanged().AddRaw( this, &SLevelEditorToolBox::HandleUserSettingsChange );
|
|
|
|
ChildSlot
|
|
[
|
|
SNew( SVerticalBox )
|
|
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.HAlign( HAlign_Left )
|
|
.Padding(0, 0, 0, 0)
|
|
[
|
|
SAssignNew( ModeToolBarContainer, SBorder )
|
|
.BorderImage( FEditorStyle::GetBrush( "NoBorder" ) )
|
|
.Padding( FMargin(4, 0, 0, 0) )
|
|
]
|
|
|
|
+ SVerticalBox::Slot()
|
|
.FillHeight( 1.0f )
|
|
.Padding( 2, 0, 0, 0 )
|
|
[
|
|
SNew( SVerticalBox )
|
|
|
|
+ SVerticalBox::Slot()
|
|
[
|
|
SAssignNew(InlineContentHolder, SBorder)
|
|
.BorderImage( FEditorStyle::GetBrush( "ToolPanel.GroupBorder" ) )
|
|
.Padding(0.f)
|
|
.Visibility( this, &SLevelEditorToolBox::GetInlineContentHolderVisibility )
|
|
]
|
|
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.HAlign( HAlign_Center )
|
|
.Padding( 2.0f, 14.0f, 2.0f, 2.0f )
|
|
[
|
|
SNew( STextBlock )
|
|
.Text( LOCTEXT("NoToolSelected", "Select a tool to display its options.") )
|
|
.Visibility( this, &SLevelEditorToolBox::GetNoToolSelectedTextVisibility )
|
|
]
|
|
]
|
|
];
|
|
|
|
UpdateModeToolBar();
|
|
}
|
|
|
|
void SLevelEditorToolBox::HandleUserSettingsChange( FName PropertyName )
|
|
{
|
|
UpdateModeToolBar();
|
|
}
|
|
|
|
void SLevelEditorToolBox::UpdateModeToolBar()
|
|
{
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>( "LevelEditor");
|
|
const TSharedPtr< const FUICommandList > CommandList = LevelEditorModule.GetGlobalLevelEditorActions();
|
|
const TSharedPtr<FExtender> ModeBarExtenders = LevelEditorModule.GetModeBarExtensibilityManager()->GetAllExtenders();
|
|
|
|
FToolBarBuilder EditorModeTools( CommandList, FMultiBoxCustomization::None, ModeBarExtenders );
|
|
{
|
|
EditorModeTools.SetStyle(&FEditorStyle::Get(), "EditorModesToolbar");
|
|
EditorModeTools.SetLabelVisibility( EVisibility::Collapsed );
|
|
|
|
const FLevelEditorModesCommands& Commands = LevelEditorModule.GetLevelEditorModesCommands();
|
|
|
|
TArray<FEdMode*> Modes;
|
|
GEditorModeTools().GetModes( Modes );
|
|
|
|
struct FCompareEdModeByPriority
|
|
{
|
|
FORCEINLINE bool operator()( const FEdMode& A, const FEdMode& B ) const
|
|
{
|
|
return A.GetPriorityOrder() < B.GetPriorityOrder();
|
|
}
|
|
};
|
|
|
|
Modes.Sort( FCompareEdModeByPriority() );
|
|
|
|
for ( FEdMode* Mode : Modes )
|
|
{
|
|
// If the mode isn't visible don't create a menu option for it.
|
|
if ( !Mode->IsVisible() )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
FName EditorModeCommandName = FName( *( FString( "EditorMode." ) + Mode->GetID().ToString() ) );
|
|
|
|
TSharedPtr<FUICommandInfo> EditorModeCommand =
|
|
FInputBindingManager::Get().FindCommandInContext( Commands.GetContextName(), EditorModeCommandName );
|
|
|
|
// If a command isn't yet registered for this mode, we need to register one.
|
|
if ( !EditorModeCommand.IsValid() )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const FUIAction* UIAction = EditorModeTools.GetTopCommandList()->GetActionForCommand( EditorModeCommand );
|
|
if ( ensure( UIAction ) )
|
|
{
|
|
EditorModeTools.AddToolBarButton( EditorModeCommand, Mode->GetID(), Mode->GetName(), Mode->GetName(), Mode->GetIcon(), Mode->GetID() );// , EUserInterfaceActionType::ToggleButton );
|
|
//EditorModeTools.AddToolBarButton( *UIAction, Mode->GetID(), Mode->GetName(), Mode->GetName(), Mode->GetIcon(), EUserInterfaceActionType::ToggleButton );
|
|
}
|
|
}
|
|
}
|
|
|
|
ModeToolBarContainer->SetContent( EditorModeTools.MakeWidget() );
|
|
|
|
const TArray< TSharedPtr< IToolkit > >& HostedToolkits = LevelEditor.Pin()->GetHostedToolkits();
|
|
for( auto HostedToolkitIt = HostedToolkits.CreateConstIterator(); HostedToolkitIt; ++HostedToolkitIt )
|
|
{
|
|
UpdateInlineContent( ( *HostedToolkitIt )->GetInlineContent() );
|
|
break;
|
|
}
|
|
}
|
|
|
|
EVisibility SLevelEditorToolBox::GetInlineContentHolderVisibility() const
|
|
{
|
|
return InlineContentHolder->GetContent() == SNullWidget::NullWidget ? EVisibility::Collapsed : EVisibility::Visible;
|
|
}
|
|
|
|
EVisibility SLevelEditorToolBox::GetNoToolSelectedTextVisibility() const
|
|
{
|
|
return InlineContentHolder->GetContent() == SNullWidget::NullWidget ? EVisibility::Visible : EVisibility::Collapsed;
|
|
}
|
|
|
|
void SLevelEditorToolBox::UpdateInlineContent(TSharedPtr<SWidget> InlineContent) const
|
|
{
|
|
if (InlineContent.IsValid() && InlineContentHolder.IsValid())
|
|
{
|
|
InlineContentHolder->SetContent(InlineContent.ToSharedRef());
|
|
}
|
|
}
|
|
|
|
void SLevelEditorToolBox::OnToolkitHostingStarted( const TSharedRef< class IToolkit >& Toolkit )
|
|
{
|
|
if( ToolkitArea.IsValid() )
|
|
{
|
|
ToolkitArea->OnToolkitHostingStarted( Toolkit );
|
|
}
|
|
|
|
UpdateInlineContent( Toolkit->GetInlineContent() );
|
|
}
|
|
|
|
void SLevelEditorToolBox::OnToolkitHostingFinished( const TSharedRef< class IToolkit >& Toolkit )
|
|
{
|
|
if( ToolkitArea.IsValid() )
|
|
{
|
|
ToolkitArea->OnToolkitHostingFinished( Toolkit );
|
|
}
|
|
|
|
bool FoundAnotherToolkit = false;
|
|
const TArray< TSharedPtr< IToolkit > >& HostedToolkits = LevelEditor.Pin()->GetHostedToolkits();
|
|
for( auto HostedToolkitIt = HostedToolkits.CreateConstIterator(); HostedToolkitIt; ++HostedToolkitIt )
|
|
{
|
|
if ( ( *HostedToolkitIt ) != Toolkit )
|
|
{
|
|
UpdateInlineContent( ( *HostedToolkitIt )->GetInlineContent() );
|
|
FoundAnotherToolkit = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !FoundAnotherToolkit )
|
|
{
|
|
UpdateInlineContent( SNullWidget::NullWidget );
|
|
}
|
|
}
|
|
|
|
FSlateIcon SLevelEditorToolBox::GetEditorModeIcon(TSharedPtr< FUICommandInfo > EditorModeUICommand, FEditorModeID EditorMode )
|
|
{
|
|
const FSlateIcon& Icon = EditorModeUICommand->GetIcon();
|
|
|
|
FName IconName = Icon.GetStyleName();
|
|
if( FLevelEditorActionCallbacks::IsEditorModeActive(EditorMode) )
|
|
{
|
|
IconName = FEditorStyle::Join(IconName, ".Selected");
|
|
}
|
|
|
|
return FSlateIcon(Icon.GetStyleSetName(), IconName);
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|