TH1/Unity/Assets/Scripts/TH1_UI/HintUI/HintWindowController.cs
2025-08-18 23:16:13 +08:00

84 lines
2.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEngine.UI;
using TMPro;
[RequireComponent(typeof(RectTransform))]
public class HintWindowController : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI _text;
[SerializeField] private Vector2 _padding = new Vector2(16, 10);
[SerializeField] private Vector2 _anchorOffset = new Vector2(16, 16);
private RectTransform _selfRt;
private Canvas _rootCanvas;
private Camera _uiCamera;
private void Awake()
{
_selfRt = (RectTransform)transform;
_rootCanvas = GetComponentInParent<Canvas>();
_uiCamera = _rootCanvas.worldCamera;
// 兜底找 Text
if (_text == null)
_text = GetComponentInChildren<TextMeshProUGUI>(true);
if (_text == null)
Debug.LogError("[HintWindowController] 找不到 TextMeshProUGUI", this);
}
public void Present(Vector2 mouseScreenPos)
{
if (_text == null) return;
RefreshSize();
ClampToScreen(mouseScreenPos);
}
public void RefreshSize()
{
_text.ForceMeshUpdate(false, false);
LayoutRebuilder.ForceRebuildLayoutImmediate(_text.rectTransform);
float w = _text.preferredWidth + _padding.x * 2f;
float h = _text.preferredHeight + _padding.y * 2f;
_selfRt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, w);
_selfRt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, h);
Canvas.ForceUpdateCanvases();
}
private void ClampToScreen(Vector2 mouseScreenPos)
{
Rect screenRect = _rootCanvas.pixelRect;
// 计算窗口左上角假想屏幕坐标
Vector2 topLeft = mouseScreenPos + _anchorOffset;
float windowW = _selfRt.rect.width;
float windowH = _selfRt.rect.height;
// 四边
float left = topLeft.x;
float right = left + windowW;
float top = topLeft.y;
float bottom = top - windowH; // 注意 Canvas 局部坐标 y 向下为正
// 修正到屏幕内
left = Mathf.Clamp(left, screenRect.xMin, screenRect.xMax - windowW);
top = Mathf.Clamp(top, screenRect.yMin + windowH, screenRect.yMax);
// 转回 Canvas 局部坐标
RectTransform canvasRt = _rootCanvas.GetComponent<RectTransform>();
RectTransformUtility.ScreenPointToLocalPointInRectangle(
canvasRt,
new Vector2(left, top),
_uiCamera,
out Vector2 localPos);
_selfRt.localPosition = localPos;
_selfRt.SetAsLastSibling();
}
}