diff --git a/Source/AutoSave/Private/AutoSaveSubsystem.cpp b/Source/AutoSave/Private/AutoSaveSubsystem.cpp index 1e55fab..39fb6d6 100644 --- a/Source/AutoSave/Private/AutoSaveSubsystem.cpp +++ b/Source/AutoSave/Private/AutoSaveSubsystem.cpp @@ -28,6 +28,18 @@ void UAutoSaveSubsystem::GetSaveStructInfosWithoutData(TArray& } } +int32 UAutoSaveSubsystem::GetIdleThreadNum() const +{ + int32 Result = 0; + + for (const TUniquePtr>& Task : TaskThreads) + { + if (!Task) ++Result; + } + + return Result; +} + FSaveStruct * UAutoSaveSubsystem::AddSaveStructRef(const FString& Filename, UScriptStruct * ScriptStruct, FSaveStructLoadDelegate OnLoaded) { if (StructInfos.Contains(Filename)) diff --git a/Source/AutoSave/Public/AutoSaveSubsystem.h b/Source/AutoSave/Public/AutoSaveSubsystem.h index b5e2de9..5b023d4 100644 --- a/Source/AutoSave/Public/AutoSaveSubsystem.h +++ b/Source/AutoSave/Public/AutoSaveSubsystem.h @@ -57,6 +57,7 @@ class AUTOSAVE_API UAutoSaveSubsystem : public UGameInstanceSubsystem, public FT GENERATED_BODY() friend class UAutoSaveBlueprintLibrary; + template friend class FSaveStructPtr; public: @@ -71,6 +72,9 @@ public: UFUNCTION(BlueprintCallable, Category = "AutoSave") void GetSaveStructInfosWithoutData(TArray& OutSaveStructInfos) const; + UFUNCTION(BlueprintPure, Category = "AutoSave") + int32 GetIdleThreadNum() const; + FSaveStruct* AddSaveStructRef(const FString& Filename, UScriptStruct* ScriptStruct = nullptr, FSaveStructLoadDelegate OnLoaded = FSaveStructLoadDelegate()); void RemoveSaveStructRef(const FString& Filename); diff --git a/Source/AutoSave/Public/SaveStruct.h b/Source/AutoSave/Public/SaveStruct.h index e69de29..33cca7f 100644 --- a/Source/AutoSave/Public/SaveStruct.h +++ b/Source/AutoSave/Public/SaveStruct.h @@ -0,0 +1,79 @@ +#pragma once + +#include "CoreMinimal.h" +#include "AutoSaveSubsystem.h" +#include "Templates/UnrealTemplate.h" + +struct FSaveStructInfo; + +class UAutoSaveSubsystem; + +template +class FSaveStructPtr : public FNoncopyable +{ +public: + + FORCEINLINE FSaveStructPtr() + : AutoSaveSubsystem(nullptr) + , Info(nullptr) + { + } + + FORCEINLINE FSaveStructPtr(UAutoSaveSubsystem* InAutoSaveSubsystem, const FString& Filename, FSaveStructLoadDelegate OnLoaded = FSaveStructLoadDelegate()) + : AutoSaveSubsystem(InAutoSaveSubsystem) + , Info(nullptr) + { + if (AutoSaveSubsystem->AddSaveStructRef(Filename, SaveStructType::StaticStruct(), OnLoaded)) + { + Info = AutoSaveSubsystem->StructInfos[Filename].Get(); + } + } + + FORCEINLINE ~FSaveStructPtr() + { + if (Info) + { + AutoSaveSubsystem->RemoveSaveStructRef(Info->Filename); + } + } + + FORCEINLINE SaveStructType* Get() const + { + return Info ? (SaveStructType*)Info->Data.GetData() : nullptr; + } + + FORCEINLINE explicit operator bool() const + { + return Info != nullptr; + } + + FORCEINLINE const bool IsValid() const + { + return Info != nullptr; + } + + FORCEINLINE const bool IsLoaded() const + { + check(IsValid()); + return Info->State == ESaveStructState::Idle || Info->State == ESaveStructState::Saving; + } + + FORCEINLINE SaveStructType& operator*() const + { + check(IsValid()); + return *Get(); + } + + FORCEINLINE SaveStructType* operator->() const + { + check(IsValid()); + return Get(); + } + +private: + + UAutoSaveSubsystem* AutoSaveSubsystem; + + FSaveStructInfo* Info; + +};