115 lines
4.5 KiB
C++
115 lines
4.5 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "DragTool_Measure.h"
|
|
#include "SceneView.h"
|
|
#include "EditorViewportClient.h"
|
|
#include "CanvasItem.h"
|
|
#include "Settings/LevelEditorViewportSettings.h"
|
|
#include "EngineGlobals.h"
|
|
#include "Editor.h"
|
|
#include "SnappingUtils.h"
|
|
#include "CanvasTypes.h"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FDragTool_Measure
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
FDragTool_Measure::FDragTool_Measure(FEditorViewportClient* InViewportClient)
|
|
: FDragTool(InViewportClient->GetModeTools()), ViewportClient(InViewportClient)
|
|
{
|
|
bUseSnapping = true;
|
|
bConvertDelta = false;
|
|
}
|
|
|
|
FVector2D FDragTool_Measure::GetSnappedPixelPos(FVector2D PixelPos)
|
|
{
|
|
FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
|
|
ViewportClient->Viewport,
|
|
ViewportClient->GetScene(),
|
|
ViewportClient->EngineShowFlags)
|
|
.SetRealtimeUpdate(ViewportClient->IsRealtime()));
|
|
|
|
FSceneView* View = ViewportClient->CalcSceneView(&ViewFamily);
|
|
|
|
// Put the mouse pos in world space
|
|
FVector WorldPos = View->ScreenToWorld(View->PixelToScreen(PixelPos.X, PixelPos.Y, 0.5f));
|
|
;
|
|
|
|
// Snap the world position
|
|
const float GridSize = GEditor->GetGridSize();
|
|
const FVector GridBase(GridSize, GridSize, GridSize);
|
|
FSnappingUtils::SnapPointToGrid(WorldPos, GridBase);
|
|
|
|
// And back into pixel-space (might fail, in which case we return the original)
|
|
View->WorldToPixel(WorldPos, PixelPos);
|
|
|
|
// The canvas we're going to render to factors in dpi scale to final position.
|
|
// Since we're basing our position off mouse coordinates it will already be pixel accurate and therefore we must back out the scale the canvas will apply
|
|
PixelPos /= ViewportClient->GetDPIScale();
|
|
|
|
return PixelPos;
|
|
}
|
|
|
|
void FDragTool_Measure::StartDrag(FEditorViewportClient* InViewportClient, const FVector& InStart, const FVector2D& InStartScreen)
|
|
{
|
|
FDragTool::StartDrag(InViewportClient, InStart, InStartScreen);
|
|
PixelStart = GetSnappedPixelPos(InStartScreen);
|
|
PixelEnd = PixelStart;
|
|
}
|
|
|
|
void FDragTool_Measure::AddDelta(const FVector& InDelta)
|
|
{
|
|
FDragTool::AddDelta(InDelta);
|
|
|
|
FIntPoint MousePos;
|
|
ViewportClient->Viewport->GetMousePos(MousePos);
|
|
PixelEnd = GetSnappedPixelPos(FVector2D(MousePos));
|
|
}
|
|
|
|
void FDragTool_Measure::Render(const FSceneView* View, FCanvas* Canvas)
|
|
{
|
|
const float OrthoUnitsPerPixel = ViewportClient->GetOrthoUnitsPerPixel(ViewportClient->Viewport);
|
|
const float Length = FMath::RoundToFloat((PixelEnd - PixelStart).Size() * OrthoUnitsPerPixel * ViewportClient->GetDPIScale());
|
|
|
|
if (View != nullptr && Canvas != nullptr && Length >= 1.f)
|
|
{
|
|
FCanvasLineItem LineItem(PixelStart, PixelEnd);
|
|
Canvas->DrawItem(LineItem);
|
|
|
|
const FVector2D PixelMid = FVector2D(PixelStart + ((PixelEnd - PixelStart) / 2));
|
|
|
|
// Calculate number of decimal places to display, based on the current viewport zoom
|
|
float Divisor = 1.0f;
|
|
int DecimalPlaces = 0;
|
|
const float OrderOfMagnitude = FMath::LogX(10.0f, OrthoUnitsPerPixel);
|
|
|
|
switch (GetDefault<ULevelEditorViewportSettings>()->MeasuringToolUnits)
|
|
{
|
|
case MeasureUnits_Meters:
|
|
Divisor = 100.0f;
|
|
// Max one decimal place allowed for meters.
|
|
DecimalPlaces = FMath::Clamp(FMath::FloorToInt(1.5f - OrderOfMagnitude), 0, 1);
|
|
break;
|
|
|
|
case MeasureUnits_Kilometers:
|
|
Divisor = 100000.0f;
|
|
// Max two decimal places allowed for kilometers.
|
|
DecimalPlaces = FMath::Clamp(FMath::FloorToInt(4.5f - OrderOfMagnitude), 0, 2);
|
|
break;
|
|
}
|
|
|
|
FNumberFormattingOptions Options;
|
|
Options.UseGrouping = false;
|
|
Options.MinimumFractionalDigits = DecimalPlaces;
|
|
Options.MaximumFractionalDigits = DecimalPlaces;
|
|
|
|
const FText LengthStr = FText::AsNumber(Length / Divisor, &Options);
|
|
|
|
FCanvasTextItem TextItem(FVector2D(FMath::FloorToFloat(PixelMid.X), FMath::FloorToFloat(PixelMid.Y)), LengthStr, GEngine->GetSmallFont(), FLinearColor::White);
|
|
TextItem.bCentreX = true;
|
|
Canvas->DrawItem(TextItem);
|
|
}
|
|
}
|