Files
UnrealEngineUWP/Engine/Source/Developer/LogVisualizer/Private/STimelineBar.cpp
sebastian kowalczyk 49aba11ae5 Optimizations to Visual Logger edytor tool:
Much faster filters due to Async framework, it's paraller now,
Optimizations to items rendered on sequencer,
Optimization to graphs rendered on canvas,
Changed as much as possible to event driven flot, to update data only when needed.

[CL 2670708 by sebastian kowalczyk in Main branch]
2015-08-27 05:21:28 -04:00

272 lines
9.1 KiB
C++

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "LogVisualizer.h"
#include "STimelineBar.h"
#include "TimeSliderController.h"
#include "STimelinesContainer.h"
#if WITH_EDITOR
# include "Editor/UnrealEd/Public/EditorComponents.h"
# include "Editor/UnrealEd/Public/EditorReimportHandler.h"
# include "Editor/UnrealEd/Public/TexAlignTools.h"
# include "Editor/UnrealEd/Public/TickableEditorObject.h"
# include "UnrealEdClasses.h"
# include "Editor/UnrealEd/Public/Editor.h"
# include "Editor/UnrealEd/Public/EditorViewportClient.h"
#endif
FReply STimelineBar::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
TimelineOwner.Pin()->OnMouseButtonDown(MyGeometry, MouseEvent);
FReply Replay = TimeSliderController->OnMouseButtonDown(SharedThis(this), MyGeometry, MouseEvent);
if (Replay.IsEventHandled())
{
FName RowName = TimelineOwner.Pin()->GetName();
FVisualLoggerDBRow& DBRow = FVisualLoggerDatabase::Get().GetRowByName(RowName);
const float ScrubPosition = TimeSliderController->GetTimeSliderArgs().ScrubPosition.Get();
const int32 ClosestItem = DBRow.GetClosestItem(ScrubPosition);
const auto& Items = DBRow.GetItems();
if (Items.IsValidIndex(ClosestItem))
{
TimeSliderController->CommitScrubPosition(Items[ClosestItem].Entry.TimeStamp, false);
}
}
return Replay;
}
FReply STimelineBar::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
TimelineOwner.Pin()->OnMouseButtonUp(MyGeometry, MouseEvent);
FReply Replay = TimeSliderController->OnMouseButtonUp(SharedThis(this), MyGeometry, MouseEvent);
if (Replay.IsEventHandled())
{
FName RowName = TimelineOwner.Pin()->GetName();
FVisualLoggerDBRow& DBRow = FVisualLoggerDatabase::Get().GetRowByName(RowName);
const float ScrubPosition = TimeSliderController->GetTimeSliderArgs().ScrubPosition.Get();
const int32 ClosestItem = DBRow.GetClosestItem(ScrubPosition);
const auto& Items = DBRow.GetItems();
if (Items.IsValidIndex(ClosestItem))
{
TimeSliderController->CommitScrubPosition(Items[ClosestItem].Entry.TimeStamp, false);
}
}
return Replay;
}
FReply STimelineBar::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
return TimeSliderController->OnMouseMove(SharedThis(this), MyGeometry, MouseEvent);
}
FReply STimelineBar::OnMouseButtonDoubleClick(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
FName RowName = TimelineOwner.Pin()->GetName();
FVisualLoggerDBRow& DBRow = FVisualLoggerDatabase::Get().GetRowByName(RowName);
UWorld* World = FLogVisualizer::Get().GetWorld();
if (World && MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton)
{
FLogVisualizer::Get().UpdateCameraPosition(RowName, DBRow.GetCurrentItemIndex());
return FReply::Handled();
}
return FReply::Unhandled();
}
STimelineBar::~STimelineBar()
{
}
void STimelineBar::Construct(const FArguments& InArgs, TSharedPtr<FVisualLoggerTimeSliderController> InTimeSliderController, TSharedPtr<STimeline> InTimelineOwner)
{
TimeSliderController = InTimeSliderController;
TimelineOwner = InTimelineOwner;
TRange<float> LocalViewRange = TimeSliderController->GetTimeSliderArgs().ViewRange.Get();
}
FVector2D STimelineBar::ComputeDesiredSize(float) const
{
return FVector2D(5000.0f, 20.0f);
}
int32 STimelineBar::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
{
//@TODO: Optimize it like it was with old LogVisualizer, to draw everything much faster (SebaK)
int32 RetLayerId = LayerId;
FArrangedChildren ArrangedChildren(EVisibility::Visible);
ArrangeChildren(AllottedGeometry, ArrangedChildren);
TRange<float> LocalViewRange = TimeSliderController->GetTimeSliderArgs().ViewRange.Get();
float LocalScrubPosition = TimeSliderController->GetTimeSliderArgs().ScrubPosition.Get();
float ViewRange = LocalViewRange.Size<float>();
float PixelsPerInput = ViewRange > 0 ? AllottedGeometry.Size.X / ViewRange : 0;
float CurrentScrubLinePos = (LocalScrubPosition - LocalViewRange.GetLowerBoundValue()) * PixelsPerInput;
float BoxWidth = FMath::Max(0.08f * PixelsPerInput, 4.0f);
// Draw a region around the entire section area
FSlateDrawElement::MakeBox(
OutDrawElements,
RetLayerId++,
AllottedGeometry.ToPaintGeometry(),
FLogVisualizerStyle::Get().GetBrush("Sequencer.SectionArea.Background"),
MyClippingRect,
ESlateDrawEffect::None,
TimelineOwner.Pin()->IsSelected() ? FLinearColor(.2f, .2f, .2f, 0.5f) : FLinearColor(.1f, .1f, .1f, 0.5f)
);
const FSlateBrush* FillImage = FLogVisualizerStyle::Get().GetBrush("LogVisualizer.LogBar.EntryDefault");
static const FColor CurrentTimeColor(140, 255, 255, 255);
static const FColor ErrorTimeColor(255, 0, 0, 255);
static const FColor WarningTimeColor(255, 255, 0, 255);
static const FColor SelectedBarColor(255, 255, 255, 255);
const FSlateBrush* SelectedFillImage = FLogVisualizerStyle::Get().GetBrush("LogVisualizer.LogBar.Selected");
const ESlateDrawEffect::Type DrawEffects = ESlateDrawEffect::None;// bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect;
TArray<float> ErrorTimes;
TArray<float> WarningTimes;
int32 EntryIndex = 0;
FVisualLoggerDBRow& DBRow = FVisualLoggerDatabase::Get().GetRowByName(TimelineOwner.Pin()->GetName());
auto &Entries = DBRow.GetItems();
while (EntryIndex < Entries.Num())
{
const FVisualLogEntry& Entry = Entries[EntryIndex].Entry;
if (Entry.TimeStamp < LocalViewRange.GetLowerBoundValue() || Entry.TimeStamp > LocalViewRange.GetUpperBoundValue())
{
EntryIndex++;
continue;
}
if (DBRow.IsItemVisible(EntryIndex)==false)
{
EntryIndex++;
continue;
}
// find bar width, connect all contiguous bars to draw them as one geometry (rendering optimization)
const float StartPos = (Entry.TimeStamp - LocalViewRange.GetLowerBoundValue()) * PixelsPerInput - 2;
float EndPos = (Entry.TimeStamp - LocalViewRange.GetLowerBoundValue()) * PixelsPerInput + 2;
int32 StartIndex = EntryIndex;
float LastEndX = MAX_FLT;
for (; StartIndex < Entries.Num(); ++StartIndex)
{
const FVisualLogEntry& CurrentEntry = Entries[StartIndex].Entry;
if (CurrentEntry.TimeStamp < LocalViewRange.GetLowerBoundValue() || CurrentEntry.TimeStamp > LocalViewRange.GetUpperBoundValue())
{
break;
}
if (DBRow.IsItemVisible(StartIndex) == false)
{
continue;
}
const TArray<FVisualLogLine>& LogLines = CurrentEntry.LogLines;
bool bAddedWarning = false;
bool bAddedError = false;
for (const FVisualLogLine& CurrentLine : LogLines)
{
if (CurrentLine.Verbosity <= ELogVerbosity::Error && !bAddedError)
{
ErrorTimes.AddUnique(CurrentEntry.TimeStamp);
bAddedError = true;
}
else if (CurrentLine.Verbosity == ELogVerbosity::Warning && !bAddedWarning)
{
WarningTimes.AddUnique(CurrentEntry.TimeStamp);
bAddedWarning = true;
}
if (bAddedError && bAddedWarning)
{
break;
}
}
const float CurrentStartPos = (CurrentEntry.TimeStamp - LocalViewRange.GetLowerBoundValue()) * PixelsPerInput - 2;
if (CurrentStartPos > EndPos)
{
break;
}
EndPos = (CurrentEntry.TimeStamp - LocalViewRange.GetLowerBoundValue()) * PixelsPerInput + 2;
}
if (EndPos - StartPos > 0)
{
const float BarWidth = (EndPos - StartPos);
FSlateDrawElement::MakeBox(
OutDrawElements,
RetLayerId,
AllottedGeometry.ToPaintGeometry(
FVector2D(StartPos, 0.0f),
FVector2D(BarWidth, AllottedGeometry.Size.Y)),
FillImage,
MyClippingRect,
DrawEffects,
CurrentTimeColor
);
}
EntryIndex = StartIndex;
}
if (WarningTimes.Num()) RetLayerId++;
for (auto CurrentTime : WarningTimes)
{
float LinePos = (CurrentTime - LocalViewRange.GetLowerBoundValue()) * PixelsPerInput;
FSlateDrawElement::MakeBox(
OutDrawElements,
RetLayerId,
AllottedGeometry.ToPaintGeometry(
FVector2D(LinePos - 3, 0.0f),
FVector2D(6, AllottedGeometry.Size.Y)),
FillImage,
MyClippingRect,
DrawEffects,
WarningTimeColor
);
}
if (ErrorTimes.Num()) RetLayerId++;
for (auto CurrentTime : ErrorTimes)
{
float LinePos = (CurrentTime - LocalViewRange.GetLowerBoundValue()) * PixelsPerInput;
FSlateDrawElement::MakeBox(
OutDrawElements,
RetLayerId,
AllottedGeometry.ToPaintGeometry(
FVector2D(LinePos - 3, 0.0f),
FVector2D(6, AllottedGeometry.Size.Y)),
FillImage,
MyClippingRect,
DrawEffects,
ErrorTimeColor
);
}
int32 BestItemIndex = DBRow.GetClosestItem(LocalScrubPosition);
if (TimelineOwner.Pin()->IsSelected() && DBRow.GetCurrentItemIndex() != INDEX_NONE)
{
const auto &HighlightedItemEntry = DBRow.GetCurrentItem();
float CurrentTime = HighlightedItemEntry.Entry.TimeStamp;
float LinePos = (CurrentTime - LocalViewRange.GetLowerBoundValue()) * PixelsPerInput;
FSlateDrawElement::MakeBox(
OutDrawElements,
++RetLayerId,
AllottedGeometry.ToPaintGeometry(
FVector2D(LinePos - 2, 0.0f),
FVector2D(4, AllottedGeometry.Size.Y)),
SelectedFillImage,
MyClippingRect,
ESlateDrawEffect::None,
SelectedBarColor
);
}
return RetLayerId;
}