2014-03-14 14:13:41 -04:00
|
|
|
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "LogVisualizerPCH.h"
|
|
|
|
|
#include "SLogBar.h"
|
|
|
|
|
#include "Debug/LogVisualizerCameraController.h"
|
2014-06-10 16:45:28 -04:00
|
|
|
#include "Debug/ReporterGraph.h"
|
2014-03-14 14:13:41 -04:00
|
|
|
#include "MainFrame.h"
|
|
|
|
|
#include "DesktopPlatformModule.h"
|
|
|
|
|
#include "Json.h"
|
|
|
|
|
#include "Editor/UnrealEd/Classes/Editor/EditorEngine.h"
|
2014-05-29 17:46:51 -04:00
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
2014-06-11 09:13:09 -04:00
|
|
|
#include "GameplayDebuggingComponent.h"
|
2014-08-14 09:13:50 -04:00
|
|
|
#include "LogVisualizerModule.h"
|
2014-06-11 09:13:09 -04:00
|
|
|
|
2014-05-22 14:14:52 -04:00
|
|
|
#include "SFilterList.h"
|
2014-06-30 10:25:10 -04:00
|
|
|
|
|
|
|
|
#if ENABLE_VISUAL_LOG
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
#define LOCTEXT_NAMESPACE "SLogVisualizer"
|
|
|
|
|
|
|
|
|
|
const FName SLogVisualizer::NAME_LogName = TEXT("LogName");
|
|
|
|
|
const FName SLogVisualizer::NAME_StartTime = TEXT("StartTime");
|
|
|
|
|
const FName SLogVisualizer::NAME_EndTime = TEXT("EndTime");
|
|
|
|
|
const FName SLogVisualizer::NAME_LogTimeSpan = TEXT("LogTimeSpan");
|
|
|
|
|
|
|
|
|
|
namespace LogVisualizer
|
|
|
|
|
{
|
|
|
|
|
static const FString LogFileExtensionPure = TEXT("vlog");
|
|
|
|
|
static const FString LogFileDescription = LOCTEXT("FileTypeDescription", "Visual Log File").ToString();
|
|
|
|
|
static const FString LogFileExtension = FString::Printf(TEXT("*.%s"), *LogFileExtensionPure);
|
|
|
|
|
static const FString FileTypes = FString::Printf( TEXT("%s (%s)|%s"), *LogFileDescription, *LogFileExtension, *LogFileExtension );
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-10 16:45:28 -04:00
|
|
|
FColor SLogVisualizer::ColorPalette[] = {
|
|
|
|
|
FColor(0xff00A480),
|
|
|
|
|
FColorList::Aquamarine,
|
|
|
|
|
FColorList::Cyan,
|
|
|
|
|
FColorList::Brown,
|
|
|
|
|
FColorList::Green,
|
|
|
|
|
FColorList::Orange,
|
|
|
|
|
FColorList::Magenta,
|
|
|
|
|
FColorList::BrightGold,
|
|
|
|
|
FColorList::NeonBlue,
|
|
|
|
|
FColorList::MediumSlateBlue,
|
|
|
|
|
FColorList::SpicyPink,
|
2014-06-26 17:26:58 -04:00
|
|
|
FColorList::SpringGreen,
|
|
|
|
|
FColorList::SteelBlue,
|
|
|
|
|
FColorList::SummerSky,
|
|
|
|
|
FColorList::Violet,
|
|
|
|
|
FColorList::VioletRed,
|
|
|
|
|
FColorList::YellowGreen,
|
2014-06-10 16:45:28 -04:00
|
|
|
FColor(0xff62E200),
|
|
|
|
|
FColor(0xff1F7B67),
|
|
|
|
|
FColor(0xff62AA2A),
|
|
|
|
|
FColor(0xff70227E),
|
|
|
|
|
FColor(0xff006B53),
|
|
|
|
|
FColor(0xff409300),
|
|
|
|
|
FColor(0xff5D016D),
|
|
|
|
|
FColor(0xff34D2AF),
|
|
|
|
|
FColor(0xff8BF13C),
|
|
|
|
|
FColor(0xffBC38D3),
|
|
|
|
|
FColor(0xff5ED2B8),
|
|
|
|
|
FColor(0xffA6F16C),
|
|
|
|
|
FColor(0xffC262D3),
|
|
|
|
|
FColor(0xff0F4FA8),
|
|
|
|
|
FColor(0xff00AE68),
|
|
|
|
|
FColor(0xffDC0055),
|
|
|
|
|
FColor(0xff284C7E),
|
|
|
|
|
FColor(0xff21825B),
|
|
|
|
|
FColor(0xffA52959),
|
|
|
|
|
FColor(0xff05316D),
|
|
|
|
|
FColor(0xff007143),
|
|
|
|
|
FColor(0xff8F0037),
|
|
|
|
|
FColor(0xff4380D3),
|
|
|
|
|
FColor(0xff36D695),
|
|
|
|
|
FColor(0xffEE3B80),
|
|
|
|
|
FColor(0xff6996D3),
|
|
|
|
|
FColor(0xff60D6A7),
|
|
|
|
|
FColor(0xffEE6B9E)
|
|
|
|
|
};
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
template <typename ItemType>
|
|
|
|
|
class SLogListView : public SListView<ItemType>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
virtual FReply OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override
|
|
|
|
|
{
|
|
|
|
|
if (!MouseEvent.IsLeftShiftDown())
|
|
|
|
|
{
|
|
|
|
|
return SListView<ItemType>::OnMouseWheel(MyGeometry, MouseEvent);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return FReply::Unhandled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RefreshList()
|
|
|
|
|
{
|
|
|
|
|
const TArray<ItemType>& ItemsSourceRef = (*this->ItemsSource);
|
|
|
|
|
|
|
|
|
|
for (int32 Index = 0; Index < ItemsSourceRef.Num(); ++Index)
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr< SLogsTableRow > TableRow = StaticCastSharedPtr< SLogsTableRow >(this->WidgetGenerator.GetWidgetForItem(ItemsSourceRef[Index]));
|
|
|
|
|
if (TableRow.IsValid())
|
|
|
|
|
{
|
|
|
|
|
TableRow->UpdateEntries();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
|
|
|
void SLogVisualizer::Construct(const FArguments& InArgs, FLogVisualizer* InLogVisualizer)
|
|
|
|
|
{
|
|
|
|
|
LogVisualizer = InLogVisualizer;
|
|
|
|
|
SortBy = ELogsSortMode::ByName;
|
|
|
|
|
LogEntryIndex = INDEX_NONE;
|
|
|
|
|
SelectedLogIndex = INDEX_NONE;
|
|
|
|
|
LogsStartTime = FLT_MAX;
|
|
|
|
|
LogsEndTime = -FLT_MAX;
|
|
|
|
|
ScrollbarOffset = 0.f;
|
|
|
|
|
ZoomSliderValue = 0.f;
|
|
|
|
|
LastBarsOffset = 0.f;
|
|
|
|
|
MinZoom = 1.0f;
|
|
|
|
|
MaxZoom = 20.0f;
|
|
|
|
|
CurrentViewedTime = 0.f;
|
|
|
|
|
bDrawLogEntriesPath = true;
|
|
|
|
|
bIgnoreTrivialLogs = true;
|
2014-06-26 17:26:58 -04:00
|
|
|
HistogramPreviewWindow = 50;
|
|
|
|
|
bShowHistogramLabelsOutside = false;
|
|
|
|
|
bStickToLastData = false;
|
2014-07-07 17:19:49 -04:00
|
|
|
bOffsetDataSet = false;
|
|
|
|
|
bHistogramGraphsFilter = true;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
UsedCategories.Empty();
|
|
|
|
|
|
|
|
|
|
ChildSlot
|
|
|
|
|
[
|
|
|
|
|
SNew(SBorder)
|
|
|
|
|
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
|
|
|
[
|
|
|
|
|
SNew(SVerticalBox)
|
|
|
|
|
|
|
|
|
|
// Toolbar
|
|
|
|
|
+SVerticalBox::Slot()
|
|
|
|
|
.AutoHeight()
|
|
|
|
|
[
|
|
|
|
|
SNew( SOverlay )
|
|
|
|
|
+ SOverlay::Slot()
|
|
|
|
|
[
|
|
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
// Record button
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(1)
|
|
|
|
|
[
|
|
|
|
|
SNew(SButton)
|
|
|
|
|
.OnClicked(this, &SLogVisualizer::OnRecordButtonClicked)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.Image(this, &SLogVisualizer::GetRecordButtonBrush)
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
// 'Pause' toggle button
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(1)
|
|
|
|
|
[
|
|
|
|
|
SNew(SCheckBox)
|
|
|
|
|
.Style(FEditorStyle::Get(), "ToggleButtonCheckbox")
|
|
|
|
|
.OnCheckStateChanged(this, &SLogVisualizer::OnPauseChanged)
|
|
|
|
|
.IsChecked(this, &SLogVisualizer::GetPauseState)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.Image(FEditorStyle::GetBrush("LogVisualizer.Pause"))
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
// 'Camera' toggle button
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(1)
|
|
|
|
|
[
|
|
|
|
|
SNew(SCheckBox)
|
|
|
|
|
.Style(FEditorStyle::Get(), "ToggleButtonCheckbox")
|
|
|
|
|
.OnCheckStateChanged(this, &SLogVisualizer::OnToggleCamera)
|
|
|
|
|
.IsChecked(this, &SLogVisualizer::GetToggleCameraState)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.Image(FEditorStyle::GetBrush("LogVisualizer.Camera"))
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.MaxWidth(3)
|
|
|
|
|
.Padding(1)
|
|
|
|
|
[
|
|
|
|
|
SNew(SSeparator)
|
|
|
|
|
.Orientation(Orient_Vertical)
|
|
|
|
|
]
|
|
|
|
|
// 'Save' function
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(1)
|
|
|
|
|
[
|
|
|
|
|
SNew(SButton)
|
|
|
|
|
.OnClicked(this, &SLogVisualizer::OnSave)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.Image(FEditorStyle::GetBrush("LogVisualizer.Save"))
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
// 'Load' function
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(1)
|
|
|
|
|
[
|
|
|
|
|
SNew(SButton)
|
|
|
|
|
.OnClicked(this, &SLogVisualizer::OnLoad)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.Image(FEditorStyle::GetBrush("LogVisualizer.Load"))
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
// 'Remove' function
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(1)
|
|
|
|
|
[
|
|
|
|
|
SNew(SButton)
|
|
|
|
|
.OnClicked(this, &SLogVisualizer::OnRemove)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(SImage)
|
|
|
|
|
.Image(FEditorStyle::GetBrush("LogVisualizer.Remove"))
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.MaxWidth(3)
|
|
|
|
|
.Padding(1)
|
|
|
|
|
[
|
|
|
|
|
SNew(SSeparator)
|
|
|
|
|
.Orientation(Orient_Vertical)
|
|
|
|
|
]
|
|
|
|
|
]
|
2014-07-07 17:19:49 -04:00
|
|
|
|
|
|
|
|
+ SOverlay::Slot()
|
2014-03-14 14:13:41 -04:00
|
|
|
.HAlign(HAlign_Right)
|
|
|
|
|
.Padding(4)
|
|
|
|
|
[
|
2014-07-07 17:19:49 -04:00
|
|
|
SNew(SComboButton)
|
|
|
|
|
.ComboButtonStyle(FEditorStyle::Get(), "ContentBrowser.Filters.Style")
|
|
|
|
|
.ForegroundColor(FLinearColor::White)
|
|
|
|
|
.ContentPadding(0)
|
|
|
|
|
.ToolTipText(LOCTEXT("SettingsToolTip", "Log Visualizer settings."))
|
|
|
|
|
.HasDownArrow(true)
|
|
|
|
|
.ContentPadding(FMargin(1, 0))
|
|
|
|
|
.ButtonContent()
|
2014-03-14 14:13:41 -04:00
|
|
|
[
|
2014-07-07 17:19:49 -04:00
|
|
|
SNew(STextBlock)
|
|
|
|
|
.TextStyle(FEditorStyle::Get(), "ContentBrowser.Filters.Text")
|
|
|
|
|
.Text(LOCTEXT("Settings", "Settings"))
|
2014-03-14 14:13:41 -04:00
|
|
|
]
|
2014-07-07 17:19:49 -04:00
|
|
|
.MenuContent()
|
2014-03-14 14:13:41 -04:00
|
|
|
[
|
2014-07-07 17:19:49 -04:00
|
|
|
SNew(SVerticalBox)
|
|
|
|
|
+ SVerticalBox::Slot()
|
|
|
|
|
.AutoHeight()
|
|
|
|
|
[
|
|
|
|
|
SNew(SCheckBox)
|
|
|
|
|
.OnCheckStateChanged(this, &SLogVisualizer::OnDrawLogEntriesPathChanged)
|
|
|
|
|
.IsChecked(this, &SLogVisualizer::GetDrawLogEntriesPathState)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(LOCTEXT("VisLogDrawLogsPath", "Draw Log\'s path"))
|
|
|
|
|
.ToolTipText(LOCTEXT("VisLogDrawLogsPathTooltip", "Toggle whether path of composed of log entries\' locations"))
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
+ SVerticalBox::Slot()
|
|
|
|
|
.AutoHeight()
|
|
|
|
|
[
|
|
|
|
|
SNew(SCheckBox)
|
|
|
|
|
.OnCheckStateChanged(this, &SLogVisualizer::OnIgnoreTrivialLogs)
|
|
|
|
|
.IsChecked(this, &SLogVisualizer::GetIgnoreTrivialLogs)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(LOCTEXT("VisLogIgnoreTrivialLogs", "Ignore trivial logs"))
|
|
|
|
|
.ToolTipText(LOCTEXT("VisLogIgnoreTrivialLogsTooltip", "Whether to show trivial logs, i.e. the ones with only one entry."))
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
+ SVerticalBox::Slot()
|
|
|
|
|
.AutoHeight()
|
|
|
|
|
[
|
|
|
|
|
SNew(SCheckBox)
|
|
|
|
|
.OnCheckStateChanged(this, &SLogVisualizer::OnChangeHistogramLabelLocation)
|
|
|
|
|
.IsChecked(this, &SLogVisualizer::GetHistogramLabelLocation)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(LOCTEXT("VisLogHistogramLabelLocation", "Set histogram labels outside graph"))
|
|
|
|
|
.ToolTipText(LOCTEXT("VisLogHistogramLabelLocationTooltip", "Whether to show histogram labels inside graph or outside."))
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
+ SVerticalBox::Slot()
|
|
|
|
|
.AutoHeight()
|
|
|
|
|
[
|
|
|
|
|
SNew(SCheckBox)
|
|
|
|
|
.OnCheckStateChanged(this, &SLogVisualizer::OnStickToLastData)
|
|
|
|
|
.IsChecked(this, &SLogVisualizer::GetStickToLastData)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(LOCTEXT("VisLogStickToLastData", "Stick to recent data"))
|
|
|
|
|
.ToolTipText(LOCTEXT("VisLogStickToLastDataTooltip", "Whether to show the recent data or not."))
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
+ SVerticalBox::Slot()
|
|
|
|
|
.AutoHeight()
|
|
|
|
|
[
|
|
|
|
|
SNew(SCheckBox)
|
|
|
|
|
.OnCheckStateChanged(this, &SLogVisualizer::OnOffsetDataSets)
|
|
|
|
|
.IsChecked(this, &SLogVisualizer::GetOffsetDataSets)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(LOCTEXT("VisLogOffsetDataSets", "Offset data sets"))
|
|
|
|
|
.ToolTipText(LOCTEXT("VisLogOffsetDataSetsTooltip", "Offset data sets on graphs to make it easier to read"))
|
|
|
|
|
]
|
|
|
|
|
]
|
2014-03-14 14:13:41 -04:00
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
|
2014-05-22 14:14:52 -04:00
|
|
|
// Filters
|
|
|
|
|
+ SVerticalBox::Slot()
|
|
|
|
|
.AutoHeight()
|
|
|
|
|
[
|
2014-08-05 09:04:35 -04:00
|
|
|
SAssignNew(FilterListPtr, SLogFilterList)
|
|
|
|
|
.OnFilterChanged(this, &SLogVisualizer::OnLogCategoryFiltersChanged)
|
2014-09-05 07:39:52 -04:00
|
|
|
.AddMetaData<FTagMetaData>(FTagMetaData(TEXT("CategoryFilters")))
|
2014-08-05 09:04:35 -04:00
|
|
|
/*.OnGetContextMenu(this, &SLogVisualizer::GetFilterContextMenu)*/
|
|
|
|
|
/*.FrontendFilters(FrontendFilters)*/
|
2014-05-22 14:14:52 -04:00
|
|
|
]
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
+SVerticalBox::Slot()
|
|
|
|
|
.FillHeight(5)
|
|
|
|
|
[
|
|
|
|
|
SNew(SSplitter)
|
|
|
|
|
.Orientation(Orient_Vertical)
|
|
|
|
|
|
|
|
|
|
+SSplitter::Slot()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBorder)
|
|
|
|
|
.BorderImage(FEditorStyle::GetBrush("Menu.Background"))
|
|
|
|
|
.Padding(1.0)
|
|
|
|
|
[
|
2014-06-26 17:26:58 -04:00
|
|
|
SAssignNew(LogsListWidget, SLogListView< TSharedPtr<FLogsListItem> >)
|
2014-03-14 14:13:41 -04:00
|
|
|
.ItemHeight(20)
|
2014-05-29 17:46:51 -04:00
|
|
|
// Called when the user double-clicks with LMB on an item in the list
|
|
|
|
|
.OnMouseButtonDoubleClick(this, &SLogVisualizer::OnListDoubleClick)
|
2014-03-14 14:13:41 -04:00
|
|
|
.ListItemsSource(&LogsList)
|
|
|
|
|
.SelectionMode(ESelectionMode::Multi)
|
|
|
|
|
.OnGenerateRow(this, &SLogVisualizer::LogsListGenerateRow)
|
|
|
|
|
.OnSelectionChanged(this, &SLogVisualizer::LogsListSelectionChanged)
|
|
|
|
|
.HeaderRow(
|
2014-05-22 14:14:52 -04:00
|
|
|
SNew(SHeaderRow)
|
2014-03-14 14:13:41 -04:00
|
|
|
// ID
|
2014-04-23 18:06:41 -04:00
|
|
|
+SHeaderRow::Column(NAME_LogName)
|
2014-03-14 14:13:41 -04:00
|
|
|
.SortMode(this, &SLogVisualizer::GetLogsSortMode)
|
|
|
|
|
.OnSort(this, &SLogVisualizer::OnSortByChanged)
|
|
|
|
|
.HAlignCell(HAlign_Left)
|
|
|
|
|
.FillWidth(0.25f)
|
|
|
|
|
[
|
|
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.HAlign(HAlign_Left)
|
|
|
|
|
.Padding(0.0, 2.0)
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
2014-04-23 18:06:41 -04:00
|
|
|
.Text(LOCTEXT("VisLogName", "Log Subject"))
|
2014-03-14 14:13:41 -04:00
|
|
|
]
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(5,0)
|
|
|
|
|
[
|
|
|
|
|
SAssignNew(LogNameFilterBox, SEditableTextBox)
|
|
|
|
|
.SelectAllTextWhenFocused(true)
|
|
|
|
|
.OnTextCommitted(this, &SLogVisualizer::FilterTextCommitted)
|
2014-07-07 17:19:49 -04:00
|
|
|
.MinDesiredWidth(90.f)
|
2014-03-14 14:13:41 -04:00
|
|
|
.RevertTextOnEscape(true)
|
|
|
|
|
]
|
|
|
|
|
]
|
2014-04-23 18:06:41 -04:00
|
|
|
+SHeaderRow::Column(NAME_LogTimeSpan)
|
2014-03-14 14:13:41 -04:00
|
|
|
.VAlignCell(VAlign_Center)
|
|
|
|
|
[
|
2014-07-07 17:19:49 -04:00
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.HAlign(HAlign_Center)
|
|
|
|
|
.Padding(0.0, 2.0)
|
2014-03-14 14:13:41 -04:00
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
2014-07-07 17:19:49 -04:00
|
|
|
.Text(LOCTEXT("VisLogFilterName", "Quick Filter"))
|
|
|
|
|
]
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(5, 0)
|
|
|
|
|
[
|
|
|
|
|
SAssignNew(QuickFilterBox, SEditableTextBox)
|
|
|
|
|
.SelectAllTextWhenFocused(true)
|
|
|
|
|
.OnTextChanged(this, &SLogVisualizer::OnQuickFilterTextChanged, ETextCommit::Default)
|
|
|
|
|
.MinDesiredWidth(170.f)
|
|
|
|
|
.RevertTextOnEscape(true)
|
|
|
|
|
]
|
|
|
|
|
+ SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(SCheckBox)
|
|
|
|
|
.OnCheckStateChanged(this, &SLogVisualizer::OnHistogramGraphsFilter)
|
|
|
|
|
.IsChecked(this, &SLogVisualizer::GetHistogramGraphsFilter)
|
|
|
|
|
.Content()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(LOCTEXT("VisLogHistogramGraphsFilter", "histogram graphs filter"))
|
|
|
|
|
.ToolTipText(LOCTEXT("VisLogHistogramGraphsFilterTooltip", "Whether to filter histogram graphs or regular categories."))
|
|
|
|
|
]
|
2014-03-14 14:13:41 -04:00
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
+SSplitter::Slot()
|
|
|
|
|
[
|
|
|
|
|
SNew(SBorder)
|
|
|
|
|
.BorderImage(FEditorStyle::GetBrush("Menu.Background"))
|
|
|
|
|
.Padding(1.0)
|
|
|
|
|
[
|
|
|
|
|
SNew(SVerticalBox)
|
|
|
|
|
|
|
|
|
|
+SVerticalBox::Slot()
|
|
|
|
|
.AutoHeight()
|
|
|
|
|
.MaxHeight(60)
|
|
|
|
|
[
|
|
|
|
|
SAssignNew( Timeline, STimeline )
|
|
|
|
|
.MinValue(0.0f)
|
|
|
|
|
.MaxValue(100.0f)
|
|
|
|
|
.FixedLabelSpacing(100.f)
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
+SVerticalBox::Slot()
|
|
|
|
|
.AutoHeight()
|
|
|
|
|
.Padding( 2 )
|
|
|
|
|
.VAlign( VAlign_Fill )
|
|
|
|
|
[
|
|
|
|
|
SAssignNew( ScrollBar, SScrollBar )
|
|
|
|
|
.Orientation( Orient_Horizontal )
|
|
|
|
|
.OnUserScrolled( this, &SLogVisualizer::OnZoomScrolled )
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
+SVerticalBox::Slot()
|
|
|
|
|
.AutoHeight()
|
|
|
|
|
.Padding( 2 )
|
|
|
|
|
[
|
|
|
|
|
SAssignNew(ZoomSlider, SSlider)
|
|
|
|
|
.Value( this, &SLogVisualizer::GetZoomValue )
|
|
|
|
|
.OnValueChanged( this, &SLogVisualizer::OnSetZoomValue )
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
+SVerticalBox::Slot()
|
|
|
|
|
.Padding(2)
|
|
|
|
|
.FillHeight(3)
|
|
|
|
|
//.VAlign(VAlign_Fill)
|
|
|
|
|
[
|
|
|
|
|
SNew(SSplitter)
|
|
|
|
|
|
|
|
|
|
+SSplitter::Slot()
|
|
|
|
|
.Value(1)
|
|
|
|
|
[
|
|
|
|
|
SNew( SBorder )
|
|
|
|
|
.Padding(1)
|
|
|
|
|
.BorderImage( FEditorStyle::GetBrush( "ToolBar.Background" ) )
|
|
|
|
|
[
|
|
|
|
|
SAssignNew(StatusItemsView, STreeView<TSharedPtr<FLogStatusItem> >)
|
|
|
|
|
.ItemHeight(40.0f)
|
|
|
|
|
.TreeItemsSource(&StatusItems)
|
|
|
|
|
.OnGenerateRow(this, &SLogVisualizer::HandleGenerateLogStatus)
|
|
|
|
|
.OnGetChildren(this, &SLogVisualizer::OnLogStatusGetChildren)
|
|
|
|
|
.SelectionMode(ESelectionMode::None)
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
+SSplitter::Slot()
|
|
|
|
|
.Value(3)
|
|
|
|
|
[
|
|
|
|
|
SNew( SBorder )
|
|
|
|
|
.Padding(1)
|
|
|
|
|
.BorderImage( FEditorStyle::GetBrush( "ToolBar.Background" ) )
|
|
|
|
|
[
|
|
|
|
|
SAssignNew(LogsLinesWidget, SListView<TSharedPtr<FLogEntryItem> >)
|
|
|
|
|
.ItemHeight(20)
|
|
|
|
|
.ListItemsSource(&LogEntryLines)
|
2014-09-15 20:13:23 -04:00
|
|
|
.SelectionMode(ESelectionMode::Single)
|
|
|
|
|
.OnSelectionChanged(this, &SLogVisualizer::LogEntryLineSelectionChanged)
|
2014-03-14 14:13:41 -04:00
|
|
|
.OnGenerateRow(this, &SLogVisualizer::LogEntryLinesGenerateRow)
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
+SVerticalBox::Slot()
|
|
|
|
|
.AutoHeight()
|
|
|
|
|
[
|
|
|
|
|
// Status area
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(this, &SLogVisualizer::GetStatusText)
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
LogVisualizer->OnLogAdded().AddSP(this, &SLogVisualizer::OnLogAdded);
|
|
|
|
|
|
2014-08-07 17:34:29 -04:00
|
|
|
if (LogsList.Num() == 0)
|
|
|
|
|
{
|
|
|
|
|
Timeline->SetVisibility(EVisibility::Hidden);
|
|
|
|
|
ScrollBar->SetVisibility(EVisibility::Hidden);
|
|
|
|
|
ZoomSlider->SetVisibility(EVisibility::Hidden);
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
TArray<TSharedPtr<FActorsVisLog> >& Logs = LogVisualizer->Logs;
|
|
|
|
|
TSharedPtr<FActorsVisLog>* SharedLog = Logs.GetTypedData();
|
|
|
|
|
for (int32 LogIndex = 0; LogIndex < Logs.Num(); ++LogIndex, ++SharedLog)
|
|
|
|
|
{
|
|
|
|
|
if (SharedLog->IsValid())
|
|
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
AddOrUpdateLog(LogIndex, SharedLog->Get());
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DoFullUpdate();
|
|
|
|
|
|
|
|
|
|
LastBrowsePath = FPaths::GameLogDir();
|
|
|
|
|
|
|
|
|
|
DrawingOnCanvasDelegate = FDebugDrawDelegate::CreateSP(this, &SLogVisualizer::DrawOnCanvas);
|
|
|
|
|
UDebugDrawService::Register(TEXT("VisLog"), DrawingOnCanvasDelegate);
|
2014-06-11 09:13:09 -04:00
|
|
|
UGameplayDebuggingComponent::OnDebuggingTargetChangedDelegate.AddSP(this, &SLogVisualizer::SelectionChanged);
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
|
|
|
|
|
|
|
|
SLogVisualizer::~SLogVisualizer()
|
|
|
|
|
{
|
2014-08-14 10:59:17 -04:00
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
if (World)
|
|
|
|
|
{
|
|
|
|
|
World->DestroyActor(FLogVisualizerModule::Get()->GetHelperActor(World));
|
|
|
|
|
}
|
2014-06-11 09:13:09 -04:00
|
|
|
UGameplayDebuggingComponent::OnDebuggingTargetChangedDelegate.RemoveAll(this);
|
2014-03-14 14:13:41 -04:00
|
|
|
LogVisualizer->OnLogAdded().RemoveAll(this);
|
|
|
|
|
UDebugDrawService::Unregister(DrawingOnCanvasDelegate);
|
2014-07-07 17:19:49 -04:00
|
|
|
InvalidateCanvas();
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
2014-05-29 17:46:51 -04:00
|
|
|
void SLogVisualizer::OnListDoubleClick(TSharedPtr<FLogsListItem> LogListItem)
|
|
|
|
|
{
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
FVector Orgin, Extent;
|
|
|
|
|
|
|
|
|
|
bool bFoundActor = false;
|
|
|
|
|
if (LogVisualizer->Logs.IsValidIndex(LogListItem->LogIndex))
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog>& Log = LogVisualizer->Logs[LogListItem->LogIndex];
|
|
|
|
|
for (FActorIterator It(GetWorld()); It; ++It)
|
|
|
|
|
{
|
2014-09-16 16:22:01 -04:00
|
|
|
AActor* Actor = *It;
|
2014-05-29 17:46:51 -04:00
|
|
|
if (Actor->GetFName() == Log->Name)
|
|
|
|
|
{
|
|
|
|
|
Actor->GetActorBounds(false, Orgin, Extent);
|
|
|
|
|
bFoundActor = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!bFoundActor)
|
|
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
Extent = FVector(150, 150, 150);
|
2014-05-29 17:46:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LogVisualizer->Logs.IsValidIndex(LogListItem->LogIndex))
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog>& Log = LogVisualizer->Logs[LogListItem->LogIndex];
|
|
|
|
|
if (Log.IsValid() && Log->Entries.IsValidIndex(LogEntryIndex))
|
|
|
|
|
{
|
|
|
|
|
Orgin = Log->Entries[LogEntryIndex]->Location;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UEditorEngine *EEngine = Cast<UEditorEngine>(GEngine);
|
|
|
|
|
if (GIsEditor && EEngine != NULL)
|
|
|
|
|
{
|
2014-06-23 10:24:03 -04:00
|
|
|
for (auto ViewportClient : EEngine->AllViewportClients)
|
2014-05-29 17:46:51 -04:00
|
|
|
{
|
|
|
|
|
ViewportClient->FocusViewportOnBox(FBox::BuildAABB(Orgin, Extent));
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-07-07 17:19:49 -04:00
|
|
|
else if (ALogVisualizerCameraController::IsEnabled(GetWorld()) && CameraController.IsValid() && CameraController->GetSpectatorPawn())
|
|
|
|
|
{
|
|
|
|
|
ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(CameraController->Player);
|
|
|
|
|
if (LocalPlayer && LocalPlayer->ViewportClient && LocalPlayer->ViewportClient->Viewport)
|
|
|
|
|
{
|
|
|
|
|
FViewport* Viewport = LocalPlayer->ViewportClient->Viewport;
|
|
|
|
|
|
|
|
|
|
FBox BoundingBox = FBox::BuildAABB(Orgin, Extent);
|
|
|
|
|
const FVector Position = BoundingBox.GetCenter();
|
|
|
|
|
float Radius = BoundingBox.GetExtent().Size();
|
|
|
|
|
|
|
|
|
|
FViewportCameraTransform ViewTransform;
|
|
|
|
|
ViewTransform.TransitionToLocation(Position, true);
|
|
|
|
|
|
|
|
|
|
float NewOrthoZoom;
|
|
|
|
|
const float AspectRatio = 1.777777f;
|
|
|
|
|
uint32 MinAxisSize = (AspectRatio > 1.0f) ? Viewport->GetSizeXY().Y : Viewport->GetSizeXY().X;
|
|
|
|
|
float Zoom = Radius / (MinAxisSize / 2);
|
|
|
|
|
|
|
|
|
|
NewOrthoZoom = Zoom * (Viewport->GetSizeXY().X*15.0f);
|
|
|
|
|
NewOrthoZoom = FMath::Clamp<float>(NewOrthoZoom, 250, MAX_FLT);
|
|
|
|
|
ViewTransform.SetOrthoZoom(NewOrthoZoom);
|
|
|
|
|
|
|
|
|
|
CameraController->GetSpectatorPawn()->TeleportTo(ViewTransform.GetLocation(), ViewTransform.GetRotation(), false, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-05-29 17:46:51 -04:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
int32 SLogVisualizer::GetCurrentVisibleLogEntryIndex(const TArray<TSharedPtr<FVisLogEntry> >& InVisibleEntries)
|
|
|
|
|
{
|
|
|
|
|
if (LogVisualizer->Logs.IsValidIndex(SelectedLogIndex))
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[SelectedLogIndex];
|
2014-05-07 20:37:19 -04:00
|
|
|
if (Log.IsValid() && Log->Entries.IsValidIndex(LogEntryIndex))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-05-07 20:37:19 -04:00
|
|
|
for (int32 Index = 0; Index < InVisibleEntries.Num(); ++Index)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-05-07 20:37:19 -04:00
|
|
|
if (InVisibleEntries[Index] == Log->Entries[LogEntryIndex])
|
|
|
|
|
{
|
|
|
|
|
return Index;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return INDEX_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
void SLogVisualizer::UpdateVisibleEntriesCache(const TSharedPtr<FActorsVisLog>& Log, int32 Index)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
int32 CurrentIndex = INDEX_NONE;
|
|
|
|
|
int32 LogListNum = LogsList.Num();
|
|
|
|
|
for (int32 LogIndex = 0; LogIndex < LogListNum; ++LogIndex)
|
|
|
|
|
{
|
|
|
|
|
if (LogsList[LogIndex]->LogIndex == Index)
|
|
|
|
|
{
|
|
|
|
|
CurrentIndex = LogIndex;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float LastTimestamp = -1;
|
|
|
|
|
if (CurrentIndex != INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
LastTimestamp = LogsList[CurrentIndex]->LastEndTimestamp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int32 NumLogs = OutEntriesCached.Num();
|
|
|
|
|
int32 CachedLogIndex = INDEX_NONE;
|
|
|
|
|
for (int32 EntriesIndex = 0; EntriesIndex < NumLogs; ++EntriesIndex)
|
|
|
|
|
{
|
|
|
|
|
if (OutEntriesCached[EntriesIndex].Log == Log)
|
|
|
|
|
{
|
|
|
|
|
CachedLogIndex = EntriesIndex;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (CachedLogIndex == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
FCachedEntries CachedLog;
|
|
|
|
|
CachedLog.Log = Log;
|
|
|
|
|
CachedLogIndex = OutEntriesCached.Add(CachedLog);
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-05-22 14:14:52 -04:00
|
|
|
if (FilterListPtr.IsValid())
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-06-23 10:24:03 -04:00
|
|
|
for (int32 EntryIndex = 0; EntryIndex < Log->Entries.Num(); ++EntryIndex)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
const TSharedPtr<FVisLogEntry> CurrentEntry = Log->Entries[EntryIndex];
|
|
|
|
|
if (CurrentEntry->TimeStamp <= LastTimestamp)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2014-06-16 23:03:48 -04:00
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
bool bAddedEntry = false;
|
2014-06-16 23:03:48 -04:00
|
|
|
if (!bAddedEntry)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
for (int32 LogLineIndex = 0; LogLineIndex < CurrentEntry->LogLines.Num(); ++LogLineIndex)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
const FVisLogEntry::FLogLine &CurrentLine = CurrentEntry->LogLines[LogLineIndex];
|
|
|
|
|
const FString CurrentCategory = CurrentLine.Category.ToString();
|
|
|
|
|
if (FilterListPtr->IsFilterEnabled(CurrentCategory, CurrentLine.Verbosity))
|
2014-06-16 23:03:48 -04:00
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
OutEntriesCached[CachedLogIndex].CachedEntries.Add(CurrentEntry);
|
2014-06-16 23:03:48 -04:00
|
|
|
bAddedEntry = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
2014-05-29 17:46:51 -04:00
|
|
|
|
2014-06-16 23:03:48 -04:00
|
|
|
if (bAddedEntry)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
for (int32 ElementIndex = 0; ElementIndex < CurrentEntry->ElementsToDraw.Num(); ++ElementIndex)
|
2014-05-29 17:46:51 -04:00
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
const FString CurrentCategory = CurrentEntry->ElementsToDraw[ElementIndex].Category.ToString();
|
|
|
|
|
FVisLogEntry::FElementToDraw &CurrentElement = CurrentEntry->ElementsToDraw[ElementIndex];
|
|
|
|
|
if (CurrentElement.Category != NAME_None && (FilterListPtr->IsFilterEnabled(CurrentCategory, CurrentElement.Verbosity)))
|
2014-05-29 17:46:51 -04:00
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
OutEntriesCached[CachedLogIndex].CachedEntries.AddUnique(CurrentEntry);
|
2014-06-16 23:03:48 -04:00
|
|
|
bAddedEntry = true;
|
2014-05-29 17:46:51 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-06-16 23:03:48 -04:00
|
|
|
if (bAddedEntry)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2014-06-10 16:45:28 -04:00
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
for (int32 SampleIndex = 0; SampleIndex < CurrentEntry->HistogramSamples.Num(); ++SampleIndex)
|
2014-06-10 16:45:28 -04:00
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
const FVisLogEntry::FHistogramSample &CurrentSample = CurrentEntry->HistogramSamples[SampleIndex];
|
|
|
|
|
const FName CurrentCategory = CurrentSample.Category;
|
|
|
|
|
const FName CurrentDataName = CurrentSample.DataName;
|
2014-06-16 23:03:48 -04:00
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
const bool bCurrentCategoryPassed = FilterListPtr->IsFilterEnabled(CurrentCategory.ToString(), ELogVerbosity::All);
|
|
|
|
|
const bool bCurrentDataNamePassed = FilterListPtr->IsFilterEnabled(CurrentDataName.ToString(), ELogVerbosity::All);
|
|
|
|
|
|
|
|
|
|
if (CurrentCategory != NAME_None && (bCurrentCategoryPassed && bCurrentDataNamePassed))
|
2014-06-10 16:45:28 -04:00
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
OutEntriesCached[CachedLogIndex].CachedEntries.AddUnique(CurrentEntry);
|
2014-06-16 23:03:48 -04:00
|
|
|
bAddedEntry = true;
|
2014-06-10 16:45:28 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-08-14 09:13:50 -04:00
|
|
|
|
|
|
|
|
if (bAddedEntry)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto CurrentBlock : CurrentEntry->DataBlocks)
|
|
|
|
|
{
|
|
|
|
|
const bool bCurrentCategoryPassed = FilterListPtr->IsFilterEnabled(CurrentBlock.Category.ToString(), ELogVerbosity::All);
|
|
|
|
|
const bool bCurrentTagNamePassed = FilterListPtr->IsFilterEnabled(CurrentBlock.TagName.ToString(), ELogVerbosity::All);
|
|
|
|
|
|
|
|
|
|
if (CurrentBlock.Category != NAME_None && (bCurrentCategoryPassed && bCurrentTagNamePassed))
|
|
|
|
|
{
|
|
|
|
|
OutEntriesCached[CachedLogIndex].CachedEntries.AddUnique(CurrentEntry);
|
|
|
|
|
bAddedEntry = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
2014-07-07 17:19:49 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// if there is no LogFilter widget - show all
|
|
|
|
|
OutEntriesCached[CachedLogIndex].CachedEntries = Log->Entries;
|
|
|
|
|
}
|
|
|
|
|
LogsList[CurrentIndex]->LastEndTimestamp = LogsList[CurrentIndex]->EndTimestamp;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
void SLogVisualizer::GetVisibleEntries(const TSharedPtr<FActorsVisLog>& Log, TArray<TSharedPtr<FVisLogEntry> >& OutEntries)
|
|
|
|
|
{
|
|
|
|
|
const int32 NumLogs = OutEntriesCached.Num();
|
|
|
|
|
int32 CachedLogIndex = INDEX_NONE;
|
|
|
|
|
for (int32 Index = 0; Index < NumLogs; ++Index)
|
|
|
|
|
{
|
|
|
|
|
if (OutEntriesCached[Index].Log == Log)
|
|
|
|
|
{
|
|
|
|
|
CachedLogIndex = Index;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
if (CachedLogIndex == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
FCachedEntries CachedLog;
|
|
|
|
|
CachedLog.Log = Log;
|
|
|
|
|
CachedLogIndex = OutEntriesCached.Add(CachedLog);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (OutEntriesCached[CachedLogIndex].CachedEntries.Num() == 0)
|
|
|
|
|
{
|
|
|
|
|
// generate entries based on current filters
|
|
|
|
|
OutEntriesCached[CachedLogIndex].CachedEntries.Reset();
|
|
|
|
|
if (FilterListPtr.IsValid())
|
|
|
|
|
{
|
|
|
|
|
for (int32 i = 0; i < Log->Entries.Num(); ++i)
|
|
|
|
|
{
|
|
|
|
|
bool bAddedEntry = false;
|
|
|
|
|
|
|
|
|
|
const TSharedPtr<FVisLogEntry> CurrentEntry = Log->Entries[i];
|
|
|
|
|
if (!bAddedEntry)
|
|
|
|
|
{
|
|
|
|
|
for (int32 j = 0; j < CurrentEntry->LogLines.Num(); ++j)
|
|
|
|
|
{
|
|
|
|
|
const FVisLogEntry::FLogLine &CurrentLine = CurrentEntry->LogLines[j];
|
|
|
|
|
const FString CurrentCategory = CurrentLine.Category.ToString();
|
|
|
|
|
if (FilterListPtr->IsFilterEnabled(CurrentCategory, CurrentLine.Verbosity))
|
|
|
|
|
{
|
|
|
|
|
OutEntriesCached[CachedLogIndex].CachedEntries.Add(CurrentEntry);
|
|
|
|
|
bAddedEntry = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bAddedEntry)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int32 j = 0; j < CurrentEntry->ElementsToDraw.Num(); ++j)
|
|
|
|
|
{
|
|
|
|
|
const FString CurrentCategory = CurrentEntry->ElementsToDraw[j].Category.ToString();
|
|
|
|
|
FVisLogEntry::FElementToDraw &CurrentElement = CurrentEntry->ElementsToDraw[j];
|
|
|
|
|
if (CurrentElement.Category != NAME_None && (FilterListPtr->IsFilterEnabled(CurrentCategory, CurrentElement.Verbosity)))
|
|
|
|
|
{
|
|
|
|
|
OutEntriesCached[CachedLogIndex].CachedEntries.AddUnique(CurrentEntry);
|
|
|
|
|
bAddedEntry = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (bAddedEntry)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int32 SampleIndex = 0; SampleIndex < CurrentEntry->HistogramSamples.Num(); ++SampleIndex)
|
|
|
|
|
{
|
|
|
|
|
const FVisLogEntry::FHistogramSample &CurrentSample = CurrentEntry->HistogramSamples[SampleIndex];
|
|
|
|
|
const FName CurrentCategory = CurrentSample.Category;
|
|
|
|
|
const FName CurrentDataName = CurrentSample.DataName;
|
|
|
|
|
|
|
|
|
|
const bool bCurrentCategoryPassed = FilterListPtr->IsFilterEnabled(CurrentCategory.ToString(), ELogVerbosity::All);
|
|
|
|
|
const bool bCurrentDataNamePassed = FilterListPtr->IsFilterEnabled(CurrentDataName.ToString(), ELogVerbosity::All);
|
|
|
|
|
|
|
|
|
|
if (CurrentCategory != NAME_None && (bCurrentCategoryPassed && bCurrentDataNamePassed))
|
|
|
|
|
{
|
|
|
|
|
OutEntriesCached[CachedLogIndex].CachedEntries.AddUnique(CurrentEntry);
|
|
|
|
|
bAddedEntry = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-08-14 09:13:50 -04:00
|
|
|
if (bAddedEntry)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto CurrentData : CurrentEntry->DataBlocks)
|
|
|
|
|
{
|
|
|
|
|
const bool bCurrentCategoryPassed = FilterListPtr->IsFilterEnabled(CurrentData.Category.ToString(), ELogVerbosity::All);
|
|
|
|
|
const bool bCurrentTagNamePassed = FilterListPtr->IsFilterEnabled(CurrentData.TagName.ToString(), ELogVerbosity::All);
|
|
|
|
|
|
|
|
|
|
if (CurrentData.TagName != NAME_None && (bCurrentCategoryPassed && bCurrentTagNamePassed))
|
|
|
|
|
{
|
|
|
|
|
OutEntriesCached[CachedLogIndex].CachedEntries.AddUnique(CurrentEntry);
|
|
|
|
|
bAddedEntry = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-07-07 17:19:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// if there is no LogFilter widget - show all
|
|
|
|
|
OutEntriesCached[CachedLogIndex].CachedEntries = Log->Entries;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OutEntries.Reset();
|
|
|
|
|
if (QuickFilterText.Len() > 0)
|
|
|
|
|
{
|
|
|
|
|
// filter our data using quick filter string
|
|
|
|
|
const int32 NumEntries = OutEntriesCached[CachedLogIndex].CachedEntries.Num();
|
|
|
|
|
for (int32 Index = 0; Index < NumEntries; ++Index)
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FVisLogEntry> LogEntry = OutEntriesCached[CachedLogIndex].CachedEntries[Index];
|
|
|
|
|
if (!LogEntry.IsValid())
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool bAddedEntry = false;
|
|
|
|
|
if (!bAddedEntry)
|
|
|
|
|
{
|
|
|
|
|
for (int32 LineIndex = 0; LineIndex < LogEntry->LogLines.Num(); ++LineIndex)
|
|
|
|
|
{
|
|
|
|
|
FString CurrentCategory = LogEntry->LogLines[LineIndex].Category.ToString();
|
|
|
|
|
if (bHistogramGraphsFilter || CurrentCategory.Find(QuickFilterText) != INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
OutEntries.AddUnique(LogEntry);
|
|
|
|
|
bAddedEntry = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bAddedEntry)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int32 ElementIndex = 0; ElementIndex < LogEntry->ElementsToDraw.Num(); ++ElementIndex)
|
|
|
|
|
{
|
|
|
|
|
FString CurrentCategory = LogEntry->ElementsToDraw[ElementIndex].Category.ToString();
|
|
|
|
|
if (bHistogramGraphsFilter || CurrentCategory.Find(QuickFilterText) != INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
OutEntries.AddUnique(LogEntry);
|
|
|
|
|
bAddedEntry = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (bAddedEntry)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int32 SampleIndex = 0; SampleIndex < LogEntry->HistogramSamples.Num(); ++SampleIndex)
|
|
|
|
|
{
|
|
|
|
|
const FName CurrentCategory = LogEntry->HistogramSamples[SampleIndex].Category;
|
|
|
|
|
const FName CurrentGraphName = LogEntry->HistogramSamples[SampleIndex].GraphName;
|
|
|
|
|
const FName CurrentDataName = LogEntry->HistogramSamples[SampleIndex].DataName;
|
|
|
|
|
|
|
|
|
|
const bool bCurrentCategoryPassed = bHistogramGraphsFilter || (QuickFilterText.Len() == 0 || CurrentCategory.ToString().Find(QuickFilterText) != INDEX_NONE);
|
|
|
|
|
const bool bCurrentDataNamePassed = !bHistogramGraphsFilter || (QuickFilterText.Len() == 0 || CurrentDataName.ToString().Find(QuickFilterText) != INDEX_NONE);
|
|
|
|
|
|
|
|
|
|
if (bCurrentCategoryPassed && bCurrentDataNamePassed)
|
|
|
|
|
{
|
|
|
|
|
OutEntries.AddUnique(LogEntry);
|
|
|
|
|
bAddedEntry = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-08-14 09:13:50 -04:00
|
|
|
if (bAddedEntry)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto CurrentData : LogEntry->DataBlocks)
|
|
|
|
|
{
|
|
|
|
|
const bool bCurrentCategoryPassed = bHistogramGraphsFilter || (QuickFilterText.Len() == 0 || CurrentData.Category.ToString().Find(QuickFilterText) != INDEX_NONE);
|
|
|
|
|
const bool bCurrentTagNamePassed = !bHistogramGraphsFilter || (QuickFilterText.Len() == 0 || CurrentData.TagName.ToString().Find(QuickFilterText) != INDEX_NONE);
|
|
|
|
|
|
|
|
|
|
if (bCurrentCategoryPassed && bCurrentTagNamePassed)
|
|
|
|
|
{
|
|
|
|
|
OutEntries.AddUnique(LogEntry);
|
|
|
|
|
bAddedEntry = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
} //for (int32 Index = 0; Index < NumEntries; ++Index)
|
|
|
|
|
} //if (QuickFilterText.Len() > 0)
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
OutEntries = OutEntriesCached[CachedLogIndex].CachedEntries;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::OnLogCategoryFiltersChanged()
|
|
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
LogsList.Reset();
|
|
|
|
|
OutEntriesCached.Reset();
|
2014-03-14 14:13:41 -04:00
|
|
|
RebuildFilteredList();
|
2014-05-22 14:14:52 -04:00
|
|
|
|
2014-05-29 17:46:51 -04:00
|
|
|
if (LogVisualizer && LogVisualizer->Logs.IsValidIndex(SelectedLogIndex))
|
2014-05-22 14:14:52 -04:00
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[SelectedLogIndex];
|
2014-06-09 11:12:52 -04:00
|
|
|
if (Log.IsValid() && Log->Entries.IsValidIndex(LogEntryIndex))
|
2014-05-29 17:46:51 -04:00
|
|
|
{
|
|
|
|
|
ShowEntry(Log->Entries[LogEntryIndex].Get());
|
|
|
|
|
}
|
2014-05-22 14:14:52 -04:00
|
|
|
}
|
2014-07-07 17:19:49 -04:00
|
|
|
InvalidateCanvas();
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UWorld* SLogVisualizer::GetWorld() const
|
|
|
|
|
{
|
|
|
|
|
// TODO: This needs to be an internalized reference
|
|
|
|
|
UEditorEngine *EEngine = Cast<UEditorEngine>(GEngine);
|
|
|
|
|
if (GIsEditor && EEngine != NULL)
|
|
|
|
|
{
|
|
|
|
|
// lets use PlayWorld during PIE/Simulate and regular world from editor otherwise, to draw debug information
|
|
|
|
|
return EEngine->PlayWorld != NULL ? EEngine->PlayWorld : EEngine->GetEditorWorldContext().World();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (!GIsEditor)
|
|
|
|
|
{
|
|
|
|
|
return LogVisualizer->GetWorld();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::Tick( const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime )
|
|
|
|
|
{
|
|
|
|
|
SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);
|
|
|
|
|
|
|
|
|
|
TimeTillNextUpdate -= InDeltaTime;
|
|
|
|
|
|
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
if (World && !World->bPlayersOnly && TimeTillNextUpdate < 0 && LogVisualizer->IsRecording())
|
|
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
DoTickUpdate();
|
|
|
|
|
//DoFullUpdate();
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
2014-06-26 17:26:58 -04:00
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
if (bStickToLastData && World && !World->bPlayersOnly && LogVisualizer->IsRecording() && World->IsGameWorld() && LogVisualizer && LogVisualizer->Logs.IsValidIndex(SelectedLogIndex))
|
2014-06-26 17:26:58 -04:00
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[SelectedLogIndex];
|
|
|
|
|
if (Log->Entries.Num() > 0 && LogEntryIndex != Log->Entries.Num() - 1)
|
|
|
|
|
{
|
|
|
|
|
LogEntryIndex = Log->Entries.Num() - 1;
|
|
|
|
|
ShowEntry(Log->Entries[LogEntryIndex].Get());
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FReply SLogVisualizer::OnMouseWheel( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent )
|
|
|
|
|
{
|
|
|
|
|
if (MouseEvent.IsLeftControlDown())
|
|
|
|
|
{
|
|
|
|
|
OnSetZoomValue(FMath::Clamp(ZoomSliderValue + MouseEvent.GetWheelDelta() * 0.05f, 0.f, 1.f));
|
|
|
|
|
return FReply::Handled();
|
|
|
|
|
}
|
2014-06-26 17:26:58 -04:00
|
|
|
|
|
|
|
|
if (MouseEvent.IsLeftShiftDown())
|
|
|
|
|
{
|
|
|
|
|
OnSetHistogramWindowValue(MouseEvent.GetWheelDelta());
|
|
|
|
|
return FReply::Handled();
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
return SCompoundWidget::OnMouseWheel(MyGeometry, MouseEvent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FReply SLogVisualizer::OnKeyDown( const FGeometry& MyGeometry, const FKeyboardEvent& InKeyboardEvent )
|
|
|
|
|
{
|
|
|
|
|
const FKey Key = InKeyboardEvent.GetKey();
|
|
|
|
|
if (Key == EKeys::Left || Key == EKeys::Right)
|
|
|
|
|
{
|
|
|
|
|
int32 MoveBy = Key == EKeys::Left ? -1 : 1;
|
|
|
|
|
if (InKeyboardEvent.IsLeftControlDown())
|
|
|
|
|
{
|
|
|
|
|
MoveBy *= 10;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IncrementCurrentLogIndex(MoveBy);
|
|
|
|
|
|
|
|
|
|
return FReply::Handled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SCompoundWidget::OnKeyDown(MyGeometry, InKeyboardEvent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TSharedRef< SWidget > SLogVisualizer::MakeMainMenu()
|
|
|
|
|
{
|
|
|
|
|
FMenuBarBuilder MenuBuilder( NULL );
|
|
|
|
|
{
|
|
|
|
|
// File
|
|
|
|
|
MenuBuilder.AddPullDownMenu(
|
|
|
|
|
NSLOCTEXT("LogVisualizer", "FileMenu", "File"),
|
|
|
|
|
NSLOCTEXT("LogVisualizer", "FileMenu_ToolTip", "Open the file menu"),
|
|
|
|
|
FNewMenuDelegate::CreateSP( this, &SLogVisualizer::OpenSavedSession ) );
|
|
|
|
|
|
|
|
|
|
// Help
|
|
|
|
|
MenuBuilder.AddPullDownMenu(
|
|
|
|
|
NSLOCTEXT("LogVisualizer", "HelpMenu", "Help"),
|
|
|
|
|
NSLOCTEXT("LogVisualizer", "HelpMenu_ToolTip", "Open the help menu"),
|
|
|
|
|
FNewMenuDelegate::CreateSP( this, &SLogVisualizer::FillHelpMenu ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create the menu bar
|
|
|
|
|
TSharedRef< SWidget > MenuBarWidget = MenuBuilder.MakeWidget();
|
|
|
|
|
|
|
|
|
|
return MenuBarWidget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::FillHelpMenu(FMenuBuilder& MenuBuilder)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::OpenSavedSession(FMenuBuilder& MenuBuilder)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------//
|
|
|
|
|
// non-slate
|
|
|
|
|
//----------------------------------------------------------------------//
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::SelectionChanged(AActor* DebuggedActor, bool bIsBeingDebuggedNow)
|
|
|
|
|
{
|
|
|
|
|
if (DebuggedActor != NULL && bIsBeingDebuggedNow)
|
|
|
|
|
{
|
|
|
|
|
SelectActor(DebuggedActor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::IncrementCurrentLogIndex(int32 IncrementBy)
|
|
|
|
|
{
|
2014-05-29 17:46:51 -04:00
|
|
|
if (!LogVisualizer->Logs.IsValidIndex(SelectedLogIndex))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[SelectedLogIndex];
|
|
|
|
|
check(Log.IsValid());
|
|
|
|
|
|
|
|
|
|
int32 NewEntryIndex = FMath::Clamp(LogEntryIndex + IncrementBy, 0, Log->Entries.Num() - 1);
|
|
|
|
|
|
2014-05-22 14:14:52 -04:00
|
|
|
if (FilterListPtr.IsValid())
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
while (NewEntryIndex >= 0 && NewEntryIndex < Log->Entries.Num())
|
|
|
|
|
{
|
2014-05-29 17:46:51 -04:00
|
|
|
bool bShouldShow = false;
|
2014-05-22 14:14:52 -04:00
|
|
|
for (int32 LineIndex = 0; LineIndex < Log->Entries[NewEntryIndex]->LogLines.Num(); ++LineIndex)
|
|
|
|
|
{
|
|
|
|
|
if (FilterListPtr->IsFilterEnabled(Log->Entries[NewEntryIndex]->LogLines[LineIndex].Category.ToString(), Log->Entries[NewEntryIndex]->LogLines[LineIndex].Verbosity))
|
|
|
|
|
{
|
2014-05-29 17:46:51 -04:00
|
|
|
bShouldShow = true;
|
2014-05-22 14:14:52 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!bShouldShow)
|
2014-05-29 17:46:51 -04:00
|
|
|
{
|
|
|
|
|
for (int32 LineIndex = 0; LineIndex < Log->Entries[NewEntryIndex]->ElementsToDraw.Num(); ++LineIndex)
|
|
|
|
|
{
|
|
|
|
|
if (Log->Entries[NewEntryIndex]->ElementsToDraw[LineIndex].Category == NAME_None || FilterListPtr->IsFilterEnabled(Log->Entries[NewEntryIndex]->ElementsToDraw[LineIndex].Category.ToString(), Log->Entries[NewEntryIndex]->ElementsToDraw[LineIndex].Verbosity))
|
|
|
|
|
{
|
|
|
|
|
bShouldShow = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-10 16:45:28 -04:00
|
|
|
if (!bShouldShow)
|
|
|
|
|
{
|
|
|
|
|
for (int32 SampleIndex = 0; SampleIndex < Log->Entries[NewEntryIndex]->HistogramSamples.Num(); ++SampleIndex)
|
|
|
|
|
{
|
|
|
|
|
const FName CurrentCategory = Log->Entries[NewEntryIndex]->HistogramSamples[SampleIndex].Category;
|
2014-06-16 23:03:48 -04:00
|
|
|
const FName CurrentGraphName = Log->Entries[NewEntryIndex]->HistogramSamples[SampleIndex].GraphName;
|
|
|
|
|
const FName CurrentDataName = Log->Entries[NewEntryIndex]->HistogramSamples[SampleIndex].DataName;
|
|
|
|
|
if (CurrentCategory == NAME_None ||
|
|
|
|
|
(FilterListPtr->IsFilterEnabled(CurrentCategory.ToString(), ELogVerbosity::All) && FilterListPtr->IsFilterEnabled(CurrentGraphName.ToString(), CurrentDataName.ToString(), ELogVerbosity::All)))
|
2014-06-10 16:45:28 -04:00
|
|
|
{
|
|
|
|
|
bShouldShow = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-14 09:13:50 -04:00
|
|
|
if (!bShouldShow)
|
|
|
|
|
{
|
|
|
|
|
for (const auto CurrentData : Log->Entries[NewEntryIndex]->DataBlocks)
|
|
|
|
|
{
|
|
|
|
|
const FName CurrentCategory = CurrentData.Category;
|
|
|
|
|
const FName CurrentTagName = CurrentData.TagName;
|
|
|
|
|
if (CurrentCategory == NAME_None ||
|
|
|
|
|
(FilterListPtr->IsFilterEnabled(CurrentCategory.ToString(), ELogVerbosity::All) && FilterListPtr->IsFilterEnabled(CurrentTagName.ToString(), ELogVerbosity::All)))
|
|
|
|
|
{
|
|
|
|
|
bShouldShow = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-29 17:46:51 -04:00
|
|
|
if (bShouldShow)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NewEntryIndex += (IncrementBy > 0 ? 1 : -1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NewEntryIndex != LogEntryIndex && Log->Entries.IsValidIndex(NewEntryIndex))
|
|
|
|
|
{
|
|
|
|
|
LogEntryIndex = NewEntryIndex;
|
|
|
|
|
ShowEntry(Log->Entries[NewEntryIndex].Get());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
void SLogVisualizer::AddOrUpdateLog(int32 LogIndex, const FActorsVisLog* Log)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
if (Log->Entries.Num() == 0)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LogsList.Num() == 0)
|
|
|
|
|
{
|
|
|
|
|
Timeline->SetVisibility(EVisibility::Visible);
|
|
|
|
|
ScrollBar->SetVisibility(EVisibility::Visible);
|
|
|
|
|
ZoomSlider->SetVisibility(EVisibility::Visible);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const float StartTimestamp = Log->Entries[0]->TimeStamp;
|
|
|
|
|
const float EndTimestamp = Log->Entries[Log->Entries.Num() - 1]->TimeStamp;
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
|
|
|
|
|
int32 CurrentIndex = INDEX_NONE;
|
|
|
|
|
int32 LogListNum = LogsList.Num();
|
|
|
|
|
for (int32 ListIndex = 0; ListIndex < LogListNum; ++ListIndex)
|
|
|
|
|
{
|
2014-07-14 19:41:38 -04:00
|
|
|
if (LogsList[ListIndex]->LogIndex == LogIndex)
|
2014-07-07 17:19:49 -04:00
|
|
|
{
|
|
|
|
|
CurrentIndex = ListIndex;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add used categories
|
2014-05-22 14:14:52 -04:00
|
|
|
for (int32 EntryIndex = 0; EntryIndex < Log->Entries.Num(); ++EntryIndex)
|
|
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
if (CurrentIndex != INDEX_NONE && Log->Entries[EntryIndex]->TimeStamp <= LogsList[CurrentIndex]->EndTimestamp)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-22 14:14:52 -04:00
|
|
|
for (auto Iter(Log->Entries[EntryIndex]->LogLines.CreateConstIterator()); Iter; Iter++)
|
|
|
|
|
{
|
|
|
|
|
int32 Index = UsedCategories.Find(Iter->Category.ToString());
|
|
|
|
|
if (Index == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
Index = UsedCategories.Add(Iter->Category.ToString());
|
|
|
|
|
FilterListPtr->AddFilter(Iter->Category.ToString(), GetColorForUsedCategory(Index));
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-05-29 17:46:51 -04:00
|
|
|
|
|
|
|
|
for (auto Iter(Log->Entries[EntryIndex]->ElementsToDraw.CreateConstIterator()); Iter; Iter++)
|
|
|
|
|
{
|
|
|
|
|
const FString CategoryAsString = Iter->Category != NAME_None ? Iter->Category.ToString() : TEXT("ShapeElement");
|
|
|
|
|
|
|
|
|
|
int32 Index = UsedCategories.Find(CategoryAsString);
|
|
|
|
|
if (Index == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
Index = UsedCategories.Add(CategoryAsString);
|
|
|
|
|
FilterListPtr->AddFilter(CategoryAsString, GetColorForUsedCategory(Index));
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-06-10 16:45:28 -04:00
|
|
|
|
|
|
|
|
for (int32 SampleIndex = 0; SampleIndex < Log->Entries[EntryIndex]->HistogramSamples.Num(); ++SampleIndex)
|
|
|
|
|
{
|
|
|
|
|
const FString CategoryAsString = Log->Entries[EntryIndex]->HistogramSamples[SampleIndex].Category.ToString();
|
|
|
|
|
|
|
|
|
|
int32 Index = UsedCategories.Find(CategoryAsString);
|
|
|
|
|
if (Index == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
Index = UsedCategories.Add(CategoryAsString);
|
|
|
|
|
FilterListPtr->AddFilter(CategoryAsString, GetColorForUsedCategory(Index));
|
|
|
|
|
}
|
2014-06-16 23:03:48 -04:00
|
|
|
|
|
|
|
|
const FString GraphNameAsString = Log->Entries[EntryIndex]->HistogramSamples[SampleIndex].GraphName.ToString();
|
|
|
|
|
const FString DataNameAsString = Log->Entries[EntryIndex]->HistogramSamples[SampleIndex].DataName.ToString();
|
|
|
|
|
FilterListPtr->AddGraphFilter(GraphNameAsString, DataNameAsString, FColor::White);
|
2014-06-10 16:45:28 -04:00
|
|
|
}
|
2014-08-14 09:13:50 -04:00
|
|
|
|
|
|
|
|
for (const auto CurrentData : Log->Entries[EntryIndex]->DataBlocks)
|
|
|
|
|
{
|
|
|
|
|
int32 Index = UsedCategories.Find(CurrentData.Category.ToString());
|
|
|
|
|
if (Index == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
Index = UsedCategories.Add(CurrentData.Category.ToString());
|
|
|
|
|
FilterListPtr->AddFilter(CurrentData.Category.ToString(), GetColorForUsedCategory(Index));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-05-22 14:14:52 -04:00
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
if (CurrentIndex == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
LogsList.Add(MakeShareable(new FLogsListItem(Log->Name.ToString(), StartTimestamp, EndTimestamp, LogIndex)));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LogsList[CurrentIndex]->StartTimestamp = StartTimestamp;
|
|
|
|
|
LogsList[CurrentIndex]->LastEndTimestamp = LogsList[CurrentIndex]->EndTimestamp;
|
|
|
|
|
LogsList[CurrentIndex]->EndTimestamp= EndTimestamp;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::DoFullUpdate()
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FLogsListItem>* LogListItem = LogsList.GetTypedData();
|
|
|
|
|
for (int32 ItemIndex = 0; ItemIndex < LogsList.Num(); ++ItemIndex, ++LogListItem)
|
|
|
|
|
{
|
|
|
|
|
if (LogListItem->IsValid() && LogVisualizer->Logs.IsValidIndex((*LogListItem)->LogIndex))
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog>& Log = LogVisualizer->Logs[(*LogListItem)->LogIndex];
|
2014-06-26 17:26:58 -04:00
|
|
|
if (Log->Entries.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
LogsStartTime = FMath::Min(Log->Entries[0]->TimeStamp, LogsStartTime);
|
|
|
|
|
LogsEndTime = FMath::Max(Log->Entries[Log->Entries.Num() - 1]->TimeStamp, LogsEndTime);
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Timeline->SetMinMaxValues(LogsStartTime, LogsEndTime);
|
|
|
|
|
// set zoom max so that single even on SBarLogs has desired size on maximum zoom
|
|
|
|
|
const float WidthPx = Timeline->GetDrawingGeometry().Size.X;
|
|
|
|
|
if (WidthPx > 0)
|
|
|
|
|
{
|
|
|
|
|
const float OldMaxZoom = MaxZoom;
|
|
|
|
|
const float PxPerTimeUnit = WidthPx * SLogBar::TimeUnit / (LogsEndTime - LogsStartTime);
|
|
|
|
|
MaxZoom = SLogBar::MaxUnitSizePx / PxPerTimeUnit;
|
|
|
|
|
if (MaxZoom < MinZoom)
|
|
|
|
|
{
|
|
|
|
|
MaxZoom = MinZoom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ZoomSliderValue = MaxZoom * ZoomSliderValue / OldMaxZoom;
|
|
|
|
|
// update
|
|
|
|
|
}
|
2014-07-07 17:19:49 -04:00
|
|
|
|
|
|
|
|
LogsList.Reset();
|
|
|
|
|
OutEntriesCached.Reset();
|
2014-03-14 14:13:41 -04:00
|
|
|
RebuildFilteredList();
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
TimeTillNextUpdate = 1.f / FullUpdateFrequency;
|
|
|
|
|
InvalidateCanvas();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::DoTickUpdate()
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FLogsListItem>* LogListItem = LogsList.GetTypedData();
|
|
|
|
|
for (int32 ItemIndex = 0; ItemIndex < LogsList.Num(); ++ItemIndex, ++LogListItem)
|
|
|
|
|
{
|
|
|
|
|
if (LogListItem->IsValid() && LogVisualizer->Logs.IsValidIndex((*LogListItem)->LogIndex))
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog>& Log = LogVisualizer->Logs[(*LogListItem)->LogIndex];
|
|
|
|
|
if (Log->Entries.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
LogsStartTime = FMath::Min(Log->Entries[0]->TimeStamp, LogsStartTime);
|
|
|
|
|
LogsEndTime = FMath::Max(Log->Entries[Log->Entries.Num() - 1]->TimeStamp, LogsEndTime);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Timeline->SetMinMaxValues(LogsStartTime, LogsEndTime);
|
|
|
|
|
// set zoom max so that single even on SBarLogs has desired size on maximum zoom
|
|
|
|
|
const float WidthPx = Timeline->GetDrawingGeometry().Size.X;
|
|
|
|
|
if (WidthPx > 0)
|
|
|
|
|
{
|
|
|
|
|
const float OldMaxZoom = MaxZoom;
|
|
|
|
|
const float PxPerTimeUnit = WidthPx * SLogBar::TimeUnit / (LogsEndTime - LogsStartTime);
|
|
|
|
|
MaxZoom = SLogBar::MaxUnitSizePx / PxPerTimeUnit;
|
|
|
|
|
if (MaxZoom < MinZoom)
|
|
|
|
|
{
|
|
|
|
|
MaxZoom = MinZoom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ZoomSliderValue = MaxZoom * ZoomSliderValue / OldMaxZoom;
|
|
|
|
|
// update
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RebuildFilteredList();
|
|
|
|
|
|
|
|
|
|
TimeTillNextUpdate = 1.f / FullUpdateFrequency;
|
|
|
|
|
InvalidateCanvas();
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::OnLogAdded()
|
|
|
|
|
{
|
|
|
|
|
// take last log
|
|
|
|
|
const int32 NewLogIndex = LogVisualizer->Logs.Num()-1;
|
|
|
|
|
|
2014-05-22 14:14:52 -04:00
|
|
|
TSharedPtr<FLogsListItem> Item;
|
|
|
|
|
for (int32 Index = 0; Index < LogsList.Num(); ++Index)
|
|
|
|
|
{
|
|
|
|
|
Item = LogsList[Index];
|
|
|
|
|
TArray<TSharedPtr<FActorsVisLog> >& Logs = LogVisualizer->Logs;
|
|
|
|
|
if (Item->Name == Logs[NewLogIndex]->Name.ToString())
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!Item.IsValid())
|
|
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
AddOrUpdateLog(NewLogIndex, LogVisualizer->Logs[NewLogIndex].Get());
|
2014-05-22 14:14:52 -04:00
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
RequestFullUpdate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TSharedRef<ITableRow> SLogVisualizer::LogsListGenerateRow(TSharedPtr<FLogsListItem> InItem, const TSharedRef<STableViewBase>& OwnerTable)
|
|
|
|
|
{
|
|
|
|
|
return SNew(SLogsTableRow, OwnerTable)
|
|
|
|
|
.Item(InItem)
|
|
|
|
|
.OwnerVisualizerWidget(SharedThis(this));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::LogsListSelectionChanged(TSharedPtr<FLogsListItem> SelectedItem, ESelectInfo::Type SelectInfo)
|
|
|
|
|
{
|
|
|
|
|
//@todo find log entry closest to current time selection
|
|
|
|
|
//LogEntryIndex = INDEX_NONE;
|
|
|
|
|
const int32 NewLogIndex = SelectedItem.IsValid() ? SelectedItem->LogIndex : INDEX_NONE;
|
|
|
|
|
if (NewLogIndex != SelectedLogIndex && NewLogIndex != INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
SelectedLogIndex = NewLogIndex;
|
2014-07-22 16:23:09 -04:00
|
|
|
|
|
|
|
|
if (LogVisualizer->Logs.IsValidIndex(NewLogIndex))
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[NewLogIndex];
|
|
|
|
|
LogEntryIndex = Log->Entries.Num() - 1;
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
2014-06-10 16:45:28 -04:00
|
|
|
if (LogVisualizer->Logs.IsValidIndex(SelectedLogIndex))
|
|
|
|
|
{
|
|
|
|
|
if (USelection* SelectedActors = GEditor->GetSelectedActors())
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[SelectedLogIndex];
|
|
|
|
|
|
|
|
|
|
if (UWorld* World = GetWorld())
|
|
|
|
|
{
|
|
|
|
|
for (FConstPawnIterator Iterator = World->GetPawnIterator(); Iterator; ++Iterator)
|
|
|
|
|
{
|
|
|
|
|
if (APawn* CurrentPawn = *Iterator)
|
|
|
|
|
{
|
|
|
|
|
if (AController* CurrentController = CurrentPawn->GetController())
|
|
|
|
|
{
|
|
|
|
|
if (CurrentController->GetName() == Log->Name.ToString())
|
|
|
|
|
{
|
|
|
|
|
SelectedActors->Select(CurrentPawn);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SelectedActors->Deselect(CurrentPawn);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
//SetCurrentViewedTime(CurrentViewedTime, /*bForce=*/true);
|
|
|
|
|
|
|
|
|
|
LogsLinesWidget->RequestListRefresh();
|
2014-07-07 17:19:49 -04:00
|
|
|
InvalidateCanvas();
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TSharedRef<ITableRow> SLogVisualizer::LogEntryLinesGenerateRow(TSharedPtr<FLogEntryItem> Item, const TSharedRef<STableViewBase>& OwnerTable)
|
|
|
|
|
{
|
|
|
|
|
return SNew( STableRow< TSharedPtr<FString> >, OwnerTable )
|
|
|
|
|
[
|
|
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(FMargin(5.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.ColorAndOpacity(FSlateColor(Item->CategoryColor))
|
|
|
|
|
.Text(Item->Category)
|
|
|
|
|
]
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(FMargin(5.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.ColorAndOpacity(FSlateColor(FLinearColor::Gray))
|
|
|
|
|
.Text(FString(TEXT("(")) + FString(FOutputDevice::VerbosityToString(Item->Verbosity)) + FString(TEXT(")")))
|
|
|
|
|
]
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
.Padding(FMargin(5.0f, 0.0f))
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock)
|
|
|
|
|
.Text(Item->Line)
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-15 20:13:23 -04:00
|
|
|
void SLogVisualizer::LogEntryLineSelectionChanged(TSharedPtr<FLogEntryItem> SelectedItem, ESelectInfo::Type SelectInfo)
|
|
|
|
|
{
|
|
|
|
|
TMap<FName, FVisualLogExtensionInterface*>& AllExtensions = FVisualLog::Get().GetAllExtensions();
|
|
|
|
|
for (auto Iterator = AllExtensions.CreateIterator(); Iterator; ++Iterator)
|
|
|
|
|
{
|
|
|
|
|
FVisualLogExtensionInterface* Extension = (*Iterator).Value;
|
|
|
|
|
if (Extension != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (SelectedItem.IsValid() == true)
|
|
|
|
|
{
|
|
|
|
|
Extension->LogEntryLineSelectionChanged(SelectedItem, SelectedItem->UserData, SelectedItem->TagName);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Extension->LogEntryLineSelectionChanged(SelectedItem, 0, NAME_None);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
2014-09-15 20:13:23 -04:00
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
bool SLogVisualizer::ShouldListLog(const TSharedPtr<FActorsVisLog>& Log)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
//// Check log name filter
|
2014-07-07 17:19:49 -04:00
|
|
|
if (!Log.IsValid() || (LogNameFilterString.Len() > 0 && !Log->Name.ToString().Contains(LogNameFilterString)))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
if (!World || World->IsGameWorld())
|
|
|
|
|
{
|
|
|
|
|
return !bIgnoreTrivialLogs || Log->Entries.Num() >= 2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
static TArray<TSharedPtr<FVisLogEntry> > OutEntries;
|
|
|
|
|
GetVisibleEntries(Log, OutEntries);
|
|
|
|
|
return !bIgnoreTrivialLogs || OutEntries.Num() >= 2;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::UpdateFilterInfo()
|
|
|
|
|
{
|
|
|
|
|
// get filters
|
|
|
|
|
LogNameFilterString = LogNameFilterBox->GetText().ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::SetCurrentViewedTime(float NewTime, const bool bForce)
|
|
|
|
|
{
|
|
|
|
|
if (CurrentViewedTime == NewTime && bForce == false)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CurrentViewedTime = NewTime;
|
2014-07-07 17:19:49 -04:00
|
|
|
InvalidateCanvas();
|
|
|
|
|
}
|
2014-06-26 17:26:58 -04:00
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
void SLogVisualizer::InvalidateCanvas()
|
|
|
|
|
{
|
2014-06-26 17:26:58 -04:00
|
|
|
#if WITH_EDITOR
|
|
|
|
|
UEditorEngine *EEngine = Cast<UEditorEngine>(GEngine);
|
|
|
|
|
if (GIsEditor && EEngine != NULL)
|
|
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
for (int32 Index = 0; Index < EEngine->AllViewportClients.Num(); Index++)
|
2014-06-26 17:26:58 -04:00
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
FEditorViewportClient* ViewportClient = EEngine->AllViewportClients[Index];
|
2014-06-26 17:26:58 -04:00
|
|
|
if (ViewportClient)
|
|
|
|
|
{
|
|
|
|
|
ViewportClient->Invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::RequestShowLogEntry(TSharedPtr<FLogsListItem> Item, TSharedPtr<FVisLogEntry> LogEntry)
|
|
|
|
|
{
|
|
|
|
|
ShowLogEntry(Item, LogEntry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::ShowLogEntry(TSharedPtr<FLogsListItem> Item, TSharedPtr<FVisLogEntry> LogEntry)
|
|
|
|
|
{
|
|
|
|
|
if(LogsListWidget->GetSelectedItems().Find(Item) == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
LogsListWidget->ClearSelection();
|
|
|
|
|
LogsListWidget->SetItemSelection(Item, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LogVisualizer->Logs.IsValidIndex(SelectedLogIndex))
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[SelectedLogIndex];
|
|
|
|
|
LogEntryIndex = Log->Entries.Find(LogEntry);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LogEntryIndex = INDEX_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShowEntry(LogEntry.Get());
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-10 16:45:28 -04:00
|
|
|
FLinearColor SLogVisualizer::GetColorForUsedCategory(int32 Index)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-06-10 16:45:28 -04:00
|
|
|
if (Index >= 0 && Index < sizeof(ColorPalette) / sizeof(ColorPalette[0]))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-06-10 16:45:28 -04:00
|
|
|
return ColorPalette[Index];
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
2014-06-10 16:45:28 -04:00
|
|
|
|
2014-06-26 17:26:58 -04:00
|
|
|
static bool bReateColorList = false;
|
|
|
|
|
static FColorList StaticColor;
|
|
|
|
|
if (!bReateColorList)
|
|
|
|
|
{
|
|
|
|
|
bReateColorList = true;
|
|
|
|
|
StaticColor.CreateColorMap();
|
|
|
|
|
}
|
|
|
|
|
return StaticColor.GetFColorByIndex(Index);
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TSharedRef<ITableRow> SLogVisualizer::HandleGenerateLogStatus(TSharedPtr<FLogStatusItem> InItem, const TSharedRef<STableViewBase>& OwnerTable)
|
|
|
|
|
{
|
|
|
|
|
if (InItem->Children.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
return SNew(STableRow<TSharedPtr<FLogStatusItem> >, OwnerTable)
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock).Text(InItem->ItemText)
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FString TooltipText = FString::Printf(TEXT("%s: %s"), *InItem->ItemText, *InItem->ValueText);
|
|
|
|
|
return SNew(STableRow<TSharedPtr<FLogStatusItem> >, OwnerTable)
|
|
|
|
|
[
|
|
|
|
|
SNew(SBorder)
|
|
|
|
|
.BorderImage( FEditorStyle::GetBrush("NoBorder") )
|
|
|
|
|
.ToolTipText(TooltipText)
|
|
|
|
|
[
|
|
|
|
|
SNew(SHorizontalBox)
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock).Text(InItem->ItemText).ColorAndOpacity(FColorList::Aquamarine)
|
|
|
|
|
]
|
|
|
|
|
+SHorizontalBox::Slot()
|
|
|
|
|
.Padding(4.0f, 0, 0, 0)
|
|
|
|
|
.AutoWidth()
|
|
|
|
|
[
|
|
|
|
|
SNew(STextBlock).Text(InItem->ValueText)
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::OnLogStatusGetChildren(TSharedPtr<FLogStatusItem> InItem, TArray< TSharedPtr<FLogStatusItem> >& OutItems)
|
|
|
|
|
{
|
|
|
|
|
OutItems = InItem->Children;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::UpdateStatusItems(const FVisLogEntry* LogEntry)
|
|
|
|
|
{
|
|
|
|
|
TArray<FString> ExpandedCategories;
|
2014-06-23 10:24:03 -04:00
|
|
|
for (int32 ItemIndex = 0; ItemIndex < StatusItems.Num(); ItemIndex++)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-06-23 10:24:03 -04:00
|
|
|
const bool bIsExpanded = StatusItemsView->IsItemExpanded(StatusItems[ItemIndex]);
|
2014-03-14 14:13:41 -04:00
|
|
|
if (bIsExpanded)
|
|
|
|
|
{
|
2014-06-23 10:24:03 -04:00
|
|
|
ExpandedCategories.Add(StatusItems[ItemIndex]->ItemText);
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StatusItems.Empty();
|
|
|
|
|
|
|
|
|
|
if (LogEntry)
|
|
|
|
|
{
|
|
|
|
|
FString TimestampDesc = FString::Printf(TEXT("%.2fs"), LogEntry->TimeStamp);
|
|
|
|
|
StatusItems.Add(MakeShareable(new FLogStatusItem(LOCTEXT("VisLogTimestamp","Time").ToString(), TimestampDesc)));
|
|
|
|
|
|
2014-06-23 10:24:03 -04:00
|
|
|
for (int32 CategoryIndex = 0; CategoryIndex < LogEntry->Status.Num(); CategoryIndex++)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-06-23 10:24:03 -04:00
|
|
|
if (LogEntry->Status[CategoryIndex].Data.Num() <= 0)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-23 10:24:03 -04:00
|
|
|
TSharedRef<FLogStatusItem> StatusItem = MakeShareable(new FLogStatusItem(LogEntry->Status[CategoryIndex].Category));
|
|
|
|
|
for (int32 LineIndex = 0; LineIndex < LogEntry->Status[CategoryIndex].Data.Num(); LineIndex++)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
FString KeyDesc, ValueDesc;
|
2014-06-23 10:24:03 -04:00
|
|
|
const bool bHasValue = LogEntry->Status[CategoryIndex].GetDesc(LineIndex, KeyDesc, ValueDesc);
|
2014-03-14 14:13:41 -04:00
|
|
|
if (bHasValue)
|
|
|
|
|
{
|
|
|
|
|
StatusItem->Children.Add(MakeShareable(new FLogStatusItem(KeyDesc, ValueDesc)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StatusItems.Add(StatusItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StatusItemsView->RequestTreeRefresh();
|
|
|
|
|
|
2014-06-23 10:24:03 -04:00
|
|
|
for (int32 ItemIndex = 0; ItemIndex < StatusItems.Num(); ItemIndex++)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-06-23 10:24:03 -04:00
|
|
|
for (const FString& Category : ExpandedCategories)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-06-23 10:24:03 -04:00
|
|
|
if (StatusItems[ItemIndex]->ItemText == Category)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-06-23 10:24:03 -04:00
|
|
|
StatusItemsView->SetItemExpansion(StatusItems[ItemIndex], true);
|
2014-03-14 14:13:41 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::ShowEntry(const FVisLogEntry* LogEntry)
|
|
|
|
|
{
|
|
|
|
|
UpdateStatusItems(LogEntry);
|
|
|
|
|
LogEntryLines.Reset();
|
|
|
|
|
|
|
|
|
|
const FVisLogEntry::FLogLine* LogLine = LogEntry->LogLines.GetTypedData();
|
|
|
|
|
for (int LineIndex = 0; LineIndex < LogEntry->LogLines.Num(); ++LineIndex, ++LogLine)
|
|
|
|
|
{
|
|
|
|
|
bool bShowLine = true;
|
|
|
|
|
|
2014-05-22 14:14:52 -04:00
|
|
|
if (FilterListPtr.IsValid())
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
FString CurrentCategory = LogLine->Category.ToString();
|
|
|
|
|
bShowLine = FilterListPtr->IsFilterEnabled(CurrentCategory, LogLine->Verbosity) && (bHistogramGraphsFilter || (QuickFilterText.Len() == 0 || CurrentCategory.Find(QuickFilterText) != INDEX_NONE));
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bShowLine)
|
|
|
|
|
{
|
|
|
|
|
FLogEntryItem EntryItem;
|
|
|
|
|
EntryItem.Category = LogLine->Category.ToString();
|
|
|
|
|
|
|
|
|
|
int32 Index = UsedCategories.Find(EntryItem.Category);
|
|
|
|
|
if (Index == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
Index = UsedCategories.Add(EntryItem.Category);
|
|
|
|
|
}
|
|
|
|
|
EntryItem.CategoryColor = GetColorForUsedCategory(Index);
|
|
|
|
|
|
|
|
|
|
EntryItem.Verbosity = LogLine->Verbosity;
|
|
|
|
|
EntryItem.Line = LogLine->Line;
|
2014-09-15 20:13:23 -04:00
|
|
|
EntryItem.UserData = LogLine->UserData;
|
|
|
|
|
EntryItem.TagName = LogLine->TagName;
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
LogEntryLines.Add(MakeShareable(new FLogEntryItem(EntryItem)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SetCurrentViewedTime(LogEntry->TimeStamp);
|
|
|
|
|
|
2014-08-14 09:13:50 -04:00
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
for (auto It = FVisualLog::Get().GetAllExtensions().CreateIterator(); It; ++It)
|
|
|
|
|
{
|
|
|
|
|
(*It).Value->OnTimestampChange(LogEntry->TimeStamp, World, FLogVisualizerModule::Get()->GetHelperActor(World));
|
|
|
|
|
}
|
|
|
|
|
InvalidateCanvas();
|
2014-03-14 14:13:41 -04:00
|
|
|
LogsLinesWidget->RequestListRefresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32 SLogVisualizer::FindIndexInLogsList(const int32 LogIndex) const
|
|
|
|
|
{
|
|
|
|
|
for (int32 Index = 0; Index < LogsList.Num(); ++Index)
|
|
|
|
|
{
|
|
|
|
|
if (LogsList[Index]->LogIndex == LogIndex)
|
|
|
|
|
{
|
|
|
|
|
return Index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return INDEX_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::RebuildFilteredList()
|
|
|
|
|
{
|
|
|
|
|
// store current selection
|
|
|
|
|
TArray< TSharedPtr<FLogsListItem> > ItemsToSelect = LogsListWidget->GetSelectedItems();
|
|
|
|
|
|
|
|
|
|
for (int32 LogIndex = 0; LogIndex < LogVisualizer->Logs.Num(); ++LogIndex)
|
|
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[LogIndex];
|
2014-03-14 14:13:41 -04:00
|
|
|
if (ShouldListLog(Log))
|
|
|
|
|
{
|
|
|
|
|
// Passed filter so add to filtered results (defer sorting until end)
|
2014-07-07 17:19:49 -04:00
|
|
|
AddOrUpdateLog(LogIndex, Log.Get());
|
|
|
|
|
UpdateVisibleEntriesCache(Log, LogIndex);
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
2014-07-07 17:19:49 -04:00
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
// When underlying array changes, refresh list
|
|
|
|
|
LogsListWidget->RequestListRefresh();
|
2014-07-07 17:19:49 -04:00
|
|
|
LogsListWidget->RefreshList();
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
// redo selection
|
|
|
|
|
if (ItemsToSelect.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FLogsListItem>* Item = ItemsToSelect.GetTypedData();
|
|
|
|
|
for (int32 ItemIndex = 0; ItemIndex < ItemsToSelect.Num(); ++ItemIndex, ++Item)
|
|
|
|
|
{
|
|
|
|
|
const int32 IndexInList = FindIndexInLogsList((*Item)->LogIndex);
|
|
|
|
|
if (IndexInList != INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
LogsListWidget->SetItemSelection(LogsList[IndexInList], true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float SLogVisualizer::GetZoomValue() const
|
|
|
|
|
{
|
|
|
|
|
return ZoomSliderValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::OnSetZoomValue( float NewValue )
|
|
|
|
|
{
|
|
|
|
|
const float PrevZoom = GetZoom();
|
|
|
|
|
const float PrevVisibleRange = 1.0f / PrevZoom;
|
|
|
|
|
|
|
|
|
|
ZoomSliderValue = NewValue;
|
|
|
|
|
const float Zoom = GetZoom();
|
|
|
|
|
|
|
|
|
|
const float MaxOffset = GetMaxScrollOffsetFraction();
|
|
|
|
|
const float MaxGraphOffset = GetMaxGraphOffset();
|
|
|
|
|
|
|
|
|
|
const float ViewedTimeSpan = (LogsEndTime - LogsStartTime) / Zoom;
|
|
|
|
|
const float ScrollOffsetFraction = FMath::Clamp((CurrentViewedTime - LogsStartTime - ViewedTimeSpan/2) / (LogsEndTime - LogsStartTime), 0.0f, MaxOffset);
|
|
|
|
|
|
|
|
|
|
const float WidthPx = Timeline->GetDrawingGeometry().Size.X;
|
|
|
|
|
const float GraphOffset = MaxOffset > 0 ? (ScrollOffsetFraction / MaxOffset) * MaxGraphOffset : 0.f;
|
|
|
|
|
|
|
|
|
|
ZoomChangedNotify.Broadcast(Zoom, -GraphOffset);
|
|
|
|
|
|
|
|
|
|
ScrollBar->SetState( ScrollOffsetFraction, 1.0f / Zoom );
|
|
|
|
|
|
|
|
|
|
Timeline->SetZoom( Zoom );
|
|
|
|
|
Timeline->SetOffset( -GraphOffset );
|
|
|
|
|
|
|
|
|
|
ScrollbarOffset = -GraphOffset;
|
2014-07-07 17:19:49 -04:00
|
|
|
InvalidateCanvas();
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::OnZoomScrolled(float InScrollOffsetFraction)
|
|
|
|
|
{
|
|
|
|
|
if( ZoomSliderValue > 0.0f )
|
|
|
|
|
{
|
|
|
|
|
const float MaxOffset = GetMaxScrollOffsetFraction();
|
|
|
|
|
const float MaxGraphOffset = GetMaxGraphOffset();
|
|
|
|
|
InScrollOffsetFraction = FMath::Clamp( InScrollOffsetFraction, 0.0f, MaxOffset );
|
|
|
|
|
float GraphOffset = -( InScrollOffsetFraction / MaxOffset ) * MaxGraphOffset;
|
|
|
|
|
|
|
|
|
|
ScrollBar->SetState( InScrollOffsetFraction, 1.0f / GetZoom() );
|
|
|
|
|
|
|
|
|
|
ZoomChangedNotify.Broadcast(GetZoom(), GraphOffset);
|
|
|
|
|
|
|
|
|
|
Timeline->SetOffset( GraphOffset );
|
|
|
|
|
|
|
|
|
|
ScrollbarOffset = GraphOffset;
|
2014-07-07 17:19:49 -04:00
|
|
|
InvalidateCanvas();
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-26 17:26:58 -04:00
|
|
|
void SLogVisualizer::OnSetHistogramWindowValue(float NewValue)
|
|
|
|
|
{
|
|
|
|
|
HistogramPreviewWindow = FMath::Clamp(HistogramPreviewWindow + NewValue * 1.0f, 0.0f, 100.0f);
|
|
|
|
|
HistogramWindowChangedNotify.Broadcast(HistogramPreviewWindow);
|
2014-07-07 17:19:49 -04:00
|
|
|
InvalidateCanvas();
|
2014-06-26 17:26:58 -04:00
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
void SLogVisualizer::OnDrawLogEntriesPathChanged(ESlateCheckBoxState::Type NewState)
|
|
|
|
|
{
|
|
|
|
|
bDrawLogEntriesPath = (NewState == ESlateCheckBoxState::Checked);
|
2014-07-07 17:19:49 -04:00
|
|
|
InvalidateCanvas();
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ESlateCheckBoxState::Type SLogVisualizer::GetDrawLogEntriesPathState() const
|
|
|
|
|
{
|
|
|
|
|
return bDrawLogEntriesPath ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::OnIgnoreTrivialLogs(ESlateCheckBoxState::Type NewState)
|
|
|
|
|
{
|
|
|
|
|
bIgnoreTrivialLogs = (NewState == ESlateCheckBoxState::Checked);
|
|
|
|
|
DoFullUpdate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ESlateCheckBoxState::Type SLogVisualizer::GetIgnoreTrivialLogs() const
|
|
|
|
|
{
|
|
|
|
|
return bIgnoreTrivialLogs ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-26 17:26:58 -04:00
|
|
|
void SLogVisualizer::OnChangeHistogramLabelLocation(ESlateCheckBoxState::Type NewState)
|
|
|
|
|
{
|
|
|
|
|
bShowHistogramLabelsOutside = (NewState == ESlateCheckBoxState::Checked);
|
2014-07-07 17:19:49 -04:00
|
|
|
InvalidateCanvas();
|
2014-06-26 17:26:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ESlateCheckBoxState::Type SLogVisualizer::GetHistogramLabelLocation() const
|
|
|
|
|
{
|
|
|
|
|
return bShowHistogramLabelsOutside ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::OnStickToLastData(ESlateCheckBoxState::Type NewState)
|
|
|
|
|
{
|
|
|
|
|
bStickToLastData = (NewState == ESlateCheckBoxState::Checked);
|
2014-07-07 17:19:49 -04:00
|
|
|
InvalidateCanvas();
|
2014-06-26 17:26:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ESlateCheckBoxState::Type SLogVisualizer::GetStickToLastData() const
|
|
|
|
|
{
|
|
|
|
|
return bStickToLastData ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
void SLogVisualizer::OnToggleCamera(ESlateCheckBoxState::Type NewState)
|
|
|
|
|
{
|
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
if (ALogVisualizerCameraController::IsEnabled(World))
|
|
|
|
|
{
|
|
|
|
|
ALogVisualizerCameraController::DisableCamera(World);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ALogVisualizerCameraController::EnableCamera(World);
|
|
|
|
|
}
|
2014-07-07 17:19:49 -04:00
|
|
|
InvalidateCanvas();
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ESlateCheckBoxState::Type SLogVisualizer::GetToggleCameraState() const
|
|
|
|
|
{
|
|
|
|
|
return ALogVisualizerCameraController::IsEnabled(GetWorld())
|
|
|
|
|
? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
void SLogVisualizer::OnOffsetDataSets(ESlateCheckBoxState::Type NewState)
|
|
|
|
|
{
|
|
|
|
|
bOffsetDataSet = (NewState == ESlateCheckBoxState::Checked);
|
|
|
|
|
InvalidateCanvas();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ESlateCheckBoxState::Type SLogVisualizer::GetOffsetDataSets() const
|
|
|
|
|
{
|
|
|
|
|
return bOffsetDataSet ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::OnHistogramGraphsFilter(ESlateCheckBoxState::Type NewState)
|
|
|
|
|
{
|
|
|
|
|
bHistogramGraphsFilter = (NewState == ESlateCheckBoxState::Checked);
|
|
|
|
|
QuickFilterText.Empty();
|
|
|
|
|
QuickFilterBox->SetText(FText::FromString(QuickFilterText));
|
|
|
|
|
|
|
|
|
|
LogsList.Reset();
|
|
|
|
|
OutEntriesCached.Reset();
|
|
|
|
|
RebuildFilteredList();
|
|
|
|
|
|
|
|
|
|
if (LogVisualizer && LogVisualizer->Logs.IsValidIndex(SelectedLogIndex))
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[SelectedLogIndex];
|
|
|
|
|
if (Log.IsValid() && Log->Entries.IsValidIndex(LogEntryIndex))
|
|
|
|
|
{
|
|
|
|
|
ShowEntry(Log->Entries[LogEntryIndex].Get());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ESlateCheckBoxState::Type SLogVisualizer::GetHistogramGraphsFilter() const
|
|
|
|
|
{
|
|
|
|
|
return bHistogramGraphsFilter ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
//----------------------------------------------------------------------//
|
|
|
|
|
// Drawing
|
|
|
|
|
//----------------------------------------------------------------------//
|
|
|
|
|
void SLogVisualizer::DrawOnCanvas(UCanvas* Canvas, APlayerController*)
|
|
|
|
|
{
|
2014-05-14 15:00:32 -04:00
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
if (World != NULL && LogVisualizer->Logs.IsValidIndex(SelectedLogIndex))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[SelectedLogIndex];
|
|
|
|
|
const TArray<TSharedPtr<FVisLogEntry> >& Entries = Log->Entries;
|
|
|
|
|
|
|
|
|
|
if (bDrawLogEntriesPath)
|
|
|
|
|
{
|
|
|
|
|
const TSharedPtr<FVisLogEntry>* Entry = Entries.GetTypedData();
|
|
|
|
|
FVector Location = (*Entry)->Location;
|
|
|
|
|
++Entry;
|
|
|
|
|
|
|
|
|
|
for (int32 Index = 1; Index < Entries.Num(); ++Index, ++Entry)
|
|
|
|
|
{
|
|
|
|
|
const FVector CurrentLocation = (*Entry)->Location;
|
2014-05-14 15:00:32 -04:00
|
|
|
DrawDebugLine(World, Location, CurrentLocation, FColor(160, 160, 240));
|
2014-03-14 14:13:41 -04:00
|
|
|
Location = CurrentLocation;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Entries.IsValidIndex(LogEntryIndex))
|
|
|
|
|
{
|
|
|
|
|
// draw all additional data stored in current entry
|
|
|
|
|
const TSharedPtr<FVisLogEntry>& Entry = Entries[LogEntryIndex];
|
|
|
|
|
|
|
|
|
|
// mark current location
|
2014-05-14 15:00:32 -04:00
|
|
|
DrawDebugCone(World, Entry->Location, /*Direction*/FVector(0, 0, 1), /*Length*/200.f
|
2014-03-14 14:13:41 -04:00
|
|
|
, PI/64, PI/64, /*NumSides*/16, FColor::Red);
|
|
|
|
|
|
|
|
|
|
UFont* Font = GEngine->GetSmallFont();
|
|
|
|
|
FCanvasTextItem TextItem( FVector2D::ZeroVector, FText::GetEmpty(), Font, FLinearColor::White );
|
|
|
|
|
const FString TimeStampString = FString::Printf(TEXT("%.2f"), Entry->TimeStamp);
|
|
|
|
|
const FVector EntryScreenLoc = Canvas->Project(Entry->Location);
|
|
|
|
|
Canvas->SetDrawColor(FColor::Black);
|
|
|
|
|
Canvas->DrawText(Font, TimeStampString,EntryScreenLoc.X+1, EntryScreenLoc.Y+1);
|
|
|
|
|
Canvas->SetDrawColor(FColor::White);
|
|
|
|
|
Canvas->DrawText(Font, TimeStampString, EntryScreenLoc.X, EntryScreenLoc.Y);
|
|
|
|
|
|
2014-06-10 16:45:28 -04:00
|
|
|
//let's draw histogram data
|
2014-06-26 17:26:58 -04:00
|
|
|
|
2014-06-10 16:45:28 -04:00
|
|
|
struct FGraphLineData
|
|
|
|
|
{
|
|
|
|
|
FName DataName;
|
|
|
|
|
TArray<FVector2D> Samples;
|
|
|
|
|
};
|
|
|
|
|
typedef TMap<FName, FGraphLineData > FGraphLines;
|
|
|
|
|
|
|
|
|
|
struct FGraphData
|
|
|
|
|
{
|
|
|
|
|
FGraphData() : Min(FVector2D(FLT_MAX, FLT_MAX)), Max(FVector2D(FLT_MIN, FLT_MIN)) {}
|
|
|
|
|
|
|
|
|
|
FVector2D Min, Max;
|
2014-07-07 17:19:49 -04:00
|
|
|
TMap<FName, FGraphLineData> GraphLines;
|
2014-06-10 16:45:28 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TMap<FName, FGraphData> CollectedGraphs;
|
|
|
|
|
|
2014-06-26 17:26:58 -04:00
|
|
|
float MinTime, MaxTime;
|
|
|
|
|
Timeline->GetMinMaxValues(MinTime, MaxTime);
|
|
|
|
|
|
|
|
|
|
const float StartTime = Timeline->GetOffset() + MinTime;
|
|
|
|
|
const float EndTime = StartTime + (MaxTime - MinTime) / this->GetZoom();
|
|
|
|
|
const float WindowHalfWidth = (EndTime - StartTime) * HistogramPreviewWindow * 0.01 * 0.5;
|
|
|
|
|
const FVector2D TimeStampWindow(Entry->TimeStamp - WindowHalfWidth, Entry->TimeStamp + WindowHalfWidth);
|
|
|
|
|
|
|
|
|
|
int32 ColorIndex = 0;
|
2014-06-10 16:45:28 -04:00
|
|
|
for (int32 EntryIndex = 0; EntryIndex < Entries.Num(); ++EntryIndex)
|
|
|
|
|
{
|
|
|
|
|
const TSharedPtr<FVisLogEntry>& CurrentEntry = Entries[EntryIndex];
|
2014-06-26 17:26:58 -04:00
|
|
|
if (HistogramPreviewWindow <= 0)
|
2014-06-10 16:45:28 -04:00
|
|
|
{
|
2014-06-26 17:26:58 -04:00
|
|
|
if (CurrentEntry->TimeStamp > Entry->TimeStamp)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-06-10 16:45:28 -04:00
|
|
|
}
|
2014-06-26 17:26:58 -04:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (CurrentEntry->TimeStamp < TimeStampWindow.X)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2014-06-10 16:45:28 -04:00
|
|
|
|
2014-06-26 17:26:58 -04:00
|
|
|
if (CurrentEntry->TimeStamp > TimeStampWindow.Y)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-06-10 16:45:28 -04:00
|
|
|
const int32 SamplesNum = CurrentEntry->HistogramSamples.Num();
|
|
|
|
|
for (int32 SampleIndex = 0; SampleIndex < SamplesNum; ++SampleIndex)
|
|
|
|
|
{
|
|
|
|
|
FVisLogEntry::FHistogramSample CurrentSample = CurrentEntry->HistogramSamples[SampleIndex];
|
2014-07-07 17:19:49 -04:00
|
|
|
|
|
|
|
|
const FName CurrentCategory = CurrentSample.Category;
|
|
|
|
|
const FName CurrentGraphName = CurrentSample.GraphName;
|
|
|
|
|
const FName CurrentDataName = CurrentSample.DataName;
|
|
|
|
|
|
|
|
|
|
const bool bIsValidByFilter = FilterListPtr->IsFilterEnabled(CurrentSample.GraphName.ToString(), CurrentSample.DataName.ToString(), ELogVerbosity::All);
|
|
|
|
|
const bool bCurrentDataNamePassed = !bHistogramGraphsFilter || (QuickFilterText.Len() == 0 || CurrentDataName.ToString().Find(QuickFilterText) != INDEX_NONE);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!FilterListPtr.IsValid() || (bIsValidByFilter /*&& bCurrentCategoryPassed*/ && bCurrentDataNamePassed))
|
2014-06-10 16:45:28 -04:00
|
|
|
{
|
|
|
|
|
FGraphData &GraphData = CollectedGraphs.FindOrAdd(CurrentSample.GraphName);
|
2014-06-16 23:03:48 -04:00
|
|
|
FGraphLineData &LineData = GraphData.GraphLines.FindOrAdd(CurrentSample.DataName);
|
2014-06-10 16:45:28 -04:00
|
|
|
LineData.DataName = CurrentSample.DataName;
|
|
|
|
|
LineData.Samples.Add( CurrentSample.SampleValue );
|
|
|
|
|
|
|
|
|
|
GraphData.Min.X = FMath::Min(GraphData.Min.X, CurrentSample.SampleValue.X);
|
|
|
|
|
GraphData.Min.Y = FMath::Min(GraphData.Min.Y, CurrentSample.SampleValue.Y);
|
|
|
|
|
|
|
|
|
|
GraphData.Max.X = FMath::Max(GraphData.Max.X, CurrentSample.SampleValue.X);
|
|
|
|
|
GraphData.Max.Y = FMath::Max(GraphData.Max.Y, CurrentSample.SampleValue.Y);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
const float GoldenRatioConjugate = 0.618033988749895f;
|
2014-06-10 16:45:28 -04:00
|
|
|
int32 GraphIndex = 0;
|
|
|
|
|
if (CollectedGraphs.Num() > 0)
|
|
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
const int NumberOfGraphs = CollectedGraphs.Num();
|
|
|
|
|
const int32 NumberOfColumns = FMath::CeilToInt(FMath::Sqrt(NumberOfGraphs));
|
|
|
|
|
int32 NumberOfRows = FMath::FloorToInt(NumberOfGraphs / NumberOfColumns);
|
|
|
|
|
if (NumberOfGraphs - NumberOfRows * NumberOfColumns > 0)
|
|
|
|
|
{
|
|
|
|
|
NumberOfRows += 1;
|
|
|
|
|
}
|
2014-06-26 17:26:58 -04:00
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
const int32 MaxNumberOfGraphs = FMath::Max(NumberOfRows, NumberOfColumns);
|
|
|
|
|
const float GraphWidth = 0.8f / NumberOfColumns;
|
|
|
|
|
const float GraphHeight = 0.8f / NumberOfRows;
|
|
|
|
|
|
|
|
|
|
const float XGraphSpacing = 0.2f / (MaxNumberOfGraphs + 1);
|
|
|
|
|
const float YGraphSpacing = 0.2f / (MaxNumberOfGraphs + 1);
|
|
|
|
|
|
|
|
|
|
const float StartX = XGraphSpacing;
|
|
|
|
|
float StartY = 0.5 + (0.5 * NumberOfRows - 1) * (GraphHeight + YGraphSpacing);
|
|
|
|
|
|
|
|
|
|
float CurrentX = StartX;
|
|
|
|
|
float CurrentY = StartY;
|
|
|
|
|
int32 GraphIndex = 0;
|
|
|
|
|
int32 CurrentColumn = 0;
|
|
|
|
|
int32 CurrentRow = 0;
|
|
|
|
|
for (auto It(CollectedGraphs.CreateIterator()); It; ++It)
|
2014-06-10 16:45:28 -04:00
|
|
|
{
|
|
|
|
|
TWeakObjectPtr<UReporterGraph> HistogramGraph = Canvas->GetReporterGraph();
|
|
|
|
|
if (!HistogramGraph.IsValid())
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
HistogramGraph->SetNumGraphLines(It->Value.GraphLines.Num());
|
|
|
|
|
int32 LineIndex = 0;
|
2014-06-26 17:26:58 -04:00
|
|
|
UFont* Font = GEngine->GetSmallFont();
|
|
|
|
|
int32 MaxStringSize = 0;
|
|
|
|
|
float Hue = 0;// StartGoldenRatio[GraphIndex++];
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
auto& CategoriesForGraph = UsedGraphCategories.FindOrAdd(It->Key.ToString());
|
|
|
|
|
|
|
|
|
|
It->Value.GraphLines.KeySort(TLess<FName>());
|
2014-06-10 16:45:28 -04:00
|
|
|
for (auto LinesIt(It->Value.GraphLines.CreateConstIterator()); LinesIt; ++LinesIt)
|
|
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
const FString DataName = LinesIt->Value.DataName.ToString();
|
|
|
|
|
int32 CategoryIndex = CategoriesForGraph.Find(DataName);
|
|
|
|
|
if (CategoryIndex == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
CategoryIndex = CategoriesForGraph.AddUnique(DataName);
|
|
|
|
|
}
|
|
|
|
|
Hue = CategoryIndex * GoldenRatioConjugate;
|
2014-06-26 17:26:58 -04:00
|
|
|
if (Hue > 1)
|
2014-06-10 16:45:28 -04:00
|
|
|
{
|
2014-06-26 17:26:58 -04:00
|
|
|
Hue -= FMath::FloorToFloat(Hue);
|
2014-06-10 16:45:28 -04:00
|
|
|
}
|
2014-07-07 17:19:49 -04:00
|
|
|
|
2014-06-26 17:26:58 -04:00
|
|
|
HistogramGraph->GetGraphLine(LineIndex)->Color = FLinearColor::FGetHSV(Hue * 255, 0, 244);
|
2014-07-07 17:19:49 -04:00
|
|
|
HistogramGraph->GetGraphLine(LineIndex)->LineName = DataName;
|
2014-06-10 16:45:28 -04:00
|
|
|
HistogramGraph->GetGraphLine(LineIndex)->Data.Append(LinesIt->Value.Samples);
|
2014-06-26 17:26:58 -04:00
|
|
|
|
|
|
|
|
int32 DummyY, CurrentX;
|
|
|
|
|
StringSize(Font, CurrentX, DummyY, *LinesIt->Value.DataName.ToString());
|
|
|
|
|
MaxStringSize = CurrentX > MaxStringSize ? CurrentX : MaxStringSize;
|
|
|
|
|
|
2014-06-10 16:45:28 -04:00
|
|
|
++LineIndex;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-26 17:26:58 -04:00
|
|
|
FVector2D GraphSpaceSize;
|
|
|
|
|
GraphSpaceSize.Y = GraphSpaceSize.X = 0.8f / CollectedGraphs.Num();
|
2014-06-10 16:45:28 -04:00
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
HistogramGraph->SetGraphScreenSize(CurrentX, CurrentX + GraphWidth, CurrentY, CurrentY + GraphHeight);
|
|
|
|
|
CurrentX += GraphWidth + XGraphSpacing;
|
2014-06-26 17:26:58 -04:00
|
|
|
HistogramGraph->SetAxesMinMax(FVector2D(TimeStampWindow.X, It->Value.Min.Y), FVector2D(TimeStampWindow.Y, It->Value.Max.Y));
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
HistogramGraph->SetNumThresholds(0);
|
2014-06-10 16:45:28 -04:00
|
|
|
HistogramGraph->SetStyles(EGraphAxisStyle::Grid, EGraphDataStyle::Lines);
|
2014-06-26 17:26:58 -04:00
|
|
|
HistogramGraph->SetBackgroundColor( FColor(0,0,0, 200) );
|
|
|
|
|
HistogramGraph->SetLegendPosition(bShowHistogramLabelsOutside ? ELegendPosition::Outside : ELegendPosition::Inside);
|
2014-07-07 17:19:49 -04:00
|
|
|
HistogramGraph->OffsetDataSets(bOffsetDataSet);
|
2014-06-10 16:45:28 -04:00
|
|
|
HistogramGraph->bVisible = true;
|
|
|
|
|
HistogramGraph->Draw(Canvas);
|
|
|
|
|
|
|
|
|
|
++GraphIndex;
|
2014-07-07 17:19:49 -04:00
|
|
|
|
|
|
|
|
if (++CurrentColumn >= NumberOfColumns)
|
|
|
|
|
{
|
|
|
|
|
CurrentColumn = 0;
|
|
|
|
|
CurrentRow++;
|
|
|
|
|
|
|
|
|
|
CurrentX = StartX;
|
|
|
|
|
CurrentY -= GraphHeight + YGraphSpacing;
|
|
|
|
|
}
|
2014-06-10 16:45:28 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-14 09:13:50 -04:00
|
|
|
AActor* HelperActor = FLogVisualizerModule::Get()->GetHelperActor(World);
|
|
|
|
|
for (const auto CurrentData : Entry->DataBlocks)
|
|
|
|
|
{
|
|
|
|
|
const FName TagName = CurrentData.TagName;
|
|
|
|
|
const bool bIsValidByFilter = FilterListPtr->IsFilterEnabled(CurrentData.Category.ToString(), ELogVerbosity::All) && FilterListPtr->IsFilterEnabled(CurrentData.TagName.ToString(), ELogVerbosity::All);
|
2014-08-21 06:12:59 -04:00
|
|
|
FVisualLogExtensionInterface* Extension = FVisualLog::Get().GetExtensionForTag(TagName);
|
|
|
|
|
if (!Extension)
|
2014-08-14 09:13:50 -04:00
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 06:12:59 -04:00
|
|
|
if (!bIsValidByFilter)
|
|
|
|
|
{
|
|
|
|
|
Extension->DisableDrawingForData(World, Canvas, HelperActor, TagName, CurrentData, Entry->TimeStamp);
|
|
|
|
|
}
|
|
|
|
|
else
|
2014-08-14 09:13:50 -04:00
|
|
|
{
|
|
|
|
|
Extension->DrawData(World, Canvas, HelperActor, TagName, CurrentData, Entry->TimeStamp);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-06-10 16:45:28 -04:00
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
const FVisLogEntry::FElementToDraw* ElementToDraw = Entry->ElementsToDraw.GetTypedData();
|
|
|
|
|
const int32 ElementsCount = Entry->ElementsToDraw.Num();
|
|
|
|
|
|
|
|
|
|
for (int32 ElementIndex = 0; ElementIndex < ElementsCount; ++ElementIndex, ++ElementToDraw)
|
|
|
|
|
{
|
2014-05-29 17:46:51 -04:00
|
|
|
if (FilterListPtr.IsValid() && !FilterListPtr->IsFilterEnabled(ElementToDraw->Category.ToString(), ElementToDraw->Verbosity))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
const FColor Color = ElementToDraw->GetFColor();
|
|
|
|
|
Canvas->SetDrawColor(Color);
|
|
|
|
|
|
|
|
|
|
switch(ElementToDraw->GetType())
|
|
|
|
|
{
|
|
|
|
|
case FVisLogEntry::FElementToDraw::SinglePoint:
|
|
|
|
|
{
|
|
|
|
|
const float Radius = float(ElementToDraw->Radius);
|
|
|
|
|
const bool bDrawLabel = ElementToDraw->Description.IsEmpty() == false;
|
|
|
|
|
const FVector* Location = ElementToDraw->Points.GetTypedData();
|
|
|
|
|
for (int32 Index = 0; Index < ElementToDraw->Points.Num(); ++Index, ++Location)
|
|
|
|
|
{
|
2014-05-14 15:00:32 -04:00
|
|
|
DrawDebugSphere(World, *Location, Radius, 16, Color);
|
2014-03-14 14:13:41 -04:00
|
|
|
if (bDrawLabel)
|
|
|
|
|
{
|
|
|
|
|
const FVector ScreenLoc = Canvas->Project(*Location);
|
|
|
|
|
Canvas->DrawText(Font, FString::Printf(TEXT("%s_%d"), *ElementToDraw->Description, Index), ScreenLoc.X, ScreenLoc.Y);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case FVisLogEntry::FElementToDraw::Segment:
|
|
|
|
|
{
|
|
|
|
|
const float Thickness = float(ElementToDraw->Thicknes);
|
|
|
|
|
const bool bDrawLabel = ElementToDraw->Description.IsEmpty() == false && ElementToDraw->Points.Num() > 2;
|
|
|
|
|
const FVector* Location = ElementToDraw->Points.GetTypedData();
|
|
|
|
|
for (int32 Index = 0; Index + 1 < ElementToDraw->Points.Num(); Index += 2, Location += 2)
|
|
|
|
|
{
|
2014-05-14 15:00:32 -04:00
|
|
|
DrawDebugLine(World, *Location, *(Location + 1), Color
|
2014-03-14 14:13:41 -04:00
|
|
|
, /*bPersistentLines*/false, /*LifeTime*/-1
|
|
|
|
|
, /*DepthPriority*/0, Thickness);
|
|
|
|
|
|
|
|
|
|
if (bDrawLabel)
|
|
|
|
|
{
|
|
|
|
|
const FString PrintString = FString::Printf(TEXT("%s_%d"), *ElementToDraw->Description, Index);
|
|
|
|
|
float TextXL, TextYL;
|
|
|
|
|
Canvas->StrLen(Font, PrintString, TextXL, TextYL);
|
|
|
|
|
const FVector ScreenLoc = Canvas->Project(*Location + (*(Location+1)-*Location)/2);
|
|
|
|
|
Canvas->DrawText(Font, *PrintString, ScreenLoc.X - TextXL/2.0f, ScreenLoc.Y - TextYL/2.0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ElementToDraw->Description.IsEmpty() == false)
|
|
|
|
|
{
|
|
|
|
|
float TextXL, TextYL;
|
|
|
|
|
Canvas->StrLen(Font, ElementToDraw->Description, TextXL, TextYL);
|
|
|
|
|
const FVector ScreenLoc = Canvas->Project(ElementToDraw->Points[0]
|
|
|
|
|
+ (ElementToDraw->Points[1] - ElementToDraw->Points[0])/2);
|
|
|
|
|
Canvas->DrawText(Font, *ElementToDraw->Description, ScreenLoc.X - TextXL/2.0f, ScreenLoc.Y - TextYL/2.0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case FVisLogEntry::FElementToDraw::Path:
|
|
|
|
|
{
|
|
|
|
|
const float Thickness = float(ElementToDraw->Thicknes);
|
|
|
|
|
FVector Location = ElementToDraw->Points[0];
|
|
|
|
|
for (int32 Index = 1; Index < ElementToDraw->Points.Num(); ++Index)
|
|
|
|
|
{
|
|
|
|
|
const FVector CurrentLocation = ElementToDraw->Points[Index];
|
2014-05-14 15:00:32 -04:00
|
|
|
DrawDebugLine(World, Location, CurrentLocation, Color
|
2014-03-14 14:13:41 -04:00
|
|
|
, /*bPersistentLines*/false, /*LifeTime*/-1
|
|
|
|
|
, /*DepthPriority*/0, Thickness);
|
|
|
|
|
Location = CurrentLocation;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-05-14 15:00:32 -04:00
|
|
|
break;
|
2014-03-14 14:13:41 -04:00
|
|
|
case FVisLogEntry::FElementToDraw::Box:
|
|
|
|
|
{
|
|
|
|
|
const float Thickness = float(ElementToDraw->Thicknes);
|
|
|
|
|
const bool bDrawLabel = ElementToDraw->Description.IsEmpty() == false && ElementToDraw->Points.Num() > 2;
|
|
|
|
|
const FVector* BoxExtent = ElementToDraw->Points.GetTypedData();
|
|
|
|
|
for (int32 Index = 0; Index + 1 < ElementToDraw->Points.Num(); Index += 2, BoxExtent += 2)
|
|
|
|
|
{
|
|
|
|
|
FBox Box(*BoxExtent, *(BoxExtent + 1));
|
2014-05-14 15:00:32 -04:00
|
|
|
DrawDebugBox(World, Box.GetCenter(), Box.GetExtent(), Color
|
2014-03-14 14:13:41 -04:00
|
|
|
, /*bPersistentLines*/false, /*LifeTime*/-1
|
|
|
|
|
, /*DepthPriority*/0/*, Thickness*/);
|
|
|
|
|
|
|
|
|
|
if (bDrawLabel)
|
|
|
|
|
{
|
|
|
|
|
const FString PrintString = FString::Printf(TEXT("%s_%d"), *ElementToDraw->Description, Index);
|
|
|
|
|
float TextXL, TextYL;
|
|
|
|
|
Canvas->StrLen(Font, PrintString, TextXL, TextYL);
|
|
|
|
|
const FVector ScreenLoc = Canvas->Project(Box.GetCenter());
|
|
|
|
|
Canvas->DrawText(Font, *PrintString, ScreenLoc.X - TextXL/2.0f, ScreenLoc.Y - TextYL/2.0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ElementToDraw->Description.IsEmpty() == false)
|
|
|
|
|
{
|
|
|
|
|
float TextXL, TextYL;
|
|
|
|
|
Canvas->StrLen(Font, ElementToDraw->Description, TextXL, TextYL);
|
|
|
|
|
const FVector ScreenLoc = Canvas->Project(ElementToDraw->Points[0]
|
|
|
|
|
+ (ElementToDraw->Points[1] - ElementToDraw->Points[0])/2);
|
|
|
|
|
Canvas->DrawText(Font, *ElementToDraw->Description, ScreenLoc.X - TextXL/2.0f, ScreenLoc.Y - TextYL/2.0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
const FSlateBrush* SLogVisualizer::GetRecordButtonBrush() const
|
|
|
|
|
{
|
|
|
|
|
if(LogVisualizer->IsRecording())
|
|
|
|
|
{
|
|
|
|
|
// If recording, show stop button
|
|
|
|
|
return FEditorStyle::GetBrush("LogVisualizer.Stop");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// If stopped, show record button
|
|
|
|
|
return FEditorStyle::GetBrush("LogVisualizer.Record");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FString SLogVisualizer::GetStatusText() const
|
|
|
|
|
{
|
|
|
|
|
return TEXT("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ESlateCheckBoxState::Type SLogVisualizer::GetPauseState() const
|
|
|
|
|
{
|
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
return (World != NULL && (World->bPlayersOnly || World->bPlayersOnlyPending)) ? ESlateCheckBoxState::Checked : ESlateCheckBoxState::Unchecked;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FReply SLogVisualizer::OnRecordButtonClicked()
|
|
|
|
|
{
|
|
|
|
|
// Toggle recording state
|
|
|
|
|
LogVisualizer->SetIsRecording(!LogVisualizer->IsRecording());
|
|
|
|
|
|
|
|
|
|
return FReply::Handled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FReply SLogVisualizer::OnLoad()
|
|
|
|
|
{
|
|
|
|
|
TArray<FString> OpenFilenames;
|
|
|
|
|
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
|
|
|
|
|
bool bOpened = false;
|
|
|
|
|
if ( DesktopPlatform )
|
|
|
|
|
{
|
|
|
|
|
void* ParentWindowWindowHandle = NULL;
|
|
|
|
|
|
|
|
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame"));
|
|
|
|
|
const TSharedPtr<SWindow>& MainFrameParentWindow = MainFrameModule.GetParentWindow();
|
|
|
|
|
if ( MainFrameParentWindow.IsValid() && MainFrameParentWindow->GetNativeWindow().IsValid() )
|
|
|
|
|
{
|
|
|
|
|
ParentWindowWindowHandle = MainFrameParentWindow->GetNativeWindow()->GetOSWindowHandle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bOpened = DesktopPlatform->OpenFileDialog(
|
|
|
|
|
ParentWindowWindowHandle,
|
|
|
|
|
LOCTEXT("OpenProjectBrowseTitle", "Open Project").ToString(),
|
|
|
|
|
LastBrowsePath,
|
|
|
|
|
TEXT(""),
|
|
|
|
|
LogVisualizer::FileTypes,
|
|
|
|
|
EFileDialogFlags::None,
|
|
|
|
|
OpenFilenames
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( bOpened )
|
|
|
|
|
{
|
|
|
|
|
if ( OpenFilenames.Num() > 0 )
|
|
|
|
|
{
|
|
|
|
|
LastBrowsePath = OpenFilenames[0];
|
|
|
|
|
LoadFiles(OpenFilenames);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-23 19:29:53 -04:00
|
|
|
DoFullUpdate();
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
return FReply::Handled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FReply SLogVisualizer::OnSave()
|
|
|
|
|
{
|
|
|
|
|
// Prompt the user for the filenames
|
|
|
|
|
TArray<FString> SaveFilenames;
|
|
|
|
|
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
|
|
|
|
|
bool bSaved = false;
|
|
|
|
|
if ( DesktopPlatform )
|
|
|
|
|
{
|
|
|
|
|
void* ParentWindowWindowHandle = NULL;
|
|
|
|
|
|
|
|
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame"));
|
|
|
|
|
const TSharedPtr<SWindow>& MainFrameParentWindow = MainFrameModule.GetParentWindow();
|
|
|
|
|
if ( MainFrameParentWindow.IsValid() && MainFrameParentWindow->GetNativeWindow().IsValid() )
|
|
|
|
|
{
|
|
|
|
|
ParentWindowWindowHandle = MainFrameParentWindow->GetNativeWindow()->GetOSWindowHandle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bSaved = DesktopPlatform->SaveFileDialog(
|
|
|
|
|
ParentWindowWindowHandle,
|
|
|
|
|
LOCTEXT("NewProjectBrowseTitle", "Choose a project location").ToString(),
|
|
|
|
|
LastBrowsePath,
|
|
|
|
|
TEXT(""),
|
|
|
|
|
LogVisualizer::FileTypes,
|
|
|
|
|
EFileDialogFlags::None,
|
|
|
|
|
SaveFilenames
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( bSaved )
|
|
|
|
|
{
|
|
|
|
|
if ( SaveFilenames.Num() > 0 )
|
|
|
|
|
{
|
|
|
|
|
LastBrowsePath = SaveFilenames[0];
|
|
|
|
|
SaveSelectedLogs(SaveFilenames[0]);
|
|
|
|
|
/*CurrentProjectFilePath = FPaths::GetPath(FPaths::GetPath(SaveFilenames[0]));
|
|
|
|
|
CurrentProjectFileName = FPaths::GetBaseFilename(SaveFilenames[0]);*/
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FReply::Handled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FReply SLogVisualizer::OnRemove()
|
|
|
|
|
{
|
|
|
|
|
TArray< TSharedPtr<FLogsListItem> > ItemsToRemove = LogsListWidget->GetSelectedItems();
|
|
|
|
|
if (ItemsToRemove.Num() > 0)
|
|
|
|
|
{
|
|
|
|
|
TArray<int32> IndicesToRemove;
|
|
|
|
|
IndicesToRemove.AddUninitialized(ItemsToRemove.Num());
|
|
|
|
|
|
|
|
|
|
for (int32 ListItemIndex = 0; ListItemIndex < ItemsToRemove.Num(); ++ListItemIndex)
|
|
|
|
|
{
|
|
|
|
|
IndicesToRemove[ListItemIndex] = ItemsToRemove[ListItemIndex]->LogIndex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IndicesToRemove.Sort();
|
|
|
|
|
|
2014-07-22 16:23:09 -04:00
|
|
|
int32 PrevIdx = -1;
|
2014-03-14 14:13:41 -04:00
|
|
|
for (int32 LogToRemove = IndicesToRemove.Num() - 1; LogToRemove >= 0; --LogToRemove)
|
|
|
|
|
{
|
2014-07-22 16:23:09 -04:00
|
|
|
if (IndicesToRemove[LogToRemove] == PrevIdx)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
LogVisualizer->Logs.RemoveAtSwap(IndicesToRemove[LogToRemove], 1, false);
|
2014-07-22 16:23:09 -04:00
|
|
|
PrevIdx = IndicesToRemove[LogToRemove];
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
const int32 IndexInList = FindIndexInLogsList(IndicesToRemove[LogToRemove]);
|
|
|
|
|
if (IndexInList != INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
LogsList.RemoveAtSwap(IndexInList);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LogsListWidget->ClearSelection();
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
LogsList.Reset();
|
|
|
|
|
OutEntriesCached.Reset();
|
2014-03-14 14:13:41 -04:00
|
|
|
RebuildFilteredList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FReply::Handled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::OnPauseChanged(ESlateCheckBoxState::Type NewState)
|
|
|
|
|
{
|
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
if (World != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (NewState != ESlateCheckBoxState::Checked)
|
|
|
|
|
{
|
|
|
|
|
World->bPlayersOnly = false;
|
|
|
|
|
World->bPlayersOnlyPending = false;
|
|
|
|
|
|
|
|
|
|
ALogVisualizerCameraController::DisableCamera(World);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
World->bPlayersOnlyPending = true;
|
|
|
|
|
// switch debug cam on
|
|
|
|
|
CameraController = ALogVisualizerCameraController::EnableCamera(World);
|
|
|
|
|
if (CameraController.IsValid())
|
|
|
|
|
{
|
|
|
|
|
CameraController->OnActorSelected = ALogVisualizerCameraController::FActorSelectedDelegate::CreateSP(
|
|
|
|
|
this, &SLogVisualizer::CameraActorSelected
|
|
|
|
|
);
|
|
|
|
|
CameraController->OnIterateLogEntries = ALogVisualizerCameraController::FLogEntryIterationDelegate::CreateSP(
|
|
|
|
|
this, &SLogVisualizer::IncrementCurrentLogIndex
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::CameraActorSelected(AActor* SelectedActor)
|
|
|
|
|
{
|
|
|
|
|
// find log corresponding to this Actor
|
|
|
|
|
if (SelectedActor == NULL || LogVisualizer == NULL)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SelectActor(SelectedActor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::SelectActor(AActor* SelectedActor)
|
|
|
|
|
{
|
2014-08-22 07:48:49 -04:00
|
|
|
const AActor* LogOwner = FVisualLog::Get().GetVisualLogRedirection(SelectedActor);
|
2014-03-14 14:13:41 -04:00
|
|
|
const int32 LogIndex = LogVisualizer->GetLogIndexForActor(LogOwner);
|
|
|
|
|
if (LogVisualizer->Logs.IsValidIndex(LogIndex))
|
|
|
|
|
{
|
|
|
|
|
SelectedLogIndex = LogIndex;
|
|
|
|
|
|
|
|
|
|
// find item pointing to given log index
|
|
|
|
|
for (int32 ItemIndex = 0; ItemIndex < LogsList.Num(); ++ItemIndex)
|
|
|
|
|
{
|
|
|
|
|
if (LogsList[ItemIndex]->LogIndex == LogIndex)
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[SelectedLogIndex];
|
|
|
|
|
ShowLogEntry(LogsList[ItemIndex], Log->Entries[Log->Entries.Num()-1]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
void SLogVisualizer::OnQuickFilterTextChanged(const FText& CommentText, ETextCommit::Type CommitInfo)
|
|
|
|
|
{
|
|
|
|
|
QuickFilterText = CommentText.ToString();
|
|
|
|
|
OnLogCategoryFiltersChanged();
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 14:13:41 -04:00
|
|
|
void SLogVisualizer::FilterTextCommitted(const FText& CommentText, ETextCommit::Type CommitInfo)
|
|
|
|
|
{
|
|
|
|
|
UpdateFilterInfo();
|
|
|
|
|
DoFullUpdate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FString SLogVisualizer::GetLogEntryStatusText() const
|
|
|
|
|
{
|
|
|
|
|
return TEXT("Pause game with Pause button\nand select log entry to start viewing\nlog's content");
|
|
|
|
|
}
|
|
|
|
|
|
Asset View now supports secondary sorting
#UDN: Feature suggestion; Content browser can sort by a second column
#branch UE4
#change
Added two new images for secondary sort ascending and descending.
(Updated styles where needed).
Added new enum EColumnSortPriority: currently only lists Primary and Secondary, but can easily accommodate more*.
(FOnSortModeChanged was modified to also have the priority as a param, fixedup existing usage).
SHeaderRow now also has a SortPriority attribute to specify the SortMode order
(Defaults to Primary if unused).
Modified TUniquePtr so that assigning one from another worked correctly.
(Reviewed by Steve Robb).
SAssetView is the only table that has been modified, so far, to take advantage of the secondary sort. SetMajorityAssetType has been updated to correctly filter out all those sorts which are no longer relevant and bump the priority of the remaining sorts to fill in the ægapsÆ made by non-longer-relevant ones.
FAssetViewSortManager has been overhauled to take SortPriority into consideration when sortingÃ
Firstly, duplicate comparison structs were removed in favour of single structs which have æascendingÆ as a paramà any remaining duplicate code was removed in favour of an inherited usage. The base struct has an array of æfurther methodsÆ to employ in the result of a tie. Should a tie occur the ænextÆ comparison is done, and so on until itÆs not a tie or we run out of comparisons to perform.*
The manager defaults to having no secondary sort, so it relies on the interface thatÆs using it to provide it.
Whenever a column is assign the code makes sure that itÆs not already assigned to another column and corrects the order to take this into account.
Fixed a bug in FCompareFAssetItemByTagNumericalAscending comparing A with A (instead of B).
Various optimizations to the sort to descrease times
*The only places æSecondaryÆ is referred to in code is in GetSortingBrush (so it can display the correct icon for the sort), and OnTitleClicked (so it can set to correct sort based on input). The sorting code itself has no concept as to a secondary sort, it can support any number of sorting levels so if in future a tertiary (or more) is added, it is only these two function which should need updating as the sort will automatically accommodate it.
reviewed by Thomas.Sarkanen, Bob.Tellez
[CL 2119201 by Andrew Brown in Main branch]
2014-06-27 04:30:08 -04:00
|
|
|
void SLogVisualizer::OnSortByChanged(const EColumnSortPriority::Type SortPriority, const FName& ColumnName, const EColumnSortMode::Type NewSortMode)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
|
|
|
|
SortBy = ELogsSortMode::ByName;
|
|
|
|
|
|
|
|
|
|
if (ColumnName == NAME_StartTime)
|
|
|
|
|
{
|
|
|
|
|
SortBy = ELogsSortMode::ByStartTime;
|
|
|
|
|
}
|
|
|
|
|
else if (ColumnName == NAME_EndTime)
|
|
|
|
|
{
|
|
|
|
|
SortBy = ELogsSortMode::ByEndTime;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:19:49 -04:00
|
|
|
LogsList.Reset();
|
|
|
|
|
OutEntriesCached.Reset();
|
2014-03-14 14:13:41 -04:00
|
|
|
RebuildFilteredList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EColumnSortMode::Type SLogVisualizer::GetLogsSortMode() const
|
|
|
|
|
{
|
|
|
|
|
return (SortBy == ELogsSortMode::ByName) ? EColumnSortMode::Ascending : EColumnSortMode::None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::LoadFiles(TArray<FString>& OpenFilenames)
|
|
|
|
|
{
|
|
|
|
|
for (int FilenameIndex = 0; FilenameIndex < OpenFilenames.Num(); ++FilenameIndex)
|
|
|
|
|
{
|
|
|
|
|
FArchive* FileAr = IFileManager::Get().CreateFileReader(*(OpenFilenames[FilenameIndex]));
|
|
|
|
|
if (FileAr != NULL)
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FJsonObject> Object;
|
2014-05-07 20:37:19 -04:00
|
|
|
TSharedRef<TJsonReader<UCS2CHAR> > Reader = TJsonReader<UCS2CHAR>::Create(FileAr);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2014-05-07 20:37:19 -04:00
|
|
|
if (FJsonSerializer::Deserialize(Reader, Object))
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-05-29 17:46:51 -04:00
|
|
|
TArray< TSharedPtr<FJsonValue> > JsonLogs = Object->GetArrayField(VisualLogJson::TAG_LOGS);
|
2014-03-14 14:13:41 -04:00
|
|
|
for (int32 LogIndex = 0; LogIndex < JsonLogs.Num(); ++LogIndex)
|
|
|
|
|
{
|
2014-05-29 17:46:51 -04:00
|
|
|
TSharedPtr<FJsonObject> JsonLogObject = JsonLogs[LogIndex]->AsObject();
|
|
|
|
|
if (JsonLogObject.IsValid() != false)
|
|
|
|
|
{
|
|
|
|
|
if (JsonLogObject->HasTypedField<EJson::String>(VisualLogJson::TAG_NAME))
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog> NewLog = MakeShareable(new FActorsVisLog(JsonLogs[LogIndex]));
|
|
|
|
|
LogVisualizer->AddLoadedLog(NewLog);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
2014-05-29 17:46:51 -04:00
|
|
|
bIgnoreTrivialLogs = false;
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileAr->Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (OpenFilenames.Num() > 0)
|
|
|
|
|
{
|
2014-07-07 17:19:49 -04:00
|
|
|
LogsList.Reset();
|
|
|
|
|
OutEntriesCached.Reset();
|
2014-03-14 14:13:41 -04:00
|
|
|
RebuildFilteredList();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SLogVisualizer::SaveSelectedLogs(FString& Filename)
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FJsonObject> Object = MakeShareable(new FJsonObject);
|
|
|
|
|
|
|
|
|
|
TArray< TSharedPtr<FJsonValue> > EntriesArray;
|
|
|
|
|
TArray< TSharedPtr<FLogsListItem> > ItemsToSave = LogsListWidget->GetSelectedItems();
|
|
|
|
|
if (ItemsToSave.Num() == 0)
|
|
|
|
|
{
|
|
|
|
|
// store all
|
|
|
|
|
ItemsToSave = LogsList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EntriesArray.Reserve(ItemsToSave.Num());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TSharedPtr<FLogsListItem>* LogListItem = ItemsToSave.GetTypedData();
|
|
|
|
|
for (int32 ItemIndex = 0; ItemIndex < ItemsToSave.Num(); ++ItemIndex, ++LogListItem)
|
|
|
|
|
{
|
|
|
|
|
if (LogListItem->IsValid() && LogVisualizer->Logs.IsValidIndex((*LogListItem)->LogIndex))
|
|
|
|
|
{
|
|
|
|
|
TSharedPtr<FActorsVisLog> Log = LogVisualizer->Logs[(*LogListItem)->LogIndex];
|
|
|
|
|
EntriesArray.Add(Log->ToJson());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (EntriesArray.Num() > 0)
|
|
|
|
|
{
|
2014-05-29 17:46:51 -04:00
|
|
|
Object->SetArrayField(VisualLogJson::TAG_LOGS, EntriesArray);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
FArchive* FileAr = IFileManager::Get().CreateFileWriter(*Filename);
|
|
|
|
|
if (FileAr != NULL)
|
|
|
|
|
{
|
2014-05-07 20:37:19 -04:00
|
|
|
TSharedRef<TJsonWriter<UCS2CHAR> > Writer = TJsonWriter<UCS2CHAR>::Create(FileAr);
|
2014-03-14 14:13:41 -04:00
|
|
|
FJsonSerializer::Serialize( Object.ToSharedRef(), Writer );
|
|
|
|
|
FileAr->Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-26 06:25:26 -04:00
|
|
|
#undef LOCTEXT_NAMESPACE
|
|
|
|
|
|
|
|
|
|
#endif //ENABLE_VISUAL_LOG
|