// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_7 #include "CoreMinimal.h" #endif // UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_7 #include "IRewindDebugger.h" #include "Widgets/SWidget.h" #include "Textures/SlateIcon.h" namespace TraceServices { class IAnalysisSession; } struct FToolMenuSection; namespace RewindDebugger { enum class ETrackHiddenFlags : uint8 { None = 0, HiddenByCode = 1 << 0, HiddenByUI = 1 << 1, AnyFlag = 0xFF }; ENUM_CLASS_FLAGS(ETrackHiddenFlags); enum class EStepMode : uint8 { Forward, Backward }; class FRewindDebuggerTrack { public: /** Result returned from a visitor functor indicating to continue or to quit early */ enum class EVisitResult : uint8 { /** Stop iterating through tracks and early exit */ Break, /** Continue to iterate through all tracks */ Continue }; FRewindDebuggerTrack() { } virtual ~FRewindDebuggerTrack() { } bool GetIsExpanded() const { return bExpanded; } void SetIsExpanded(const bool bIsExpanded) { bExpanded = bIsExpanded; } bool GetIsSelected() const { return bSelected; } void SetIsSelected(const bool bIsSelected) { bSelected = bIsSelected; } bool GetIsTreeHovered() const { return bTreeHovered; } void SetIsTreeHovered(const bool bIsHovered) { bTreeHovered = bIsHovered; } bool GetIsTrackHovered() const { return bTrackHovered; } void SetIsTrackHovered(const bool bIsHovered) { bTrackHovered = bIsHovered; } bool GetIsHovered() const { return bTrackHovered || bTreeHovered; } /** Update should do work to compute children etc. for the current time range. Return true if children have changed. */ bool Update() { return UpdateInternal(); } /** Get a widget to show in the timeline view for this track */ TSharedPtr GetTimelineView() { return GetTimelineViewInternal(); } /** Get a widget to show in the details tab, when this track is selected */ TSharedPtr GetDetailsView() { return GetDetailsViewInternal(); } /** unique name for track (must match creator name if track is created by an IRewindDebuggerViewCreator) */ FName GetName() const { return GetNameInternal(); } /** icon to display in the tree view */ FSlateIcon GetIcon() { return GetIconInternal(); } /** display name for track in Tree View */ FText GetDisplayName() const { return GetDisplayNameInternal(); } /** insights main UObject id for an object associated with this track */ uint64 GetUObjectId() const { return GetObjectIdInternal(); } UE_DEPRECATED(5.7, "Use GetUObjectID instead.") uint64 GetObjectId() const { return GetUObjectId(); } /** insights object id for an object associated with this track */ FObjectId GetAssociatedObjectId() const { return FObjectId(GetObjectIdInternal()); } /** tracks can customize the tooltip for the step command */ FText GetStepCommandTooltip(const EStepMode StepMode) const { return GetStepCommandTooltipInternal(StepMode); } /** tracks can return a different time for the step action; default the main recording frame time is used */ TOptional GetStepFrameTime(const EStepMode StepMode, const double CurrentScrubTime) const { return GetStepFrameTimeInternal(StepMode, CurrentScrubTime); } /** * Visit the current track along with its child hierarchy recursively * to call provided function on each track until a call returns EVisitResult::Break */ static EVisitResult Visit(TSharedPtr Track, TFunction SubTrack)> IteratorFunction) { if (IteratorFunction(Track) == EVisitResult::Break) { return EVisitResult::Break; } return Track->Visit(IteratorFunction); } private: /** * Visit the child hierarchy recursively to call provided function on each track until a call returns EVisitResult::Break */ EVisitResult Visit(TFunction SubTrack)> IteratorFunction) { // GetChildrenInternal can provide children using the returned array view, // the output parameter, or both. TArray> Children; for (const TSharedPtr& Track : GetChildrenInternal(Children)) { if (Visit(Track, IteratorFunction) == EVisitResult::Break) { return EVisitResult::Break; } } for (const TSharedPtr& Track : Children) { if (Visit(Track, IteratorFunction) == EVisitResult::Break) { return EVisitResult::Break; } } return EVisitResult::Continue; } public: /** iterates over all sub-tracks of this track and call Iterator function */ void IterateSubTracks(TFunction SubTrack)> IteratorFunction) const { // GetChildrenInternal can provide children using the returned array view, // the output parameter, or both. TArray> Children; for (const TSharedPtr& Track : GetChildrenInternal(Children)) { IteratorFunction(Track); } for (const TSharedPtr& Track : Children) { IteratorFunction(Track); } } /** returns true for tracks that contain debug data (used for filtering out parts of the hierarchy with no useful information in them) */ bool HasDebugData() const { return HasDebugDataInternal(); } /** Called when a track is double-clicked. Returns true if the track handled the double click */ bool HandleDoubleClick() { return HandleDoubleClickInternal(); } void SetHiddenFlag(const ETrackHiddenFlags Flag) { EnumAddFlags(HiddenFlags, Flag); } void UnsetHiddenFlag(const ETrackHiddenFlags Flag) { EnumRemoveFlags(HiddenFlags, Flag); } bool HasAnyFlags(const ETrackHiddenFlags Flags) const { return EnumHasAnyFlags(HiddenFlags, Flags); } bool IsVisible() const { return HiddenFlags == ETrackHiddenFlags::None; } UE_DEPRECATED(5.7, "Use SetHiddenFlag/UnsetHiddenFlag instead.") void SetIsVisible(const bool bInIsVisible) { if (bInIsVisible) { UnsetHiddenFlag(ETrackHiddenFlags::HiddenByCode); } else { SetHiddenFlag(ETrackHiddenFlags::HiddenByCode); } } /** Called to generate context menu for the current selected track */ virtual void BuildContextMenu(FToolMenuSection& InMenuSection) {}; private: virtual bool UpdateInternal() { return false; } virtual TSharedPtr GetTimelineViewInternal() { return TSharedPtr(); } virtual TSharedPtr GetDetailsViewInternal() { return TSharedPtr(); } virtual FSlateIcon GetIconInternal() { return FSlateIcon(); } virtual FName GetNameInternal() const { return ""; } virtual FText GetDisplayNameInternal() const { return FText(); } virtual uint64 GetObjectIdInternal() const { return {}; } virtual bool HasDebugDataInternal() const { return true; } virtual FText GetStepCommandTooltipInternal(EStepMode) const { return {}; } virtual TOptional GetStepFrameTimeInternal(EStepMode, double) const { return {}; } UE_DEPRECATED(5.7, "Implement and use GetChildrenInternal instead.") virtual void IterateSubTracksInternal(TFunction SubTrack)> IteratorFunction) final { } /** * Method that derive classes can override to provide children tracks for methods like Visit and IterateSubTracks * Caller of this method is expected to handle both the return value and the output parameter. * @param OutTracks Optional parameter that can be used when the derived class can't provide a const view of the children * @return An array view on the sub tracks */ virtual TConstArrayView> GetChildrenInternal(TArray>& OutTracks) const { return {}; } virtual bool HandleDoubleClickInternal() { IRewindDebugger::Instance()->OpenDetailsPanel(); return true; }; ETrackHiddenFlags HiddenFlags = ETrackHiddenFlags::None; bool bSelected : 1 = false; bool bTrackHovered : 1 = false; bool bTreeHovered : 1 = false; bool bExpanded : 1 = true; }; } // namespace RewindDebugger