using System.Runtime.CompilerServices;
using Svelto.Common;
using Svelto.DataStructures;
using Svelto.ECS.Internal;
namespace Svelto.ECS
{
public partial class EnginesRoot
{
///
/// todo: EnginesRoot was a weakreference to give the change to inject
/// entity functions from other engines root. It probably should be reverted
///
class GenericEntityFunctions : IEntityFunctions
{
internal GenericEntityFunctions(EnginesRoot weakReference)
{
_enginesRoot = new Svelto.DataStructures.WeakReference(weakReference);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveEntity(uint entityID, ExclusiveBuildGroup groupID, [CallerMemberName] string memberName = "") where T :
IEntityDescriptor, new()
{
RemoveEntity(new EGID(entityID, groupID), memberName);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveEntity(EGID entityEGID, [CallerMemberName] string memberName = "") where T : IEntityDescriptor, new()
{
DBC.ECS.Check.Require(entityEGID.groupID != 0, "invalid group detected");
var descriptorComponentsToBuild = EntityDescriptorTemplate.descriptor.componentsToBuild;
_enginesRoot.Target.CheckRemoveEntityID(entityEGID, TypeCache.type, memberName);
_enginesRoot.Target.QueueEntitySubmitOperation(
new EntitySubmitOperation(EntitySubmitOperationType.Remove, entityEGID, entityEGID,
descriptorComponentsToBuild));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveEntitiesFromGroup(ExclusiveBuildGroup groupID)
{
DBC.ECS.Check.Require(groupID != 0, "invalid group detected");
_enginesRoot.Target.RemoveGroupID(groupID);
_enginesRoot.Target.QueueEntitySubmitOperation(
new EntitySubmitOperation(EntitySubmitOperationType.RemoveGroup, new EGID(0, groupID), new EGID()));
}
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// void RemoveAllEntities(ExclusiveGroup group)
// where D : IEntityDescriptor, new() where S : unmanaged, IEntityComponent
// {
// var targetEntitiesDB = _enginesRoot.Target._entitiesDB;
// var (buffer, count) = targetEntitiesDB.QueryEntities(@group);
// for (uint i = 0; i < count; ++i)
// {
// RemoveEntity(new EGID(i, group));
// }
// }
//
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// void RemoveAllEntities()
// where D : IEntityDescriptor, new() where S : unmanaged, IEntityComponent
// {
// var targetEntitiesDB = _enginesRoot.Target._entitiesDB;
// foreach (var ((buffer, count), exclusiveGroupStruct) in targetEntitiesDB.QueryEntities())
// for (uint i = 0; i < count; ++i)
// {
// RemoveEntity(new EGID(i, exclusiveGroupStruct));
// }
// }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SwapEntitiesInGroup(ExclusiveBuildGroup fromGroupID, ExclusiveBuildGroup toGroupID)
where T : IEntityDescriptor, new()
{
if (_enginesRoot.Target._groupEntityComponentsDB.TryGetValue(
fromGroupID.group, out FasterDictionary entitiesInGroupPerType)
== true)
{
#if DEBUG && !PROFILE_SVELTO
IComponentBuilder[] components = EntityDescriptorTemplate.descriptor.componentsToBuild;
var dictionary = entitiesInGroupPerType[new RefWrapperType(components[0].GetEntityComponentType())];
dictionary.KeysEvaluator((key) =>
{
_enginesRoot.Target.CheckRemoveEntityID(new EGID(key, fromGroupID), TypeCache.type);
_enginesRoot.Target.CheckAddEntityID(new EGID(key, toGroupID), TypeCache.type);
});
#endif
_enginesRoot.Target.QueueEntitySubmitOperation(
new EntitySubmitOperation(EntitySubmitOperationType.SwapGroup, new EGID(0, fromGroupID)
, new EGID(0, toGroupID)));
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SwapEntityGroup(uint entityID, ExclusiveBuildGroup fromGroupID,
ExclusiveBuildGroup toGroupID)
where T : IEntityDescriptor, new()
{
SwapEntityGroup(new EGID(entityID, fromGroupID), toGroupID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SwapEntityGroup(EGID fromID, ExclusiveBuildGroup toGroupID)
where T : IEntityDescriptor, new()
{
SwapEntityGroup(fromID, new EGID(fromID.entityID, (uint) toGroupID));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SwapEntityGroup(EGID fromID, ExclusiveBuildGroup toGroupID
, ExclusiveBuildGroup mustBeFromGroup)
where T : IEntityDescriptor, new()
{
if (fromID.groupID != mustBeFromGroup)
throw new ECSException("Entity is not coming from the expected group");
SwapEntityGroup(fromID, toGroupID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SwapEntityGroup(EGID fromID, EGID toID
, ExclusiveBuildGroup mustBeFromGroup)
where T : IEntityDescriptor, new()
{
if (fromID.groupID != mustBeFromGroup)
throw new ECSException("Entity is not coming from the expected group");
SwapEntityGroup(fromID, toID);
}
#if UNITY_NATIVE
public NativeEntityRemove ToNativeRemove(string memberName) where T : IEntityDescriptor, new()
{
return _enginesRoot.Target.ProvideNativeEntityRemoveQueue(memberName);
}
public NativeEntitySwap ToNativeSwap(string memberName) where T : IEntityDescriptor, new()
{
return _enginesRoot.Target.ProvideNativeEntitySwapQueue(memberName);
}
#endif
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SwapEntityGroup(EGID fromID, EGID toID)
where T : IEntityDescriptor, new()
{
DBC.ECS.Check.Require(fromID.groupID != 0, "invalid group detected");
DBC.ECS.Check.Require(toID.groupID != 0, "invalid group detected");
var enginesRootTarget = _enginesRoot.Target;
var descriptorComponentsToBuild = EntityDescriptorTemplate.descriptor.componentsToBuild;
enginesRootTarget.CheckRemoveEntityID(fromID, TypeCache.type);
enginesRootTarget.CheckAddEntityID(toID, TypeCache.type);
enginesRootTarget.QueueEntitySubmitOperation(
new EntitySubmitOperation(EntitySubmitOperationType.Swap,
fromID, toID, descriptorComponentsToBuild));
}
//enginesRoot is a weakreference because GenericEntityStreamConsumerFactory can be injected inside
//engines of other enginesRoot
readonly Svelto.DataStructures.WeakReference _enginesRoot;
}
void QueueEntitySubmitOperation(EntitySubmitOperation entitySubmitOperation)
{
#if DEBUG && !PROFILE_SVELTO
entitySubmitOperation.trace = new System.Diagnostics.StackFrame(1, true);
#endif
_entitiesOperations.Add((ulong) entitySubmitOperation.fromID, entitySubmitOperation);
}
void QueueEntitySubmitOperation(EntitySubmitOperation entitySubmitOperation) where T : IEntityDescriptor
{
#if DEBUG && !PROFILE_SVELTO
entitySubmitOperation.trace = new System.Diagnostics.StackFrame(1, true);
if (_entitiesOperations.TryGetValue((ulong) entitySubmitOperation.fromID, out var entitySubmitedOperation))
{
if (entitySubmitedOperation != entitySubmitOperation)
throw new ECSException("Only one entity operation per submission is allowed"
.FastConcat(" entityComponentType: ")
.FastConcat(typeof(T).Name)
.FastConcat(" submission type ", entitySubmitOperation.type.ToString(),
" from ID: ", entitySubmitOperation.fromID.entityID.ToString())
.FastConcat(" previous operation type: ",
_entitiesOperations[(ulong) entitySubmitOperation.fromID].type
.ToString()));
}
else
#endif
_entitiesOperations[(ulong) entitySubmitOperation.fromID] = entitySubmitOperation;
}
}
}