mirror of
http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite.git
synced 2025-11-20 05:17:13 +08:00
132 lines
5.3 KiB
C#
132 lines
5.3 KiB
C#
|
|
using System.Collections.Generic;
|
|||
|
|
using Data;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using UnityEditor;
|
|||
|
|
using TMPro;
|
|||
|
|
|
|||
|
|
namespace UI
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 技能树节点的用户界面组件。
|
|||
|
|
/// </summary>
|
|||
|
|
public class SkillTreeNodeUI : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 节点的RectTransform组件。
|
|||
|
|
/// </summary>
|
|||
|
|
public RectTransform rectTransform;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 节点的最小高度。
|
|||
|
|
/// </summary>
|
|||
|
|
[SerializeField] private float NODE_MIN_HEIGHT = 39.0122f * 2;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 两条连接线结束点之间的最小垂直间距。
|
|||
|
|
/// </summary>
|
|||
|
|
[SerializeField]private float MIN_VERTICAL_SPACING = 12.9447f;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 技能节点入口线UI组件。
|
|||
|
|
/// </summary>
|
|||
|
|
public SkillNodeEnterLineUI skillNodeEnterLineUI;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 输出线连接点的参考或容器。
|
|||
|
|
/// </summary>
|
|||
|
|
public RectTransform outputHead;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 文本显示组件。
|
|||
|
|
/// </summary>
|
|||
|
|
public TMP_Text text;
|
|||
|
|
|
|||
|
|
public SkillTreeDef skillTreeDef;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 初始化技能树节点UI。
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="linkLinePoints">连接线的点数组。</param>
|
|||
|
|
/// <param name="label">节点显示的文本标签。</param>
|
|||
|
|
public void Init(Vector2[] linkLinePoints, string label)
|
|||
|
|
{
|
|||
|
|
text.text = label;
|
|||
|
|
if (linkLinePoints is { Length: > 0 })
|
|||
|
|
{
|
|||
|
|
var height = skillNodeEnterLineUI.GetRequiredHeight(linkLinePoints.Length);
|
|||
|
|
height = Mathf.Max(height + NODE_MIN_HEIGHT / 2 + 10, NODE_MIN_HEIGHT);
|
|||
|
|
rectTransform.sizeDelta = new Vector2(rectTransform.sizeDelta.x, height);
|
|||
|
|
skillNodeEnterLineUI.Init(linkLinePoints);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 预先计算技能树节点在初始化后所需的最小高度。
|
|||
|
|
/// 此方法可以在调用 Init 之前用于布局计算。
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="linkLineCount">连接线(入口线)的数量。</param>
|
|||
|
|
/// <returns>节点所需的最小高度。</returns>
|
|||
|
|
public float GetRequiredNodeHeight(int linkLineCount)
|
|||
|
|
{
|
|||
|
|
// 如果没有连接线或 skillNodeEnterLineUI 组件为空,则高度为最小高度
|
|||
|
|
if (linkLineCount <= 0 || skillNodeEnterLineUI == null)
|
|||
|
|
{
|
|||
|
|
return NODE_MIN_HEIGHT;
|
|||
|
|
}
|
|||
|
|
// 获取 SkillNodeEnterLineUI 根据连接线数量计算出的所需高度
|
|||
|
|
var calculatedLineHeight = skillNodeEnterLineUI.GetRequiredHeight(linkLineCount);
|
|||
|
|
// 结合最小节点高度和额外的填充,确保节点有足够的空间
|
|||
|
|
// 逻辑与 Init() 方法中的高度计算保持一致
|
|||
|
|
var finalHeight = Mathf.Max(calculatedLineHeight + NODE_MIN_HEIGHT / 2 + 10, NODE_MIN_HEIGHT);
|
|||
|
|
|
|||
|
|
return finalHeight;
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 查询出口位置。
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="totalCount">总数量。</param>
|
|||
|
|
/// <param name="index">位置(从上往下,0-based)。</param>
|
|||
|
|
/// <returns>世界坐标。</returns>
|
|||
|
|
public Vector2 GetOutputPosition(int totalCount, int index)
|
|||
|
|
{
|
|||
|
|
// 输入验证,防止无效的totalCount或index导致错误
|
|||
|
|
if (totalCount <= 0 || index < 0 || index >= totalCount)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"获取输出位置时,总数 ({totalCount}) 或索引 ({index}) 无效。返回outputHead的默认位置。");
|
|||
|
|
// 返回outputHead的中心位置作为备用,或者Vector2.zero取决于具体需求
|
|||
|
|
return outputHead.position;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1. 计算 X 坐标:outputHead 的右边界
|
|||
|
|
var corners = new Vector3[4];
|
|||
|
|
outputHead.GetWorldCorners(corners);
|
|||
|
|
// corners[2] 是右上角的世界坐标点
|
|||
|
|
var worldX = corners[2].x;
|
|||
|
|
|
|||
|
|
// 2. 计算 Y 坐标:以 outputHead 的中心Y坐标为基准进行偏移
|
|||
|
|
var worldY = outputHead.position.y;
|
|||
|
|
|
|||
|
|
if (totalCount == 2)
|
|||
|
|
{
|
|||
|
|
// 特殊情况:当输出点为2个时,点1为(x,y+d),点2为(x,y-d),d为MIN_VERTICAL_SPACING
|
|||
|
|
if (index == 0) // 第一个点 (最上面的点)
|
|||
|
|
{
|
|||
|
|
worldY += MIN_VERTICAL_SPACING;
|
|||
|
|
}
|
|||
|
|
else // 第二个点 (最下面的点)
|
|||
|
|
{
|
|||
|
|
worldY -= MIN_VERTICAL_SPACING;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// 一般情况:多个点均匀纵向排列,以outputHead的Y为中心
|
|||
|
|
// 计算最顶部的点 (index=0) 相对于中心点Y的偏移量
|
|||
|
|
// 总共有 (totalCount - 1) 个 MIN_VERTICAL_SPACING 的间距
|
|||
|
|
// 索引为 index 的点的偏移量为:
|
|||
|
|
// ( (totalCount - 1) / 2.0f - index ) * MIN_VERTICAL_SPACING
|
|||
|
|
var halfTotalSpacing = (totalCount - 1) / 2.0f;
|
|||
|
|
var yOffset = (halfTotalSpacing - index) * MIN_VERTICAL_SPACING;
|
|||
|
|
worldY += yOffset;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return new Vector2(worldX, worldY);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|