UI焦点问题
导言
最近在做道具轮盘,大致流程是按下某个按键,弹出一个轮盘,使用鼠标或者手柄来选择某个插槽。 本篇记录一下实现中的一些坑。
实现原理
FVector2D URadialWheelWidget::GetWheelCenterPosition()
{
if (!WheelOverlay)
{
return FVector2D::ZeroVector;
}
// 获取 Overlay 的几何信息
const FGeometry& Geometry = WheelOverlay->GetCachedGeometry();
// 本地中心点
const FVector2D LocalCenter = Geometry.GetLocalSize() * 0.5f;
// 转换到绝对屏幕坐标
FVector2D PixelPosition;
FVector2D ViewportPosition;
USlateBlueprintLibrary::LocalToViewport(this, Geometry, LocalCenter, PixelPosition, ViewportPosition);
// 加上DPI缩放
return ViewportPosition * UWidgetLayoutLibrary::GetViewportScale(this);
}
void URadialWheelWidget::CalcAngleAndDistanceFromDir(const FVector2D& Dir, float& OutAngle, double& OutDistance) const
{
OutDistance = Dir.Size();
if (!Dir.IsNearlyZero())
{
// Y 翻转
OutAngle = FMath::RadiansToDegrees(FMath::Atan2(Dir.Y, Dir.X)) + 90.f;
OutAngle = FRotator::ClampAxis(OutAngle);
}
else
{
OutDistance = 0.0;
OutAngle = 0.f;
}
}
FVector2D URadialWheelWidget::GetMousePosition()
{
float Angle = 0.f;
double Distance = 0.0;
//1. 获取鼠标在屏幕中的绝对位置(考虑DPI缩放)
const FVector2D MousePos = UWidgetLayoutLibrary::GetMousePositionOnViewport(this) *
UWidgetLayoutLibrary::GetViewportScale(this);
//2.获取轮盘中心坐标
const FVector2D Center = GetWheelCenterPosition();
//3.计算偏移向量
const FVector2D Dir = MousePos - Center;
//4.计算角度和距离
CalcAngleAndDistanceFromDir(Dir, Angle, Distance);
}
大约 1 分钟