167 lines
7.2 KiB
C++
167 lines
7.2 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "ViewportInteractionDragOperations.h"
|
|
#include "ViewportInteractionTypes.h"
|
|
#include "VIGizmoHandle.h"
|
|
#include "ViewportInteractor.h"
|
|
#include "ViewportWorldInteraction.h"
|
|
#include "SnappingUtils.h"
|
|
#include "ViewportInteractor.h"
|
|
#include "UnrealWidgetFwd.h"
|
|
|
|
namespace VI
|
|
{
|
|
static FAutoConsoleVariable ScaleSensitivity(TEXT("VI.ScaleSensitivity"), 0.005f, TEXT("Sensitivity for scaling"));
|
|
}
|
|
|
|
void UTranslationDragOperation::ExecuteDrag(FDraggingTransformableData& DraggingData)
|
|
{
|
|
// Translate the gizmo!
|
|
DraggingData.OutGizmoUnsnappedTargetTransform.SetLocation(DraggingData.PassDraggedTo);
|
|
DraggingData.bOutMovedTransformGizmo = true;
|
|
DraggingData.bOutShouldApplyVelocitiesFromDrag = true;
|
|
DraggingData.bOutTranslated = true;
|
|
}
|
|
|
|
UPlaneTranslationDragOperation::UPlaneTranslationDragOperation()
|
|
{
|
|
bPlaneConstraint = true;
|
|
}
|
|
|
|
void UPlaneTranslationDragOperation::ExecuteDrag(struct FDraggingTransformableData& DraggingData)
|
|
{
|
|
// Translate the gizmo!
|
|
DraggingData.OutGizmoUnsnappedTargetTransform.SetLocation(DraggingData.PassDraggedTo);
|
|
DraggingData.bOutMovedTransformGizmo = true;
|
|
DraggingData.bOutShouldApplyVelocitiesFromDrag = true;
|
|
DraggingData.bOutTranslated = true;
|
|
}
|
|
|
|
URotateOnAngleDragOperation::URotateOnAngleDragOperation():
|
|
Super(),
|
|
StartDragAngleOnRotation(),
|
|
DraggingRotationHandleDirection()
|
|
{
|
|
|
|
}
|
|
|
|
void URotateOnAngleDragOperation::ExecuteDrag(FDraggingTransformableData& DraggingData)
|
|
{
|
|
const FTransformGizmoHandlePlacement& HandlePlacement = DraggingData.OptionalHandlePlacement.GetValue();
|
|
const FTransform& GizmoStartTransform = DraggingData.GizmoStartTransform;
|
|
|
|
int32 CenterHandleCount, FacingAxisIndex, CenterAxisIndex;
|
|
HandlePlacement.GetCenterHandleCountAndFacingAxisIndex( /* Out */ CenterHandleCount, /* Out */ FacingAxisIndex, /* Out */ CenterAxisIndex);
|
|
|
|
FVector GizmoSpaceFacingAxisVector = UGizmoHandleGroup::GetAxisVector(FacingAxisIndex, HandlePlacement.Axes[FacingAxisIndex]);
|
|
|
|
USceneComponent* DraggingTransformGizmoComponent = DraggingData.Interactor->GetInteractorData().DraggingTransformGizmoComponent.Get();
|
|
if (DraggingTransformGizmoComponent)
|
|
{
|
|
const FTransform WorldToGizmo = GizmoStartTransform.Inverse();
|
|
|
|
FTransform NewGizmoToWorld;
|
|
{
|
|
if (!DraggingRotationHandleDirection.IsSet())
|
|
{
|
|
DraggingRotationHandleDirection = DraggingTransformGizmoComponent->GetComponentTransform().GetRotation().Vector();
|
|
DraggingRotationHandleDirection->Normalize();
|
|
}
|
|
|
|
//@todo ViewportInteraction: Use UViewportWorldInteraction::ComputeConstrainedDragDeltaFromStart instead of calculating where the laser hit on the plane with this intersect.
|
|
// Get the laser pointer intersection on the plane of the handle
|
|
const FPlane RotationPlane = FPlane(GizmoStartTransform.GetLocation(), DraggingRotationHandleDirection.GetValue());
|
|
const ECoordSystem CoordSystem = DraggingData.WorldInteraction->GetTransformGizmoCoordinateSpace();
|
|
const FVector LaserImpactOnRotationPlane = FMath::LinePlaneIntersection(DraggingData.LaserPointerStart, DraggingData.LaserPointerStart + DraggingData.LaserPointerDirection, RotationPlane);
|
|
|
|
{
|
|
FTransform GizmoTransformNoRotation = FTransform(FRotator::ZeroRotator, GizmoStartTransform.GetLocation());
|
|
if (CoordSystem == COORD_Local)
|
|
{
|
|
GizmoTransformNoRotation.SetRotation(GizmoStartTransform.GetRotation());
|
|
}
|
|
|
|
LocalIntersectPointOnRotationGizmo = GizmoTransformNoRotation.InverseTransformPositionNoScale(LaserImpactOnRotationPlane);
|
|
}
|
|
|
|
// Set output for hover point
|
|
DraggingData.OutUnsnappedDraggedTo = LaserImpactOnRotationPlane;
|
|
|
|
// Relative offset of the intersection on the plane
|
|
const FVector GizmoSpaceLaserImpactOnRotationPlane = WorldToGizmo.TransformPosition(LaserImpactOnRotationPlane);
|
|
FVector RotatedIntersectLocationOnPlane;
|
|
if (CoordSystem == COORD_Local)
|
|
{
|
|
RotatedIntersectLocationOnPlane = GizmoSpaceFacingAxisVector.Rotation().UnrotateVector(GizmoSpaceLaserImpactOnRotationPlane);
|
|
}
|
|
else
|
|
{
|
|
RotatedIntersectLocationOnPlane = GizmoStartTransform.TransformVector(GizmoSpaceFacingAxisVector).Rotation().UnrotateVector(GizmoSpaceLaserImpactOnRotationPlane);
|
|
}
|
|
|
|
// Get the angle between the center and the intersected point
|
|
float AngleToIntersectedLocation = (float)FMath::Atan2(RotatedIntersectLocationOnPlane.Y, RotatedIntersectLocationOnPlane.Z);
|
|
if (!StartDragAngleOnRotation.IsSet())
|
|
{
|
|
StartDragAngleOnRotation = AngleToIntersectedLocation;
|
|
}
|
|
|
|
// Delta rotation in gizmo space between the starting and the intersection rotation
|
|
const float AngleDeltaRotationFromStart = FMath::FindDeltaAngleRadians(AngleToIntersectedLocation, StartDragAngleOnRotation.GetValue());
|
|
const FQuat GizmoSpaceDeltaRotation = FQuat(GizmoSpaceFacingAxisVector, AngleDeltaRotationFromStart);
|
|
|
|
const FTransform GizmoSpaceRotatedTransform(GizmoSpaceDeltaRotation);
|
|
NewGizmoToWorld = GizmoSpaceRotatedTransform * GizmoStartTransform;
|
|
}
|
|
|
|
// Rotate the gizmo!
|
|
DraggingData.OutGizmoUnsnappedTargetTransform = NewGizmoToWorld;
|
|
DraggingData.bOutMovedTransformGizmo = true;
|
|
DraggingData.bOutShouldApplyVelocitiesFromDrag = true;
|
|
DraggingData.bOutRotated = true;
|
|
}
|
|
}
|
|
|
|
FVector URotateOnAngleDragOperation::GetLocalIntersectPointOnRotationGizmo() const
|
|
{
|
|
return LocalIntersectPointOnRotationGizmo;
|
|
}
|
|
|
|
void UScaleDragOperation::ExecuteDrag(struct FDraggingTransformableData& DraggingData)
|
|
{
|
|
const FTransformGizmoHandlePlacement& HandlePlacement = DraggingData.OptionalHandlePlacement.GetValue();
|
|
int32 CenterHandleCount, FacingAxisIndex, CenterAxisIndex;
|
|
HandlePlacement.GetCenterHandleCountAndFacingAxisIndex(/* Out */ CenterHandleCount, /* Out */ FacingAxisIndex, /* Out */ CenterAxisIndex);
|
|
|
|
const FVector PassGizmoSpaceDraggedTo = DraggingData.GizmoStartTransform.InverseTransformPositionNoScale(DraggingData.PassDraggedTo);
|
|
double AddedScaleOnAxis = PassGizmoSpaceDraggedTo[FacingAxisIndex] * VI::ScaleSensitivity->GetFloat();
|
|
|
|
// Invert if we we are scaling on the negative side of the gizmo
|
|
USceneComponent* DraggingTransformGizmoComponent = DraggingData.Interactor->GetInteractorData().DraggingTransformGizmoComponent.Get();
|
|
if (DraggingTransformGizmoComponent && DraggingTransformGizmoComponent->GetRelativeTransform().GetLocation()[FacingAxisIndex] < 0)
|
|
{
|
|
AddedScaleOnAxis *= -1;
|
|
}
|
|
|
|
FVector NewScale = DraggingData.GizmoStartTransform.GetScale3D();
|
|
NewScale[FacingAxisIndex] += AddedScaleOnAxis;
|
|
DraggingData.OutGizmoUnsnappedTargetTransform.SetScale3D(NewScale);
|
|
|
|
DraggingData.bOutMovedTransformGizmo = true;
|
|
DraggingData.bOutShouldApplyVelocitiesFromDrag = true;
|
|
DraggingData.bOutScaled = true;
|
|
}
|
|
|
|
void UUniformScaleDragOperation::ExecuteDrag(struct FDraggingTransformableData& DraggingData)
|
|
{
|
|
//Always use Z for uniform scale
|
|
const FVector RelativeDraggedTo = DraggingData.PassDraggedTo - DraggingData.GizmoStartTransform.GetLocation();
|
|
const FVector AddedScaleOnAxis(RelativeDraggedTo.Z * VI::ScaleSensitivity->GetFloat());
|
|
const FVector NewScale = DraggingData.GizmoStartTransform.GetScale3D() + AddedScaleOnAxis;
|
|
DraggingData.OutGizmoUnsnappedTargetTransform.SetScale3D(NewScale);
|
|
|
|
DraggingData.bOutMovedTransformGizmo = true;
|
|
DraggingData.bOutShouldApplyVelocitiesFromDrag = true;
|
|
DraggingData.bOutScaled = true;
|
|
}
|