Files
UnrealEngine/Engine/Plugins/Animation/GameplayInsights/Source/RewindDebugger/Private/RewindDebugger.h
2025-05-18 13:04:45 +08:00

292 lines
7.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_7
#include "CoreMinimal.h"
#include "UObject/WeakObjectPtr.h"
#endif // UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_7
#include "BindableProperty.h"
#include "Containers/Ticker.h"
#include "IRewindDebugger.h"
#include "IRewindDebuggerTrackCreator.h"
#include "RewindDebuggerTrack.h"
namespace TraceServices
{
class IAnalysisSession;
}
class FMenuBuilder;
class IGameplayProvider;
class SDockTab;
class SWidget;
class USkeletalMeshComponent;
struct FObjectInfo;
/**
* Singleton class that handles the logic for the Rewind Debugger:
* - Playback/Scrubbing state
* - Start/Stop recording
* - Keeping track of the current Debug Target object, and outputting a list of its sub objects/elements for the UI
*/
class FRewindDebugger : public IRewindDebugger
{
public:
FRewindDebugger();
virtual ~FRewindDebugger();
//~ IRewindDebugger interface
virtual double CurrentTraceTime() const override
{
return TraceTime.Get();
}
virtual double GetScrubTime() const override
{
return CurrentScrubTime;
}
virtual const TRange<double>& GetCurrentTraceRange() const override
{
return CurrentTraceRange;
}
virtual const TRange<double>& GetCurrentViewRange() const override
{
return CurrentViewRange;
}
virtual const TraceServices::IAnalysisSession* GetAnalysisSession() const override;
virtual uint64 GetTargetActorId() const override;
virtual bool GetTargetActorPosition(FVector& OutPosition) const override;
virtual UWorld* GetWorldToVisualize() const override;
virtual bool IsRecording() const override;
virtual bool IsPIESimulating() const override
{
return bPIESimulating;
}
virtual bool IsTraceFileLoaded() const override;
virtual double GetRecordingDuration() const override
{
return RecordingDuration.Get();
}
virtual TSharedPtr<FDebugObjectInfo> GetSelectedObject() const override;
virtual TSharedPtr<RewindDebugger::FRewindDebuggerTrack> GetSelectedTrack() const override;
virtual TArray<TSharedPtr<FDebugObjectInfo>>& GetDebuggedObjects() override;
virtual bool IsObjectCurrentlyDebugged(uint64 ObjectId) const override;
virtual bool ShouldDisplayWorld(uint64 WorldId) override
{
return DisplayWorldId == WorldId;
}
void OnConnection();
void GetTargetObjectIds(TArray<RewindDebugger::FObjectId>& OutTargetObjectIds) const;
TArray<TSharedPtr<RewindDebugger::FRewindDebuggerTrack>>& GetTracks()
{
return DebugTracks;
}
/** create singleton instance */
static void Initialize();
/** destroy singleton instance */
static void Shutdown();
/** get singleton instance */
static FRewindDebugger* Instance()
{
return static_cast<FRewindDebugger*>(InternalInstance);
}
/** Start a new Recording: Start tracing Object + Animation data, increment the current recording index, and reset the recording elapsed time to 0 */
void StartRecording() const;
void OnClearRecording();
void OnRecordingStarted();
void OnRecordingStopped();
bool CanStartRecording() const
{
return !IsRecording() && bPIESimulating;
}
bool CanOpenTrace() const;
void OpenTrace(const FString& FilePath);
void OpenTrace();
void AttachToSession();
bool CanClearTrace() const;
void ClearTrace();
bool CanSaveTrace() const;
void SaveTrace(FString FileName);
void SaveTrace();
bool ShouldAutoRecordOnPIE() const;
void SetShouldAutoRecordOnPIE(bool InValue);
bool ShouldAutoEject() const;
void SetShouldAutoEject(bool InValue);
/** Stop recording: Stop tracing Object + Animation Data. */
void StopRecording();
bool CanStopRecording() const
{
return IsRecording();
}
//~ VCR controls
bool CanPause() const;
void Pause();
bool CanPlay() const;
void Play();
bool IsPlaying() const;
bool CanPlayReverse() const;
void PlayReverse();
void ScrubToStart();
void ScrubToEnd();
void Step(int32 InNumberOfFrames);
void StepForward();
void StepBackward();
bool CanScrub() const;
void ScrubToTime(double ScrubTime, bool bIsScrubbing);
/** Tick function: While recording, update recording duration. While paused, and we have recorded data, update skinned mesh poses for the current frame, and handle playback. */
void Tick(float DeltaTime);
/** update the list of tracks for the currently selected debug target */
void RefreshDebugTracks();
void SetCurrentViewRange(const TRange<double>& Range);
DECLARE_DELEGATE(FOnTrackListChanged)
void SetTrackListChangedDelegate(const FOnTrackListChanged& InTrackListChangedDelegate);
void TrackDoubleClicked(TSharedPtr<RewindDebugger::FRewindDebuggerTrack> InSelectedTrack);
void TrackSelectionChanged(TSharedPtr<RewindDebugger::FRewindDebuggerTrack> InSelectedTrack);
TSharedPtr<SWidget> BuildTrackContextMenu() const;
void UpdateDetailsPanel(TSharedRef<SDockTab> DetailsTab);
static void RegisterTrackContextMenu();
static void MakeOtherWorldsMenu(class UToolMenu* Menu);
void SetDisplayWorld(uint64 WorldId);
static void MakeWorldsMenu(class UToolMenu* Menu);
static void RegisterToolBar();
DECLARE_DELEGATE_OneParam(FOnTrackCursor, bool)
void SetTrackCursorDelegate(const FOnTrackCursor& InTrackCursorDelegate);
TBindableProperty<double>* GetTraceTimeProperty()
{
return &TraceTime;
}
TBindableProperty<double>* GetRecordingDurationProperty()
{
return &RecordingDuration;
}
TBindableProperty<FString, BindingType_Out>* GetDebugTargetActorProperty()
{
return &SelectedObjectName;
}
virtual void OpenDetailsPanel() override;
void SetIsDetailsPanelOpen(bool bIsOpen)
{
bIsDetailsPanelOpen = bIsOpen;
}
virtual const FObjectInfo* FindOwningActorInfo(const IGameplayProvider* GameplayProvider, uint64 ObjectId) const override;
TArrayView<RewindDebugger::FRewindDebuggerTrackType> GetTrackTypes()
{
return TrackTypes;
};
private:
static void RefreshDebuggedObjects(TArray<TSharedPtr<RewindDebugger::FRewindDebuggerTrack>>& InTracks, TArray<TSharedPtr<FDebugObjectInfo>>& OutObjects);
void OnPIEStarted(bool bSimulating);
void OnPIEPaused(bool bSimulating);
void OnPIEResumed(bool bSimulating);
void OnPIEStopped(bool bSimulating);
void OnPIESingleStepped(bool bSimulating);
void SetCurrentScrubTime(double Time);
TBindableProperty<double> TraceTime;
TBindableProperty<double> RecordingDuration;
TBindableProperty<FString, BindingType_Out> SelectedObjectName;
enum class EControlState : int8
{
Play,
PlayReverse,
Pause
};
EControlState ControlState = EControlState::Pause;
FOnTrackListChanged TrackListChangedDelegate;
FOnTrackCursor TrackCursorDelegate;
bool bQueueStartRecording = false;
bool bTraceJustConnected = false;
bool bPIEStarted = false;
bool bPIESimulating = false;
bool bRecording = false;
double PreviousTraceTime = -1;
double CurrentScrubTime = 0;
TRange<double> CurrentViewRange{ 0, 10 };
TRange<double> CurrentTraceRange{ 0, 0 };
uint16 RecordingIndex = 0;
struct FScrubTimeInformation
{
/** Profiling/Tracing time */
double ProfileTime = 0;
/** Scrub Frame Index */
int64 FrameIndex = 0;
};
FScrubTimeInformation ScrubTimeInformation;
FScrubTimeInformation LowerBoundViewTimeInformation;
FScrubTimeInformation UpperBoundViewTimeInformation;
static void GetScrubTimeInformation(double InDebugTime, FScrubTimeInformation& InOutTimeInformation, uint16 InRecordingIndex, const TraceServices::IAnalysisSession* AnalysisSession);
TArray<TSharedPtr<FDebugObjectInfo>> DebuggedObjects;
mutable TSharedPtr<FDebugObjectInfo> SelectedObject;
TArray<TSharedPtr<RewindDebugger::FRewindDebuggerTrack>> DebugTracks;
TSharedPtr<RewindDebugger::FRewindDebuggerTrack> SelectedTrack;
TArray<RewindDebugger::FObjectId> CandidateIds;
mutable class IUnrealInsightsModule* UnrealInsightsModule = nullptr;
FTSTicker::FDelegateHandle TickerHandle;
bool bTargetActorPositionValid = false;
FVector TargetActorPosition;
uint64 TargetActorMeshId = 0;
uint64 TargetActorIdForMesh = 0;
TArray<RewindDebugger::FRewindDebuggerTrackType> TrackTypes;
bool bIsDetailsPanelOpen = true;
uint64 DisplayWorldId = 0;
bool bDisplayWorldIdValid = false;
};