331 lines
10 KiB
C#
331 lines
10 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using Logic.Skill;
|
||
using RuntimeData;
|
||
using TH1Resource;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
namespace TH1_Renderer
|
||
{
|
||
/// <summary>
|
||
/// 单位负面状态图标数据类 - 存储单个状态的显示信息和对应的GameObject
|
||
/// </summary>
|
||
[Serializable]
|
||
public class UnitStatusIcon
|
||
{
|
||
/// <summary>对应的技能类型</summary>
|
||
public SkillType SkillType { get; private set; }
|
||
|
||
/// <summary>技能等级/层数</summary>
|
||
public int Level { get; private set; }
|
||
|
||
/// <summary>显示用的GameObject</summary>
|
||
public GameObject IconObject { get; private set; }
|
||
|
||
/// <summary>图标Image组件</summary>
|
||
public Image IconImage { get; private set; }
|
||
|
||
/// <summary>层数文本组件(可选)</summary>
|
||
public TMPro.TextMeshProUGUI LevelText { get; private set; }
|
||
|
||
/// <summary>是否需要显示层数</summary>
|
||
public bool HasLevelDisplay => LevelText != null;
|
||
|
||
public UnitStatusIcon(SkillType skillType, int level, GameObject iconObject)
|
||
{
|
||
SkillType = skillType;
|
||
Level = level;
|
||
IconObject = iconObject;
|
||
|
||
// 获取组件引用
|
||
IconImage = iconObject.GetComponent<Image>();
|
||
LevelText = iconObject.GetComponentInChildren<TMPro.TextMeshProUGUI>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新层数显示
|
||
/// </summary>
|
||
public void UpdateLevel(int newLevel)
|
||
{
|
||
Level = newLevel;
|
||
if (HasLevelDisplay && Level > 1)
|
||
{
|
||
LevelText.text = Level.ToString();
|
||
LevelText.gameObject.SetActive(true);
|
||
}
|
||
else if (HasLevelDisplay)
|
||
{
|
||
LevelText.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置图标Sprite
|
||
/// </summary>
|
||
public void SetIcon(Sprite sprite)
|
||
{
|
||
if (IconImage != null)
|
||
IconImage.sprite = sprite;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置图标颜色
|
||
/// </summary>
|
||
public void SetColor(Color color)
|
||
{
|
||
if (IconImage != null)
|
||
IconImage.color = color;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 销毁图标GameObject
|
||
/// </summary>
|
||
public void Destroy()
|
||
{
|
||
if (IconObject != null)
|
||
GameObject.Destroy(IconObject);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置显示状态
|
||
/// </summary>
|
||
public void SetVisible(bool visible)
|
||
{
|
||
if (IconObject != null)
|
||
IconObject.SetActive(visible);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 单位状态管理器 - 管理单位的所有重要负面状态显示
|
||
/// </summary>
|
||
public class UnitStatusArea
|
||
{
|
||
private readonly Dictionary<SkillType, UnitStatusIcon> _statusIcons = new();
|
||
private readonly Transform _statusContainer;
|
||
private readonly GameObject _statusIconPrefab;
|
||
private readonly uint _unitId;
|
||
|
||
// KomeijiFear 图片路径(RuntimeResources 下相对路径)
|
||
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>
|
||
public IEnumerable<UnitStatusIcon> AllIcons => _statusIcons.Values;
|
||
|
||
public UnitStatusArea(uint unitId, Transform statusContainer, GameObject statusIconPrefab)
|
||
{
|
||
_unitId = unitId;
|
||
_statusContainer = statusContainer;
|
||
_statusIconPrefab = statusIconPrefab;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加或更新状态显示
|
||
/// </summary>
|
||
/// <param name="skillType">技能类型</param>
|
||
/// <param name="level">技能等级/层数</param>
|
||
/// <param name="icon">图标Sprite</param>
|
||
/// <returns>是否成功添加或更新</returns>
|
||
public bool AddOrUpdateStatus(SkillType skillType, int level, Sprite icon)
|
||
{
|
||
bool isUpdate = false;
|
||
Sprite finalIcon = icon;
|
||
|
||
// KomeijiFear 特殊处理:根据等级切换图片
|
||
if (skillType == SkillType.KomeijiFear)
|
||
{
|
||
string targetPath = level >= 2 ? KOMEIJI_FEAR2_PATH : KOMEIJI_FEAR_PATH;
|
||
var specialSprite = Resources.Load<Sprite>(targetPath);
|
||
if (specialSprite != null)
|
||
finalIcon = specialSprite;
|
||
}
|
||
|
||
if (_statusIcons.TryGetValue(skillType, out var existingIcon))
|
||
{
|
||
// 已存在则更新层数和图标
|
||
existingIcon.UpdateLevel(level);
|
||
|
||
// KomeijiFear 等级变化可能导致图片变化
|
||
if (skillType == SkillType.KomeijiFear && finalIcon != existingIcon.IconImage?.sprite)
|
||
{
|
||
existingIcon.SetIcon(finalIcon);
|
||
}
|
||
|
||
isUpdate = true;
|
||
}
|
||
else
|
||
{
|
||
// 不存在则创建新的
|
||
if (_statusIconPrefab == null || _statusContainer == null)
|
||
return false;
|
||
|
||
var newIconObj = GameObject.Instantiate(_statusIconPrefab, _statusContainer);
|
||
var statusIcon = new UnitStatusIcon(skillType, level, newIconObj);
|
||
statusIcon.SetIcon(finalIcon);
|
||
statusIcon.UpdateLevel(level);
|
||
|
||
// KomeijiFear 特殊处理:显示为绿色
|
||
if (skillType == SkillType.KomeijiFear)
|
||
{
|
||
statusIcon.SetColor(Color.green);
|
||
}
|
||
else
|
||
{
|
||
statusIcon.SetColor(Color.white);
|
||
}
|
||
|
||
_statusIcons.Add(skillType, statusIcon);
|
||
isUpdate = true;
|
||
}
|
||
|
||
// 每次更新后强制刷新布局
|
||
RefreshLayout();
|
||
|
||
return isUpdate;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除指定状态
|
||
/// </summary>
|
||
/// <param name="skillType">技能类型</param>
|
||
/// <returns>是否成功移除</returns>
|
||
public bool RemoveStatus(SkillType skillType)
|
||
{
|
||
if (!_statusIcons.TryGetValue(skillType, out var icon))
|
||
return false;
|
||
|
||
icon.Destroy();
|
||
_statusIcons.Remove(skillType);
|
||
|
||
// 移除后强制刷新布局
|
||
RefreshLayout();
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否包含指定状态
|
||
/// </summary>
|
||
public bool HasStatus(SkillType skillType)
|
||
{
|
||
return _statusIcons.ContainsKey(skillType);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取指定状态的层数
|
||
/// </summary>
|
||
public int GetStatusLevel(SkillType skillType)
|
||
{
|
||
return _statusIcons.TryGetValue(skillType, out var icon) ? icon.Level : 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除所有状态
|
||
/// </summary>
|
||
public void ClearAllStatus()
|
||
{
|
||
foreach (var icon in _statusIcons.Values)
|
||
{
|
||
icon.Destroy();
|
||
}
|
||
_statusIcons.Clear();
|
||
|
||
// 清除后强制刷新布局
|
||
RefreshLayout();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 同步单位的技能数据 - 只显示指定的负面技能
|
||
/// </summary>
|
||
/// <param name="unitData">单位数据</param>
|
||
/// <param name="negativeSkillTypes">需要显示的负面技能类型列表</param>
|
||
public void SyncWithUnitSkills(UnitData unitData, List<SkillType> negativeSkillTypes)
|
||
{
|
||
if (unitData == null || unitData.Skills == null) return;
|
||
|
||
// 找出需要移除的状态(已不在要显示的列表中)
|
||
var toRemove = new List<SkillType>();
|
||
foreach (var skillType in _statusIcons.Keys)
|
||
{
|
||
if (!negativeSkillTypes.Contains(skillType))
|
||
toRemove.Add(skillType);
|
||
}
|
||
|
||
bool hasChanged = false;
|
||
|
||
// 移除过期状态
|
||
foreach (var skillType in toRemove)
|
||
{
|
||
RemoveStatus(skillType);
|
||
hasChanged = true;
|
||
}
|
||
|
||
// 更新或添加状态
|
||
foreach (var skillType in negativeSkillTypes)
|
||
{
|
||
if (!unitData.GetSkill(skillType, out var skill))
|
||
{
|
||
// 如果单位没有此技能但正在显示,则移除
|
||
if (HasStatus(skillType))
|
||
{
|
||
RemoveStatus(skillType);
|
||
hasChanged = true;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
// 获取技能图标
|
||
if (!Table.Instance.SkillDataAssets.GetSkillInfo(skillType, out var skillInfo))
|
||
continue;
|
||
|
||
int level = skill.HasLevel ? skill.Level : 1;
|
||
|
||
// 检查是否需要更新(新增或层数变化)
|
||
if (!HasStatus(skillType) || GetStatusLevel(skillType) != level)
|
||
{
|
||
AddOrUpdateStatus(skillType, level, skillInfo.SkillIcon);
|
||
hasChanged = true;
|
||
}
|
||
}
|
||
|
||
// 如果有变化,强制刷新布局(AddOrUpdateStatus 和 RemoveStatus 内部也会调用,这里作为保险)
|
||
if (hasChanged)
|
||
{
|
||
RefreshLayout();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新所有状态的显示位置(用于自动布局更新)
|
||
/// </summary>
|
||
public void RefreshLayout()
|
||
{
|
||
if (_statusContainer == null) return;
|
||
|
||
// 强制刷新布局
|
||
if (_statusContainer is UnityEngine.RectTransform rectTransform)
|
||
{
|
||
UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置整个状态区域是否可见
|
||
/// </summary>
|
||
public void SetAreaVisible(bool visible)
|
||
{
|
||
if (_statusContainer != null)
|
||
_statusContainer.gameObject.SetActive(visible);
|
||
}
|
||
}
|
||
}
|