192 lines
7.1 KiB
C#
192 lines
7.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using AYellowpaper.SerializedCollections;
|
|
using BITKit;
|
|
using UnityEngine;
|
|
using UnityEngine.Pool;
|
|
using UnityEngine.UIElements;
|
|
using YamlDotNet.Serialization;
|
|
using YamlDotNet.Serialization.NamingConventions;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
namespace Net.BITKit.BitMask
|
|
{
|
|
|
|
public class ScriptableBitMask : ScriptableObject,ISerializationCallbackReceiver
|
|
{
|
|
[SerializeField] public ScriptableImplements implements;
|
|
|
|
internal readonly Dictionary<string, List<string>> Dictionary=new();
|
|
[SerializeField] public string yaml;
|
|
|
|
public Type Type => implements.Type;
|
|
|
|
public Type[] Types => implements ? implements.Types : Array.Empty<Type>();
|
|
|
|
private void OnEnable()
|
|
{
|
|
OnBeforeSerialize();
|
|
}
|
|
|
|
public void OnBeforeSerialize()
|
|
{
|
|
if(string.IsNullOrEmpty(yaml))return;
|
|
var deserializer = new DeserializerBuilder()
|
|
.WithNamingConvention(CamelCaseNamingConvention.Instance) // 驼峰命名
|
|
.Build();
|
|
Dictionary.Clear();
|
|
var newDictionary = deserializer.Deserialize<Dictionary<string, List<string>>>(yaml);
|
|
foreach (var pair in newDictionary)
|
|
{
|
|
Dictionary[pair.Key] = pair.Value;
|
|
}
|
|
}
|
|
|
|
public void OnAfterDeserialize()
|
|
{
|
|
if(Dictionary.Count is 0)return;
|
|
var serializer = new SerializerBuilder()
|
|
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
|
.Build();
|
|
yaml = serializer.Serialize(Dictionary);
|
|
}
|
|
public IDictionary<Type,HashSet<Type>> FlagMask
|
|
{
|
|
get
|
|
{
|
|
var typeDictionary = implements.Types.ToDictionary(x => x.Name, x => x);
|
|
|
|
var nextDictionary = new Dictionary<Type, HashSet<Type>>();
|
|
|
|
foreach (var (key, d) in Dictionary)
|
|
{
|
|
if (typeDictionary.TryGetValue(key, out var type) is false) continue;
|
|
var hashSet = new HashSet<Type>();
|
|
foreach (var x in d)
|
|
{
|
|
if(typeDictionary.TryGetValue(x,out var t1) is false)continue;
|
|
hashSet.Add(t1);
|
|
}
|
|
nextDictionary[type]=hashSet;
|
|
}
|
|
|
|
foreach (var type in Types)
|
|
{
|
|
if (nextDictionary.TryAdd(type, new HashSet<Type>())) ;
|
|
}
|
|
|
|
return nextDictionary;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
#if UNITY_EDITOR
|
|
[CustomEditor(typeof(ScriptableBitMask),true)]
|
|
public sealed class ScriptableBitMaskEditor:Editor
|
|
{
|
|
private const int CellSize = 24;
|
|
public override VisualElement CreateInspectorGUI()
|
|
{
|
|
if (serializedObject.targetObject is not ScriptableBitMask scriptableBitMask)
|
|
return base.CreateInspectorGUI();
|
|
|
|
var inspector = new VisualElement
|
|
{
|
|
style =
|
|
{
|
|
flexDirection = FlexDirection.Column
|
|
}
|
|
};
|
|
|
|
var defaultPropertyFields = inspector.Create<VisualElement>();
|
|
|
|
BITInspectorExtensions.FillDefaultInspector(defaultPropertyFields.Create<VisualElement>(),serializedObject,false);
|
|
|
|
var root = inspector.Create<VisualElement>();
|
|
|
|
root.style.flexDirection = new StyleEnum<FlexDirection>(FlexDirection.Row);
|
|
|
|
|
|
var allFlags = scriptableBitMask.Types;
|
|
|
|
var labelRow = root.Create<VisualElement>();
|
|
var toggleRot = root.Create<VisualElement>();
|
|
|
|
labelRow.style.alignSelf = new StyleEnum<Align>(Align.FlexEnd);
|
|
|
|
for (var x = -1; x < allFlags.Length; x++)
|
|
{
|
|
if (x is -1)
|
|
{
|
|
var container = toggleRot.Create<VisualElement>();
|
|
container.style.flexDirection = FlexDirection.Row;
|
|
foreach (var type in scriptableBitMask.Types.Reverse())
|
|
{
|
|
var text = container.Create<Label>();
|
|
text.style.width = CellSize;
|
|
text.text = string.Join("\n", type.Name.ToArray());
|
|
}
|
|
|
|
continue;
|
|
}
|
|
{
|
|
var xEnum = allFlags[x];
|
|
|
|
var label = labelRow.Create<Label>();
|
|
|
|
label.text = xEnum.Name;
|
|
|
|
label.style.height = CellSize;
|
|
|
|
label.style.unityTextAlign = TextAnchor.MiddleRight;
|
|
|
|
var toggles = toggleRot.Create<VisualElement>();
|
|
toggles.style.flexDirection = new StyleEnum<FlexDirection>(FlexDirection.Row);
|
|
|
|
for (var y = allFlags.Length-1; y >= 0+x; y--)
|
|
{
|
|
var yEnum = allFlags[y];
|
|
var toggle = toggles.Create<Toggle>();
|
|
|
|
toggle.tooltip = $"{xEnum.Name}/{yEnum.Name}";
|
|
|
|
toggle.style.width = toggle.style.height = CellSize;
|
|
toggle.style.marginBottom
|
|
= toggleRot.style.marginLeft
|
|
= toggleRot.style.marginRight
|
|
= toggleRot.style.marginTop
|
|
= toggleRot.style.paddingBottom
|
|
=toggleRot.style.paddingLeft
|
|
=toggleRot.style.paddingRight
|
|
=toggleRot.style.paddingTop
|
|
=-1;
|
|
|
|
toggle.SetValueWithoutNotify(scriptableBitMask.Dictionary.GetOrCreate(xEnum.Name).Contains(yEnum.Name));
|
|
toggle.RegisterValueChangedCallback(changeEvent =>
|
|
{
|
|
if (changeEvent.newValue)
|
|
{
|
|
scriptableBitMask.Dictionary.GetOrCreate(xEnum.Name).TryAdd(yEnum.Name);
|
|
scriptableBitMask.Dictionary.GetOrCreate(yEnum.Name).TryAdd(xEnum.Name);
|
|
}
|
|
else
|
|
{
|
|
scriptableBitMask.Dictionary.GetOrCreate(xEnum.Name).TryRemove(yEnum.Name);
|
|
scriptableBitMask.Dictionary.GetOrCreate(yEnum.Name).TryRemove(xEnum.Name);
|
|
}
|
|
scriptableBitMask.OnAfterDeserialize();
|
|
EditorUtility.SetDirty(serializedObject.targetObject);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
return root;
|
|
}
|
|
}
|
|
#endif
|
|
}
|