initial Commit
This commit is contained in:
28
Plugins/PS_ReplaySystem/ReplaySystem.uplugin
Normal file
28
Plugins/PS_ReplaySystem/ReplaySystem.uplugin
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"FileVersion": 3,
|
||||
"Version": 1,
|
||||
"VersionName": "1.0",
|
||||
"FriendlyName": "ReplaySystem",
|
||||
"Description": "Exposes the Unreal replay system to blueprints",
|
||||
"Category": "Replay",
|
||||
"CreatedBy": "TareE",
|
||||
"CreatedByURL": "https://www.oyintare.dev/",
|
||||
"DocsURL": "https://replay.oyintare.dev/",
|
||||
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/1b0cbe31111d482baaf531d187651e7f",
|
||||
"SupportURL": "",
|
||||
"CanContainContent": true,
|
||||
"Installed": true,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "ReplaySystem",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "EarliestPossible",
|
||||
"PlatformAllowList": [
|
||||
"Win64",
|
||||
"Mac",
|
||||
"Linux",
|
||||
"Android"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
Plugins/PS_ReplaySystem/Resources/Icon128.png
Normal file
BIN
Plugins/PS_ReplaySystem/Resources/Icon128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
@@ -0,0 +1,24 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
|
||||
#include "DeleteReplayObject.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
|
||||
|
||||
void UDeleteReplayObject::DeleteReplay(const FString& ReplayName)
|
||||
{
|
||||
EnumerateStreamsPtr = FNetworkReplayStreaming::Get().GetFactory().CreateReplayStreamer();
|
||||
|
||||
OnDeleteFinishedStreamCompleteDel = FDeleteFinishedStreamCallback::CreateUObject(this, &UDeleteReplayObject::OnDeleteFinishedStreamComplete);
|
||||
|
||||
if (EnumerateStreamsPtr.Get())
|
||||
{
|
||||
EnumerateStreamsPtr.Get()->DeleteFinishedStream(ReplayName, OnDeleteFinishedStreamCompleteDel);
|
||||
}
|
||||
}
|
||||
|
||||
void UDeleteReplayObject::OnDeleteFinishedStreamComplete(const FDeleteFinishedStreamResult& Result)
|
||||
{
|
||||
const bool WasSuccessful = Result.WasSuccessful();
|
||||
OnDeleteComplete.Broadcast(WasSuccessful);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
|
||||
#include "GetSavedReplaysObject.h"
|
||||
#include "ReplayStructs.h"
|
||||
#include "ReplayObject.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
|
||||
|
||||
void UGetSavedReplaysObject::GetSavedReplays()
|
||||
{
|
||||
EnumerateStreamsPtr = FNetworkReplayStreaming::Get().GetFactory().CreateReplayStreamer();
|
||||
|
||||
EnumerateStreamsCallbackDel = FEnumerateStreamsCallback::CreateUObject(this, &UGetSavedReplaysObject::OnEnumerateStreamsComplete);
|
||||
|
||||
if (EnumerateStreamsPtr.Get())
|
||||
{
|
||||
EnumerateStreamsPtr.Get()->EnumerateStreams(FNetworkReplayVersion(), INDEX_NONE, FString(), TArray<FString>(), EnumerateStreamsCallbackDel);
|
||||
}
|
||||
}
|
||||
|
||||
void UGetSavedReplaysObject::OnEnumerateStreamsComplete(const FEnumerateStreamsResult& Result)
|
||||
{
|
||||
|
||||
TArray<UReplayObject* > Replays;
|
||||
|
||||
TArray<FNetworkReplayStreamInfo> StreamInfos = Result.FoundStreams;
|
||||
|
||||
for (FNetworkReplayStreamInfo StreamInfo : StreamInfos)
|
||||
{
|
||||
FReplayInfo ReplayInfoTemp;
|
||||
ReplayInfoTemp.FriendlyName = StreamInfo.FriendlyName;
|
||||
ReplayInfoTemp.ActualName = StreamInfo.Name;
|
||||
ReplayInfoTemp.RecordDate = StreamInfo.Timestamp;
|
||||
ReplayInfoTemp.LengthInMS = StreamInfo.LengthInMS;
|
||||
const float SizeInKb = StreamInfo.SizeInBytes / 1024.0f;
|
||||
ReplayInfoTemp.SizeInMb = SizeInKb / 1024.0f;
|
||||
|
||||
UReplayObject* ReplayObj = NewObject<UReplayObject>();
|
||||
ReplayObj->ReplayInfo = ReplayInfoTemp;
|
||||
Replays.Add(ReplayObj);
|
||||
}
|
||||
|
||||
OnGetReplaysComplete.Broadcast(Replays);
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
|
||||
#include "GoToTimeObject.h"
|
||||
#include "Engine.h"
|
||||
#include "ReplayPlayerController.h"
|
||||
#include "ReplaySystemBPLibrary.h"
|
||||
#include "Engine/DemoNetDriver.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
|
||||
// Sets default values
|
||||
UGoToTimeObject::UGoToTimeObject()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void UGoToTimeObject::GoToTime(UObject* WorldContextObject, float TimeToGoTo,bool bRetainPauseState)
|
||||
{
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (const AWorldSettings* WorldSettings = World->GetWorldSettings())
|
||||
{
|
||||
// clamp time just in case
|
||||
const float ClampedTime = UKismetMathLibrary::FClamp(TimeToGoTo,0.0f,UReplaySystemBPLibrary::GetReplayLength(WorldContextObject));
|
||||
|
||||
if (UDemoNetDriver* DemoDriver = UReplaySystemBPLibrary::GetDemoDriver(World))
|
||||
{
|
||||
if (DemoDriver && DemoDriver->ServerConnection && DemoDriver->ServerConnection->PlayerController && DemoDriver->ServerConnection->PlayerController->PlayerState)
|
||||
{
|
||||
if(const AReplayPlayerController * ReplayPC = Cast<AReplayPlayerController>(DemoDriver->ServerConnection->PlayerController))
|
||||
{
|
||||
if(ReplayPC->bIsSpectating)
|
||||
{
|
||||
if(const AActor* ActorBeingSpectated = Cast<AActor>(ReplayPC->GetViewTarget()))
|
||||
{
|
||||
const FNetworkGUID ActorBeingSpectatedGUID = DemoDriver->GetGUIDForActor(ActorBeingSpectated);
|
||||
DemoDriver->AddNonQueuedGUIDForScrubbing(ActorBeingSpectatedGUID);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(const AActor* ActorPossessed = Cast<AActor>(ReplayPC->GetPawn()))
|
||||
{
|
||||
const FNetworkGUID SpectatorPawnGUID = DemoDriver->GetGUIDForActor(ActorPossessed);
|
||||
DemoDriver->AddNonQueuedGUIDForScrubbing(SpectatorPawnGUID);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(const APlayerController * PC = Cast<APlayerController>(DemoDriver->ServerConnection->PlayerController))
|
||||
{
|
||||
if(const AActor* ActorPossessed = Cast<AActor>(PC->GetPawn()))
|
||||
{
|
||||
const FNetworkGUID SpectatorPawnGUID = DemoDriver->GetGUIDForActor(ActorPossessed);
|
||||
DemoDriver->AddNonQueuedGUIDForScrubbing(SpectatorPawnGUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( FActorIterator It( World->GetWorld()); It; ++It )
|
||||
{
|
||||
if ( It->bAlwaysRelevant )
|
||||
{
|
||||
const FNetworkGUID ActorGUID = DemoDriver->GetGUIDForActor(*It);
|
||||
DemoDriver->AddNonQueuedGUIDForScrubbing(ActorGUID);
|
||||
}
|
||||
}
|
||||
|
||||
bRetainPauseStateBeforeMove = bRetainPauseState;
|
||||
WCO = WorldContextObject;
|
||||
|
||||
if(WorldSettings->GetPauserPlayerState())
|
||||
{
|
||||
bPauseStateBeforeMove = true;
|
||||
}
|
||||
|
||||
OnGoToTimeDelegate = FOnGotoTimeDelegate::CreateUObject(this,&UGoToTimeObject::OnGoToTimeProcessed);
|
||||
|
||||
DemoDriver->GotoTimeInSeconds(ClampedTime,OnGoToTimeDelegate);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UGoToTimeObject::OnGoToTimeProcessed(bool bWasSuccessful)
|
||||
{
|
||||
const UObject* WorldContext = WCO;
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContext))
|
||||
{
|
||||
if (AWorldSettings* WorldSettings = World->GetWorldSettings())
|
||||
{
|
||||
if (UDemoNetDriver* DemoDriver = UReplaySystemBPLibrary::GetDemoDriver(World))
|
||||
{
|
||||
if(OnGotoTimeComplete.IsBound())
|
||||
{
|
||||
OnGotoTimeComplete.Broadcast(bWasSuccessful);
|
||||
}
|
||||
|
||||
if(bRetainPauseStateBeforeMove && !bPauseStateBeforeMove == false)
|
||||
{
|
||||
UReplaySystemBPLibrary::PausePlayback(WCO);
|
||||
}
|
||||
|
||||
if( AReplayPlayerController* ReplayPC = Cast<AReplayPlayerController>(UGameplayStatics::GetPlayerController(World,0)))
|
||||
{
|
||||
ReplayPC->OnGoToTime(UReplaySystemBPLibrary::GetCurrentReplayTime(WCO));
|
||||
ReplayPC->OnStopSpectateActor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
|
||||
#include "ModifyReplayObject.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
|
||||
|
||||
void UModifyReplayObject::RenameReplay(const FString& ReplayName, const FString& NewName, const int32 UserIndex,bool bIsNormalName)
|
||||
{
|
||||
EnumerateStreamsPtr = FNetworkReplayStreaming::Get().GetFactory().CreateReplayStreamer();
|
||||
|
||||
OnRenameReplayCompleteDel = FRenameReplayCallback::CreateUObject(this, &UModifyReplayObject::OnRenameReplayComplete);
|
||||
|
||||
if (EnumerateStreamsPtr.Get())
|
||||
{
|
||||
if (bIsNormalName)
|
||||
{
|
||||
EnumerateStreamsPtr.Get()->RenameReplay(ReplayName,NewName,UserIndex, OnRenameReplayCompleteDel);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
EnumerateStreamsPtr.Get()->RenameReplayFriendlyName(ReplayName, NewName,UserIndex, OnRenameReplayCompleteDel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UModifyReplayObject::OnRenameReplayComplete(const FRenameReplayResult& Result)
|
||||
{
|
||||
bool WasSuccessful = Result.WasSuccessful();
|
||||
//OnRenameComplete.Broadcast(WasSuccessful);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
|
||||
#include "RenameReplayObject.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
|
||||
|
||||
void URenameReplayObject::RenameReplay(const FString& ReplayName, const FString& NewName, const int32 UserIndex,bool bIsNormalName)
|
||||
{
|
||||
EnumerateStreamsPtr = FNetworkReplayStreaming::Get().GetFactory().CreateReplayStreamer();
|
||||
|
||||
OnRenameReplayCompleteDel = FRenameReplayCallback::CreateUObject(this, &URenameReplayObject::OnRenameReplayComplete);
|
||||
|
||||
if (EnumerateStreamsPtr.Get())
|
||||
{
|
||||
if (bIsNormalName)
|
||||
{
|
||||
EnumerateStreamsPtr.Get()->RenameReplay(ReplayName,NewName,UserIndex, OnRenameReplayCompleteDel);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
EnumerateStreamsPtr.Get()->RenameReplayFriendlyName(ReplayName, NewName,UserIndex, OnRenameReplayCompleteDel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void URenameReplayObject::OnRenameReplayComplete(const FRenameReplayResult& Result)
|
||||
{
|
||||
bool WasSuccessful = Result.WasSuccessful();
|
||||
OnRenameComplete.Broadcast(WasSuccessful);
|
||||
}
|
||||
@@ -0,0 +1,984 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
|
||||
|
||||
#include "ReplayDataObject.h"
|
||||
#include "Kismet/KismetStringLibrary.h"
|
||||
#include "HAL/FileManagerGeneric.h"
|
||||
#include "ReplayStructs.h"
|
||||
#include "Kismet/KismetTextLibrary.h"
|
||||
|
||||
|
||||
void UReplayDataObject::AddBooleanData(FString Name,bool Data)
|
||||
{
|
||||
FReplayBoolData StructVar;
|
||||
StructVar.Name = Name;
|
||||
StructVar.Value = Data;
|
||||
|
||||
if(const int Index = DoesBooleanDataExist(Name) != -1)
|
||||
{
|
||||
boolData[Index] = StructVar;
|
||||
}
|
||||
else
|
||||
{
|
||||
boolData.Add(StructVar);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::AddByteData(FString Name,TArray<uint8> Data)
|
||||
{
|
||||
FReplayByteData StructVar;
|
||||
StructVar.Name = Name;
|
||||
StructVar.Value = Data;
|
||||
|
||||
if(const int Index = DoesByteDataExist(Name) != -1)
|
||||
{
|
||||
byteData[Index] = StructVar;
|
||||
}
|
||||
else
|
||||
{
|
||||
byteData.Add(StructVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::AddIntegerData(FString Name,int Data)
|
||||
{
|
||||
FReplayIntData StructVar;
|
||||
StructVar.Name = Name;
|
||||
StructVar.Value = Data;
|
||||
|
||||
|
||||
if(const int Index = DoesIntegerDataExist(Name) != -1)
|
||||
{
|
||||
intData[Index] = StructVar;
|
||||
}
|
||||
else
|
||||
{
|
||||
intData.Add(StructVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::AddInteger64Data(FString Name,int64 Data)
|
||||
{
|
||||
FReplayInt64Data StructVar;
|
||||
StructVar.Name = Name;
|
||||
StructVar.Value = Data;
|
||||
|
||||
if(const int Index = DoesInteger64DataExist(Name) != -1)
|
||||
{
|
||||
int64Data[Index] = StructVar;
|
||||
}
|
||||
else
|
||||
{
|
||||
int64Data.Add(StructVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::AddFloatData(FString Name,float Data)
|
||||
{
|
||||
FReplayFloatData StructVar;
|
||||
StructVar.Name = Name;
|
||||
StructVar.Value = Data;
|
||||
|
||||
if(const int Index = DoesFloatDataExist(Name) != -1)
|
||||
{
|
||||
floatData[Index] = StructVar;
|
||||
}
|
||||
else
|
||||
{
|
||||
floatData.Add(StructVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::AddNameData(FString Name,FName Data)
|
||||
{
|
||||
FReplayNameData StructVar;
|
||||
StructVar.Name = Name;
|
||||
StructVar.Value = Data;
|
||||
|
||||
if(const int Index = DoesNameDataExist(Name) != -1)
|
||||
{
|
||||
nameData[Index] = StructVar;
|
||||
}
|
||||
else
|
||||
{
|
||||
nameData.Add(StructVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::AddStringData(FString Name,FString Data)
|
||||
{
|
||||
FReplayStringData StructVar;
|
||||
StructVar.Name = Name;
|
||||
StructVar.Value = Data;
|
||||
|
||||
if(const int Index = DoesStringDataExist(Name) != -1)
|
||||
{
|
||||
stringData[Index] = StructVar;
|
||||
}
|
||||
else
|
||||
{
|
||||
stringData.Add(StructVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::AddTextData(FString Name,FText Data)
|
||||
{
|
||||
FReplayTextData StructVar;
|
||||
StructVar.Name = Name;
|
||||
StructVar.Value = Data;
|
||||
|
||||
if(const int Index = DoesTextDataExist(Name) != -1)
|
||||
{
|
||||
textData[Index] = StructVar;
|
||||
}
|
||||
else
|
||||
{
|
||||
textData.Add(StructVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::AddVectorData(FString Name,FVector Data)
|
||||
{
|
||||
FReplayVectorData StructVar;
|
||||
StructVar.Name = Name;
|
||||
StructVar.Value = Data;
|
||||
|
||||
if(const int Index = DoesVectorDataExist(Name) != -1)
|
||||
{
|
||||
vectorData[Index] = StructVar;
|
||||
}
|
||||
else
|
||||
{
|
||||
vectorData.Add(StructVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::AddRotatorData(FString Name,FRotator Data)
|
||||
{
|
||||
FReplayRotatorData StructVar;
|
||||
StructVar.Name = Name;
|
||||
StructVar.Value = Data;
|
||||
|
||||
if(const int Index = DoesRotatorDataExist(Name) != -1)
|
||||
{
|
||||
rotatorData[Index] = StructVar;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotatorData.Add(StructVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::AddTransformData(FString Name,FTransform Data)
|
||||
{
|
||||
FReplayTransformData StructVar;
|
||||
StructVar.Name = Name;
|
||||
StructVar.Value = Data;
|
||||
|
||||
if(const int Index = DoesTransformDataExist(Name) != -1)
|
||||
{
|
||||
transformData[Index] = StructVar;
|
||||
}
|
||||
else
|
||||
{
|
||||
transformData.Add(StructVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int UReplayDataObject::DoesBooleanDataExist (FString Name)
|
||||
{
|
||||
for (int i = 0; i < boolData.Num(); ++i)
|
||||
{
|
||||
if (boolData[i].Name == Name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int UReplayDataObject::DoesByteDataExist (FString Name)
|
||||
{
|
||||
for (int i = 0; i < byteData.Num(); ++i)
|
||||
{
|
||||
if (byteData[i].Name == Name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int UReplayDataObject::DoesIntegerDataExist (FString Name)
|
||||
{
|
||||
for (int i = 0; i < intData.Num(); ++i)
|
||||
{
|
||||
if (intData[i].Name == Name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int UReplayDataObject::DoesInteger64DataExist (FString Name)
|
||||
{
|
||||
for (int i = 0; i < int64Data.Num(); ++i)
|
||||
{
|
||||
if (int64Data[i].Name == Name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int UReplayDataObject::DoesFloatDataExist (FString Name)
|
||||
{
|
||||
for (int i = 0; i < floatData.Num(); ++i)
|
||||
{
|
||||
if (floatData[i].Name == Name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int UReplayDataObject::DoesNameDataExist (FString Name)
|
||||
{
|
||||
for (int i = 0; i < nameData.Num(); ++i)
|
||||
{
|
||||
if (nameData[i].Name == Name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int UReplayDataObject::DoesStringDataExist (FString Name)
|
||||
{
|
||||
for (int i = 0; i < stringData.Num(); ++i)
|
||||
{
|
||||
if (stringData[i].Name == Name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int UReplayDataObject::DoesTextDataExist (FString Name)
|
||||
{
|
||||
for (int i = 0; i < textData.Num(); ++i)
|
||||
{
|
||||
if (textData[i].Name == Name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int UReplayDataObject::DoesVectorDataExist (FString Name)
|
||||
{
|
||||
for (int i = 0; i < vectorData.Num(); ++i)
|
||||
{
|
||||
if (vectorData[i].Name == Name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int UReplayDataObject::DoesRotatorDataExist (FString Name)
|
||||
{
|
||||
for (int i = 0; i < stringData.Num(); ++i)
|
||||
{
|
||||
if (stringData[i].Name == Name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int UReplayDataObject::DoesTransformDataExist (FString Name)
|
||||
{
|
||||
for (int i = 0; i < transformData.Num(); ++i)
|
||||
{
|
||||
if (transformData[i].Name == Name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::RemoveBooleanData(FString Name)
|
||||
{
|
||||
if (const int Index = DoesBooleanDataExist(Name) != -1)
|
||||
{
|
||||
boolData.RemoveAt(Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::RemoveByteData(FString Name)
|
||||
{
|
||||
if (const int Index = DoesByteDataExist(Name) != -1)
|
||||
{
|
||||
byteData.RemoveAt(Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::RemoveIntegerData(FString Name)
|
||||
{
|
||||
if (const int Index = DoesIntegerDataExist(Name) != -1)
|
||||
{
|
||||
intData.RemoveAt(Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::RemoveInteger64Data(FString Name)
|
||||
{
|
||||
if (const int Index = DoesInteger64DataExist(Name) != -1)
|
||||
{
|
||||
int64Data.RemoveAt(Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::RemoveFloatData(FString Name)
|
||||
{
|
||||
if (const int Index = DoesFloatDataExist(Name) != -1)
|
||||
{
|
||||
floatData.RemoveAt(Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::RemoveNameData(FString Name)
|
||||
{
|
||||
if (const int Index = DoesNameDataExist(Name) != -1)
|
||||
{
|
||||
nameData.RemoveAt(Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::RemoveStringData(FString Name)
|
||||
{
|
||||
if (const int Index = DoesStringDataExist(Name) != -1)
|
||||
{
|
||||
stringData.RemoveAt(Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::RemoveTextData(FString Name)
|
||||
{
|
||||
if (const int Index = DoesTextDataExist(Name) != -1)
|
||||
{
|
||||
textData.RemoveAt(Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::RemoveVectorData(FString Name)
|
||||
{
|
||||
if (const int Index = DoesVectorDataExist(Name) != -1)
|
||||
{
|
||||
vectorData.RemoveAt(Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::RemoveRotatorData(FString Name)
|
||||
{
|
||||
if (const int Index = DoesRotatorDataExist(Name) != -1)
|
||||
{
|
||||
rotatorData.RemoveAt(Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UReplayDataObject::RemoveTransformData(FString Name)
|
||||
{
|
||||
if (const int Index = DoesTransformDataExist(Name) != -1)
|
||||
{
|
||||
transformData.RemoveAt(Index);
|
||||
}
|
||||
}
|
||||
|
||||
bool UReplayDataObject::GetBooleanData(FString Name)
|
||||
{
|
||||
bool bReturnValue = false;
|
||||
|
||||
for (FReplayBoolData Data : boolData)
|
||||
{
|
||||
if (Data.Name == Name)
|
||||
{
|
||||
return Data.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return bReturnValue;
|
||||
}
|
||||
|
||||
|
||||
TArray<uint8> UReplayDataObject::GetByteData(FString Name)
|
||||
{
|
||||
TArray<uint8> ReturnValue;
|
||||
|
||||
for (FReplayByteData Data : byteData)
|
||||
{
|
||||
if (Data.Name == Name)
|
||||
{
|
||||
return Data.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
int UReplayDataObject::GetIntegerData(FString Name)
|
||||
{
|
||||
int ReturnValue = 0;
|
||||
|
||||
for (FReplayIntData Data : intData)
|
||||
{
|
||||
if (Data.Name == Name)
|
||||
{
|
||||
return Data.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
int64 UReplayDataObject::GetInteger64Data(FString Name)
|
||||
{
|
||||
int64 ReturnValue = 0;
|
||||
|
||||
for (FReplayInt64Data Data : int64Data)
|
||||
{
|
||||
if (Data.Name == Name)
|
||||
{
|
||||
return Data.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
float UReplayDataObject::GetFloatData(FString Name)
|
||||
{
|
||||
float ReturnValue = 0.0;
|
||||
|
||||
for (FReplayFloatData Data : floatData)
|
||||
{
|
||||
if (Data.Name == Name)
|
||||
{
|
||||
return Data.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
FName UReplayDataObject::GetNameData(FString Name)
|
||||
{
|
||||
FName ReturnValue = "";
|
||||
|
||||
for (FReplayNameData Data : nameData)
|
||||
{
|
||||
if (Data.Name == Name)
|
||||
{
|
||||
return Data.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
FString UReplayDataObject::GetStringData(FString Name)
|
||||
{
|
||||
FString ReturnValue = "";
|
||||
|
||||
for (FReplayStringData Data : stringData)
|
||||
{
|
||||
if (Data.Name == Name)
|
||||
{
|
||||
return Data.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
FText UReplayDataObject::GetTextData(FString Name)
|
||||
{
|
||||
FText ReturnValue;
|
||||
|
||||
for (FReplayTextData Data : textData)
|
||||
{
|
||||
if (Data.Name == Name)
|
||||
{
|
||||
return Data.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
FVector UReplayDataObject::GetVectorData(FString Name)
|
||||
{
|
||||
FVector ReturnValue = FVector();
|
||||
|
||||
for (FReplayVectorData Data : vectorData)
|
||||
{
|
||||
if (Data.Name == Name)
|
||||
{
|
||||
return Data.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
FRotator UReplayDataObject::GetRotatorData(FString Name)
|
||||
{
|
||||
FRotator ReturnValue = FRotator();
|
||||
|
||||
for (FReplayRotatorData Data : rotatorData)
|
||||
{
|
||||
if (Data.Name == Name)
|
||||
{
|
||||
return Data.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
FTransform UReplayDataObject::GetTransformData(FString Name)
|
||||
{
|
||||
FTransform ReturnValue = FTransform();
|
||||
|
||||
for (FReplayTransformData Data : transformData)
|
||||
{
|
||||
if (Data.Name == Name)
|
||||
{
|
||||
return Data.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
FString UReplayDataObject::SaveReplayMetaDataToString()
|
||||
{
|
||||
//First Write all structs into strings
|
||||
|
||||
TArray<FString> BoolArray;
|
||||
|
||||
for (FReplayBoolData Data : boolData)
|
||||
{
|
||||
FString DataName = Data.Name;
|
||||
FString DataValue = UKismetStringLibrary::Conv_BoolToString(Data.Value);
|
||||
|
||||
BoolArray.Add(DataName + DataValuesSeperator + DataValue);
|
||||
}
|
||||
|
||||
|
||||
TArray<FString> ByteArray;
|
||||
|
||||
for (FReplayByteData Data : byteData)
|
||||
{
|
||||
FString DataName = Data.Name;
|
||||
FString DataValue;
|
||||
|
||||
FUTF8ToTCHAR Src = FUTF8ToTCHAR((const ANSICHAR*) (Data.Value.GetData() + 0), Data.Value.Num());
|
||||
DataValue.AppendChars(Src.Get(), Src.Length());
|
||||
|
||||
ByteArray.Add(DataName + DataValuesSeperator + DataValue);
|
||||
}
|
||||
|
||||
|
||||
TArray<FString> IntArray;
|
||||
|
||||
for (FReplayIntData Data : intData)
|
||||
{
|
||||
FString DataName = Data.Name;
|
||||
FString DataValue = UKismetStringLibrary::Conv_IntToString(Data.Value);
|
||||
|
||||
IntArray.Add(DataName + DataValuesSeperator + DataValue);
|
||||
}
|
||||
|
||||
TArray<FString> Int64Array;
|
||||
|
||||
for (FReplayInt64Data Data : int64Data)
|
||||
{
|
||||
FString DataName = Data.Name;
|
||||
FString DataValue = UKismetStringLibrary::Conv_IntToString(Data.Value);
|
||||
|
||||
Int64Array.Add(DataName + DataValuesSeperator + DataValue);
|
||||
}
|
||||
|
||||
TArray<FString> FloatArray;
|
||||
|
||||
for (FReplayFloatData Data : floatData)
|
||||
{
|
||||
FString DataName = Data.Name;
|
||||
|
||||
#if ENGINE_MAJOR_VERSION <= 4
|
||||
FString DataValue = UKismetStringLibrary::Conv_FloatToString(Data.Value);
|
||||
#else
|
||||
FString DataValue = FString::SanitizeFloat(Data.Value);
|
||||
#endif
|
||||
|
||||
|
||||
FloatArray.Add(DataName + DataValuesSeperator + DataValue);
|
||||
}
|
||||
|
||||
TArray<FString> NameArray;
|
||||
|
||||
for (FReplayNameData Data : nameData)
|
||||
{
|
||||
FString DataName = Data.Name;
|
||||
FString DataValue = UKismetStringLibrary::Conv_NameToString(Data.Value);
|
||||
|
||||
NameArray.Add(DataName + DataValuesSeperator + DataValue);
|
||||
}
|
||||
|
||||
TArray<FString> StringArray;
|
||||
|
||||
for (FReplayStringData Data : stringData)
|
||||
{
|
||||
FString DataName = Data.Name;
|
||||
FString DataValue = Data.Value;
|
||||
|
||||
StringArray.Add(DataName + DataValuesSeperator + DataValue);
|
||||
}
|
||||
|
||||
TArray<FString> TextArray;
|
||||
|
||||
for (FReplayTextData Data : textData)
|
||||
{
|
||||
FString DataName = Data.Name;
|
||||
FString DataValue = UKismetTextLibrary::Conv_TextToString(Data.Value);
|
||||
|
||||
TextArray.Add(DataName + DataValuesSeperator + DataValue);
|
||||
}
|
||||
|
||||
TArray<FString> VectorArray;
|
||||
|
||||
for (FReplayVectorData Data : vectorData)
|
||||
{
|
||||
FString DataName = Data.Name;
|
||||
FString DataValue = UKismetStringLibrary::Conv_VectorToString(Data.Value);
|
||||
|
||||
VectorArray.Add(DataName + DataValuesSeperator + DataValue);
|
||||
}
|
||||
|
||||
TArray<FString> RotatorArray;
|
||||
|
||||
for (FReplayRotatorData Data : rotatorData)
|
||||
{
|
||||
FString DataName = Data.Name;
|
||||
FString DataValue = UKismetStringLibrary::Conv_RotatorToString(Data.Value);
|
||||
|
||||
RotatorArray.Add(DataName + DataValuesSeperator + DataValue);
|
||||
}
|
||||
|
||||
TArray<FString> TransformArray;
|
||||
|
||||
for (FReplayTransformData Data : transformData)
|
||||
{
|
||||
FString DataName = Data.Name;
|
||||
FString DataVectorPart = UKismetStringLibrary::Conv_VectorToString(Data.Value.GetLocation());
|
||||
FString DataRotatorPart = UKismetStringLibrary::Conv_RotatorToString(Data.Value.GetRotation().Rotator());
|
||||
FString DataScalePart = UKismetStringLibrary::Conv_VectorToString(Data.Value.GetScale3D());
|
||||
|
||||
TArray<FString> DataValues;
|
||||
DataValues.Add(DataVectorPart);
|
||||
DataValues.Add(DataRotatorPart);
|
||||
DataValues.Add(DataScalePart);
|
||||
|
||||
FString DataValue = UKismetStringLibrary::JoinStringArray(DataValues,transformDataSeperator);
|
||||
|
||||
TransformArray.Add(DataName + DataValuesSeperator + DataValue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
FString BoolArrayAsSingleString = UKismetStringLibrary::JoinStringArray(BoolArray, DataArraySeperator);
|
||||
FString ByteArrayAsSingleString = UKismetStringLibrary::JoinStringArray(ByteArray, DataArraySeperator);
|
||||
FString IntArrayAsSingleString = UKismetStringLibrary::JoinStringArray(IntArray, DataArraySeperator);
|
||||
FString Int64ArrayAsSingleString = UKismetStringLibrary::JoinStringArray(Int64Array, DataArraySeperator);
|
||||
FString FloatArrayAsSingleString = UKismetStringLibrary::JoinStringArray(FloatArray, DataArraySeperator);
|
||||
FString NameArrayAsSingleString = UKismetStringLibrary::JoinStringArray(NameArray, DataArraySeperator);
|
||||
FString StringArrayAsSingleString = UKismetStringLibrary::JoinStringArray(StringArray, DataArraySeperator);
|
||||
FString TextArrayAsSingleString = UKismetStringLibrary::JoinStringArray(TextArray, DataArraySeperator);
|
||||
FString VectorArrayAsSingleString = UKismetStringLibrary::JoinStringArray(VectorArray, DataArraySeperator);
|
||||
FString RotatorArrayAsSingleString = UKismetStringLibrary::JoinStringArray(RotatorArray, DataArraySeperator);
|
||||
FString TransformArrayAsSingleString = UKismetStringLibrary::JoinStringArray(TransformArray, DataArraySeperator);
|
||||
|
||||
TArray<FString> FinalStringArray;
|
||||
FinalStringArray.Add(boolDataIdentifier + DataIdentifierSeperator + BoolArrayAsSingleString);
|
||||
FinalStringArray.Add(byteDataIdentifier + DataIdentifierSeperator + ByteArrayAsSingleString);
|
||||
FinalStringArray.Add(intDataIdentifier + DataIdentifierSeperator + IntArrayAsSingleString);
|
||||
FinalStringArray.Add(int64DataIdentifier + DataIdentifierSeperator + Int64ArrayAsSingleString);
|
||||
FinalStringArray.Add(floatDataIdentifier + DataIdentifierSeperator + FloatArrayAsSingleString);
|
||||
FinalStringArray.Add(nameDataIdentifier + DataIdentifierSeperator + NameArrayAsSingleString);
|
||||
FinalStringArray.Add(stringDataIdentifier + DataIdentifierSeperator + StringArrayAsSingleString);
|
||||
FinalStringArray.Add(textDataIdentifier + DataIdentifierSeperator + TextArrayAsSingleString);
|
||||
FinalStringArray.Add(vectorDataIdentifier + DataIdentifierSeperator + VectorArrayAsSingleString);
|
||||
FinalStringArray.Add(rotatorDataIdentifier + DataIdentifierSeperator + RotatorArrayAsSingleString);
|
||||
FinalStringArray.Add(transformDataIdentifier + DataIdentifierSeperator + TransformArrayAsSingleString);
|
||||
|
||||
FString FinalString = UKismetStringLibrary::JoinStringArray(FinalStringArray, FinalArraySeperator);
|
||||
|
||||
return FinalString;
|
||||
}
|
||||
|
||||
bool UReplayDataObject::LoadReplayMetaDataFromString(FString StringDataToParse)
|
||||
{
|
||||
boolData.Empty();
|
||||
byteData.Empty();
|
||||
intData.Empty();
|
||||
int64Data.Empty();
|
||||
floatData.Empty();
|
||||
nameData.Empty();
|
||||
stringData.Empty();
|
||||
textData.Empty();
|
||||
vectorData.Empty();
|
||||
rotatorData.Empty();
|
||||
transformData.Empty();
|
||||
|
||||
|
||||
|
||||
TArray<FString> LoadedStringArray = UKismetStringLibrary::ParseIntoArray(StringDataToParse, FinalArraySeperator);
|
||||
|
||||
for (FString Field : LoadedStringArray)
|
||||
{
|
||||
|
||||
|
||||
FString DataIdentifier;
|
||||
FString DataPart;
|
||||
|
||||
UKismetStringLibrary::Split(Field,DataIdentifierSeperator,DataIdentifier,DataPart);
|
||||
|
||||
TArray<FString> DataArray = UKismetStringLibrary::ParseIntoArray(DataPart,DataArraySeperator);
|
||||
|
||||
for (FString DataItem : DataArray)
|
||||
{
|
||||
if (DataIdentifier == boolDataIdentifier)
|
||||
{
|
||||
FReplayBoolData LoadedData;
|
||||
FString Name;
|
||||
FString Value;
|
||||
UKismetStringLibrary::Split(DataItem,DataValuesSeperator,Name, Value);
|
||||
LoadedData.Name = Name;
|
||||
if(Value == "true")
|
||||
{
|
||||
LoadedData.Value = true;
|
||||
}
|
||||
AddBooleanData(LoadedData.Name,LoadedData.Value);
|
||||
}
|
||||
|
||||
if (DataIdentifier == byteDataIdentifier)
|
||||
{
|
||||
FReplayByteData LoadedData;
|
||||
FString Name;
|
||||
FString Value;
|
||||
UKismetStringLibrary::Split(DataItem,DataValuesSeperator,Name, Value);
|
||||
LoadedData.Name = Name;
|
||||
TArray<uint8> ByteArray;
|
||||
|
||||
if(!(Value.Len() <= 0))
|
||||
{
|
||||
FTCHARToUTF8 Src = FTCHARToUTF8(Value.GetCharArray().GetData());
|
||||
ByteArray.Append((uint8*) Src.Get(), Src.Length());
|
||||
}
|
||||
|
||||
LoadedData.Value = ByteArray;
|
||||
AddByteData(LoadedData.Name,LoadedData.Value);
|
||||
}
|
||||
|
||||
if (DataIdentifier == intDataIdentifier)
|
||||
{
|
||||
FReplayIntData LoadedData;
|
||||
FString Name;
|
||||
FString Value;
|
||||
UKismetStringLibrary::Split(DataItem,DataValuesSeperator,Name, Value);
|
||||
LoadedData.Name = Name;
|
||||
LoadedData.Value = UKismetStringLibrary::Conv_StringToInt(Value);
|
||||
|
||||
AddIntegerData(LoadedData.Name,LoadedData.Value);
|
||||
}
|
||||
|
||||
if (DataIdentifier == int64DataIdentifier)
|
||||
{
|
||||
FReplayInt64Data LoadedData;
|
||||
FString Name;
|
||||
FString Value;
|
||||
UKismetStringLibrary::Split(DataItem,DataValuesSeperator,Name, Value);
|
||||
LoadedData.Name = Name;
|
||||
LoadedData.Value = UKismetStringLibrary::Conv_StringToInt(Value);
|
||||
|
||||
AddInteger64Data(LoadedData.Name,LoadedData.Value);
|
||||
}
|
||||
|
||||
if (DataIdentifier == floatDataIdentifier)
|
||||
{
|
||||
FReplayFloatData LoadedData;
|
||||
FString Name;
|
||||
FString Value;
|
||||
UKismetStringLibrary::Split(DataItem,DataValuesSeperator,Name, Value);
|
||||
LoadedData.Name = Name;
|
||||
|
||||
#if ENGINE_MAJOR_VERSION <= 4
|
||||
LoadedData.Value = UKismetStringLibrary::Conv_StringToFloat(Value);
|
||||
#else
|
||||
LexFromString(LoadedData.Value,*Value);
|
||||
#endif
|
||||
|
||||
|
||||
AddFloatData(LoadedData.Name,LoadedData.Value);
|
||||
}
|
||||
|
||||
if (DataIdentifier == nameDataIdentifier)
|
||||
{
|
||||
FReplayNameData LoadedData;
|
||||
FString Name;
|
||||
FString Value;
|
||||
UKismetStringLibrary::Split(DataItem,DataValuesSeperator,Name, Value);
|
||||
LoadedData.Name = Name;
|
||||
LoadedData.Value = UKismetStringLibrary::Conv_StringToName(Value);
|
||||
|
||||
AddNameData(LoadedData.Name,LoadedData.Value);
|
||||
}
|
||||
|
||||
if (DataIdentifier == stringDataIdentifier)
|
||||
{
|
||||
FReplayStringData LoadedData;
|
||||
FString Name;
|
||||
FString Value;
|
||||
UKismetStringLibrary::Split(DataItem,DataValuesSeperator,Name, Value);
|
||||
LoadedData.Name = Name;
|
||||
LoadedData.Value = Value;
|
||||
|
||||
AddStringData(LoadedData.Name,LoadedData.Value);
|
||||
}
|
||||
|
||||
if (DataIdentifier == textDataIdentifier)
|
||||
{
|
||||
FReplayTextData LoadedData;
|
||||
FString Name;
|
||||
FString Value;
|
||||
UKismetStringLibrary::Split(DataItem,DataValuesSeperator,Name, Value);
|
||||
LoadedData.Name = Name;
|
||||
LoadedData.Value = UKismetTextLibrary::Conv_StringToText(Value);
|
||||
|
||||
AddTextData(LoadedData.Name,LoadedData.Value);
|
||||
}
|
||||
|
||||
if (DataIdentifier == vectorDataIdentifier)
|
||||
{
|
||||
FReplayVectorData LoadedData;
|
||||
FString Name;
|
||||
FString Value;
|
||||
UKismetStringLibrary::Split(DataItem,DataValuesSeperator,Name, Value);
|
||||
LoadedData.Name = Name;
|
||||
FVector ConvertedValue;
|
||||
bool bWasSuccessful;
|
||||
UKismetStringLibrary::Conv_StringToVector(Value,ConvertedValue,bWasSuccessful);
|
||||
LoadedData.Value = ConvertedValue;
|
||||
|
||||
AddVectorData(LoadedData.Name,LoadedData.Value);
|
||||
}
|
||||
|
||||
if (DataIdentifier == rotatorDataIdentifier)
|
||||
{
|
||||
FReplayRotatorData LoadedData;
|
||||
FString Name;
|
||||
FString Value;
|
||||
UKismetStringLibrary::Split(DataItem,DataValuesSeperator,Name, Value);
|
||||
LoadedData.Name = Name;
|
||||
FRotator ConvertedValue;
|
||||
bool bWasSuccessful;
|
||||
UKismetStringLibrary::Conv_StringToRotator(Value,ConvertedValue,bWasSuccessful);
|
||||
LoadedData.Value = ConvertedValue;
|
||||
|
||||
AddRotatorData(LoadedData.Name,LoadedData.Value);
|
||||
}
|
||||
|
||||
if (DataIdentifier == transformDataIdentifier)
|
||||
{
|
||||
FReplayTransformData LoadedData;
|
||||
FString Name;
|
||||
FString Value;
|
||||
UKismetStringLibrary::Split(DataItem,DataValuesSeperator,Name, Value);
|
||||
LoadedData.Name = Name;
|
||||
|
||||
TArray<FString> DataComponents = UKismetStringLibrary::ParseIntoArray(Value,transformDataSeperator);
|
||||
|
||||
FVector ConvertedVectorValue;
|
||||
bool bWasSuccessful;
|
||||
UKismetStringLibrary::Conv_StringToVector(DataComponents[0],ConvertedVectorValue,bWasSuccessful);
|
||||
|
||||
FRotator ConvertedRotatorValue;
|
||||
UKismetStringLibrary::Conv_StringToRotator(DataComponents[1],ConvertedRotatorValue,bWasSuccessful);
|
||||
|
||||
FVector ConvertedScaleValue;
|
||||
UKismetStringLibrary::Conv_StringToVector(DataComponents[2],ConvertedScaleValue,bWasSuccessful);
|
||||
LoadedData.Value = FTransform(ConvertedRotatorValue,ConvertedVectorValue,ConvertedScaleValue);
|
||||
|
||||
AddTransformData(LoadedData.Name,LoadedData.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
|
||||
#include "ReplayObject.h"
|
||||
#include "ReplayDataObject.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
#include "HAL/FileManagerGeneric.h"
|
||||
#include "Engine/DemoNetDriver.h"
|
||||
|
||||
void UReplayObject::RequestEvents(FString Group,int UserIndex)
|
||||
{
|
||||
const TSharedPtr<INetworkReplayStreamer> EnumerateStreamsPtr = FNetworkReplayStreaming::Get().GetFactory().CreateReplayStreamer();
|
||||
|
||||
EnumerateEventsDel = FEnumerateEventsCallback::CreateUObject(this, &UReplayObject::OnEnumerateEventsComplete);
|
||||
|
||||
if (EnumerateStreamsPtr.Get())
|
||||
{
|
||||
EnumerateStreamsPtr.Get()->EnumerateEvents(ReplayInfo.ActualName,Group,UserIndex, EnumerateEventsDel);
|
||||
}
|
||||
}
|
||||
|
||||
void UReplayObject::OnEnumerateEventsComplete(const FEnumerateEventsResult& Results)
|
||||
{
|
||||
TArray<FReplayEvent> ReplayEvents;
|
||||
if(Results.WasSuccessful())
|
||||
{
|
||||
for(FReplayEventListItem EventItem : Results.ReplayEventList.ReplayEvents)
|
||||
{
|
||||
FReplayEvent ReplayEventTemp;
|
||||
ReplayEventTemp.EventID = EventItem.ID;
|
||||
|
||||
ReplayEventTemp.Group = EventItem.Group;
|
||||
ReplayEventTemp.TimeInMs = (int32)EventItem.Time1;
|
||||
|
||||
UReplayDataObject* DataObject = NewObject<UReplayDataObject>();
|
||||
DataObject->LoadReplayMetaDataFromString(EventItem.Metadata);
|
||||
ReplayEventTemp.Data = DataObject;
|
||||
|
||||
ReplayEvents.Add(ReplayEventTemp);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
OnRequestEventsComplete.Broadcast(ReplayEvents);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
|
||||
#include "ReplayPlayerController.h"
|
||||
|
||||
AReplayPlayerController::AReplayPlayerController()
|
||||
{
|
||||
bShouldPerformFullTickWhenPaused = true;
|
||||
SetTickableWhenPaused(true);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "ReplaySystem.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogReplaySystem);
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FReplaySystemModule"
|
||||
|
||||
void FReplaySystemModule::StartupModule()
|
||||
{
|
||||
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
|
||||
|
||||
}
|
||||
|
||||
void FReplaySystemModule::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.
|
||||
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FReplaySystemModule, ReplaySystem)
|
||||
@@ -0,0 +1,490 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "ReplaySystemBPLibrary.h"
|
||||
#include "Engine/World.h"
|
||||
#include "GameFramework/WorldSettings.h"
|
||||
#include "Engine/DemoNetDriver.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "DeleteReplayObject.h"
|
||||
#include "GetSavedReplaysObject.h"
|
||||
#include "GoToTimeObject.h"
|
||||
#include "RenameReplayObject.h"
|
||||
#include "ReplayDataObject.h"
|
||||
#include "ReplayPlayerController.h"
|
||||
#include "Containers/UnrealString.h"
|
||||
#include "RequestEventsObject.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
|
||||
|
||||
UReplaySystemBPLibrary::UReplaySystemBPLibrary(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
void UReplaySystemBPLibrary::SetReplaySavePath(UObject* WorldContextObject, const FString& Path)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (const TSharedPtr<INetworkReplayStreamer> EnumerateStreamsPtr = FNetworkReplayStreaming::Get().GetFactory().
|
||||
CreateReplayStreamer())
|
||||
{
|
||||
EnumerateStreamsPtr->SetDemoPath(Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FString UReplaySystemBPLibrary::GetReplaySavePath(UObject* WorldContextObject)
|
||||
{
|
||||
FString Path = "";
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (const TSharedPtr<INetworkReplayStreamer> EnumerateStreamsPtr = FNetworkReplayStreaming::Get().GetFactory().
|
||||
CreateReplayStreamer())
|
||||
{
|
||||
EnumerateStreamsPtr->GetDemoPath(Path);
|
||||
}
|
||||
}
|
||||
return Path;
|
||||
}
|
||||
|
||||
void UReplaySystemBPLibrary::RecordReplay(UObject* WorldContextObject, const FString& ReplayName,
|
||||
const FString& ReplayFriendlyName)
|
||||
{
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (UGameInstance* GI = Cast<UGameInstance>(World->GetGameInstance()))
|
||||
{
|
||||
const TArray<FString> Options;
|
||||
|
||||
GI->StartRecordingReplay(ReplayName, ReplayFriendlyName, Options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UReplaySystemBPLibrary::StopRecordingReplay(UObject* WorldContextObject)
|
||||
{
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (IsRecordingReplay(WorldContextObject))
|
||||
{
|
||||
if (UGameInstance* GI = Cast<UGameInstance>(World->GetGameInstance()))
|
||||
{
|
||||
GI->StopRecordingReplay();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UReplaySystemBPLibrary::IsRecordingReplay(UObject* WorldContextObject)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (World != nullptr && GetDemoDriver(World) != nullptr)
|
||||
{
|
||||
return GetDemoDriver(World)->IsRecording();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
UDeleteReplayObject* UReplaySystemBPLibrary::DeleteReplay(UObject* WorldContextObject, const FString& ReplayName)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (UDeleteReplayObject* ReplayDeleteObj = NewObject<UDeleteReplayObject>())
|
||||
{
|
||||
ReplayDeleteObj->DeleteReplay(ReplayName);
|
||||
return ReplayDeleteObj;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
URenameReplayObject* UReplaySystemBPLibrary::RenameReplay(UObject* WorldContextObject, const FString& ReplayName,
|
||||
const FString& NewReplayName, const int32 UserIndex)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (URenameReplayObject* ReplayRenameObj = NewObject<URenameReplayObject>())
|
||||
{
|
||||
ReplayRenameObj->RenameReplay(ReplayName, NewReplayName, UserIndex, true);
|
||||
return ReplayRenameObj;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
URenameReplayObject* UReplaySystemBPLibrary::RenameReplayFriendly(UObject* WorldContextObject,
|
||||
const FString& ReplayName,
|
||||
const FString& NewFriendlyReplayName,
|
||||
const int32 UserIndex)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (URenameReplayObject* ReplayRenameObj = NewObject<URenameReplayObject>())
|
||||
{
|
||||
ReplayRenameObj->RenameReplay(ReplayName, NewFriendlyReplayName, UserIndex, false);
|
||||
return ReplayRenameObj;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UGetSavedReplaysObject* UReplaySystemBPLibrary::GetSavedReplays(UObject* WorldContextObject)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (UGetSavedReplaysObject* SavedReplaysObj = NewObject<UGetSavedReplaysObject>())
|
||||
{
|
||||
SavedReplaysObj->GetSavedReplays();
|
||||
return SavedReplaysObj;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool UReplaySystemBPLibrary::PlayRecordedReplay(UObject* WorldContextObject, const FString& ReplayName)
|
||||
{
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (UGameInstance* GI = Cast<UGameInstance>(World->GetGameInstance()))
|
||||
{
|
||||
const TArray<FString> Options;
|
||||
|
||||
return GI->PlayReplay(ReplayName, nullptr, Options);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
UGoToTimeObject* UReplaySystemBPLibrary::RestartReplayPlayback(UObject* WorldContextObject)
|
||||
{
|
||||
UGoToTimeObject* GoToTimeObject = NewObject<UGoToTimeObject>();
|
||||
if (!GoToTimeObject)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GoToTimeObject->GoToTime(WorldContextObject, 0.0f, false);
|
||||
|
||||
return GoToTimeObject;
|
||||
}
|
||||
|
||||
UGoToTimeObject* UReplaySystemBPLibrary::GoToSpecificTime(UObject* WorldContextObject, float TimeToGoTo,
|
||||
bool bRetainCurrentPauseState)
|
||||
{
|
||||
UGoToTimeObject* GoToTimeObject = NewObject<UGoToTimeObject>();
|
||||
if (!GoToTimeObject)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GoToTimeObject->GoToTime(WorldContextObject, TimeToGoTo, bRetainCurrentPauseState);
|
||||
|
||||
return GoToTimeObject;
|
||||
}
|
||||
|
||||
void UReplaySystemBPLibrary::PausePlayback(UObject* WorldContextObject)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (AWorldSettings* WorldSettings = World->GetWorldSettings())
|
||||
{
|
||||
if (const UDemoNetDriver* DemoDriver = GetDemoDriver(World))
|
||||
{
|
||||
if (DemoDriver && DemoDriver->ServerConnection && DemoDriver->ServerConnection->PlayerController && DemoDriver->ServerConnection->PlayerController->PlayerState)
|
||||
{
|
||||
World->bIsCameraMoveableWhenPaused = true;
|
||||
WorldSettings->SetPauserPlayerState(DemoDriver->ServerConnection->PlayerController->PlayerState);
|
||||
if (AReplayPlayerController* ReplayPC = Cast<AReplayPlayerController>(
|
||||
UGameplayStatics::GetPlayerController(World, 0)))
|
||||
{
|
||||
ReplayPC->OnTogglePause(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UReplaySystemBPLibrary::ResumePlayback(UObject* WorldContextObject)
|
||||
{
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (AWorldSettings* WorldSettings = World->GetWorldSettings())
|
||||
{
|
||||
WorldSettings->SetPauserPlayerState(nullptr);
|
||||
if (AReplayPlayerController* ReplayPC = Cast<AReplayPlayerController>(
|
||||
UGameplayStatics::GetPlayerController(World, 0)))
|
||||
{
|
||||
ReplayPC->OnTogglePause(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UReplaySystemBPLibrary::SetPlaybackSpeed(UObject* WorldContextObject, float Speed)
|
||||
{
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (AWorldSettings* WorldSettings = World->GetWorldSettings())
|
||||
{
|
||||
WorldSettings->DemoPlayTimeDilation = Speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float UReplaySystemBPLibrary::GetPlaybackSpeed(UObject* WorldContextObject)
|
||||
{
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (const AWorldSettings* WorldSettings = World->GetWorldSettings())
|
||||
{
|
||||
return WorldSettings->DemoPlayTimeDilation;
|
||||
}
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float UReplaySystemBPLibrary::GetCurrentReplayTime(UObject* WorldContextObject)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (const UDemoNetDriver* DemoDriver = GetDemoDriver(World))
|
||||
{
|
||||
return DemoDriver->GetDemoCurrentTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float UReplaySystemBPLibrary::GetReplayLength(UObject* WorldContextObject)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (const UDemoNetDriver* DemoDriver = GetDemoDriver(World))
|
||||
{
|
||||
if (IsRecordingReplay(WorldContextObject))
|
||||
{
|
||||
return DemoDriver->AccumulatedRecordTime;
|
||||
}
|
||||
|
||||
if (IsPlayingReplay(WorldContextObject))
|
||||
{
|
||||
return DemoDriver->GetDemoTotalTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
bool UReplaySystemBPLibrary::IsPlayingReplay(UObject* WorldContextObject)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (const UDemoNetDriver* DemoDriver = GetDemoDriver(World))
|
||||
{
|
||||
return DemoDriver->IsPlaying();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UReplaySystemBPLibrary::IsReplayPlaybackPaused(UObject* WorldContextObject)
|
||||
{
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (IsPlayingReplay(WorldContextObject))
|
||||
{
|
||||
if (const AWorldSettings* WorldSettings = World->GetWorldSettings())
|
||||
{
|
||||
return WorldSettings->GetPauserPlayerState() != nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FString UReplaySystemBPLibrary::GetActiveReplayName(UObject* WorldContextObject)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (World != nullptr && GetDemoDriver(World) != nullptr)
|
||||
{
|
||||
return GetDemoDriver(World)->GetActiveReplayName();
|
||||
}
|
||||
}
|
||||
return "None";
|
||||
}
|
||||
|
||||
bool UReplaySystemBPLibrary::AddEventToActiveReplay(UObject* WorldContextObject, const FString& EventName,
|
||||
const FString& Group, UReplayDataObject* DataObject)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (IsRecordingReplay(WorldContextObject))
|
||||
{
|
||||
if (World != nullptr && GetDemoDriver(World) != nullptr)
|
||||
{
|
||||
FString EmptyString = "";
|
||||
const TArray<uint8> Data;
|
||||
if (DataObject)
|
||||
{
|
||||
FString ReplayDataString = DataObject->SaveReplayMetaDataToString();
|
||||
EmptyString = ReplayDataString;
|
||||
}
|
||||
|
||||
GetDemoDriver(World)->AddOrUpdateEvent(EventName, Group, EmptyString, Data);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
URequestEventsObject* UReplaySystemBPLibrary::RequestActiveReplayEvents(UObject* WorldContextObject, FString Group,
|
||||
int UserIndex)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (!IsRecordingReplay(WorldContextObject) && IsPlayingReplay(WorldContextObject))
|
||||
{
|
||||
if (URequestEventsObject* RequestEventsObject = NewObject<URequestEventsObject>())
|
||||
{
|
||||
RequestEventsObject->RequestEvents(GetActiveReplayName(WorldContextObject), Group, UserIndex);
|
||||
return RequestEventsObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UReplayDataObject* UReplaySystemBPLibrary::CreateReplayDataObject()
|
||||
{
|
||||
UReplayDataObject* DataObject = NewObject<UReplayDataObject>();
|
||||
return DataObject;
|
||||
}
|
||||
|
||||
float UReplaySystemBPLibrary::MsToSeconds(const int32 MS)
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION <= 4
|
||||
const float MsAsFloat = UKismetMathLibrary::Conv_IntToFloat(MS);
|
||||
#else
|
||||
const float MsAsFloat = UKismetMathLibrary::Conv_IntToDouble(MS);
|
||||
#endif
|
||||
|
||||
const float MsAsSeconds = MsAsFloat / 1000;
|
||||
return MsAsSeconds;
|
||||
}
|
||||
|
||||
void UReplaySystemBPLibrary::SpectateActor(UObject* WorldContextObject, AActor* Actor, FBlendSettings BlendSettings)
|
||||
{
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (!Actor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (UGameplayStatics::GetPlayerController(World, 0))
|
||||
{
|
||||
if (APlayerController* PC = UGameplayStatics::GetPlayerController(World, 0))
|
||||
{
|
||||
if (!PC->IsLocalController())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Everything from here is happening only locally/on the client
|
||||
PC->SetViewTargetWithBlend(Actor, BlendSettings.BlendTime, BlendSettings.BlendFunction,
|
||||
BlendSettings.BlendExponent, BlendSettings.bLockOutgoing);
|
||||
if (AReplayPlayerController* ReplayPC = Cast<AReplayPlayerController>(
|
||||
UGameplayStatics::GetPlayerController(World, 0)))
|
||||
{
|
||||
ReplayPC->OnSpectateActor(Actor);
|
||||
ReplayPC->bIsSpectating = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UReplaySystemBPLibrary::StopSpectating(UObject* WorldContextObject, FBlendSettings BlendSettings)
|
||||
{
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (UGameplayStatics::GetPlayerController(World, 0))
|
||||
{
|
||||
if (APlayerController* PC = UGameplayStatics::GetPlayerController(World, 0))
|
||||
{
|
||||
if (!PC->IsLocalController())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Everything from here is happening only locally/on the client
|
||||
|
||||
PC->SetViewTargetWithBlend(PC->GetPawn(), BlendSettings.BlendTime, BlendSettings.BlendFunction,
|
||||
BlendSettings.BlendExponent, BlendSettings.bLockOutgoing);
|
||||
|
||||
if (AReplayPlayerController* ReplayPC = Cast<AReplayPlayerController>(
|
||||
UGameplayStatics::GetPlayerController(World, 0)))
|
||||
{
|
||||
ReplayPC->OnStopSpectateActor();
|
||||
ReplayPC->bIsSpectating = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UDemoNetDriver* UReplaySystemBPLibrary::GetDemoDriver(const UObject* WorldContextObject)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION > 4
|
||||
return World->GetDemoNetDriver();
|
||||
#elif ENGINE_MINOR_VERSION >= 26
|
||||
return World->GetDemoNetDriver();
|
||||
#elif ENGINE_MINOR_VERSION < 26
|
||||
return World->DemoNetDriver;
|
||||
#endif
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UReplaySystemBPLibrary::SetMaxRecordHz(UObject* WorldContextObject, float Hz)
|
||||
{
|
||||
if (const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject))
|
||||
{
|
||||
if (UGameplayStatics::GetPlayerController(World, 0))
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION <= 4
|
||||
FString Command = "demo.recordhz " + UKismetStringLibrary::Conv_FloatToString(Hz);
|
||||
#else
|
||||
FString Command = "demo.recordhz " + FString::SanitizeFloat(Hz);
|
||||
#endif
|
||||
|
||||
|
||||
UGameplayStatics::GetPlayerController(World, 0)->ConsoleCommand(Command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float UReplaySystemBPLibrary::GetMaxRecordHz()
|
||||
{
|
||||
static const auto CVar = IConsoleManager::Get().FindConsoleVariable(TEXT("demo.recordhz"));
|
||||
const float value = CVar->GetFloat();
|
||||
return value;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
|
||||
#include "RequestEventsObject.h"
|
||||
#include "ReplayStructs.h"
|
||||
#include "ReplayObject.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
#include "ReplayDataObject.h"
|
||||
|
||||
|
||||
void URequestEventsObject::RequestEvents(FString ReplayName,FString Group, int UserIndex)
|
||||
{
|
||||
const TSharedPtr<INetworkReplayStreamer> EnumerateStreamsPtr = FNetworkReplayStreaming::Get().GetFactory().CreateReplayStreamer();
|
||||
|
||||
EnumerateEventsDel = FEnumerateEventsCallback::CreateUObject(this, &URequestEventsObject::OnEnumerateEventsComplete);
|
||||
|
||||
if (EnumerateStreamsPtr.Get())
|
||||
{
|
||||
EnumerateStreamsPtr.Get()->EnumerateEvents(ReplayName,Group,UserIndex, EnumerateEventsDel);
|
||||
}
|
||||
}
|
||||
|
||||
void URequestEventsObject::OnEnumerateEventsComplete(const FEnumerateEventsResult& Results)
|
||||
{
|
||||
TArray<FReplayEvent> ReplayEvents;
|
||||
if(Results.WasSuccessful())
|
||||
{
|
||||
for(FReplayEventListItem EventItem : Results.ReplayEventList.ReplayEvents)
|
||||
{
|
||||
FReplayEvent ReplayEventTemp;
|
||||
ReplayEventTemp.EventID = EventItem.ID;
|
||||
|
||||
ReplayEventTemp.Group = EventItem.Group;
|
||||
ReplayEventTemp.TimeInMs = static_cast<int32>(EventItem.Time1);
|
||||
UReplayDataObject* DataObject = NewObject<UReplayDataObject>();
|
||||
DataObject->LoadReplayMetaDataFromString(EventItem.Metadata);
|
||||
ReplayEventTemp.Data = DataObject;
|
||||
|
||||
ReplayEvents.Add(ReplayEventTemp);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
OnRequestEventsComplete.Broadcast(ReplayEvents);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
#include "ReplayDelegates.h"
|
||||
#include "DeleteReplayObject.generated.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
UCLASS(BlueprintType, Blueprintable)
|
||||
class REPLAYSYSTEM_API UDeleteReplayObject : public UObject
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Replay")
|
||||
FOnDeleteComplete OnDeleteComplete;
|
||||
|
||||
void DeleteReplay(const FString& ReplayName);
|
||||
|
||||
|
||||
TSharedPtr<INetworkReplayStreamer> EnumerateStreamsPtr;
|
||||
|
||||
FDeleteFinishedStreamCallback OnDeleteFinishedStreamCompleteDel;
|
||||
|
||||
void OnDeleteFinishedStreamComplete(const FDeleteFinishedStreamResult& Result);
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ReplayObject.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
#include "GetSavedReplaysObject.generated.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
UCLASS(BlueprintType, Blueprintable)
|
||||
class REPLAYSYSTEM_API UGetSavedReplaysObject : public UObject
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Replay")
|
||||
FOnGetReplaysComplete OnGetReplaysComplete;
|
||||
|
||||
void GetSavedReplays();
|
||||
|
||||
TSharedPtr<INetworkReplayStreamer> EnumerateStreamsPtr;
|
||||
|
||||
FEnumerateStreamsCallback EnumerateStreamsCallbackDel;
|
||||
|
||||
/** Called when we get results from the replay streaming interface */
|
||||
void OnEnumerateStreamsComplete(const FEnumerateStreamsResult& Result);
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ReplayDelegates.h"
|
||||
#include "Engine.h"
|
||||
#include "Engine/DemoNetDriver.h"
|
||||
#include "GoToTimeObject.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class REPLAYSYSTEM_API UGoToTimeObject : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Sets default values for this actor's properties
|
||||
UGoToTimeObject();
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnGotoTimeComplete OnGotoTimeComplete;
|
||||
|
||||
void GoToTime(UObject* WorldContextObject,float TimeToGoTo,bool bRetainPauseState);
|
||||
|
||||
UPROPERTY()
|
||||
UObject* WCO;
|
||||
|
||||
bool bPauseStateBeforeMove = false;
|
||||
|
||||
bool bRetainPauseStateBeforeMove = false;
|
||||
|
||||
|
||||
|
||||
FOnGotoTimeDelegate OnGoToTimeDelegate;
|
||||
|
||||
void OnGoToTimeProcessed(bool bWasSuccessful);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
#include "ReplayDelegates.h"
|
||||
#include "ModifyReplayObject.generated.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
UCLASS(BlueprintType, Blueprintable)
|
||||
class REPLAYSYSTEM_API UModifyReplayObject : public UObject
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
//UPROPERTY(BlueprintAssignable, Category = "Replay")
|
||||
//FOnModifyReplayComplete OnRenameComplete;
|
||||
|
||||
void RenameReplay(const FString& ReplayName, const FString& NewName, const int32 UserIndex, bool bIsNormalName);
|
||||
|
||||
|
||||
TSharedPtr<INetworkReplayStreamer> EnumerateStreamsPtr;
|
||||
|
||||
FRenameReplayCallback OnRenameReplayCompleteDel;
|
||||
|
||||
void OnRenameReplayComplete(const FRenameReplayResult& Result);
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
#include "ReplayDelegates.h"
|
||||
#include "RenameReplayObject.generated.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
UCLASS(BlueprintType, Blueprintable)
|
||||
class REPLAYSYSTEM_API URenameReplayObject : public UObject
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Replay")
|
||||
FOnRenameReplayComplete OnRenameComplete;
|
||||
|
||||
void RenameReplay(const FString& ReplayName, const FString& NewName, const int32 UserIndex, bool bIsNormalName);
|
||||
|
||||
|
||||
TSharedPtr<INetworkReplayStreamer> EnumerateStreamsPtr;
|
||||
|
||||
FRenameReplayCallback OnRenameReplayCompleteDel;
|
||||
|
||||
void OnRenameReplayComplete(const FRenameReplayResult& Result);
|
||||
};
|
||||
@@ -0,0 +1,242 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ReplayStructs.h"
|
||||
#include "ReplayDataObject.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
UCLASS(BlueprintType, Blueprintable)
|
||||
class REPLAYSYSTEM_API UReplayDataObject : public UObject
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
FString DataPlaceHolder = "---PlaceHolderValue---";
|
||||
|
||||
FString DataArraySeperator = "---DataArray---";
|
||||
|
||||
FString DataValuesSeperator = "---DataValue---";
|
||||
|
||||
FString FinalArraySeperator = "---FinalArraySep---";
|
||||
|
||||
FString NewLineReplacer = " ---NewLineRep--- ";
|
||||
|
||||
FString NewLineReplacerR = " ---NEWLINE-R--- ";
|
||||
|
||||
FString boolDataIdentifier = "---BoolI---";
|
||||
|
||||
FString byteDataIdentifier = "---ByteI---";
|
||||
|
||||
FString intDataIdentifier = "---IntI---";
|
||||
|
||||
FString int64DataIdentifier = "---Int64I---";
|
||||
|
||||
FString floatDataIdentifier = "---FloatI---";
|
||||
|
||||
FString nameDataIdentifier = "---NameI---";
|
||||
|
||||
FString stringDataIdentifier = "---StringI---";
|
||||
|
||||
FString textDataIdentifier = "---TextI---";
|
||||
|
||||
FString vectorDataIdentifier = "---VectorI---";
|
||||
|
||||
FString rotatorDataIdentifier = "---RotatorI---";
|
||||
|
||||
FString transformDataIdentifier = "---TransformI---";
|
||||
|
||||
FString DataIdentifierSeperator = "---IdentifierSep---";
|
||||
|
||||
FString transformDataSeperator = "---TransformDataSep---";
|
||||
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DataObject")
|
||||
TArray<FReplayBoolData> boolData;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DataObject")
|
||||
TArray<FReplayByteData> byteData;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DataObject")
|
||||
TArray<FReplayIntData> intData;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DataObject")
|
||||
TArray<FReplayInt64Data> int64Data;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DataObject")
|
||||
TArray<FReplayFloatData> floatData;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DataObject")
|
||||
TArray<FReplayNameData> nameData;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DataObject")
|
||||
TArray<FReplayStringData> stringData;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DataObject")
|
||||
TArray<FReplayTextData> textData;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DataObject")
|
||||
TArray<FReplayVectorData> vectorData;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DataObject")
|
||||
TArray<FReplayRotatorData> rotatorData;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DataObject")
|
||||
TArray<FReplayTransformData> transformData;
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "DataObject")
|
||||
int DoesBooleanDataExist (FString Name);
|
||||
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "DataObject")
|
||||
int DoesByteDataExist (FString Name);
|
||||
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "DataObject")
|
||||
int DoesIntegerDataExist (FString Name);
|
||||
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "DataObject")
|
||||
int DoesInteger64DataExist (FString Name);
|
||||
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "DataObject")
|
||||
int DoesFloatDataExist (FString Name);
|
||||
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "DataObject")
|
||||
int DoesNameDataExist (FString Name);
|
||||
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "DataObject")
|
||||
int DoesStringDataExist (FString Name);
|
||||
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "DataObject")
|
||||
int DoesTextDataExist (FString Name);
|
||||
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "DataObject")
|
||||
int DoesVectorDataExist (FString Name);
|
||||
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "DataObject")
|
||||
int DoesRotatorDataExist (FString Name);
|
||||
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "DataObject")
|
||||
int DoesTransformDataExist (FString Name);
|
||||
|
||||
|
||||
// Adds or updates data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void AddBooleanData(FString Name,bool Data);
|
||||
// Adds or updates data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void AddByteData(FString Name,TArray<uint8> Data);
|
||||
// Adds or updates data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void AddIntegerData(FString Name,int Data);
|
||||
// Adds or updates data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void AddInteger64Data(FString Name,int64 Data);
|
||||
// Adds or updates data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void AddFloatData(FString Name,float Data);
|
||||
// Adds or updates data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void AddNameData(FString Name,FName Data);
|
||||
// Adds or updates data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void AddStringData(FString Name,FString Data);
|
||||
// Adds or updates data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void AddTextData(FString Name,FText Data);
|
||||
// Adds or updates data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void AddVectorData(FString Name,FVector Data);
|
||||
// Adds or updates data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void AddRotatorData(FString Name,FRotator Data);
|
||||
// Adds or updates data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void AddTransformData(FString Name,FTransform Data);
|
||||
|
||||
// Removes data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void RemoveBooleanData(FString Name);
|
||||
// Removes data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void RemoveByteData(FString Name);
|
||||
// Removes data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void RemoveIntegerData(FString Name);
|
||||
// Removes data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void RemoveInteger64Data(FString Name);
|
||||
// Removes data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void RemoveFloatData(FString Name);
|
||||
// Removes data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void RemoveNameData(FString Name);
|
||||
// Removes data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void RemoveStringData(FString Name);
|
||||
// Removes data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void RemoveTextData(FString Name);
|
||||
// Removes data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void RemoveVectorData(FString Name);
|
||||
// Removes data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void RemoveRotatorData(FString Name);
|
||||
// Removes data of the specified type (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
void RemoveTransformData(FString Name);
|
||||
|
||||
// Returns the stored value if it exists (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
bool GetBooleanData(FString Name);
|
||||
// Returns the stored value if it exists (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
TArray<uint8> GetByteData(FString Name);
|
||||
// Returns the stored value if it exists (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
int GetIntegerData(FString Name);
|
||||
// Returns the stored value if it exists (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
int64 GetInteger64Data(FString Name);
|
||||
// Returns the stored value if it exists (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
float GetFloatData(FString Name);
|
||||
// Returns the stored value if it exists (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
FName GetNameData(FString Name);
|
||||
// Returns the stored value if it exists (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
FString GetStringData(FString Name);
|
||||
// Returns the stored value if it exists (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
FText GetTextData(FString Name);
|
||||
// Returns the stored value if it exists (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
FVector GetVectorData(FString Name);
|
||||
// Returns the stored value if it exists (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
FRotator GetRotatorData(FString Name);
|
||||
// Returns the stored value if it exists (Case Sensitive)
|
||||
UFUNCTION(BlueprintCallable, Category = "DataObject")
|
||||
FTransform GetTransformData(FString Name);
|
||||
|
||||
/*Used Internaly to Create/Save meta data for a replay*/
|
||||
UFUNCTION(Category = "DataObject")
|
||||
FString SaveReplayMetaDataToString();
|
||||
|
||||
/*Used Internaly to Load a meta data for a replay*/
|
||||
UFUNCTION(Category = "DataObject")
|
||||
bool LoadReplayMetaDataFromString(FString StringDataToParse);
|
||||
|
||||
|
||||
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ReplayStructs.h"
|
||||
#include "ReplayDelegates.generated.h"
|
||||
|
||||
class UReplayObject;
|
||||
class APawn;
|
||||
|
||||
UDELEGATE()
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestEventsComplete,const TArray<FReplayEvent>&, Events);
|
||||
|
||||
UDELEGATE()
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRenameReplayComplete, bool, bWasSuccessful);
|
||||
|
||||
UDELEGATE()
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnGetReplaysComplete,const TArray<UReplayObject *> &, Replays);
|
||||
|
||||
UDELEGATE()
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnDeleteComplete, bool, bWasSuccessful);
|
||||
|
||||
UDELEGATE()
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnGotoTimeComplete, const bool ,bWasSuccessful);
|
||||
|
||||
UDELEGATE()
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnReplayComplete);
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
#include "ReplayDelegates.h"
|
||||
#include "ReplayStructs.h"
|
||||
#include "ReplayObject.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
class UReplayDataObject;
|
||||
|
||||
UCLASS(BlueprintType, Blueprintable)
|
||||
class REPLAYSYSTEM_API UReplayObject : public UObject
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY()
|
||||
UWorld* World = nullptr;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = Replay)
|
||||
FReplayInfo ReplayInfo;
|
||||
|
||||
|
||||
// called once the events have been gotten
|
||||
UPROPERTY(BlueprintAssignable, Category = "Replay|Events")
|
||||
FOnRequestEventsComplete OnRequestEventsComplete;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the events of a loaded replay
|
||||
* @param Group
|
||||
* @param UserIndex
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Replay")
|
||||
void RequestEvents(FString Group,int UserIndex);
|
||||
|
||||
FEnumerateEventsCallback EnumerateEventsDel;
|
||||
|
||||
void OnEnumerateEventsComplete(const FEnumerateEventsResult& Results);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "ReplayPlayerController.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class REPLAYSYSTEM_API AReplayPlayerController : public APlayerController
|
||||
{
|
||||
GENERATED_BODY()
|
||||
AReplayPlayerController();
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintImplementableEvent,Category="Replay")
|
||||
void OnGoToTime(float currentTime);
|
||||
|
||||
/**
|
||||
* true means paused
|
||||
* @param PauseState
|
||||
*/
|
||||
UFUNCTION(BlueprintImplementableEvent,Category="Replay")
|
||||
void OnTogglePause(bool PauseState);
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent,Category="Replay")
|
||||
void OnSpectateActor(AActor* Actor);
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent,Category="Replay")
|
||||
void OnStopSpectateActor();
|
||||
|
||||
|
||||
|
||||
bool bIsSpectating = false;
|
||||
};
|
||||
@@ -0,0 +1,371 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Camera/PlayerCameraManager.h"
|
||||
#include "Curves/CurveVector.h"
|
||||
#include "ReplayStructs.generated.h"
|
||||
|
||||
|
||||
class UReplayDataObject;
|
||||
class UCurveVector;
|
||||
class FNetworkGUID;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayInfo
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
//The UI name of the replay
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString FriendlyName;
|
||||
//The actual name of the replay on disk
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString ActualName;
|
||||
//The date the replay was recorded
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FDateTime RecordDate;
|
||||
//The length of the replay in milliseconds
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
int32 LengthInMS = 0;
|
||||
//The size of the replay in Mb
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
float SizeInMb = 0.0f;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FBlendSettings
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
//The time taken to blend
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
float BlendTime = 0.2f;
|
||||
//Cubic, Linear etc functions for blending
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
TEnumAsByte<EViewTargetBlendFunction> BlendFunction = EViewTargetBlendFunction::VTBlend_Linear;
|
||||
///Exponent used by certain blend functions to control the blend
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
float BlendExponent = 0;
|
||||
//If true, lock outgoing view target to last frame's camera position for the remainder of the blend
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
bool bLockOutgoing = false;
|
||||
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayEvent
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
//The Event ID
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString EventID;
|
||||
//The group this event belongs to
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Group;
|
||||
// The time the event was added at in milliseconds
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
int32 TimeInMs = 0;
|
||||
//The event data
|
||||
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = Replay)
|
||||
UReplayDataObject* Data=nullptr;
|
||||
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayBoolData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
bool Value = true;
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayBoolData& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayBoolData& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayByteData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
TArray<uint8> Value;
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayByteData& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayByteData& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayIntData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
int Value=0;
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayIntData& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayIntData& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayInt64Data
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
int64 Value = 0;
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayInt64Data& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayInt64Data& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayFloatData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
float Value = 0.0f;
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayFloatData& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayFloatData& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayNameData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FName Value;
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayNameData& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayNameData& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayStringData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Value;
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayStringData& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayStringData& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayTextData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FText Value;
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayTextData& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayTextData& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayVectorData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FVector Value = FVector(0.0f, 0.0f, 0.0f);
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayVectorData& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayVectorData& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayRotatorData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FRotator Value = FRotator(0.0f, 0.0f, 0.0f);
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayRotatorData& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayRotatorData& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayTransformData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FTransform Value;
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayTransformData& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayTransformData& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FReplayObjectData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Replay)
|
||||
UObject* Value=nullptr;
|
||||
|
||||
FORCEINLINE bool operator<(const FReplayObjectData& Other) const
|
||||
{
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FReplayObjectData& Other) const
|
||||
{
|
||||
return Name == Other.Name;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogReplaySystem, Log, All);
|
||||
|
||||
|
||||
class FReplaySystemModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
@@ -0,0 +1,308 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
#include "ReplayStructs.h"
|
||||
#include "ReplaySystemBPLibrary.generated.h"
|
||||
|
||||
/*
|
||||
* Function library class.
|
||||
* Each function in it is expected to be static and represents blueprint node that can be called in any blueprint.
|
||||
*
|
||||
* When declaring function you can define metadata for the node. Key function specifiers will be BlueprintPure and BlueprintCallable.
|
||||
* BlueprintPure - means the function does not affect the owning object in any way and thus creates a node without Exec pins.
|
||||
* BlueprintCallable - makes a function which can be executed in Blueprints - Thus it has Exec pins.
|
||||
* DisplayName - full name of the node, shown when you mouse over the node and in the blueprint drop down menu.
|
||||
* Its lets you name the node using characters not allowed in C++ function names.
|
||||
* CompactNodeTitle - the word(s) that appear on the node.
|
||||
* Keywords - the list of keywords that helps you to find node when you search for it using Blueprint drop-down menu.
|
||||
* Good example is "Print String" node which you can find also by using keyword "log".
|
||||
* Category - the category your node will be under in the Blueprint drop-down menu.
|
||||
*
|
||||
* For more info on custom blueprint nodes visit documentation:
|
||||
* https://wiki.unrealengine.com/Custom_Blueprint_Node_Creation
|
||||
*/
|
||||
|
||||
class UGoToTimeObject;
|
||||
class UDeleteReplayObject;
|
||||
class UGetSavedReplaysObject;
|
||||
class URenameReplayObject;
|
||||
class UReplayDataObject;
|
||||
class UReplayObject;
|
||||
class URequestEventsObject;
|
||||
class UInstantReplayObject;
|
||||
|
||||
UCLASS()
|
||||
class UReplaySystemBPLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Sets the path for all replays (Does not copy existing replays over)
|
||||
* @param WorldContextObject
|
||||
* @param Path New path
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static void SetReplaySavePath(UObject* WorldContextObject, const FString& Path);
|
||||
|
||||
/**
|
||||
* Gets the current path where replays are stored
|
||||
* @param WorldContextObject
|
||||
* @return Path
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure,Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static FString GetReplaySavePath(UObject* WorldContextObject);
|
||||
|
||||
|
||||
/**
|
||||
* Starts recording a replay
|
||||
* @param WorldContextObject
|
||||
* @param ReplayName The name to save the replay as on disk (Used internally)
|
||||
* @param ReplayFriendlyName The Ui friendly name of the replay (Used by you or users)
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem|Recording", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static void RecordReplay(UObject* WorldContextObject, const FString& ReplayName,
|
||||
const FString& ReplayFriendlyName);
|
||||
|
||||
/**
|
||||
* Stop recording a replay
|
||||
* @param WorldContextObject
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem|Recording", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static void StopRecordingReplay(UObject* WorldContextObject);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Finds out if a replay is being recorded
|
||||
* @param WorldContextObject
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static bool IsRecordingReplay(UObject* WorldContextObject);
|
||||
|
||||
/**
|
||||
* Delete a replay
|
||||
* @param WorldContextObject
|
||||
* @param ReplayName The name the replay is saved as on disk
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static UDeleteReplayObject* DeleteReplay(UObject* WorldContextObject, const FString& ReplayName);
|
||||
|
||||
/**
|
||||
* Changes the name a replay is saved as on the disk
|
||||
* @param WorldContextObject
|
||||
* @param ReplayName The current name on disk of this replay
|
||||
* @param NewReplayName New name to save as on disk
|
||||
* @param UserIndex
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static URenameReplayObject* RenameReplay(UObject* WorldContextObject, const FString& ReplayName, const FString& NewReplayName, const int32 UserIndex);
|
||||
|
||||
/**
|
||||
* Changes the friendly name of a replay
|
||||
* @param WorldContextObject
|
||||
* @param ReplayName The current name on disk of this replay
|
||||
* @param NewFriendlyReplayName New friendly to give it
|
||||
* @param UserIndex
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static URenameReplayObject* RenameReplayFriendly(UObject* WorldContextObject, const FString& ReplayName, const FString& NewFriendlyReplayName, const int32 UserIndex);
|
||||
|
||||
/**
|
||||
* Get all the saved replays
|
||||
* @param WorldContextObject
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static UGetSavedReplaysObject* GetSavedReplays(UObject* WorldContextObject);
|
||||
|
||||
/**
|
||||
* Play a recorded replay
|
||||
* @param WorldContextObject
|
||||
* @param ReplayName
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem|Playback", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static bool PlayRecordedReplay(UObject* WorldContextObject, const FString& ReplayName);
|
||||
|
||||
/**
|
||||
* Restart the currently playing replay
|
||||
* @param WorldContextObject
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem|Playback", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static UGoToTimeObject* RestartReplayPlayback(UObject* WorldContextObject);
|
||||
|
||||
/**
|
||||
* Goto a specific time in the replay
|
||||
* @param WorldContextObject
|
||||
* @param TimeToGoTo Time in seconds to goto
|
||||
* @param bRetainCurrentPauseState Use this on a need basis as it can cause some physics issues
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem|Playback", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static UGoToTimeObject* GoToSpecificTime(UObject* WorldContextObject, float TimeToGoTo,
|
||||
bool bRetainCurrentPauseState);
|
||||
|
||||
|
||||
/**
|
||||
* Pause the replay playback
|
||||
* @param WorldContextObject
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem|Playback", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static void PausePlayback(UObject* WorldContextObject);
|
||||
|
||||
/**
|
||||
* Resume the replay playback
|
||||
* @param WorldContextObject
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem|Playback", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static void ResumePlayback(UObject* WorldContextObject);
|
||||
|
||||
/**
|
||||
* Sets the Playback speed of the replay
|
||||
* @param WorldContextObject Set the playback speed of the replay
|
||||
* @param Speed Like time dilation 0.1,1,10
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem|Playback", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static void SetPlaybackSpeed(UObject* WorldContextObject, float Speed);
|
||||
|
||||
|
||||
/**
|
||||
* Get the playback speed of the replay
|
||||
* @param WorldContextObject
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "ReplaySystem|Playback", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static float GetPlaybackSpeed(UObject* WorldContextObject);
|
||||
|
||||
|
||||
/**
|
||||
* Get the current time in seconds of the replay
|
||||
* @param WorldContextObject
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "ReplaySystem|Playback", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static float GetCurrentReplayTime(UObject* WorldContextObject);
|
||||
|
||||
|
||||
/**
|
||||
* Get the total length in seconds of the replay currently playing or being recorded
|
||||
* @param WorldContextObject
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "ReplaySystem|Playback", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static float GetReplayLength(UObject* WorldContextObject);
|
||||
|
||||
|
||||
/**
|
||||
* returns true if a replay is being played
|
||||
* @param WorldContextObject
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static bool IsPlayingReplay(UObject* WorldContextObject);
|
||||
|
||||
/**
|
||||
* Returns true of the replay has been paused
|
||||
* @param WorldContextObject
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static bool IsReplayPlaybackPaused(UObject* WorldContextObject);
|
||||
|
||||
/**
|
||||
* Gets the name on disk/memory of the replay currently playing or being recorded
|
||||
* @param WorldContextObject
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static FString GetActiveReplayName(UObject* WorldContextObject);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds or Updates said event in the replay currently being recorded
|
||||
* @param WorldContextObject
|
||||
* @param EventName The name of the event
|
||||
* @param Group The group this event belongs to
|
||||
* @param DataObject optional object containing extra data
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static bool AddEventToActiveReplay(UObject* WorldContextObject,const FString& EventName, const FString& Group, UReplayDataObject* DataObject);
|
||||
|
||||
/**
|
||||
* Gets the Events of the replay currently playing
|
||||
* @param WorldContextObject
|
||||
* @param Group The group name
|
||||
* @param UserIndex
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static URequestEventsObject* RequestActiveReplayEvents(UObject* WorldContextObject,FString Group,int UserIndex);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a data object for storing event meta data for a replay
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "ReplaySystem")
|
||||
static UReplayDataObject* CreateReplayDataObject();
|
||||
|
||||
static UReplayDataObject* LoadEventFromByteData(TArray<uint8> Bytes);
|
||||
|
||||
/**
|
||||
* Helper function to convert milliseconds to seconds
|
||||
* @param MS
|
||||
* @return
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable,BlueprintPure, Category = "ReplaySystem|Utilities")
|
||||
static float MsToSeconds(const int32 MS);
|
||||
|
||||
/**
|
||||
* Just sets the view target of the controller to the specified actor
|
||||
* @param WorldContextObject
|
||||
* @param Actor The pawn to spectate
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable,Category= "ReplaySystem",meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static void SpectateActor(UObject* WorldContextObject, AActor* Actor, FBlendSettings BlendSettings);
|
||||
|
||||
/**
|
||||
* Just sets the view target of the controller back to the possessed pawn
|
||||
* @param WorldContextObject
|
||||
* @param BlendSettings
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable,Category= "ReplaySystem",meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static void StopSpectating(UObject* WorldContextObject,FBlendSettings BlendSettings);
|
||||
|
||||
UFUNCTION(Category= "ReplaySystem",meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static UDemoNetDriver* GetDemoDriver(const UObject* WorldContextObject);
|
||||
|
||||
/**
|
||||
*Set the maximum number of frames recorded per second by the replay
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable,Category= "ReplaySystem",meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"))
|
||||
static void SetMaxRecordHz(UObject* WorldContextObject,float Hz = 8.0f);
|
||||
|
||||
|
||||
/**
|
||||
* Get the maximum number of frames recorded per second by the replay
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable,Category= "ReplaySystem")
|
||||
static float GetMaxRecordHz();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "NetworkReplayStreaming.h"
|
||||
#include "ReplayDelegates.h"
|
||||
#include "RequestEventsObject.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
UCLASS(BlueprintType, Blueprintable)
|
||||
class REPLAYSYSTEM_API URequestEventsObject : public UObject
|
||||
{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Replay|Events")
|
||||
FOnRequestEventsComplete OnRequestEventsComplete;
|
||||
|
||||
void RequestEvents(FString ReplayName,FString Group,int UserIndex);
|
||||
|
||||
FEnumerateEventsCallback EnumerateEventsDel;
|
||||
|
||||
void OnEnumerateEventsComplete(const FEnumerateEventsResult& Results);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright 2020-Present Oyintare Ebelo. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class ReplaySystem : ModuleRules
|
||||
{
|
||||
public ReplaySystem(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add other private include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"NetworkReplayStreaming",
|
||||
"Json",
|
||||
"JsonUtilities",
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[] {
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user