You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Engine source (Main branch up to CL 2026164)
This commit is contained in:
318
Engine/Source/Developer/ModuleUI/Private/SModuleUI.cpp
Normal file
318
Engine/Source/Developer/ModuleUI/Private/SModuleUI.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "ModuleUIPrivatePCH.h"
|
||||
|
||||
|
||||
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||||
void SModuleUI::Construct(const SModuleUI::FArguments& InArgs)
|
||||
{
|
||||
#define LOCTEXT_NAMESPACE "ModuleUI"
|
||||
|
||||
ChildSlot
|
||||
.Padding( FMargin(8) )
|
||||
[
|
||||
SNew( SVerticalBox )
|
||||
|
||||
// List of modules
|
||||
+ SVerticalBox::Slot()
|
||||
.FillHeight( 1.0f ) // We want the list to stretch vertically to fill up the user-resizable space
|
||||
[
|
||||
SAssignNew( ModuleListView, SModuleListView )
|
||||
.ItemHeight( 24 )
|
||||
.ListItemsSource( &ModuleListItems )
|
||||
.OnGenerateRow( this, &SModuleUI::OnGenerateWidgetForModuleListView )
|
||||
.HeaderRow
|
||||
(
|
||||
SNew(SHeaderRow)
|
||||
+SHeaderRow::Column("ModuleName")
|
||||
.DefaultLabel(NSLOCTEXT("ModuleUI", "ModuleName", "Module").ToString())
|
||||
.FillWidth(200)
|
||||
+SHeaderRow::Column("ModuleActions")
|
||||
.DefaultLabel(NSLOCTEXT("ModuleUI", "ModuleActions", "Actions").ToString())
|
||||
.FillWidth(1000)
|
||||
)
|
||||
]
|
||||
];
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
|
||||
// Register to find out about module changes
|
||||
FModuleManager::Get().OnModulesChanged().AddSP( this, &SModuleUI::OnModulesChanged );
|
||||
|
||||
|
||||
// Gather data from module manager
|
||||
UpdateModuleListItems();
|
||||
}
|
||||
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||||
|
||||
|
||||
SModuleUI::~SModuleUI()
|
||||
{
|
||||
// Unregister callbacks
|
||||
FModuleManager::Get().OnModulesChanged().RemoveAll( this );
|
||||
}
|
||||
|
||||
|
||||
TSharedRef<ITableRow> SModuleUI::OnGenerateWidgetForModuleListView(TSharedPtr< FModuleListItem > InItem, const TSharedRef<STableViewBase>& OwnerTable)
|
||||
{
|
||||
#define LOCTEXT_NAMESPACE "ModuleUI"
|
||||
|
||||
class SModuleItemWidget : public SMultiColumnTableRow< TSharedPtr< FModuleListItem > >
|
||||
{
|
||||
public:
|
||||
SLATE_BEGIN_ARGS( SModuleItemWidget ){}
|
||||
SLATE_END_ARGS()
|
||||
|
||||
void Construct( const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwnerTable, TSharedPtr<FModuleListItem> InListItem )
|
||||
{
|
||||
Item = InListItem;
|
||||
|
||||
SMultiColumnTableRow< TSharedPtr< FModuleListItem > >::Construct( FSuperRowType::FArguments(), InOwnerTable );
|
||||
}
|
||||
|
||||
TSharedRef<SWidget> GenerateWidgetForColumn( const FName& ColumnName )
|
||||
{
|
||||
if ( ColumnName == "ModuleName" )
|
||||
{
|
||||
return
|
||||
SNew( STextBlock )
|
||||
.Text( Item->ModuleName.ToString() );
|
||||
}
|
||||
else if ( ColumnName == "ModuleActions" )
|
||||
{
|
||||
return
|
||||
SNew( SHorizontalBox )
|
||||
|
||||
// Load button
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.Padding( 2.0f, 0.0f )
|
||||
[
|
||||
SNew( SButton )
|
||||
.Visibility( Item.ToSharedRef(), &FModuleListItem::GetVisibilityBasedOnUnloadedState )
|
||||
.Text( LOCTEXT("Load", "Load") )
|
||||
.OnClicked( Item.ToSharedRef(), &FModuleListItem::OnLoadClicked )
|
||||
]
|
||||
|
||||
// Unload button
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.Padding( 2.0f, 0.0f )
|
||||
[
|
||||
SNew( SButton )
|
||||
.Visibility( Item.ToSharedRef(), &FModuleListItem::GetVisibilityBasedOnLoadedAndShutdownableState )
|
||||
.Text( LOCTEXT("Unload", "Unload") )
|
||||
.OnClicked( Item.ToSharedRef(), &FModuleListItem::OnUnloadClicked )
|
||||
]
|
||||
|
||||
// Reload button
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.Padding( 2.0f, 0.0f )
|
||||
[
|
||||
SNew( SButton )
|
||||
.Visibility( Item.ToSharedRef(), &FModuleListItem::GetVisibilityBasedOnReloadableState )
|
||||
.Text( LOCTEXT("Reload", "Reload") )
|
||||
.OnClicked( Item.ToSharedRef(), &FModuleListItem::OnReloadClicked )
|
||||
]
|
||||
|
||||
// Recompile button
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.Padding( 2.0f, 0.0f )
|
||||
[
|
||||
SNew( SButton )
|
||||
.Visibility( Item.ToSharedRef(), &FModuleListItem::GetVisibilityBasedOnRecompilableState )
|
||||
.Text( LOCTEXT("Recompile", "Recompile") )
|
||||
.OnClicked( Item.ToSharedRef(), &FModuleListItem::OnRecompileClicked )
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
return SNew(STextBlock) .Text(LOCTEXT("UnknownColumn", "Unknown Column"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TSharedPtr< FModuleListItem > Item;
|
||||
};
|
||||
|
||||
return SNew( SModuleItemWidget, OwnerTable, InItem );
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
}
|
||||
|
||||
|
||||
void SModuleUI::OnModulesChanged( FName ModuleThatChanged, EModuleChangeReason::Type ReasonForChange )
|
||||
{
|
||||
// @todo: Consider using dirty bit for this instead, refresh on demand
|
||||
UpdateModuleListItems();
|
||||
}
|
||||
|
||||
void SModuleUI::UpdateModuleListItems()
|
||||
{
|
||||
ModuleListItems.Reset();
|
||||
|
||||
TArray< FModuleManager::FModuleStatus > ModuleStatuses;
|
||||
FModuleManager::Get().QueryModules( ModuleStatuses );
|
||||
|
||||
for( TArray< FModuleManager::FModuleStatus >::TConstIterator ModuleIt( ModuleStatuses ); ModuleIt; ++ModuleIt )
|
||||
{
|
||||
const FModuleManager::FModuleStatus& ModuleStatus = *ModuleIt;
|
||||
|
||||
FName ModuleName(*ModuleStatus.Name);
|
||||
|
||||
TSharedRef< FModuleListItem > NewItem( new FModuleListItem() );
|
||||
NewItem->ModuleName = ModuleName;
|
||||
ModuleListItems.Add( NewItem );
|
||||
}
|
||||
|
||||
|
||||
// Sort the list of modules alphabetically
|
||||
struct FModuleSorter
|
||||
{
|
||||
FORCEINLINE bool operator()( const TSharedPtr<FModuleListItem>& A, const TSharedPtr<FModuleListItem>& B ) const
|
||||
{
|
||||
return A->ModuleName < B->ModuleName;
|
||||
}
|
||||
};
|
||||
ModuleListItems.Sort( FModuleSorter() );
|
||||
|
||||
// Update the list view if we have one
|
||||
if( ModuleListView.IsValid() )
|
||||
{
|
||||
ModuleListView->RequestListRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FReply SModuleUI::FModuleListItem::OnLoadClicked()
|
||||
{
|
||||
GEngine->DeferredCommands.Add( FString::Printf( TEXT( "Module Load %s" ), *ModuleName.ToString() ) );
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
|
||||
FReply SModuleUI::FModuleListItem::OnUnloadClicked()
|
||||
{
|
||||
GEngine->DeferredCommands.Add( FString::Printf( TEXT( "Module Unload %s" ), *ModuleName.ToString() ) );
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
|
||||
FReply SModuleUI::FModuleListItem::OnReloadClicked()
|
||||
{
|
||||
GEngine->DeferredCommands.Add( FString::Printf( TEXT( "Module Reload %s" ), *ModuleName.ToString() ) );
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
|
||||
FReply SModuleUI::FModuleListItem::OnRecompileClicked()
|
||||
{
|
||||
const bool bShowProgressDialog = true;
|
||||
const bool bShowCancelButton = false;
|
||||
|
||||
FFormatNamedArguments Args;
|
||||
Args.Add( TEXT("ModuleName"), FText::FromName( ModuleName ) );
|
||||
GWarn->BeginSlowTask( FText::Format( NSLOCTEXT("ModuleUI", "Recompile_SlowTaskName", "Compiling {ModuleName}..."), Args ), bShowProgressDialog, bShowCancelButton );
|
||||
|
||||
// Does the module have any UObject classes in it? If so we'll use HotReload to recompile it.
|
||||
FModuleManager::FModuleStatus ModuleStatus;
|
||||
if( ensure( FModuleManager::Get().QueryModule( ModuleName, ModuleStatus ) ) )
|
||||
{
|
||||
//@todo This is for content-only packages that show up in the
|
||||
// Module UI... don't crash when recompile is clicked
|
||||
if (FPaths::IsProjectFilePathSet())
|
||||
{
|
||||
if (ModuleStatus.bIsLoaded == false)
|
||||
{
|
||||
if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*ModuleStatus.FilePath) == false)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Unable to recompile module %s... Is it a content-only module?"), *ModuleName.ToString());
|
||||
GWarn->EndSlowTask();
|
||||
return FReply::Handled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TArray< UPackage* > PackagesToRebind;
|
||||
if( ModuleStatus.bIsLoaded )
|
||||
{
|
||||
const bool bIsHotReloadable = FModuleManager::Get().DoesLoadedModuleHaveUObjects( ModuleName );
|
||||
if( bIsHotReloadable )
|
||||
{
|
||||
// Is there a UPackage with the same name as this module?
|
||||
FString PotentialPackageName = FString(TEXT("/Script/")) + ModuleName.ToString();
|
||||
UPackage* Package = FindPackage( NULL, *PotentialPackageName);
|
||||
if( Package != NULL )
|
||||
{
|
||||
PackagesToRebind.Add( Package );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( PackagesToRebind.Num() > 0 )
|
||||
{
|
||||
// Perform a hot reload
|
||||
const bool bWaitForCompletion = true;
|
||||
RebindPackages( PackagesToRebind, TArray<FName>(), bWaitForCompletion, *GLog );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Perform a regular unload, then reload
|
||||
const bool bReloadAfterRecompile = true;
|
||||
FModuleManager::Get().RecompileModule( ModuleName, bReloadAfterRecompile, *GLog );
|
||||
}
|
||||
}
|
||||
|
||||
GWarn->EndSlowTask();
|
||||
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
|
||||
EVisibility SModuleUI::FModuleListItem::GetVisibilityBasedOnLoadedAndShutdownableState() const
|
||||
{
|
||||
if ( GIsSavingPackage || GIsGarbageCollecting )
|
||||
{
|
||||
return EVisibility::Hidden;
|
||||
}
|
||||
|
||||
const bool bIsHotReloadable = FModuleManager::Get().DoesLoadedModuleHaveUObjects(ModuleName);
|
||||
const bool bCanShutDown = ( FModuleManager::Get().IsModuleLoaded(ModuleName)
|
||||
&& !bIsHotReloadable
|
||||
&& FModuleManager::Get().GetModuleInterface(ModuleName).SupportsDynamicReloading() );
|
||||
|
||||
return bCanShutDown ? EVisibility::Visible : EVisibility::Hidden;
|
||||
}
|
||||
|
||||
|
||||
EVisibility SModuleUI::FModuleListItem::GetVisibilityBasedOnReloadableState() const
|
||||
{
|
||||
return GetVisibilityBasedOnLoadedAndShutdownableState();
|
||||
};
|
||||
|
||||
|
||||
EVisibility SModuleUI::FModuleListItem::GetVisibilityBasedOnRecompilableState() const
|
||||
{
|
||||
if ( GIsSavingPackage || GIsGarbageCollecting )
|
||||
{
|
||||
return EVisibility::Hidden;
|
||||
}
|
||||
|
||||
const bool bIsHotReloadable = FModuleManager::Get().DoesLoadedModuleHaveUObjects(ModuleName);
|
||||
const bool bCanReload = ( !FModuleManager::Get().IsModuleLoaded(ModuleName)
|
||||
|| FModuleManager::Get().GetModuleInterface(ModuleName).SupportsDynamicReloading()
|
||||
|| bIsHotReloadable );
|
||||
|
||||
return bCanReload ? EVisibility::Visible : EVisibility::Hidden;
|
||||
}
|
||||
|
||||
|
||||
EVisibility SModuleUI::FModuleListItem::GetVisibilityBasedOnUnloadedState() const
|
||||
{
|
||||
return FModuleManager::Get().IsModuleLoaded( ModuleName ) ? EVisibility::Hidden : EVisibility::Visible;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user