2019-12-26 14:45:42 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
2019-10-01 20:41:42 -04:00
|
|
|
|
|
|
|
|
#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
|
2021-01-14 19:07:52 -04:00
|
|
|
MouseBehavior = NewObject<UClickDragInputBehavior>();
|
2019-10-01 20:41:42 -04:00
|
|
|
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();
|
|
|
|
|
|
2021-01-14 19:07:52 -04:00
|
|
|
// Find interaction start point and parameter.
|
|
|
|
|
FVector NearestPt; float RayNearestParam;
|
2019-10-01 20:41:42 -04:00
|
|
|
GizmoMath::NearestPointOnLineToRay(InteractionOrigin, InteractionAxis,
|
|
|
|
|
PressPos.WorldRay.Origin, PressPos.WorldRay.Direction,
|
|
|
|
|
InteractionStartPoint, InteractionStartParameter,
|
2021-01-14 19:07:52 -04:00
|
|
|
NearestPt, RayNearestParam);
|
2019-10-01 20:41:42 -04:00
|
|
|
|
2021-01-14 19:07:52 -04:00
|
|
|
FVector AxisOrigin = AxisSource->GetOrigin();
|
|
|
|
|
|
|
|
|
|
float DirectionSign = FVector::DotProduct(InteractionStartPoint - AxisOrigin, InteractionAxis);
|
2020-01-27 20:11:15 -05:00
|
|
|
ParameterSign = (bEnableSignedAxis && DirectionSign < 0) ? -1.0f : 1.0f;
|
|
|
|
|
|
2021-01-14 19:07:52 -04:00
|
|
|
// 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;
|
|
|
|
|
|
2019-10-01 20:41:42 -04:00
|
|
|
InteractionCurPoint = InteractionStartPoint;
|
2020-01-27 20:11:15 -05:00
|
|
|
InteractionStartParameter *= ParameterSign;
|
2019-10-01 20:41:42 -04:00
|
|
|
InteractionCurParameter = InteractionStartParameter;
|
|
|
|
|
|
|
|
|
|
InitialTargetParameter = ParameterSource->GetParameter();
|
|
|
|
|
ParameterSource->BeginModify();
|
|
|
|
|
|
|
|
|
|
bInInteraction = true;
|
|
|
|
|
|
2021-04-05 01:34:07 -04:00
|
|
|
if (HitTarget)
|
|
|
|
|
{
|
|
|
|
|
HitTarget->UpdateInteractingState(bInInteraction);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-01 20:41:42 -04:00
|
|
|
if (StateTarget)
|
|
|
|
|
{
|
|
|
|
|
StateTarget->BeginUpdate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UAxisPositionGizmo::OnClickDrag(const FInputDeviceRay& DragPos)
|
|
|
|
|
{
|
2021-01-14 19:07:52 -04:00
|
|
|
FVector HitPoint;
|
2019-10-01 20:41:42 -04:00
|
|
|
|
2021-01-14 19:07:52 -04:00
|
|
|
// 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);
|
2021-01-28 13:03:54 -04:00
|
|
|
InteractionCurParameter += bCustomDestinationAlignsAxisOrigin ? InteractionStartAxisOriginParameterOffset : 0;
|
2021-01-14 19:07:52 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
float RayNearestParam; float AxisNearestParam;
|
|
|
|
|
FVector RayNearestPt;
|
|
|
|
|
GizmoMath::NearestPointOnLineToRay(InteractionOrigin, InteractionAxis,
|
|
|
|
|
DragPos.WorldRay.Origin, DragPos.WorldRay.Direction,
|
|
|
|
|
InteractionCurPoint, AxisNearestParam,
|
|
|
|
|
RayNearestPt, RayNearestParam);
|
|
|
|
|
|
|
|
|
|
InteractionCurParameter = ParameterSign * AxisNearestParam;
|
|
|
|
|
}
|
2019-10-01 20:41:42 -04:00
|
|
|
|
|
|
|
|
float DeltaParam = InteractionCurParameter - InteractionStartParameter;
|
2021-01-14 19:07:52 -04:00
|
|
|
float NewParamValue = InitialTargetParameter + DeltaParam;
|
2019-10-01 20:41:42 -04:00
|
|
|
|
2021-01-14 19:07:52 -04:00
|
|
|
ParameterSource->SetParameter(NewParamValue);
|
2019-10-01 20:41:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UAxisPositionGizmo::OnClickRelease(const FInputDeviceRay& ReleasePos)
|
|
|
|
|
{
|
|
|
|
|
check(bInInteraction);
|
|
|
|
|
|
|
|
|
|
ParameterSource->EndModify();
|
|
|
|
|
if (StateTarget)
|
|
|
|
|
{
|
|
|
|
|
StateTarget->EndUpdate();
|
|
|
|
|
}
|
|
|
|
|
bInInteraction = false;
|
2021-04-05 01:34:07 -04:00
|
|
|
|
|
|
|
|
if (HitTarget)
|
|
|
|
|
{
|
|
|
|
|
HitTarget->UpdateInteractingState(bInInteraction);
|
|
|
|
|
}
|
2019-10-01 20:41:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UAxisPositionGizmo::OnTerminateDragSequence()
|
|
|
|
|
{
|
|
|
|
|
check(bInInteraction);
|
|
|
|
|
|
|
|
|
|
ParameterSource->EndModify();
|
|
|
|
|
if (StateTarget)
|
|
|
|
|
{
|
|
|
|
|
StateTarget->EndUpdate();
|
|
|
|
|
}
|
|
|
|
|
bInInteraction = false;
|
2021-04-05 01:34:07 -04:00
|
|
|
|
|
|
|
|
if (HitTarget)
|
|
|
|
|
{
|
|
|
|
|
HitTarget->UpdateInteractingState(bInInteraction);
|
|
|
|
|
}
|
2019-10-01 20:41:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|