Files
UnrealEngineUWP/Engine/Source/Runtime/InteractiveToolsFramework/Private/BaseGizmos/AxisPositionGizmo.cpp
tyson brochu f0753ca380 Don't snap the transform gizmo on mouse-down, wait for the drag event.
#jira UE-131786
#rnx
#rb ryan.schmidt semion.piskarev
#preflight 61a510e3ee100b68faa0517d

#ROBOMERGE-AUTHOR: tyson.brochu
#ROBOMERGE-SOURCE: CL 18312385 in //UE5/Release-5.0/... via CL 18312447
#ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469)

[CL 18312473 by tyson brochu in ue5-release-engine-test branch]
2021-11-29 13:01:50 -05:00

193 lines
5.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "BaseGizmos/AxisPositionGizmo.h"
#include "InteractiveGizmoManager.h"
#include "BaseBehaviors/ClickDragBehavior.h"
#include "BaseBehaviors/MouseHoverBehavior.h"
#include "BaseGizmos/GizmoMath.h"
UInteractiveGizmo* UAxisPositionGizmoBuilder::BuildGizmo(const FToolBuilderState& SceneState) const
{
UAxisPositionGizmo* NewGizmo = NewObject<UAxisPositionGizmo>(SceneState.GizmoManager);
return NewGizmo;
}
void UAxisPositionGizmo::Setup()
{
UInteractiveGizmo::Setup();
// Add default mouse input behavior
MouseBehavior = NewObject<UClickDragInputBehavior>();
MouseBehavior->Initialize(this);
MouseBehavior->SetDefaultPriority(FInputCapturePriority(FInputCapturePriority::DEFAULT_GIZMO_PRIORITY));
AddInputBehavior(MouseBehavior);
UMouseHoverBehavior* HoverBehavior = NewObject<UMouseHoverBehavior>();
HoverBehavior->Initialize(this);
HoverBehavior->SetDefaultPriority(FInputCapturePriority(FInputCapturePriority::DEFAULT_GIZMO_PRIORITY));
AddInputBehavior(HoverBehavior);
AxisSource = NewObject<UGizmoConstantAxisSource>(this);
ParameterSource = NewObject<UGizmoLocalFloatParameterSource>(this);
HitTarget = NewObject<UGizmoComponentHitTarget>(this);
StateTarget = NewObject<UGizmoNilStateTarget>(this);
bInInteraction = false;
}
FInputRayHit UAxisPositionGizmo::CanBeginClickDragSequence(const FInputDeviceRay& PressPos)
{
FInputRayHit GizmoHit;
if (HitTarget && AxisSource && ParameterSource)
{
GizmoHit = HitTarget->IsHit(PressPos);
if (GizmoHit.bHit)
{
LastHitPosition = PressPos.WorldRay.PointAt(GizmoHit.HitDepth);
}
}
return GizmoHit;
}
void UAxisPositionGizmo::OnClickPress(const FInputDeviceRay& PressPos)
{
InteractionOrigin = LastHitPosition;
InteractionAxis = AxisSource->GetDirection();
// Find interaction start point and parameter.
FVector NearestPt; float RayNearestParam;
GizmoMath::NearestPointOnLineToRay(InteractionOrigin, InteractionAxis,
PressPos.WorldRay.Origin, PressPos.WorldRay.Direction,
InteractionStartPoint, InteractionStartParameter,
NearestPt, RayNearestParam);
FVector AxisOrigin = AxisSource->GetOrigin();
float DirectionSign = FVector::DotProduct(InteractionStartPoint - AxisOrigin, InteractionAxis);
ParameterSign = (bEnableSignedAxis && DirectionSign < 0) ? -1.0f : 1.0f;
// Figure out how the parameter would need to be adjusted to bring the axis origin to the
// interaction start point. This is used when aligning the axis origin to a custom destination.
float AxisOriginParamValue;
GizmoMath::NearestPointOnLine(InteractionOrigin, InteractionAxis, AxisOrigin,
NearestPt, AxisOriginParamValue);
InteractionStartAxisOriginParameterOffset = InteractionStartParameter - AxisOriginParamValue;
InteractionCurPoint = InteractionStartPoint;
InteractionStartParameter *= ParameterSign;
InteractionCurParameter = InteractionStartParameter;
InitialTargetParameter = ParameterSource->GetParameter();
ParameterSource->BeginModify();
bInInteraction = true;
if (HitTarget)
{
HitTarget->UpdateInteractingState(bInInteraction);
}
if (StateTarget)
{
StateTarget->BeginUpdate();
}
}
void UAxisPositionGizmo::OnClickDrag(const FInputDeviceRay& DragPos)
{
FVector HitPoint;
// See if we should use the custom destination function.
FCustomDestinationParams Params;
Params.WorldRay = &DragPos.WorldRay;
if (ShouldUseCustomDestinationFunc() && CustomDestinationFunc(Params, HitPoint))
{
GizmoMath::NearestPointOnLine(InteractionOrigin, InteractionAxis, HitPoint,
InteractionCurPoint, InteractionCurParameter);
InteractionCurParameter += bCustomDestinationAlignsAxisOrigin ? InteractionStartAxisOriginParameterOffset : 0;
}
else
{
float RayNearestParam; float AxisNearestParam;
FVector RayNearestPt;
GizmoMath::NearestPointOnLineToRay(InteractionOrigin, InteractionAxis,
DragPos.WorldRay.Origin, DragPos.WorldRay.Direction,
InteractionCurPoint, AxisNearestParam,
RayNearestPt, RayNearestParam);
InteractionCurParameter = ParameterSign * AxisNearestParam;
}
float DeltaParam = InteractionCurParameter - InteractionStartParameter;
float NewParamValue = InitialTargetParameter + DeltaParam;
ParameterSource->SetParameter(NewParamValue);
}
void UAxisPositionGizmo::OnClickRelease(const FInputDeviceRay& ReleasePos)
{
check(bInInteraction);
ParameterSource->EndModify();
if (StateTarget)
{
StateTarget->EndUpdate();
}
bInInteraction = false;
if (HitTarget)
{
HitTarget->UpdateInteractingState(bInInteraction);
}
}
void UAxisPositionGizmo::OnTerminateDragSequence()
{
check(bInInteraction);
ParameterSource->EndModify();
if (StateTarget)
{
StateTarget->EndUpdate();
}
bInInteraction = false;
if (HitTarget)
{
HitTarget->UpdateInteractingState(bInInteraction);
}
}
FInputRayHit UAxisPositionGizmo::BeginHoverSequenceHitTest(const FInputDeviceRay& PressPos)
{
FInputRayHit GizmoHit;
if (HitTarget)
{
GizmoHit = HitTarget->IsHit(PressPos);
}
return GizmoHit;
}
void UAxisPositionGizmo::OnBeginHover(const FInputDeviceRay& DevicePos)
{
HitTarget->UpdateHoverState(true);
}
bool UAxisPositionGizmo::OnUpdateHover(const FInputDeviceRay& DevicePos)
{
// not necessary...
HitTarget->UpdateHoverState(true);
return true;
}
void UAxisPositionGizmo::OnEndHover()
{
HitTarget->UpdateHoverState(false);
}