502 lines
17 KiB
C++
502 lines
17 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "TimeRulerTrack.h"
|
|
|
|
#include "Fonts/FontMeasure.h"
|
|
#include "Fonts/SlateFontInfo.h"
|
|
#include "Framework/Application/SlateApplication.h"
|
|
#include "Framework/MultiBox/MultiBoxBuilder.h"
|
|
#include "Rendering/DrawElements.h"
|
|
#include "Styling/AppStyle.h"
|
|
|
|
// TraceInsightsCore
|
|
#include "InsightsCore/Common/PaintUtils.h"
|
|
#include "InsightsCore/Common/TimeUtils.h"
|
|
|
|
// TraceInsights
|
|
#include "Insights/InsightsStyle.h"
|
|
#include "Insights/TimingProfiler/TimingProfilerManager.h"
|
|
#include "Insights/TimingProfiler/ViewModels/TimeMarker.h"
|
|
#include "Insights/TimingProfiler/Widgets/STimingProfilerWindow.h"
|
|
#include "Insights/ViewModels/DrawHelpers.h"
|
|
#include "Insights/ViewModels/TimingTrackViewport.h"
|
|
#include "Insights/Widgets/SLogView.h"
|
|
|
|
#include <limits>
|
|
|
|
#define LOCTEXT_NAMESPACE "UE::Insights::TimingProfiler::FTimeRulerTrack"
|
|
|
|
namespace UE::Insights::TimingProfiler
|
|
{
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
INSIGHTS_IMPLEMENT_RTTI(FTimeRulerTrack)
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
FTimeRulerTrack::FTimeRulerTrack()
|
|
: FBaseTimingTrack(TEXT("Time Ruler"))
|
|
, WhiteBrush(FAppStyle::Get().GetBrush("WhiteBrush"))
|
|
, Font(FAppStyle::Get().GetFontStyle("SmallFont"))
|
|
, CrtMousePosTime(0.0)
|
|
, CrtMousePosTextWidth(0.0f)
|
|
{
|
|
SetValidLocations(ETimingTrackLocation::TopDocked);
|
|
SetOrder(FTimingTrackOrder::TimeRuler);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
FTimeRulerTrack::~FTimeRulerTrack()
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::Reset()
|
|
{
|
|
FBaseTimingTrack::Reset();
|
|
|
|
bIsSelecting = false;
|
|
SelectionStartTime = 0.0;
|
|
SelectionEndTime = 0.0;
|
|
|
|
TimeMarkers.Reset();
|
|
bIsScrubbing = false;
|
|
|
|
constexpr float TimeRulerHeight = 24.0f;
|
|
SetHeight(TimeRulerHeight);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::SetSelection(const bool bInIsSelecting, const double InSelectionStartTime, const double InSelectionEndTime)
|
|
{
|
|
bIsSelecting = bInIsSelecting;
|
|
SelectionStartTime = InSelectionStartTime;
|
|
SelectionEndTime = InSelectionEndTime;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::AddTimeMarker(TSharedRef<FTimeMarker> InTimeMarker)
|
|
{
|
|
TimeMarkers.Add(InTimeMarker);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::RemoveTimeMarker(TSharedRef<FTimeMarker> InTimeMarker)
|
|
{
|
|
TimeMarkers.Remove(InTimeMarker);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::RemoveAllTimeMarkers()
|
|
{
|
|
TimeMarkers.Reset();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TSharedPtr<FTimeMarker> FTimeRulerTrack::GetTimeMarkerByName(const FString& InTimeMarkerName)
|
|
{
|
|
for (TSharedRef<FTimeMarker>& TimeMarker : TimeMarkers)
|
|
{
|
|
if (TimeMarker->GetName().Equals(InTimeMarkerName))
|
|
{
|
|
return TimeMarker;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TSharedPtr<FTimeMarker> FTimeRulerTrack::GetTimeMarkerAtPos(const FVector2D& InPosition, const FTimingTrackViewport& InViewport)
|
|
{
|
|
TSharedPtr<FTimeMarker> ClosestTimeMarker = nullptr;
|
|
|
|
constexpr float TimeMarkerBoxHeight = 12.0f;
|
|
const float InPositionY = static_cast<float>(InPosition.Y);
|
|
if (InPositionY >= GetPosY() && InPositionY < GetPosY() + TimeMarkerBoxHeight)
|
|
{
|
|
const float InPositionX = static_cast<float>(InPosition.X);
|
|
float MinDX = 42.0f;
|
|
for (TSharedRef<FTimeMarker>& TimeMarker : TimeMarkers)
|
|
{
|
|
if (TimeMarker->IsVisible())
|
|
{
|
|
const float MarkerX = InViewport.TimeToSlateUnitsRounded(TimeMarker->GetTime());
|
|
const float DX = FMath::Abs(InPositionX - MarkerX);
|
|
if (DX <= MinDX)
|
|
{
|
|
MinDX = DX;
|
|
ClosestTimeMarker = TimeMarker;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ClosestTimeMarker;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::StartScrubbing(TSharedRef<FTimeMarker> InTimeMarker)
|
|
{
|
|
// Move the scrubbing time marker at the end of sorting list to be draw on top of other markers.
|
|
TimeMarkers.Remove(InTimeMarker);
|
|
TimeMarkers.Add(InTimeMarker);
|
|
|
|
ScrubbingTimeMarker = InTimeMarker;
|
|
ScrubbingTimeMarker->StartDragging();
|
|
|
|
bIsScrubbing = true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::StopScrubbing()
|
|
{
|
|
if (bIsScrubbing)
|
|
{
|
|
ScrubbingTimeMarker->StopDragging();
|
|
bIsScrubbing = false;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::PostUpdate(const ITimingTrackUpdateContext& Context)
|
|
{
|
|
//constexpr float HeaderWidth = 100.0f;
|
|
//constexpr float HeaderHeight = 14.0f;
|
|
|
|
const float MouseY = static_cast<float>(Context.GetMousePosition().Y);
|
|
if (MouseY >= GetPosY() && MouseY < GetPosY() + GetHeight())
|
|
{
|
|
SetHoveredState(true);
|
|
//const float MouseX = static_cast<float>(Context.GetMousePosition().X);
|
|
//SetHeaderHoveredState(MouseX < HeaderWidth && MouseY < GetPosY() + HeaderHeight);
|
|
}
|
|
else
|
|
{
|
|
SetHoveredState(false);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::Draw(const ITimingTrackDrawContext& Context) const
|
|
{
|
|
FDrawContext& DrawContext = Context.GetDrawContext();
|
|
const FTimingTrackViewport& Viewport = Context.GetViewport();
|
|
|
|
const float MinorTickMark = 5.0f;
|
|
const float MajorTickMark = 20 * MinorTickMark;
|
|
|
|
const float MinorTickMarkHeight = 5.0f;
|
|
const float MajorTickMarkHeight = 11.0f;
|
|
|
|
const float TextY = GetPosY() + MajorTickMarkHeight;
|
|
|
|
double MinorTickMarkTime = Viewport.GetDurationForViewportDX(MinorTickMark);
|
|
double MajorTickMarkTime = Viewport.GetDurationForViewportDX(MajorTickMark);
|
|
|
|
double VX = Viewport.GetStartTime() * Viewport.GetScaleX();
|
|
double MinorN = FMath::FloorToDouble(VX / static_cast<double>(MinorTickMark));
|
|
double MajorN = FMath::FloorToDouble(VX / static_cast<double>(MajorTickMark));
|
|
float MinorOX = static_cast<float>(FMath::RoundToDouble(MinorN * static_cast<double>(MinorTickMark) - VX));
|
|
float MajorOX = static_cast<float>(FMath::RoundToDouble(MajorN * static_cast<double>(MajorTickMark) - VX));
|
|
|
|
// Draw the time ruler's background.
|
|
FDrawHelpers::DrawBackground(DrawContext, WhiteBrush, Viewport, GetPosY(), GetHeight());
|
|
|
|
// Draw the minor tick marks.
|
|
for (float X = MinorOX; X < Viewport.GetWidth(); X += MinorTickMark)
|
|
{
|
|
const bool bIsTenth = ((int32)(((X - MajorOX) / MinorTickMark) + 0.4f) % 2 == 0);
|
|
const float MinorTickH = bIsTenth ? MinorTickMarkHeight : MinorTickMarkHeight - 1.0f;
|
|
DrawContext.DrawBox(X, GetPosY(), 1.0f, MinorTickH, WhiteBrush,
|
|
bIsTenth ? FLinearColor(0.3f, 0.3f, 0.3f, 1.0f) : FLinearColor(0.25f, 0.25f, 0.25f, 1.0f));
|
|
}
|
|
// Draw the major tick marks.
|
|
for (float X = MajorOX; X < Viewport.GetWidth(); X += MajorTickMark)
|
|
{
|
|
DrawContext.DrawBox(X, GetPosY(), 1.0f, MajorTickMarkHeight, WhiteBrush, FLinearColor(0.4f, 0.4f, 0.4f, 1.0f));
|
|
}
|
|
DrawContext.LayerId++;
|
|
|
|
const double DT = static_cast<double>(MajorTickMark) / Viewport.GetScaleX();
|
|
const double Precision = FMath::Max(DT / 10.0, FTimeValue::Nanosecond);
|
|
|
|
const TSharedRef<FSlateFontMeasure> FontMeasureService = FSlateApplication::Get().GetRenderer()->GetFontMeasureService();
|
|
const float FontScale = DrawContext.Geometry.Scale;
|
|
|
|
// Draw the time at major tick marks.
|
|
for (float X = MajorOX; X < Viewport.GetWidth() + MajorTickMark; X += MajorTickMark)
|
|
{
|
|
const double T = Viewport.SlateUnitsToTime(X);
|
|
FString Text = FormatTime(T, Precision);
|
|
const float TextWidth = static_cast<float>(FontMeasureService->Measure(Text, Font, FontScale).X / FontScale);
|
|
DrawContext.DrawText(X - TextWidth / 2, TextY, Text, Font,
|
|
(T < Viewport.GetMinValidTime() || T >= Viewport.GetMaxValidTime()) ? FLinearColor(0.7f, 0.5f, 0.5f, 1.0f) : FLinearColor(0.8f, 0.8f, 0.8f, 1.0f));
|
|
}
|
|
DrawContext.LayerId++;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::PostDraw(const ITimingTrackDrawContext& Context) const
|
|
{
|
|
FDrawContext& DrawContext = Context.GetDrawContext();
|
|
const FTimingTrackViewport& Viewport = Context.GetViewport();
|
|
const FVector2D& MousePosition = Context.GetMousePosition();
|
|
|
|
const bool bShowMousePos = !MousePosition.IsZero() && !bIsScrubbing;
|
|
const bool bIsMouseOver = bShowMousePos && MousePosition.Y >= GetPosY() && MousePosition.Y < GetPosY() + GetHeight();
|
|
|
|
if (bShowMousePos)
|
|
{
|
|
const FLinearColor MousePosLineColor(0.9f, 0.9f, 0.9f, 0.1f);
|
|
const FLinearColor MousePosTextBackgroundColor(0.9f, 0.9f, 0.9f, 1.0f);
|
|
FLinearColor MousePosTextForegroundColor(0.1f, 0.1f, 0.1f, 1.0f);
|
|
|
|
// Time at current mouse position.
|
|
FString MousePosText;
|
|
const double MousePosTime = Viewport.SlateUnitsToTime(static_cast<float>(MousePosition.X));
|
|
CrtMousePosTime = MousePosTime;
|
|
|
|
const double DT = 100.0 / Viewport.GetScaleX();
|
|
const double MousePosPrecision = FMath::Max(DT / 100.0, FTimeValue::Nanosecond);
|
|
if (bIsMouseOver)
|
|
{
|
|
// If mouse is hovering the time ruler, format time with a better precision (split seconds in ms, us, ns and ps).
|
|
MousePosText = FormatTimeSplit(MousePosTime, MousePosPrecision);
|
|
}
|
|
else
|
|
{
|
|
// Format current time with one more digit than the time at major tick marks.
|
|
MousePosText = FormatTime(MousePosTime, MousePosPrecision);
|
|
}
|
|
|
|
const TSharedRef<FSlateFontMeasure> FontMeasureService = FSlateApplication::Get().GetRenderer()->GetFontMeasureService();
|
|
const float FontScale = DrawContext.Geometry.Scale;
|
|
|
|
const float MousePosTextWidth = FMath::RoundToFloat(static_cast<float>(FontMeasureService->Measure(MousePosText, Font, FontScale).X / FontScale));
|
|
|
|
if (!FMath::IsNearlyEqual(CrtMousePosTextWidth, MousePosTextWidth))
|
|
{
|
|
// Animate the box's width (to avoid flickering).
|
|
CrtMousePosTextWidth = CrtMousePosTextWidth * 0.6f + MousePosTextWidth * 0.4f;
|
|
}
|
|
|
|
const float TextY = GetPosY() + 11.0f;
|
|
|
|
float X = static_cast<float>(MousePosition.X);
|
|
float W = CrtMousePosTextWidth + 4.0f;
|
|
if (bIsSelecting && SelectionStartTime < SelectionEndTime)
|
|
{
|
|
// While selecting, display the current time on either left or right side of the selected time range (i.e. to not overlap the selection arrows).
|
|
float SelectionX1 = Viewport.TimeToSlateUnitsRounded(SelectionStartTime);
|
|
float SelectionX2 = Viewport.TimeToSlateUnitsRounded(SelectionEndTime);
|
|
if (FMath::Abs(X - SelectionX1) > FMath::Abs(SelectionX2 - X))
|
|
{
|
|
X = SelectionX2 + W / 2.0f;
|
|
}
|
|
else
|
|
{
|
|
X = SelectionX1 - W / 2.0f;
|
|
}
|
|
MousePosTextForegroundColor = FLinearColor(0.01f, 0.05f, 0.2f, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
// Draw horizontal line at mouse position.
|
|
//DrawContext.DrawBox(0.0f, static_cast<float>(MousePosition.Y), Viewport.Width, 1.0f, WhiteBrush, MousePosLineColor);
|
|
|
|
// Draw vertical line at mouse position.
|
|
DrawContext.DrawBox(static_cast<float>(MousePosition.X), Viewport.GetPosY(), 1.0f, Viewport.GetHeight(), WhiteBrush, MousePosLineColor);
|
|
|
|
// Stroke the vertical line above current time box.
|
|
DrawContext.DrawBox(static_cast<float>(MousePosition.X), GetPosY(), 1.0f, TextY - GetPosY(), WhiteBrush, MousePosTextBackgroundColor);
|
|
}
|
|
|
|
// Fill the current time box.
|
|
DrawContext.DrawBox(X - W / 2.0f, TextY, W, 12.0f, WhiteBrush, MousePosTextBackgroundColor);
|
|
DrawContext.LayerId++;
|
|
|
|
// Draw current time text.
|
|
DrawContext.DrawText(X - MousePosTextWidth / 2.0f, TextY, MousePosText, Font, MousePosTextForegroundColor);
|
|
DrawContext.LayerId++;
|
|
}
|
|
|
|
// Draw the time markers.
|
|
for (const TSharedRef<FTimeMarker>& TimeMarker : TimeMarkers)
|
|
{
|
|
DrawTimeMarker(Context, *TimeMarker);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::DrawTimeMarker(const ITimingTrackDrawContext& Context, const FTimeMarker& TimeMarker) const
|
|
{
|
|
if (!TimeMarker.IsVisible())
|
|
{
|
|
return;
|
|
}
|
|
|
|
const FTimingTrackViewport& Viewport = Context.GetViewport();
|
|
|
|
const float TimeMarkerX = Viewport.TimeToSlateUnitsRounded(TimeMarker.GetTime());
|
|
const float HalfWidth = TimeMarker.GetCrtTextWidth() / 2;
|
|
|
|
if (TimeMarkerX < -HalfWidth || TimeMarkerX > Viewport.GetWidth() + HalfWidth)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const float TimeMarkerY = GetPosY();
|
|
constexpr float BoxHeight = 12.0f;
|
|
|
|
FDrawContext& DrawContext = Context.GetDrawContext();
|
|
|
|
// Draw the vertical line.
|
|
DrawContext.DrawBox(TimeMarkerX, TimeMarkerY, 1.0f, Viewport.GetPosY() + Viewport.GetHeight() - TimeMarkerY, WhiteBrush, TimeMarker.GetColor());
|
|
DrawContext.LayerId++;
|
|
|
|
const FVector2D& MousePosition = Context.GetMousePosition();
|
|
|
|
const bool bIsMouseOverTrack = !MousePosition.IsZero() &&
|
|
MousePosition.Y >= GetPosY() &&
|
|
MousePosition.Y < GetPosY() + GetHeight();
|
|
|
|
constexpr float FixedHalfWidth = 42.0f;
|
|
const bool bIsMouseOverMarker = bIsMouseOverTrack &&
|
|
MousePosition.Y >= GetPosY() + TimeMarkerY &&
|
|
MousePosition.Y < GetPosY() + TimeMarkerY + BoxHeight &&
|
|
MousePosition.X >= TimeMarkerX - FixedHalfWidth &&
|
|
MousePosition.X < TimeMarkerX + FixedHalfWidth;
|
|
|
|
// Decide what text to display.
|
|
FString TimeMarkerText;
|
|
if (bIsMouseOverTrack)
|
|
{
|
|
if (TimeMarker.GetName().Len() > 0)
|
|
{
|
|
TimeMarkerText = TimeMarker.GetName() + TEXT(": ");
|
|
}
|
|
|
|
// Format time value with one more digit than the time at major tick marks.
|
|
const double DT = 100.0 / Viewport.GetScaleX();
|
|
const double Precision = FMath::Max(DT / 100.0, FTimeValue::Nanosecond);
|
|
|
|
if (bIsMouseOverMarker)
|
|
{
|
|
// If mouse is hovering the time marker, format time with a better precision (split seconds in ms, us, ns and ps).
|
|
TimeMarkerText += FormatTimeSplit(TimeMarker.GetTime(), Precision);
|
|
}
|
|
else
|
|
{
|
|
TimeMarkerText += FormatTime(TimeMarker.GetTime(), Precision);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (TimeMarker.GetName().Len() > 0)
|
|
{
|
|
TimeMarkerText = TimeMarker.GetName();
|
|
}
|
|
else
|
|
{
|
|
TimeMarkerText = TEXT("T");
|
|
}
|
|
}
|
|
|
|
const TSharedRef<FSlateFontMeasure> FontMeasureService = FSlateApplication::Get().GetRenderer()->GetFontMeasureService();
|
|
const float FontScale = DrawContext.Geometry.Scale;
|
|
|
|
const float TextWidth = FMath::RoundToFloat(static_cast<float>(FontMeasureService->Measure(TimeMarkerText, Font, FontScale).X / FontScale));
|
|
|
|
if (!FMath::IsNearlyEqual(TimeMarker.GetCrtTextWidth(), TextWidth))
|
|
{
|
|
// Animate the box's width (to avoid flickering).
|
|
TimeMarker.SetCrtTextWidthAnimated(TextWidth);
|
|
}
|
|
|
|
const FLinearColor TextBackgroundColor(TimeMarker.GetColor().CopyWithNewOpacity(1.0f));
|
|
const FLinearColor TextForegroundColor(0.07f, 0.07f, 0.07f, 1.0f);
|
|
|
|
// Fill the time marker box.
|
|
const float BoxWidth = TimeMarker.GetCrtTextWidth() + 4.0f;
|
|
DrawContext.DrawBox(TimeMarkerX - BoxWidth / 2, TimeMarkerY, BoxWidth, BoxHeight, WhiteBrush, TextBackgroundColor);
|
|
DrawContext.LayerId++;
|
|
|
|
// Draw time marker text.
|
|
DrawContext.DrawText(TimeMarkerX - TextWidth / 2, TimeMarkerY, TimeMarkerText, Font, TextForegroundColor);
|
|
DrawContext.LayerId++;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::BuildContextMenu(FMenuBuilder& MenuBuilder)
|
|
{
|
|
TArray<TSharedRef<FTimeMarker>> VisibleTimeMarkers;
|
|
for (TSharedRef<FTimeMarker>& TimeMarker : TimeMarkers)
|
|
{
|
|
if (TimeMarker->IsVisible())
|
|
{
|
|
VisibleTimeMarkers.Add(TimeMarker);
|
|
}
|
|
}
|
|
|
|
FText CrtMousePosTimeText = FText::FromString(FormatTimeAuto(CrtMousePosTime, 2));
|
|
|
|
if (VisibleTimeMarkers.Num() > 0)
|
|
{
|
|
// Sort TimeMarkers by name.
|
|
VisibleTimeMarkers.Sort([](const TSharedRef<FTimeMarker>& A, const TSharedRef<FTimeMarker>& B) -> bool { return A->GetName().Compare(B->GetName()) <= 0; });
|
|
|
|
MenuBuilder.BeginSection("TimeMarkers", LOCTEXT("ContextMenu_Section_TimeMarkers", "Time Markers"));
|
|
|
|
for (TSharedRef<FTimeMarker>& TimeMarker : VisibleTimeMarkers)
|
|
{
|
|
FUIAction Action_MoveTimeMarker
|
|
(
|
|
FExecuteAction::CreateSP(this, &FTimeRulerTrack::ContextMenu_MoveTimeMarker_Execute, TimeMarker),
|
|
FCanExecuteAction()
|
|
);
|
|
const FString& MarkerNameString = TimeMarker->GetName();
|
|
const FText MarkerNameText = FText::FromString((MarkerNameString.Len() > 0) ? MarkerNameString : TEXT("T"));
|
|
MenuBuilder.AddMenuEntry
|
|
(
|
|
FText::Format(LOCTEXT("ContextMenu_MoveTimeMarker_Fmt", "Move Time Marker '{0}' (\u2192 {1})"), MarkerNameText, CrtMousePosTimeText),
|
|
FText::Format(LOCTEXT("ContextMenu_MoveTimeMarker_Desc_Fmt", "Move the time marker '{0}' at the current mouse position ({1})."), MarkerNameText, CrtMousePosTimeText),
|
|
FSlateIcon(),
|
|
Action_MoveTimeMarker,
|
|
NAME_None,
|
|
EUserInterfaceActionType::Button
|
|
);
|
|
}
|
|
|
|
MenuBuilder.EndSection();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FTimeRulerTrack::ContextMenu_MoveTimeMarker_Execute(TSharedRef<FTimeMarker> InTimeMarker)
|
|
{
|
|
InTimeMarker->SetTime(CrtMousePosTime);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
} // namespace UE::Insights::TimingProfiler
|
|
|
|
#undef LOCTEXT_NAMESPACE
|