273 lines
9.3 KiB
C#
273 lines
9.3 KiB
C#
using System.Collections.Generic;
|
||
using Logic.Skill;
|
||
using RuntimeData;
|
||
using TH1_Logic.Core;
|
||
using UnityEngine;
|
||
|
||
namespace TH1_Renderer
|
||
{
|
||
internal class UnitStatusIcon
|
||
{
|
||
public int Level;
|
||
public StatusIconMono IconMono;
|
||
public GameObject IconObject;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 单位状态管理器 - 管理单位的所有重要负面状态显示
|
||
/// </summary>
|
||
public class UnitStatusArea
|
||
{
|
||
private readonly Dictionary<SkillType, UnitStatusIcon> _statusIcons = new();
|
||
private readonly Dictionary<SkillType, int> _statusLevels = new();
|
||
private readonly Transform _statusContainer;
|
||
private readonly GameObject _statusIconPrefab;
|
||
private readonly UnityEngine.RectTransform _infoGroup;
|
||
|
||
// private const string KOMEIJI_FEAR_PATH = "TH1UI/Icon/SkillIcon/Komeiji/Skill_KomeijiFear";
|
||
// private const string KOMEIJI_FEAR2_PATH = "TH1UI/Icon/SkillIcon/Komeiji/Skill_KomeijiFear2";
|
||
|
||
/// <summary>
|
||
/// 当前显示的状态数量
|
||
/// </summary>
|
||
public int Count => _statusIcons.Count;
|
||
|
||
/// <summary>
|
||
/// 获取所有当前显示的状态
|
||
/// </summary>
|
||
internal IEnumerable<UnitStatusIcon> AllIcons => _statusIcons.Values;
|
||
|
||
public UnitStatusArea(Transform statusContainer, GameObject statusIconPrefab, UnityEngine.RectTransform infoGroup = null)
|
||
{
|
||
_statusContainer = statusContainer;
|
||
_statusIconPrefab = statusIconPrefab;
|
||
_infoGroup = infoGroup;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加或更新状态显示
|
||
/// </summary>
|
||
/// <param name="skillType">技能类型</param>
|
||
/// <param name="unitFullType">单位完整类型</param>
|
||
/// <param name="hasLevel">是否有层数机制</param>
|
||
/// <param name="level">技能等级/层数</param>
|
||
/// <returns>是否成功添加或更新</returns>
|
||
public bool AddOrUpdateStatus(SkillType skillType, UnitFullType unitFullType, bool hasLevel, int level)
|
||
{
|
||
if (_statusIconPrefab == null || _statusContainer == null)
|
||
return false;
|
||
|
||
if (!_statusIcons.TryGetValue(skillType, out var existingIcon))
|
||
{
|
||
var newIconObj = GameObject.Instantiate(_statusIconPrefab, _statusContainer);
|
||
var iconMono = newIconObj.GetComponent<StatusIconMono>();
|
||
if (iconMono == null)
|
||
{
|
||
iconMono = newIconObj.AddComponent<StatusIconMono>();
|
||
}
|
||
|
||
existingIcon = new UnitStatusIcon
|
||
{
|
||
IconObject = newIconObj,
|
||
IconMono = iconMono,
|
||
Level = 0
|
||
};
|
||
_statusIcons.Add(skillType, existingIcon);
|
||
}
|
||
|
||
existingIcon.Level = level;
|
||
existingIcon.IconMono.SetContent(skillType, unitFullType, hasLevel, level);
|
||
|
||
// if (skillType == SkillType.KomeijiFear)
|
||
// {
|
||
// string targetPath = level >= 2 ? KOMEIJI_FEAR2_PATH : KOMEIJI_FEAR_PATH;
|
||
// var specialSprite = TH1Resource.ResourceLoader.Load<Sprite>(targetPath);
|
||
// if (specialSprite != null)
|
||
// {
|
||
// existingIcon.IconMono.SetIcon(specialSprite);
|
||
// }
|
||
// existingIcon.IconMono.SetColor(Color.green);
|
||
// }
|
||
// else
|
||
// {
|
||
// existingIcon.IconMono.SetColor(Color.white);
|
||
// }
|
||
existingIcon.IconMono.SetColor(Color.white);
|
||
|
||
_statusLevels[skillType] = level;
|
||
RefreshLayout();
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除指定状态
|
||
/// </summary>
|
||
/// <param name="skillType">技能类型</param>
|
||
/// <returns>是否成功移除</returns>
|
||
public bool RemoveStatus(SkillType skillType)
|
||
{
|
||
if (!_statusIcons.TryGetValue(skillType, out var icon))
|
||
return false;
|
||
|
||
if (icon.IconObject != null)
|
||
{
|
||
// GameObject.Destroy 是延迟销毁;先 SetActive(false) 让 LayoutGroup 在本帧
|
||
// 重建时立即忽略此节点,否则 StatusAreaContainer 的尺寸测量仍会包含它,
|
||
// 导致父节点(InfoGroup/背景板)的尺寸无法收缩。
|
||
icon.IconObject.SetActive(false);
|
||
GameObject.Destroy(icon.IconObject);
|
||
}
|
||
_statusIcons.Remove(skillType);
|
||
_statusLevels.Remove(skillType);
|
||
|
||
// 移除后强制刷新布局
|
||
RefreshLayout();
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否包含指定状态
|
||
/// </summary>
|
||
public bool HasStatus(SkillType skillType)
|
||
{
|
||
return _statusIcons.ContainsKey(skillType);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取指定状态的层数
|
||
/// </summary>
|
||
public int GetStatusLevel(SkillType skillType)
|
||
{
|
||
return _statusLevels.TryGetValue(skillType, out var level) ? level : 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除所有状态
|
||
/// </summary>
|
||
public void ClearAllStatus()
|
||
{
|
||
foreach (var icon in _statusIcons.Values)
|
||
{
|
||
if (icon.IconObject != null)
|
||
{
|
||
// 先 SetActive(false) 让 LayoutGroup 立即忽略,再 Destroy(延迟销毁)。
|
||
icon.IconObject.SetActive(false);
|
||
GameObject.Destroy(icon.IconObject);
|
||
}
|
||
}
|
||
_statusIcons.Clear();
|
||
_statusLevels.Clear();
|
||
|
||
// 清除后强制刷新布局
|
||
RefreshLayout();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 同步单位技能数据到状态显示区域
|
||
/// 仅显示 SkillInfo.ShowOnUnitMono = true 且当前单位拥有的技能
|
||
/// </summary>
|
||
public void SyncWithUnitSkills(UnitData unitData)
|
||
{
|
||
if (unitData == null || unitData.Skills == null) return;
|
||
|
||
var showSkills = new HashSet<SkillType>();
|
||
foreach (var skill in unitData.Skills)
|
||
{
|
||
if (skill == null) continue;
|
||
var skillType = skill.GetSkillType();
|
||
if (!Table.Instance.SkillDataAssets.GetSkillInfo(skillType, out var skillInfo)) continue;
|
||
if (skillInfo.ShowOnUnitMono)
|
||
{
|
||
showSkills.Add(skillType);
|
||
}
|
||
}
|
||
|
||
var toRemove = new List<SkillType>();
|
||
foreach (var skillType in _statusIcons.Keys)
|
||
{
|
||
if (!showSkills.Contains(skillType))
|
||
toRemove.Add(skillType);
|
||
}
|
||
|
||
bool hasChanged = false;
|
||
|
||
foreach (var skillType in toRemove)
|
||
{
|
||
RemoveStatus(skillType);
|
||
hasChanged = true;
|
||
}
|
||
|
||
foreach (var skillType in showSkills)
|
||
{
|
||
if (!unitData.GetSkill(skillType, out var skill))
|
||
{
|
||
if (HasStatus(skillType))
|
||
{
|
||
RemoveStatus(skillType);
|
||
hasChanged = true;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if (skill.HasLevel && skill.NoShow)
|
||
{
|
||
if (HasStatus(skillType))
|
||
{
|
||
RemoveStatus(skillType);
|
||
hasChanged = true;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
bool hasLevel = skill.HasLevel;
|
||
int level = hasLevel ? skill.Level : 1;
|
||
|
||
if (!HasStatus(skillType) || GetStatusLevel(skillType) != level)
|
||
{
|
||
AddOrUpdateStatus(skillType, unitData.UnitFullType, hasLevel, level);
|
||
hasChanged = true;
|
||
}
|
||
else if (_statusIcons.TryGetValue(skillType, out var existingIcon))
|
||
{
|
||
existingIcon.IconMono.SetContent(skillType, unitData.UnitFullType, hasLevel, level);
|
||
}
|
||
}
|
||
|
||
if (hasChanged)
|
||
{
|
||
RefreshLayout();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新所有状态的显示位置(用于自动布局更新)
|
||
/// </summary>
|
||
public void RefreshLayout()
|
||
{
|
||
if (_statusContainer == null) return;
|
||
|
||
// 强制刷新布局
|
||
if (_statusContainer is UnityEngine.RectTransform rectTransform)
|
||
{
|
||
UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
|
||
}
|
||
|
||
// 图标增减后同时重排 InfoGroup,让背景板等父级 LayoutGroup 感知尺寸变化
|
||
if (_infoGroup != null)
|
||
{
|
||
UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(_infoGroup);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置整个状态区域是否可见
|
||
/// </summary>
|
||
public void SetAreaVisible(bool visible)
|
||
{
|
||
if (_statusContainer != null)
|
||
_statusContainer.gameObject.SetActive(visible);
|
||
}
|
||
}
|
||
}
|