163 lines
6.0 KiB
C++
163 lines
6.0 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
#include "Utils.h"
|
|
#include "EditorViewportClient.h"
|
|
#include "SceneView.h"
|
|
|
|
#if PLATFORM_WINDOWS
|
|
// Needed for showing balloon messages
|
|
#include "Windows/AllowWindowsPlatformTypes.h"
|
|
#include <ShellAPI.h>
|
|
#include "Windows/HideWindowsPlatformTypes.h"
|
|
#endif
|
|
|
|
DEFINE_LOG_CATEGORY(LogUtils);
|
|
|
|
IMPLEMENT_HIT_PROXY(HWidgetUtilProxy,HHitProxy);
|
|
|
|
float UnrealEd_WidgetSize = 0.15f; // Proportion of the viewport the widget should fill
|
|
|
|
/** Utility for calculating drag direction when you click on this widget. */
|
|
void HWidgetUtilProxy::CalcVectors(FSceneView* SceneView, const FViewportClick& Click, FVector& LocalManDir, FVector& WorldManDir, float& DragDirX, float& DragDirY)
|
|
{
|
|
if(Axis == EAxisList::X)
|
|
{
|
|
WorldManDir = WidgetMatrix.GetScaledAxis( EAxis::X );
|
|
LocalManDir = FVector(1,0,0);
|
|
}
|
|
else if(Axis == EAxisList::Y)
|
|
{
|
|
WorldManDir = WidgetMatrix.GetScaledAxis( EAxis::Y );
|
|
LocalManDir = FVector(0,1,0);
|
|
}
|
|
else
|
|
{
|
|
WorldManDir = WidgetMatrix.GetScaledAxis( EAxis::Z );
|
|
LocalManDir = FVector(0,0,1);
|
|
}
|
|
|
|
FVector WorldDragDir = WorldManDir;
|
|
|
|
if(Mode == WMM_Rotate)
|
|
{
|
|
if( FMath::Abs(Click.GetDirection() | WorldManDir) > KINDA_SMALL_NUMBER ) // If click direction and circle plane are parallel.. can't resolve.
|
|
{
|
|
// First, find actual position we clicking on the circle in world space.
|
|
const FVector ClickPosition = FMath::LinePlaneIntersection( Click.GetOrigin(),
|
|
Click.GetOrigin() + Click.GetDirection(),
|
|
WidgetMatrix.GetOrigin(),
|
|
WorldManDir );
|
|
|
|
// Then find Radial direction vector (from center to widget to clicked position).
|
|
FVector RadialDir = ( ClickPosition - WidgetMatrix.GetOrigin() );
|
|
RadialDir.Normalize();
|
|
|
|
// Then tangent in plane is just the cross product. Should always be unit length again because RadialDir and WorlManDir should be orthogonal.
|
|
WorldDragDir = RadialDir ^ WorldManDir;
|
|
}
|
|
}
|
|
|
|
// Transform world-space drag dir to screen space.
|
|
FVector ScreenDir = SceneView->ViewMatrices.GetViewMatrix().TransformVector(WorldDragDir);
|
|
ScreenDir.Z = 0.0f;
|
|
|
|
if( ScreenDir.IsZero() )
|
|
{
|
|
DragDirX = 0.0f;
|
|
DragDirY = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
ScreenDir.Normalize();
|
|
DragDirX = static_cast<float>(ScreenDir.X);
|
|
DragDirY = static_cast<float>(ScreenDir.Y);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Utility function for drawing manipulation widget in a 3D viewport.
|
|
* If we are hit-testing will create HWidgetUtilProxys for each axis, filling in InInfo1 and InInfo2 as passed in by user.
|
|
*/
|
|
void FUnrealEdUtils::DrawWidget(const FSceneView* View,FPrimitiveDrawInterface* PDI, const FMatrix& WidgetMatrix, int32 InInfo1, int32 InInfo2, EAxisList::Type HighlightAxis, EWidgetMovementMode bInMode)
|
|
{
|
|
DrawWidget( View, PDI, WidgetMatrix, InInfo1, InInfo2, HighlightAxis, bInMode, PDI->IsHitTesting() );
|
|
}
|
|
|
|
void FUnrealEdUtils::DrawWidget(const FSceneView* View,FPrimitiveDrawInterface* PDI, const FMatrix& WidgetMatrix, int32 InInfo1, int32 InInfo2, EAxisList::Type HighlightAxis, EWidgetMovementMode bInMode, bool bHitTesting)
|
|
{
|
|
const FVector WidgetOrigin = WidgetMatrix.GetOrigin();
|
|
|
|
// Calculate size to draw widget so it takes up the same screen space.
|
|
const double ZoomFactor = FMath::Min<double>(View->ViewMatrices.GetProjectionMatrix().M[0][0], View->ViewMatrices.GetProjectionMatrix().M[1][1]);
|
|
const double WidgetRadius = View->Project(WidgetOrigin).W * (UnrealEd_WidgetSize / ZoomFactor);
|
|
|
|
// Choose its color. Highlight manipulated axis in yellow.
|
|
FColor XColor(FColor::Red);
|
|
FColor YColor(FColor::Green);
|
|
FColor ZColor(FColor::Blue);
|
|
|
|
if (HighlightAxis == EAxisList::X)
|
|
{
|
|
XColor = FColor::Yellow;
|
|
}
|
|
else if (HighlightAxis == EAxisList::Y)
|
|
{
|
|
YColor = FColor::Yellow;
|
|
}
|
|
else if (HighlightAxis == EAxisList::Z)
|
|
{
|
|
ZColor = FColor::Yellow;
|
|
}
|
|
|
|
const FVector XAxis = WidgetMatrix.GetScaledAxis( EAxis::X );
|
|
const FVector YAxis = WidgetMatrix.GetScaledAxis( EAxis::Y );
|
|
const FVector ZAxis = WidgetMatrix.GetScaledAxis( EAxis::Z );
|
|
|
|
if(bInMode == WMM_Rotate)
|
|
{
|
|
if(bHitTesting) PDI->SetHitProxy( new HWidgetUtilProxy(InInfo1, InInfo2, EAxisList::X, WidgetMatrix, bInMode) );
|
|
DrawCircle(PDI,WidgetOrigin, YAxis, ZAxis, XColor, WidgetRadius, 24, SDPG_Foreground);
|
|
if(bHitTesting) PDI->SetHitProxy( NULL );
|
|
|
|
if(bHitTesting) PDI->SetHitProxy( new HWidgetUtilProxy(InInfo1, InInfo2, EAxisList::Y, WidgetMatrix, bInMode) );
|
|
DrawCircle(PDI,WidgetOrigin, XAxis, ZAxis, YColor, WidgetRadius, 24, SDPG_Foreground);
|
|
if(bHitTesting) PDI->SetHitProxy( NULL );
|
|
|
|
if(bHitTesting) PDI->SetHitProxy( new HWidgetUtilProxy(InInfo1, InInfo2, EAxisList::Z, WidgetMatrix, bInMode) );
|
|
DrawCircle(PDI,WidgetOrigin, XAxis, YAxis, ZColor, WidgetRadius, 24, SDPG_Foreground);
|
|
if(bHitTesting) PDI->SetHitProxy( NULL );
|
|
}
|
|
else
|
|
{
|
|
FMatrix WidgetTM;
|
|
|
|
// Draw the widget arrows.
|
|
if(bHitTesting) PDI->SetHitProxy( new HWidgetUtilProxy(InInfo1, InInfo2, EAxisList::X, WidgetMatrix, bInMode) );
|
|
WidgetTM = FMatrix(XAxis, YAxis, ZAxis, WidgetOrigin);
|
|
DrawDirectionalArrow(PDI,WidgetTM, XColor, WidgetRadius, 1.f, SDPG_Foreground);
|
|
if(bHitTesting) PDI->SetHitProxy( NULL );
|
|
|
|
if(bHitTesting) PDI->SetHitProxy( new HWidgetUtilProxy(InInfo1, InInfo2, EAxisList::Y, WidgetMatrix, bInMode) );
|
|
WidgetTM = FMatrix(YAxis, ZAxis, XAxis, WidgetOrigin);
|
|
DrawDirectionalArrow(PDI,WidgetTM, YColor, WidgetRadius, 1.f, SDPG_Foreground);
|
|
if(bHitTesting) PDI->SetHitProxy( NULL );
|
|
|
|
if(bHitTesting) PDI->SetHitProxy( new HWidgetUtilProxy(InInfo1, InInfo2, EAxisList::Z, WidgetMatrix, bInMode) );
|
|
WidgetTM = FMatrix(ZAxis, XAxis, YAxis, WidgetOrigin);
|
|
DrawDirectionalArrow(PDI,WidgetTM, ZColor, WidgetRadius, 1.f, SDPG_Foreground);
|
|
if(bHitTesting) PDI->SetHitProxy( NULL );
|
|
|
|
if(bInMode == WMM_Scale)
|
|
{
|
|
FVector AlongX = WidgetOrigin + (XAxis * WidgetRadius * 0.3f);
|
|
FVector AlongY = WidgetOrigin + (YAxis * WidgetRadius * 0.3f);
|
|
FVector AlongZ = WidgetOrigin + (ZAxis * WidgetRadius * 0.3f);
|
|
|
|
PDI->DrawLine(AlongX, AlongY, FColor::White, SDPG_Foreground);
|
|
PDI->DrawLine(AlongY, AlongZ, FColor::White, SDPG_Foreground);
|
|
PDI->DrawLine(AlongZ, AlongX, FColor::White, SDPG_Foreground);
|
|
}
|
|
}
|
|
}
|