This commit is contained in:
Oleg Petruny 2025-04-24 16:13:56 +02:00
parent 78005d450c
commit bdbb2397c1
12 changed files with 256 additions and 6 deletions

Binary file not shown.

Binary file not shown.

View File

@ -12,7 +12,12 @@ public class Lost_Edge : ModuleRules
PrivateDependencyModuleNames.AddRange(new string[] { "EnhancedInput", "UMG", "RHI", "RenderCore", "Lost_EdgeShaders", "PakFile", //"TextureCompressor",
"LevelSequence", "MovieScene", "HTTP", "Json", "ApplicationCore", "ProceduralMeshComponent", "Landscape", "MeshDescription", "StaticMeshDescription",
"AssetRegistry", "UnrealEd", "LevelEditor" }); // "Slate", "SlateCore"
"AssetRegistry", "LevelEditor", "MoviePlayer", "Slate", "SlateCore" });
if (Target.bBuildEditor)
{
PrivateDependencyModuleNames.AddRange(new string[] { "UnrealEd" });
}
// UE_LOG(LogTemp, Log, TEXT("capture: %s"), (capture ? TEXT("true") : TEXT("false")));
// GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("1"));

View File

@ -3,4 +3,4 @@
#include "Lost_Edge.h"
#include "Modules/ModuleManager.h"
IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, Lost_Edge, "Lost_Edge" );
IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, Lost_Edge, "Lost_Edge");

View File

@ -0,0 +1,24 @@
// Oleg Petruny proprietary.
#pragma once
#include "Kismet/BlueprintFunctionLibrary.h"
#include "CommonData.generated.h"
/**
* Collection of common/universal/without own scope/specific data values.
*/
UCLASS()
class UCommonData : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
static const TSharedPtr<const FSlateBrush> KindaBlackColorBrush()
{
static auto brush = MakeShared<const FSlateColorBrush>(FLinearColor(0.01f, 0.01f, 0.01f));
return brush;
}
};

View File

@ -8,6 +8,7 @@
#include "ContentLoader.h"
#include "CustomGameSettings.h"
#include "Levels/LevelBase.h"
#include "LoadingScreen/LoadingScreen.h"
#include "PlayerBase.h"
#include "SaveData.h"
@ -21,11 +22,14 @@ UCustomGameInstance* UCustomGameInstance::instance = nullptr;
void UCustomGameInstance::Init()
{
// init game instance
UGameInstance::Init();
instance = this;
// setup content loader
contentLoader = NewObject<UContentLoader>(this);
// setup global singletons
for(auto& _class : globalInstancesClasses)
{
UObject* gi = NewObject<UObject>(_class);
@ -34,10 +38,16 @@ void UCustomGameInstance::Init()
}
globalInstancesClasses.Empty();
// set current save
if(auto save = UGameplayStatics::LoadGameFromSlot(saveName, saveIndex))
saveData = Cast<USaveData>(save);
else
saveData = Cast<USaveData>(UGameplayStatics::CreateSaveGameObject(USaveData::StaticClass()));
// setup loading screen
loadingScreen = NewObject<ULoadingScreen>(this);
FCoreUObjectDelegates::PreLoadMap.AddUObject(loadingScreen, &ULoadingScreen::BeginLoadingScreen);
FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(loadingScreen, &ULoadingScreen::EndLoadingScreen);
}
void UCustomGameInstance::Shutdown()

View File

@ -52,6 +52,8 @@ public:
protected:
UPROPERTY()
class UContentLoader* contentLoader;
UPROPERTY()
class ULoadingScreen* loadingScreen;
UPROPERTY(EditDefaultsOnly)
TSet<TSubclassOf<UObject>> globalInstancesClasses;

View File

@ -4,7 +4,6 @@
#include "AssetRegistry/AssetRegistryModule.h"
#include "Components/BoxComponent.h"
#include "Editor/EditorEngine.h"
#include "Engine/SkyLight.h"
#include "Engine/StaticMeshActor.h"
#include "Landscape.h"
@ -15,6 +14,9 @@
#include "ProceduralMeshComponent.h"
#include "ProceduralMeshConversion.h"
#include "StaticMeshDescription.h"
#if WITH_EDITOR
#include "Editor/EditorEngine.h"
#endif
AGrassGenerator::AGrassGenerator()
{
@ -44,6 +46,7 @@ void AGrassGenerator::PostEditChangeProperty(FPropertyChangedEvent& PropertyChan
void AGrassGenerator::Generate()
{
#if WITH_EDITOR
Clear();
FVector loc = GetActorLocation();
@ -177,16 +180,20 @@ void AGrassGenerator::Generate()
mesh->CreateMeshSection(sectionsCount++, vertices, triangles, normals, UVs, {}, {}, false);
Update();
#endif
}
void AGrassGenerator::Clear()
{
#if WITH_EDITOR
mesh->ClearAllMeshSections();
sectionsCount = 0;
#endif
}
void AGrassGenerator::Export()
{
#if WITH_EDITOR
const FString actorName = GetName();
const FString levelName = GetWorld()->GetMapName().RightChop(2);
const FString levelPath = FPaths::GetPath(GEditor->GetEditorSubsystem<ULevelEditorSubsystem>()->GetCurrentLevel()->GetPathName());
@ -205,9 +212,7 @@ void AGrassGenerator::Export()
smeshDesc->SetMeshDescription(meshDesc);
smesh->BuildFromStaticMeshDescriptions({ smeshDesc }, false, true);
smesh->GetStaticMaterials().Add({ grassMaterial.LoadSynchronous() });
#if WITH_EDITOR
smesh->PostEditChange();
#endif
smesh->MarkPackageDirty();
FAssetRegistryModule::AssetCreated(smesh);
@ -225,6 +230,7 @@ void AGrassGenerator::Export()
GEditor->SelectNone(false, true);
GEditor->SelectActor(smeshActor, true, true);
GEditor->RedrawAllViewports();
#endif
}
void AGrassGenerator::Update()

View File

@ -0,0 +1,42 @@
// Oleg Petruny proprietary.
#include "LoadingScreen.h"
#include "MoviePlayer.h"
#include "SLoadingScreenWidget.h"
void ULoadingScreen::BeginLoadingScreen(const FString& mapName)
{
if(active || IsRunningDedicatedServer())
return;
active = true;
FLoadingScreenAttributes params;
params.bAutoCompleteWhenLoadingCompletes = false;
params.MinimumLoadingScreenDisplayTime = 2.0f;
if(first)
{
// Game init loading screen
first = false;
params.bMoviesAreSkippable = true;
params.WidgetLoadingScreen = SNew(SStartupImageWidget)
.FadeDuration(params.MinimumLoadingScreenDisplayTime);
}
else
{
// Game level loading screen
params.WidgetLoadingScreen = SNew(SStartupImageWidget)
.FadeDuration(params.MinimumLoadingScreenDisplayTime);
}
GetMoviePlayer()->SetupLoadingScreen(params);
}
void ULoadingScreen::EndLoadingScreen(UWorld* inLoadedWorld)
{
if(!active)
return;
active = false;
}

View File

@ -0,0 +1,23 @@
// Oleg Petruny proprietary.
#pragma once
#include "UObject/Object.h"
#include "LoadingScreen.generated.h"
UCLASS()
class ULoadingScreen : public UObject
{
GENERATED_BODY()
public:
UFUNCTION()
void BeginLoadingScreen(const FString& mapName);
UFUNCTION()
void EndLoadingScreen(UWorld* inLoadedWorld);
private:
bool active = false;
bool first = true;
};

View File

@ -0,0 +1,97 @@
// Oleg Petruny proprietary.
#include "SLoadingScreenWidget.h"
#include "Engine/Texture2D.h"
#include "Slate/DeferredCleanupSlateBrush.h"
#include "Widgets/Images/SImage.h"
#include "Widgets/Layout/SBorder.h"
#include "Widgets/Layout/SScaleBox.h"
#include "CommonData.h"
namespace
{
constexpr auto startupImageA = TEXT("/Script/Engine.Texture2D'/Game/Movies/Images/T_StartupImageA.T_StartupImageA'");
constexpr auto startupImageB = TEXT("/Script/Engine.Texture2D'/Game/Movies/Images/T_StartupImageB.T_StartupImageB'");
}
void SStartupImageWidget::Construct(const FArguments& inArgs)
{
FSoftObjectPath assetA{ startupImageA };
UTexture2D* imageA = Cast<UTexture2D>(assetA.TryLoad());
check(imageA); // image A loading failed
FSoftObjectPath assetB{ startupImageB };
UTexture2D* imageB = Cast<UTexture2D>(assetB.TryLoad());
check(imageB); // image B loading failed
// cache brushes into memory
imageABrush = FDeferredCleanupSlateBrush::CreateBrush(imageA);
imageBBrush = FDeferredCleanupSlateBrush::CreateBrush(imageB);
imageAWidget = SNew(SImage).Image(imageABrush->GetSlateBrush()).RenderOpacity(1.0f);
imageBWidget = SNew(SImage).Image(imageBBrush->GetSlateBrush()).RenderOpacity(0.0f);
// construct widget
ChildSlot
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.Padding(0)
.BorderImage(UCommonData::KindaBlackColorBrush().Get())
[
SNew(SScaleBox)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.Stretch(EStretch::ScaleToFitY)
.StretchDirection(EStretchDirection::Both)
[
SNew(SOverlay)
+ SOverlay::Slot()
[
imageAWidget.ToSharedRef()
]
+ SOverlay::Slot()
[
imageBWidget.ToSharedRef()
]
+ SOverlay::Slot()
[
SNew(STextBlock).Text(FText::FromString(TEXT("Loading...")))
]
]
]
];
// start fading
isFading = true;
fadeDuration = inArgs._FadeDuration;
currentTime = 0.0f;
fadeTickHandle = FTSTicker::GetCoreTicker().AddTicker(
FTickerDelegate::CreateRaw(this, &SStartupImageWidget::FadeTick),
0.0f);
}
SStartupImageWidget::~SStartupImageWidget()
{
isFading = false;
FTSTicker::GetCoreTicker().RemoveTicker(fadeTickHandle);
}
bool SStartupImageWidget::FadeTick(float deltaTime)
{
currentTime += deltaTime;
float fade = currentTime / fadeDuration;
if(fade > 1.0f)
{
fade = 1.0f;
isFading = false;
FTSTicker::GetCoreTicker().RemoveTicker(fadeTickHandle);
}
imageAWidget->SetRenderOpacity(1.0f - fade);
imageBWidget->SetRenderOpacity(fade);
return isFading;
}

View File

@ -0,0 +1,35 @@
// Oleg Petruny proprietary.
#pragma once
#include "Widgets/SCompoundWidget.h"
struct FLoadingScreenWidgetArguments
{
float fadeDuration = 2.0f;
};
class SStartupImageWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SStartupImageWidget) {}
SLATE_ARGUMENT(float, FadeDuration)
SLATE_END_ARGS()
void Construct(const FArguments& inArgs);
virtual ~SStartupImageWidget();
private:
bool FadeTick(float deltaTime);
TSharedPtr<class FDeferredCleanupSlateBrush> imageABrush;
TSharedPtr<class FDeferredCleanupSlateBrush> imageBBrush;
TSharedPtr<SImage> imageAWidget;
TSharedPtr<SImage> imageBWidget;
float fadeDuration;
float currentTime;
bool isFading = false;
FTSTicker::FDelegateHandle fadeTickHandle;
};