diff --git a/src/Buildin/EcsDefaultWorldProvider.cs b/src/Buildin/EcsDefaultWorldProvider.cs index 4892e3f..21cf271 100644 --- a/src/Buildin/EcsDefaultWorldProvider.cs +++ b/src/Buildin/EcsDefaultWorldProvider.cs @@ -5,6 +5,6 @@ namespace DCFApixels.DragonECS [CreateAssetMenu(fileName = nameof(EcsDefaultWorldProvider), menuName = EcsConsts.FRAMEWORK_NAME + "/WorldProviders/" + nameof(EcsDefaultWorldProvider), order = 1)] public class EcsDefaultWorldProvider : EcsWorldProvider { - protected override EcsDefaultWorld BuildWorld(ConfigContainer configs) { return new EcsDefaultWorld(configs, WorldID); } + protected override EcsDefaultWorld BuildWorld(ConfigContainer configs) { return new EcsDefaultWorld(configs, null, WorldID); } } } diff --git a/src/Buildin/EcsDefaultWorldSingletonProvider.cs b/src/Buildin/EcsDefaultWorldSingletonProvider.cs index fbd0b25..2f2abc2 100644 --- a/src/Buildin/EcsDefaultWorldSingletonProvider.cs +++ b/src/Buildin/EcsDefaultWorldSingletonProvider.cs @@ -14,6 +14,6 @@ return _instance; } } - protected override EcsDefaultWorld BuildWorld(ConfigContainer configs) { return new EcsDefaultWorld(configs, WorldID); } + protected override EcsDefaultWorld BuildWorld(ConfigContainer configs) { return new EcsDefaultWorld(configs, null, WorldID); } } } diff --git a/src/Buildin/EcsRootUnity.cs b/src/Buildin/EcsRootUnity.cs index fbf4531..d859dab 100644 --- a/src/Buildin/EcsRootUnity.cs +++ b/src/Buildin/EcsRootUnity.cs @@ -77,6 +77,7 @@ namespace DCFApixels.DragonECS private void OnDrawGizmos() { + Gizmos.DrawIcon(transform.position, "", false); _pipeline?.DrawGizmos(); } diff --git a/src/Buildin/EcsWorldProvider.cs b/src/Buildin/EcsWorldProvider.cs index 45e2735..8f4f35e 100644 --- a/src/Buildin/EcsWorldProvider.cs +++ b/src/Buildin/EcsWorldProvider.cs @@ -5,6 +5,6 @@ namespace DCFApixels.DragonECS [CreateAssetMenu(fileName = nameof(EcsWorldProvider), menuName = EcsConsts.FRAMEWORK_NAME + "/WorldProviders/" + nameof(EcsWorldProvider), order = 1)] public class EcsWorldProvider : EcsWorldProvider { - protected override EcsWorld BuildWorld(ConfigContainer configs) { return new EcsWorld(configs, WorldID); } + protected override EcsWorld BuildWorld(ConfigContainer configs) { return new EcsWorld(configs, null, WorldID); } } } diff --git a/src/Connectors/Editor/EcsWorldProviderBaseEditor.cs b/src/Connectors/Editor/EcsWorldProviderBaseEditor.cs index 2d8a12b..8d61c90 100644 --- a/src/Connectors/Editor/EcsWorldProviderBaseEditor.cs +++ b/src/Connectors/Editor/EcsWorldProviderBaseEditor.cs @@ -33,7 +33,6 @@ namespace DCFApixels.DragonECS.Unity.Editors } EcsGUI.Layout.DrawWorldBaseInfo(Target.GetCurrentWorldRaw()); - base.OnInspectorGUI(); GUILayout.Space(10); @@ -53,6 +52,8 @@ namespace DCFApixels.DragonECS.Unity.Editors c.a = 0.3f; EditorGUI.DrawRect(r, c); GUILayout.Space(10); + + EcsGUI.Layout.DrawWorldComponents(Target.GetCurrentWorldRaw()); } } } diff --git a/src/DebugUtils/Editor/SettingsEditor.cs b/src/DebugUtils/Editor/SettingsEditor.cs index 42ab0ed..d8ad072 100644 --- a/src/DebugUtils/Editor/SettingsEditor.cs +++ b/src/DebugUtils/Editor/SettingsEditor.cs @@ -53,29 +53,25 @@ namespace DCFApixels.DragonECS.Unity.Editors //using (prefs.DisableAutoSave()) { - GUILayout.BeginHorizontal(); prefs.IsShowHidden = EditorGUILayout.ToggleLeft( UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.IsShowHidden)), prefs.IsShowHidden); - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); prefs.IsShowInterfaces = EditorGUILayout.ToggleLeft( UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.IsShowInterfaces)), prefs.IsShowInterfaces); - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); prefs.IsShowRuntimeComponents = EditorGUILayout.ToggleLeft( UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.IsShowRuntimeComponents)), prefs.IsShowRuntimeComponents); - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); prefs.IsUseCustomNames = EditorGUILayout.ToggleLeft( UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.IsUseCustomNames)), prefs.IsUseCustomNames); - GUILayout.EndHorizontal(); + + //prefs.IsFastModeRuntimeComponents = EditorGUILayout.ToggleLeft( + // UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.IsFastModeRuntimeComponents)), + // prefs.IsFastModeRuntimeComponents); prefs.ComponentColorMode = (ComponentColorMode)EditorGUILayout.EnumPopup(UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.ComponentColorMode)), prefs.ComponentColorMode); } diff --git a/src/DebugUtils/Editor/UserSettingsPrefs.cs b/src/DebugUtils/Editor/UserSettingsPrefs.cs index eb7f9cc..35707df 100644 --- a/src/DebugUtils/Editor/UserSettingsPrefs.cs +++ b/src/DebugUtils/Editor/UserSettingsPrefs.cs @@ -69,17 +69,18 @@ namespace DCFApixels.DragonECS.Unity.Editors } } } - //[SerializeField] - //private bool _poolsToggle = false; - //public bool PoolsToggle + //private bool _isFastModeRuntimeComponents = false; + //public bool IsFastModeRuntimeComponents //{ - // get => _poolsToggle; + // get => _isFastModeRuntimeComponents; // set // { - // _isChanged = _poolsToggle != value; - // _poolsToggle = value; - // AutoSave(); + // if (_isFastModeRuntimeComponents != value) + // { + // _isFastModeRuntimeComponents = value; + // AutoSave(); + // } // } //} diff --git a/src/DebugUtils/Monitors/Editor/WorldMonitorEditor.cs b/src/DebugUtils/Monitors/Editor/WorldMonitorEditor.cs index 67149d2..ea734fc 100644 --- a/src/DebugUtils/Monitors/Editor/WorldMonitorEditor.cs +++ b/src/DebugUtils/Monitors/Editor/WorldMonitorEditor.cs @@ -118,6 +118,8 @@ namespace DCFApixels.DragonECS.Unity.Editors EcsGUI.Layout.DrawWorldBaseInfo(Target.World); + + EcsGUI.Layout.DrawWorldComponents(Target.World); } } } diff --git a/src/Internal/ArrayUtility.cs b/src/Internal/ArrayUtility.cs index f55393e..b17c463 100644 --- a/src/Internal/ArrayUtility.cs +++ b/src/Internal/ArrayUtility.cs @@ -71,4 +71,75 @@ namespace DCFApixels.DragonECS.Unity.Internal void IEnumerator.Reset() { throw new NotSupportedException(); } } } + + internal static class ArrayUtility + { + private static int GetHighBitNumber(uint bits) + { + if (bits == 0) + { + return -1; + } + int bit = 0; + if ((bits & 0xFFFF0000) != 0) + { + bits >>= 16; + bit |= 16; + } + if ((bits & 0xFF00) != 0) + { + bits >>= 8; + bit |= 8; + } + if ((bits & 0xF0) != 0) + { + bits >>= 4; + bit |= 4; + } + if ((bits & 0xC) != 0) + { + bits >>= 2; + bit |= 2; + } + if ((bits & 0x2) != 0) + { + bit |= 1; + } + return bit; + } + public static int NormalizeSizeToPowerOfTwo(int minSize) + { + unchecked + { + return 1 << (GetHighBitNumber((uint)minSize - 1u) + 1); + } + } + public static int NormalizeSizeToPowerOfTwo_ClampOverflow(int minSize) + { + unchecked + { + int hibit = (GetHighBitNumber((uint)minSize - 1u) + 1); + if (hibit >= 32) + { + return int.MaxValue; + } + return 1 << hibit; + } + } + public static void Fill(T[] array, T value, int startIndex = 0, int length = -1) + { + if (length < 0) + { + length = array.Length; + } + else + { + length = startIndex + length; + } + for (int i = startIndex; i < length; i++) + { + array[i] = value; + } + } + } } \ No newline at end of file diff --git a/src/Internal/Editor/EcsGUI.Layout.cs b/src/Internal/Editor/EcsGUI.Layout.cs new file mode 100644 index 0000000..1bfa5b9 --- /dev/null +++ b/src/Internal/Editor/EcsGUI.Layout.cs @@ -0,0 +1,492 @@ +#if UNITY_EDITOR +using DCFApixels.DragonECS.Unity.Internal; +using System; +using System.Collections.Generic; +using System.Reflection; +using Unity.Collections.LowLevel.Unsafe; +using UnityEditor; +using UnityEngine; +using Color = UnityEngine.Color; +using UnityComponent = UnityEngine.Component; +using UnityObject = UnityEngine.Object; + +namespace DCFApixels.DragonECS.Unity.Editors +{ + internal static partial class EcsGUI + { + public static partial class Layout + { + public static void ScriptAssetButton(MonoScript script, params GUILayoutOption[] options) + { + EcsGUI.ScriptAssetButton(GUILayoutUtility.GetRect(UnityEditorUtility.GetLabelTemp(), EditorStyles.miniButton, options), script); + } + + + public static void CopyMetaIDButton(string metaID, params GUILayoutOption[] options) + { + Rect r = GUILayoutUtility.GetRect(UnityEditorUtility.GetLabelTemp(), EditorStyles.miniButton, options); + var current = Event.current; + var hover = IconHoverScan(r, current); + using (new ColorScope(new Color(1f, 1f, 1f, hover ? 1f : 0.8f))) + { + DrawIcon(r, Icons.Instance.MetaIDIcon, hover ? 1f : 2f, metaID); + if (hover && current.type == EventType.MouseUp) + { + GUIUtility.systemCopyBuffer = metaID; + } + } + } + public static bool IconButton(Texture icon, params GUILayoutOption[] options) + { + bool result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), options); + DrawIcon(GUILayoutUtility.GetLastRect(), icon, 0, null); + return result; + } + public static bool IconButton(Texture icon, float iconPadding = 0, string description = null) + { + bool result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty)); + DrawIcon(GUILayoutUtility.GetLastRect(), icon, iconPadding, description); + return result; + } + public static bool IconButton(Texture icon, float iconPadding = 0, string description = null, GUIStyle style = null, params GUILayoutOption[] options) + { + bool result; + if (style == null) + { + result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), options); + } + else + { + result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), style, options); + } + DrawIcon(GUILayoutUtility.GetLastRect(), icon, iconPadding, description); + return result; + } + + public static void DrawEmptyComponentProperty(SerializedProperty property, string name, bool isDisplayEmpty) + { + EcsGUI.DrawEmptyComponentProperty(GUILayoutUtility.GetRect(UnityEditorUtility.GetLabel(name), EditorStyles.label), property, name, isDisplayEmpty); + } + public static void DrawEmptyComponentProperty(SerializedProperty property, GUIContent label, bool isDisplayEmpty) + { + EcsGUI.DrawEmptyComponentProperty(GUILayoutUtility.GetRect(label, EditorStyles.label), property, label, isDisplayEmpty); + } + public static void DrawWorldBaseInfo(EcsWorld world) + { + bool isNull = world == null || world.IsDestroyed || world.ID == 0; + int entitesCount = isNull ? 0 : world.Count; + int capacity = isNull ? 0 : world.Capacity; + long Version = isNull ? 0 : world.Version; + int leakedEntitesCount = isNull ? 0 : world.CountLeakedEntitesDebug(); + EditorGUILayout.IntField("Entities", entitesCount, EditorStyles.boldLabel); + EditorGUILayout.IntField("Capacity", capacity, EditorStyles.boldLabel); + EditorGUILayout.LongField("Version", Version, EditorStyles.boldLabel); + Color color = leakedEntitesCount > 0 ? Color.yellow : GUI.contentColor; + using (new ContentColorScope(color)) + { + EditorGUILayout.IntField("Leaked Entites", leakedEntitesCount, EditorStyles.boldLabel); + } + } + public static void DrawWorldComponents(EcsWorld world) + { + bool isNull = world == null || world.IsDestroyed || world.ID == 0; + if (isNull) { return; } + using (BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f))) + { + IsShowRuntimeComponents = EditorGUILayout.BeginFoldoutHeaderGroup(IsShowRuntimeComponents, "RUNTIME COMPONENTS", EditorStyles.foldout); + EditorGUILayout.EndFoldoutHeaderGroup(); + if (IsShowRuntimeComponents == false) { return; } + + var worldID = world.ID; + var cmps = world.GetWorldComponents(); + int index = -1; + int total = 9; + foreach (var cmp in cmps) + { + index++; + var meta = cmp.ComponentType.ToMeta(); + if (meta.IsHidden == false || IsShowHidden) + { + Type componentType = cmp.ComponentType; + + object data = cmp.GetRaw(worldID); + + ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType); + + float padding = EditorGUIUtility.standardVerticalSpacing; + Rect optionButton = GUILayoutUtility.GetLastRect(); + optionButton.yMin = optionButton.yMax; + optionButton.yMax += HeadIconsRect.height; + optionButton.xMin = optionButton.xMax - 64; + optionButton.center += Vector2.up * padding * 2f; + //Canceling isExpanded + if (ClickTest(optionButton)) + { + ref bool isExpanded = ref expandMatrix.Down(); + isExpanded = !isExpanded; + } + + Color panelColor = SelectPanelColor(meta, index, total); + GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA)); + EditorGUI.BeginChangeCheck(); + + ////Close button + //optionButton.xMin = optionButton.xMax - HeadIconsRect.width; + //if (CloseButton(optionButton)) + //{ + // cmp.Del(worldID); + // return; + //} + + //Edit script button + if (ScriptsCache.TryGetScriptAsset(meta, out MonoScript script)) + { + optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); + EcsGUI.ScriptAssetButton(optionButton, script); + } + //Description icon + if (string.IsNullOrEmpty(meta.Description.Text) == false) + { + optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); + DescriptionIcon(optionButton, meta.Description.Text); + } + + RuntimeComponentReflectionCache.FieldInfoData componentInfoData = new RuntimeComponentReflectionCache.FieldInfoData(null, componentType, meta.Name); + if (DrawRuntimeData(ref componentInfoData, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData)) + { + cmp.SetRaw(worldID, resultData); + } + + GUILayout.EndVertical(); + } + } + } + } + + #region entity bar + public static void EntityBarForAlive(EntityStatus status, int id, short gen, short world) + { + float width = EditorGUIUtility.currentViewWidth; + float height = EntityBarHeight; + EcsGUI.EntityBarForAlive(GUILayoutUtility.GetRect(width, height), status, id, gen, world); + } + public static void EntityBar(EntityStatus status, bool isPlaceholder, int id, short gen, short world) + { + float width = EditorGUIUtility.currentViewWidth; + float height = EntityBarHeight; + EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height), isPlaceholder, status, id, gen, world); + } + public static void EntityBar(int id, short gen, short world) + { + float width = EditorGUIUtility.currentViewWidth; + float height = EntityBarHeight; + EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height), id, gen, world); + } + public static void EntityBar() + { + float width = EditorGUIUtility.currentViewWidth; + float height = EntityBarHeight; + EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height)); + } + #endregion + + public static bool AddComponentButtons(out Rect dropDownRect) + { + return EcsGUI.AddComponentButton(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); + } + public static AddClearButton AddClearComponentButtons(out Rect dropDownRect) + { + return EcsGUI.AddClearComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); + } + public static AddClearButton AddClearSystemButtons(out Rect dropDownRect) + { + return EcsGUI.AddClearSystemButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); + } + public static void DrawRuntimeComponents(entlong entity, bool isWithFoldout = true) + { + if (entity.TryUnpackForUnityEditor(out int entityID, out _, out _, out EcsWorld world)) + { + DrawRuntimeComponents(entityID, world, isWithFoldout); + } + } + + [ThreadStatic] + private static List _componentPoolsBuffer; + public static void DrawRuntimeComponents(int entityID, EcsWorld world, bool isWithFoldout = true) + { + using (BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f))) + { + if (isWithFoldout) + { + IsShowRuntimeComponents = EditorGUILayout.BeginFoldoutHeaderGroup(IsShowRuntimeComponents, "RUNTIME COMPONENTS", EditorStyles.foldout); + EditorGUILayout.EndFoldoutHeaderGroup(); + } + if (isWithFoldout == false || IsShowRuntimeComponents) + { + if (AddComponentButtons(out Rect dropDownRect)) + { + RuntimeComponentsUtility.GetAddComponentGenericMenu(world).Open(dropDownRect, entityID); + } + + GUILayout.Box("", UnityEditorUtility.GetStyle(GUI.color, 0.16f), GUILayout.ExpandWidth(true)); + IsShowHidden = EditorGUI.Toggle(GUILayoutUtility.GetLastRect(), "Show Hidden", IsShowHidden); + + if (_componentPoolsBuffer == null) + { + _componentPoolsBuffer = new List(64); + } + world.GetComponentPoolsFor(entityID, _componentPoolsBuffer); + int i = 0; + //int iMax = _componentPoolsBuffer.Count; + foreach (var componentPool in _componentPoolsBuffer) + { + DrawRuntimeComponent(entityID, componentPool, 9, i++); + } + } + } + } + private static void DrawRuntimeComponent(int entityID, IEcsPool pool, int total, int index) + { + var meta = pool.ComponentType.ToMeta(); + if (meta.IsHidden == false || IsShowHidden) + { + Type componentType = pool.ComponentType; + + object data = pool.GetRaw(entityID); + + ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType); + + float padding = EditorGUIUtility.standardVerticalSpacing; + Rect optionButton = GUILayoutUtility.GetLastRect(); + optionButton.yMin = optionButton.yMax; + optionButton.yMax += HeadIconsRect.height; + optionButton.xMin = optionButton.xMax - 64; + optionButton.center += Vector2.up * padding * 2f; + //Canceling isExpanded + if (ClickTest(optionButton)) + { + ref bool isExpanded = ref expandMatrix.Down(); + isExpanded = !isExpanded; + } + + Color panelColor = SelectPanelColor(meta, index, total); + GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA)); + EditorGUI.BeginChangeCheck(); + + //Close button + optionButton.xMin = optionButton.xMax - HeadIconsRect.width; + if (CloseButton(optionButton)) + { + pool.Del(entityID); + return; + } + //Edit script button + if (ScriptsCache.TryGetScriptAsset(meta, out MonoScript script)) + { + optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); + EcsGUI.ScriptAssetButton(optionButton, script); + } + //Description icon + if (string.IsNullOrEmpty(meta.Description.Text) == false) + { + optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); + DescriptionIcon(optionButton, meta.Description.Text); + } + + RuntimeComponentReflectionCache.FieldInfoData componentInfoData = new RuntimeComponentReflectionCache.FieldInfoData(null, componentType, meta.Name); + + if (DrawRuntimeData(ref componentInfoData, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData)) + { + pool.SetRaw(entityID, resultData); + } + + + GUILayout.EndVertical(); + } + } + + #region Default DrawRuntimeData + [InitializeOnLoadMethod] + private static void ResetRuntimeComponentReflectionCache() + { + _runtimeComponentReflectionCaches.Clear(); + } + internal class RuntimeComponentReflectionCache + { + public readonly Type Type; + + public readonly bool IsUnityObjectType; + public readonly bool IsUnitySerializable; + public readonly bool IsUnmanaged; + + public readonly FieldInfoData[] Fields; + + public readonly RefEditorWrapper Wrapper; + + public RuntimeComponentReflectionCache(Type type) + { + Type = type; + + IsUnmanaged = UnsafeUtility.IsUnmanaged(type); + IsUnityObjectType = typeof(UnityObject).IsAssignableFrom(type); + IsUnitySerializable = IsUnityObjectType || (!type.IsGenericType && type.IsSerializable); + + Wrapper = RefEditorWrapper.Take(); + + if (type == typeof(void)) { return; } + + if (IsUnitySerializable == false) + { + var fs = type.GetFields(fieldFlags); + Fields = new FieldInfoData[fs.Length]; + for (int i = 0; i < fs.Length; i++) + { + var f = fs[i]; + Fields[i] = new FieldInfoData(f); + } + } + } + public readonly struct FieldInfoData + { + public readonly FieldInfo FieldInfo; + public readonly Type FieldType; + public readonly string UnityFormatName; + public readonly bool IsUnityObjectField; + public FieldInfoData(FieldInfo fieldInfo) + { + FieldInfo = fieldInfo; + FieldType = fieldInfo.FieldType; + IsUnityObjectField = typeof(UnityObject).IsAssignableFrom(fieldInfo.FieldType); + UnityFormatName = UnityEditorUtility.TransformFieldName(fieldInfo.Name); + } + public FieldInfoData(FieldInfo fieldInfo, Type fieldType, string unityFormatName) + { + FieldInfo = fieldInfo; + FieldType = fieldType; + UnityFormatName = unityFormatName; + IsUnityObjectField = typeof(UnityObject).IsAssignableFrom(fieldType); + } + } + } + private static Dictionary _runtimeComponentReflectionCaches = new Dictionary(); + private static RuntimeComponentReflectionCache GetRuntimeComponentReflectionCache(Type type) + { + if (_runtimeComponentReflectionCaches.TryGetValue(type, out RuntimeComponentReflectionCache result) == false) + { + result = new RuntimeComponentReflectionCache(type); + _runtimeComponentReflectionCaches.Add(type, result); + } + return result; + } + private static bool DrawRuntimeData(ref RuntimeComponentReflectionCache.FieldInfoData fieldInfoData, GUIContent label, ExpandMatrix expandMatrix, object data, out object outData) + { + outData = data; + Type type = data == null ? typeof(void) : data.GetType(); + + RuntimeComponentReflectionCache cache = GetRuntimeComponentReflectionCache(type); + + bool isUnityObjectField = fieldInfoData.IsUnityObjectField; + if (isUnityObjectField == false && data == null) + { + EditorGUILayout.TextField(label, "Null"); + return false; + } + bool isUnityObjectType = cache.IsUnityObjectType; + + ref bool isExpanded = ref expandMatrix.Down(); + bool changed = false; + + + if (cache.IsUnitySerializable == false) + { + isExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(isExpanded, label, EditorStyles.foldout); + EditorGUILayout.EndFoldoutHeaderGroup(); + + if (isExpanded) + { + using (UpIndentLevel()) + { + for (int j = 0, jMax = cache.Fields.Length; j < jMax; j++) + { + var field = cache.Fields[j]; + if (DrawRuntimeData(ref field, UnityEditorUtility.GetLabel(field.UnityFormatName), expandMatrix, field.FieldInfo.GetValue(data), out object fieldData)) + { + field.FieldInfo.SetValue(data, fieldData); + outData = data; + changed = true; + } + } + } + } + } + else + { + Type fieldType = fieldInfoData.FieldType; + if (isUnityObjectType || isUnityObjectField) + { + EditorGUI.BeginChangeCheck(); + var uobj = UnsafeUtility.As(ref data); + + bool isComponent = typeof(UnityComponent).IsAssignableFrom(fieldType); + if (isComponent) + { + uobj = EditorGUILayout.ObjectField(label, uobj, typeof(UnityObject), true); + } + else + { + uobj = EditorGUILayout.ObjectField(label, uobj, fieldType, true); + } + + if (EditorGUI.EndChangeCheck()) + { + if (isComponent && uobj is GameObject go) + { + uobj = go.GetComponent(fieldType); + } + + outData = uobj; + changed = true; + } + } + else + { + EditorGUI.BeginChangeCheck(); + //WrapperBase wrapper = RefEditorWrapper.Take(data); + + RefEditorWrapper wrapper = cache.Wrapper; + + wrapper.data = data; + wrapper.SO.Update(); + + wrapper.IsExpanded = isExpanded; + try + { + EditorGUILayout.PropertyField(wrapper.Property, label, true); + } + catch (ArgumentException) + { + if (Event.current.type != EventType.Repaint) + { + throw; + } + } + + if (EditorGUI.EndChangeCheck()) + { + isExpanded = wrapper.IsExpanded; + wrapper.SO.ApplyModifiedProperties(); + outData = wrapper.Data; + changed = true; + } + //wrapper.Release(); + } + } + + expandMatrix.Up(); + return changed; + } + #endregion + } + } +} +#endif \ No newline at end of file diff --git a/src/Internal/Editor/EcsGUI.Layout.cs.meta b/src/Internal/Editor/EcsGUI.Layout.cs.meta new file mode 100644 index 0000000..f0151db --- /dev/null +++ b/src/Internal/Editor/EcsGUI.Layout.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f7a7468927b696e4899e73de0866d947 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Internal/Editor/EcsGUI.cs b/src/Internal/Editor/EcsGUI.cs index 39f84c2..0837fd5 100644 --- a/src/Internal/Editor/EcsGUI.cs +++ b/src/Internal/Editor/EcsGUI.cs @@ -2,27 +2,25 @@ using DCFApixels.DragonECS.Unity.Internal; using System; using System.Collections.Generic; - -//using System.Drawing; using System.Reflection; -using Unity.Collections.LowLevel.Unsafe; using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEngine; using Color = UnityEngine.Color; -using UnityComponent = UnityEngine.Component; -using UnityObject = UnityEngine.Object; namespace DCFApixels.DragonECS.Unity.Editors { - internal static class EcsGUI + internal static partial class EcsGUI { #region Scores private static int _changedCounter = 0; private static bool _changed = false; private static bool _delayedChanged = false; - public static int ChangedCounter => _changedCounter; + public static int ChangedCounter + { + get { return _changedCounter; } + } public static bool Changed { get @@ -273,6 +271,7 @@ namespace DCFApixels.DragonECS.Unity.Editors public static float EntityBarHeight => EditorGUIUtility.singleLineHeight + 3f; private static float indent => (float)EditorGUI.indentLevel * 15f; + private static float indentLevel => EditorGUI.indentLevel; #region Properties private static ComponentColorMode AutoColorMode @@ -290,6 +289,11 @@ namespace DCFApixels.DragonECS.Unity.Editors get { return UserSettingsPrefs.instance.IsShowRuntimeComponents; } set { UserSettingsPrefs.instance.IsShowRuntimeComponents = value; } } + //private static bool IsFastModeRuntimeComponents + //{ + // get { return UserSettingsPrefs.instance.IsFastModeRuntimeComponents; } + // set { UserSettingsPrefs.instance.IsFastModeRuntimeComponents = value; } + //} private static float OneLineHeight { get => EditorGUIUtility.singleLineHeight; @@ -453,18 +457,6 @@ namespace DCFApixels.DragonECS.Unity.Editors } #endregion - //#region One line elems - //public static bool LeftToggle(Rect position, GUIContent label, bool value) - //{ - // position = position.AddPadding(indent, 0, 0, 0); - // Rect togglePos; - // (togglePos, position) = position.HorizontalSliceLeft(18f); - // - // EditorGUI.togg(position, label); - // GUI.Label(position, label); - //} - //#endregion - #region entity bar public static void EntityBarForAlive(Rect position, EntityStatus status, int id, short gen, short world) { @@ -1019,405 +1011,8 @@ namespace DCFApixels.DragonECS.Unity.Editors _currentProperty = property; GetReferenceDropDown(sortedPredicateTypes, sortedWithOutTypes).Show(position); } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - - public static partial class Layout - { - public static void ScriptAssetButton(MonoScript script, params GUILayoutOption[] options) - { - EcsGUI.ScriptAssetButton(GUILayoutUtility.GetRect(UnityEditorUtility.GetLabelTemp(), EditorStyles.miniButton, options), script); - } - - - public static void CopyMetaIDButton(string metaID, params GUILayoutOption[] options) - { - Rect r = GUILayoutUtility.GetRect(UnityEditorUtility.GetLabelTemp(), EditorStyles.miniButton, options); - var current = Event.current; - var hover = IconHoverScan(r, current); - using (new ColorScope(new Color(1f, 1f, 1f, hover ? 1f : 0.8f))) - { - DrawIcon(r, Icons.Instance.MetaIDIcon, hover ? 1f : 2f, metaID); - if (hover && current.type == EventType.MouseUp) - { - GUIUtility.systemCopyBuffer = metaID; - } - } - } - public static bool IconButton(Texture icon, params GUILayoutOption[] options) - { - bool result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), options); - DrawIcon(GUILayoutUtility.GetLastRect(), icon, 0, null); - return result; - } - public static bool IconButton(Texture icon, float iconPadding = 0, string description = null) - { - bool result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty)); - DrawIcon(GUILayoutUtility.GetLastRect(), icon, iconPadding, description); - return result; - } - public static bool IconButton(Texture icon, float iconPadding = 0, string description = null, GUIStyle style = null, params GUILayoutOption[] options) - { - bool result; - if (style == null) - { - result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), options); - } - else - { - result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), style, options); - } - DrawIcon(GUILayoutUtility.GetLastRect(), icon, iconPadding, description); - return result; - } - - public static void DrawEmptyComponentProperty(SerializedProperty property, string name, bool isDisplayEmpty) - { - EcsGUI.DrawEmptyComponentProperty(GUILayoutUtility.GetRect(UnityEditorUtility.GetLabel(name), EditorStyles.label), property, name, isDisplayEmpty); - } - public static void DrawEmptyComponentProperty(SerializedProperty property, GUIContent label, bool isDisplayEmpty) - { - EcsGUI.DrawEmptyComponentProperty(GUILayoutUtility.GetRect(label, EditorStyles.label), property, label, isDisplayEmpty); - } - public static void DrawWorldBaseInfo(EcsWorld world) - { - bool isNull = world == null || world.IsDestroyed || world.ID == 0; - int entitesCount = isNull ? 0 : world.Count; - int capacity = isNull ? 0 : world.Capacity; - int leakedEntitesCount = isNull ? 0 : world.CountLeakedEntitesDebug(); - EditorGUILayout.IntField("Entities", entitesCount, EditorStyles.boldLabel); - EditorGUILayout.IntField("Capacity", capacity, EditorStyles.boldLabel); - EditorGUILayout.LongField("Version", world.Version, EditorStyles.boldLabel); - Color color = leakedEntitesCount > 0 ? Color.yellow : GUI.contentColor; - using (new ContentColorScope(color)) - { - EditorGUILayout.IntField("Leaked Entites", leakedEntitesCount, EditorStyles.boldLabel); - } - } - - #region entity bar - public static void EntityBarForAlive(EntityStatus status, int id, short gen, short world) - { - float width = EditorGUIUtility.currentViewWidth; - float height = EntityBarHeight; - EcsGUI.EntityBarForAlive(GUILayoutUtility.GetRect(width, height), status, id, gen, world); - } - public static void EntityBar(EntityStatus status, bool isPlaceholder, int id, short gen, short world) - { - float width = EditorGUIUtility.currentViewWidth; - float height = EntityBarHeight; - EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height), isPlaceholder, status, id, gen, world); - } - public static void EntityBar(int id, short gen, short world) - { - float width = EditorGUIUtility.currentViewWidth; - float height = EntityBarHeight; - EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height), id, gen, world); - } - public static void EntityBar() - { - float width = EditorGUIUtility.currentViewWidth; - float height = EntityBarHeight; - EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height)); - } - #endregion - - public static bool AddComponentButtons(out Rect dropDownRect) - { - return EcsGUI.AddComponentButton(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); - } - public static AddClearButton AddClearComponentButtons(out Rect dropDownRect) - { - return EcsGUI.AddClearComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); - } - public static AddClearButton AddClearSystemButtons(out Rect dropDownRect) - { - return EcsGUI.AddClearSystemButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); - } - public static void DrawRuntimeComponents(entlong entity, bool isWithFoldout = true) - { - if (entity.TryUnpackForUnityEditor(out int entityID, out _, out _, out EcsWorld world)) - { - DrawRuntimeComponents(entityID, world, isWithFoldout); - } - } - - [ThreadStatic] - private static List _componentPoolsBuffer; - public static void DrawRuntimeComponents(int entityID, EcsWorld world, bool isWithFoldout = true) - { - using (BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f))) - { - if (isWithFoldout) - { - IsShowRuntimeComponents = EditorGUILayout.BeginFoldoutHeaderGroup(IsShowRuntimeComponents, "RUNTIME COMPONENTS", EditorStyles.foldout); - EditorGUILayout.EndFoldoutHeaderGroup(); - } - if (isWithFoldout == false || IsShowRuntimeComponents) - { - if (AddComponentButtons(out Rect dropDownRect)) - { - RuntimeComponentsUtility.GetAddComponentGenericMenu(world).Open(dropDownRect, entityID); - } - - GUILayout.Box("", UnityEditorUtility.GetStyle(GUI.color, 0.16f), GUILayout.ExpandWidth(true)); - IsShowHidden = EditorGUI.Toggle(GUILayoutUtility.GetLastRect(), "Show Hidden", IsShowHidden); - - if (_componentPoolsBuffer == null) - { - _componentPoolsBuffer = new List(64); - } - world.GetComponentPoolsFor(entityID, _componentPoolsBuffer); - int i = 0; - //int iMax = _componentPoolsBuffer.Count; - foreach (var componentPool in _componentPoolsBuffer) - { - DrawRuntimeComponent(entityID, componentPool, 9, i++); - } - } - } - } - private static void DrawRuntimeComponent(int entityID, IEcsPool pool, int total, int index) - { - var meta = pool.ComponentType.ToMeta(); - if (meta.IsHidden == false || IsShowHidden) - { - Type componentType = pool.ComponentType; - - object data = pool.GetRaw(entityID); - - ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType); - - float padding = EditorGUIUtility.standardVerticalSpacing; - Rect optionButton = GUILayoutUtility.GetLastRect(); - optionButton.yMin = optionButton.yMax; - optionButton.yMax += HeadIconsRect.height; - optionButton.xMin = optionButton.xMax - 64; - optionButton.center += Vector2.up * padding * 2f; - //Canceling isExpanded - if (ClickTest(optionButton)) - { - ref bool isExpanded = ref expandMatrix.Down(); - isExpanded = !isExpanded; - } - - Color panelColor = SelectPanelColor(meta, index, total); - GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA)); - EditorGUI.BeginChangeCheck(); - - //Close button - optionButton.xMin = optionButton.xMax - HeadIconsRect.width; - if (CloseButton(optionButton)) - { - pool.Del(entityID); - return; - } - //Edit script button - if (ScriptsCache.TryGetScriptAsset(meta, out MonoScript script)) - { - optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); - EcsGUI.ScriptAssetButton(optionButton, script); - } - //Description icon - if (string.IsNullOrEmpty(meta.Description.Text) == false) - { - optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); - DescriptionIcon(optionButton, meta.Description.Text); - } - - RuntimeComponentReflectionCache.FieldInfoData componentInfoData = new RuntimeComponentReflectionCache.FieldInfoData(null, componentType, meta.Name); - if (DrawRuntimeData(ref componentInfoData, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData)) - { - pool.SetRaw(entityID, resultData); - } - - GUILayout.EndVertical(); - } - } - [InitializeOnLoadMethod] - private static void ResetRuntimeComponentReflectionCache() - { - _runtimeComponentReflectionCaches.Clear(); - } - private class RuntimeComponentReflectionCache - { - public readonly Type Type; - - public readonly bool IsUnityObjectType; - public readonly bool IsUnitySerializable; - public readonly bool IsUnmanaged; - - public readonly FieldInfoData[] Fields; - - public readonly RefEditorWrapper Wrapper; - - public RuntimeComponentReflectionCache(Type type) - { - Type = type; - - IsUnmanaged = UnsafeUtility.IsUnmanaged(type); - IsUnityObjectType = typeof(UnityObject).IsAssignableFrom(type); - IsUnitySerializable = IsUnityObjectType || (!type.IsGenericType && type.IsSerializable); - - Wrapper = RefEditorWrapper.Take(); - - if (type == typeof(void)) { return; } - - if (IsUnitySerializable == false) - { - var fs = type.GetFields(fieldFlags); - Fields = new FieldInfoData[fs.Length]; - for (int i = 0; i < fs.Length; i++) - { - var f = fs[i]; - Fields[i] = new FieldInfoData(f); - } - } - } - public readonly struct FieldInfoData - { - public readonly FieldInfo FieldInfo; - public readonly Type FieldType; - public readonly string UnityFormatName; - public readonly bool IsUnityObjectField; - public FieldInfoData(FieldInfo fieldInfo) - { - FieldInfo = fieldInfo; - FieldType = fieldInfo.FieldType; - IsUnityObjectField = typeof(UnityObject).IsAssignableFrom(fieldInfo.FieldType); - UnityFormatName = UnityEditorUtility.TransformFieldName(fieldInfo.Name); - } - public FieldInfoData(FieldInfo fieldInfo, Type fieldType, string unityFormatName) - { - FieldInfo = fieldInfo; - FieldType = fieldType; - UnityFormatName = unityFormatName; - IsUnityObjectField = typeof(UnityObject).IsAssignableFrom(fieldType); - } - } - } - private static Dictionary _runtimeComponentReflectionCaches = new Dictionary(); - private static RuntimeComponentReflectionCache GetRuntimeComponentReflectionCache(Type type) - { - if (_runtimeComponentReflectionCaches.TryGetValue(type, out RuntimeComponentReflectionCache result) == false) - { - result = new RuntimeComponentReflectionCache(type); - _runtimeComponentReflectionCaches.Add(type, result); - } - return result; - } - private static bool DrawRuntimeData(ref RuntimeComponentReflectionCache.FieldInfoData fieldInfoData, GUIContent label, ExpandMatrix expandMatrix, object data, out object outData) - { - outData = data; - Type type = data == null ? typeof(void) : data.GetType(); - - RuntimeComponentReflectionCache cache = GetRuntimeComponentReflectionCache(type); - - bool isUnityObjectField = fieldInfoData.IsUnityObjectField; - if (isUnityObjectField == false && data == null) - { - EditorGUILayout.TextField(label, "Null"); - return false; - } - bool isUnityObjectType = cache.IsUnityObjectType; - - ref bool isExpanded = ref expandMatrix.Down(); - bool changed = false; - - - if (cache.IsUnitySerializable == false) - { - isExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(isExpanded, label, EditorStyles.foldout); - EditorGUILayout.EndFoldoutHeaderGroup(); - - if (isExpanded) - { - using (UpIndentLevel()) - { - for (int j = 0, jMax = cache.Fields.Length; j < jMax; j++) - { - var field = cache.Fields[j]; - if (DrawRuntimeData(ref field, UnityEditorUtility.GetLabel(field.UnityFormatName), expandMatrix, field.FieldInfo.GetValue(data), out object fieldData)) - { - field.FieldInfo.SetValue(data, fieldData); - outData = data; - changed = true; - } - } - } - } - } - else - { - Type fieldType = fieldInfoData.FieldType; - if (isUnityObjectType || isUnityObjectField) - { - EditorGUI.BeginChangeCheck(); - var uobj = UnsafeUtility.As(ref data); - - bool isComponent = typeof(UnityComponent).IsAssignableFrom(fieldType); - if (isComponent) - { - uobj = EditorGUILayout.ObjectField(label, uobj, typeof(UnityObject), true); - } - else - { - uobj = EditorGUILayout.ObjectField(label, uobj, fieldType, true); - } - - if (EditorGUI.EndChangeCheck()) - { - if (isComponent && uobj is GameObject go) - { - uobj = go.GetComponent(fieldType); - } - - outData = uobj; - changed = true; - } - } - else - { - EditorGUI.BeginChangeCheck(); - //WrapperBase wrapper = RefEditorWrapper.Take(data); - - RefEditorWrapper wrapper = cache.Wrapper; - - wrapper.data = data; - wrapper.SO.Update(); - - wrapper.IsExpanded = isExpanded; - try - { - EditorGUILayout.PropertyField(wrapper.Property, label, true); - } - catch (ArgumentException) - { - if (Event.current.type != EventType.Repaint) - { - throw; - } - } - - if (EditorGUI.EndChangeCheck()) - { - isExpanded = wrapper.IsExpanded; - wrapper.SO.ApplyModifiedProperties(); - outData = wrapper.Data; - changed = true; - } - //wrapper.Release(); - } - } - - expandMatrix.Up(); - return changed; - } - } +#endregion } } #endif \ No newline at end of file diff --git a/src/Internal/Editor/ExtendedEditor.cs b/src/Internal/Editor/ExtendedEditor.cs index 5648dc7..f9d4e6c 100644 --- a/src/Internal/Editor/ExtendedEditor.cs +++ b/src/Internal/Editor/ExtendedEditor.cs @@ -92,12 +92,35 @@ namespace DCFApixels.DragonECS.Unity.Editors { base.OnInspectorGUI(); } - - protected SerializedProperty FindProperty(string name) { return serializedObject.FindProperty(name); } + + + //Color proColor = (Color)new Color32(56, 56, 56, 255); + //Color plebColor = (Color)new Color32(194, 194, 194, 255); + //protected override void OnHeaderGUI() + //{ + // //base.OnHeaderGUI(); + // var rect = EditorGUILayout.GetControlRect(false, 0f); + // rect.height = EditorGUIUtility.singleLineHeight; + // rect.y -= rect.height; + // rect.x = 48; + // rect.xMax -= rect.x * 2f; + // + // //GUI.skin.settings + // EditorGUI.DrawRect(rect, EditorGUIUtility.isProSkin ? proColor : plebColor); + // + // //string header = (target as ComponentFolder).folderName; // <--- your variable + // string header = ""; + // if (string.IsNullOrEmpty(header)) + // { + // header = target.ToString() + 1; + // } + // + // EditorGUI.LabelField(rect, header, EditorStyles.boldLabel); + //} } internal abstract class ExtendedEditor : ExtendedEditor { diff --git a/src/Internal/Editor/UnityEditorUtility.cs b/src/Internal/Editor/UnityEditorUtility.cs index 4ec3289..7df6d82 100644 --- a/src/Internal/Editor/UnityEditorUtility.cs +++ b/src/Internal/Editor/UnityEditorUtility.cs @@ -103,12 +103,15 @@ namespace DCFApixels.DragonECS.Unity.Editors namespace DCFApixels.DragonECS.Unity.Editors { using UnityEditor; + using Assembly = System.Reflection.Assembly; [InitializeOnLoad] internal static partial class UnityEditorUtility { static UnityEditorUtility() { + _integrationAssembly = typeof(UnityEditorUtility).Assembly; + colorBoxeStyles = new SparseArray(); List serializableTypes = new List(); @@ -144,6 +147,7 @@ namespace DCFApixels.DragonECS.Unity.Editors //}).ToArray(); } + internal static readonly Assembly _integrationAssembly; internal static readonly Type[] _serializableTypes; internal static readonly TypeMeta[] _serializableTypeWithMetaIDMetas; private static readonly Dictionary _metaIDTypePairs = new Dictionary(); diff --git a/src/Internal/Utils/StructList.cs b/src/Internal/Utils/StructList.cs new file mode 100644 index 0000000..793319d --- /dev/null +++ b/src/Internal/Utils/StructList.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.CompilerServices; + +namespace DCFApixels.DragonECS.Unity.Internal +{ + [DebuggerDisplay("Count: {Count}")] + internal struct StructList + { + internal T[] _items; + internal int _count; + + public IEnumerable Enumerable + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _items.Take(_count); } + } + public bool IsNull + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _items == null; } + } + public bool IsNullOrEmpty + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _items == null || _items.Length <= 0; } + } + public int Count + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _count; } + } + public int Capacity + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _items.Length; } + set + { + if (value <= _items.Length) { return; } + value = ArrayUtility.NormalizeSizeToPowerOfTwo(value); + Array.Resize(ref _items, value); + } + } + public T this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { +#if DEBUG + if (index < 0 || index >= _count) { Throw.ArgumentOutOfRange(); } +#endif + return _items[index]; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set + { +#if DEBUG + if (index < 0 || index >= _count) { Throw.ArgumentOutOfRange(); } +#endif + _items[index] = value; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public StructList(int capacity) + { + _items = new T[ArrayUtility.NormalizeSizeToPowerOfTwo(capacity)]; + _count = 0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Add(T item) + { + if (_count >= _items.Length) + { + Array.Resize(ref _items, _items.Length << 1); + } + _items[_count++] = item; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int IndexOf(T item) + { + return Array.IndexOf(_items, item, 0, _count); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SwapAt(int idnex1, int idnex2) + { + T tmp = _items[idnex1]; + _items[idnex1] = _items[idnex2]; + _items[idnex2] = tmp; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FastRemoveAt(int index) + { +#if DEBUG + if (index < 0 || index >= _count) { Throw.ArgumentOutOfRange(); } +#endif + _items[index] = _items[--_count]; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RemoveAt(int index) + { +#if DEBUG + if (index < 0 || index >= _count) { Throw.ArgumentOutOfRange(); } +#endif + _items[index] = _items[--_count]; + _items[_count] = default; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void RemoveAtWithOrder(int index) + { +#if DEBUG + if (index < 0 || index >= _count) { Throw.ArgumentOutOfRange(); } +#endif + for (int i = index; i < _count;) + { + _items[i++] = _items[i]; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Remove(T item) + { + int index = IndexOf(item); + if (index >= 0) + { + RemoveAt(index); + return true; + } + return false; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool RemoveWithOrder(T item) + { + int index = IndexOf(item); + if (index >= 0) + { + RemoveAtWithOrder(index); + return true; + } + return false; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void FastClear() + { + _count = 0; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Clear() + { + for (int i = 0; i < _count; i++) + { + _items[i] = default; + } + _count = 0; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ReadOnlySpan.Enumerator GetEnumerator() + { + return new ReadOnlySpan(_items, 0, _count).GetEnumerator(); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ReadOnlySpan ToReadOnlySpan() + { + return new ReadOnlySpan(_items, 0, _count); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public IEnumerable ToEnumerable() + { + return _items.Take(_count); + } + + public T[] ToArray() + { + T[] result = new T[_count]; + Array.Copy(_items, result, _count); + return _items; + } + } +} \ No newline at end of file diff --git a/src/Internal/Utils/StructList.cs.meta b/src/Internal/Utils/StructList.cs.meta new file mode 100644 index 0000000..1aeea41 --- /dev/null +++ b/src/Internal/Utils/StructList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 366ced1c4c1442c4db00c5a2b8c5787d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Internal/Utils/Throw.cs b/src/Internal/Utils/Throw.cs new file mode 100644 index 0000000..03aa65d --- /dev/null +++ b/src/Internal/Utils/Throw.cs @@ -0,0 +1,12 @@ +using System; + +namespace DCFApixels.DragonECS.Unity.Internal +{ + internal static class Throw + { + internal static void ArgumentOutOfRange() + { + throw new ArgumentOutOfRangeException(); + } + } +} diff --git a/src/Internal/Utils/Throw.cs.meta b/src/Internal/Utils/Throw.cs.meta new file mode 100644 index 0000000..4b32348 --- /dev/null +++ b/src/Internal/Utils/Throw.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 525c4a5bc83fb3343b3b93a02d3caf59 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Templates/EntityTemplate/Editor/EntityTemplateEditor.cs b/src/Templates/EntityTemplate/Editor/EntityTemplateEditor.cs index 24f4085..96e2f52 100644 --- a/src/Templates/EntityTemplate/Editor/EntityTemplateEditor.cs +++ b/src/Templates/EntityTemplate/Editor/EntityTemplateEditor.cs @@ -1,7 +1,9 @@ #if UNITY_EDITOR using DCFApixels.DragonECS.Unity.Internal; using DCFApixels.DragonECS.Unity.RefRepairer.Editors; +using System; using UnityEditor; +using UnityEditor.Graphs; using UnityEditorInternal; using UnityEngine;