mirror of
https://github.com/DCFApixels/DragonECS-Unity.git
synced 2025-09-18 01:54:35 +08:00
add runtime editing
This commit is contained in:
parent
a356d31937
commit
cb4ef1c853
@ -24,25 +24,45 @@ namespace DCFApixels.DragonECS
|
|||||||
[Header("Default Configs")]
|
[Header("Default Configs")]
|
||||||
[Header("Entites")]
|
[Header("Entites")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int EntitiesCapacity = EcsWorldConfig.Default.EntitiesCapacity;
|
private int _entitiesCapacity = EcsWorldConfig.Default.EntitiesCapacity;
|
||||||
|
|
||||||
[Header("Groups")]
|
[Header("Groups")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int GroupCapacity = EcsWorldConfig.Default.GroupCapacity;
|
private int _groupCapacity = EcsWorldConfig.Default.GroupCapacity;
|
||||||
|
|
||||||
[Header("Pools/Components")]
|
[Header("Pools/Components")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int PoolsCapacity = EcsWorldConfig.Default.PoolsCapacity;
|
private int _poolsCapacity = EcsWorldConfig.Default.PoolsCapacity;
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int PoolComponentsCapacity = EcsWorldConfig.Default.PoolComponentsCapacity;
|
private int _poolComponentsCapacity = EcsWorldConfig.Default.PoolComponentsCapacity;
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int PoolRecycledComponentsCapacity = EcsWorldConfig.Default.PoolRecycledComponentsCapacity;
|
private int _poolRecycledComponentsCapacity = EcsWorldConfig.Default.PoolRecycledComponentsCapacity;
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
public sealed override bool IsEmpty
|
public sealed override bool IsEmpty
|
||||||
{
|
{
|
||||||
get { return _world == null; }
|
get { return _world == null; }
|
||||||
}
|
}
|
||||||
|
public int EntitiesCapacity
|
||||||
|
{
|
||||||
|
get { return _entitiesCapacity; }
|
||||||
|
}
|
||||||
|
public int GroupCapacity
|
||||||
|
{
|
||||||
|
get { return _groupCapacity; }
|
||||||
|
}
|
||||||
|
public int PoolsCapacity
|
||||||
|
{
|
||||||
|
get { return _poolsCapacity; }
|
||||||
|
}
|
||||||
|
public int PoolComponentsCapacity
|
||||||
|
{
|
||||||
|
get { return _poolComponentsCapacity; }
|
||||||
|
}
|
||||||
|
public int PoolRecycledComponentsCapacity
|
||||||
|
{
|
||||||
|
get { return _poolRecycledComponentsCapacity; }
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
@ -94,7 +114,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#region Events
|
#region Events
|
||||||
protected virtual TWorld BuildWorld()
|
protected virtual TWorld BuildWorld()
|
||||||
{
|
{
|
||||||
EcsWorldConfig config = new EcsWorldConfig(EntitiesCapacity, GroupCapacity, PoolsCapacity, PoolComponentsCapacity, PoolRecycledComponentsCapacity);
|
EcsWorldConfig config = new EcsWorldConfig(_entitiesCapacity, _groupCapacity, _poolsCapacity, _poolComponentsCapacity, _poolRecycledComponentsCapacity);
|
||||||
ConfigContainer configs = new ConfigContainer().Set(config);
|
ConfigContainer configs = new ConfigContainer().Set(config);
|
||||||
return (TWorld)Activator.CreateInstance(typeof(TWorld), new object[] { configs, _worldID });
|
return (TWorld)Activator.CreateInstance(typeof(TWorld), new object[] { configs, _worldID });
|
||||||
}
|
}
|
||||||
|
@ -12,32 +12,32 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
|||||||
private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 17f, 19f);
|
private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 17f, 19f);
|
||||||
private static readonly Rect TooltipIconRect = new Rect(0f, 0f, 21f, 15f);
|
private static readonly Rect TooltipIconRect = new Rect(0f, 0f, 21f, 15f);
|
||||||
|
|
||||||
private GUIStyle removeButtonStyle;
|
private GUIStyle _removeButtonStyle;
|
||||||
private GenericMenu genericMenu;
|
private GenericMenu _genericMenu;
|
||||||
private bool _isInit = false;
|
private bool _isInit = false;
|
||||||
|
|
||||||
#region Init
|
#region Init
|
||||||
private void Init()
|
private void Init()
|
||||||
{
|
{
|
||||||
if (genericMenu == null) { _isInit = false; }
|
if (_genericMenu == null) { _isInit = false; }
|
||||||
if (_isInit) { return; }
|
if (_isInit) { return; }
|
||||||
|
|
||||||
var tmpstylebase = UnityEditorUtility.GetStyle(new Color(0.9f, 0f, 0.22f), 0.5f);
|
var tmpstylebase = UnityEditorUtility.GetStyle(new Color(0.9f, 0f, 0.22f), 0.5f);
|
||||||
var tmpStyle = UnityEditorUtility.GetStyle(new Color(1f, 0.5f, 0.7f), 0.5f);
|
var tmpStyle = UnityEditorUtility.GetStyle(new Color(1f, 0.5f, 0.7f), 0.5f);
|
||||||
|
|
||||||
removeButtonStyle = new GUIStyle(EditorStyles.linkLabel);
|
_removeButtonStyle = new GUIStyle(EditorStyles.linkLabel);
|
||||||
removeButtonStyle.alignment = TextAnchor.MiddleCenter;
|
_removeButtonStyle.alignment = TextAnchor.MiddleCenter;
|
||||||
|
|
||||||
removeButtonStyle.normal = tmpstylebase.normal;
|
_removeButtonStyle.normal = tmpstylebase.normal;
|
||||||
removeButtonStyle.hover = tmpStyle.normal;
|
_removeButtonStyle.hover = tmpStyle.normal;
|
||||||
removeButtonStyle.active = tmpStyle.normal;
|
_removeButtonStyle.active = tmpStyle.normal;
|
||||||
removeButtonStyle.focused = tmpStyle.normal;
|
_removeButtonStyle.focused = tmpStyle.normal;
|
||||||
|
|
||||||
removeButtonStyle.padding = new RectOffset(0, 0, 0, 0);
|
_removeButtonStyle.padding = new RectOffset(0, 0, 0, 0);
|
||||||
removeButtonStyle.margin = new RectOffset(0, 0, 0, 0);
|
_removeButtonStyle.margin = new RectOffset(0, 0, 0, 0);
|
||||||
removeButtonStyle.border = new RectOffset(0, 0, 0, 0);
|
_removeButtonStyle.border = new RectOffset(0, 0, 0, 0);
|
||||||
|
|
||||||
genericMenu = new GenericMenu();
|
_genericMenu = new GenericMenu();
|
||||||
|
|
||||||
var componentTemplateDummies = ComponentTemplateTypeCache.Dummies;
|
var componentTemplateDummies = ComponentTemplateTypeCache.Dummies;
|
||||||
foreach (var dummy in componentTemplateDummies)
|
foreach (var dummy in componentTemplateDummies)
|
||||||
@ -56,7 +56,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
|||||||
{
|
{
|
||||||
name = $"{name} {EcsUnityConsts.INFO_MARK}";
|
name = $"{name} {EcsUnityConsts.INFO_MARK}";
|
||||||
}
|
}
|
||||||
genericMenu.AddItem(new GUIContent(name, description), false, OnAddComponent, dummy);
|
_genericMenu.AddItem(new GUIContent(name, description), false, OnAddComponent, dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
_isInit = true;
|
_isInit = true;
|
||||||
@ -122,7 +122,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
|||||||
if (GUILayout.Button("Add Component", GUILayout.Height(24f)))
|
if (GUILayout.Button("Add Component", GUILayout.Height(24f)))
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
genericMenu.ShowAsContext();
|
_genericMenu.ShowAsContext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void DrawFooter(ITemplateInternal target)
|
private void DrawFooter(ITemplateInternal target)
|
||||||
@ -167,8 +167,6 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
|||||||
string description = meta.Description;
|
string description = meta.Description;
|
||||||
Color panelColor = meta.Color.ToUnityColor().Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE);
|
Color panelColor = meta.Color.ToUnityColor().Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE);
|
||||||
|
|
||||||
Rect removeButtonRect = GUILayoutUtility.GetLastRect();
|
|
||||||
|
|
||||||
//GUIContent label = new GUIContent(name);
|
//GUIContent label = new GUIContent(name);
|
||||||
GUIContent label = UnityEditorUtility.GetLabel(name);
|
GUIContent label = UnityEditorUtility.GetLabel(name);
|
||||||
bool isEmpty = componentType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Length <= 0;
|
bool isEmpty = componentType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Length <= 0;
|
||||||
@ -176,6 +174,8 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
|||||||
Color alphaPanelColor = panelColor;
|
Color alphaPanelColor = panelColor;
|
||||||
alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA;
|
alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA;
|
||||||
|
|
||||||
|
Rect removeButtonRect = GUILayoutUtility.GetLastRect();
|
||||||
|
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(alphaPanelColor));
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(alphaPanelColor));
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
|||||||
removeButtonRect.center = new Vector2(lastrect.xMax + removeButtonRect.width, lastrect.yMin + removeButtonRect.height / 2f);
|
removeButtonRect.center = new Vector2(lastrect.xMax + removeButtonRect.width, lastrect.yMin + removeButtonRect.height / 2f);
|
||||||
|
|
||||||
GUILayout.Label("", GUILayout.Width(removeButtonRect.width));
|
GUILayout.Label("", GUILayout.Width(removeButtonRect.width));
|
||||||
if (GUI.Button(removeButtonRect, "x", removeButtonStyle))
|
if (GUI.Button(removeButtonRect, "x", _removeButtonStyle))
|
||||||
{
|
{
|
||||||
OnRemoveComponentAt(index);
|
OnRemoveComponentAt(index);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
|||||||
internal readonly static Color GreenColor = new Color32(75, 255, 0, 255);
|
internal readonly static Color GreenColor = new Color32(75, 255, 0, 255);
|
||||||
internal readonly static Color RedColor = new Color32(255, 0, 75, 255);
|
internal readonly static Color RedColor = new Color32(255, 0, 75, 255);
|
||||||
|
|
||||||
|
private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 17f, 19f);
|
||||||
|
private static readonly Rect TooltipIconRect = new Rect(0f, 0f, 21f, 15f);
|
||||||
//private static GUILayoutOption[] _defaultParams;
|
//private static GUILayoutOption[] _defaultParams;
|
||||||
//private static bool _isInit = false;
|
//private static bool _isInit = false;
|
||||||
//private static void Init()
|
//private static void Init()
|
||||||
@ -68,6 +70,13 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
|
|
||||||
|
if (GUILayout.Button("Add Component", GUILayout.Height(24f)))
|
||||||
|
{
|
||||||
|
GenericMenu genericMenu = RuntimeComponentsUtility.GetAddComponentGenericMenu(world);
|
||||||
|
RuntimeComponentsUtility.CurrentEntityID = entityID;
|
||||||
|
genericMenu.ShowAsContext();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private static readonly BindingFlags fieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
private static readonly BindingFlags fieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
private static void DrawRuntimeComponent(int entityID, IEcsPool pool)
|
private static void DrawRuntimeComponent(int entityID, IEcsPool pool)
|
||||||
@ -77,16 +86,37 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
|||||||
{
|
{
|
||||||
object data = pool.GetRaw(entityID);
|
object data = pool.GetRaw(entityID);
|
||||||
Color panelColor = meta.Color.ToUnityColor().Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE);
|
Color panelColor = meta.Color.ToUnityColor().Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE);
|
||||||
|
|
||||||
|
float padding = EditorGUIUtility.standardVerticalSpacing;
|
||||||
|
Rect removeButtonRect = GUILayoutUtility.GetLastRect();
|
||||||
|
|
||||||
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA));
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA));
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
|
|
||||||
|
bool isRemoveComponent = false;
|
||||||
|
removeButtonRect.yMin = removeButtonRect.yMax;
|
||||||
|
removeButtonRect.yMax += RemoveButtonRect.height;
|
||||||
|
removeButtonRect.xMin = removeButtonRect.xMax - RemoveButtonRect.width;
|
||||||
|
removeButtonRect.center += Vector2.up * padding * 2f;
|
||||||
|
if (GUI.Button(removeButtonRect, "x"))
|
||||||
|
{
|
||||||
|
isRemoveComponent = true;
|
||||||
|
}
|
||||||
|
|
||||||
Type componentType = pool.ComponentType;
|
Type componentType = pool.ComponentType;
|
||||||
ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType);
|
ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType);
|
||||||
bool changed = DrawRuntimeData(componentType, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData);
|
bool changed = DrawRuntimeData(componentType, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData);
|
||||||
if (changed)
|
if (changed || isRemoveComponent)
|
||||||
|
{
|
||||||
|
if (isRemoveComponent)
|
||||||
|
{
|
||||||
|
pool.Del(entityID);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
pool.SetRaw(entityID, resultData);
|
pool.SetRaw(entityID, resultData);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using DCFApixels.DragonECS.Unity.Internal;
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
@ -156,5 +158,95 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static class RuntimeComponentsUtility
|
||||||
|
{
|
||||||
|
public struct WorldData
|
||||||
|
{
|
||||||
|
public GenericMenu addComponentGenericMenu;
|
||||||
|
public int poolsCount;
|
||||||
|
public WorldData(GenericMenu addComponentGenericMenu, int poolsCount)
|
||||||
|
{
|
||||||
|
this.addComponentGenericMenu = addComponentGenericMenu;
|
||||||
|
this.poolsCount = poolsCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//world id
|
||||||
|
private static Dictionary<EcsWorld, WorldData> _worldDatas = new Dictionary<EcsWorld, WorldData>();
|
||||||
|
|
||||||
|
public static GenericMenu GetAddComponentGenericMenu(EcsWorld world)
|
||||||
|
{
|
||||||
|
if (_worldDatas.TryGetValue(world, out WorldData data))
|
||||||
|
{
|
||||||
|
if (data.poolsCount != world.PoolsCount)
|
||||||
|
{
|
||||||
|
data = CreateWorldData(world);
|
||||||
|
_worldDatas[world] = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data = CreateWorldData(world);
|
||||||
|
_worldDatas[world] = data;
|
||||||
|
world.AddListener(new Listener(world));
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.addComponentGenericMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WorldData CreateWorldData(EcsWorld world)
|
||||||
|
{
|
||||||
|
GenericMenu genericMenu = new GenericMenu();
|
||||||
|
|
||||||
|
var pools = world.AllPools;
|
||||||
|
for (int i = 0; i < world.PoolsCount; i++)
|
||||||
|
{
|
||||||
|
var pool = pools[i];
|
||||||
|
if (pool.IsNullOrDummy())
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var meta = pool.ComponentType.ToMeta();
|
||||||
|
|
||||||
|
genericMenu.AddItem(new GUIContent(meta.Name, meta.Description), false, OnAddComponent, pool);
|
||||||
|
}
|
||||||
|
return new WorldData(genericMenu, world.PoolsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int CurrentEntityID = 0;
|
||||||
|
|
||||||
|
private static void OnAddComponent(object userData)
|
||||||
|
{
|
||||||
|
IEcsPool pool = (IEcsPool)userData;
|
||||||
|
if (pool.World.IsUsed(CurrentEntityID) == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pool.Has(CurrentEntityID) == false)
|
||||||
|
{
|
||||||
|
pool.AddRaw(CurrentEntityID, Activator.CreateInstance(pool.ComponentType));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Entity({CurrentEntityID}) already has component {EcsDebugUtility.GetGenericTypeName(pool.ComponentType)}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Listener : IEcsWorldEventListener
|
||||||
|
{
|
||||||
|
private EcsWorld _world;
|
||||||
|
public Listener(EcsWorld world)
|
||||||
|
{
|
||||||
|
_world = world;
|
||||||
|
}
|
||||||
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
||||||
|
public void OnWorldDestroy()
|
||||||
|
{
|
||||||
|
_worldDatas.Remove(_world);
|
||||||
|
}
|
||||||
|
public void OnWorldResize(int newSize) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user