fixed build issues, added binaries, and updated the AsyncLoadingScreen plugin directory

This commit is contained in:
Devrim Yasar
2025-04-14 13:03:05 -05:00
parent b91d8c9412
commit cc50ba0c39
2200 changed files with 910483 additions and 318 deletions

View File

@ -0,0 +1,201 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "AsyncLoadingScreen.h"
#include "MoviePlayer.h"
#include "LoadingScreenSettings.h"
#include "SCenterLayout.h"
#include "SClassicLayout.h"
#include "SLetterboxLayout.h"
#include "SSidebarLayout.h"
#include "SDualSidebarLayout.h"
#include "Framework/Application/SlateApplication.h"
#include "AsyncLoadingScreenLibrary.h"
#include "Engine/Texture2D.h"
#define LOCTEXT_NAMESPACE "FAsyncLoadingScreenModule"
void FAsyncLoadingScreenModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
if (!IsRunningDedicatedServer() && FSlateApplication::IsInitialized())
{
const ULoadingScreenSettings* Settings = GetDefault<ULoadingScreenSettings>();
if (IsMoviePlayerEnabled())
{
GetMoviePlayer()->OnPrepareLoadingScreen().AddRaw(this, &FAsyncLoadingScreenModule::PreSetupLoadingScreen);
}
// If PreloadBackgroundImages option is check, load all background images into memory
if (Settings->bPreloadBackgroundImages)
{
LoadBackgroundImages();
}
// Prepare the startup screen, the PreSetupLoadingScreen callback won't be called
// if we've already explicitly setup the loading screen
bIsStartupLoadingScreen = true;
SetupLoadingScreen(Settings->StartupLoadingScreen);
}
}
void FAsyncLoadingScreenModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
if (!IsRunningDedicatedServer())
{
// TODO: Unregister later
GetMoviePlayer()->OnPrepareLoadingScreen().RemoveAll(this);
}
}
bool FAsyncLoadingScreenModule::IsGameModule() const
{
return true;
}
TArray<UTexture2D*> FAsyncLoadingScreenModule::GetBackgroundImages()
{
return bIsStartupLoadingScreen ? StartupBackgroundImages : DefaultBackgroundImages;
}
void FAsyncLoadingScreenModule::PreSetupLoadingScreen()
{
UE_LOG(LogTemp, Warning, TEXT("PreSetupLoadingScreen"));
const bool bIsEnableLoadingScreen = UAsyncLoadingScreenLibrary::GetIsEnableLoadingScreen();
if (bIsEnableLoadingScreen)
{
const ULoadingScreenSettings* Settings = GetDefault<ULoadingScreenSettings>();
bIsStartupLoadingScreen = false;
SetupLoadingScreen(Settings->DefaultLoadingScreen);
}
}
void FAsyncLoadingScreenModule::SetupLoadingScreen(const FALoadingScreenSettings& LoadingScreenSettings)
{
TArray<FString> MoviesList = LoadingScreenSettings.MoviePaths;
// Shuffle the movies list
if (LoadingScreenSettings.bShuffle == true)
{
ShuffleMovies(MoviesList);
}
if (LoadingScreenSettings.bSetDisplayMovieIndexManually == true)
{
MoviesList.Empty();
// Show specific movie if valid otherwise show original movies list
if (LoadingScreenSettings.MoviePaths.IsValidIndex(UAsyncLoadingScreenLibrary::GetDisplayMovieIndex()))
{
MoviesList.Add(LoadingScreenSettings.MoviePaths[UAsyncLoadingScreenLibrary::GetDisplayMovieIndex()]);
}
else
{
MoviesList = LoadingScreenSettings.MoviePaths;
}
}
FLoadingScreenAttributes LoadingScreen;
LoadingScreen.MinimumLoadingScreenDisplayTime = LoadingScreenSettings.MinimumLoadingScreenDisplayTime;
LoadingScreen.bAutoCompleteWhenLoadingCompletes = LoadingScreenSettings.bAutoCompleteWhenLoadingCompletes;
LoadingScreen.bMoviesAreSkippable = LoadingScreenSettings.bMoviesAreSkippable;
LoadingScreen.bWaitForManualStop = LoadingScreenSettings.bWaitForManualStop;
LoadingScreen.bAllowInEarlyStartup = LoadingScreenSettings.bAllowInEarlyStartup;
LoadingScreen.bAllowEngineTick = LoadingScreenSettings.bAllowEngineTick;
LoadingScreen.MoviePaths = MoviesList;
LoadingScreen.PlaybackType = LoadingScreenSettings.PlaybackType;
if (LoadingScreenSettings.bShowWidgetOverlay)
{
const ULoadingScreenSettings* Settings = GetDefault<ULoadingScreenSettings>();
switch (LoadingScreenSettings.Layout)
{
case EAsyncLoadingScreenLayout::ALSL_Classic:
LoadingScreen.WidgetLoadingScreen = SNew(SClassicLayout, LoadingScreenSettings, Settings->Classic);
break;
case EAsyncLoadingScreenLayout::ALSL_Center:
LoadingScreen.WidgetLoadingScreen = SNew(SCenterLayout, LoadingScreenSettings, Settings->Center);
break;
case EAsyncLoadingScreenLayout::ALSL_Letterbox:
LoadingScreen.WidgetLoadingScreen = SNew(SLetterboxLayout, LoadingScreenSettings, Settings->Letterbox);
break;
case EAsyncLoadingScreenLayout::ALSL_Sidebar:
LoadingScreen.WidgetLoadingScreen = SNew(SSidebarLayout, LoadingScreenSettings, Settings->Sidebar);
break;
case EAsyncLoadingScreenLayout::ALSL_DualSidebar:
LoadingScreen.WidgetLoadingScreen = SNew(SDualSidebarLayout, LoadingScreenSettings, Settings->DualSidebar);
break;
}
}
GetMoviePlayer()->SetupLoadingScreen(LoadingScreen);
}
void FAsyncLoadingScreenModule::ShuffleMovies(TArray<FString>& MoviesList)
{
if (MoviesList.Num() > 0)
{
int32 LastIndex = MoviesList.Num() - 1;
for (int32 i = 0; i <= LastIndex; ++i)
{
int32 Index = FMath::RandRange(i, LastIndex);
if (i != Index)
{
MoviesList.Swap(i, Index);
}
}
}
}
void FAsyncLoadingScreenModule::LoadBackgroundImages()
{
// Empty all background images array
RemoveAllBackgroundImages();
const ULoadingScreenSettings* Settings = GetDefault<ULoadingScreenSettings>();
// Preload startup background images
for (auto& Image : Settings->StartupLoadingScreen.Background.Images)
{
UTexture2D* LoadedImage = Cast<UTexture2D>(Image.TryLoad());
if (LoadedImage)
{
StartupBackgroundImages.Add(LoadedImage);
}
}
// Preload default background images
for (auto& Image : Settings->DefaultLoadingScreen.Background.Images)
{
UTexture2D* LoadedImage = Cast<UTexture2D> (Image.TryLoad());
if (LoadedImage)
{
DefaultBackgroundImages.Add(LoadedImage);
}
}
}
void FAsyncLoadingScreenModule::RemoveAllBackgroundImages()
{
StartupBackgroundImages.Empty();
DefaultBackgroundImages.Empty();
}
bool FAsyncLoadingScreenModule::IsPreloadBackgroundImagesEnabled()
{
return GetDefault<ULoadingScreenSettings>()->bPreloadBackgroundImages;
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FAsyncLoadingScreenModule, AsyncLoadingScreen)

View File

@ -0,0 +1,64 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "AsyncLoadingScreenLibrary.h"
#include "MoviePlayer.h"
#include "AsyncLoadingScreen.h"
int32 UAsyncLoadingScreenLibrary::DisplayBackgroundIndex = -1;
int32 UAsyncLoadingScreenLibrary::DisplayTipTextIndex = -1;
int32 UAsyncLoadingScreenLibrary::DisplayMovieIndex = -1;
bool UAsyncLoadingScreenLibrary::bShowLoadingScreen = true;
void UAsyncLoadingScreenLibrary::SetDisplayBackgroundIndex(int32 BackgroundIndex)
{
UAsyncLoadingScreenLibrary::DisplayBackgroundIndex = BackgroundIndex;
}
void UAsyncLoadingScreenLibrary::SetDisplayTipTextIndex(int32 TipTextIndex)
{
UAsyncLoadingScreenLibrary::DisplayTipTextIndex = TipTextIndex;
}
void UAsyncLoadingScreenLibrary::SetDisplayMovieIndex(int32 MovieIndex)
{
UAsyncLoadingScreenLibrary::DisplayMovieIndex = MovieIndex;
}
void UAsyncLoadingScreenLibrary::SetEnableLoadingScreen(bool bIsEnableLoadingScreen)
{
bShowLoadingScreen = bIsEnableLoadingScreen;
}
void UAsyncLoadingScreenLibrary::StopLoadingScreen()
{
GetMoviePlayer()->StopMovie();
}
void UAsyncLoadingScreenLibrary::PreloadBackgroundImages()
{
if (FAsyncLoadingScreenModule::IsAvailable())
{
FAsyncLoadingScreenModule& LoadingScreenModule = FAsyncLoadingScreenModule::Get();
if (LoadingScreenModule.IsPreloadBackgroundImagesEnabled())
{
LoadingScreenModule.LoadBackgroundImages();
}
}
}
void UAsyncLoadingScreenLibrary::RemovePreloadedBackgroundImages()
{
if (FAsyncLoadingScreenModule::IsAvailable())
{
FAsyncLoadingScreenModule& LoadingScreenModule = FAsyncLoadingScreenModule::Get();
LoadingScreenModule.RemoveAllBackgroundImages();
}
}

View File

@ -0,0 +1,39 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "LoadingScreenSettings.h"
#include "UObject/ConstructorHelpers.h"
#include "Engine/Font.h"
#define LOCTEXT_NAMESPACE "AsyncLoadingScreen"
FLoadingWidgetSettings::FLoadingWidgetSettings() : LoadingText(LOCTEXT("Loading", "LOADING")) {}
//FLoadingCompleteTextSettings::FLoadingCompleteTextSettings() : LoadingCompleteText(LOCTEXT("Loading Complete", "Loading is complete! Press any key to continue...")) {}
ULoadingScreenSettings::ULoadingScreenSettings(const FObjectInitializer& Initializer) : Super(Initializer)
{
StartupLoadingScreen.TipWidget.TipWrapAt = 1000.0f;
StartupLoadingScreen.bShowWidgetOverlay = false;
DefaultLoadingScreen.TipWidget.TipWrapAt = 1000.0f;
// Set default font
if (!IsRunningDedicatedServer())
{
static ConstructorHelpers::FObjectFinder<UFont> RobotoFontObj(TEXT("/Engine/EngineFonts/Roboto"));
StartupLoadingScreen.TipWidget.Appearance.Font = FSlateFontInfo(RobotoFontObj.Object, 20, FName("Normal"));
DefaultLoadingScreen.TipWidget.Appearance.Font = FSlateFontInfo(RobotoFontObj.Object, 20, FName("Normal"));
StartupLoadingScreen.LoadingWidget.Appearance.Font = FSlateFontInfo(RobotoFontObj.Object, 32, FName("Bold"));
DefaultLoadingScreen.LoadingWidget.Appearance.Font = FSlateFontInfo(RobotoFontObj.Object, 32, FName("Bold"));
StartupLoadingScreen.LoadingCompleteTextSettings.Appearance.Font = FSlateFontInfo(RobotoFontObj.Object, 24, FName("Normal"));
DefaultLoadingScreen.LoadingCompleteTextSettings.Appearance.Font = FSlateFontInfo(RobotoFontObj.Object, 24, FName("Normal"));
}
}
#undef LOCTEXT_NAMESPACE

View File

@ -0,0 +1,72 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "SBackgroundWidget.h"
#include "LoadingScreenSettings.h"
#include "Slate/DeferredCleanupSlateBrush.h"
#include "Widgets/Images/SImage.h"
#include "Widgets/Layout/SBorder.h"
#include "Engine/Texture2D.h"
#include "AsyncLoadingScreenLibrary.h"
#include "AsyncLoadingScreen.h"
void SBackgroundWidget::Construct(const FArguments& InArgs, const FBackgroundSettings& Settings)
{
// If there's an image defined
if (Settings.Images.Num() > 0)
{
int32 ImageIndex = FMath::RandRange(0, Settings.Images.Num() - 1);
if (Settings.bSetDisplayBackgroundManually == true)
{
if (Settings.Images.IsValidIndex(UAsyncLoadingScreenLibrary::GetDisplayBackgroundIndex()))
{
ImageIndex = UAsyncLoadingScreenLibrary::GetDisplayBackgroundIndex();
}
}
// Load background from settings
UTexture2D* LoadingImage = nullptr;
const FSoftObjectPath& ImageAsset = Settings.Images[ImageIndex];
UObject* ImageObject = ImageAsset.TryLoad();
LoadingImage = Cast<UTexture2D>(ImageObject);
// If IsPreloadBackgroundImagesEnabled is enabled, load from images array
FAsyncLoadingScreenModule& LoadingScreenModule = FAsyncLoadingScreenModule::Get();
if (LoadingScreenModule.IsPreloadBackgroundImagesEnabled())
{
TArray<UTexture2D*> BackgroundImages = LoadingScreenModule.GetBackgroundImages();
if (!BackgroundImages.IsEmpty() && BackgroundImages.IsValidIndex(ImageIndex))
{
LoadingImage = BackgroundImages[ImageIndex];
}
}
if (LoadingImage)
{
ImageBrush = FDeferredCleanupSlateBrush::CreateBrush(LoadingImage);
ChildSlot
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.Padding(Settings.Padding)
.BorderBackgroundColor(Settings.BackgroundColor)
.BorderImage(FCoreStyle::Get().GetBrush("WhiteBrush"))
[
SNew(SScaleBox)
.Stretch(Settings.ImageStretch)
[
SNew(SImage)
.Image(ImageBrush.IsValid() ? ImageBrush->GetSlateBrush() : nullptr)
]
]
];
}
}
}

View File

@ -0,0 +1,129 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "SCenterLayout.h"
#include "LoadingScreenSettings.h"
#include "Widgets/Layout/SSafeZone.h"
#include "Widgets/Layout/SDPIScaler.h"
#include "SHorizontalLoadingWidget.h"
#include "SVerticalLoadingWidget.h"
#include "SBackgroundWidget.h"
#include "STipWidget.h"
#include "Widgets/SOverlay.h"
#include "Widgets/Layout/SBorder.h"
#include "SLoadingCompleteText.h"
void SCenterLayout::Construct(const FArguments& InArgs, const FALoadingScreenSettings& Settings, const FCenterLayoutSettings& LayoutSettings)
{
// Root widget and background
TSharedRef<SOverlay> Root = SNew(SOverlay)
+ SOverlay::Slot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SBackgroundWidget, Settings.Background)
];
// Placeholder for loading widget
TSharedRef<SWidget> LoadingWidget = SNullWidget::NullWidget;
if (Settings.LoadingWidget.LoadingWidgetType == ELoadingWidgetType::LWT_Horizontal)
{
LoadingWidget = SNew(SHorizontalLoadingWidget, Settings.LoadingWidget);
}
else
{
LoadingWidget = SNew(SVerticalLoadingWidget, Settings.LoadingWidget);
}
// Add loading widget at center
Root->AddSlot()
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
LoadingWidget
];
if (LayoutSettings.bIsTipAtBottom)
{
// Add tip widget at bottom
Root->AddSlot()
.HAlign(LayoutSettings.BorderHorizontalAlignment)
.VAlign(VAlign_Bottom)
.Padding(0, 0, 0, LayoutSettings.BorderVerticalOffset)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.BorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(LayoutSettings.TipAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.TipAlignment.VerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.BorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SCenterLayout::GetDPIScale)
[
SNew(STipWidget, Settings.TipWidget)
]
]
]
];
}
else
{
// Add tip widget at top
Root->AddSlot()
.HAlign(LayoutSettings.BorderHorizontalAlignment)
.VAlign(VAlign_Top)
.Padding(0, LayoutSettings.BorderVerticalOffset, 0, 0)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.BorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(LayoutSettings.TipAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.TipAlignment.VerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.BorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SCenterLayout::GetDPIScale)
[
SNew(STipWidget, Settings.TipWidget)
]
]
]
];
}
// Construct loading complete text if enable
if (Settings.bShowLoadingCompleteText)
{
Root->AddSlot()
.VAlign(Settings.LoadingCompleteTextSettings.Alignment.VerticalAlignment)
.HAlign(Settings.LoadingCompleteTextSettings.Alignment.HorizontalAlignment)
.Padding(Settings.LoadingCompleteTextSettings.Padding)
[
SNew(SLoadingCompleteText, Settings.LoadingCompleteTextSettings)
];
}
// Add root to this widget
ChildSlot
[
Root
];
}

View File

@ -0,0 +1,162 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "SClassicLayout.h"
#include "LoadingScreenSettings.h"
#include "Widgets/Layout/SSafeZone.h"
#include "Widgets/Layout/SDPIScaler.h"
#include "Widgets/Layout/SSpacer.h"
#include "Widgets/SBoxPanel.h"
#include "SHorizontalLoadingWidget.h"
#include "SVerticalLoadingWidget.h"
#include "SBackgroundWidget.h"
#include "STipWidget.h"
#include "SLoadingCompleteText.h"
void SClassicLayout::Construct(const FArguments& InArgs, const FALoadingScreenSettings& Settings, const FClassicLayoutSettings& LayoutSettings)
{
// Root widget and background
TSharedRef<SOverlay> Root = SNew(SOverlay)
+ SOverlay::Slot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SBackgroundWidget, Settings.Background)
];
// Placeholder for loading widget
TSharedRef<SWidget> LoadingWidget = SNullWidget::NullWidget;
if (Settings.LoadingWidget.LoadingWidgetType == ELoadingWidgetType::LWT_Horizontal)
{
LoadingWidget = SNew(SHorizontalLoadingWidget, Settings.LoadingWidget);
}
else
{
LoadingWidget = SNew(SVerticalLoadingWidget, Settings.LoadingWidget);
}
TSharedRef<SHorizontalBox> HorizontalBox = SNew(SHorizontalBox);
if (LayoutSettings.bIsLoadingWidgetAtLeft)
{
// Add Loading widget on left first
HorizontalBox.Get().AddSlot()
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
.AutoWidth()
[
LoadingWidget
];
// Add spacer at midder
HorizontalBox.Get().AddSlot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.AutoWidth()
[
SNew(SSpacer)
.Size(FVector2D(LayoutSettings.Space, 0.0f))
];
// Tip Text on the right
HorizontalBox.Get().AddSlot()
.FillWidth(1.0f)
.HAlign(LayoutSettings.TipAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.TipAlignment.VerticalAlignment)
[
SNew(STipWidget, Settings.TipWidget)
];
}
else
{
// Tip Text on the left
HorizontalBox.Get().AddSlot()
.FillWidth(1.0f)
.HAlign(LayoutSettings.TipAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.TipAlignment.VerticalAlignment)
[
// Add tip text
SNew(STipWidget, Settings.TipWidget)
];
// Add spacer at midder
HorizontalBox.Get().AddSlot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.AutoWidth()
[
SNew(SSpacer)
.Size(FVector2D(LayoutSettings.Space, 0.0f))
];
// Add Loading widget on right
HorizontalBox.Get().AddSlot()
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
.AutoWidth()
[
LoadingWidget
];
}
EVerticalAlignment VerticalAlignment;
// Set vertical alignment for widget
if (LayoutSettings.bIsWidgetAtBottom)
{
VerticalAlignment = EVerticalAlignment::VAlign_Bottom;
}
else
{
VerticalAlignment = EVerticalAlignment::VAlign_Top;
}
// Creating loading theme
Root->AddSlot()
.HAlign(LayoutSettings.BorderHorizontalAlignment)
.VAlign(VerticalAlignment)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.BorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.IsTitleSafe(true)
.Padding(LayoutSettings.BorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SClassicLayout::GetDPIScale)
[
HorizontalBox
]
]
]
];
// Construct loading complete text if enable
if (Settings.bShowLoadingCompleteText)
{
Root->AddSlot()
.VAlign(Settings.LoadingCompleteTextSettings.Alignment.VerticalAlignment)
.HAlign(Settings.LoadingCompleteTextSettings.Alignment.HorizontalAlignment)
.Padding(Settings.LoadingCompleteTextSettings.Padding)
[
SNew(SLoadingCompleteText, Settings.LoadingCompleteTextSettings)
];
}
// Add root to this widget
ChildSlot
[
Root
];
}

View File

@ -0,0 +1,172 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "SDualSidebarLayout.h"
#include "LoadingScreenSettings.h"
#include "Widgets/Layout/SSafeZone.h"
#include "Widgets/Layout/SDPIScaler.h"
#include "Widgets/Layout/SSpacer.h"
#include "SHorizontalLoadingWidget.h"
#include "SVerticalLoadingWidget.h"
#include "SBackgroundWidget.h"
#include "STipWidget.h"
#include "SLoadingCompleteText.h"
void SDualSidebarLayout::Construct(const FArguments& InArgs, const FALoadingScreenSettings& Settings, const FDualSidebarLayoutSettings& LayoutSettings)
{
// Root widget and background
TSharedRef<SOverlay> Root = SNew(SOverlay)
+ SOverlay::Slot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SBackgroundWidget, Settings.Background)
];
// Placeholder for loading widget
TSharedRef<SWidget> LoadingWidget = SNullWidget::NullWidget;
if (Settings.LoadingWidget.LoadingWidgetType == ELoadingWidgetType::LWT_Horizontal)
{
LoadingWidget = SNew(SHorizontalLoadingWidget, Settings.LoadingWidget);
}
else
{
LoadingWidget = SNew(SVerticalLoadingWidget, Settings.LoadingWidget);
}
if (LayoutSettings.bIsLoadingWidgetAtRight)
{
// Add loading widget at right
Root.Get().AddSlot()
.HAlign(HAlign_Right)
.VAlign(LayoutSettings.RightBorderVerticalAlignment)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.RightBorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(HAlign_Fill)
.VAlign(LayoutSettings.RightVerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.RightBorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SDualSidebarLayout::GetDPIScale)
[
LoadingWidget
]
]
]
];
// Add tip widget at left
Root.Get().AddSlot()
.HAlign(HAlign_Left)
.VAlign(LayoutSettings.LeftBorderVerticalAlignment)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.LeftBorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(HAlign_Fill)
.VAlign(LayoutSettings.LeftVerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.LeftBorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SDualSidebarLayout::GetDPIScale)
[
SNew(STipWidget, Settings.TipWidget)
]
]
]
];
}
else
{
// Add Tip widget at right
Root.Get().AddSlot()
.HAlign(HAlign_Right)
.VAlign(LayoutSettings.RightBorderVerticalAlignment)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.RightBorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(HAlign_Fill)
.VAlign(LayoutSettings.RightVerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.RightBorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SDualSidebarLayout::GetDPIScale)
[
SNew(STipWidget, Settings.TipWidget)
]
]
]
];
// Add Loading widget at left
Root.Get().AddSlot()
.HAlign(HAlign_Left)
.VAlign(LayoutSettings.LeftBorderVerticalAlignment)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.LeftBorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(HAlign_Fill)
.VAlign(LayoutSettings.LeftVerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.LeftBorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SDualSidebarLayout::GetDPIScale)
[
LoadingWidget
]
]
]
];
}
// Construct loading complete text if enable
if (Settings.bShowLoadingCompleteText)
{
Root->AddSlot()
.VAlign(Settings.LoadingCompleteTextSettings.Alignment.VerticalAlignment)
.HAlign(Settings.LoadingCompleteTextSettings.Alignment.HorizontalAlignment)
.Padding(Settings.LoadingCompleteTextSettings.Padding)
[
SNew(SLoadingCompleteText, Settings.LoadingCompleteTextSettings)
];
}
// Add root to this widget
ChildSlot
[
Root
];
}

View File

@ -0,0 +1,122 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "SHorizontalLoadingWidget.h"
#include "LoadingScreenSettings.h"
#include "Widgets/Layout/SSpacer.h"
#include "Widgets/Images/SImage.h"
#include "Slate/DeferredCleanupSlateBrush.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/SBoxPanel.h"
void SHorizontalLoadingWidget::Construct(const FArguments& InArgs, const FLoadingWidgetSettings& Settings)
{
bPlayReverse = Settings.ImageSequenceSettings.bPlayReverse;
// Root is a Horizontal Box of course
TSharedRef<SHorizontalBox> Root = SNew(SHorizontalBox);
// Construct Loading Icon Widget
ConstructLoadingIcon(Settings);
EVisibility LoadingTextVisibility;
if (Settings.LoadingText.IsEmpty())
{
LoadingTextVisibility = EVisibility::Collapsed;
}
else
{
LoadingTextVisibility = EVisibility::SelfHitTestInvisible;
}
// If loading text is on the right
if (Settings.bLoadingTextRightPosition)
{
// Add Loading Icon on the left first
Root.Get().AddSlot()
.HAlign(Settings.LoadingIconAlignment.HorizontalAlignment)
.VAlign(Settings.LoadingIconAlignment.VerticalAlignment)
.AutoWidth()
[
LoadingIcon
];
// Add a Spacer in middle
Root.Get().AddSlot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.AutoWidth()
[
SNew(SSpacer)
.Size(FVector2D(Settings.Space, 0.0f))
];
// Add Loading Text on the right
Root.Get().AddSlot()
.HAlign(Settings.TextAlignment.HorizontalAlignment)
.VAlign(Settings.TextAlignment.VerticalAlignment)
.AutoWidth()
[
SNew(STextBlock)
.Visibility(LoadingTextVisibility)
.ColorAndOpacity(Settings.Appearance.ColorAndOpacity)
.Font(Settings.Appearance.Font)
.ShadowOffset(Settings.Appearance.ShadowOffset)
.ShadowColorAndOpacity(Settings.Appearance.ShadowColorAndOpacity)
.Justification(Settings.Appearance.Justification)
.Text(Settings.LoadingText)
];
}
// If loading text is on the left
else
{
// Add Loading Text on the left first
Root.Get().AddSlot()
.HAlign(Settings.TextAlignment.HorizontalAlignment)
.VAlign(Settings.TextAlignment.VerticalAlignment)
.AutoWidth()
[
SNew(STextBlock)
.Visibility(LoadingTextVisibility)
.ColorAndOpacity(Settings.Appearance.ColorAndOpacity)
.Font(Settings.Appearance.Font)
.ShadowOffset(Settings.Appearance.ShadowOffset)
.ShadowColorAndOpacity(Settings.Appearance.ShadowColorAndOpacity)
.Justification(Settings.Appearance.Justification)
.Text(Settings.LoadingText)
];
// Add a Spacer in middle
Root.Get().AddSlot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.AutoWidth()
[
SNew(SSpacer)
.Size(FVector2D(Settings.Space, 0.0f))
];
// Add Loading Icon on the right finally
Root.Get().AddSlot()
.HAlign(Settings.LoadingIconAlignment.HorizontalAlignment)
.VAlign(Settings.LoadingIconAlignment.VerticalAlignment)
.AutoWidth()
[
LoadingIcon
];
}
// Add root to this widget
ChildSlot
[
Root
];
}

View File

@ -0,0 +1,168 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "SLetterboxLayout.h"
#include "LoadingScreenSettings.h"
#include "Widgets/Layout/SSafeZone.h"
#include "Widgets/Layout/SDPIScaler.h"
#include "SHorizontalLoadingWidget.h"
#include "SVerticalLoadingWidget.h"
#include "SBackgroundWidget.h"
#include "STipWidget.h"
#include "SLoadingCompleteText.h"
void SLetterboxLayout::Construct(const FArguments& InArgs, const FALoadingScreenSettings& Settings, const FLetterboxLayoutSettings& LayoutSettings)
{
// Root widget and background
TSharedRef<SOverlay> Root = SNew(SOverlay)
+ SOverlay::Slot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SBackgroundWidget, Settings.Background)
];
// Placeholder for loading widget
TSharedRef<SWidget> LoadingWidget = SNullWidget::NullWidget;
if (Settings.LoadingWidget.LoadingWidgetType == ELoadingWidgetType::LWT_Horizontal)
{
LoadingWidget = SNew(SHorizontalLoadingWidget, Settings.LoadingWidget);
}
else
{
LoadingWidget = SNew(SVerticalLoadingWidget, Settings.LoadingWidget);
}
if (LayoutSettings.bIsLoadingWidgetAtTop)
{
// Add a border widget at top, then add Loading widget
Root->AddSlot()
.HAlign(LayoutSettings.TopBorderHorizontalAlignment)
.VAlign(VAlign_Top)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.TopBorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(LayoutSettings.LoadingWidgetAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.LoadingWidgetAlignment.VerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.TopBorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SLetterboxLayout::GetDPIScale)
[
LoadingWidget
]
]
]
];
// Add a border widget at bottom, then add Tip widget
Root->AddSlot()
.HAlign(LayoutSettings.BottomBorderHorizontalAlignment)
.VAlign(VAlign_Bottom)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.BottomBorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(LayoutSettings.TipAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.TipAlignment.VerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.BottomBorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SLetterboxLayout::GetDPIScale)
[
SNew(STipWidget, Settings.TipWidget)
]
]
]
];
}
else
{
// Add a border widget at top, then add Tip widget
Root->AddSlot()
.HAlign(LayoutSettings.TopBorderHorizontalAlignment)
.VAlign(VAlign_Top)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.TopBorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(LayoutSettings.TipAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.TipAlignment.VerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.TopBorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SLetterboxLayout::GetDPIScale)
[
SNew(STipWidget, Settings.TipWidget)
]
]
]
];
// Add a border widget at bottom, then add Loading widget
Root->AddSlot()
.HAlign(LayoutSettings.BottomBorderHorizontalAlignment)
.VAlign(VAlign_Bottom)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.BottomBorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(LayoutSettings.LoadingWidgetAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.LoadingWidgetAlignment.VerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.BottomBorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SLetterboxLayout::GetDPIScale)
[
LoadingWidget
]
]
]
];
}
// Construct loading complete text if enable
if (Settings.bShowLoadingCompleteText)
{
Root->AddSlot()
.VAlign(Settings.LoadingCompleteTextSettings.Alignment.VerticalAlignment)
.HAlign(Settings.LoadingCompleteTextSettings.Alignment.HorizontalAlignment)
.Padding(Settings.LoadingCompleteTextSettings.Padding)
[
SNew(SLoadingCompleteText, Settings.LoadingCompleteTextSettings)
];
}
// Add Root to this widget
ChildSlot
[
Root
];
}

View File

@ -0,0 +1,78 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "SLoadingCompleteText.h"
#include "LoadingScreenSettings.h"
#include "MoviePlayer.h"
#include "Widgets/Text/STextBlock.h"
void SLoadingCompleteText::Construct(const FArguments& InArgs, const FLoadingCompleteTextSettings& CompleteTextSettings)
{
CompleteTextColor = CompleteTextSettings.Appearance.ColorAndOpacity.GetSpecifiedColor();
CompleteTextAnimationSpeed = CompleteTextSettings.AnimationSpeed;
ChildSlot
[
SNew(STextBlock)
.Font(CompleteTextSettings.Appearance.Font)
.ShadowOffset(CompleteTextSettings.Appearance.ShadowOffset)
.ShadowColorAndOpacity(CompleteTextSettings.Appearance.ShadowColorAndOpacity)
.Justification(CompleteTextSettings.Appearance.Justification)
.Text(CompleteTextSettings.LoadingCompleteText)
.ColorAndOpacity(this, &SLoadingCompleteText::GetLoadingCompleteTextColor)
.Visibility(this, &SLoadingCompleteText::GetLoadingCompleteTextVisibility)
];
// Register animated image sequence active timer event
if (CompleteTextSettings.bFadeInOutAnim && !bIsActiveTimerRegistered)
{
bIsActiveTimerRegistered = true;
RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &SLoadingCompleteText::AnimateText));
}
}
EVisibility SLoadingCompleteText::GetLoadingCompleteTextVisibility() const
{
return GetMoviePlayer()->IsLoadingFinished() ? EVisibility::Visible : EVisibility::Hidden;
}
FSlateColor SLoadingCompleteText::GetLoadingCompleteTextColor() const
{
return CompleteTextColor;
}
EActiveTimerReturnType SLoadingCompleteText::AnimateText(double InCurrentTime, float InDeltaTime)
{
const float MinAlpha = 0.1f;
const float MaxAlpha = 1.0f;
float TextAlpha = CompleteTextColor.A;
if (TextAlpha >= MaxAlpha)
{
bCompleteTextReverseAnim = true;
}
else if (TextAlpha <= MinAlpha)
{
bCompleteTextReverseAnim = false;
}
if (!bCompleteTextReverseAnim)
{
TextAlpha += InDeltaTime * CompleteTextAnimationSpeed;
}
else
{
TextAlpha -= InDeltaTime * CompleteTextAnimationSpeed;
}
CompleteTextColor.A = TextAlpha;
return EActiveTimerReturnType::Continue;
}

View File

@ -0,0 +1,47 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "SLoadingScreenLayout.h"
#include "Engine/UserInterfaceSettings.h"
#include "Engine/Engine.h"
#include "Engine/GameViewportClient.h"
float SLoadingScreenLayout::PointSizeToSlateUnits(float PointSize)
{
const float SlateFreeTypeHorizontalResolutionDPI = 96.0f;
const float FreeTypeNativeDPI = 72.0;
const float PixelSize = PointSize * (SlateFreeTypeHorizontalResolutionDPI / FreeTypeNativeDPI);
return PixelSize;
}
float SLoadingScreenLayout::GetDPIScale() const
{
FIntPoint Size;
if (GEngine && GEngine->GameViewport)
{
FVector2D ViewportSize;
GEngine->GameViewport->GetViewportSize(ViewportSize);
int32 X = FGenericPlatformMath::FloorToInt(ViewportSize.X);
int32 Y = FGenericPlatformMath::FloorToInt(ViewportSize.Y);
Size = FIntPoint(X, Y);
}
else
{
const FVector2D DrawSize = GetTickSpaceGeometry().ToPaintGeometry().GetLocalSize();
if (DrawSize.Equals(FVector2D::ZeroVector))
{
return 1.0f;
}
int32 X = FGenericPlatformMath::FloorToInt(DrawSize.X);
int32 Y = FGenericPlatformMath::FloorToInt(DrawSize.Y);
Size = FIntPoint(X, Y);
}
return FMath::Clamp(GetDefault<UUserInterfaceSettings>()->GetDPIScaleBasedOnSize(Size), 0.1f, 1.0f);
}

View File

@ -0,0 +1,128 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "SLoadingWidget.h"
#include "Widgets/Images/SImage.h"
#include "Slate/DeferredCleanupSlateBrush.h"
#include "Widgets/Layout/SSpacer.h"
#include "Engine/Texture2D.h"
#include "MoviePlayer.h"
#include "Widgets/SCompoundWidget.h"
int32 SLoadingWidget::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
{
TotalDeltaTime += Args.GetDeltaTime();
if (TotalDeltaTime >= Interval)
{
if (CleanupBrushList.Num() > 1)
{
if (bPlayReverse)
{
ImageIndex--;
}
else
{
ImageIndex++;
}
if (ImageIndex >= CleanupBrushList.Num())
{
ImageIndex = 0;
}
else if (ImageIndex < 0)
{
ImageIndex = CleanupBrushList.Num() - 1;
}
StaticCastSharedRef<SImage>(LoadingIcon)->SetImage(CleanupBrushList[ImageIndex].IsValid() ? CleanupBrushList[ImageIndex]->GetSlateBrush() : nullptr);
}
TotalDeltaTime = 0.0f;
}
return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
}
SThrobber::EAnimation SLoadingWidget::GetThrobberAnimation(const FThrobberSettings& ThrobberSettings) const
{
const int32 AnimationParams = (ThrobberSettings.bAnimateVertically ? SThrobber::Vertical : 0) |
(ThrobberSettings.bAnimateHorizontally ? SThrobber::Horizontal : 0) |
(ThrobberSettings.bAnimateOpacity ? SThrobber::Opacity : 0);
return static_cast<SThrobber::EAnimation>(AnimationParams);
}
void SLoadingWidget::ConstructLoadingIcon(const FLoadingWidgetSettings& Settings)
{
if (Settings.LoadingIconType == ELoadingIconType::LIT_ImageSequence)
{
// Loading Widget is image sequence
if (Settings.ImageSequenceSettings.Images.Num() > 0)
{
CleanupBrushList.Empty();
ImageIndex = 0;
FVector2D Scale = Settings.ImageSequenceSettings.Scale;
for (auto Image: Settings.ImageSequenceSettings.Images)
{
if (Image)
{
CleanupBrushList.Add(FDeferredCleanupSlateBrush::CreateBrush(Image, FVector2D(Image->GetSurfaceWidth() * Scale.X, Image->GetSurfaceHeight() * Scale.Y)));
}
}
// Create Image slate widget
LoadingIcon = SNew(SImage)
.Image(CleanupBrushList[ImageIndex]->GetSlateBrush());
// Update play animation interval
Interval = Settings.ImageSequenceSettings.Interval;
}
else
{
// If there is no image in the array then create a spacer instead
LoadingIcon = SNew(SSpacer).Size(FVector2D::ZeroVector);
}
}
else if (Settings.LoadingIconType == ELoadingIconType::LIT_CircularThrobber)
{
// Loading Widget is SCircularThrobber
LoadingIcon = SNew(SCircularThrobber)
.NumPieces(Settings.CircularThrobberSettings.NumberOfPieces)
.Period(Settings.CircularThrobberSettings.Period)
.Radius(Settings.CircularThrobberSettings.Radius)
.PieceImage(&Settings.CircularThrobberSettings.Image);
}
else
{
// Loading Widget is SThrobber
LoadingIcon = SNew(SThrobber)
.NumPieces(Settings.ThrobberSettings.NumberOfPieces)
.Animate(GetThrobberAnimation(Settings.ThrobberSettings))
.PieceImage(&Settings.ThrobberSettings.Image);
}
// Set Loading Icon render transform
LoadingIcon.Get().SetRenderTransform(FSlateRenderTransform(FScale2D(Settings.TransformScale), Settings.TransformTranslation));
LoadingIcon.Get().SetRenderTransformPivot(Settings.TransformPivot);
// Hide loading widget when level loading is done if bHideLoadingWidgetWhenCompletes is true
if (Settings.bHideLoadingWidgetWhenCompletes)
{
SetVisibility(TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateRaw(this, &SLoadingWidget::GetLoadingWidgetVisibility)));
}
}
EVisibility SLoadingWidget::GetLoadingWidgetVisibility() const
{
return GetMoviePlayer()->IsLoadingFinished() ? EVisibility::Hidden : EVisibility::Visible;
}

View File

@ -0,0 +1,184 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "SSidebarLayout.h"
#include "LoadingScreenSettings.h"
#include "Widgets/Layout/SSafeZone.h"
#include "Widgets/Layout/SDPIScaler.h"
#include "Widgets/Layout/SSpacer.h"
#include "SHorizontalLoadingWidget.h"
#include "SVerticalLoadingWidget.h"
#include "SBackgroundWidget.h"
#include "STipWidget.h"
#include "SLoadingCompleteText.h"
#include "Widgets/SBoxPanel.h"
void SSidebarLayout::Construct(const FArguments& InArgs, const FALoadingScreenSettings& Settings, const FSidebarLayoutSettings& LayoutSettings)
{
// Root widget and background
TSharedRef<SOverlay> Root = SNew(SOverlay)
+ SOverlay::Slot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SBackgroundWidget, Settings.Background)
];
// Placeholder for loading widget
TSharedRef<SWidget> LoadingWidget = SNullWidget::NullWidget;
if (Settings.LoadingWidget.LoadingWidgetType == ELoadingWidgetType::LWT_Horizontal)
{
LoadingWidget = SNew(SHorizontalLoadingWidget, Settings.LoadingWidget);
}
else
{
LoadingWidget = SNew(SVerticalLoadingWidget, Settings.LoadingWidget);
}
TSharedRef<SVerticalBox> VerticalBox = SNew(SVerticalBox);
if (LayoutSettings.bIsLoadingWidgetAtTop)
{
// Add loading widget at top
VerticalBox.Get().AddSlot()
.AutoHeight()
.HAlign(LayoutSettings.LoadingWidgetAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.LoadingWidgetAlignment.VerticalAlignment)
[
LoadingWidget
];
// Add SSpacer at middle
VerticalBox.Get().AddSlot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.AutoHeight()
[
SNew(SSpacer)
.Size(FVector2D(0.0f, LayoutSettings.Space))
];
// Add tip widget at bottom
VerticalBox.Get().AddSlot()
.AutoHeight()
.HAlign(LayoutSettings.TipAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.TipAlignment.VerticalAlignment)
[
SNew(STipWidget, Settings.TipWidget)
];
}
else
{
// Add tip widget at top
VerticalBox.Get().AddSlot()
.AutoHeight()
.HAlign(LayoutSettings.TipAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.TipAlignment.VerticalAlignment)
[
SNew(STipWidget, Settings.TipWidget)
];
// Add SSpacer at middle
VerticalBox.Get().AddSlot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.AutoHeight()
[
SNew(SSpacer)
.Size(FVector2D(0.0f, LayoutSettings.Space))
];
// Add loading widget at bottom
VerticalBox.Get().AddSlot()
.AutoHeight()
.HAlign(LayoutSettings.LoadingWidgetAlignment.HorizontalAlignment)
.VAlign(LayoutSettings.LoadingWidgetAlignment.VerticalAlignment)
[
LoadingWidget
];
}
if (LayoutSettings.bIsWidgetAtRight)
{
// Add widget at right
Root.Get().AddSlot()
.HAlign(HAlign_Right)
.VAlign(LayoutSettings.BorderVerticalAlignment)
.Padding(0, 0, LayoutSettings.BorderHorizontalOffset, 0)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.BorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(HAlign_Fill)
.VAlign(LayoutSettings.VerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.BorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SSidebarLayout::GetDPIScale)
[
VerticalBox
]
]
]
];
}
else
{
// Add widget at left
Root.Get().AddSlot()
.HAlign(HAlign_Left)
.VAlign(LayoutSettings.BorderVerticalAlignment)
.Padding(LayoutSettings.BorderHorizontalOffset, 0, 0, 0)
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.BorderImage(&LayoutSettings.BorderBackground)
.BorderBackgroundColor(FLinearColor::White)
[
SNew(SSafeZone)
.HAlign(HAlign_Fill)
.VAlign(LayoutSettings.VerticalAlignment)
.IsTitleSafe(true)
.Padding(LayoutSettings.BorderPadding)
[
SNew(SDPIScaler)
.DPIScale(this, &SSidebarLayout::GetDPIScale)
[
VerticalBox
]
]
]
];
}
// Construct loading complete text if enable
if (Settings.bShowLoadingCompleteText)
{
Root->AddSlot()
.VAlign(Settings.LoadingCompleteTextSettings.Alignment.VerticalAlignment)
.HAlign(Settings.LoadingCompleteTextSettings.Alignment.HorizontalAlignment)
.Padding(Settings.LoadingCompleteTextSettings.Padding)
[
SNew(SLoadingCompleteText, Settings.LoadingCompleteTextSettings)
];
}
// Add root to this widget
ChildSlot
[
Root
];
}

View File

@ -0,0 +1,41 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "STipWidget.h"
#include "LoadingScreenSettings.h"
#include "Widgets/Text/STextBlock.h"
#include "AsyncLoadingScreenLibrary.h"
void STipWidget::Construct(const FArguments& InArgs, const FTipSettings& Settings)
{
if (Settings.TipText.Num() > 0)
{
int32 TipIndex = FMath::RandRange(0, Settings.TipText.Num() - 1);
if (Settings.bSetDisplayTipTextManually == true)
{
if (Settings.TipText.IsValidIndex(UAsyncLoadingScreenLibrary::GetDisplayTipTextIndex()))
{
TipIndex = UAsyncLoadingScreenLibrary::GetDisplayTipTextIndex();
}
}
ChildSlot
[
SNew(STextBlock)
.ColorAndOpacity(Settings.Appearance.ColorAndOpacity)
.Font(Settings.Appearance.Font)
.ShadowOffset(Settings.Appearance.ShadowOffset)
.ShadowColorAndOpacity(Settings.Appearance.ShadowColorAndOpacity)
.Justification(Settings.Appearance.Justification)
.WrapTextAt(Settings.TipWrapAt)
.Text(Settings.TipText[TipIndex])
];
}
}

View File

@ -0,0 +1,120 @@
/************************************************************************************
* *
* Copyright (C) 2020 Truong Bui. *
* Website: https://github.com/truong-bui/AsyncLoadingScreen *
* Licensed under the MIT License. See 'LICENSE' file for full license information. *
* *
************************************************************************************/
#include "SVerticalLoadingWidget.h"
#include "LoadingScreenSettings.h"
#include "Widgets/Layout/SSpacer.h"
#include "Widgets/Images/SImage.h"
#include "Slate/DeferredCleanupSlateBrush.h"
#include "Widgets/Text/STextBlock.h"
void SVerticalLoadingWidget::Construct(const FArguments& InArgs, const FLoadingWidgetSettings& Settings)
{
bPlayReverse = Settings.ImageSequenceSettings.bPlayReverse;
// Root is a Vertical Box
TSharedRef<SVerticalBox> Root = SNew(SVerticalBox);
// Construct Loading Icon Widget
ConstructLoadingIcon(Settings);
EVisibility LoadingTextVisibility;
if (Settings.LoadingText.IsEmpty())
{
LoadingTextVisibility = EVisibility::Collapsed;
}
else
{
LoadingTextVisibility = EVisibility::SelfHitTestInvisible;
}
// If loading text is on the top
if (Settings.bLoadingTextTopPosition)
{
// Add Loading Text on the top first
Root.Get().AddSlot()
.HAlign(Settings.TextAlignment.HorizontalAlignment)
.VAlign(Settings.TextAlignment.VerticalAlignment)
.AutoHeight()
[
SNew(STextBlock)
.Visibility(LoadingTextVisibility)
.ColorAndOpacity(Settings.Appearance.ColorAndOpacity)
.Font(Settings.Appearance.Font)
.ShadowOffset(Settings.Appearance.ShadowOffset)
.ShadowColorAndOpacity(Settings.Appearance.ShadowColorAndOpacity)
.Justification(Settings.Appearance.Justification)
.Text(Settings.LoadingText)
];
// Add a Spacer in middle
Root.Get().AddSlot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.AutoHeight()
[
SNew(SSpacer)
.Size(FVector2D(0.0f, Settings.Space))
];
// Add Loading Icon at the bottom finally
Root.Get().AddSlot()
.HAlign(Settings.LoadingIconAlignment.HorizontalAlignment)
.VAlign(Settings.LoadingIconAlignment.VerticalAlignment)
.AutoHeight()
[
LoadingIcon
];
}
// If loading text is at the bottom
else
{
// Add Loading Icon on the top
Root.Get().AddSlot()
.HAlign(Settings.LoadingIconAlignment.HorizontalAlignment)
.VAlign(Settings.LoadingIconAlignment.VerticalAlignment)
.AutoHeight()
[
LoadingIcon
];
// Add a Spacer in middle
Root.Get().AddSlot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.AutoHeight()
[
SNew(SSpacer)
.Size(FVector2D(0.0f, Settings.Space))
];
// Add Loading Text at the bottom
Root.Get().AddSlot()
.HAlign(Settings.TextAlignment.HorizontalAlignment)
.VAlign(Settings.TextAlignment.VerticalAlignment)
.AutoHeight()
[
SNew(STextBlock)
.Visibility(LoadingTextVisibility)
.ColorAndOpacity(Settings.Appearance.ColorAndOpacity)
.Font(Settings.Appearance.Font)
.ShadowOffset(Settings.Appearance.ShadowOffset)
.ShadowColorAndOpacity(Settings.Appearance.ShadowColorAndOpacity)
.Justification(Settings.Appearance.Justification)
.Text(Settings.LoadingText)
];
}
// Add root to this widget
ChildSlot
[
Root
];
}