entity structs cannot support strings anymore (use ECSString instead)tags/2.8
@@ -36,8 +36,6 @@ public static partial class ExtensionMethods | |||
public static void ProjectOnPlane(ref this float3 vector, in float3 planeNormal) | |||
{ | |||
var num1 = math.dot(planeNormal,planeNormal); | |||
if ((double) num1 < (double) Mathf.Epsilon) | |||
return; | |||
var num2 = math.dot(vector,planeNormal) / num1; | |||
vector.x -= planeNormal.x * num2; | |||
@@ -3,10 +3,20 @@ namespace Svelto.ECS.Experimental | |||
public struct ECSString | |||
{ | |||
internal uint id; | |||
ECSString(uint toEcs) | |||
{ | |||
id = toEcs; | |||
} | |||
public static implicit operator string(ECSString ecsString) | |||
{ | |||
return ResourcesECSDB<string>.FromECS(ecsString.id); | |||
} | |||
public static implicit operator ECSString(string text) | |||
{ | |||
return new ECSString(ResourcesECSDB<string>.ToECS(text)); | |||
} | |||
} | |||
} |
@@ -2,8 +2,7 @@ | |||
using System.Collections.Generic; | |||
using System.Runtime.CompilerServices; | |||
using Svelto.Common; | |||
using Svelto.Common.Internal; | |||
using Svelto.DataStructures; | |||
using Svelto.DataStructures; | |||
using Svelto.DataStructures.Experimental; | |||
namespace Svelto.ECS.Internal | |||
@@ -14,17 +13,15 @@ namespace Svelto.ECS.Internal | |||
ITypeSafeDictionary Create(); | |||
void RemoveEntitiesFromEngines( | |||
Dictionary<Type, FasterList<IEngine>> entityViewEnginesDB, | |||
ref PlatformProfiler profiler); | |||
Dictionary<Type, FasterList<IEngine>> entityViewEnginesDB, in PlatformProfiler profiler); | |||
void MoveEntityFromDictionaryAndEngines(EGID fromEntityGid, EGID? toEntityID, ITypeSafeDictionary toGroup, | |||
Dictionary<Type, FasterList<IEngine>> engines, | |||
ref PlatformProfiler profiler); | |||
Dictionary<Type, FasterList<IEngine>> engines, in PlatformProfiler profiler); | |||
void AddEntitiesFromDictionary(ITypeSafeDictionary entitiesToSubmit, uint groupId); | |||
void AddEntitiesToEngines(Dictionary<Type, FasterList<IEngine>> entityViewEnginesDb, | |||
ITypeSafeDictionary realDic, ref PlatformProfiler profiler); | |||
ITypeSafeDictionary realDic, in PlatformProfiler profiler); | |||
void SetCapacity(uint size); | |||
void Trim(); | |||
@@ -32,7 +29,8 @@ namespace Svelto.ECS.Internal | |||
bool Has(uint entityIdEntityId); | |||
} | |||
class TypeSafeDictionary<TValue> : FasterDictionary<uint, TValue>, ITypeSafeDictionary where TValue : struct, IEntityStruct | |||
class TypeSafeDictionary<TValue> : FasterDictionary<uint, TValue>, | |||
ITypeSafeDictionary where TValue : struct, IEntityStruct | |||
{ | |||
static readonly Type _type = typeof(TValue); | |||
static readonly string _typeName = _type.Name; | |||
@@ -70,29 +68,28 @@ namespace Svelto.ECS.Internal | |||
public void AddEntitiesToEngines( | |||
Dictionary<Type, FasterList<IEngine>> entityViewEnginesDB, | |||
ITypeSafeDictionary realDic, ref PlatformProfiler profiler) | |||
ITypeSafeDictionary realDic, in PlatformProfiler profiler) | |||
{ | |||
foreach (var value in this) | |||
{ | |||
var typeSafeDictionary = realDic as TypeSafeDictionary<TValue>; | |||
AddEntityViewToEngines(entityViewEnginesDB, ref typeSafeDictionary.GetValueByRef(value.Key), null, | |||
ref profiler); | |||
in profiler); | |||
} | |||
} | |||
public bool Has(uint entityIdEntityId) { return ContainsKey(entityIdEntityId); } | |||
public void MoveEntityFromDictionaryAndEngines(EGID fromEntityGid, EGID? toEntityID, | |||
ITypeSafeDictionary toGroup, | |||
Dictionary<Type, FasterList<IEngine>> engines, | |||
ref PlatformProfiler profiler) | |||
ITypeSafeDictionary toGroup, Dictionary<Type, FasterList<IEngine>> engines, | |||
in PlatformProfiler profiler) | |||
{ | |||
var valueIndex = GetValueIndex(fromEntityGid.entityID); | |||
if (toGroup != null) | |||
{ | |||
RemoveEntityViewFromEngines(engines, ref _values[valueIndex], fromEntityGid.groupID, ref profiler); | |||
RemoveEntityViewFromEngines(engines, ref _values[valueIndex], fromEntityGid.groupID, in profiler); | |||
var toGroupCasted = toGroup as TypeSafeDictionary<TValue>; | |||
ref var entity = ref _values[valueIndex]; | |||
@@ -114,10 +111,10 @@ namespace Svelto.ECS.Internal | |||
var index = toGroupCasted.Add(fromEntityGid.entityID, ref entity); | |||
AddEntityViewToEngines(engines, ref toGroupCasted._values[index], previousGroup, | |||
ref profiler); | |||
in profiler); | |||
} | |||
else | |||
RemoveEntityViewFromEngines(engines, ref _values[valueIndex], null, ref profiler); | |||
RemoveEntityViewFromEngines(engines, ref _values[valueIndex], null, in profiler); | |||
Remove(fromEntityGid.entityID); | |||
@@ -125,20 +122,20 @@ namespace Svelto.ECS.Internal | |||
public void RemoveEntitiesFromEngines( | |||
Dictionary<Type, FasterList<IEngine>> entityViewEnginesDB, | |||
ref PlatformProfiler profiler) | |||
in PlatformProfiler profiler) | |||
{ | |||
var values = GetValuesArray(out var count); | |||
for (var i = 0; i < count; i++) | |||
RemoveEntityViewFromEngines(entityViewEnginesDB, ref values[i], null, ref profiler); | |||
RemoveEntityViewFromEngines(entityViewEnginesDB, ref values[i], null, in profiler); | |||
} | |||
public ITypeSafeDictionary Create() { return new TypeSafeDictionary<TValue>(); } | |||
void AddEntityViewToEngines(Dictionary<Type, FasterList<IEngine>> entityViewEnginesDB, | |||
ref TValue entity, | |||
ExclusiveGroup.ExclusiveGroupStruct? previousGroup, | |||
ref PlatformProfiler profiler) | |||
ref TValue entity, | |||
ExclusiveGroup.ExclusiveGroupStruct? previousGroup, | |||
in PlatformProfiler profiler) | |||
{ | |||
//get all the engines linked to TValue | |||
if (!entityViewEnginesDB.TryGetValue(_type, out var entityViewsEngines)) return; | |||
@@ -179,8 +176,7 @@ namespace Svelto.ECS.Internal | |||
static void RemoveEntityViewFromEngines( | |||
Dictionary<Type, FasterList<IEngine>> entityViewEnginesDB, ref TValue entity, | |||
ExclusiveGroup.ExclusiveGroupStruct? previousGroup, | |||
ref PlatformProfiler profiler) | |||
ExclusiveGroup.ExclusiveGroupStruct? previousGroup, in PlatformProfiler profiler) | |||
{ | |||
if (!entityViewEnginesDB.TryGetValue(_type, out var entityViewsEngines)) return; | |||
@@ -2,6 +2,12 @@ using System; | |||
namespace Svelto.ECS | |||
{ | |||
/// <summary> | |||
/// DynamicEntityDescriptor can be used to add entity views to an existing EntityDescriptor that act as flags, | |||
/// at building time. | |||
/// This method allocates, so it shouldn't be abused | |||
/// </summary> | |||
/// <typeparam name="TType"></typeparam> | |||
public struct DynamicEntityDescriptor<TType>:IEntityDescriptor where TType : IEntityDescriptor, new() | |||
{ | |||
public DynamicEntityDescriptor(IEntityBuilder[] extraEntities) | |||
@@ -16,15 +16,14 @@ namespace Svelto.ECS | |||
/// </summary> | |||
public void Dispose() | |||
{ | |||
var profiler = new PlatformProfiler(); | |||
using (profiler.StartNewSession("Final Dispose")) | |||
using (var profiler = new PlatformProfiler("Final Dispose")) | |||
{ | |||
foreach (var groups in _groupEntityDB) | |||
foreach (var entityList in groups.Value) | |||
{ | |||
try | |||
{ | |||
entityList.Value.RemoveEntitiesFromEngines(_reactiveEnginesAddRemove, ref profiler); | |||
entityList.Value.RemoveEntitiesFromEngines(_reactiveEnginesAddRemove, profiler); | |||
} | |||
catch (Exception e) | |||
{ | |||
@@ -136,8 +135,7 @@ namespace Svelto.ECS | |||
/// | |||
void MoveEntity(IEntityBuilder[] entityBuilders, EGID fromEntityGID, Type originalDescriptorType, EGID? toEntityGID) | |||
{ | |||
var profiler = new PlatformProfiler(); | |||
using (profiler.StartNewSession("Move Entity")) | |||
using (var sampler = new PlatformProfiler("Move Entity")) | |||
{ | |||
//for each entity view generated by the entity descriptor | |||
if (_groupEntityDB.TryGetValue(fromEntityGID.groupID, out var fromGroup) == false) | |||
@@ -167,7 +165,7 @@ namespace Svelto.ECS | |||
for (int i = 0; i < entitiesToMove.Length; i++) | |||
MoveEntityView(fromEntityGID, toEntityGID, toGroup, ref fromGroup, | |||
entitiesToMove[i].GetEntityType(), profiler); | |||
entitiesToMove[i].GetEntityType(), sampler); | |||
} | |||
//otherwise it's a normal static entity descriptor | |||
else | |||
@@ -191,13 +189,13 @@ namespace Svelto.ECS | |||
for (var i = 0; i < entityBuilders.Length; i++) | |||
MoveEntityView(fromEntityGID, toEntityGID, toGroup, ref fromGroup, | |||
entityBuilders[i].GetEntityType(), profiler); | |||
entityBuilders[i].GetEntityType(), sampler); | |||
} | |||
} | |||
} | |||
void MoveEntityView(EGID entityGID, EGID? toEntityGID, Dictionary<Type, ITypeSafeDictionary> toGroup, | |||
ref Dictionary<Type, ITypeSafeDictionary> fromGroup, Type entityViewType, PlatformProfiler profiler) | |||
ref Dictionary<Type, ITypeSafeDictionary> fromGroup, Type entityViewType, in PlatformProfiler profiler) | |||
{ | |||
if (fromGroup.TryGetValue(entityViewType, out var fromTypeSafeDictionary) == false) | |||
{ | |||
@@ -231,7 +229,7 @@ namespace Svelto.ECS | |||
toEntitiesDictionary, | |||
toEntityGID == null ? _reactiveEnginesAddRemove : | |||
_reactiveEnginesSwap, | |||
ref profiler); | |||
in profiler); | |||
if (fromTypeSafeDictionary.Count == 0) //clean up | |||
{ | |||
@@ -263,14 +261,13 @@ namespace Svelto.ECS | |||
void RemoveGroupAndEntitiesFromDB(uint groupID) | |||
{ | |||
var profiler = new PlatformProfiler(); | |||
using (profiler.StartNewSession("Remove Group")) | |||
using (var profiler = new PlatformProfiler("Remove Group")) | |||
{ | |||
var dictionariesOfEntities = _groupEntityDB[groupID]; | |||
foreach (var dictionaryOfEntities in dictionariesOfEntities) | |||
{ | |||
var platformProfiler = profiler; | |||
dictionaryOfEntities.Value.RemoveEntitiesFromEngines(_reactiveEnginesAddRemove, ref platformProfiler); | |||
dictionaryOfEntities.Value.RemoveEntitiesFromEngines(_reactiveEnginesAddRemove, platformProfiler); | |||
var groupedGroupOfEntities = _groupsPerEntity[dictionaryOfEntities.Key]; | |||
groupedGroupOfEntities.Remove(groupID); | |||
} | |||
@@ -14,8 +14,7 @@ namespace Svelto.ECS | |||
void SubmitEntityViews() | |||
{ | |||
var profiler = new PlatformProfiler(); | |||
using (profiler.StartNewSession("Svelto.ECS - Entities Submission")) | |||
using (var profiler = new PlatformProfiler("Svelto.ECS - Entities Submission")) | |||
{ | |||
if (_entitiesOperations.Count > 0) | |||
{ | |||
@@ -102,7 +101,7 @@ namespace Svelto.ECS | |||
} | |||
void AddEntityViewsToTheDBAndSuitableEngines(DoubleBufferedEntitiesToAdd dbgroupsOfEntitiesToSubmit, | |||
PlatformProfiler profiler) | |||
in PlatformProfiler profiler) | |||
{ | |||
//each group is indexed by entity view type. for each type there is a dictionary indexed by entityID | |||
var groupsOfEntitiesToSubmit = dbgroupsOfEntitiesToSubmit.other; | |||
@@ -148,7 +147,7 @@ namespace Svelto.ECS | |||
{ | |||
var realDic = groupDB[entityViewsPerType.Key]; | |||
entityViewsPerType.Value.AddEntitiesToEngines(_reactiveEnginesAddRemove, realDic, ref profiler); | |||
entityViewsPerType.Value.AddEntitiesToEngines(_reactiveEnginesAddRemove, realDic, in profiler); | |||
} | |||
} | |||
} | |||
@@ -29,8 +29,6 @@ namespace Svelto.ECS | |||
var field = fields[i]; | |||
var fieldFieldType = field.FieldType; | |||
if (fieldFieldType == STRINGTYPE) continue; | |||
SubCheckFields(fieldFieldType); | |||
} | |||
} | |||
@@ -2,6 +2,7 @@ using System; | |||
using System.Collections.Concurrent; | |||
using System.Collections.Generic; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS.Internal; | |||
namespace Svelto.ECS | |||
{ | |||
@@ -14,27 +15,27 @@ namespace Svelto.ECS | |||
/// just the current state | |||
/// - you want a thread-safe way to read entity states, which includes all the state changes and not the last | |||
/// one only | |||
/// - you want to communicate between EnginesRoots | |||
/// - you want to communicate between EnginesRoots | |||
/// </summary> | |||
class EntitiesStream | |||
{ | |||
internal Consumer<T> GenerateConsumer<T>(string name, int capacity) where T : unmanaged, IEntityStruct | |||
{ | |||
if (_streams.ContainsKey(typeof(T)) == false) _streams[typeof(T)] = new EntityStream<T>(); | |||
return (_streams[typeof(T)] as EntityStream<T>).GenerateConsumer(name, capacity); | |||
} | |||
internal void PublishEntity<T>(ref T entity) where T : unmanaged, IEntityStruct | |||
{ | |||
if (_streams.TryGetValue(typeof(T), out var typeSafeStream)) | |||
if (_streams.TryGetValue(typeof(T), out var typeSafeStream)) | |||
(typeSafeStream as EntityStream<T>).PublishEntity(ref entity); | |||
else | |||
Console.LogWarning("No Consumers are waiting for this entity to change " | |||
.FastConcat(typeof(T).ToString())); | |||
Console.LogWarningDebug("No Consumers are waiting for this entity to change ", typeof(T)); | |||
} | |||
readonly ConcurrentDictionary<Type, ITypeSafeStream> _streams = new ConcurrentDictionary<Type, ITypeSafeStream>(); | |||
readonly ConcurrentDictionary<Type, ITypeSafeStream> _streams = | |||
new ConcurrentDictionary<Type, ITypeSafeStream>(); | |||
} | |||
interface ITypeSafeStream | |||
@@ -54,10 +55,10 @@ namespace Svelto.ECS | |||
_buffers.Add(consumer); | |||
return consumer; | |||
} | |||
public void RemoveConsumer(Consumer<T> consumer) | |||
{ | |||
_buffers.UnorderedRemove(consumer); | |||
_buffers.UnorderedRemove(consumer); | |||
} | |||
readonly FasterListThreadSafe<Consumer<T>> _buffers = new FasterListThreadSafe<Consumer<T>>(); | |||
@@ -77,20 +78,15 @@ namespace Svelto.ECS | |||
_ringBuffer.Enqueue(ref entity, _name); | |||
} | |||
/// <summary> | |||
/// this can be better, I probably would need to get the group regardless if it supports EGID or not | |||
/// </summary> | |||
/// <param name="group"></param> | |||
/// <param name="entity"></param> | |||
/// <returns></returns> | |||
public bool TryDequeue(ExclusiveGroup group, out T entity) | |||
{ | |||
if (_ringBuffer.TryDequeue(out entity, _name) == true) | |||
{ | |||
if (EntityBuilder<T>.HAS_EGID) | |||
return (entity as INeedEGID).ID.groupID == @group; | |||
return true; | |||
throw new ECSException( | |||
"When an exclusive group is defined, TryDeque must operate on an entity with EGID"); | |||
} | |||
return false; | |||
@@ -99,10 +95,10 @@ namespace Svelto.ECS | |||
public bool TryDequeue(out T entity) { return _ringBuffer.TryDequeue(out entity, _name); } | |||
public void Flush() { _ringBuffer.Reset(); } | |||
public void Dispose() { _stream.RemoveConsumer(this); } | |||
readonly RingBuffer<T> _ringBuffer; | |||
readonly EntityStream<T> _stream; | |||
readonly string _name; | |||
} | |||
} | |||
} |
@@ -1,5 +1,10 @@ | |||
namespace Svelto.ECS | |||
{ | |||
/// <summary> | |||
/// Inherit from an ExtendibleEntityDescriptor to extend a base entity descriptor that can be used | |||
/// to swap and remove specialized entities from abstract engines | |||
/// </summary> | |||
/// <typeparam name="TType"></typeparam> | |||
public abstract class ExtendibleEntityDescriptor<TType>:IEntityDescriptor where TType : IEntityDescriptor, new() | |||
{ | |||
protected ExtendibleEntityDescriptor(IEntityBuilder[] extraEntities) | |||
@@ -7,7 +12,7 @@ namespace Svelto.ECS | |||
_dynamicDescriptor = new DynamicEntityDescriptor<TType>(extraEntities); | |||
} | |||
public IEntityBuilder[] entitiesToBuild { get { return _dynamicDescriptor.entitiesToBuild; } } | |||
public IEntityBuilder[] entitiesToBuild => _dynamicDescriptor.entitiesToBuild; | |||
readonly DynamicEntityDescriptor<TType> _dynamicDescriptor; | |||
} |
@@ -9,7 +9,7 @@ namespace Svelto.ECS.Unity | |||
{ | |||
var holder = Create<T>(new EGID(startIndex++, group), contextHolder, factory); | |||
var childs = contextHolder.GetComponentsInChildren<IEntityDescriptorHolder>(true); | |||
foreach (var child in childs) | |||
{ | |||
if (child.GetType() != typeof(T)) | |||
@@ -18,10 +18,10 @@ namespace Svelto.ECS.Unity | |||
startIndex = InternalBuildAll(startIndex, child, factory, group, childImplementors); | |||
} | |||
} | |||
return holder; | |||
} | |||
public static T Create<T>(EGID ID, Transform contextHolder, | |||
IEntityFactory factory) where T : MonoBehaviour, IEntityDescriptorHolder | |||
{ | |||
@@ -32,7 +32,16 @@ namespace Svelto.ECS.Unity | |||
return holder; | |||
} | |||
public static EntityStructInitializer CreateWithEntity<T>(EGID ID, Transform contextHolder, | |||
IEntityFactory factory, out T holder) where T : MonoBehaviour, IEntityDescriptorHolder | |||
{ | |||
holder = contextHolder.GetComponentInChildren<T>(true); | |||
var implementors = holder.GetComponents<IImplementor>(); | |||
return factory.BuildEntity(ID, holder.GetDescriptor(), implementors); | |||
} | |||
public static uint CreateAll<T>(uint startIndex, ExclusiveGroup group, Transform contextHolder, | |||
IEntityFactory factory) where T : MonoBehaviour, IEntityDescriptorHolder | |||
{ | |||
@@ -47,11 +56,11 @@ namespace Svelto.ECS.Unity | |||
return startIndex; | |||
} | |||
static uint InternalBuildAll(uint startIndex, IEntityDescriptorHolder descriptorHolder, IEntityFactory factory, ExclusiveGroup group, IImplementor[] implementors) | |||
{ | |||
ExclusiveGroup.ExclusiveGroupStruct realGroup = group; | |||
if (string.IsNullOrEmpty(descriptorHolder.groupName) == false) | |||
realGroup = ExclusiveGroup.Search(descriptorHolder.groupName); | |||
@@ -61,13 +70,13 @@ namespace Svelto.ECS.Unity | |||
egid = new EGID(startIndex++, realGroup); | |||
else | |||
egid = new EGID(holderId, realGroup); | |||
var init = factory.BuildEntity(egid, descriptorHolder.GetDescriptor(), implementors); | |||
init.Init(new EntityHierarchyStruct(group)); | |||
return startIndex; | |||
} | |||
} | |||
} | |||
} | |||
#endif |