Browse Source

Update Svelto.ECS

pull/109/head
Sebastiano Mandala 1 year ago
parent
commit
f57ce5389c
18 changed files with 211 additions and 151 deletions
  1. +1
    -1
      com.sebaslab.svelto.common
  2. +5
    -0
      com.sebaslab.svelto.ecs/CHANGELOG.md
  3. +0
    -100
      com.sebaslab.svelto.ecs/Core/ComponentBuilder.cs
  4. +52
    -0
      com.sebaslab.svelto.ecs/Core/ComponentID.cs
  5. +38
    -0
      com.sebaslab.svelto.ecs/Core/ComponentTypeID.cs
  6. +38
    -0
      com.sebaslab.svelto.ecs/Core/ComponentTypeMap.cs
  7. +1
    -1
      com.sebaslab.svelto.ecs/Core/EnginesRoot.GenericEntityFactory.cs
  8. +17
    -9
      com.sebaslab.svelto.ecs/Core/EntityDescriptor/DynamicEntityDescriptor.cs
  9. +1
    -1
      com.sebaslab.svelto.ecs/Core/EntityDescriptor/ExtendibleEntityDescriptor.cs
  10. +7
    -7
      com.sebaslab.svelto.ecs/Core/Filters/Legacy/EntitiesDB.LegacyFilters.cs
  11. +34
    -21
      com.sebaslab.svelto.ecs/Core/Groups/EntityDescriptorsWarmup.cs
  12. +0
    -6
      com.sebaslab.svelto.ecs/Core/IEntityFactory.cs
  13. +12
    -0
      com.sebaslab.svelto.ecs/Core/IEntitySerializationFactory.cs
  14. +1
    -1
      com.sebaslab.svelto.ecs/Extensions/Svelto/Legacy/EntitiesDBFiltersExtension.cs
  15. +1
    -1
      com.sebaslab.svelto.ecs/Serialization/DefaultVersioningFactory.cs
  16. +1
    -1
      com.sebaslab.svelto.ecs/Svelto.ECS.csproj
  17. +1
    -1
      com.sebaslab.svelto.ecs/package.json
  18. +1
    -1
      com.sebaslab.svelto.ecs/version.json

+ 1
- 1
com.sebaslab.svelto.common

@@ -1 +1 @@
Subproject commit 114ce56f5efe5b5a2a8326ef55587ca668e72503
Subproject commit b3b6ad7f922cfdac70d1ee5c28c580ddd451a1ff

+ 5
- 0
com.sebaslab.svelto.ecs/CHANGELOG.md View File

@@ -1,6 +1,11 @@
# Svelto.ECS Changelog
All notable changes to this project will be documented in this file. Changes are listed in random order of importance.

## [3.4.5] - 04-2023
* improved code after internal data refactoring and fixed some bugs
* Added static DynamicEntityDescriptor method to create a new DynamicEntityDescriptor without passing an array of components
* factory method to build entities without entity descriptor is now internal

## [3.4.4] - 04-2023

* refactored internal datastructures


+ 0
- 100
com.sebaslab.svelto.ecs/Core/ComponentBuilder.cs View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using DBC.ECS;
using Svelto.Common;
@@ -26,104 +24,6 @@ namespace Svelto.ECS
}
}

public static class BurstCompatibleCounter
{
public static int counter;
}

static public class ComponentTypeMap
{
static readonly FasterDictionary<RefWrapper<Type>, ComponentID> _componentTypeMap = new FasterDictionary<RefWrapper<Type>, ComponentID>();
static readonly FasterDictionary<ComponentID, Type> _reverseComponentTypeMap = new FasterDictionary<ComponentID, Type>();

public static void Add(Type type, ComponentID idData)
{
_componentTypeMap.Add(type, idData);
_reverseComponentTypeMap.Add(idData, type);
}

public static ComponentID FetchID(Type type)
{
return _componentTypeMap[type];
}

public static Type FetchType(ComponentID id)
{
return _reverseComponentTypeMap[id];
}
}

public class ComponentTypeID<T> where T : struct, _IInternalEntityComponent
{
static readonly SharedStaticWrapper<ComponentID, ComponentTypeID<T>> _id;

public static ComponentID id
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _id.Data;
}

//todo: any reason to not do this? If I don't, I cannot Create filters in ready functions and
//I have to remove the CreateFilter method
static ComponentTypeID()
{
Init();
}

#if UNITY_BURST
[Unity.Burst.BurstDiscard]
//SharedStatic values must be initialized from not burstified code
#endif
static void Init()
{
_id.Data = Interlocked.Increment(ref BurstCompatibleCounter.counter);
ComponentTypeMap.Add(typeof(T), id);
}
}

sealed class ComponentIDDebugProxy
{
public ComponentIDDebugProxy(ComponentID id)
{
this._id = id;
}
public Type type => ComponentTypeMap.FetchType(_id);

readonly ComponentID _id;
}
[DebuggerTypeProxy(typeof(ComponentIDDebugProxy))]
public struct ComponentID: IEquatable<ComponentID>
{
public static implicit operator int(ComponentID id)
{
return id._id;
}
public static implicit operator uint(ComponentID id)
{
return (uint)id._id;
}
public static implicit operator ComponentID(int id)
{
return new ComponentID() {_id = id};
}

public bool Equals(ComponentID other)
{
return _id == other._id;
}

public override int GetHashCode()
{
return _id;
}
int _id;
}

public class ComponentBuilder<T> : IComponentBuilder where T : struct, _IInternalEntityComponent
{
internal static readonly Type ENTITY_COMPONENT_TYPE;


+ 52
- 0
com.sebaslab.svelto.ecs/Core/ComponentID.cs View File

@@ -0,0 +1,52 @@
using System;
using System.Diagnostics;

namespace Svelto.ECS
{
sealed class ComponentIDDebugProxy
{
public ComponentIDDebugProxy(ComponentID id)
{
this._id = id;
}

public Type type => ComponentTypeMap.FetchType(_id);

readonly ComponentID _id;
}


[DebuggerTypeProxy(typeof(ComponentIDDebugProxy))]
public struct ComponentID: IEquatable<ComponentID>
{
public static implicit operator int(ComponentID id)
{
return id._id;
}

public static implicit operator uint(ComponentID id)
{
return (uint)id._id;
}

public static implicit operator ComponentID(int id)
{
return new ComponentID()
{
_id = id
};
}

public bool Equals(ComponentID other)
{
return _id == other._id;
}

public override int GetHashCode()
{
return _id;
}

int _id;
}
}

+ 38
- 0
com.sebaslab.svelto.ecs/Core/ComponentTypeID.cs View File

@@ -0,0 +1,38 @@
using System.Runtime.CompilerServices;
using System.Threading;
using Svelto.Common;
using Svelto.ECS.Internal;

namespace Svelto.ECS
{
public static class BurstCompatibleCounter
{
public static int counter;
}

public class ComponentTypeID<T> where T : struct, _IInternalEntityComponent
{
static readonly SharedStaticWrapper<ComponentID, ComponentTypeID<T>> _id;

public static ComponentID id
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _id.Data;
}

static ComponentTypeID()
{
Init();
}

#if UNITY_BURST
[Unity.Burst.BurstDiscard]
//SharedStatic values must be initialized from not burstified code
#endif
static void Init()
{
_id.Data = Interlocked.Increment(ref BurstCompatibleCounter.counter);
ComponentTypeMap.Add(typeof(T), id);
}
}
}

+ 38
- 0
com.sebaslab.svelto.ecs/Core/ComponentTypeMap.cs View File

@@ -0,0 +1,38 @@
using System;
using System.Runtime.CompilerServices;
using Svelto.DataStructures;

namespace Svelto.ECS
{
public static class ComponentTypeMap
{
static readonly FasterDictionary<RefWrapper<Type>, ComponentID> _componentTypeMap = new FasterDictionary<RefWrapper<Type>, ComponentID>();
static readonly FasterDictionary<ComponentID, Type> _reverseComponentTypeMap = new FasterDictionary<ComponentID, Type>();

public static void Add(Type type, ComponentID idData)
{
_componentTypeMap.Add(type, idData);
_reverseComponentTypeMap.Add(idData, type);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ComponentID FetchID(Type type)
{
if (_componentTypeMap.TryGetValue(type, out var index) == false)
{
//if warming up is working correctly, this should never happen
var componentType = typeof(ComponentTypeID<>).MakeGenericType(type);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(componentType.TypeHandle);
return _componentTypeMap[type];
}
return index;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Type FetchType(ComponentID id)
{
return _reverseComponentTypeMap[id];
}
}
}

+ 1
- 1
com.sebaslab.svelto.ecs/Core/EnginesRoot.GenericEntityFactory.cs View File

@@ -7,7 +7,7 @@ namespace Svelto.ECS
{
public partial class EnginesRoot
{
class GenericEntityFactory : IEntityFactory
class GenericEntityFactory : IEntityFactory, IEntitySerializationFactory
{
public GenericEntityFactory(EnginesRoot weakReference)
{


+ 17
- 9
com.sebaslab.svelto.ecs/Core/EntityDescriptor/DynamicEntityDescriptor.cs View File

@@ -14,40 +14,48 @@ namespace Svelto.ECS
/// <typeparam name="TType"></typeparam>
public struct DynamicEntityDescriptor<TType> : IDynamicEntityDescriptor where TType : IEntityDescriptor, new()
{
internal DynamicEntityDescriptor(bool isExtendible) : this()
public static DynamicEntityDescriptor<TType> CreateDynamicEntityDescriptor()
{
var entityDescriptor = new DynamicEntityDescriptor<TType>();
var defaultEntities = EntityDescriptorTemplate<TType>.realDescriptor.componentsToBuild;
var length = defaultEntities.Length;

if (FetchEntityInfoComponent(defaultEntities) == -1)
{
_componentsToBuild = new IComponentBuilder[length + 1];
entityDescriptor._componentsToBuild = new IComponentBuilder[length + 1];

Array.Copy(defaultEntities, 0, _componentsToBuild, 0, length);
Array.Copy(defaultEntities, 0, entityDescriptor._componentsToBuild, 0, length);
//assign it after otherwise the previous copy will overwrite the value in case the item
//is already present
_componentsToBuild[length] = new ComponentBuilder<EntityInfoComponent>(new EntityInfoComponent
entityDescriptor._componentsToBuild[length] = new ComponentBuilder<EntityInfoComponent>(new EntityInfoComponent
{
componentsToBuild = _componentsToBuild
componentsToBuild = entityDescriptor._componentsToBuild
});
}
else
{
_componentsToBuild = new IComponentBuilder[length];
entityDescriptor._componentsToBuild = new IComponentBuilder[length];

Array.Copy(defaultEntities, 0, _componentsToBuild, 0, length);
Array.Copy(defaultEntities, 0, entityDescriptor._componentsToBuild, 0, length);
}

return entityDescriptor;
}

public DynamicEntityDescriptor(IComponentBuilder[] extraEntityBuilders) : this(true)
public DynamicEntityDescriptor(IComponentBuilder[] extraEntityBuilders)
{
this = CreateDynamicEntityDescriptor();
var extraEntitiesLength = extraEntityBuilders.Length;

_componentsToBuild = Construct(extraEntitiesLength, extraEntityBuilders);
}

public DynamicEntityDescriptor(FasterList<IComponentBuilder> extraEntityBuilders) : this(true)
public DynamicEntityDescriptor(FasterList<IComponentBuilder> extraEntityBuilders)
{
this = CreateDynamicEntityDescriptor();
var extraEntities = extraEntityBuilders.ToArrayFast(out _);
var extraEntitiesLength = extraEntityBuilders.count;



+ 1
- 1
com.sebaslab.svelto.ecs/Core/EntityDescriptor/ExtendibleEntityDescriptor.cs View File

@@ -38,7 +38,7 @@ namespace Svelto.ECS

protected ExtendibleEntityDescriptor()
{
_dynamicDescriptor = new DynamicEntityDescriptor<TType>(true);
_dynamicDescriptor = DynamicEntityDescriptor<TType>.CreateDynamicEntityDescriptor();
}

protected ExtendibleEntityDescriptor<TType> ExtendWith<T>() where T : IEntityDescriptor, new()


+ 7
- 7
com.sebaslab.svelto.ecs/Core/Filters/Legacy/EntitiesDB.LegacyFilters.cs View File

@@ -127,6 +127,7 @@ namespace Svelto.ECS
}

public void ClearFilter<T>(int filterID, ExclusiveGroupStruct exclusiveGroupStruct)
where T : struct, _IInternalEntityComponent
{
if (_filtersLegacy.TryGetValue(ComponentTypeID<T>.id, out var fasterDictionary))
{
@@ -137,14 +138,14 @@ namespace Svelto.ECS
}
}

public void ClearFilters<T>(int filterID)
public void ClearFilters<T>(int filterID) where T : struct, _IInternalEntityComponent
{
if (_filtersLegacy.TryGetValue(ComponentTypeID<T>.id, out var fasterDictionary))
foreach (var filtersPerGroup in fasterDictionary)
filtersPerGroup.value.ClearFilter(filterID);
}

public void DisposeFilters<T>(ExclusiveGroupStruct exclusiveGroupStruct)
public void DisposeFilters<T>(ExclusiveGroupStruct exclusiveGroupStruct) where T : struct, _IInternalEntityComponent
{
if (_filtersLegacy.TryGetValue(ComponentTypeID<T>.id, out var fasterDictionary))
{
@@ -153,7 +154,7 @@ namespace Svelto.ECS
}
}

public void DisposeFilters<T>()
public void DisposeFilters<T>() where T : struct, _IInternalEntityComponent
{
if (_filtersLegacy.TryGetValue(ComponentTypeID<T>.id, out var fasterDictionary))
foreach (var filtersPerGroup in fasterDictionary)
@@ -162,7 +163,7 @@ namespace Svelto.ECS
_filtersLegacy.Remove(ComponentTypeID<T>.id);
}

public void DisposeFilterForGroup<T>(int resetFilterID, ExclusiveGroupStruct group)
public void DisposeFilterForGroup<T>(int resetFilterID, ExclusiveGroupStruct group) where T : struct, _IInternalEntityComponent
{
if (_filtersLegacy.TryGetValue(ComponentTypeID<T>.id, out var fasterDictionary))
fasterDictionary[@group].DisposeFilter(resetFilterID);
@@ -185,14 +186,13 @@ namespace Svelto.ECS

public bool AddEntityToFilter<N>(int filtersID, EGID egid, N mapper) where N : IEGIDMapper
{
ref var filter =
ref CreateOrGetFilterForGroup(filtersID, egid.groupID, new RefWrapperType(mapper.entityType));
ref var filter = ref CreateOrGetFilterForGroup(filtersID, egid.groupID, ComponentTypeMap.FetchID(mapper.entityType));

return filter.Add(egid.entityID, mapper);
}

internal ref LegacyFilterGroup CreateOrGetFilterForGroup(int filterID, ExclusiveGroupStruct groupID,
RefWrapperType refWrapper)
ComponentID refWrapper)
{
var fasterDictionary = _filtersLegacy.GetOrAdd(refWrapper,
() => new FasterDictionary<ExclusiveGroupStruct, LegacyGroupFilters>());


+ 34
- 21
com.sebaslab.svelto.ecs/Core/Groups/EntityDescriptorsWarmup.cs View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Svelto.ECS.Internal;

namespace Svelto.ECS
{
@@ -15,35 +16,47 @@ namespace Svelto.ECS
List<Assembly> assemblies = AssemblyUtility.GetCompatibleAssemblies();
foreach (Assembly assembly in assemblies)
{
var typeOfEntityDescriptors = typeof(IEntityDescriptor);
var typeOfEntityDescriptors = typeof(IEntityDescriptor);

foreach (Type type in AssemblyUtility.GetTypesSafe(assembly))
foreach (Type type in AssemblyUtility.GetTypesSafe(assembly))
{
if (type.IsInterface == false && typeOfEntityDescriptors.IsAssignableFrom(type)) //IsClass and IsSealed and IsAbstract means only static classes
{
if (typeOfEntityDescriptors.IsAssignableFrom(type)) //IsClass and IsSealed and IsAbstract means only static classes
try
{
//the main goal of this iteration is to warm up the component builders and descriptors
//note: I could have just instanced the entity descriptor, but in this way I will warm up the EntityDescriptorTemplate too
var warmup = typeof(EntityDescriptorTemplate<>).MakeGenericType(type);
try
{
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(warmup.TypeHandle);
}
catch
{
continue;
}

PropertyInfo field = warmup.GetProperty("descriptor", BindingFlags.Static | BindingFlags.Public);
object value = field.GetValue(null); // pass null because the field is static
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(warmup.TypeHandle);
}
catch (Exception e)
{
continue;
}
}
}
var typeOfComponents = typeof(_IInternalEntityComponent);

// cast the value to your descriptor type
IEntityDescriptor descriptor = (IEntityDescriptor)value;
foreach (IComponentBuilder component in descriptor.componentsToBuild)
{
var typeArguments = component.GetEntityComponentType();
var warmup2 = typeof(ComponentTypeID<>).MakeGenericType(typeArguments);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(warmup2.TypeHandle);
}
//the main goal of this iteration is to warm up the component IDs
foreach (Type type in AssemblyUtility.GetTypesSafe(assembly))
{
if (type.IsInterface == false && typeOfComponents.IsAssignableFrom(type)) //IsClass and IsSealed and IsAbstract means only static classes
{
try
{
var componentType = typeof(ComponentTypeID<>).MakeGenericType(type);
//is called only once ever, even if runs multiple times.
//this warms up the component builder. There could be different implementation of components builders for the same component type in theory
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(componentType.TypeHandle);
}
catch (Exception e)
{
continue;
}
}
}
}
}
}

+ 0
- 6
com.sebaslab.svelto.ecs/Core/IEntityFactory.cs View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;

namespace Svelto.ECS
@@ -52,11 +51,6 @@ namespace Svelto.ECS
EntityInitializer BuildEntity<T>(EGID egid, T entityDescriptor, IEnumerable<object> implementors = null,
[System.Runtime.CompilerServices.CallerMemberName] string caller = null) where T : IEntityDescriptor;

//Todo: analyze if this can be internal or just related to serialization
EntityInitializer BuildEntity(EGID egid, IComponentBuilder[] componentsToBuild, Type descriptorType,
IEnumerable<object> implementors = null,
[System.Runtime.CompilerServices.CallerMemberName] string caller = null);

#if UNITY_NATIVE
Svelto.ECS.Native.NativeEntityFactory ToNative<T>([System.Runtime.CompilerServices.CallerMemberName] string callerName
= null) where T : IEntityDescriptor, new();


+ 12
- 0
com.sebaslab.svelto.ecs/Core/IEntitySerializationFactory.cs View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;

namespace Svelto.ECS
{
interface IEntitySerializationFactory
{
EntityInitializer BuildEntity(EGID egid, IComponentBuilder[] componentsToBuild, Type descriptorType,
IEnumerable<object> implementors = null,
[System.Runtime.CompilerServices.CallerMemberName] string caller = null);
}
}

+ 1
- 1
com.sebaslab.svelto.ecs/Extensions/Svelto/Legacy/EntitiesDBFiltersExtension.cs View File

@@ -9,7 +9,7 @@ namespace Svelto.ECS
public static bool AddEntityToFilter<N>(this EntitiesDB.LegacyFilters legacyFilters, int filtersID, EGID egid, N mapper) where N : IEGIDMultiMapper
{
ref var filter =
ref legacyFilters.CreateOrGetFilterForGroup(filtersID, egid.groupID, new RefWrapperType(mapper.entityType));
ref legacyFilters.CreateOrGetFilterForGroup(filtersID, egid.groupID, ComponentTypeMap.FetchID(mapper.entityType));

return filter.Add(egid.entityID, mapper);
}


+ 1
- 1
com.sebaslab.svelto.ecs/Serialization/DefaultVersioningFactory.cs View File

@@ -16,7 +16,7 @@ namespace Svelto.ECS.Serialization
? entityDescriptor.componentsToSerialize
: entityDescriptor.componentsToBuild;

var initializer = factory.BuildEntity(egid, entityDescriptorEntitiesToSerialize, TypeCache<T>.type);
var initializer = (factory as IEntitySerializationFactory).BuildEntity(egid, entityDescriptorEntitiesToSerialize, TypeCache<T>.type);

entitySerialization.DeserializeEntityComponents(serializationData, entityDescriptor, ref initializer,
serializationType);


+ 1
- 1
com.sebaslab.svelto.ecs/Svelto.ECS.csproj View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>Svelto.ECS</AssemblyName>
<LangVersion>10</LangVersion>
<LangVersion>9</LangVersion>
<TargetFramework>netstandard2.1</TargetFramework>
<Company>Svelto</Company>
<AssemblyVersion>3.4</AssemblyVersion>


+ 1
- 1
com.sebaslab.svelto.ecs/package.json View File

@@ -19,7 +19,7 @@
"svelto.ecs"
],
"name": "com.sebaslab.svelto.ecs",
"version": "3.4.4",
"version": "3.4.5",
"type": "library",
"unity": "2020.3"
}

+ 1
- 1
com.sebaslab.svelto.ecs/version.json View File

@@ -1,3 +1,3 @@
{
"version": "3.4.4"
"version": "3.4.5"
}

Loading…
Cancel
Save