diff --git a/src/Debug/EcsDebugUtility.cs b/src/Debug/EcsDebugUtility.cs index 5565e8b..341d969 100644 --- a/src/Debug/EcsDebugUtility.cs +++ b/src/Debug/EcsDebugUtility.cs @@ -5,11 +5,14 @@ namespace DCFApixels.DragonECS { public static class EcsDebugUtility { + public static string GetGenericTypeFullName(int maxDepth = 2) => GetGenericTypeFullName(typeof(T), maxDepth); + public static string GetGenericTypeFullName(Type type, int maxDepth = 2) => GetGenericTypeNameInternal(type, maxDepth, true); public static string GetGenericTypeName(int maxDepth = 2) => GetGenericTypeName(typeof(T), maxDepth); - public static string GetGenericTypeName(Type type, int maxDepth = 2) + public static string GetGenericTypeName(Type type, int maxDepth = 2) => GetGenericTypeNameInternal(type, maxDepth, false); + private static string GetGenericTypeNameInternal(Type type, int maxDepth, bool isFull) { #if (DEBUG && !DISABLE_DEBUG) - string friendlyName = type.Name; + string friendlyName = isFull ? type.FullName : type.Name; if (!type.IsGenericType || maxDepth == 0) return friendlyName; @@ -21,7 +24,7 @@ namespace DCFApixels.DragonECS Type[] typeParameters = type.GetGenericArguments(); for (int i = 0; i < typeParameters.Length; ++i) { - string typeParamName = GetGenericTypeName(typeParameters[i], maxDepth - 1); + string typeParamName = GetGenericTypeNameInternal(typeParameters[i], maxDepth - 1, false);//чтобы строка не была слишком длинной, используются сокращенные имена для типов аргументов friendlyName += (i == 0 ? typeParamName : "," + typeParamName); } friendlyName += ">"; diff --git a/src/EcsGroup.cs b/src/EcsGroup.cs index 16a2159..0658ae1 100644 --- a/src/EcsGroup.cs +++ b/src/EcsGroup.cs @@ -1,13 +1,12 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS +using static DCFApixels.DragonECS.EcsGroup.ThrowHalper; +#endif namespace DCFApixels.DragonECS { -#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - using static EcsGroup.ThrowHalper; -#endif - [StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)] public readonly ref struct EcsReadonlyGroup { diff --git a/src/EcsRunner.cs b/src/EcsRunner.cs index d657be1..7f732b2 100644 --- a/src/EcsRunner.cs +++ b/src/EcsRunner.cs @@ -5,6 +5,7 @@ using System.Collections.ObjectModel; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; +using static DCFApixels.DragonECS.EcsDebugUtility; namespace DCFApixels.DragonECS { @@ -31,21 +32,19 @@ namespace DCFApixels.DragonECS [EditorBrowsable(EditorBrowsableState.Never)] public interface IEcsRunner { - public EcsPipeline Source { get; } - public Type Interface { get; } - public IList Targets { get; } - public object Filter { get; } - public bool IsHasFilter { get; } - public bool IsDestroyed { get; } - public bool IsEmpty { get; } - - public void Destroy(); + EcsPipeline Source { get; } + Type Interface { get; } + IList Targets { get; } + object Filter { get; } + bool IsHasFilter { get; } + bool IsDestroyed { get; } + bool IsEmpty { get; } + void Destroy(); } internal static class EcsRunnerActivator { private static Dictionary _runnerHandlerTypes; //interface base type/Runner handler type pairs; - static EcsRunnerActivator() { List delayedExceptions = new List(); @@ -59,24 +58,22 @@ namespace DCFApixels.DragonECS } #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - for (int i = 0; i < runnerHandlerTypes.Count; i++) - { - var e = CheckRunnerValide(runnerHandlerTypes[i]); - if (e != null) + for (int i = 0; i < runnerHandlerTypes.Count; i++) { - runnerHandlerTypes.RemoveAt(i--); - delayedExceptions.Add(e); + var e = CheckRunnerValide(runnerHandlerTypes[i]); + if (e != null) + { + runnerHandlerTypes.RemoveAt(i--); + delayedExceptions.Add(e); + } } - } #endif _runnerHandlerTypes = new Dictionary(); foreach (var item in runnerHandlerTypes) { Type interfaceType = item.BaseType.GenericTypeArguments[0]; -// if(!_runnerHandlerTypes.ContainsKey(interfaceType.GUID))//TODO это кажется костыль, изначально все работало без этого ифа - _runnerHandlerTypes.Add(interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType, item); + _runnerHandlerTypes.Add(interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType, item); } - if (delayedExceptions.Count > 0) { foreach (var item in delayedExceptions) EcsDebug.Print(EcsConsts.DEBUG_ERROR_TAG, item.Message); @@ -91,24 +88,23 @@ namespace DCFApixels.DragonECS if (type.ReflectedType != null) { - return new EcsRunnerImplementationException($"{type.FullName}.ReflectedType must be Null, but equal to {type.ReflectedType.FullName}."); + return new EcsRunnerImplementationException($"{GetGenericTypeFullName(type, 1)}.ReflectedType must be Null, but equal to {GetGenericTypeFullName(type.ReflectedType, 1)}."); } if (!baseTypeArgument.IsInterface) { - return new EcsRunnerImplementationException($"Argument T of class EcsRunner, can only be an inetrface.The {baseTypeArgument.FullName} type is not an interface."); + return new EcsRunnerImplementationException($"Argument T of class EcsRunner, can only be an inetrface. The {GetGenericTypeFullName(baseTypeArgument, 1)} type is not an interface."); } var interfaces = type.GetInterfaces(); if (!interfaces.Any(o => o == baseTypeArgument)) { - return new EcsRunnerImplementationException($"Runner {type.FullName} does not implement interface {baseTypeArgument.FullName}."); + return new EcsRunnerImplementationException($"Runner {GetGenericTypeFullName(type, 1)} does not implement interface {GetGenericTypeFullName(baseTypeArgument, 1)}."); } return null; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void InitFor() where TInterface : IEcsSystem { @@ -116,7 +112,7 @@ namespace DCFApixels.DragonECS if (!_runnerHandlerTypes.TryGetValue(interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType, out Type runnerType)) { - throw new Exception(); + throw new EcsRunnerImplementationException($"There is no implementation of a runner for the {GetGenericTypeFullName(1)} interface."); } if (interfaceType.IsGenericType) { @@ -135,22 +131,22 @@ namespace DCFApixels.DragonECS internal static void Register(Type subclass) { #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS - if (_subclass != null) - { - throw new EcsRunnerImplementationException($"The Runner<{typeof(TInterface).FullName}> can have only one implementing subclass"); - } + if (_subclass != null) + { + throw new EcsRunnerImplementationException($"The Runner<{typeof(TInterface).FullName}> can have only one implementing subclass"); + } - Type interfaceType = typeof(TInterface); + Type interfaceType = typeof(TInterface); - var interfaces = interfaceType.GetInterfaces(); - if (interfaceType.IsInterface == false) - { - throw new ArgumentException($"{typeof(TInterface).FullName} is not interface"); - } - if (interfaces.Length != 1 || interfaces[0] != typeof(IEcsSystem)) - { - throw new ArgumentException($"{typeof(TInterface).FullName} does not directly inherit the {nameof(IEcsSystem)} interface"); - } + var interfaces = interfaceType.GetInterfaces(); + if (interfaceType.IsInterface == false) + { + throw new ArgumentException($"{typeof(TInterface).FullName} is not interface"); + } + if (interfaces.Length != 1 || interfaces[0] != typeof(IEcsSystem)) + { + throw new ArgumentException($"{typeof(TInterface).FullName} does not directly inherit the {nameof(IEcsSystem)} interface"); + } #endif _subclass = subclass; } @@ -192,9 +188,7 @@ namespace DCFApixels.DragonECS #region Instantiate private static TInterface Instantiate(EcsPipeline source, TInterface[] targets, bool isHasFilter, object filter) { - if (_subclass == null) - EcsRunnerActivator.InitFor(); - + if (_subclass == null) EcsRunnerActivator.InitFor(); var instance = (EcsRunner)Activator.CreateInstance(_subclass); return (TInterface)(IEcsSystem)instance.Set(source, targets, isHasFilter, filter); } @@ -235,7 +229,6 @@ namespace DCFApixels.DragonECS OnSetup(); return this; } - internal void Rebuild() { if (_isHasFilter) @@ -243,7 +236,6 @@ namespace DCFApixels.DragonECS else Set(_source, FilterSystems(_source.AllSystems, _filter), _isHasFilter, _filter); } - public void Destroy() { _isDestroyed = true; @@ -254,11 +246,11 @@ namespace DCFApixels.DragonECS _filter = null; OnDestroy(); } - protected virtual void OnSetup() { } protected virtual void OnDestroy() { } } } + #region Extensions public static class EcsRunner { diff --git a/src/entlong.cs b/src/entlong.cs index cb1f37c..f2fd5ba 100644 --- a/src/entlong.cs +++ b/src/entlong.cs @@ -1,4 +1,5 @@ -using System; +#pragma warning disable IDE1006 +using System; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -6,9 +7,7 @@ using System.Runtime.InteropServices; namespace DCFApixels.DragonECS { using static entlong.ThrowHalper; - // uniqueID - 32 bits - // gen - 16 bits - // world - 16 bits + // [ id 32 | gen 16 | world 16 ] /// Strong identifier/Permanent entity identifier [StructLayout(LayoutKind.Explicit, Pack = 2, Size = 8)] public readonly struct entlong : IEquatable, IEquatable @@ -34,12 +33,6 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get => this == NULL; } - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsNotNull - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => this != NULL; - } [EditorBrowsable(EditorBrowsableState.Never)] public int ID @@ -135,7 +128,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() => unchecked((int)full) ^ (int)(full >> 32); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override string ToString() => $"entity(id:{id} g:{gen} w:{world} {(IsAlive ? "alive" : "not alive")})"; + public override string ToString() => $"entity(id:{id} g:{gen} w:{world} {(IsNull ? "null" : IsAlive ? "alive" : "not alive")})"; [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool Equals(object obj) => obj is entlong other && full == other.full; #endregion @@ -159,9 +152,9 @@ namespace DCFApixels.DragonECS public static void ThrowIsNotAlive(entlong entity) { if (entity.IsNull) - throw new EcsFrameworkException("The entity identifier is null."); + throw new EcsFrameworkException($"The {entity} is null."); else - throw new EcsFrameworkException("The entity is not alive."); + throw new EcsFrameworkException($"The {entity} is not alive."); } } #endregion