406 lines
12 KiB
C++
406 lines
12 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "BaseGizmos/ParameterToTransformAdapters.h"
|
|
#include "BaseGizmos/GizmoMath.h"
|
|
|
|
|
|
void UGizmoAxisTranslationParameterSource::SetParameter(float NewValue)
|
|
{
|
|
Parameter = NewValue;
|
|
LastChange.CurrentValue = NewValue;
|
|
|
|
double UseDelta = LastChange.GetChangeDelta();
|
|
|
|
// check for any constraints on the delta value
|
|
double SnappedDelta = 0;
|
|
if (AxisDeltaConstraintFunction(UseDelta, SnappedDelta))
|
|
{
|
|
UseDelta = SnappedDelta;
|
|
}
|
|
|
|
// construct translation as delta from initial position
|
|
FVector Translation = UseDelta * CurTranslationAxis;
|
|
|
|
// translate the initial transform
|
|
FTransform NewTransform = InitialTransform;
|
|
NewTransform.AddToTranslation(Translation);
|
|
|
|
// apply position constraint
|
|
FVector SnappedPos;
|
|
if (PositionConstraintFunction(NewTransform.GetTranslation(), SnappedPos))
|
|
{
|
|
FVector SnappedLinePos = GizmoMath::ProjectPointOntoLine(SnappedPos, CurTranslationOrigin, CurTranslationAxis);
|
|
NewTransform.SetTranslation(SnappedLinePos);
|
|
}
|
|
|
|
TransformSource->SetTransform(NewTransform);
|
|
|
|
OnParameterChanged.Broadcast(this, LastChange);
|
|
}
|
|
|
|
void UGizmoAxisTranslationParameterSource::BeginModify()
|
|
{
|
|
check(AxisSource);
|
|
|
|
LastChange = FGizmoFloatParameterChange(Parameter);
|
|
|
|
InitialTransform = TransformSource->GetTransform();
|
|
CurTranslationAxis = AxisSource->GetDirection();
|
|
CurTranslationOrigin = AxisSource->GetOrigin();
|
|
}
|
|
|
|
void UGizmoAxisTranslationParameterSource::EndModify()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UGizmoPlaneTranslationParameterSource::SetParameter(const FVector2D& NewValue)
|
|
{
|
|
Parameter = NewValue;
|
|
LastChange.CurrentValue = NewValue;
|
|
|
|
// construct translation as delta from initial position
|
|
FVector2D Delta = LastChange.GetChangeDelta();
|
|
double UseDeltaX = Delta.X;
|
|
double UseDeltaY = Delta.Y;
|
|
|
|
// check for any constraints on the delta value
|
|
double SnappedDeltaX = 0, SnappedDeltaY = 0;
|
|
if (AxisXDeltaConstraintFunction(UseDeltaX, SnappedDeltaX))
|
|
{
|
|
UseDeltaX = SnappedDeltaX;
|
|
}
|
|
if (AxisYDeltaConstraintFunction(UseDeltaY, SnappedDeltaY))
|
|
{
|
|
UseDeltaY = SnappedDeltaY;
|
|
}
|
|
|
|
FVector Translation = UseDeltaX*CurTranslationAxisX + UseDeltaY*CurTranslationAxisY;
|
|
|
|
// apply translation to initial transform
|
|
FTransform NewTransform = InitialTransform;
|
|
NewTransform.AddToTranslation(Translation);
|
|
|
|
// apply position constraint
|
|
FVector SnappedPos;
|
|
if (PositionConstraintFunction(NewTransform.GetTranslation(), SnappedPos))
|
|
{
|
|
FVector PlanePos = GizmoMath::ProjectPointOntoPlane(SnappedPos, CurTranslationOrigin, CurTranslationNormal);
|
|
NewTransform.SetTranslation(PlanePos);
|
|
}
|
|
|
|
TransformSource->SetTransform(NewTransform);
|
|
|
|
OnParameterChanged.Broadcast(this, LastChange);
|
|
}
|
|
|
|
void UGizmoPlaneTranslationParameterSource::BeginModify()
|
|
{
|
|
check(AxisSource);
|
|
|
|
LastChange = FGizmoVec2ParameterChange(Parameter);
|
|
|
|
// save initial transformation and axis information
|
|
InitialTransform = TransformSource->GetTransform();
|
|
CurTranslationOrigin = AxisSource->GetOrigin();
|
|
AxisSource->GetAxisFrame(CurTranslationNormal, CurTranslationAxisX, CurTranslationAxisY);
|
|
}
|
|
|
|
void UGizmoPlaneTranslationParameterSource::EndModify()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
void UGizmoAxisRotationParameterSource::SetParameter(float NewValue)
|
|
{
|
|
Angle = NewValue;
|
|
LastChange.CurrentValue = NewValue;
|
|
|
|
double AngleDelta = LastChange.GetChangeDelta();
|
|
double SnappedDelta;
|
|
if (AngleDeltaConstraintFunction(AngleDelta, SnappedDelta))
|
|
{
|
|
AngleDelta = SnappedDelta;
|
|
}
|
|
|
|
// construct rotation as delta from initial position
|
|
FQuat DeltaRotation(CurRotationAxis, AngleDelta);
|
|
DeltaRotation = RotationConstraintFunction(DeltaRotation);
|
|
|
|
// rotate the vector from the rotation origin to the transform origin,
|
|
// to get the translation of the origin produced by the rotation
|
|
FVector DeltaPosition = InitialTransform.GetLocation() - CurRotationOrigin;
|
|
DeltaPosition = DeltaRotation * DeltaPosition;
|
|
FVector NewLocation = CurRotationOrigin + DeltaPosition;
|
|
|
|
// rotate the initial transform by the rotation
|
|
FQuat NewRotation = DeltaRotation * InitialTransform.GetRotation();
|
|
|
|
// construct new transform
|
|
FTransform NewTransform = InitialTransform;
|
|
NewTransform.SetLocation(NewLocation);
|
|
NewTransform.SetRotation(NewRotation);
|
|
TransformSource->SetTransform(NewTransform);
|
|
|
|
OnParameterChanged.Broadcast(this, LastChange);
|
|
}
|
|
|
|
|
|
void UGizmoAxisRotationParameterSource::BeginModify()
|
|
{
|
|
check(AxisSource != nullptr);
|
|
|
|
LastChange = FGizmoFloatParameterChange(Angle);
|
|
|
|
// save initial transformation and axis information
|
|
InitialTransform = TransformSource->GetTransform();
|
|
CurRotationAxis = AxisSource->GetDirection();
|
|
CurRotationOrigin = AxisSource->GetOrigin();
|
|
}
|
|
|
|
void UGizmoAxisRotationParameterSource::EndModify()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGizmoUniformScaleParameterSource::SetParameter(const FVector2D& NewValue)
|
|
{
|
|
Parameter = NewValue;
|
|
LastChange.CurrentValue = NewValue;
|
|
|
|
// Convert 2D parameter delta to a 1D uniform scale change
|
|
// This possibly be exposed as a TFunction to allow customization?
|
|
double SignedDelta = LastChange.GetChangeDelta().X + LastChange.GetChangeDelta().Y;
|
|
SignedDelta *= ScaleMultiplier;
|
|
|
|
FTransform NewTransform = InitialTransform;
|
|
const FVector StartScale = InitialTransform.GetScale3D();
|
|
|
|
double SnappedDelta;
|
|
bool bIsSnapped = false;
|
|
|
|
// if using snapping while scaling
|
|
if (ScaleAxisDeltaConstraintFunction(SignedDelta, SnappedDelta))
|
|
{
|
|
SignedDelta = SnappedDelta;
|
|
bIsSnapped = true;
|
|
}
|
|
|
|
FVector NewScale;
|
|
// if the initial scale is uniform and snapping is on, we can use an additive method to scale up or down
|
|
if (StartScale.IsUniform() && bIsSnapped)
|
|
{
|
|
NewScale = FVector(SignedDelta) + StartScale;
|
|
}
|
|
// otherwise, we need to use multiplication to scale
|
|
// ex: initial scale is (1,2,4) and scale delta is .5 -> next incremented scale should be (1.5, 3, 6)
|
|
// to preserve proportions. Addition would result in (1.5, 2.5, 4.5) which does not keep original proportions.
|
|
// Additionally, using multiplication when scale is uniform would result in an ex where InitScale=(2,2,2) and
|
|
// ScaleDelta = .5 where next scale would be (3,3,3), where the intermediate scale of (2.5,2.5,2.5) is unreachable
|
|
else
|
|
{
|
|
NewScale = SignedDelta * StartScale + StartScale;
|
|
}
|
|
|
|
// currently calling ScaleConstraintFunction has no effect (no changes made to SignedDelta) because this constraint function
|
|
// is intended to relate to WorldGridSnapping. Currently WorldGridSnapping has no effect on scaling, with or without normal snapping
|
|
// because the viewport scale mode fixes the transform space to local
|
|
SignedDelta = ScaleConstraintFunction(SignedDelta);
|
|
|
|
NewTransform.SetScale3D(NewScale);
|
|
|
|
TransformSource->SetTransform(NewTransform);
|
|
|
|
OnParameterChanged.Broadcast(this, LastChange);
|
|
}
|
|
|
|
void UGizmoUniformScaleParameterSource::BeginModify()
|
|
{
|
|
check(AxisSource);
|
|
|
|
LastChange = FGizmoVec2ParameterChange(Parameter);
|
|
|
|
// save initial transformation and axis information
|
|
InitialTransform = TransformSource->GetTransform();
|
|
CurScaleOrigin = AxisSource->GetOrigin();
|
|
// note: currently not used!
|
|
AxisSource->GetAxisFrame(CurScaleNormal, CurScaleAxisX, CurScaleAxisY);
|
|
}
|
|
|
|
void UGizmoUniformScaleParameterSource::EndModify()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UGizmoAxisScaleParameterSource::SetParameter(float NewValue)
|
|
{
|
|
Parameter = NewValue;
|
|
LastChange.CurrentValue = NewValue;
|
|
|
|
double ScaleDelta = LastChange.GetChangeDelta();
|
|
ScaleDelta *= ScaleMultiplier;
|
|
|
|
FTransform NewTransform = InitialTransform;
|
|
const FVector StartScale = InitialTransform.GetScale3D();
|
|
|
|
FVector NewScale;
|
|
double SnappedDelta;
|
|
|
|
// check for any constraints on the delta value
|
|
if (ScaleAxisDeltaConstraintFunction(ScaleDelta, SnappedDelta))
|
|
{
|
|
ScaleDelta = SnappedDelta;
|
|
// use additive scaling when snap is on
|
|
NewScale = StartScale + ScaleDelta * CurScaleAxis;
|
|
}
|
|
else
|
|
{
|
|
// use multiplicative scaling when snap is off
|
|
NewScale = StartScale * (FVector3d{1} + (ScaleDelta * CurScaleAxis));
|
|
}
|
|
|
|
// currently calling ScaleConstraintFunction has no effect (no changes made to ScaleDelta) because this constraint function
|
|
// is intended to relate to WorldGridSnapping. Currently WorldGridSnapping has no effect on scaling, with or without normal snapping
|
|
// because the viewport scale mode fixes the transform space to local
|
|
ScaleDelta = ScaleConstraintFunction(ScaleDelta);
|
|
|
|
if (bClampToZero)
|
|
{
|
|
NewScale = FVector::Max(FVector::ZeroVector, NewScale);
|
|
}
|
|
|
|
NewTransform.SetScale3D(NewScale);
|
|
|
|
TransformSource->SetTransform(NewTransform);
|
|
|
|
OnParameterChanged.Broadcast(this, LastChange);
|
|
}
|
|
|
|
void UGizmoAxisScaleParameterSource::BeginModify()
|
|
{
|
|
check(AxisSource);
|
|
|
|
LastChange = FGizmoFloatParameterChange(Parameter);
|
|
|
|
InitialTransform = TransformSource->GetTransform();
|
|
|
|
CurScaleAxis = AxisSource->GetDirection();
|
|
CurScaleOrigin = AxisSource->GetOrigin();
|
|
}
|
|
|
|
void UGizmoAxisScaleParameterSource::EndModify()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UGizmoPlaneScaleParameterSource::SetParameter(const FVector2D& NewValue)
|
|
{
|
|
Parameter = NewValue;
|
|
LastChange.CurrentValue = NewValue;
|
|
|
|
// construct Scale as delta from initial position
|
|
FVector2D ScaleDelta = LastChange.GetChangeDelta() * ScaleMultiplier;
|
|
|
|
if (bUseEqualScaling)
|
|
{
|
|
ScaleDelta = FVector2D(ScaleDelta.X + ScaleDelta.Y);
|
|
}
|
|
|
|
FTransform NewTransform = InitialTransform;
|
|
const FVector StartScale = InitialTransform.GetScale3D();
|
|
|
|
double UseScaleDeltaX = ScaleDelta.X;
|
|
double UseScaleDeltaY = ScaleDelta.Y;
|
|
|
|
FVector NewScale;
|
|
|
|
if (bUseEqualScaling)
|
|
{
|
|
double SnappedDeltaX = 0.0, SnappedDeltaY = 0.0;
|
|
bool bIsSnapped = true;
|
|
|
|
// if using snapping while scaling on X and Y axis
|
|
if (ScaleAxisXDeltaConstraintFunction(UseScaleDeltaX, SnappedDeltaX))
|
|
{
|
|
UseScaleDeltaX = SnappedDeltaX;
|
|
}
|
|
else
|
|
{
|
|
bIsSnapped = false;
|
|
}
|
|
if (ScaleAxisYDeltaConstraintFunction(UseScaleDeltaY, SnappedDeltaY))
|
|
{
|
|
UseScaleDeltaY = SnappedDeltaY;
|
|
}
|
|
else
|
|
{
|
|
bIsSnapped = false;
|
|
}
|
|
|
|
// determines if the initial scales of the 2 affected axes are equivalent, and if we can therefore use uniform scaling (additive function)
|
|
const FVector AffectedValuesVector = StartScale*CurScaleAxisX + StartScale*CurScaleAxisY;
|
|
const bool bIsUniformAcrossScaleAxes = (AffectedValuesVector.X == AffectedValuesVector.Y) || (AffectedValuesVector.X == AffectedValuesVector.Z) || (AffectedValuesVector.Y == AffectedValuesVector.Z);
|
|
|
|
// will use additive if scale is uniform across 2 axes of the plane AND snapping is on
|
|
if (bIsUniformAcrossScaleAxes && bIsSnapped)
|
|
{
|
|
// uses an additive function to scale when both initial values are equal
|
|
// ex: allows for a case where InitScale= (2,2,1) scaling by 1 across Z axis, next increment will be (3,3,1) instead of (4,4,1)
|
|
NewScale = StartScale + UseScaleDeltaX*CurScaleAxisX + UseScaleDeltaY*CurScaleAxisY;
|
|
}
|
|
else
|
|
{
|
|
NewScale = StartScale + (UseScaleDeltaX * StartScale * CurScaleAxisX) + (UseScaleDeltaY * StartScale * CurScaleAxisY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NewScale = StartScale + (UseScaleDeltaX * StartScale * CurScaleAxisX) + (UseScaleDeltaY * StartScale * CurScaleAxisY);
|
|
}
|
|
|
|
// currently calling ScaleConstraintFunction has no effect (no changes made to SignedDelta) because this constraint function
|
|
// is intended to relate to WorldGridSnapping. Currently WorldGridSnapping has no effect on scaling, with or without normal snapping
|
|
// because the viewport scale mode fixes the transform space to local
|
|
ScaleDelta = ScaleConstraintFunction(ScaleDelta);
|
|
|
|
if (bClampToZero)
|
|
{
|
|
NewScale = FVector::Max(NewScale, FVector::ZeroVector);
|
|
}
|
|
|
|
NewTransform.SetScale3D(NewScale);
|
|
|
|
TransformSource->SetTransform(NewTransform);
|
|
|
|
OnParameterChanged.Broadcast(this, LastChange);
|
|
}
|
|
|
|
void UGizmoPlaneScaleParameterSource::BeginModify()
|
|
{
|
|
check(AxisSource);
|
|
|
|
LastChange = FGizmoVec2ParameterChange(Parameter);
|
|
|
|
// save initial transformation and axis information
|
|
InitialTransform = TransformSource->GetTransform();
|
|
CurScaleOrigin = AxisSource->GetOrigin();
|
|
AxisSource->GetAxisFrame(CurScaleNormal, CurScaleAxisX, CurScaleAxisY);
|
|
}
|
|
|
|
void UGizmoPlaneScaleParameterSource::EndModify()
|
|
{
|
|
} |