WidgetLibrary = WidgetLibrary or {} --- 设置 ---@param widget UUserWidget ---@param offset float function WidgetLibrary.SetWidgetToRightBorder(widget, offset) if not widget then return end local slot = WidgetLayoutLibrary.SlotAsCanvasSlot(widget) slot:SetAnchors({ Minimum = { X = 1, Y = 0 }, Maximum = { X = 1, Y = 0 } }) slot:SetAlignment({ X = 1, Y = 0 }) local offsets = slot:GetOffsets() slot:SetOffsets({ Left = offset, Right = offsets.Right, Bottom = offsets.Bottom, Top = offsets.Top }) end --- 为防止被清除做出的全局处理 function WidgetLibrary.BindButtonClicked(TargetButton, Func, Obj) TargetButton.OnClicked:Add(Func, Obj) end --- 为防止被清除做出的全局处理 function WidgetLibrary.BindButtonPressed(TargetButton, Func, Obj) TargetButton.OnPressed:Add(Func, Obj) end --- 为防止被清除做出的全局处理 function WidgetLibrary.BindButtonReleased(TargetButton, Func, Obj) TargetButton.OnReleased:Add(Func, Obj) end --- 绑定UI文本 function WidgetLibrary.TextBlockBindingPropertyText(TargetTextBlock, Func, Obj) TargetTextBlock:BindingProperty("Text", Func, Obj) end function WidgetLibrary.BindingPropertyChange(DelegationPropertyName, TargetWidgetItem, Func, Obj) TargetWidgetItem:BindingProperty(DelegationPropertyName, Func, Obj) end --- 直接绑定按键点击打开WidgetManager的页面 function WidgetLibrary.ButtonOnClickShowPanel(TargetButton, UIType, bIsShow) if bIsShow == nil then bIsShow = true end TargetButton.OnClicked:Add( function() if bIsShow then WidgetManager:ShowPanel(UIType, false) else WidgetManager:ClosePanel(UIType) end end ) end function WidgetLibrary.SliderOnValueChanged(Slider, Func, Obj) Slider.OnValueChanged:Add(Func, Obj) end --- Widget对齐到世界坐标 ---@ActorPos Vector ---@param CanvasSlot UCanvasPanelSlot function WidgetLibrary.SetWidgetAlignToWorldPosition(ActorPos, CanvasSlot) local IsOnScreen, WidgetPosition = WidgetLayoutLibrary.ProjectWorldLocationToWidgetPosition(UGCSystemLibrary.GetLocalPlayerController(), ActorPos, {X = 0, Y = 0}); -- 获取屏幕视口尺寸信息 local VPSize = WidgetLayoutLibrary.GetViewportSize(UGCSystemLibrary.GetLocalPlayerController()) local VPScale = WidgetLayoutLibrary.GetViewportScale(UGCSystemLibrary.GetLocalPlayerController()) local WidgetSize = VectorHelper.MulNumber2D(VPSize, 1 / VPScale) -- 获取插槽尺寸信息 local CompSize = CanvasSlot:GetSize() local MidCompSize = VectorHelper.MulNumber2D(CompSize, 0.5) -- 获取移动位置范围 local TargetPosMin = MidCompSize local TargetPosMax = VectorHelper.Sub2D(WidgetSize, MidCompSize) local TargetDir = nil -- Actor判断是否在视锥范围内 if not (IsOnScreen and VectorHelper.Vector2DInRange(WidgetPosition, TargetPosMin, TargetPosMax)) then -- 获取目标位置到相机的向量映射到相机平面的向量 local LocalCamera = UGCSystemLibrary.GetLocalPlayerController().PlayerCameraManager local CameraPos = LocalCamera:K2_GetActorLocation() local CameraForward = LocalCamera:GetActorForwardVector() local ActorToCameraVector = VectorHelper.Sub(ActorPos, CameraPos) local PlaneVector = KismetMathLibrary.ProjectVectorOnToPlane(ActorToCameraVector, CameraForward) -- 将平面向量旋转至原点 local RotatorPlaneVector = KismetMathLibrary.NegateRotator(KismetMathLibrary.Conv_VectorToRotator(CameraForward)) local NormalPlaneVector = KismetMathLibrary.GreaterGreater_VectorRotator(PlaneVector, RotatorPlaneVector) -- 获取屏幕的方向向量 TargetDir = {X = NormalPlaneVector.Y, Y = -NormalPlaneVector.Z} TargetDir = VectorHelper.MulNumber2D(TargetDir, 1 / VectorHelper.Length2D(TargetDir)) -- 判断屏幕及方向向量的斜率 if math.abs(TargetDir.Y / TargetDir.X) < WidgetSize.Y / WidgetSize.X then WidgetPosition.X = ((TargetDir.X < 0) and TargetPosMin.X or TargetPosMax.X) WidgetPosition.Y = ((WidgetSize.X / 2 - MidCompSize.X) / math.abs(TargetDir.X) * TargetDir.Y + WidgetSize.Y / 2) else WidgetPosition.Y = ((TargetDir.Y < 0) and TargetPosMin.Y or TargetPosMax.Y) WidgetPosition.X = ((WidgetSize.Y - MidCompSize.Y) / 2 / math.abs(TargetDir.Y) * TargetDir.X + WidgetSize.X / 2) end end return WidgetPosition, TargetDir end