void FVisualLoggerCanvasRenderer::DrawOnCanvas(class UCanvas* Canvas, class APlayerController*)
{
	if (GEngine == NULL || CurrentTimeLine.IsValid() == false)
	{
		return;
	}

	UWorld* World = FLogVisualizer::Get().GetWorld();
	if (World == NULL)
	{
		return;
	}

	UFont* Font = GEngine->GetSmallFont();
	FCanvasTextItem TextItem(FVector2D::ZeroVector, FText::GetEmpty(), Font, FLinearColor::White);

	const FString TimeStampString = FString::Printf(TEXT("%.2f"), SelectedEntry.TimeStamp);
	LogVisualizer::DrawTextShadowed(Canvas, Font, TimeStampString, SelectedEntry.Location);

	for (const auto CurrentData : SelectedEntry.DataBlocks)
	{
		const FName TagName = CurrentData.TagName;
		const bool bIsValidByFilter = FCategoryFiltersManager::Get().MatchCategoryFilters(CurrentData.Category.ToString(), ELogVerbosity::All) && FCategoryFiltersManager::Get().MatchCategoryFilters(CurrentData.TagName.ToString(), ELogVerbosity::All);
		FVisualLogExtensionInterface* Extension = FVisualLogger::Get().GetExtensionForTag(TagName);
		if (!Extension)
		{
			continue;
		}

		if (!bIsValidByFilter)
		{
			Extension->DisableDrawingForData(FLogVisualizer::Get().GetWorld(), Canvas, NULL, TagName, CurrentData, SelectedEntry.TimeStamp);
		}
		else
		{
			Extension->DrawData(FLogVisualizer::Get().GetWorld(), Canvas, NULL, TagName, CurrentData, SelectedEntry.TimeStamp);
		}
	}

	if (ULogVisualizerSessionSettings::StaticClass()->GetDefaultObject<ULogVisualizerSessionSettings>()->bEnableGraphsVisualization)
	{
		DrawHistogramGraphs(Canvas, NULL);
	}
}
void FVisualLoggerCanvasRenderer::DrawOnCanvas(class UCanvas* Canvas, class APlayerController*)
{
	if (GEngine == NULL)
	{
		return;
	}

	UWorld* World = FLogVisualizer::Get().GetWorld();
	if (World == NULL)
	{
		return;
	}

	UFont* Font = GEngine->GetSmallFont();
	FCanvasTextItem TextItem(FVector2D::ZeroVector, FText::GetEmpty(), Font, FLinearColor::White);

	const FString TimeStampString = FString::Printf(TEXT("%.2f"), SelectedEntry.TimeStamp);
	LogVisualizer::DrawTextShadowed(Canvas, Font, TimeStampString, SelectedEntry.Location);

	if (bDirtyData && FLogVisualizer::Get().GetTimeSliderController().IsValid())
	{
		const FVisualLoggerTimeSliderArgs&  TimeSliderArgs = FLogVisualizer::Get().GetTimeSliderController()->GetTimeSliderArgs();
		TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get();
		const float LocalViewRangeMin = LocalViewRange.GetLowerBoundValue();
		const float LocalViewRangeMax = LocalViewRange.GetUpperBoundValue();
		const float LocalSequenceLength = LocalViewRangeMax - LocalViewRangeMin;
		const float WindowHalfWidth = LocalSequenceLength * TimeSliderArgs.CursorSize.Get() * 0.5f;
		const FVector2D TimeStampWindow(SelectedEntry.TimeStamp - WindowHalfWidth, SelectedEntry.TimeStamp + WindowHalfWidth);

		CollectedGraphs.Reset();
		const TArray<FName>& RowNames = FVisualLoggerDatabase::Get().GetSelectedRows();
		for (auto RowName : RowNames)
		{
			if (FVisualLoggerDatabase::Get().IsRowVisible(RowName) == false)
			{
				continue;
			}

			const TArray<FVisualLoggerGraph>& AllGraphs = FVisualLoggerGraphsDatabase::Get().GetGraphsByOwnerName(RowName);
			for (const FVisualLoggerGraph& CurrentGraph : AllGraphs)
			{
				const FName GraphName = CurrentGraph.GetGraphName();
				const FName OwnerName = CurrentGraph.GetOwnerName();

				if (FVisualLoggerGraphsDatabase::Get().IsGraphVisible(OwnerName, GraphName) == false)
				{
					continue;
				}

				for (auto DataIt(CurrentGraph.GetConstDataIterator()); DataIt; ++DataIt)
				{
					const FVisualLoggerGraphData& GraphData = *DataIt;
					const bool bIsGraphDataDisabled = FVisualLoggerFilters::Get().IsGraphDataDisabled(GraphName, GraphData.DataName);
					if (bIsGraphDataDisabled)
					{
						continue;
					}

					const FName FullGraphName = *FString::Printf(TEXT("%s$%s"), *RowName.ToString(), *GraphName.ToString());
					FGraphData &CollectedGraphData = CollectedGraphs.FindOrAdd(FullGraphName);
					FGraphLineData &LineData = CollectedGraphData.GraphLines.FindOrAdd(GraphData.DataName);
					LineData.DataName = GraphData.DataName;
					LineData.Samples = GraphData.Samples;
					LineData.LeftExtreme = FVector2D::ZeroVector;
					LineData.RightExtreme = FVector2D::ZeroVector;

					int32 LeftSideOutsideIndex = INDEX_NONE;
					int32 RightSideOutsideIndex = INDEX_NONE;
					for (int32 SampleIndex = 0; SampleIndex < GraphData.Samples.Num(); SampleIndex++)
					{
						const FVector2D& SampleValue = GraphData.Samples[SampleIndex];
						CollectedGraphData.Min.X = FMath::Min(CollectedGraphData.Min.X, SampleValue.X);
						CollectedGraphData.Min.Y = FMath::Min(CollectedGraphData.Min.Y, SampleValue.Y);

						CollectedGraphData.Max.X = FMath::Max(CollectedGraphData.Max.X, SampleValue.X);
						CollectedGraphData.Max.Y = FMath::Max(CollectedGraphData.Max.Y, SampleValue.Y);

						const float CurrentTimeStamp = GraphData.TimeStamps[SampleIndex];
						if (CurrentTimeStamp < TimeStampWindow.X)
						{
							LineData.LeftExtreme = SampleValue;
						}
						else if (CurrentTimeStamp > TimeStampWindow.Y)
						{
							LineData.RightExtreme = SampleValue;
							break;
						}
					}
				}
			}
		}
		bDirtyData = false;
	}

	if (ULogVisualizerSessionSettings::StaticClass()->GetDefaultObject<ULogVisualizerSessionSettings>()->bEnableGraphsVisualization)
	{
		DrawHistogramGraphs(Canvas, NULL);
	}

	const TMap<FName, FVisualLogExtensionInterface*>& Extensions = FVisualLogger::Get().GetAllExtensions();
	for (const auto& CurrentExtension : Extensions)
	{
		CurrentExtension.Value->DrawData(FVisualLoggerEditorInterface::Get(), Canvas);
	}
}