// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. #pragma once #include "CoreMinimal.h" #include "Components/GameStateComponent.h" #include "LoadingProcessInterface.h" #include "OLSExperienceManagerComponent.generated.h" namespace UE::GameFeatures { struct FResult; } DECLARE_MULTICAST_DELEGATE_OneParam(FOLSExperienceLoadedNativeDelegate, const class UOLSExperienceDefinitionDataAsset* /*experience*/); enum class EOLSExperienceLoadState { Unloaded, Loading, LoadingGameFeatures, LoadingChaosTestingDelay, ExecutingActions, Loaded, Deactivating }; UCLASS() class OLS_API UOLSExperienceManagerComponent : public UGameStateComponent, public ILoadingProcessInterface { GENERATED_BODY() public: UOLSExperienceManagerComponent(const FObjectInitializer& objectInitializer); //~ Begin UActorComponent interface virtual void EndPlay(const EEndPlayReason::Type endPlayReason) override; virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override; //~ End UActorComponent interface //~ Begin ILoadingProcessInterface interface virtual bool ShouldShowLoadingScreen(FString& outReason) const override; //~ End ILoadingProcessInterface public: // This returns the current experience if it is fully loaded, asserting otherwise // (i.e., if you called it too soon) const UOLSExperienceDefinitionDataAsset* GetCurrentExperienceChecked() const; // Tries to set the current experience, either a UI or gameplay one void SetCurrentExperience(FPrimaryAssetId experienceId); // Returns true if the experience is fully loaded bool IsExperienceLoaded() const; // Ensures the delegate is called once the experience has been loaded, // before others are called. // However, if the experience has already loaded, calls the delegate immediately. void CallOrRegister_OnExperienceLoaded_HighPriority(FOLSExperienceLoadedNativeDelegate::FDelegate&& delegate); // Ensures the delegate is called once the experience has been loaded // If the experience has already loaded, calls the delegate immediately void CallOrRegister_OnExperienceLoaded(FOLSExperienceLoadedNativeDelegate::FDelegate&& delegate); // Ensures the delegate is called once the experience has been loaded // If the experience has already loaded, calls the delegate immediately void CallOrRegister_OnExperienceLoaded_LowPriority(FOLSExperienceLoadedNativeDelegate::FDelegate&& delegate); private: UFUNCTION() void OnRep_CurrentExperience(); private: void StartExperienceLoad(); void OnExperienceLoadComplete(); void OnGameFeaturePluginLoadComplete(const UE::GameFeatures::FResult& result); void OnExperienceFullLoadCompleted(); void OnActionDeactivationCompleted(); void OnAllActionsDeactivated(); private: UPROPERTY(ReplicatedUsing = OnRep_CurrentExperience) TObjectPtr CurrentExperience = nullptr; private: EOLSExperienceLoadState LoadState = EOLSExperienceLoadState::Unloaded; int32 NumGameFeaturePluginsLoading = 0; TArray GameFeaturePluginURLs; int32 NumObservedPausers = 0; int32 NumExpectedPausers = 0; /** * Delegate called when the experience has finished loading just before others * (e.g., subsystems that set up for regular gameplay) */ FOLSExperienceLoadedNativeDelegate OnExperienceLoaded_HighPriority; /** Delegate called when the experience has finished loading */ FOLSExperienceLoadedNativeDelegate OnExperienceLoaded; /** Delegate called when the experience has finished loading */ FOLSExperienceLoadedNativeDelegate OnExperienceLoaded_LowPriority; };