2025-03-14 16:53:25 +08:00
|
|
|
|
#if DISABLE_DEBUG
|
|
|
|
|
|
#undef DEBUG
|
|
|
|
|
|
#endif
|
2026-03-16 21:52:45 +08:00
|
|
|
|
using DCFApixels.DragonECS.Core;
|
2025-05-18 10:52:24 +08:00
|
|
|
|
using DCFApixels.DragonECS.Core.Internal;
|
2025-05-09 19:38:28 +08:00
|
|
|
|
using DCFApixels.DragonECS.Core.Unchecked;
|
2024-01-05 23:49:29 +08:00
|
|
|
|
using System;
|
2024-08-31 14:51:13 +08:00
|
|
|
|
using System.Collections.Generic;
|
2023-12-24 15:40:19 +08:00
|
|
|
|
using System.ComponentModel;
|
2024-01-05 22:16:48 +08:00
|
|
|
|
using System.Diagnostics;
|
2023-12-24 15:40:19 +08:00
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
|
|
|
|
|
|
|
namespace DCFApixels.DragonECS
|
|
|
|
|
|
{
|
2024-04-28 19:43:10 +08:00
|
|
|
|
#if ENABLE_IL2CPP
|
|
|
|
|
|
using Unity.IL2CPP.CompilerServices;
|
2024-11-08 17:21:36 +08:00
|
|
|
|
[Il2CppSetOption(Option.NullChecks, false)]
|
2024-04-28 19:43:10 +08:00
|
|
|
|
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
|
|
|
|
|
#endif
|
2024-01-05 22:16:48 +08:00
|
|
|
|
[DebuggerTypeProxy(typeof(DebuggerProxy))]
|
2023-12-24 15:40:19 +08:00
|
|
|
|
public readonly ref struct EcsSpan
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly ReadOnlySpan<int> _values;
|
2024-04-16 12:46:09 +08:00
|
|
|
|
private readonly short _worldID;
|
2023-12-24 15:40:19 +08:00
|
|
|
|
|
|
|
|
|
|
#region Properties
|
2024-03-02 04:20:34 +08:00
|
|
|
|
public bool IsNull
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get { return _worldID == 0; }
|
|
|
|
|
|
}
|
2025-03-11 14:30:33 +08:00
|
|
|
|
public short WorldID
|
2023-12-31 13:07:53 +08:00
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-03-02 04:20:34 +08:00
|
|
|
|
get { return _worldID; }
|
2023-12-31 13:07:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
public EcsWorld World
|
|
|
|
|
|
{
|
2024-03-02 04:20:34 +08:00
|
|
|
|
get { return EcsWorld.GetWorld(_worldID); }
|
2023-12-31 13:07:53 +08:00
|
|
|
|
}
|
2024-03-02 04:22:29 +08:00
|
|
|
|
public int Count
|
2023-12-31 13:07:53 +08:00
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-03-02 04:20:34 +08:00
|
|
|
|
get { return _values.Length; }
|
2023-12-31 13:07:53 +08:00
|
|
|
|
}
|
2024-03-02 06:07:50 +08:00
|
|
|
|
public EcsLongsSpan Longs
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get { return new EcsLongsSpan(this); }
|
|
|
|
|
|
}
|
2025-03-11 14:30:33 +08:00
|
|
|
|
public bool IsSourceEntities
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2026-03-17 10:28:04 +08:00
|
|
|
|
get { return _values == EcsWorld.GetWorld(_worldID).GetCurrentEntities_Internal()._values; }
|
2025-03-11 14:30:33 +08:00
|
|
|
|
}
|
2024-04-28 19:43:10 +08:00
|
|
|
|
#if ENABLE_IL2CPP
|
|
|
|
|
|
[Il2CppSetOption(Option.ArrayBoundsChecks, true)]
|
|
|
|
|
|
#endif
|
2024-01-08 13:39:38 +08:00
|
|
|
|
public int this[int index]
|
2023-12-24 15:40:19 +08:00
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-03-02 04:20:34 +08:00
|
|
|
|
get { return _values[index]; }
|
2024-01-07 19:32:16 +08:00
|
|
|
|
}
|
2023-12-24 15:40:19 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Constructors
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-04-16 12:46:09 +08:00
|
|
|
|
internal EcsSpan(short worldID, ReadOnlySpan<int> span)
|
2023-12-24 15:40:19 +08:00
|
|
|
|
{
|
|
|
|
|
|
_worldID = worldID;
|
|
|
|
|
|
_values = span;
|
|
|
|
|
|
}
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-04-16 12:46:09 +08:00
|
|
|
|
internal EcsSpan(short worldID, int[] array)
|
2023-12-24 15:40:19 +08:00
|
|
|
|
{
|
|
|
|
|
|
_worldID = worldID;
|
2024-03-02 04:20:34 +08:00
|
|
|
|
_values = new ReadOnlySpan<int>(array);
|
2023-12-24 15:40:19 +08:00
|
|
|
|
}
|
2024-04-16 12:46:09 +08:00
|
|
|
|
internal EcsSpan(short worldID, int[] array, int length)
|
2023-12-24 15:40:19 +08:00
|
|
|
|
{
|
|
|
|
|
|
_worldID = worldID;
|
|
|
|
|
|
_values = new ReadOnlySpan<int>(array, 0, length);
|
|
|
|
|
|
}
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-04-16 12:46:09 +08:00
|
|
|
|
internal EcsSpan(short worldID, int[] array, int start, int length)
|
2023-12-24 15:40:19 +08:00
|
|
|
|
{
|
|
|
|
|
|
_worldID = worldID;
|
|
|
|
|
|
_values = new ReadOnlySpan<int>(array, start, length);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-08-31 14:51:13 +08:00
|
|
|
|
#region Slice/ToArray
|
2024-03-02 06:07:50 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public EcsSpan Slice(int start) { return new EcsSpan(_worldID, _values.Slice(start)); }
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public EcsSpan Slice(int start, int length) { return new EcsSpan(_worldID, _values.Slice(start, length)); }
|
|
|
|
|
|
public int[] ToArray() { return _values.ToArray(); }
|
2024-08-31 14:51:13 +08:00
|
|
|
|
public int ToArray(ref int[] dynamicBuffer)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dynamicBuffer.Length < _values.Length)
|
|
|
|
|
|
{
|
2025-08-26 15:50:11 +08:00
|
|
|
|
Array.Resize(ref dynamicBuffer, ArrayUtility.CeilPow2(_values.Length));
|
2024-08-31 14:51:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
foreach (var e in this)
|
|
|
|
|
|
{
|
|
|
|
|
|
dynamicBuffer[i++] = e;
|
|
|
|
|
|
}
|
|
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
public void ToCollection(ICollection<int> collection)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var e in this)
|
|
|
|
|
|
{
|
|
|
|
|
|
collection.Add(e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-12-31 17:33:48 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2023-12-24 15:40:19 +08:00
|
|
|
|
#region operators
|
2026-03-17 10:28:04 +08:00
|
|
|
|
public static bool operator ==(EcsSpan left, EcsSpan right) { return left._values == right._values && left._worldID == right._worldID; }
|
|
|
|
|
|
public static bool operator !=(EcsSpan left, EcsSpan right) { return left._values != right._values || left._worldID != right._worldID; }
|
2023-12-24 15:40:19 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Enumerator
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-03-02 04:20:34 +08:00
|
|
|
|
public ReadOnlySpan<int>.Enumerator GetEnumerator() { return _values.GetEnumerator(); }
|
2023-12-24 15:40:19 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Other
|
2026-03-16 21:52:45 +08:00
|
|
|
|
public ReadOnlySpan<int> AsSystemSpan() { return _values; }
|
2023-12-24 15:40:19 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-03-02 06:07:50 +08:00
|
|
|
|
public int First() { return _values[0]; }
|
2023-12-24 15:40:19 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-03-02 06:07:50 +08:00
|
|
|
|
public int Last() { return _values[_values.Length - 1]; }
|
2024-03-02 04:20:34 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
|
{
|
|
|
|
|
|
return CollectionUtility.EntitiesToString(_values.ToArray(), "span");
|
|
|
|
|
|
}
|
2024-01-05 22:16:48 +08:00
|
|
|
|
#pragma warning disable CS0809 // Устаревший член переопределяет неустаревший член
|
|
|
|
|
|
[Obsolete("Equals() on EcsSpan will always throw an exception. Use the equality operator instead.")]
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
2024-03-02 04:20:34 +08:00
|
|
|
|
public override bool Equals(object obj) { throw new NotSupportedException(); }
|
2024-01-05 22:16:48 +08:00
|
|
|
|
[Obsolete("GetHashCode() on EcsSpan will always throw an exception.")]
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
2024-03-02 04:20:34 +08:00
|
|
|
|
public override int GetHashCode() { throw new NotSupportedException(); }
|
2024-01-05 22:16:48 +08:00
|
|
|
|
#pragma warning restore CS0809 // Устаревший член переопределяет неустаревший член
|
|
|
|
|
|
|
|
|
|
|
|
internal class DebuggerProxy
|
|
|
|
|
|
{
|
|
|
|
|
|
private int[] _values;
|
2024-04-16 12:46:09 +08:00
|
|
|
|
private short _worldID;
|
2024-03-02 04:20:34 +08:00
|
|
|
|
public EcsWorld World { get { return EcsWorld.GetWorld(_worldID); } }
|
2024-02-29 22:42:33 +08:00
|
|
|
|
public EntitySlotInfo[] Entities
|
2024-01-05 22:16:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
2024-02-29 22:42:33 +08:00
|
|
|
|
EntitySlotInfo[] result = new EntitySlotInfo[_values.Length];
|
2024-01-05 22:16:48 +08:00
|
|
|
|
int i = 0;
|
|
|
|
|
|
foreach (var e in _values)
|
2024-02-29 22:42:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
result[i++] = World.GetEntitySlotInfoDebug(e);
|
|
|
|
|
|
}
|
2024-01-05 22:16:48 +08:00
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-03-02 04:20:34 +08:00
|
|
|
|
public int Count { get { return _values.Length; } }
|
2024-01-05 22:16:48 +08:00
|
|
|
|
public DebuggerProxy(EcsSpan span)
|
|
|
|
|
|
{
|
2024-03-02 04:22:29 +08:00
|
|
|
|
_values = new int[span.Count];
|
2024-01-05 22:16:48 +08:00
|
|
|
|
span._values.CopyTo(_values);
|
|
|
|
|
|
_worldID = span._worldID;
|
|
|
|
|
|
}
|
2024-03-02 06:07:50 +08:00
|
|
|
|
public DebuggerProxy(EcsLongsSpan span) : this(span.ToSpan()) { }
|
2026-03-16 21:52:45 +08:00
|
|
|
|
public DebuggerProxy(EcsUnsafeSpan span) : this(span.ToSpan()) { }
|
2024-01-05 22:16:48 +08:00
|
|
|
|
}
|
2023-12-24 15:40:19 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
2024-03-02 06:07:50 +08:00
|
|
|
|
|
2024-04-28 19:43:10 +08:00
|
|
|
|
#if ENABLE_IL2CPP
|
2024-11-08 17:21:36 +08:00
|
|
|
|
[Il2CppSetOption(Option.NullChecks, false)]
|
2024-04-28 19:43:10 +08:00
|
|
|
|
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
|
|
|
|
|
#endif
|
2024-03-02 06:07:50 +08:00
|
|
|
|
[DebuggerTypeProxy(typeof(EcsSpan.DebuggerProxy))]
|
|
|
|
|
|
public readonly ref struct EcsLongsSpan
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly EcsSpan _source;
|
|
|
|
|
|
|
|
|
|
|
|
#region Properties
|
|
|
|
|
|
public bool IsNull
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get { return _source.IsNull; }
|
|
|
|
|
|
}
|
2025-03-11 14:30:33 +08:00
|
|
|
|
public short WorldID
|
2024-03-02 06:07:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get { return _source.WorldID; }
|
|
|
|
|
|
}
|
|
|
|
|
|
public EcsWorld World
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return _source.World; }
|
|
|
|
|
|
}
|
|
|
|
|
|
public int Count
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get { return _source.Count; }
|
|
|
|
|
|
}
|
2025-03-11 14:30:33 +08:00
|
|
|
|
public bool IsSourceEntities
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get { return _source.IsSourceEntities; }
|
|
|
|
|
|
}
|
2024-04-28 19:43:10 +08:00
|
|
|
|
#if ENABLE_IL2CPP
|
|
|
|
|
|
[Il2CppSetOption(Option.ArrayBoundsChecks, true)]
|
|
|
|
|
|
#endif
|
2024-03-02 17:12:41 +08:00
|
|
|
|
public entlong this[int index]
|
2024-03-02 06:07:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-03-02 17:12:41 +08:00
|
|
|
|
get { return World.GetEntityLong(_source[index]); }
|
2024-03-02 06:07:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Constructors
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
internal EcsLongsSpan(EcsSpan span)
|
|
|
|
|
|
{
|
|
|
|
|
|
_source = span;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-03-02 20:51:18 +08:00
|
|
|
|
#region Slice/ToSpan/ToArry
|
2024-03-02 06:07:50 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public EcsLongsSpan Slice(int start) { return new EcsLongsSpan(_source.Slice(start)); }
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public EcsLongsSpan Slice(int start, int length) { return new EcsLongsSpan(_source.Slice(start, length)); }
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public EcsSpan ToSpan() { return _source; }
|
2024-08-31 14:51:13 +08:00
|
|
|
|
public entlong[] ToArray()
|
|
|
|
|
|
{
|
|
|
|
|
|
entlong[] result = new entlong[_source.Count];
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
foreach (var e in this)
|
|
|
|
|
|
{
|
|
|
|
|
|
result[i++] = e;
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
public int ToArray(ref entlong[] dynamicBuffer)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dynamicBuffer.Length < _source.Count)
|
|
|
|
|
|
{
|
2025-08-26 15:50:11 +08:00
|
|
|
|
Array.Resize(ref dynamicBuffer, ArrayUtility.CeilPow2(_source.Count));
|
2024-08-31 14:51:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
foreach (var e in this)
|
|
|
|
|
|
{
|
|
|
|
|
|
dynamicBuffer[i++] = e;
|
|
|
|
|
|
}
|
|
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
public void ToCollection(ICollection<entlong> collection)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var e in this)
|
|
|
|
|
|
{
|
|
|
|
|
|
collection.Add(e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-03-02 06:07:50 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region operators
|
2024-10-05 18:05:33 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-03-02 06:07:50 +08:00
|
|
|
|
public static bool operator ==(EcsLongsSpan left, EcsLongsSpan right) { return left._source == right._source; }
|
2024-10-05 18:05:33 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-03-02 06:07:50 +08:00
|
|
|
|
public static bool operator !=(EcsLongsSpan left, EcsLongsSpan right) { return left._source != right._source; }
|
2024-10-05 18:05:33 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public static implicit operator EcsSpan(EcsLongsSpan a) { return a.ToSpan(); }
|
2024-03-02 06:07:50 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Enumerator
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public Enumerator GetEnumerator() { return new Enumerator(_source.World, _source.GetEnumerator()); }
|
|
|
|
|
|
public ref struct Enumerator
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly EcsWorld _world;
|
|
|
|
|
|
private ReadOnlySpan<int>.Enumerator _enumerator;
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public Enumerator(EcsWorld world, ReadOnlySpan<int>.Enumerator enumerator)
|
|
|
|
|
|
{
|
|
|
|
|
|
_world = world;
|
|
|
|
|
|
_enumerator = enumerator;
|
|
|
|
|
|
}
|
|
|
|
|
|
public entlong Current
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get { return _world.GetEntityLong(_enumerator.Current); }
|
|
|
|
|
|
}
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public bool MoveNext() { return _enumerator.MoveNext(); }
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Other
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public entlong First() { return _source.World.GetEntityLong(_source.First()); }
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public entlong Last() { return _source.World.GetEntityLong(_source.Last()); }
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
|
{
|
|
|
|
|
|
return CollectionUtility.EntitiesToString(_source.ToArray(), "longs_span");
|
|
|
|
|
|
}
|
|
|
|
|
|
#pragma warning disable CS0809 // Устаревший член переопределяет неустаревший член
|
|
|
|
|
|
[Obsolete("Equals() on EcsLongSpan will always throw an exception. Use the equality operator instead.")]
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
|
|
|
|
public override bool Equals(object obj) { throw new NotSupportedException(); }
|
|
|
|
|
|
[Obsolete("GetHashCode() on EcsLongSpan will always throw an exception.")]
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
|
|
|
|
public override int GetHashCode() { throw new NotSupportedException(); }
|
|
|
|
|
|
#pragma warning restore CS0809 // Устаревший член переопределяет неустаревший член
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
2026-03-16 21:52:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace DCFApixels.DragonECS.Core
|
|
|
|
|
|
{
|
|
|
|
|
|
#if ENABLE_IL2CPP
|
|
|
|
|
|
using Unity.IL2CPP.CompilerServices;
|
|
|
|
|
|
[Il2CppSetOption(Option.NullChecks, false)]
|
|
|
|
|
|
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
|
|
|
|
|
#endif
|
|
|
|
|
|
[DebuggerTypeProxy(typeof(EcsSpan.DebuggerProxy))]
|
|
|
|
|
|
public unsafe readonly struct EcsUnsafeSpan
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly int* _values;
|
|
|
|
|
|
private readonly int _length;
|
|
|
|
|
|
private readonly short _worldID;
|
|
|
|
|
|
|
|
|
|
|
|
#region Properties
|
|
|
|
|
|
public bool IsNull
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get { return _worldID == 0; }
|
|
|
|
|
|
}
|
|
|
|
|
|
public short WorldID
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get { return _worldID; }
|
|
|
|
|
|
}
|
|
|
|
|
|
public EcsWorld World
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return EcsWorld.GetWorld(_worldID); }
|
|
|
|
|
|
}
|
|
|
|
|
|
public int Count
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get { return _length; }
|
|
|
|
|
|
}
|
|
|
|
|
|
public EcsLongsSpan Longs
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get { return ToSpan().Longs; }
|
|
|
|
|
|
}
|
|
|
|
|
|
public bool IsSourceEntities
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2026-03-17 10:28:04 +08:00
|
|
|
|
get { return ToSpan().IsSourceEntities; }
|
2026-03-16 21:52:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public int this[int index]
|
|
|
|
|
|
{
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
|
if ((uint)index >= (uint)_length || (uint)index < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
ThrowHelper.ThrowIndexOutOfRangeException();
|
|
|
|
|
|
}
|
|
|
|
|
|
#elif DRAGONECS_STABILITY_MODE
|
|
|
|
|
|
return EcsConsts.NULL_ENTITY_ID;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
return _values[index];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Constructors
|
|
|
|
|
|
internal EcsUnsafeSpan(short worldID, int* array, int length)
|
|
|
|
|
|
{
|
|
|
|
|
|
_worldID = worldID;
|
|
|
|
|
|
_values = array;
|
|
|
|
|
|
_length = length;
|
|
|
|
|
|
}
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
internal EcsUnsafeSpan(short worldID, int* array, int start, int length)
|
|
|
|
|
|
{
|
|
|
|
|
|
_worldID = worldID;
|
|
|
|
|
|
_values = array + start;
|
|
|
|
|
|
_length = length;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Slice/ToArray
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public EcsUnsafeSpan Slice(int start)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((uint)start > (uint)_length)
|
|
|
|
|
|
{
|
|
|
|
|
|
ThrowHelper.ThrowArgumentOutOfRangeException();
|
|
|
|
|
|
}
|
|
|
|
|
|
return new EcsUnsafeSpan(_worldID, _values, start, _length - start);
|
|
|
|
|
|
}
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public EcsUnsafeSpan Slice(int start, int length)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
|
|
|
|
|
|
{
|
|
|
|
|
|
ThrowHelper.ThrowArgumentOutOfRangeException();
|
|
|
|
|
|
}
|
|
|
|
|
|
return new EcsUnsafeSpan(_worldID, _values, start, length);
|
|
|
|
|
|
}
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public EcsSpan ToSpan() { return new EcsSpan(_worldID, new ReadOnlySpan<int>(_values, _length)); }
|
|
|
|
|
|
public int[] ToArray() { return new ReadOnlySpan<int>(_values, _length).ToArray(); }
|
|
|
|
|
|
public int ToArray(ref int[] dynamicBuffer)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dynamicBuffer.Length < _length)
|
|
|
|
|
|
{
|
|
|
|
|
|
Array.Resize(ref dynamicBuffer, ArrayUtility.CeilPow2(_length));
|
|
|
|
|
|
}
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
foreach (var e in this)
|
|
|
|
|
|
{
|
|
|
|
|
|
dynamicBuffer[i++] = e;
|
|
|
|
|
|
}
|
|
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
public void ToCollection(ICollection<int> collection)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var e in this)
|
|
|
|
|
|
{
|
|
|
|
|
|
collection.Add(e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region operators
|
2026-03-17 10:28:04 +08:00
|
|
|
|
public static bool operator ==(EcsUnsafeSpan left, EcsUnsafeSpan right) { return left._values == right._values && left._length == right._length && left._worldID == right._worldID; }
|
|
|
|
|
|
public static bool operator !=(EcsUnsafeSpan left, EcsUnsafeSpan right) { return left._values != right._values || left._length != right._length || left._worldID != right._worldID; }
|
2026-03-16 21:52:45 +08:00
|
|
|
|
public static implicit operator EcsSpan(EcsUnsafeSpan a) { return a.ToSpan(); }
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Enumerator
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public ReadOnlySpan<int>.Enumerator GetEnumerator() { return new ReadOnlySpan<int>(_values, _length).GetEnumerator(); }
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Other
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public int First() { return _values[0]; }
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
|
public int Last() { return _values[_length - 1]; }
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
|
{
|
|
|
|
|
|
return CollectionUtility.EntitiesToString(ToArray(), "span");
|
|
|
|
|
|
}
|
|
|
|
|
|
public override bool Equals(object obj)
|
|
|
|
|
|
{
|
|
|
|
|
|
return obj is EcsUnsafeSpan other && other == this;
|
|
|
|
|
|
}
|
|
|
|
|
|
public override int GetHashCode()
|
|
|
|
|
|
{
|
|
|
|
|
|
return *_values ^ _length ^ (_worldID << 16);
|
|
|
|
|
|
}
|
|
|
|
|
|
private static class ThrowHelper
|
|
|
|
|
|
{
|
|
|
|
|
|
public static void ThrowIndexOutOfRangeException() => throw new IndexOutOfRangeException();
|
|
|
|
|
|
public static void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException();
|
|
|
|
|
|
public static void ThrowInvalidOperationException() => throw new InvalidOperationException();
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
2024-03-02 06:07:50 +08:00
|
|
|
|
}
|