372 lines
11 KiB
C++
372 lines
11 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "SCaptureRegionWidget.h"
|
|
|
|
#include "Fonts/SlateFontInfo.h"
|
|
#include "GenericPlatform/ICursor.h"
|
|
#include "HAL/PlatformCrt.h"
|
|
#include "HighResScreenshot.h"
|
|
#include "Input/Events.h"
|
|
#include "InputCoreTypes.h"
|
|
#include "Internationalization/Internationalization.h"
|
|
#include "Layout/Children.h"
|
|
#include "Layout/Geometry.h"
|
|
#include "Layout/Visibility.h"
|
|
#include "Math/IntPoint.h"
|
|
#include "Math/UnrealMathSSE.h"
|
|
#include "Misc/AssertionMacros.h"
|
|
#include "Misc/Optional.h"
|
|
#include "Slate/SceneViewport.h"
|
|
#include "Styling/CoreStyle.h"
|
|
#include "Templates/SharedPointer.h"
|
|
#include "Templates/TypeHash.h"
|
|
#include "Types/SlateEnums.h"
|
|
#include "Widgets/Text/STextBlock.h"
|
|
|
|
void SCaptureRegionWidget::Construct( const FArguments& InArgs )
|
|
{
|
|
this->ChildSlot
|
|
.VAlign(VAlign_Center)
|
|
.HAlign(HAlign_Center)
|
|
[
|
|
SNew(STextBlock)
|
|
.Font(FCoreStyle::GetDefaultFontStyle("Regular", 20))
|
|
.ShadowOffset(FVector2D(1, 1))
|
|
.Text(NSLOCTEXT("CaptureRegion", "SpecifyRectangleToCaptureMessage", "Please specify capture rectangle"))
|
|
];
|
|
|
|
Deactivate(true);
|
|
|
|
// OnCaptureRegionChanged = InArgs._OnCaptureRegionChanged;
|
|
// OnCaptureRegionCompleted = InArgs._OnCaptureRegionCompleted;
|
|
|
|
CurrentState = State_Inactive;
|
|
PotentialInteraction = PI_DrawNewCaptureRegion;
|
|
bIgnoreExistingCaptureRegion = false;
|
|
}
|
|
|
|
void SCaptureRegionWidget::Activate(bool bCurrentCaptureRegionIsFullViewport)
|
|
{
|
|
SetVisibility(EVisibility::Visible);
|
|
|
|
OriginalCaptureRegion = GetHighResScreenshotConfig().UnscaledCaptureRegion;
|
|
bIgnoreExistingCaptureRegion = bCurrentCaptureRegionIsFullViewport;
|
|
}
|
|
|
|
void SCaptureRegionWidget::Deactivate(bool bKeepChanges)
|
|
{
|
|
if (GetVisibility() != EVisibility::Hidden)
|
|
{
|
|
SetVisibility(EVisibility::Hidden);
|
|
|
|
bIgnoreExistingCaptureRegion = false;
|
|
|
|
if (!bKeepChanges)
|
|
{
|
|
GetHighResScreenshotConfig().UnscaledCaptureRegion = OriginalCaptureRegion;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SCaptureRegionWidget::Reset()
|
|
{
|
|
bIgnoreExistingCaptureRegion = true;
|
|
}
|
|
|
|
FReply SCaptureRegionWidget::OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent )
|
|
{
|
|
if (IsEnabled() && MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton)
|
|
{
|
|
FVector2D ViewportPosition = MouseEvent.GetScreenSpacePosition() - FVector2D(MyGeometry.AbsolutePosition);
|
|
FIntRect& CurrentCaptureRegion = GetHighResScreenshotConfig().UnscaledCaptureRegion;
|
|
|
|
switch (PotentialInteraction)
|
|
{
|
|
case PI_DrawNewCaptureRegion:
|
|
{
|
|
DragStartPosition = MouseEvent.GetScreenSpacePosition() - FVector2D(MyGeometry.AbsolutePosition);
|
|
BuildNewCaptureRegion(DragStartPosition, DragStartPosition);
|
|
CurrentState = State_Dragging;
|
|
break;
|
|
}
|
|
case PI_ResizeBL:
|
|
{
|
|
DragStartPosition = FVector2D(CurrentCaptureRegion.Max.X, CurrentCaptureRegion.Min.Y);
|
|
BuildNewCaptureRegion(ViewportPosition, DragStartPosition);
|
|
CurrentState = State_Dragging;
|
|
break;
|
|
}
|
|
|
|
case PI_ResizeTL:
|
|
{
|
|
DragStartPosition = FVector2D(CurrentCaptureRegion.Max.X, CurrentCaptureRegion.Max.Y);
|
|
BuildNewCaptureRegion(ViewportPosition, DragStartPosition);
|
|
CurrentState = State_Dragging;
|
|
break;
|
|
}
|
|
case PI_ResizeBR:
|
|
{
|
|
DragStartPosition = FVector2D(CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Min.Y);
|
|
BuildNewCaptureRegion(ViewportPosition, DragStartPosition);
|
|
CurrentState = State_Dragging;
|
|
break;
|
|
}
|
|
|
|
case PI_ResizeTR:
|
|
{
|
|
DragStartPosition = FVector2D(CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Max.Y);
|
|
BuildNewCaptureRegion(ViewportPosition, DragStartPosition);
|
|
CurrentState = State_Dragging;
|
|
break;
|
|
}
|
|
|
|
case PI_ResizeBottom:
|
|
{
|
|
DragStartPosition = FVector2D(CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Min.Y);
|
|
CurrentState = State_YAxisResize;
|
|
break;
|
|
}
|
|
|
|
case PI_ResizeTop:
|
|
{
|
|
DragStartPosition = FVector2D(CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Max.Y);
|
|
CurrentState = State_YAxisResize;
|
|
break;
|
|
}
|
|
|
|
case PI_ResizeLeft:
|
|
{
|
|
DragStartPosition = FVector2D(CurrentCaptureRegion.Max.X, CurrentCaptureRegion.Min.Y);
|
|
CurrentState = State_XAxisResize;
|
|
break;
|
|
}
|
|
|
|
case PI_ResizeRight:
|
|
{
|
|
DragStartPosition = FVector2D(CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Min.Y);
|
|
CurrentState = State_XAxisResize;
|
|
break;
|
|
}
|
|
|
|
case PI_MoveExistingRegion:
|
|
{
|
|
DragStartPosition = ViewportPosition;
|
|
CurrentState = State_Moving;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FReply::Handled();
|
|
}
|
|
else
|
|
{
|
|
return FReply::Unhandled();
|
|
}
|
|
}
|
|
|
|
FReply SCaptureRegionWidget::OnMouseButtonUp( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent )
|
|
{
|
|
if (IsEnabled() && MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton)
|
|
{
|
|
FVector2D ViewportPosition = MouseEvent.GetScreenSpacePosition() - FVector2D(MyGeometry.AbsolutePosition);
|
|
FIntRect& CurrentCaptureRegion = GetHighResScreenshotConfig().UnscaledCaptureRegion;
|
|
|
|
switch (CurrentState)
|
|
{
|
|
case State_Dragging:
|
|
{
|
|
BuildNewCaptureRegion(ViewportPosition, DragStartPosition);
|
|
CurrentState = State_Inactive;
|
|
bIgnoreExistingCaptureRegion = false;
|
|
break;
|
|
}
|
|
|
|
case State_XAxisResize:
|
|
{
|
|
ViewportPosition.Y = CurrentCaptureRegion.Max.Y;
|
|
BuildNewCaptureRegion(ViewportPosition, DragStartPosition);
|
|
CurrentState = State_Inactive;
|
|
break;
|
|
}
|
|
|
|
case State_YAxisResize:
|
|
{
|
|
ViewportPosition.X = CurrentCaptureRegion.Max.X;
|
|
BuildNewCaptureRegion(ViewportPosition, DragStartPosition);
|
|
CurrentState = State_Inactive;
|
|
break;
|
|
}
|
|
|
|
case State_Moving:
|
|
{
|
|
CurrentState = State_Inactive;
|
|
//OnCaptureRegionChanged.ExecuteIfBound(CurrentCaptureRegion);
|
|
SendUpdatedCaptureRegion();
|
|
break;
|
|
}
|
|
|
|
case State_Inactive:
|
|
{
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
check(false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FReply::Handled();
|
|
}
|
|
else
|
|
{
|
|
return FReply::Unhandled();
|
|
}
|
|
}
|
|
|
|
FReply SCaptureRegionWidget::OnMouseMove( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent )
|
|
{
|
|
if (IsEnabled())
|
|
{
|
|
FVector2D ViewportPosition = MouseEvent.GetScreenSpacePosition() - FVector2D(MyGeometry.AbsolutePosition);
|
|
FIntRect& CurrentCaptureRegion = GetHighResScreenshotConfig().UnscaledCaptureRegion;
|
|
|
|
switch (CurrentState)
|
|
{
|
|
case State_Dragging:
|
|
{
|
|
BuildNewCaptureRegion(ViewportPosition, DragStartPosition);
|
|
break;
|
|
}
|
|
|
|
case State_Moving:
|
|
{
|
|
FVector2D Delta = ViewportPosition - DragStartPosition;
|
|
DragStartPosition = ViewportPosition;
|
|
CurrentCaptureRegion += FIntPoint((int32)Delta.X, (int32)Delta.Y);
|
|
//OnCaptureRegionChanged.ExecuteIfBound(CurrentCaptureRegion);
|
|
SendUpdatedCaptureRegion();
|
|
break;
|
|
}
|
|
|
|
case State_XAxisResize:
|
|
{
|
|
ViewportPosition.Y = CurrentCaptureRegion.Max.Y;
|
|
BuildNewCaptureRegion(ViewportPosition, DragStartPosition);
|
|
break;
|
|
}
|
|
|
|
case State_YAxisResize:
|
|
{
|
|
ViewportPosition.X = CurrentCaptureRegion.Max.X;
|
|
BuildNewCaptureRegion(ViewportPosition, DragStartPosition);
|
|
break;
|
|
}
|
|
|
|
case State_Inactive:
|
|
{
|
|
if (CurrentCaptureRegion.Area() > 0 && !bIgnoreExistingCaptureRegion)
|
|
{
|
|
// Common tests
|
|
bool bWithinXRangeOfExistingRegion = ViewportPosition.X >= CurrentCaptureRegion.Min.X && ViewportPosition.X <= CurrentCaptureRegion.Max.X;
|
|
bool bWithinYRangeOfExistingRegion = ViewportPosition.Y >= CurrentCaptureRegion.Min.Y && ViewportPosition.Y <= CurrentCaptureRegion.Max.Y;
|
|
|
|
// Distance away from an edge which we consider intersecting
|
|
const float EdgeDistance = 5;
|
|
|
|
// Check if we're over the corners
|
|
if ((ViewportPosition - FVector2D((float)CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Min.Y)).Size() < EdgeDistance)
|
|
{
|
|
SetCursor(EMouseCursor::ResizeSouthEast);
|
|
PotentialInteraction = PI_ResizeTL;
|
|
}
|
|
else if ((ViewportPosition - FVector2D((float)CurrentCaptureRegion.Min.X, CurrentCaptureRegion.Max.Y)).Size() < EdgeDistance)
|
|
{
|
|
SetCursor(EMouseCursor::ResizeSouthWest);
|
|
PotentialInteraction = PI_ResizeBL;
|
|
}
|
|
else if ((ViewportPosition - FVector2D((float)CurrentCaptureRegion.Max.X, CurrentCaptureRegion.Min.Y)).Size() < EdgeDistance)
|
|
{
|
|
SetCursor(EMouseCursor::ResizeSouthWest);
|
|
PotentialInteraction = PI_ResizeTR;
|
|
}
|
|
else if ((ViewportPosition - FVector2D((float)CurrentCaptureRegion.Max.X, CurrentCaptureRegion.Max.Y)).Size() < EdgeDistance)
|
|
{
|
|
SetCursor(EMouseCursor::ResizeSouthEast);
|
|
PotentialInteraction = PI_ResizeBR;
|
|
}
|
|
else if (FMath::Abs((float)CurrentCaptureRegion.Min.X - ViewportPosition.X) < EdgeDistance && bWithinYRangeOfExistingRegion)
|
|
{
|
|
SetCursor(EMouseCursor::ResizeLeftRight);
|
|
PotentialInteraction = PI_ResizeLeft;
|
|
}
|
|
else if (FMath::Abs((float)CurrentCaptureRegion.Max.X - ViewportPosition.X) < EdgeDistance && bWithinYRangeOfExistingRegion)
|
|
{
|
|
SetCursor(EMouseCursor::ResizeLeftRight);
|
|
PotentialInteraction = PI_ResizeRight;
|
|
}
|
|
else if (FMath::Abs((float)CurrentCaptureRegion.Min.Y - ViewportPosition.Y) < EdgeDistance && bWithinXRangeOfExistingRegion)
|
|
{
|
|
SetCursor(EMouseCursor::ResizeUpDown);
|
|
PotentialInteraction = PI_ResizeTop;
|
|
}
|
|
else if (FMath::Abs((float)CurrentCaptureRegion.Max.Y - ViewportPosition.Y) < EdgeDistance && bWithinXRangeOfExistingRegion)
|
|
{
|
|
SetCursor(EMouseCursor::ResizeUpDown);
|
|
PotentialInteraction = PI_ResizeBottom;
|
|
}
|
|
else if (CurrentCaptureRegion.Contains(FIntPoint((int32)ViewportPosition.X, (int32)ViewportPosition.Y)))
|
|
{
|
|
SetCursor(EMouseCursor::CardinalCross);
|
|
PotentialInteraction = PI_MoveExistingRegion;
|
|
}
|
|
else
|
|
{
|
|
SetCursor(EMouseCursor::Crosshairs);
|
|
PotentialInteraction = PI_DrawNewCaptureRegion;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetCursor(EMouseCursor::Crosshairs);
|
|
PotentialInteraction = PI_DrawNewCaptureRegion;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
check(false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FReply::Handled();
|
|
}
|
|
else
|
|
{
|
|
return FReply::Unhandled();
|
|
}
|
|
}
|
|
|
|
void SCaptureRegionWidget::BuildNewCaptureRegion(const FVector2D& InPointA, const FVector2D& InPointB)
|
|
{
|
|
FIntRect& CurrentCaptureRegion = GetHighResScreenshotConfig().UnscaledCaptureRegion;
|
|
CurrentCaptureRegion.Min = FIntPoint(FMath::Min((int32)InPointA.X, (int32)InPointB.X), FMath::Min((int32)InPointA.Y, (int32)InPointB.Y));
|
|
CurrentCaptureRegion.Max = FIntPoint(FMath::Max((int32)InPointA.X, (int32)InPointB.X), FMath::Max((int32)InPointA.Y, (int32)InPointB.Y));
|
|
//OnCaptureRegionChanged.ExecuteIfBound(CurrentCaptureRegion);
|
|
SendUpdatedCaptureRegion();
|
|
}
|
|
|
|
void SCaptureRegionWidget::SendUpdatedCaptureRegion()
|
|
{
|
|
auto& Config = GetHighResScreenshotConfig();
|
|
auto ConfigViewport = Config.TargetViewport.Pin();
|
|
if (ConfigViewport.IsValid())
|
|
{
|
|
ConfigViewport->Invalidate();
|
|
}
|
|
}
|