diff --git a/src/EcsGroup.cs b/src/EcsGroup.cs index 40dacf8..7542435 100644 --- a/src/EcsGroup.cs +++ b/src/EcsGroup.cs @@ -9,6 +9,7 @@ using System.Runtime.InteropServices; namespace DCFApixels.DragonECS { + //_dense заполняется с индекса 1 [StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)] [DebuggerTypeProxy(typeof(DebuggerProxy))] public readonly ref struct EcsReadonlyGroup @@ -185,11 +186,13 @@ namespace DCFApixels.DragonECS #endregion #region Add/Remove - public void UncheckedAdd(int entityID) => AddInternal(entityID); - public void Add(int entityID) + public void AddUnchecked(int entityID) => AddInternal(entityID); + public bool Add(int entityID) { - if (Has(entityID)) return; + if (Has(entityID)) + return false; AddInternal(entityID); + return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void AddInternal(int entityID) @@ -203,11 +206,13 @@ namespace DCFApixels.DragonECS _sparse[entityID] = _count; } - public void UncheckedRemove(int entityID) => RemoveInternal(entityID); - public void Remove(int entityID) + public void RemoveUnchecked(int entityID) => RemoveInternal(entityID); + public bool Remove(int entityID) { - if (!Has(entityID)) return; + if (!Has(entityID)) + return false; RemoveInternal(entityID); + return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void RemoveInternal(int entityID) @@ -289,6 +294,8 @@ namespace DCFApixels.DragonECS #endregion #region Set operations + + #region UnionWith /// as Union sets [MethodImpl(MethodImplOptions.AggressiveInlining)] public void UnionWith(EcsReadonlyGroup group) => UnionWith(group.GetGroupInternal()); @@ -302,7 +309,50 @@ namespace DCFApixels.DragonECS if (!Has(item)) AddInternal(item); } + public void UnionWithRange(int[] range) + { + foreach (var item in range) + { + if (!Has(item)) + AddInternal(item); + } + } + public void UnionWithRange(Span range) + { + foreach (var item in range) + { + if (!Has(item)) + AddInternal(item); + } + } + public void UnionWithRange(ReadOnlySpan range) + { + foreach (var item in range) + { + if (!Has(item)) + AddInternal(item); + } + } + public void UnionWithRange(T range) where T : IList + { + for (int i = 0; i < range.Count; i++) + { + int item = range[i]; + if (!Has(item)) + AddInternal(item); + } + } + public void UnionWithRange(IEnumerable otherRange) + { + foreach (var item in otherRange) + { + if (!Has(item)) + AddInternal(item); + } + } + #endregion + #region ExceptWith /// as Except sets [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExceptWith(EcsReadonlyGroup group) => ExceptWith(group.GetGroupInternal()); @@ -312,11 +362,63 @@ namespace DCFApixels.DragonECS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS if (_source != group.World) Throw.Group_ArgumentDifferentWorldsException(); #endif - foreach (var item in this) - if (group.Has(item)) - RemoveInternal(item); + if (group.Count > Count) + { + foreach (var item in this) + if (group.Has(item)) + RemoveInternal(item); + } + else + { + foreach (var item in group) + if (Has(item)) + RemoveInternal(item); + } } + public void ExceptWithRange(int[] range) + { + foreach (var item in range) + { + if (Has(item)) + RemoveInternal(item); + } + } + public void ExceptWithRange(Span range) + { + foreach (var item in range) + { + if (Has(item)) + RemoveInternal(item); + } + } + public void ExceptWithRange(ReadOnlySpan range) + { + foreach (var item in range) + { + if (Has(item)) + RemoveInternal(item); + } + } + public void ExceptWithRange(T range) where T : IList + { + for (int i = 0; i < range.Count; i++) + { + int item = range[i]; + if (Has(item)) + RemoveInternal(item); + } + } + public void ExceptWithRange(IEnumerable otherRange) + { + foreach (var item in otherRange) + { + if (!Has(item)) + AddInternal(item); + } + } + #endregion + #region IntersectWith /// as Intersect sets [MethodImpl(MethodImplOptions.AggressiveInlining)] public void IntersectWith(EcsReadonlyGroup group) => IntersectWith(group.GetGroupInternal()); @@ -330,7 +432,9 @@ namespace DCFApixels.DragonECS if (!group.Has(item)) RemoveInternal(item); } + #endregion + #region SymmetricExceptWith /// as Symmetric Except sets [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SymmetricExceptWith(EcsReadonlyGroup group) => SymmetricExceptWith(group.GetGroupInternal()); @@ -346,7 +450,9 @@ namespace DCFApixels.DragonECS else AddInternal(item); } + #endregion + #region Inverse public void Inverse() { foreach (var item in _source.Entities) @@ -355,7 +461,9 @@ namespace DCFApixels.DragonECS else AddInternal(item); } + #endregion + #region SetEquals [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool SetEquals(EcsReadonlyGroup group) => SetEquals(group.GetGroupInternal()); public bool SetEquals(EcsGroup group) @@ -370,7 +478,9 @@ namespace DCFApixels.DragonECS return false; return true; } + #endregion + #region Overlaps [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Overlaps(EcsReadonlyGroup group) => Overlaps(group.GetGroupInternal()); public bool Overlaps(EcsGroup group) @@ -383,7 +493,9 @@ namespace DCFApixels.DragonECS return true; return false; } + #endregion + #region IsSubsetOf [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsSubsetOf(EcsReadonlyGroup group) => Overlaps(group.GetGroupInternal()); public bool IsSubsetOf(EcsGroup group) @@ -398,7 +510,9 @@ namespace DCFApixels.DragonECS return false; return true; } + #endregion + #region IsSupersetOf [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsSupersetOf(EcsReadonlyGroup group) => Overlaps(group.GetGroupInternal()); public bool IsSupersetOf(EcsGroup group) @@ -415,6 +529,8 @@ namespace DCFApixels.DragonECS } #endregion + #endregion + #region Static Set operations /// as Intersect sets /// new group from pool @@ -560,24 +676,14 @@ namespace DCFApixels.DragonECS #endregion #region Object - public override string ToString() => $"group{{{string.Join(", ", _dense.Take(_count))}}}"; - //public override int GetHashCode() - //{ - // unchecked - // { - // uint hash = 0; - // foreach (var item in this) - // hash ^= ((uint)item * 314159u); //реализация от балды, так как не нужен, но фишка в том что хеш не учитывает порядок сущьностей, что явлется правильным поведением. - // return (int)hash; - // } - //} + public override string ToString() => $"group{{{string.Join(", ", _dense.Skip(1).Take(_count))}}}"; #endregion #region OtherMethods [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int First() => this[0]; + public int First() => _dense[1]; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Last() => this[_count - 1]; + public int Last() => _dense[_count]; #endregion #region OnWorldResize