273 lines
8.1 KiB
C#
273 lines
8.1 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名字填进去
|
|
// 加载配置文件,没有就空着
|
|
if (ConfigUtil.Instance.TryGetSpriteConfig(config.key, out var oldConfig))
|
|
{
|
|
config = oldConfig;
|
|
}
|
|
else
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
} |