You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#jira UETOOL-4781 #rb ryan.schmidt, brooke.hubert, jimmy.andrews #preflight 6272b741e95a8b960ebfba9c [CL 20050122 by Christina TempelaarL in ue5-main branch]
409 lines
11 KiB
C++
409 lines
11 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "BaseGizmos/GizmoElementBase.h"
|
|
#include "BaseGizmos/GizmoInterfaces.h"
|
|
#include "BaseGizmos/GizmoRenderingUtil.h"
|
|
#include "Materials/MaterialInterface.h"
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LogGizmoElements, Log, All);
|
|
|
|
bool UGizmoElementBase::GetViewDependentVisibility(const FSceneView* View, const FTransform& InLocalToWorldTransform, const FVector& InLocalCenter) const
|
|
{
|
|
if (ViewDependentType == EGizmoElementViewDependentType::None || ViewAlignType == EGizmoElementViewAlignType::PointOnly || ViewAlignType == EGizmoElementViewAlignType::PointEye)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
FVector ViewDir;
|
|
|
|
if (View->IsPerspectiveProjection())
|
|
{
|
|
|
|
FVector WorldCenter = InLocalToWorldTransform.TransformPosition(InLocalCenter);
|
|
ViewDir = WorldCenter - View->ViewLocation;
|
|
ViewDir.Normalize();
|
|
}
|
|
else
|
|
{
|
|
ViewDir = View->GetViewDirection();
|
|
}
|
|
|
|
bool bVisibleViewDependent;
|
|
if (ViewDependentType == EGizmoElementViewDependentType::Axis)
|
|
{
|
|
bVisibleViewDependent = FMath::Abs(FVector::DotProduct(ViewDependentAxis, ViewDir)) < DefaultViewAlignAxialMaxCosAngleTol;
|
|
}
|
|
else // (ViewDependentType == EGizmoElementViewDependentType::Plane)
|
|
{
|
|
bVisibleViewDependent = FMath::Abs(FVector::DotProduct(ViewDependentAxis, ViewDir)) > DefaultViewAlignPlanarMinCosAngleTol;
|
|
}
|
|
|
|
return bVisibleViewDependent;
|
|
|
|
}
|
|
|
|
|
|
bool UGizmoElementBase::GetViewAlignRot(const FSceneView* View, const FTransform& InLocalToWorldTransform, const FVector& InLocalCenter, FQuat& OutAlignRot) const
|
|
{
|
|
if (ViewAlignType == EGizmoElementViewAlignType::None)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
FVector Scale = InLocalToWorldTransform.GetScale3D();
|
|
if (!FMath::IsNearlyEqual(Scale.X, Scale.Y, KINDA_SMALL_NUMBER) || !FMath::IsNearlyEqual(Scale.X, Scale.Z, KINDA_SMALL_NUMBER))
|
|
{
|
|
// Warn that non-uniform scale is not currently supported
|
|
bool bNonUniformScaleWarning = true;
|
|
if (bNonUniformScaleWarning)
|
|
{
|
|
UE_LOG(LogGizmoElements, Warning, TEXT("Gizmo element library view-dependent alignment does not currently support non-uniform scale (%f %f %f)."),
|
|
Scale.X, Scale.Y, Scale.Z);
|
|
bNonUniformScaleWarning = false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
FVector LocalViewDir;
|
|
|
|
FTransform WorldToLocalTransform = InLocalToWorldTransform.Inverse();
|
|
|
|
if (View->IsPerspectiveProjection())
|
|
{
|
|
FVector LocalViewLocation = WorldToLocalTransform.TransformPosition(View->ViewLocation);
|
|
LocalViewDir = InLocalCenter - LocalViewLocation;
|
|
LocalViewDir.Normalize();
|
|
}
|
|
else
|
|
{
|
|
FVector WorldViewDir = View->GetViewDirection();
|
|
LocalViewDir = WorldToLocalTransform.GetRotation().RotateVector(WorldViewDir);
|
|
LocalViewDir.Normalize();
|
|
}
|
|
|
|
if (ViewAlignType == EGizmoElementViewAlignType::PointOnly)
|
|
{
|
|
OutAlignRot = FQuat::FindBetweenNormals(ViewAlignNormal, -LocalViewDir);
|
|
}
|
|
else if (ViewAlignType == EGizmoElementViewAlignType::PointEye)
|
|
{
|
|
FVector Right = ViewAlignAxis ^ ViewAlignNormal;
|
|
Right.Normalize();
|
|
FVector Up = ViewAlignNormal ^ Right;
|
|
|
|
FMatrix LocalToCanonicalBasis(
|
|
FPlane(ViewAlignNormal.X, Right.X, Up.X, 0.0),
|
|
FPlane(ViewAlignNormal.Y, Right.Y, Up.Y, 0.0),
|
|
FPlane(ViewAlignNormal.Z, Right.Z, Up.Z, 0.0),
|
|
FPlane::ZeroVector);
|
|
|
|
FVector LocalViewUp = WorldToLocalTransform.TransformVector(View->GetViewUp());
|
|
FVector TargetFwd = -LocalViewDir;
|
|
FVector TargetRight = LocalViewUp ^ TargetFwd;
|
|
TargetRight.Normalize();
|
|
FVector TargetUp = TargetFwd ^ TargetRight;
|
|
|
|
FMatrix CanonicalToAlignRotBasis(
|
|
FPlane(TargetFwd.X, TargetFwd.Y, TargetFwd.Z, 0.0),
|
|
FPlane(TargetRight.X, TargetRight.Y, TargetRight.Z, 0.0),
|
|
FPlane(TargetUp.X, TargetUp.Y, TargetUp.Z, 0.0),
|
|
FPlane::ZeroVector);
|
|
|
|
FMatrix LocalToAligned = LocalToCanonicalBasis * CanonicalToAlignRotBasis;
|
|
OutAlignRot = LocalToAligned.ToQuat();
|
|
OutAlignRot.Normalize();
|
|
}
|
|
else if (ViewAlignType == EGizmoElementViewAlignType::Axial)
|
|
{
|
|
// if Axis and Dir are almost coincident, do not adjust the rotation
|
|
if ((FMath::Abs(FVector::DotProduct(ViewAlignAxis, -LocalViewDir))) >= DefaultViewAlignAxialMaxCosAngleTol)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
FVector TargetRight = -LocalViewDir ^ ViewAlignAxis;
|
|
TargetRight.Normalize();
|
|
FVector TargetNormal = ViewAlignAxis ^ TargetRight;
|
|
TargetNormal.Normalize();
|
|
OutAlignRot = FQuat::FindBetweenNormals(ViewAlignNormal, TargetNormal);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
const UMaterialInterface* UGizmoElementBase::GetCurrentMaterial(const FRenderTraversalState& RenderState) const
|
|
{
|
|
EGizmoElementInteractionState CurrentState;
|
|
|
|
if (RenderState.InteractionState == EGizmoElementInteractionState::None)
|
|
{
|
|
CurrentState = ElementInteractionState;
|
|
}
|
|
else
|
|
{
|
|
CurrentState = RenderState.InteractionState;
|
|
}
|
|
|
|
if (CurrentState == EGizmoElementInteractionState::Hovering)
|
|
{
|
|
if (RenderState.HoverMaterial.IsValid())
|
|
{
|
|
return RenderState.HoverMaterial.Get();
|
|
}
|
|
return HoverMaterial;
|
|
}
|
|
|
|
if (CurrentState == EGizmoElementInteractionState::Interacting)
|
|
{
|
|
if (RenderState.InteractMaterial.IsValid())
|
|
{
|
|
return RenderState.InteractMaterial.Get();
|
|
}
|
|
return InteractMaterial;
|
|
}
|
|
|
|
// CurrentState is None, so just return the regular material
|
|
if (RenderState.Material.IsValid())
|
|
{
|
|
return RenderState.Material.Get();
|
|
}
|
|
return Material;
|
|
}
|
|
|
|
void UGizmoElementBase::CacheRenderState(const FTransform& InLocalToWorldState, bool InVisibleViewDependent)
|
|
{
|
|
CachedLocalToWorldTransform = InLocalToWorldState;
|
|
bHasCachedLocalToWorldTransform = true;
|
|
bCachedVisibleViewDependent = InVisibleViewDependent;
|
|
}
|
|
|
|
void UGizmoElementBase::ResetCachedRenderState()
|
|
{
|
|
bHasCachedLocalToWorldTransform = false;
|
|
bCachedVisibleViewDependent = true;
|
|
}
|
|
|
|
void UGizmoElementBase::UpdateRenderTraversalState(FRenderTraversalState& InRenderTraversalState)
|
|
{
|
|
if (InRenderTraversalState.InteractionState == EGizmoElementInteractionState::None)
|
|
{
|
|
InRenderTraversalState.InteractionState = ElementInteractionState;
|
|
}
|
|
if (!InRenderTraversalState.HoverMaterial.IsValid())
|
|
{
|
|
InRenderTraversalState.HoverMaterial = HoverMaterial;
|
|
}
|
|
if (!InRenderTraversalState.InteractMaterial.IsValid())
|
|
{
|
|
InRenderTraversalState.InteractMaterial = InteractMaterial;
|
|
}
|
|
if (!InRenderTraversalState.Material.IsValid())
|
|
{
|
|
InRenderTraversalState.Material = Material;
|
|
}
|
|
}
|
|
|
|
bool UGizmoElementBase::IsVisible() const
|
|
{
|
|
bool bVisible = static_cast<uint8>(ElementState) & static_cast<uint8>(EGizmoElementState::Visible);
|
|
return (bEnabled && bVisible);
|
|
}
|
|
|
|
bool UGizmoElementBase::IsHittable() const
|
|
{
|
|
bool bHittable = static_cast<uint8>(ElementState) & static_cast<uint8>(EGizmoElementState::Hittable);
|
|
return (bEnabled && bHittable);
|
|
}
|
|
|
|
bool UGizmoElementBase::IsHittableInView() const
|
|
{
|
|
return (IsHittable() && bHasCachedLocalToWorldTransform && (!IsVisible() || bCachedVisibleViewDependent));
|
|
}
|
|
|
|
void UGizmoElementBase::SetEnabled(bool InEnabled)
|
|
{
|
|
bEnabled = InEnabled;
|
|
}
|
|
|
|
bool UGizmoElementBase::GetEnabled() const
|
|
{
|
|
return bEnabled;
|
|
}
|
|
void UGizmoElementBase::SetPartIdentifier(uint32 InPartIdentifier)
|
|
{
|
|
PartIdentifier = InPartIdentifier;
|
|
}
|
|
|
|
uint32 UGizmoElementBase::GetPartIdentifier()
|
|
{
|
|
return PartIdentifier;
|
|
}
|
|
|
|
void UGizmoElementBase::SetElementState(EGizmoElementState InElementState)
|
|
{
|
|
ElementState = InElementState;
|
|
}
|
|
|
|
EGizmoElementState UGizmoElementBase::GetElementState() const
|
|
{
|
|
return ElementState;
|
|
}
|
|
|
|
void UGizmoElementBase::SetElementInteractionState(EGizmoElementInteractionState InElementInteractionState)
|
|
{
|
|
ElementInteractionState = InElementInteractionState;
|
|
}
|
|
|
|
EGizmoElementInteractionState UGizmoElementBase::GetElementInteractionState() const
|
|
{
|
|
return ElementInteractionState;
|
|
}
|
|
|
|
void UGizmoElementBase::UpdatePartHittableState(bool bHittable, uint32 InPartIdentifier)
|
|
{
|
|
if (InPartIdentifier == PartIdentifier)
|
|
{
|
|
uint8 State = static_cast<uint8>(ElementState);
|
|
uint8 HittableMask = static_cast<uint8>(EGizmoElementState::Hittable);
|
|
uint8 NewState = (bHittable ? State | HittableMask : State & (~HittableMask));
|
|
ElementState = static_cast<EGizmoElementState>(NewState);
|
|
}
|
|
}
|
|
|
|
void UGizmoElementBase::UpdatePartVisibleState(bool bVisible, uint32 InPartIdentifier)
|
|
{
|
|
if (InPartIdentifier == PartIdentifier)
|
|
{
|
|
uint8 State = static_cast<uint8>(ElementState);
|
|
uint8 VisibleMask = static_cast<uint8>(EGizmoElementState::Visible);
|
|
uint8 NewState = (bVisible ? State | VisibleMask : State & (~VisibleMask));
|
|
ElementState = static_cast<EGizmoElementState>(NewState);
|
|
}
|
|
}
|
|
|
|
void UGizmoElementBase::UpdatePartInteractionState(EGizmoElementInteractionState InInteractionState, uint32 InPartIdentifier)
|
|
{
|
|
if (InPartIdentifier == PartIdentifier)
|
|
{
|
|
ElementInteractionState = InInteractionState;
|
|
}
|
|
}
|
|
|
|
void UGizmoElementBase::SetViewDependentType(EGizmoElementViewDependentType InViewDependentType)
|
|
{
|
|
ViewDependentType = InViewDependentType;
|
|
}
|
|
|
|
EGizmoElementViewDependentType UGizmoElementBase::GetViewDependentType() const
|
|
{
|
|
return ViewDependentType;
|
|
}
|
|
|
|
void UGizmoElementBase::SetViewDependentAngleTol(float InAngleTol)
|
|
{
|
|
ViewDependentAngleTol = InAngleTol;
|
|
ViewDependentAxialMaxCosAngleTol = FMath::Abs(FMath::Cos(ViewDependentAngleTol));
|
|
ViewDependentPlanarMinCosAngleTol = FMath::Abs(FMath::Cos(HALF_PI + ViewDependentAngleTol));
|
|
}
|
|
|
|
float UGizmoElementBase::GetViewDependentAngleTol() const
|
|
{
|
|
return ViewDependentAngleTol;
|
|
}
|
|
|
|
void UGizmoElementBase::SetViewDependentAxis(FVector InViewDependentAxis)
|
|
{
|
|
ViewDependentAxis = InViewDependentAxis;
|
|
ViewDependentAxis.Normalize();
|
|
}
|
|
|
|
FVector UGizmoElementBase::GetViewDependentAxis() const
|
|
{
|
|
return ViewDependentAxis;
|
|
}
|
|
|
|
void UGizmoElementBase::SetViewAlignType(EGizmoElementViewAlignType InViewAlignType)
|
|
{
|
|
ViewAlignType = InViewAlignType;
|
|
}
|
|
|
|
EGizmoElementViewAlignType UGizmoElementBase::GetViewAlignType() const
|
|
{
|
|
return ViewAlignType;
|
|
}
|
|
|
|
void UGizmoElementBase::SetViewAlignAxis(FVector InViewAlignAxis)
|
|
{
|
|
ViewAlignAxis = InViewAlignAxis;
|
|
ViewAlignAxis.Normalize();
|
|
}
|
|
|
|
FVector UGizmoElementBase::GetViewAlignAxis() const
|
|
{
|
|
return ViewAlignAxis;
|
|
}
|
|
|
|
void UGizmoElementBase::SetViewAlignNormal(FVector InViewAlignNormal)
|
|
{
|
|
ViewAlignNormal = InViewAlignNormal;
|
|
ViewAlignNormal.Normalize();
|
|
}
|
|
|
|
FVector UGizmoElementBase::GetViewAlignNormal() const
|
|
{
|
|
return ViewAlignNormal;
|
|
}
|
|
|
|
void UGizmoElementBase::SetViewAlignAxialAngleTol(float InAngleTol)
|
|
{
|
|
ViewAlignAxialAngleTol = InAngleTol;
|
|
ViewAlignAxialMaxCosAngleTol = FMath::Abs(FMath::Cos(ViewAlignAxialAngleTol));
|
|
}
|
|
|
|
float UGizmoElementBase::GetViewAlignAxialAngleTol() const
|
|
{
|
|
return ViewAlignAxialAngleTol;
|
|
}
|
|
|
|
void UGizmoElementBase::SetMaterial(UMaterialInterface* InMaterial)
|
|
{
|
|
Material = InMaterial;
|
|
}
|
|
|
|
UMaterialInterface* UGizmoElementBase::GetMaterial() const
|
|
{
|
|
return Material;
|
|
}
|
|
|
|
void UGizmoElementBase::SetHoverMaterial(UMaterialInterface* InHoverMaterial)
|
|
{
|
|
HoverMaterial = InHoverMaterial;
|
|
}
|
|
|
|
UMaterialInterface* UGizmoElementBase::GetHoverMaterial() const
|
|
{
|
|
return HoverMaterial;
|
|
}
|
|
|
|
void UGizmoElementBase::SetInteractMaterial(UMaterialInterface* InInteractMaterial)
|
|
{
|
|
InteractMaterial = InInteractMaterial;
|
|
}
|
|
|
|
UMaterialInterface* UGizmoElementBase::GetInteractMaterial() const
|
|
{
|
|
return InteractMaterial;
|
|
}
|
|
|
|
void UGizmoElementBase::SetVertexColor(const FColor& InVertexColor)
|
|
{
|
|
VertexColor = InVertexColor;
|
|
}
|
|
|
|
FColor UGizmoElementBase::GetVertexColor() const
|
|
{
|
|
return VertexColor;
|
|
}
|
|
|
|
|