Sprite群组编辑器
This commit is contained in:
@@ -1,40 +1,236 @@
|
||||
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 Sprite索引
|
||||
#region 索引
|
||||
|
||||
private Dictionary<string, SpriteRenderer> _rendererDict;
|
||||
[HideInInspector] public SpriteGroupConfig config;
|
||||
[HideInInspector] public GameObject spriteGroup;
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly Dictionary<string, SpriteRenderer> _spriteDict = new();
|
||||
private Dictionary<string, List<string>> _stateDict;
|
||||
/// <summary>
|
||||
/// 根据PS文件加载
|
||||
/// </summary>
|
||||
public void InstantiateByPsd()
|
||||
{
|
||||
if (spriteGroup)
|
||||
{
|
||||
// 先销毁
|
||||
DestroyAllChildren();
|
||||
// 再新建
|
||||
InstantiateGroup();
|
||||
// 把PSD名字填进去
|
||||
config.key = spriteGroup.name;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("请先设置要加载的图集");
|
||||
}
|
||||
}
|
||||
|
||||
public void InstantiateByConfig()
|
||||
{
|
||||
// 校验Key是否存在
|
||||
if (!config.Validate()) return;
|
||||
// 查查有没有Prefab
|
||||
Debug.Log(config.PrefabResourcePath);
|
||||
var prefab = Resources.Load<GameObject>(config.PrefabResourcePath);
|
||||
if (!prefab)
|
||||
{
|
||||
Debug.Log("对应Prefab不存在");
|
||||
return;
|
||||
}
|
||||
// 实例化Prefab
|
||||
spriteGroup = prefab;
|
||||
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>();
|
||||
_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) != null)
|
||||
{
|
||||
// 如果存在,替换 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
|
||||
|
||||
[SerializeField] private string state;
|
||||
#region 切换State
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
}
|
||||
|
||||
public void SaveAsState()
|
||||
{
|
||||
var spriteRenderers = GetComponentsInChildren<SpriteRenderer>();
|
||||
|
||||
var activeList = (from render in spriteRenderers
|
||||
where render.gameObject.activeSelf
|
||||
select render.gameObject.name).ToList();
|
||||
|
||||
_stateDict[state] = activeList;
|
||||
}
|
||||
|
||||
public void LoadState()
|
||||
/// <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 struct 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;
|
||||
private Dictionary<string, string[]> _stateDict;
|
||||
|
||||
public Dictionary<string, string[]> StateDict
|
||||
{
|
||||
get { return _stateDict ??= new Dictionary<string, string[]>(); }
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user