mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 09:54:35 +08:00
redesign world components
This commit is contained in:
parent
8eb5953c0d
commit
4f98009256
117
src/DataInterfaces.cs
Normal file
117
src/DataInterfaces.cs
Normal file
@ -0,0 +1,117 @@
|
||||
using DCFApixels.DragonECS.Internal;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
#region IEcsWorldComponent
|
||||
public interface IEcsWorldComponent<T>
|
||||
{
|
||||
void Init(ref T component, EcsWorld world);
|
||||
}
|
||||
public static class EcsWorldComponentHandler<T>
|
||||
{
|
||||
public static readonly IEcsWorldComponent<T> instance;
|
||||
public static readonly bool isHasHandler;
|
||||
static EcsWorldComponentHandler()
|
||||
{
|
||||
Type targetType = typeof(T);
|
||||
isHasHandler = targetType.GetInterfaces().Contains(typeof(IEcsWorldComponent<>).MakeGenericType(targetType));
|
||||
if (isHasHandler)
|
||||
{
|
||||
instance = (IEcsWorldComponent<T>)Activator.CreateInstance(typeof(ComponentResetHandler<>).MakeGenericType(targetType));
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = new DummyHandler();
|
||||
}
|
||||
}
|
||||
private class DummyHandler : IEcsWorldComponent<T>
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Init(ref T component, EcsWorld world) { }
|
||||
}
|
||||
}
|
||||
internal class WorldComponentHandler<T> : IEcsWorldComponent<T>
|
||||
where T : IEcsWorldComponent<T>
|
||||
{
|
||||
private T _fakeInstnace;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Init(ref T component, EcsWorld world) => _fakeInstnace.Init(ref component, world);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEcsComponentReset
|
||||
public interface IEcsComponentReset<T>
|
||||
{
|
||||
void Reset(ref T component);
|
||||
}
|
||||
public static class EcsComponentResetHandler<T>
|
||||
{
|
||||
public static readonly IEcsComponentReset<T> instance;
|
||||
public static readonly bool isHasHandler;
|
||||
static EcsComponentResetHandler()
|
||||
{
|
||||
Type targetType = typeof(T);
|
||||
isHasHandler = targetType.GetInterfaces().Contains(typeof(IEcsComponentReset<>).MakeGenericType(targetType));
|
||||
if (isHasHandler)
|
||||
{
|
||||
instance = (IEcsComponentReset<T>)Activator.CreateInstance(typeof(ComponentResetHandler<>).MakeGenericType(targetType));
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = new DummyHandler();
|
||||
}
|
||||
}
|
||||
private sealed class DummyHandler : IEcsComponentReset<T>
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Reset(ref T component) => component = default;
|
||||
}
|
||||
}
|
||||
internal sealed class ComponentResetHandler<T> : IEcsComponentReset<T>
|
||||
where T : IEcsComponentReset<T>
|
||||
{
|
||||
private T _fakeInstnace;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Reset(ref T component) => _fakeInstnace.Reset(ref component);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEcsComponentCopy
|
||||
public interface IEcsComponentCopy<T>
|
||||
{
|
||||
void Copy(ref T from, ref T to);
|
||||
}
|
||||
public static class EcsComponentCopyHandler<T>
|
||||
{
|
||||
public static readonly IEcsComponentCopy<T> instance;
|
||||
public static readonly bool isHasHandler;
|
||||
static EcsComponentCopyHandler()
|
||||
{
|
||||
Type targetType = typeof(T);
|
||||
isHasHandler = targetType.GetInterfaces().Contains(typeof(IEcsComponentCopy<>).MakeGenericType(targetType));
|
||||
if (isHasHandler)
|
||||
{
|
||||
instance = (IEcsComponentCopy<T>)Activator.CreateInstance(typeof(ComponentCopyHandler<>).MakeGenericType(targetType));
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = new DummyHandler();
|
||||
}
|
||||
}
|
||||
private sealed class DummyHandler : IEcsComponentCopy<T>
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Copy(ref T from, ref T to) => to = from;
|
||||
}
|
||||
}
|
||||
internal sealed class ComponentCopyHandler<T> : IEcsComponentCopy<T>
|
||||
where T : IEcsComponentCopy<T>
|
||||
{
|
||||
private T _fakeInstnace;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Copy(ref T from, ref T to) => _fakeInstnace.Copy(ref from, ref to);
|
||||
}
|
||||
#endregion
|
||||
}
|
123
src/EcsWorld.cs
123
src/EcsWorld.cs
@ -7,16 +7,49 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public abstract class EcsWorld
|
||||
public abstract partial class EcsWorld
|
||||
{
|
||||
private const short GEN_BITS = 0x7fff;
|
||||
private const short DEATH_GEN_BIT = short.MinValue;
|
||||
private const int DEL_ENT_BUFFER_SIZE_OFFSET = 2;
|
||||
|
||||
internal static EcsWorld[] Worlds = new EcsWorld[8];
|
||||
internal static EcsWorld[] Worlds = new EcsWorld[4];
|
||||
private static IntDispenser _worldIdDispenser = new IntDispenser(0);
|
||||
|
||||
static EcsWorld()
|
||||
{
|
||||
Worlds[0] = new EcsNullWorld();
|
||||
}
|
||||
|
||||
public static EcsWorld GetWorld(int worldID) => Worlds[worldID];
|
||||
|
||||
private static class WorldComponentPool<T>
|
||||
{
|
||||
private static T[] _items = new T[4];
|
||||
private static int[] _mapping = new int[4];
|
||||
private static int _count;
|
||||
private static IEcsWorldComponent<T> _interface = EcsWorldComponentHandler<T>.instance;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref T Get(int itemIndex) => ref _items[itemIndex];
|
||||
public static int GetItemIndex(int worldID)
|
||||
{
|
||||
if (_mapping.Length < Worlds.Length)
|
||||
Array.Resize(ref _mapping, Worlds.Length);
|
||||
|
||||
ref int itemIndex = ref _mapping[worldID];
|
||||
if (itemIndex <= 0)
|
||||
{
|
||||
itemIndex = ++_count;
|
||||
_interface.Init(ref _items[itemIndex], Worlds[worldID]);
|
||||
}
|
||||
return itemIndex;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref T GetForWorld(int worldID) => ref _items[GetItemIndex(worldID)];
|
||||
}
|
||||
}
|
||||
public abstract partial class EcsWorld
|
||||
{
|
||||
public readonly short id;
|
||||
|
||||
private Type _worldType;
|
||||
@ -44,8 +77,6 @@ namespace DCFApixels.DragonECS
|
||||
private List<IEcsWorldEventListener> _listeners = new List<IEcsWorldEventListener>();
|
||||
private List<IEcsEntityEventListener> _entityListeners = new List<IEcsEntityEventListener>();
|
||||
|
||||
private object[] _components = new object[2];
|
||||
|
||||
#region Properties
|
||||
public int WorldTypeID => _worldTypeID;
|
||||
public int Count => _entitiesCount;
|
||||
@ -55,10 +86,6 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region Constructors/Destroy
|
||||
static EcsWorld()
|
||||
{
|
||||
Worlds[0] = new EcsNullWorld();
|
||||
}
|
||||
public EcsWorld() : this(true) { }
|
||||
internal EcsWorld(bool isIndexable)
|
||||
{
|
||||
@ -156,80 +183,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
return (TExecutor)result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region WorldComponents
|
||||
public EcsWorld SetupComponents(IEnumerable<object> components, params object[] componentsParams)
|
||||
{
|
||||
foreach (var component in components)
|
||||
SetComponent(component);
|
||||
foreach (var component in componentsParams)
|
||||
SetComponent(component);
|
||||
return this;
|
||||
}
|
||||
public EcsWorld SetupComponents(params object[] components)
|
||||
{
|
||||
foreach (var component in components)
|
||||
SetComponent(component);
|
||||
return this;
|
||||
}
|
||||
public void SetComponent(object component)
|
||||
{
|
||||
Type componentType = component.GetType();
|
||||
if (componentType.IsValueType || componentType.IsPrimitive)
|
||||
throw new ArgumentException();
|
||||
SetComponentInternal(WorldMetaStorage.GetWorldComponentID(componentType, _worldTypeID), component);
|
||||
}
|
||||
public void SetComponent<T>(T component) where T : class
|
||||
{
|
||||
SetComponentInternal(WorldMetaStorage.GetWorldComponentID<T>(_worldTypeID), component);
|
||||
}
|
||||
private void SetComponentInternal(int index, object component)
|
||||
{
|
||||
if (index >= _components.Length)
|
||||
Array.Resize(ref _components, _components.Length << 1);
|
||||
|
||||
ref var currentComponent = ref _components[index];
|
||||
if (currentComponent == component)
|
||||
return;
|
||||
if (currentComponent != null && currentComponent is IEcsWorldComponent oldComponentInterface)
|
||||
oldComponentInterface.OnRemovedFromWorld(this);
|
||||
currentComponent = component;
|
||||
if (component is IEcsWorldComponent newComponentInterface)
|
||||
newComponentInterface.OnAddedToWorld(this);
|
||||
}
|
||||
public T GetComponent<T>() where T : class
|
||||
{
|
||||
if (!TryGetComponent(out T result))
|
||||
throw new NullReferenceException();
|
||||
return result;
|
||||
}
|
||||
public bool TryGetComponent<T>(out T component) where T : class
|
||||
{
|
||||
int index = WorldMetaStorage.GetWorldComponentID<T>(_worldTypeID);
|
||||
if (index >= _components.Length)
|
||||
{
|
||||
component = null;
|
||||
return false;
|
||||
}
|
||||
component = (T)_components[index];
|
||||
return component != null;
|
||||
}
|
||||
public bool HasComponent<T>()
|
||||
{
|
||||
int index = WorldMetaStorage.GetWorldComponentID<T>(_worldTypeID);
|
||||
if (index >= _components.Length)
|
||||
return false;
|
||||
return _components[index] != null;
|
||||
}
|
||||
public void RemoveComponent<T>()
|
||||
{
|
||||
int index = WorldMetaStorage.GetWorldComponentID<T>(_worldTypeID);
|
||||
ref var currentComponent = ref _components[index];
|
||||
if (currentComponent is IEcsWorldComponent componentInterface)
|
||||
componentInterface.OnRemovedFromWorld(this);
|
||||
currentComponent = null;
|
||||
}
|
||||
public ref T GetComponent<T>() where T : struct => ref WorldComponentPool<T>.GetForWorld(id);
|
||||
#endregion
|
||||
|
||||
#region Where Query
|
||||
@ -455,11 +409,6 @@ namespace DCFApixels.DragonECS
|
||||
internal sealed class EcsNullWorld : EcsWorld { }
|
||||
|
||||
#region Callbacks Interface
|
||||
public interface IEcsWorldComponent
|
||||
{
|
||||
void OnAddedToWorld(EcsWorld world);
|
||||
void OnRemovedFromWorld(EcsWorld world);
|
||||
}
|
||||
public interface IEcsWorldEventListener
|
||||
{
|
||||
void OnWorldResize(int newSize);
|
||||
|
@ -121,80 +121,6 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Reset/Copy interfaces
|
||||
public interface IEcsComponentReset<T>
|
||||
{
|
||||
void Reset(ref T component);
|
||||
}
|
||||
public static class EcsComponentResetHandler<T>
|
||||
{
|
||||
public static readonly IEcsComponentReset<T> instance;
|
||||
public static readonly bool isHasHandler;
|
||||
static EcsComponentResetHandler()
|
||||
{
|
||||
Type targetType = typeof(T);
|
||||
if (targetType.GetInterfaces().Contains(typeof(IEcsComponentReset<>).MakeGenericType(targetType)))
|
||||
{
|
||||
instance = (IEcsComponentReset<T>)Activator.CreateInstance(typeof(ComponentResetHandler<>).MakeGenericType(targetType));
|
||||
isHasHandler = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = new ComponentResetDummyHandler<T>();
|
||||
isHasHandler = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal sealed class ComponentResetDummyHandler<T> : IEcsComponentReset<T>
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Reset(ref T component) => component = default;
|
||||
}
|
||||
internal sealed class ComponentResetHandler<T> : IEcsComponentReset<T>
|
||||
where T : IEcsComponentReset<T>
|
||||
{
|
||||
private T _fakeInstnace = default;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Reset(ref T component) => _fakeInstnace.Reset(ref component);
|
||||
}
|
||||
|
||||
public interface IEcsComponentCopy<T>
|
||||
{
|
||||
void Copy(ref T from, ref T to);
|
||||
}
|
||||
public static class EcsComponentCopyHandler<T>
|
||||
{
|
||||
public static readonly IEcsComponentCopy<T> instance;
|
||||
public static readonly bool isHasHandler;
|
||||
static EcsComponentCopyHandler()
|
||||
{
|
||||
Type targetType = typeof(T);
|
||||
if (targetType.GetInterfaces().Contains(typeof(IEcsComponentCopy<>).MakeGenericType(targetType)))
|
||||
{
|
||||
instance = (IEcsComponentCopy<T>)Activator.CreateInstance(typeof(ComponentCopyHandler<>).MakeGenericType(targetType));
|
||||
isHasHandler = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = new ComponentCopyDummyHandler<T>();
|
||||
isHasHandler = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal sealed class ComponentCopyDummyHandler<T> : IEcsComponentCopy<T>
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Copy(ref T from, ref T to) => to = from;
|
||||
}
|
||||
internal sealed class ComponentCopyHandler<T> : IEcsComponentCopy<T>
|
||||
where T : IEcsComponentCopy<T>
|
||||
{
|
||||
private T _fakeInstnace = default;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Copy(ref T from, ref T to) => _fakeInstnace.Copy(ref from, ref to);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Callbacks Interface
|
||||
public interface IEcsPoolEventListener
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user