This commit is contained in:
Mikhail 2024-03-07 03:18:00 +08:00
parent 6e718691cd
commit ade0db2b0c
35 changed files with 323 additions and 222 deletions

View File

@ -3,19 +3,5 @@
namespace DCFApixels.DragonECS
{
[CreateAssetMenu(fileName = nameof(EcsDefaultWorldProvider), menuName = EcsConsts.FRAMEWORK_NAME + "/WorldProviders/" + nameof(EcsDefaultWorldProvider), order = 1)]
public class EcsDefaultWorldProvider : EcsWorldProvider<EcsDefaultWorld>
{
//private static EcsDefaultWorldProvider _singleInstance;
//public static EcsDefaultWorldProvider SingletonInstance
//{
// get
// {
// if (_singleInstance == null)
// {
// _singleInstance = FindOrCreateSingleton<EcsDefaultWorldProvider>();
// }
// return _singleInstance;
// }
//}
}
public class EcsDefaultWorldProvider : EcsWorldProvider<EcsDefaultWorld> { }
}

View File

@ -14,10 +14,5 @@
return _instance;
}
}
protected override EcsDefaultWorld BuildWorld()
{
return new EcsDefaultWorld();
}
}
}

View File

@ -16,8 +16,29 @@ namespace DCFApixels.DragonECS
[Serializable]
public abstract class EcsWorldProvider<TWorld> : EcsWorldProviderBase where TWorld : EcsWorld
{
private readonly static EcsWorldConfig _emptyConfig = new EcsWorldConfig();
private TWorld _world;
[SerializeField]
public short _worldID = -1;
[Header("Default Configs")]
[Header("Entites")]
[SerializeField]
private int EntitiesCapacity = _emptyConfig.Get_EntitiesCapacity();
[Header("Groups")]
[SerializeField]
private int GroupCapacity = _emptyConfig.Get_GroupCapacity();
[Header("Pools/Components")]
[SerializeField]
private int PoolsCapacity = _emptyConfig.Get_PoolsCapacity();
[SerializeField]
private int PoolComponentsCapacity = _emptyConfig.Get_PoolComponentsCapacity();
[SerializeField]
private int PoolRecycledComponentsCapacity = _emptyConfig.Get_PoolRecycledComponentsCapacity();
#region Properties
public sealed override bool IsEmpty
{
@ -74,7 +95,13 @@ namespace DCFApixels.DragonECS
#region Events
protected virtual TWorld BuildWorld()
{
return (TWorld)Activator.CreateInstance(typeof(TWorld), new object[] { null, -1 });
EcsWorldConfig config = new EcsWorldConfig();
config.Set_EntitiesCapacity(EntitiesCapacity);
config.Set_GroupCapacity(GroupCapacity);
config.Set_PoolComponentsCapacity(PoolComponentsCapacity);
config.Set_PoolRecycledComponentsCapacity(PoolRecycledComponentsCapacity);
config.Set_PoolsCapacity(PoolsCapacity);
return (TWorld)Activator.CreateInstance(typeof(TWorld), new object[] { config, _worldID });
}
protected virtual void OnWorldCreated(TWorld world) { }
#endregion

View File

@ -12,18 +12,36 @@ namespace DCFApixels.DragonECS.Unity.Editors
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (Target.IsEmpty)
{
var style = EcsEditor.GetStyle(new Color32(255, 0, 75, 100));
var style = UnityEditorUtility.GetStyle(new Color32(255, 0, 75, 100));
GUILayout.Box("Is Empty", style, GUILayout.ExpandWidth(true));
}
else
{
var style = EcsEditor.GetStyle(new Color32(75, 255, 0, 100));
var style = UnityEditorUtility.GetStyle(new Color32(75, 255, 0, 100));
EcsWorld world = Target.GetRaw();
GUILayout.Box($"{world.GetMeta().Name} ( {world.id} )", style, GUILayout.ExpandWidth(true));
}
base.OnInspectorGUI();
GUILayout.Space(10);
if (GUILayout.Button("Destroy"))
{
var w = Target.GetRaw();
if (w != null && w.IsDestroyed == false)
{
w.Destroy();
}
Target.SetRaw(null);
}
Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 2f);
Color c = Color.white;
c.a = 0.3f;
EditorGUI.DrawRect(r, c);
GUILayout.Space(10);
}
}
}

View File

@ -1,13 +1,18 @@
using System;
using Unity.Profiling;
using UnityEditor;
using UnityEngine;
namespace DCFApixels.DragonECS
{
[InitializeOnLoad]
public class UnityDebugService : DebugService
{
private ProfilerMarker[] _profilerMarkers = new ProfilerMarker[64];
static UnityDebugService()
{
Activate();
}
public static void Activate()
{
Set<UnityDebugService>();

View File

@ -1,13 +1,12 @@
using DCFApixels.DragonECS.Unity.Internal;
#if UNITY_EDITOR
using DCFApixels.DragonECS.Unity.Internal;
using System;
using System.Reflection;
#if UNITY_EDITOR
namespace DCFApixels.DragonECS.Unity.Editors
{
using UnityEditor;
using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors
{
public abstract class EntityTemplateEditorBase : Editor
{
private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 17f, 19f);
@ -20,13 +19,11 @@ namespace DCFApixels.DragonECS.Unity.Editors
#region Init
private void Init()
{
if (genericMenu == null)
_isInit = false;
if (_isInit)
return;
if (genericMenu == null) { _isInit = false; }
if (_isInit) { return; }
var tmpstylebase = EcsEditor.GetStyle(new Color(0.9f, 0f, 0.22f), 0.5f);
var tmpStyle = EcsEditor.GetStyle(new Color(1f, 0.5f, 0.7f), 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);
removeButtonStyle = new GUIStyle(EditorStyles.linkLabel);
removeButtonStyle.alignment = TextAnchor.MiddleCenter;
@ -111,7 +108,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
DrawTop(target);
GUILayout.BeginVertical(EcsEditor.GetStyle(Color.black, 0.2f));
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f));
GUILayout.Label("", GUILayout.Height(0), GUILayout.ExpandWidth(true));
for (int i = 0; i < componentsProp.arraySize; i++)
{
@ -172,14 +169,15 @@ namespace DCFApixels.DragonECS.Unity.Editors
Rect removeButtonRect = GUILayoutUtility.GetLastRect();
GUIContent label = new GUIContent(name);
//GUIContent label = new GUIContent(name);
GUIContent label = UnityEditorUtility.GetLabel(name);
bool isEmpty = componentType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Length <= 0;
float padding = EditorGUIUtility.standardVerticalSpacing;
Color alphaPanelColor = panelColor;
alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA;
EditorGUI.BeginChangeCheck();
GUILayout.BeginVertical(EcsEditor.GetStyle(alphaPanelColor));
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(alphaPanelColor));
#region Draw Component Block
bool isRemoveComponent = false;
@ -204,12 +202,12 @@ namespace DCFApixels.DragonECS.Unity.Editors
{
OnRemoveComponentAt(index);
}
if (!string.IsNullOrEmpty(description))
if (string.IsNullOrEmpty(description) == false)
{
Rect tooltipIconRect = TooltipIconRect;
tooltipIconRect.center = removeButtonRect.center;
tooltipIconRect.center -= Vector2.right * tooltipIconRect.width;
GUIContent descriptionLabel = new GUIContent(EcsUnityConsts.INFO_MARK, description);
GUIContent descriptionLabel = UnityEditorUtility.GetLabel(EcsUnityConsts.INFO_MARK, description);
GUI.Label(tooltipIconRect, descriptionLabel, EditorStyles.boldLabel);
}
#endregion

View File

@ -1,5 +1,4 @@
using Codice.Utils;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

8
src/Internal.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fc246fdeda320b649899ee44aca24e18
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 7ff185425dcbca44f820bfc6c564d1d2
guid: 93ac43c51e44bbb459de81017f530fbe
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@ -2,63 +2,11 @@
using DCFApixels.DragonECS.Unity.Internal;
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors
{
internal static class EcsUnityEditorUtility
{
public static string TransformFieldName(string name)
{
if (name.Length <= 0)
{
return name;
}
StringBuilder b = new StringBuilder();
bool nextWorld = true;
bool prewIsUpper = false;
for (int i = 0; i < name.Length; i++)
{
char c = name[i];
if (char.IsLetter(c) == false)
{
nextWorld = true;
prewIsUpper = false;
continue;
}
bool isUpper = char.IsUpper(c);
if (isUpper)
{
if (nextWorld == false && prewIsUpper == false)
{
b.Append(' ');
nextWorld = true;
}
}
if (nextWorld)
{
b.Append(char.ToUpper(c));
}
else
{
b.Append(c);
}
nextWorld = false;
prewIsUpper = isUpper;
}
return b.ToString();
}
}
internal static class EcsGUI
{
internal readonly static Color GrayColor = new Color32(100, 100, 100, 255);
@ -89,23 +37,27 @@ namespace DCFApixels.DragonECS.Unity.Editors
get { return DebugMonitorPrefs.instance.IsShowRuntimeComponents; }
set { DebugMonitorPrefs.instance.IsShowRuntimeComponents = value; }
}
public static void DrawRuntimeComponents(entlong entity)
public static void DrawRuntimeComponents(entlong entity, bool isWithFoldout = true)
{
if (entity.TryUnpack(out int entityID, out EcsWorld world))
{
DrawRuntimeComponents(entityID, world);
DrawRuntimeComponents(entityID, world, isWithFoldout);
}
}
public static void DrawRuntimeComponents(int entityID, EcsWorld world)
public static void DrawRuntimeComponents(int entityID, EcsWorld world, bool isWithFoldout = true)
{
var componentTypeIDs = world.GetComponentTypeIDs(entityID);
GUILayout.BeginVertical(EcsEditor.GetStyle(Color.black, 0.2f));
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f));
IsShowRuntimeComponents = EditorGUILayout.Foldout(IsShowRuntimeComponents, "RUNTIME COMPONENTS");
if (IsShowRuntimeComponents)
if (isWithFoldout)
{
GUILayout.Box("", EcsEditor.GetStyle(GUI.color, 0.16f), GUILayout.ExpandWidth(true));
IsShowRuntimeComponents = EditorGUILayout.BeginFoldoutHeaderGroup(IsShowRuntimeComponents, "RUNTIME COMPONENTS", EditorStyles.foldout);
EditorGUILayout.EndFoldoutHeaderGroup();
}
if (isWithFoldout == false || IsShowRuntimeComponents)
{
GUILayout.Box("", UnityEditorUtility.GetStyle(GUI.color, 0.16f), GUILayout.ExpandWidth(true));
IsShowHidden = EditorGUI.Toggle(GUILayoutUtility.GetLastRect(), "Show Hidden", IsShowHidden);
foreach (var componentTypeID in componentTypeIDs)
{
@ -125,12 +77,12 @@ namespace DCFApixels.DragonECS.Unity.Editors
{
object data = pool.GetRaw(entityID);
Color panelColor = meta.Color.ToUnityColor().Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE);
GUILayout.BeginVertical(EcsEditor.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA));
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA));
EditorGUI.BeginChangeCheck();
Type componentType = pool.ComponentType;
ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType);
bool changed = DrawRuntimeData(componentType, new GUIContent(meta.Name), expandMatrix, data, out object resultData);
bool changed = DrawRuntimeData(componentType, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData);
if (changed)
{
pool.SetRaw(entityID, resultData);
@ -158,12 +110,11 @@ namespace DCFApixels.DragonECS.Unity.Editors
EditorGUI.indentLevel++;
foreach (var field in type.GetFields(fieldFlags))
{
GUIContent subLabel = new GUIContent(EcsUnityEditorUtility.TransformFieldName(field.Name));
GUIContent subLabel = UnityEditorUtility.GetLabel(UnityEditorUtility.TransformFieldName(field.Name));
if (DrawRuntimeData(field.FieldType, subLabel, expandMatrix, field.GetValue(data), out object fieldData))
{
field.SetValue(data, fieldData);
outData = fieldData;
outData = data;
changed = true;
}
}
@ -175,8 +126,21 @@ namespace DCFApixels.DragonECS.Unity.Editors
if (isUnityObject)
{
EditorGUI.BeginChangeCheck();
UnityEngine.Object uobj = (UnityEngine.Object)data;
var uobj = (UnityEngine.Object)data;
bool isComponent = (typeof(UnityEngine.Component)).IsAssignableFrom(fieldType);
if (isComponent)
{
uobj = EditorGUILayout.ObjectField(label, uobj, typeof(UnityEngine.Object), true);
}
else
{
uobj = EditorGUILayout.ObjectField(label, uobj, fieldType, true);
}
if (isComponent && uobj is GameObject go)
{
uobj = go.GetComponent(fieldType);
}
if (EditorGUI.EndChangeCheck())
{
outData = uobj;
@ -198,6 +162,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
outData = w.Data;
changed = true;
}
w.Release();
}
}
@ -206,104 +171,5 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
}
}
[InitializeOnLoad]
public static class EcsEditor
{
static EcsEditor()
{
colorBoxeStyles = new SparseArray<GUIStyle>();
}
private static SparseArray<GUIStyle> colorBoxeStyles = new SparseArray<GUIStyle>();
public static GUIStyle GetStyle(Color color, float alphaMultiplier)
{
color.a *= alphaMultiplier;
return GetStyle(color);
}
public static GUIStyle GetStyle(Color32 color32)
{
int colorCode = new Color32Union(color32).colorCode;
if (colorBoxeStyles.TryGetValue(colorCode, out GUIStyle style))
{
if (style == null || style.normal.background == null)
{
style = CreateStyle(color32, colorCode);
colorBoxeStyles[colorCode] = style;
}
return style;
}
style = CreateStyle(color32, colorCode);
colorBoxeStyles.Add(colorCode, style);
return style;
}
private static GUIStyle CreateStyle(Color32 color32, int colorCode)
{
GUIStyle result = new GUIStyle(GUI.skin.box);
Color componentColor = color32;
Texture2D texture2D = CreateTexture(2, 2, componentColor);
result.hover.background = texture2D;
result.focused.background = texture2D;
result.active.background = texture2D;
result.normal.background = texture2D;
return result;
}
private static Texture2D CreateTexture(int width, int height, Color color)
{
var pixels = new Color[width * height];
for (var i = 0; i < pixels.Length; ++i)
pixels[i] = color;
var result = new Texture2D(width, height);
result.SetPixels(pixels);
result.Apply();
return result;
}
#region Utils
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 4)]
private readonly ref struct Color32Union
{
[FieldOffset(0)]
public readonly int colorCode;
[FieldOffset(0)]
public readonly byte r;
[FieldOffset(1)]
public readonly byte g;
[FieldOffset(2)]
public readonly byte b;
[FieldOffset(3)]
public readonly byte a;
public Color32Union(byte r, byte g, byte b, byte a) : this()
{
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
public Color32Union(Color32 color) : this()
{
r = color.r;
g = color.g;
b = color.b;
a = color.a;
}
}
#endregion
}
public static class ReflectionExtensions
{
public static bool TryGetAttribute<T>(this MemberInfo self, out T attrbiute) where T : Attribute
{
attrbiute = self.GetCustomAttribute<T>();
return attrbiute != null;
}
public static bool HasAttribute<T>(this MemberInfo self) where T : Attribute
{
return self.GetCustomAttribute<T>() != null;
}
}
}
#endif

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: f72bc8ca8108c2b4aac41df126dba1e1
guid: f27d7dd0452a826479d2b19d7885ce49
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -25,12 +25,12 @@ namespace DCFApixels.DragonECS.Unity.Editors
return result;
}
}
}
[Serializable]
public class EmptyDummy
internal class EmptyDummy
{
public static readonly EmptyDummy Instance = new EmptyDummy();
private EmptyDummy() { }
}
}
#endif

View File

@ -0,0 +1,160 @@
#if UNITY_EDITOR
using DCFApixels.DragonECS.Unity.Internal;
using System.Runtime.InteropServices;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors
{
[InitializeOnLoad]
internal static class UnityEditorUtility
{
static UnityEditorUtility()
{
colorBoxeStyles = new SparseArray<GUIStyle>();
}
private static SparseArray<GUIStyle> colorBoxeStyles = new SparseArray<GUIStyle>();
private static GUIContent _singletonContent = null;
#region TransformFieldName
public static string TransformFieldName(string name)
{
if (name.Length <= 0)
{
return name;
}
StringBuilder b = new StringBuilder();
bool nextWorld = true;
bool prewIsUpper = false;
for (int i = 0; i < name.Length; i++)
{
char c = name[i];
if (char.IsLetter(c) == false)
{
nextWorld = true;
prewIsUpper = false;
continue;
}
bool isUpper = char.IsUpper(c);
if (isUpper)
{
if (nextWorld == false && prewIsUpper == false)
{
b.Append(' ');
nextWorld = true;
}
}
if (nextWorld)
{
b.Append(char.ToUpper(c));
}
else
{
b.Append(c);
}
nextWorld = false;
prewIsUpper = isUpper;
}
return b.ToString();
}
#endregion
#region Label
public static GUIContent GetLabel(string name, string tooltip = null)
{
if (_singletonContent == null)
{
_singletonContent = new GUIContent();
}
_singletonContent.text = name;
_singletonContent.tooltip = tooltip;
return _singletonContent;
}
#endregion
#region GetStyle
public static GUIStyle GetStyle(Color color, float alphaMultiplier)
{
color.a *= alphaMultiplier;
return GetStyle(color);
}
public static GUIStyle GetStyle(Color32 color32)
{
int colorCode = new Color32Union(color32).colorCode;
if (colorBoxeStyles.TryGetValue(colorCode, out GUIStyle style))
{
if (style == null || style.normal.background == null)
{
style = CreateStyle(color32, colorCode);
colorBoxeStyles[colorCode] = style;
}
return style;
}
style = CreateStyle(color32, colorCode);
colorBoxeStyles.Add(colorCode, style);
return style;
}
private static GUIStyle CreateStyle(Color32 color32, int colorCode)
{
GUIStyle result = new GUIStyle(GUI.skin.box);
Color componentColor = color32;
Texture2D texture2D = CreateTexture(2, 2, componentColor);
result.hover.background = texture2D;
result.focused.background = texture2D;
result.active.background = texture2D;
result.normal.background = texture2D;
return result;
}
private static Texture2D CreateTexture(int width, int height, Color color)
{
var pixels = new Color[width * height];
for (var i = 0; i < pixels.Length; ++i)
pixels[i] = color;
var result = new Texture2D(width, height);
result.SetPixels(pixels);
result.Apply();
return result;
}
#endregion
#region Utils
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 4)]
private readonly ref struct Color32Union
{
[FieldOffset(0)]
public readonly int colorCode;
[FieldOffset(0)]
public readonly byte r;
[FieldOffset(1)]
public readonly byte g;
[FieldOffset(2)]
public readonly byte b;
[FieldOffset(3)]
public readonly byte a;
public Color32Union(byte r, byte g, byte b, byte a) : this()
{
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
public Color32Union(Color32 color) : this()
{
r = color.r;
g = color.g;
b = color.b;
a = color.a;
}
}
#endregion
}
}
#endif

View File

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

View File

@ -0,0 +1,20 @@
#if UNITY_EDITOR
using System;
using System.Reflection;
namespace DCFApixels.DragonECS.Unity.Internal
{
internal static class ReflectionExtensions
{
public static bool TryGetAttribute<T>(this MemberInfo self, out T attrbiute) where T : Attribute
{
attrbiute = self.GetCustomAttribute<T>();
return attrbiute != null;
}
public static bool HasAttribute<T>(this MemberInfo self) where T : Attribute
{
return self.GetCustomAttribute<T>() != null;
}
}
}
#endif

View File

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

View File

@ -1,7 +1,4 @@
//SparseArray. Analogous to Dictionary<int, T>, but faster.
//Benchmark result of indexer.get speed test with 300 elements:
//[Dictinary: 5.786us] [SparseArray: 2.047us].
using System;
using System;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;