Files
aibis-dream/Assets/Scripts/Framework/OtherKit/SpriteGroupKit.cs
T
2025-03-08 20:54:44 +08:00

265 lines
7.8 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using AibisDream.Kit;
using Newtonsoft.Json;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace AibisDream.Framework
{
public class SpriteGroupKit : MonoBehaviour
{
#region 索引
private Dictionary<string, SpriteRenderer> _rendererDict = new();
[HideInInspector] public SpriteGroupConfig config = new();
[HideInInspector] public GameObject spriteGroup;
#endregion
private Dictionary<string, SpriteRenderer> RendererDict
{
get
{
if (_rendererDict is not { Count: > 0 })
{
if (transform.GetChild(0))
{
var rendererArray = transform.GetChild(0).GetComponentsInChildren<SpriteRenderer>(true);
_rendererDict = new Dictionary<string, SpriteRenderer>();
foreach (var rendererItem in rendererArray)
{
_rendererDict[rendererItem.gameObject.name] = rendererItem;
}
}
else
{
_rendererDict = new Dictionary<string, SpriteRenderer>();
}
}
return _rendererDict;
}
}
/// <summary>
/// 根据PS文件加载
/// </summary>
public void InstantiateByPsd()
{
if (spriteGroup)
{
// 先销毁
DestroyAllChildren();
// 再新建
InstantiateGroup();
// 把PSD名字填进去
config = new SpriteGroupConfig
{
key = spriteGroup.name
};
}
else
{
Debug.Log("请先设置要加载的图集");
}
}
public void InstantiateByConfig()
{
StartCoroutine(InstantiateByConfigAsync());
}
public IEnumerator InstantiateByConfigAsync()
{
// 校验Key是否存在
if (!config.Validate()) yield break;
// 查查有没有Prefab
var request = Resources.LoadAsync<GameObject>(config.PrefabResourcePath);
#if DEBUG
if (request.asset == null)
{
Debug.Log($"prefab没有找到");
yield break;
}
#endif
// 实例化Prefab
spriteGroup = request.asset as GameObject;
DestroyAllChildren();
InstantiateGroup();
// 加载配置文件,没有就空着
if (ConfigUtil.Instance.TryGetSpriteConfig(config.key, out var oldConfig))
{
config = oldConfig;
}
}
private void InstantiateGroup()
{
var root = Instantiate(spriteGroup, transform);
var rendererArray = root.GetComponentsInChildren<SpriteRenderer>(true);
_rendererDict = new Dictionary<string, SpriteRenderer>();
foreach (var rendererItem in rendererArray)
{
_rendererDict[rendererItem.gameObject.name] = rendererItem;
}
}
private void DestroyAllChildren()
{
foreach (Transform child in transform)
{
#if UNITY_EDITOR
if (!EditorApplication.isPlaying)
{
DestroyImmediate(child.gameObject);
continue;
}
#endif
Destroy(child.gameObject);
}
}
#region 保存逻辑
public void SaveState(string curState)
{
var activeArray = RendererDict
.Where(pair => pair.Value.gameObject.activeSelf)
.Select(item => item.Key)
.ToArray();
config.stateDict[curState] = activeArray;
}
public void SaveSpriteGroup()
{
// 先校验参数是不是都是正确的
if (!config.Validate())
{
Debug.Log("配置项存在空字段");
return;
}
// 先保存Prefab
SaveAsPrefab(transform.GetChild(0).gameObject, config.PrefabPath);
// 再保存Config
ConfigUtil.Instance.SaveSpriteGroupConfig(config);
}
private static void SaveAsPrefab(GameObject target, string localPath)
{
#if UNITY_EDITOR
// 先验证Prefab是否存在
if (AssetDatabase.LoadAssetAtPath<GameObject>(localPath))
{
// 如果存在,替换 Prefab
PrefabUtility.SaveAsPrefabAssetAndConnect(target, localPath, InteractionMode.UserAction);
Debug.Log("Prefab replaced at: " + localPath);
}
else
{
// 如果不存在,创建新的 Prefab
PrefabUtility.SaveAsPrefabAsset(target, localPath);
Debug.Log("Prefab created at: " + localPath);
}
#endif
}
#endregion
#region 切换State
/// <summary>
/// 切换状态
/// </summary>
public void SwitchState(string stateName)
{
// 检查是否存在
if (!config.stateDict.TryGetValue(stateName, out var activeArray)) return;
// 按状态激活
foreach (var item in RendererDict.Values)
{
item.gameObject.SetActive(activeArray.Contains(item.gameObject.name));
}
}
#endregion
#region 排序逻辑
public void Reorder()
{
if (!config.ValidateLayer())
{
Debug.LogWarning("排序参数错误");
return;
}
if (RendererDict is not { Count: > 0 })
{
Debug.LogWarning("还没有加载图集");
return;
}
// 排序
var renderers = RendererDict.Values;
var sortedRenderers = renderers.OrderBy(item => item, new LayerComparer()).ToArray();
for (var i = 0; i < sortedRenderers.Length; i++)
{
sortedRenderers[i].sortingLayerID = config.layerId;
sortedRenderers[i].sortingOrder = config.minLayer + i;
}
}
#endregion
}
[Serializable]
public class SpriteGroupConfig
{
[JsonIgnore]
public string PrefabPath => $"Assets/Resources/SpriteGroup/{key}.prefab";
[JsonIgnore]
public string PrefabResourcePath => $"SpriteGroup/{key}";
public string key;
public int layerId;
public int maxLayer;
public int minLayer;
public Dictionary<string, string[]> stateDict = new();
public bool Validate()
{
return !string.IsNullOrEmpty(key);
}
public bool ValidateLayer()
{
if (!SortingLayer.IsValid(layerId)) return false;
if (maxLayer <= minLayer) return false;
return true;
}
}
public class LayerComparer : IComparer<SpriteRenderer>
{
public int Compare(SpriteRenderer x, SpriteRenderer y)
{
if (ReferenceEquals(x, y)) return 0;
if (ReferenceEquals(null, y)) return 1;
if (ReferenceEquals(null, x)) return -1;
var sortingLayerIDComparison = x.sortingLayerID.CompareTo(y.sortingLayerID);
if (sortingLayerIDComparison != 0) return sortingLayerIDComparison;
return x.sortingOrder.CompareTo(y.sortingOrder);
}
}
}