#if UNITY_EDITOR using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEngine; namespace DCFApixels.DragonECS.Unity.Editors { internal class ComponentDropDown : MetaObjectsDropDown { public ComponentDropDown() { IEnumerable<(IComponentTemplate, ITypeMeta)> itemMetaPairs = ComponentTemplateTypeCache.Dummies.ToArray().Select(dummy => { ITypeMeta meta; if (dummy is IComponentTemplateWithMetaOverride withMetaOverride) { meta = withMetaOverride; } else { meta = dummy.Type.GetMeta(); } return (dummy, meta); }); Setup(itemMetaPairs); } } internal class RuntimeComponentDropDown : MetaObjectsDropDown { public RuntimeComponentDropDown(IEnumerable pools) { IEnumerable<(IEcsPool, ITypeMeta)> itemMetaPairs = pools.Select(pool => { return (pool, (ITypeMeta)pool.ComponentType.GetMeta()); }); Setup(itemMetaPairs); } } internal class MetaObjectsDropDown : AdvancedDropdown { private string _name; private bool _isContainsNull; private IEnumerable<(T, ITypeMeta)> _itemMetaPairs; public MetaObjectsDropDown() : base(new AdvancedDropdownState()) { minimumSize = new Vector2(minimumSize.x, EditorGUIUtility.singleLineHeight * 30); } protected void Setup(IEnumerable<(T, ITypeMeta)> itemMetaPairs, string name = "Select Type", bool isContainsNull = true) { _name = name; _isContainsNull = isContainsNull; _itemMetaPairs = itemMetaPairs; } protected override AdvancedDropdownItem BuildRoot() { int increment = 0; var root = new Item(default, _name, increment++); if (_isContainsNull) { root.AddChild(new Item(default, "", increment++)); } Dictionary dict = new Dictionary(); foreach (var pair in _itemMetaPairs) { ITypeMeta meta = pair.Item2; string description = meta.Description.Text; MetaGroup group = meta.Group; var splitedGroup = group.Splited; Item parent = root; if (splitedGroup.Count > 0) { int i = 1; foreach (var subgroup in splitedGroup) { Key key = new Key(group, i); if (dict.TryGetValue(key, out Item item) == false) { item = new Item(default, subgroup, increment++); parent.AddChild(item); dict.Add(key, item); } parent = item; i++; } } var leafItem = new Item(pair.Item1, meta.Name, increment++); parent.AddChild(leafItem); } return root; } protected override void ItemSelected(AdvancedDropdownItem item) { base.ItemSelected(item); OnSelected((Item)item); } public event Action OnSelected = delegate { }; public class Item : AdvancedDropdownItem { public readonly T Obj; public Item(T obj, string name, int id) : base(name) { Obj = obj; this.id = id; } } #region Key private readonly struct Key : IEquatable { public readonly MetaGroup Group; public readonly int Length; public Key(MetaGroup group, int length) { Group = group; Length = length; } public bool Equals(Key other) { if (Length != other.Length) { return false; } IEnumerator splitedEnum = Group.Splited.GetEnumerator(); IEnumerator splitedEnumOther = other.Group.Splited.GetEnumerator(); for (int i = 0; i < Length; i++) { splitedEnum.MoveNext(); splitedEnumOther.MoveNext(); if (splitedEnum.Current != splitedEnumOther.Current) { return false; } } return true; } public override bool Equals(object obj) { return obj is Key key && Equals(key); } public override int GetHashCode() { unchecked { int state = Length; state ^= state << 13; state ^= state >> 17; state ^= state << 5; var x = Group.Splited.GetEnumerator(); x.MoveNext(); return x.Current.GetHashCode() ^ state; }; } } #endregion } } #endif