update world components

This commit is contained in:
Mikhail 2023-06-21 15:03:33 +08:00
parent 4f98009256
commit aea6c75ad6
2 changed files with 61 additions and 5 deletions

View File

@ -8,6 +8,7 @@ namespace DCFApixels.DragonECS
public interface IEcsWorldComponent<T> public interface IEcsWorldComponent<T>
{ {
void Init(ref T component, EcsWorld world); void Init(ref T component, EcsWorld world);
void OnDestroy(ref T component, EcsWorld world);
} }
public static class EcsWorldComponentHandler<T> public static class EcsWorldComponentHandler<T>
{ {
@ -30,6 +31,7 @@ namespace DCFApixels.DragonECS
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Init(ref T component, EcsWorld world) { } public void Init(ref T component, EcsWorld world) { }
public void OnDestroy(ref T component, EcsWorld world) { }
} }
} }
internal class WorldComponentHandler<T> : IEcsWorldComponent<T> internal class WorldComponentHandler<T> : IEcsWorldComponent<T>
@ -38,6 +40,7 @@ namespace DCFApixels.DragonECS
private T _fakeInstnace; private T _fakeInstnace;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Init(ref T component, EcsWorld world) => _fakeInstnace.Init(ref component, world); public void Init(ref T component, EcsWorld world) => _fakeInstnace.Init(ref component, world);
public void OnDestroy(ref T component, EcsWorld world) => _fakeInstnace.OnDestroy(ref component, world);
} }
#endregion #endregion

View File

@ -4,9 +4,18 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 4)]
public struct EcsWorldDataRef<T> where T : struct
{
private int _worldID;
public EcsWorldDataRef(int worldID) => _worldID = worldID;
public EcsWorld World => EcsWorld.GetWorld(_worldID);
public ref T Inst => ref EcsWorld.GetData<T>(_worldID);
}
public abstract partial class EcsWorld public abstract partial class EcsWorld
{ {
private const short GEN_BITS = 0x7fff; private const short GEN_BITS = 0x7fff;
@ -16,21 +25,41 @@ namespace DCFApixels.DragonECS
internal static EcsWorld[] Worlds = new EcsWorld[4]; internal static EcsWorld[] Worlds = new EcsWorld[4];
private static IntDispenser _worldIdDispenser = new IntDispenser(0); private static IntDispenser _worldIdDispenser = new IntDispenser(0);
private static List<DataReleaser> _dataReleaseres = new List<DataReleaser>();
static EcsWorld() static EcsWorld()
{ {
Worlds[0] = new EcsNullWorld(); Worlds[0] = new EcsNullWorld();
} }
private static void ReleaseData(int worldID)
{
for (int i = 0, iMax = _dataReleaseres.Count; i < iMax; i++)
_dataReleaseres[i].Release(worldID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static EcsWorld GetWorld(int worldID) => Worlds[worldID]; public static EcsWorld GetWorld(int worldID) => Worlds[worldID];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T GetData<T>(int worldID) => ref WorldComponentPool<T>.GetForWorld(worldID);
private abstract class DataReleaser
{
public abstract void Release(int worldID);
}
private static class WorldComponentPool<T> private static class WorldComponentPool<T>
{ {
private static T[] _items = new T[4]; private static T[] _items = new T[4];
private static int[] _mapping = new int[4]; private static int[] _mapping = new int[4];
private static int _count; private static int _count;
private static int[] _recycledItems = new int[4];
private static int _recycledItemsCount;
private static IEcsWorldComponent<T> _interface = EcsWorldComponentHandler<T>.instance; private static IEcsWorldComponent<T> _interface = EcsWorldComponentHandler<T>.instance;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T Get(int itemIndex) => ref _items[itemIndex]; public static ref T Get(int itemIndex) => ref _items[itemIndex];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T GetForWorld(int worldID) => ref _items[GetItemIndex(worldID)];
public static int GetItemIndex(int worldID) public static int GetItemIndex(int worldID)
{ {
if (_mapping.Length < Worlds.Length) if (_mapping.Length < Worlds.Length)
@ -38,14 +67,37 @@ namespace DCFApixels.DragonECS
ref int itemIndex = ref _mapping[worldID]; ref int itemIndex = ref _mapping[worldID];
if (itemIndex <= 0) if (itemIndex <= 0)
{
if(_recycledItemsCount > 0)
{
_count++;
itemIndex = _recycledItems[--_recycledItemsCount];
}
else
{ {
itemIndex = ++_count; itemIndex = ++_count;
}
_interface.Init(ref _items[itemIndex], Worlds[worldID]); _interface.Init(ref _items[itemIndex], Worlds[worldID]);
_dataReleaseres.Add(new Releaser());
} }
return itemIndex; return itemIndex;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static void Release(int worldID)
public static ref T GetForWorld(int worldID) => ref _items[GetItemIndex(worldID)]; {
ref int itemIndex = ref _mapping[worldID];
if(itemIndex != 0)
{
_interface.OnDestroy(ref _items[itemIndex], Worlds[worldID]);
_recycledItems[_recycledItemsCount++] = itemIndex;
}
}
private sealed class Releaser : DataReleaser
{
public sealed override void Release(int worldID)
{
WorldComponentPool<T>.Release(worldID);
}
}
} }
} }
public abstract partial class EcsWorld public abstract partial class EcsWorld
@ -127,6 +179,7 @@ namespace DCFApixels.DragonECS
_subjects = null; _subjects = null;
_executors = null; _executors = null;
Worlds[id] = null; Worlds[id] = null;
ReleaseData(id);
_worldIdDispenser.Release(id); _worldIdDispenser.Release(id);
} }
#endregion #endregion
@ -183,7 +236,7 @@ namespace DCFApixels.DragonECS
} }
return (TExecutor)result; return (TExecutor)result;
} }
public ref T GetComponent<T>() where T : struct => ref WorldComponentPool<T>.GetForWorld(id); public ref T Get<T>() where T : struct => ref WorldComponentPool<T>.GetForWorld(id);
#endregion #endregion
#region Where Query #region Where Query