mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 18:14:37 +08:00
update Hybridity implementation
This commit is contained in:
parent
b49be251a5
commit
6354d91769
@ -37,6 +37,12 @@ namespace DCFApixels.DragonECS
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void PrintWarning(object v) => Print(EcsConsts.DEBUG_WARNING_TAG, v);
|
public static void PrintWarning(object v) => Print(EcsConsts.DEBUG_WARNING_TAG, v);
|
||||||
public static void PrintError(object v) => Print(EcsConsts.DEBUG_ERROR_TAG, v);
|
public static void PrintError(object v) => Print(EcsConsts.DEBUG_ERROR_TAG, v);
|
||||||
|
public static void Print()
|
||||||
|
{
|
||||||
|
#if !DISABLE_DRAGONECS_DEBUGGER
|
||||||
|
DebugService.Instance.Print("");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
public static void Print(object v)
|
public static void Print(object v)
|
||||||
{
|
{
|
||||||
#if !DISABLE_DRAGONECS_DEBUGGER
|
#if !DISABLE_DRAGONECS_DEBUGGER
|
||||||
|
@ -10,60 +10,6 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
private const BindingFlags RFL_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
private const BindingFlags RFL_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
|
|
||||||
private struct ProcessInterface
|
|
||||||
{
|
|
||||||
public Type interfaceType;
|
|
||||||
public string processName;
|
|
||||||
public ProcessInterface(Type interfaceType, string processName)
|
|
||||||
{
|
|
||||||
this.interfaceType = interfaceType;
|
|
||||||
this.processName = processName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static Dictionary<Type, ProcessInterface> _processes = new Dictionary<Type, ProcessInterface>();
|
|
||||||
|
|
||||||
static EcsDebugUtility()
|
|
||||||
{
|
|
||||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
|
||||||
{
|
|
||||||
var types = assembly.GetTypes();
|
|
||||||
foreach (var type in types)
|
|
||||||
{
|
|
||||||
if (!type.IsInterface)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (type.GetInterface(nameof(IEcsProcess)) != null)
|
|
||||||
{
|
|
||||||
string name = type.Name;
|
|
||||||
if (name[0] == 'I' && name.Length > 1 && char.IsUpper(name[1]))
|
|
||||||
name = name.Substring(1);
|
|
||||||
name = Regex.Replace(name, @"\bEcs|Process\b", "");
|
|
||||||
_processes.Add(type, new ProcessInterface(type, name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Process
|
|
||||||
public static bool IsProcessInterface(Type type)
|
|
||||||
{
|
|
||||||
if (type.IsGenericType) type = type.GetGenericTypeDefinition();
|
|
||||||
return _processes.ContainsKey(type);
|
|
||||||
}
|
|
||||||
public static string GetProcessInterfaceName(Type type)
|
|
||||||
{
|
|
||||||
if (type.IsGenericType) type = type.GetGenericTypeDefinition();
|
|
||||||
return _processes[type].processName;
|
|
||||||
}
|
|
||||||
public static bool TryGetProcessInterfaceName(Type type, out string name)
|
|
||||||
{
|
|
||||||
if (type.IsGenericType) type = type.GetGenericTypeDefinition();
|
|
||||||
bool result = _processes.TryGetValue(type, out ProcessInterface data);
|
|
||||||
name = data.processName;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region GetGenericTypeName
|
#region GetGenericTypeName
|
||||||
public static string GetGenericTypeFullName<T>(int maxDepth = 2) => GetGenericTypeFullName(typeof(T), maxDepth);
|
public static string GetGenericTypeFullName<T>(int maxDepth = 2) => GetGenericTypeFullName(typeof(T), maxDepth);
|
||||||
public static string GetGenericTypeFullName(Type type, int maxDepth = 2) => GetGenericTypeNameInternal(type, maxDepth, true);
|
public static string GetGenericTypeFullName(Type type, int maxDepth = 2) => GetGenericTypeNameInternal(type, maxDepth, true);
|
||||||
|
@ -6,6 +6,7 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using static DCFApixels.DragonECS.EcsDebugUtility;
|
using static DCFApixels.DragonECS.EcsDebugUtility;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
@ -263,4 +264,85 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public static class EcsProcessUtility
|
||||||
|
{
|
||||||
|
private struct ProcessInterface
|
||||||
|
{
|
||||||
|
public Type interfaceType;
|
||||||
|
public string processName;
|
||||||
|
public ProcessInterface(Type interfaceType, string processName)
|
||||||
|
{
|
||||||
|
this.interfaceType = interfaceType;
|
||||||
|
this.processName = processName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static Dictionary<Type, ProcessInterface> _processes = new Dictionary<Type, ProcessInterface>();
|
||||||
|
private static HashSet<Type> _systems = new HashSet<Type>();
|
||||||
|
|
||||||
|
static EcsProcessUtility()
|
||||||
|
{
|
||||||
|
Type processBasicInterface = typeof(IEcsProcess);
|
||||||
|
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
var types = assembly.GetTypes();
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
if (type.GetInterface(nameof(IEcsProcess)) != null || type == processBasicInterface)
|
||||||
|
{
|
||||||
|
if (type.IsInterface)
|
||||||
|
{
|
||||||
|
string name = type.Name;
|
||||||
|
if (name[0] == 'I' && name.Length > 1 && char.IsUpper(name[1]))
|
||||||
|
name = name.Substring(1);
|
||||||
|
name = Regex.Replace(name, @"\bEcs|Process\b", "");
|
||||||
|
if (Regex.IsMatch(name, "`\\w{1,}$"))
|
||||||
|
{
|
||||||
|
var s = name.Split("`");
|
||||||
|
name = s[0] + $"<{s[1]}>";
|
||||||
|
}
|
||||||
|
_processes.Add(type, new ProcessInterface(type, name));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_systems.Add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Systems
|
||||||
|
public static bool IsSystem(Type type) => _systems.Contains(type);
|
||||||
|
public static bool IsEcsSystem(this Type type) => _systems.Contains(type);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Process
|
||||||
|
public static bool IsProcessInterface(Type type)
|
||||||
|
{
|
||||||
|
if (type.IsGenericType) type = type.GetGenericTypeDefinition();
|
||||||
|
return _processes.ContainsKey(type);
|
||||||
|
}
|
||||||
|
public static bool IsEcsProcessInterface(this Type type) => IsProcessInterface(type);
|
||||||
|
|
||||||
|
public static string GetProcessInterfaceName(Type type)
|
||||||
|
{
|
||||||
|
if (type.IsGenericType) type = type.GetGenericTypeDefinition();
|
||||||
|
return _processes[type].processName;
|
||||||
|
}
|
||||||
|
public static bool TryGetProcessInterfaceName(Type type, out string name)
|
||||||
|
{
|
||||||
|
if (type.IsGenericType) type = type.GetGenericTypeDefinition();
|
||||||
|
bool result = _processes.TryGetValue(type, out ProcessInterface data);
|
||||||
|
name = data.processName;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Type> GetEcsProcessInterfaces(this Type self)
|
||||||
|
{
|
||||||
|
return self.GetInterfaces().Where(o=> o.IsEcsProcessInterface());
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ namespace DCFApixels.DragonECS
|
|||||||
if (_poolIds.Contains(EcsTypeCode.Get<TPool>()))
|
if (_poolIds.Contains(EcsTypeCode.Get<TPool>()))
|
||||||
throw new EcsFrameworkException("The pool has already been created.");
|
throw new EcsFrameworkException("The pool has already been created.");
|
||||||
|
|
||||||
Type componentType = typeof(TPool).GetInterfaces().First(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEcsPoolImplementation<>));
|
Type componentType = typeof(TPool).GetInterfaces().First(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEcsPoolImplementation<>)).GetGenericArguments()[0];
|
||||||
int componentTypeCode = EcsTypeCode.Get(componentType);
|
int componentTypeCode = EcsTypeCode.Get(componentType);
|
||||||
|
|
||||||
if (_componentIds.TryGetValue(componentTypeCode, out int componentID))
|
if (_componentIds.TryGetValue(componentTypeCode, out int componentID))
|
||||||
|
@ -1,13 +1,24 @@
|
|||||||
using DCFApixels.DragonECS.Utils;
|
using DCFApixels.DragonECS.Internal;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using UnityEngine;
|
||||||
|
using static UnityEditor.Progress;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
|
namespace Internal
|
||||||
|
{
|
||||||
|
public interface IEcsHybridPoolInternal : IEcsPool
|
||||||
|
{
|
||||||
|
void AddRefInternal(int entityID, object component, bool isAppend);
|
||||||
|
void DelInternal(int entityID, bool isAppend);
|
||||||
|
}
|
||||||
|
}
|
||||||
/// <summary>Pool for IEcsHybridComponent components</summary>
|
/// <summary>Pool for IEcsHybridComponent components</summary>
|
||||||
public sealed class EcsHybridPool<T> : IEcsPoolImplementation<T>, IEcsHybridPool<T>, IEnumerable<T> //IEnumerable<T> - IntelliSense hack
|
public sealed class EcsHybridPool<T> : IEcsPoolImplementation<T>, IEcsHybridPool<T>, IEcsHybridPoolInternal, IEnumerable<T> //IEnumerable<T> - IntelliSense hack
|
||||||
where T : IEcsHybridComponent
|
where T : IEcsHybridComponent
|
||||||
{
|
{
|
||||||
private EcsWorld _source;
|
private EcsWorld _source;
|
||||||
@ -31,25 +42,12 @@ namespace DCFApixels.DragonECS
|
|||||||
public EcsWorld World => _source;
|
public EcsWorld World => _source;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Init
|
|
||||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
|
||||||
{
|
|
||||||
_source = world;
|
|
||||||
_componentID = componentID;
|
|
||||||
|
|
||||||
const int capacity = 512;
|
|
||||||
|
|
||||||
_mapping = new int[world.Capacity];
|
|
||||||
_recycledItems = new int[128];
|
|
||||||
_recycledItemsCount = 0;
|
|
||||||
_items = new T[capacity];
|
|
||||||
_entities = new int[capacity];
|
|
||||||
_itemsCount = 0;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
public void Add(int entityID, T component)
|
void IEcsHybridPoolInternal.AddRefInternal(int entityID, object component, bool isMain)
|
||||||
|
{
|
||||||
|
AddInternal(entityID, (T)component, isMain);
|
||||||
|
}
|
||||||
|
private void AddInternal(int entityID, T component, bool isMain)
|
||||||
{
|
{
|
||||||
ref int itemIndex = ref _mapping[entityID];
|
ref int itemIndex = ref _mapping[entityID];
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
@ -71,40 +69,23 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
this.IncrementEntityComponentCount(entityID);
|
this.IncrementEntityComponentCount(entityID);
|
||||||
_listeners.InvokeOnAdd(entityID);
|
_listeners.InvokeOnAdd(entityID);
|
||||||
component.OnAddToPool(_source.GetEntityLong(entityID));
|
if(isMain)
|
||||||
|
component.OnAddToPool(_source.GetEntityLong(entityID));
|
||||||
_items[itemIndex] = component;
|
_items[itemIndex] = component;
|
||||||
_entities[itemIndex] = entityID;
|
_entities[itemIndex] = entityID;
|
||||||
}
|
}
|
||||||
|
public void Add(int entityID, T component)
|
||||||
|
{
|
||||||
|
HybridMapping mapping = _source.GetHybridMapping(component.GetType());
|
||||||
|
mapping.GetTargetTypePool().AddRefInternal(entityID, component, false);
|
||||||
|
foreach (var pool in mapping.GetPools())
|
||||||
|
pool.AddRefInternal(entityID, component, true);
|
||||||
|
}
|
||||||
public void Set(int entityID, T component)
|
public void Set(int entityID, T component)
|
||||||
{
|
{
|
||||||
ref int itemIndex = ref _mapping[entityID];
|
if(Has(entityID))
|
||||||
if(itemIndex <= 0)
|
Del(entityID);
|
||||||
{//null
|
Add(entityID, component);
|
||||||
if (_recycledItemsCount > 0)
|
|
||||||
{
|
|
||||||
itemIndex = _recycledItems[--_recycledItemsCount];
|
|
||||||
_itemsCount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
itemIndex = ++_itemsCount;
|
|
||||||
if (itemIndex >= _items.Length)
|
|
||||||
{
|
|
||||||
Array.Resize(ref _items, _items.Length << 1);
|
|
||||||
Array.Resize(ref _entities, _items.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.IncrementEntityComponentCount(entityID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{//not null
|
|
||||||
_listeners.InvokeOnDel(entityID);
|
|
||||||
_items[itemIndex].OnDelFromPool(_source.GetEntityLong(entityID));
|
|
||||||
}
|
|
||||||
_listeners.InvokeOnAdd(entityID);
|
|
||||||
component.OnAddToPool(_source.GetEntityLong(entityID));
|
|
||||||
_items[itemIndex] = component;
|
|
||||||
_entities[itemIndex] = entityID;
|
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public T Get(int entityID)
|
public T Get(int entityID)
|
||||||
@ -128,14 +109,19 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
return _mapping[entityID] > 0;
|
return _mapping[entityID] > 0;
|
||||||
}
|
}
|
||||||
public void Del(int entityID)
|
void IEcsHybridPoolInternal.DelInternal(int entityID, bool isMain)
|
||||||
|
{
|
||||||
|
DelInternal(entityID, isMain);
|
||||||
|
}
|
||||||
|
private void DelInternal(int entityID, bool isMain)
|
||||||
{
|
{
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
|
if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
|
||||||
#endif
|
#endif
|
||||||
ref int itemIndex = ref _mapping[entityID];
|
ref int itemIndex = ref _mapping[entityID];
|
||||||
T component = _items[itemIndex];
|
T component = _items[itemIndex];
|
||||||
component.OnDelFromPool(_source.GetEntityLong(entityID));
|
if(isMain)
|
||||||
|
component.OnDelFromPool(_source.GetEntityLong(entityID));
|
||||||
if (_recycledItemsCount >= _recycledItems.Length)
|
if (_recycledItemsCount >= _recycledItems.Length)
|
||||||
Array.Resize(ref _recycledItems, _recycledItems.Length << 1);
|
Array.Resize(ref _recycledItems, _recycledItems.Length << 1);
|
||||||
_recycledItems[_recycledItemsCount++] = itemIndex;
|
_recycledItems[_recycledItemsCount++] = itemIndex;
|
||||||
@ -145,6 +131,14 @@ namespace DCFApixels.DragonECS
|
|||||||
this.DecrementEntityComponentCount(entityID);
|
this.DecrementEntityComponentCount(entityID);
|
||||||
_listeners.InvokeOnDel(entityID);
|
_listeners.InvokeOnDel(entityID);
|
||||||
}
|
}
|
||||||
|
public void Del(int entityID)
|
||||||
|
{
|
||||||
|
var component = Get(entityID);
|
||||||
|
HybridMapping mapping = _source.GetHybridMapping(component.GetType());
|
||||||
|
mapping.GetTargetTypePool().DelInternal(entityID, false);
|
||||||
|
foreach (var pool in mapping.GetPools())
|
||||||
|
pool.DelInternal(entityID, true);
|
||||||
|
}
|
||||||
public void TryDel(int entityID)
|
public void TryDel(int entityID)
|
||||||
{
|
{
|
||||||
if (Has(entityID)) Del(entityID);
|
if (Has(entityID)) Del(entityID);
|
||||||
@ -175,6 +169,20 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
|
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
||||||
|
{
|
||||||
|
_source = world;
|
||||||
|
_componentID = componentID;
|
||||||
|
|
||||||
|
const int capacity = 512;
|
||||||
|
|
||||||
|
_mapping = new int[world.Capacity];
|
||||||
|
_recycledItems = new int[128];
|
||||||
|
_recycledItemsCount = 0;
|
||||||
|
_items = new T[capacity];
|
||||||
|
_entities = new int[capacity];
|
||||||
|
_itemsCount = 0;
|
||||||
|
}
|
||||||
void IEcsPoolImplementation.OnWorldResize(int newSize)
|
void IEcsPoolImplementation.OnWorldResize(int newSize)
|
||||||
{
|
{
|
||||||
Array.Resize(ref _mapping, newSize);
|
Array.Resize(ref _mapping, newSize);
|
||||||
@ -218,13 +226,11 @@ namespace DCFApixels.DragonECS
|
|||||||
void OnAddToPool(entlong entity);
|
void OnAddToPool(entlong entity);
|
||||||
void OnDelFromPool(entlong entity);
|
void OnDelFromPool(entlong entity);
|
||||||
}
|
}
|
||||||
public static class IEcsHybridComponentExtensions
|
public static class EcsHybridPoolExtensions
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool IsNullOrNotAlive(this IEcsHybridComponent self) => self == null || self.IsAlive;
|
public static bool IsNullOrNotAlive(this IEcsHybridComponent self) => self == null || self.IsAlive;
|
||||||
}
|
|
||||||
public static class EcsHybridPoolExt
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static EcsHybridPool<T> GetPool<T>(this EcsWorld self) where T : IEcsHybridComponent
|
public static EcsHybridPool<T> GetPool<T>(this EcsWorld self) where T : IEcsHybridComponent
|
||||||
{
|
{
|
||||||
@ -253,65 +259,94 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public partial class EcsWorld
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static class InterfaceMatrix
|
|
||||||
{
|
{
|
||||||
private static SparseArray<InterfaceMatrixEdge> _edges = new SparseArray<InterfaceMatrixEdge>();
|
private Dictionary<Type, HybridMapping> _mappings = new Dictionary<Type, HybridMapping>();
|
||||||
private static SparseArray64<InterfaceMatrixEdge> _matrix = new SparseArray64<InterfaceMatrixEdge>();
|
|
||||||
public static bool HasEdge<TParent, TChild>()
|
|
||||||
{
|
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
|
||||||
if (!InterfaceIsDeclared<TParent>() || !InterfaceIsDeclared<TChild>())
|
|
||||||
EcsDebug.PrintWarning($"{nameof(TParent)} or {nameof(TChild)} not declared.");
|
|
||||||
#endif
|
|
||||||
return _matrix.Contains(InterfaceId<TParent>._id, InterfaceId<TChild>._id);
|
|
||||||
}
|
|
||||||
public static bool InterfaceIsDeclared<T>() => _edges.Contains(InterfaceId<T>._id);
|
|
||||||
|
|
||||||
public static void DeclareInterfacesFromClass<T>()
|
internal HybridMapping GetHybridMapping(Type type)
|
||||||
{
|
{
|
||||||
Type type = typeof(T);
|
if(!_mappings.TryGetValue(type, out HybridMapping mapping))
|
||||||
if (type.IsInterface)
|
{
|
||||||
throw new ArgumentException($"The argument {nameof(T)} cannot be an interface");
|
mapping = new HybridMapping(this, type);
|
||||||
|
_mappings.Add(type, mapping);
|
||||||
|
}
|
||||||
|
return mapping;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal class InterfaceMatrixEdge
|
|
||||||
{
|
|
||||||
private static int _increment = 0;
|
|
||||||
|
|
||||||
public readonly int id;
|
internal class HybridMapping
|
||||||
public readonly Type parentType;
|
|
||||||
public readonly Type childType;
|
|
||||||
public readonly int parentID;
|
|
||||||
public readonly int childID;
|
|
||||||
public static InterfaceMatrixEdge New<TParent, TChild>()
|
|
||||||
{
|
|
||||||
return new InterfaceMatrixEdge(
|
|
||||||
typeof(TParent),
|
|
||||||
typeof(TChild),
|
|
||||||
InterfaceId<TParent>._id,
|
|
||||||
InterfaceId<TChild>._id);
|
|
||||||
}
|
|
||||||
public InterfaceMatrixEdge(Type parentType, Type childType, int parentID, int childID)
|
|
||||||
{
|
|
||||||
id = _increment++;
|
|
||||||
this.parentType = parentType;
|
|
||||||
this.childType = childType;
|
|
||||||
this.parentID = parentID;
|
|
||||||
this.childID = childID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal static class InterfaceId
|
|
||||||
{
|
{
|
||||||
internal static int _increment;
|
private EcsWorld _source;
|
||||||
}
|
private object[] _sourceForReflection;
|
||||||
internal static class InterfaceId<T>
|
private Type _type;
|
||||||
{
|
|
||||||
public static int _id = InterfaceId._increment++;
|
private IEcsHybridPoolInternal _targetTypePool;
|
||||||
|
private List<IEcsHybridPoolInternal> _relatedPools;
|
||||||
|
|
||||||
|
private static Type hybridPoolType = typeof(EcsHybridPool<>);
|
||||||
|
private static MethodInfo getHybridPoolMethod = typeof(EcsHybridPoolExtensions).GetMethod($"{nameof(EcsHybridPoolExtensions.GetPool)}", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
|
||||||
|
private static HashSet<Type> _hybridComponents = new HashSet<Type>();
|
||||||
|
static HybridMapping()
|
||||||
|
{
|
||||||
|
Type hybridComponentType = typeof(IEcsHybridComponent);
|
||||||
|
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
var types = assembly.GetTypes();
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
if (type.GetInterface(nameof(IEcsHybridComponent)) != null && type != hybridComponentType)
|
||||||
|
{
|
||||||
|
_hybridComponents.Add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static bool IsEcsHybridComponentType(Type type)
|
||||||
|
{
|
||||||
|
return _hybridComponents.Contains(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HybridMapping(EcsWorld source, Type type)
|
||||||
|
{
|
||||||
|
if (!type.IsClass)
|
||||||
|
throw new ArgumentException();
|
||||||
|
|
||||||
|
_source = source;
|
||||||
|
_type = type;
|
||||||
|
_relatedPools = new List<IEcsHybridPoolInternal>();
|
||||||
|
_sourceForReflection = new object[]{ source };
|
||||||
|
_targetTypePool = CreateHybridPool(type);
|
||||||
|
foreach (var item in type.GetInterfaces())
|
||||||
|
{
|
||||||
|
if(IsEcsHybridComponentType(item))
|
||||||
|
{
|
||||||
|
_relatedPools.Add(CreateHybridPool(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type baseType = type.BaseType;
|
||||||
|
while(baseType != typeof(object) && IsEcsHybridComponentType(baseType))
|
||||||
|
{
|
||||||
|
_relatedPools.Add(CreateHybridPool(baseType));
|
||||||
|
baseType = baseType.BaseType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private IEcsHybridPoolInternal CreateHybridPool(Type componentType)
|
||||||
|
{
|
||||||
|
//var x = (IEcsHybridPoolInternal)getHybridPoolMethod.MakeGenericMethod(componentType).Invoke(null, _sourceForReflection);
|
||||||
|
//Debug.Log("_" + x.ComponentID + "_" +x.ComponentType.Name);
|
||||||
|
//return x;
|
||||||
|
return (IEcsHybridPoolInternal)getHybridPoolMethod.MakeGenericMethod(componentType).Invoke(null, _sourceForReflection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEcsHybridPoolInternal GetTargetTypePool()
|
||||||
|
{
|
||||||
|
return _targetTypePool;
|
||||||
|
}
|
||||||
|
public List<IEcsHybridPoolInternal> GetPools()
|
||||||
|
{
|
||||||
|
return _relatedPools;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,22 +31,6 @@ namespace DCFApixels.DragonECS
|
|||||||
public EcsWorld World => _source;
|
public EcsWorld World => _source;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Init
|
|
||||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
|
||||||
{
|
|
||||||
_source = world;
|
|
||||||
_componentID = componentID;
|
|
||||||
|
|
||||||
const int capacity = 512;
|
|
||||||
|
|
||||||
_mapping = new int[world.Capacity];
|
|
||||||
_recycledItems = new int[128];
|
|
||||||
_recycledItemsCount = 0;
|
|
||||||
_items = new T[capacity];
|
|
||||||
_itemsCount = 0;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
public ref T Add(int entityID)
|
public ref T Add(int entityID)
|
||||||
{
|
{
|
||||||
@ -149,6 +133,19 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
|
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
||||||
|
{
|
||||||
|
_source = world;
|
||||||
|
_componentID = componentID;
|
||||||
|
|
||||||
|
const int capacity = 512;
|
||||||
|
|
||||||
|
_mapping = new int[world.Capacity];
|
||||||
|
_recycledItems = new int[128];
|
||||||
|
_recycledItemsCount = 0;
|
||||||
|
_items = new T[capacity];
|
||||||
|
_itemsCount = 0;
|
||||||
|
}
|
||||||
void IEcsPoolImplementation.OnWorldResize(int newSize)
|
void IEcsPoolImplementation.OnWorldResize(int newSize)
|
||||||
{
|
{
|
||||||
Array.Resize(ref _mapping, newSize);
|
Array.Resize(ref _mapping, newSize);
|
||||||
|
@ -26,17 +26,6 @@ namespace DCFApixels.DragonECS
|
|||||||
public EcsWorld World => _source;
|
public EcsWorld World => _source;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Init
|
|
||||||
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
|
||||||
{
|
|
||||||
_source = world;
|
|
||||||
_componentID = componentID;
|
|
||||||
|
|
||||||
_mapping = new bool[world.Capacity];
|
|
||||||
_count = 0;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Method
|
#region Method
|
||||||
public void Add(int entityID)
|
public void Add(int entityID)
|
||||||
{
|
{
|
||||||
@ -114,6 +103,14 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
|
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
|
||||||
|
{
|
||||||
|
_source = world;
|
||||||
|
_componentID = componentID;
|
||||||
|
|
||||||
|
_mapping = new bool[world.Capacity];
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
void IEcsPoolImplementation.OnWorldResize(int newSize)
|
void IEcsPoolImplementation.OnWorldResize(int newSize)
|
||||||
{
|
{
|
||||||
Array.Resize(ref _mapping, newSize);
|
Array.Resize(ref _mapping, newSize);
|
||||||
|
@ -1,31 +1,47 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS.Internal
|
||||||
{
|
{
|
||||||
namespace Internal
|
public static class EcsTypeCode
|
||||||
{
|
{
|
||||||
internal static class EcsTypeCode
|
private static readonly Dictionary<Type, int> _codes = new Dictionary<Type, int>();
|
||||||
|
private static int _incremetn = 1;
|
||||||
|
public static int Count => _codes.Count;
|
||||||
|
public static int Get(Type type)
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<Type, int> _codes = new Dictionary<Type, int>();
|
if (!_codes.TryGetValue(type, out int code))
|
||||||
private static int _incremetn = 1;
|
|
||||||
public static int Count => _codes.Count;
|
|
||||||
public static int Get(Type type)
|
|
||||||
{
|
{
|
||||||
if (!_codes.TryGetValue(type, out int code))
|
code = _incremetn++;
|
||||||
{
|
_codes.Add(type, code);
|
||||||
code = _incremetn++;
|
|
||||||
_codes.Add(type, code);
|
|
||||||
}
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static int Get<T>() => Cache<T>.code;
|
|
||||||
private static class Cache<T>
|
|
||||||
{
|
|
||||||
public static readonly int code = Get(typeof(T));
|
|
||||||
}
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int Get<T>() => EcsTypeCodeCache<T>.code;
|
||||||
|
public static bool Has(Type type) => _codes.ContainsKey(type);
|
||||||
|
public static bool Has<T>() => _codes.ContainsKey(typeof(T));
|
||||||
|
public static IEnumerable<TypeCodeInfo> GetDeclared() => _codes.Select(o => new TypeCodeInfo(o.Key, o.Value));
|
||||||
|
}
|
||||||
|
public static class EcsTypeCodeCache<T>
|
||||||
|
{
|
||||||
|
public static readonly int code = EcsTypeCode.Get(typeof(T));
|
||||||
|
}
|
||||||
|
public struct TypeCodeInfo
|
||||||
|
{
|
||||||
|
public Type type;
|
||||||
|
public int code;
|
||||||
|
public TypeCodeInfo(Type type, int code)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return this.AutoToString(false) + "\n\r";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user