update popup

This commit is contained in:
Mikhail 2024-09-12 01:35:37 +08:00
parent d87331c956
commit 96571bf452
7 changed files with 239 additions and 131 deletions

View File

@ -70,6 +70,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
#endregion
#region ReferenceDropDown
private class ReferenceDropDown : AdvancedDropdown
{
public readonly Type[] PredicateTypes;
@ -100,7 +101,6 @@ namespace DCFApixels.DragonECS.Unity.Editors
if (isAssignable)
{
ITypeMeta meta = type.ToMeta();
string name = meta.Name;
string description = meta.Description.Text;
MetaGroup group = meta.Group;
var splitedGroup = group.Splited;
@ -123,7 +123,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
}
var leafItem = new Item(type, name, increment++);
var leafItem = new Item(type, meta.Name, increment++);
parent.AddChild(leafItem);
}
}
@ -165,7 +165,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
return false;
}
IEnumerator<string> splitedEnum = Group.Splited.GetEnumerator();
IEnumerator<string> splitedEnumOther = Group.Splited.GetEnumerator();
IEnumerator<string> splitedEnumOther = other.Group.Splited.GetEnumerator();
for (int i = 0; i < Length; i++)
{
splitedEnum.MoveNext();
@ -195,50 +195,9 @@ namespace DCFApixels.DragonECS.Unity.Editors
};
}
}
//private readonly struct Key : IEquatable<Key>
//{
// public readonly string FullName;
// public readonly int Length;
// public Key(string fullName, int length)
// {
// FullName = fullName;
// Length = length;
// }
// public bool Equals(Key other)
// {
// if (Length != other.Length)
// {
// return false;
// }
// for (int i = 0; i < Length; i++)
// {
// if (FullName[i] != other.FullName[i])
// {
// 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;
// return FullName.GetHashCode() ^ state;
// };
// }
//}
#endregion
}
#endregion
#region Init
private static void Init()
@ -344,19 +303,19 @@ namespace DCFApixels.DragonECS.Unity.Editors
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.SYSTEMS_GROUP)]
[System.Serializable] public class TestSystem0 : IEcsProcess { }
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.SYSTEMS_GROUP)]
[System.Serializable] public class TestSystem1 : IEcsProcess { }
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.SYSTEMS_GROUP)]
[System.Serializable] public class TestSystem2 : IEcsProcess { }
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.SYSTEMS_GROUP)]
[System.Serializable] public class TestSystem3 : IEcsProcess { }
[MetaGroup(EcsConsts.PACK_GROUP)]
[System.Serializable] public class TestSystem4 : IEcsProcess { }
[MetaGroup(EcsConsts.PACK_GROUP)]
[System.Serializable] public class TestSystem7 : IEcsProcess { }
[MetaGroup(EcsConsts.PACK_GROUP)]
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.AUTHOR)]
[System.Serializable] public class TestSystem8 : IEcsProcess { }
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.AUTHOR)]
[System.Serializable] public class _TestSystemX : IEcsProcess { }
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.AUTHOR)]
[System.Serializable] public class TestSystem9 : IEcsProcess { }
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.AUTHOR)]
[System.Serializable] public class TestSystem5 : IEcsProcess { }
[System.Serializable] public class TestSystem6 : IEcsProcess { }

View File

@ -33,47 +33,29 @@ namespace DCFApixels.DragonECS.Unity.Editors
private const float DamagedComponentHeight = 18f * 2f;
private static bool _isInit;
private static GenericMenu _genericMenu;
private static ComponentDropDown _componentDropDown;
#region Init
private static void Init()
{
if (_genericMenu == null) { _isInit = false; }
if (_componentDropDown == null) { _isInit = false; }
if (_isInit) { return; }
_genericMenu = new GenericMenu();
_componentDropDown = new ComponentDropDown();
var componentTemplateDummies = ComponentTemplateTypeCache.Dummies;
foreach (var dummy in componentTemplateDummies)
{
if (dummy.Type.GetCustomAttribute<SerializableAttribute>() == null)
{
Debug.LogWarning($"Type {dummy.Type.Name} does not have the [Serializable] attribute");
continue;
}
ITypeMeta meta = dummy is ITypeMeta metaOverride ? metaOverride : dummy.Type.ToMeta();
string name = meta.Name;
string description = meta.Description.Text;
MetaGroup group = meta.Group;
if (group.Name.Length > 0)
{
name = group.Name + name;
}
_genericMenu.AddItem(new GUIContent(name, description), false, SelectComponent, dummy);
}
_componentDropDown.OnSelected += SelectComponent;
_isInit = true;
}
[ThreadStatic]
private static SerializedProperty currentProperty;
private static void SelectComponent(object dummy)
private static void SelectComponent(ComponentDropDown.Item item)
{
currentProperty.managedReferenceValue = ((IComponentTemplate)dummy).Clone();
currentProperty.managedReferenceValue = item.Obj.Clone();
currentProperty.isExpanded = false;
currentProperty.serializedObject.ApplyModifiedProperties();
}
#endregion
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
@ -260,7 +242,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
if (GUI.Button(buttonRect, "Select"))
{
currentProperty = componentRefProp;
_genericMenu.ShowAsContext();
_componentDropDown.Show(buttonRect);
}
}
private void DrawDamagedComponent(Rect position, string message)

View File

@ -11,7 +11,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
{
private static readonly Rect HeadIconsRect = new Rect(0f, 0f, 19f, 19f);
private GenericMenu _genericMenu;
private ComponentDropDown _componentDropDown;
private bool _isInit = false;
private static ComponentColorMode AutoColorMode
@ -23,41 +23,22 @@ namespace DCFApixels.DragonECS.Unity.Editors
#region Init
private void Init()
{
if (_genericMenu == null) { _isInit = false; }
if (_componentDropDown == null) { _isInit = false; }
if (_isInit) { return; }
_genericMenu = new GenericMenu();
_componentDropDown = new ComponentDropDown();
var componentTemplateDummies = ComponentTemplateTypeCache.Dummies;
foreach (var dummy in componentTemplateDummies)
{
if (dummy.Type.GetCustomAttribute<SerializableAttribute>() == null)
{
Debug.LogWarning($"Type {dummy.Type.Name} does not have the [Serializable] attribute");
continue;
}
ITypeMeta meta = dummy is ITypeMeta metaOverride ? metaOverride : dummy.Type.ToMeta();
string name = meta.Name;
string description = meta.Description.Text;
MetaGroup group = meta.Group;
if (group.Name.Length > 0)
{
name = group.Name + name;
}
_genericMenu.AddItem(new GUIContent(name, description), false, OnAddComponent, dummy);
}
_componentDropDown.OnSelected += OnAddComponent;
_isInit = true;
}
#endregion
#region Add/Remove
private void OnAddComponent(object obj)
private void OnAddComponent(ComponentDropDown.Item item)
{
Type componentType = obj.GetType();
IComponentTemplate cmptmp = (IComponentTemplate)obj;
Type componentType = item.Obj.GetType();
IComponentTemplate cmptmp = item.Obj;
if (this.target is ITemplateInternal target)
{
SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
@ -112,11 +93,11 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
private void DrawTop(ITemplateInternal target)
{
switch (EcsGUI.Layout.AddClearComponentButtons())
switch (EcsGUI.Layout.AddClearComponentButtons(out Rect rect))
{
case EcsGUI.AddClearComponentButton.AddComponent:
Init();
_genericMenu.ShowAsContext();
_componentDropDown.Show(rect);
break;
case EcsGUI.AddClearComponentButton.Clear:
Init();

View File

@ -0,0 +1,171 @@
#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<IComponentTemplate>
{
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<IEcsPool>
{
public RuntimeComponentDropDown(IEnumerable<IEcsPool> pools)
{
IEnumerable<(IEcsPool, ITypeMeta)> itemMetaPairs = pools.Select(pool =>
{
return (pool, (ITypeMeta)pool.ComponentType.GetMeta());
});
Setup(itemMetaPairs);
}
}
internal class MetaObjectsDropDown<T> : 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, "<NULL>", increment++));
}
Dictionary<Key, Item> dict = new Dictionary<Key, Item>();
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<Item> 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<Key>
{
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<string> splitedEnum = Group.Splited.GetEnumerator();
IEnumerator<string> 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

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: be69cae0ab609f14783c21e187dab681
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -431,16 +431,18 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
}
}
public static bool AddComponentButtons(Rect position)
public static bool AddComponentButton(Rect position, out Rect dropDownRect)
{
position = RectUtility.AddPadding(position, 20f, 20f, 12f, 2f);
return GUI.Button(position, "Add Component");
dropDownRect = RectUtility.AddPadding(position, 20f, 20f, 12f, 2f);
return GUI.Button(dropDownRect, "Add Component");
}
public static AddClearComponentButton AddClearComponentButtons(Rect position)
public static AddClearComponentButton AddClearComponentButtons(Rect position, out Rect dropDownRect)
{
position = RectUtility.AddPadding(position, 20f, 20f, 12f, 2f);
var (left, right) = RectUtility.HorizontalSliceLerp(position, 0.75f);
dropDownRect = left;
if (GUI.Button(left, "Add Component"))
{
return AddClearComponentButton.AddComponent;
@ -559,13 +561,13 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
#endregion
public static bool AddComponentButtons()
public static bool AddComponentButtons(out Rect dropDownRect)
{
return EcsGUI.AddComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f));
return EcsGUI.AddComponentButton(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f), out dropDownRect);
}
public static AddClearComponentButton AddClearComponentButtons()
public static AddClearComponentButton AddClearComponentButtons(out Rect dropDownRect)
{
return EcsGUI.AddClearComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f));
return EcsGUI.AddClearComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f), out dropDownRect);
}
public static void DrawRuntimeComponents(entlong entity, bool isWithFoldout = true)
{
@ -587,11 +589,11 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
if (isWithFoldout == false || IsShowRuntimeComponents)
{
if (AddComponentButtons())
if (AddComponentButtons(out Rect dropDownRect))
{
GenericMenu genericMenu = RuntimeComponentsUtility.GetAddComponentGenericMenu(world);
RuntimeComponentDropDown genericMenu = RuntimeComponentsUtility.GetAddComponentGenericMenu(world);
RuntimeComponentsUtility.CurrentEntityID = entityID;
genericMenu.ShowAsContext();
genericMenu.Show(dropDownRect);
}
GUILayout.Box("", UnityEditorUtility.GetStyle(GUI.color, 0.16f), GUILayout.ExpandWidth(true));
@ -600,7 +602,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
int i = 0;
foreach (var componentTypeID in componentTypeIDs)
{
var pool = world.GetPoolInstance(componentTypeID);
var pool = world.FindPoolInstance(componentTypeID);
{
DrawRuntimeComponent(componentTypeIDs.Length, i++, entityID, pool);
}

View File

@ -1,6 +1,7 @@
using DCFApixels.DragonECS.Unity.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using UnityEditor;
@ -272,9 +273,9 @@ namespace DCFApixels.DragonECS.Unity.Editors
{
public struct WorldData
{
public GenericMenu addComponentGenericMenu;
public RuntimeComponentDropDown addComponentGenericMenu;
public int poolsCount;
public WorldData(GenericMenu addComponentGenericMenu, int poolsCount)
public WorldData(RuntimeComponentDropDown addComponentGenericMenu, int poolsCount)
{
this.addComponentGenericMenu = addComponentGenericMenu;
this.poolsCount = poolsCount;
@ -283,7 +284,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
//world id
private static Dictionary<EcsWorld, WorldData> _worldDatas = new Dictionary<EcsWorld, WorldData>();
public static GenericMenu GetAddComponentGenericMenu(EcsWorld world)
public static RuntimeComponentDropDown GetAddComponentGenericMenu(EcsWorld world)
{
if (_worldDatas.TryGetValue(world, out WorldData data))
{
@ -305,20 +306,21 @@ namespace DCFApixels.DragonECS.Unity.Editors
private static WorldData CreateWorldData(EcsWorld world)
{
GenericMenu genericMenu = new GenericMenu();
IEnumerable<IEcsPool> pools = world.AllPools.ToArray().Where(o => o.IsNullOrDummy() == false);
RuntimeComponentDropDown genericMenu = new RuntimeComponentDropDown(pools);
var pools = world.AllPools;
for (int i = 0; i < pools.Length; i++)
{
var pool = pools[i];
if (pool.IsNullOrDummy())
{
continue;
}
var meta = pool.ComponentType.ToMeta();
string name = meta.Group.Name + meta.Name;
genericMenu.AddItem(new GUIContent(name, meta.Description.Text), false, OnAddComponent, pool);
}
//var pools = world.AllPools;
//for (int i = 0; i < pools.Length; i++)
//{
// var pool = pools[i];
// if (pool.IsNullOrDummy())
// {
// continue;
// }
// var meta = pool.ComponentType.ToMeta();
// string name = meta.Group.Name + meta.Name;
// genericMenu.AddItem(new GUIContent(name, meta.Description.Text), false, OnAddComponent, pool);
//}
return new WorldData(genericMenu, world.PoolsCount);
}