diff --git a/Docs/plugins.png b/Docs/plugins.png deleted file mode 100644 index 2cdaebe..0000000 Binary files a/Docs/plugins.png and /dev/null differ diff --git a/LoadingScreen.uplugin b/LoadingScreen.uplugin index 60a4395..d120ee7 100644 --- a/LoadingScreen.uplugin +++ b/LoadingScreen.uplugin @@ -10,8 +10,8 @@ "CreatedByURL": "https://www.epicgames.com", "DocsURL": "https://github.com/ue4plugins/LoadingScreen", "SupportURL": "https://github.com/ue4plugins/LoadingScreen/issues", - "EngineVersion": "4.16.0", - "EnabledByDefault": false, + "EngineVersion": "4.22", + "EnabledByDefault": true, "CanContainContent": true, "Modules": [ @@ -21,4 +21,4 @@ "LoadingPhase": "PreLoadingScreen" } ] -} \ No newline at end of file +} diff --git a/README.md b/README.md index 5052f4a..a897293 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ time to avoid needing to write a new loading screen manually. ## Supported Platforms -This plug-in was last built against **Unreal Engine 4.16**. It works on all platforms (probably). +This plug-in was last built against **Unreal Engine 4.22**. It works on all platforms (probably). ## Dependencies @@ -33,15 +33,7 @@ If you use it as a project plug-in, clone this repository into your project's */Plugins* directory and compile your game in Visual Studio. A C++ code project is required for this to work. -If you use it as an Engine plug-in, clone this repository into the -*/Engine/Plugins/Media* directory and compile your game. Full Unreal Engine 4 -source code from GitHub (4.12 or higher) is required for this. - -After compiling the plug-in, you have to **enable it** in Unreal Editor's -plug-in browser. - -![plugin](Docs/plugins.png) - +The plug-in configured to be enabled by default once it's in your game's plug-in directory. ## Support diff --git a/Source/LoadingScreen/LoadingScreen.Build.cs b/Source/LoadingScreen/LoadingScreen.Build.cs index 6824151..0742db4 100644 --- a/Source/LoadingScreen/LoadingScreen.Build.cs +++ b/Source/LoadingScreen/LoadingScreen.Build.cs @@ -1,4 +1,4 @@ -// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. namespace UnrealBuildTool.Rules { @@ -21,8 +21,7 @@ public LoadingScreen(ReadOnlyTargetRules Target) "SlateCore", "InputCore", "Engine" - } - ); + }); } } } diff --git a/Source/LoadingScreen/Private/LoadingScreenModule.cpp b/Source/LoadingScreen/Private/LoadingScreenModule.cpp index 856b240..fa72a55 100644 --- a/Source/LoadingScreen/Private/LoadingScreenModule.cpp +++ b/Source/LoadingScreen/Private/LoadingScreenModule.cpp @@ -1,4 +1,4 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. #include "ILoadingScreenModule.h" #include "LoadingScreenSettings.h" @@ -43,6 +43,7 @@ void FLoadingScreenModule::StartupModule() { Ref.TryLoad(); } + for ( const FStringAssetReference& Ref : Settings->DefaultScreen.Images ) { Ref.TryLoad(); diff --git a/Source/LoadingScreen/Private/LoadingScreenSettings.cpp b/Source/LoadingScreen/Private/LoadingScreenSettings.cpp index a1bef51..6cabe7f 100644 --- a/Source/LoadingScreen/Private/LoadingScreenSettings.cpp +++ b/Source/LoadingScreen/Private/LoadingScreenSettings.cpp @@ -1,4 +1,4 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. #include "LoadingScreenSettings.h" #include "UObject/ConstructorHelpers.h" @@ -7,19 +7,8 @@ #define LOCTEXT_NAMESPACE "LoadingScreen" FLoadingScreenDescription::FLoadingScreenDescription() - : MinimumLoadingScreenDisplayTime(-1) - , bAutoCompleteWhenLoadingCompletes(true) - , bMoviesAreSkippable(true) - , bWaitForManualStop(false) - , bShowUIOverlay(true) - , LoadingText(LOCTEXT("Loading", "LOADING")) - , ImageStretch(EStretch::ScaleToFit) + : LoadingText(LOCTEXT("Loading", "LOADING")) { - if ( !IsRunningDedicatedServer() ) - { - static ConstructorHelpers::FObjectFinder RobotoFontObj(TEXT("/Engine/EngineFonts/Roboto")); - LoadingFont = FSlateFontInfo(RobotoFontObj.Object, 32, FName("Bold")); - } } ULoadingScreenSettings::ULoadingScreenSettings(const FObjectInitializer& Initializer) @@ -31,6 +20,7 @@ ULoadingScreenSettings::ULoadingScreenSettings(const FObjectInitializer& Initial { static ConstructorHelpers::FObjectFinder RobotoFontObj(TEXT("/Engine/EngineFonts/Roboto")); TipFont = FSlateFontInfo(RobotoFontObj.Object, 20, FName("Normal")); + LoadingFont = FSlateFontInfo(RobotoFontObj.Object, 32, FName("Bold")); } } diff --git a/Source/LoadingScreen/Private/LoadingScreenSettings.h b/Source/LoadingScreen/Private/LoadingScreenSettings.h index 2c63037..ceb6936 100644 --- a/Source/LoadingScreen/Private/LoadingScreenSettings.h +++ b/Source/LoadingScreen/Private/LoadingScreenSettings.h @@ -1,4 +1,4 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. #pragma once @@ -18,48 +18,52 @@ struct LOADINGSCREEN_API FLoadingScreenDescription FLoadingScreenDescription(); /** The minimum time that a loading screen should be opened for, -1 if there is no minimum time. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Loading) - float MinimumLoadingScreenDisplayTime; - - /** If true, the loading screen will disappear as soon as all movies are played and loading is done. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Loading) - bool bAutoCompleteWhenLoadingCompletes; - + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Loading) + float MinimumLoadingScreenDisplayTime = -1; + + /** If true, the loading screen will disappear as soon as loading is done. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Loading) + bool bAutoCompleteWhenLoadingCompletes = true; + /** If true, movies can be skipped by clicking the loading screen as long as loading is done. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Loading) - bool bMoviesAreSkippable; - - /** If true, movie playback continues until Stop is called. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Loading) - bool bWaitForManualStop; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Loading) + bool bMoviesAreSkippable = true; - /** Should we just play back, loop, etc. NOTE: if the playback type is MT_LoopLast, then bAutoCompleteWhenLoadingCompletes will be togged on when the last movie is hit*/ + /** If true, movie playback continues until Stop is called. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Loading) + bool bWaitForManualStop = false; + + /** Should we just play back, loop, etc. NOTE: if playback type is MT_LoadingLoop, then MoviePlayer will auto complete when in the last movie and load finishes regardless of bAutoCompleteWhenLoadingCompletes */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Loading) TEnumAsByte PlaybackType; + /** The movie paths local to the game's Content/Movies/ directory without extension. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Movies) + TArray MoviePaths; + /** Should we show the images/tips/loading text? Generally you'll want to set this to false if you just want to show a movie. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Display) - bool bShowUIOverlay; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Display) + bool bShowUIOverlay = true; - /** */ + /** Text displayed beside the animated icon */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Display) FText LoadingText; - /** */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Display) - FSlateFontInfo LoadingFont; - - /** The movie paths local to the game's Content/Movies/ directory we will play. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Movies) - TArray MoviePaths; - /** The texture display while in the loading screen on top of the movie. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Images, meta=(AllowedClasses="Texture2D")) - TArray Images; + TArray Images; /** The scaling type to apply to images. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Images) - TEnumAsByte ImageStretch; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Images) + TEnumAsByte ImageStretch = EStretch::ScaleToFit; + + /** The background color to use */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Images) + FLinearColor BackgroundColor = FLinearColor::Black; + + /** The background color to use for tips */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Images) + FLinearColor TipBackgroundColor = FLinearColor(0, 0, 0, 0.75f); }; /** @@ -84,11 +88,15 @@ class LOADINGSCREEN_API ULoadingScreenSettings : public UDeveloperSettings UPROPERTY(config, EditAnywhere, BlueprintReadWrite, Category=Advice) FSlateFontInfo TipFont; + /** The font to display on loading. */ + UPROPERTY(config, EditAnywhere, BlueprintReadWrite, Category = Display) + FSlateFontInfo LoadingFont; + /** The size of the tip before it's wrapped to the next line. */ UPROPERTY(config, EditAnywhere, BlueprintReadWrite, Category=Advice) float TipWrapAt; /** The tips to display on the load screen. */ - UPROPERTY(config, EditAnywhere, BlueprintReadWrite, Category=Advice) + UPROPERTY(config, EditAnywhere, BlueprintReadWrite, Category=Advice, meta = (MultiLine = "true")) TArray Tips; }; diff --git a/Source/LoadingScreen/Private/SSimpleLoadingScreen.cpp b/Source/LoadingScreen/Private/SSimpleLoadingScreen.cpp index 0f5fd38..b80a27c 100644 --- a/Source/LoadingScreen/Private/SSimpleLoadingScreen.cpp +++ b/Source/LoadingScreen/Private/SSimpleLoadingScreen.cpp @@ -1,56 +1,71 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. #include "SSimpleLoadingScreen.h" -#include "SScaleBox.h" -#include "Widgets/Images/SImage.h" -#include "Widgets/Layout/SSpacer.h" #include "Widgets/SOverlay.h" #include "Widgets/SBoxPanel.h" -#include "Widgets/Text/STextBlock.h" +#include "Widgets/Layout/SScaleBox.h" +#include "Widgets/Layout/SSpacer.h" #include "Widgets/Layout/SBorder.h" -#include "SSafeZone.h" -#include "SThrobber.h" -#include "SDPIScaler.h" +#include "Widgets/Layout/SSafeZone.h" +#include "Widgets/Layout/SDPIScaler.h" +#include "Widgets/Text/STextBlock.h" +#include "Widgets/Images/SImage.h" +#include "Widgets/Images/SThrobber.h" #include "Engine/Texture2D.h" #include "Engine/UserInterfaceSettings.h" +#include "Slate/DeferredCleanupSlateBrush.h" #define LOCTEXT_NAMESPACE "LoadingScreen" ///////////////////////////////////////////////////// // SSimpleLoadingScreen -void SSimpleLoadingScreen::Construct(const FArguments& InArgs, const FLoadingScreenDescription& InScreenDescription) +static float PointSizeToSlateUnits(float PointSize) { - LastComputedDPIScale = 1.0f; + //FreeTypeConstants::HorizontalDPI = 96; + const float SlateFreeTypeHorizontalResolutionDPI = 96.0f; + const float FreeTypeNativeDPI = 72.0f; + const float PixelSize = PointSize * (SlateFreeTypeHorizontalResolutionDPI / FreeTypeNativeDPI); + + return PixelSize; +} +void SSimpleLoadingScreen::Construct(const FArguments& InArgs, const FLoadingScreenDescription& InScreenDescription) +{ const ULoadingScreenSettings* Settings = GetDefault(); - //Settings->TipFont; - //InScreenDescription.LoadingFont.GetCompositeFont()->SubTypefaces[0]->Typeface.Fonts[0].Font.BulkDataPtr->GetLinker()->GetOwnerThreadId() + const FSlateFontInfo& TipFont = Settings->TipFont; + const FSlateFontInfo& LoadingFont = Settings->LoadingFont; TSharedRef Root = SNew(SOverlay); // If there's an image defined if ( InScreenDescription.Images.Num() > 0 ) { - int32 ImageIndex = FMath::RandRange(0, InScreenDescription.Images.Num() - 1); + const int32 ImageIndex = FMath::RandRange(0, InScreenDescription.Images.Num() - 1); const FStringAssetReference& ImageAsset = InScreenDescription.Images[ImageIndex]; UObject* ImageObject = ImageAsset.TryLoad(); if ( UTexture2D* LoadingImage = Cast(ImageObject) ) { - FVector2D Size = FVector2D(LoadingImage->GetSizeX(), LoadingImage->GetSizeY()); - LoadingScreenBrush = MakeShareable(new FLoadingScreenBrush(LoadingImage, Size, FName(*ImageAsset.ToString()))); + LoadingScreenBrush = FDeferredCleanupSlateBrush::CreateBrush(LoadingImage); Root->AddSlot() .HAlign(HAlign_Fill) .VAlign(VAlign_Fill) [ - SNew(SScaleBox) - .Stretch(InScreenDescription.ImageStretch) + SNew(SBorder) + .HAlign(HAlign_Fill) + .VAlign(VAlign_Fill) + .BorderBackgroundColor(InScreenDescription.BackgroundColor) + .BorderImage(FCoreStyle::Get().GetBrush("WhiteBrush")) [ - SNew(SImage) - .Image(LoadingScreenBrush.Get()) + SNew(SScaleBox) + .Stretch(InScreenDescription.ImageStretch) + [ + SNew(SImage) + .Image(LoadingScreenBrush.IsValid() ? LoadingScreenBrush->GetSlateBrush() : nullptr) + ] ] ]; } @@ -59,13 +74,19 @@ void SSimpleLoadingScreen::Construct(const FArguments& InArgs, const FLoadingScr TSharedRef TipWidget = SNullWidget::NullWidget; if ( Settings->Tips.Num() > 0 ) { - int32 TipIndex = FMath::RandRange(0, Settings->Tips.Num() - 1); + const int32 TipIndex = FMath::RandRange(0, Settings->Tips.Num() - 1); TipWidget = SNew(STextBlock) .WrapTextAt(Settings->TipWrapAt) - //.Font(Settings->TipFont) + .Font(TipFont) .Text(Settings->Tips[TipIndex]); } + else + { + // Need to use a spacer when being rendered on another thread, incrementing the SNullWidget will + // lead to shared ptr crashes. + TipWidget = SNew(SSpacer); + } Root->AddSlot() .HAlign(HAlign_Fill) @@ -74,7 +95,7 @@ void SSimpleLoadingScreen::Construct(const FArguments& InArgs, const FLoadingScr SNew(SBorder) .HAlign(HAlign_Fill) .VAlign(VAlign_Fill) - .BorderBackgroundColor(FLinearColor(0, 0, 0, 0.75)) + .BorderBackgroundColor(InScreenDescription.TipBackgroundColor) .BorderImage(FCoreStyle::Get().GetBrush("WhiteBrush")) [ SNew(SSafeZone) @@ -93,8 +114,7 @@ void SSimpleLoadingScreen::Construct(const FArguments& InArgs, const FLoadingScr .AutoWidth() [ SNew(SCircularThrobber) - // Convert font size to pixels, pixel_size = point_size * resolution / 72, then half it to get radius - .Radius((InScreenDescription.LoadingFont.Size * 96.0f/72.0f) / 2.0f) + .Radius(PointSizeToSlateUnits(LoadingFont.Size) / 2.0f) ] + SHorizontalBox::Slot() @@ -104,7 +124,7 @@ void SSimpleLoadingScreen::Construct(const FArguments& InArgs, const FLoadingScr [ SNew(STextBlock) .Text(InScreenDescription.LoadingText) - //.Font(InScreenDescription.LoadingFont) + .Font(LoadingFont) ] + SHorizontalBox::Slot() @@ -134,22 +154,11 @@ void SSimpleLoadingScreen::Construct(const FArguments& InArgs, const FLoadingScr ]; } -void SSimpleLoadingScreen::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) -{ - const FVector2D& LocalSize = AllottedGeometry.GetLocalSize(); - FIntPoint Size((int32)LocalSize.X, (int32)LocalSize.Y); - const float NewScale = GetDefault()->GetDPIScaleBasedOnSize(Size); - - if ( NewScale != LastComputedDPIScale ) - { - LastComputedDPIScale = NewScale; - SlatePrepass(1.0f); - } -} - float SSimpleLoadingScreen::GetDPIScale() const { - return LastComputedDPIScale; + const FVector2D& DrawSize = GetCachedGeometry().ToPaintGeometry().GetLocalSize(); + const FIntPoint Size((int32)DrawSize.X, (int32)DrawSize.Y); + return GetDefault()->GetDPIScaleBasedOnSize(Size); } #undef LOCTEXT_NAMESPACE diff --git a/Source/LoadingScreen/Private/SSimpleLoadingScreen.h b/Source/LoadingScreen/Private/SSimpleLoadingScreen.h index cc81737..91fab88 100644 --- a/Source/LoadingScreen/Private/SSimpleLoadingScreen.h +++ b/Source/LoadingScreen/Private/SSimpleLoadingScreen.h @@ -5,24 +5,7 @@ #include "SCompoundWidget.h" #include "LoadingScreenSettings.h" -/** -* Special brush to prevent garbage collection -*/ -struct FLoadingScreenBrush : public FSlateDynamicImageBrush, public FGCObject -{ - FLoadingScreenBrush(class UTexture2D* InTexture, const FVector2D& InImageSize, const FName InImagePath) - : FSlateDynamicImageBrush(InTexture, InImageSize, InImagePath) - { - } - - virtual void AddReferencedObjects(FReferenceCollector& Collector) override - { - if ( ResourceObject ) - { - Collector.AddReferencedObject(ResourceObject); - } - } -}; +class FDeferredCleanupSlateBrush; class SSimpleLoadingScreen : public SCompoundWidget { @@ -34,12 +17,9 @@ class SSimpleLoadingScreen : public SCompoundWidget void Construct(const FArguments& InArgs, const FLoadingScreenDescription& ScreenDescription); - virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; - private: float GetDPIScale() const; private: - TSharedPtr LoadingScreenBrush; - float LastComputedDPIScale; + TSharedPtr LoadingScreenBrush; }; diff --git a/Source/LoadingScreen/Public/ILoadingScreenModule.h b/Source/LoadingScreen/Public/ILoadingScreenModule.h index 99aa65c..b5b5294 100644 --- a/Source/LoadingScreen/Public/ILoadingScreenModule.h +++ b/Source/LoadingScreen/Public/ILoadingScreenModule.h @@ -1,4 +1,4 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. #pragma once