using System.Collections.Generic;
using Svelto.Common;
using Svelto.DataStructures;
namespace Svelto.ECS
{
public partial class EnginesRoot
{
///
/// Todo: it would be probably better to split even further the logic between submission and callbacks
/// Something to do when I will optimize the callbacks
///
///
///
IEnumerator SingleSubmission(PlatformProfiler profiler)
{
while (true)
{
DBC.ECS.Check.Require(_maxNumberOfOperationsPerFrame > 0);
ClearChecks();
uint numberOfOperations = 0;
if (_entitiesOperations.count > 0)
{
using (var sample = profiler.Sample("Remove and Swap operations"))
{
_transientEntitiesOperations.FastClear();
_entitiesOperations.CopyValuesTo(_transientEntitiesOperations);
_entitiesOperations.FastClear();
EntitySubmitOperation[] entitiesOperations =
_transientEntitiesOperations.ToArrayFast(out var count);
for (var i = 0; i < count; i++)
{
try
{
switch (entitiesOperations[i].type)
{
case EntitySubmitOperationType.Swap:
MoveEntityFromAndToEngines(entitiesOperations[i].builders
, entitiesOperations[i].fromID
, entitiesOperations[i].toID);
break;
case EntitySubmitOperationType.Remove:
MoveEntityFromAndToEngines(entitiesOperations[i].builders
, entitiesOperations[i].fromID, null);
break;
case EntitySubmitOperationType.RemoveGroup:
RemoveEntitiesFromGroup(entitiesOperations[i].fromID.groupID, profiler);
break;
case EntitySubmitOperationType.SwapGroup:
SwapEntitiesBetweenGroups(entitiesOperations[i].fromID.groupID
, entitiesOperations[i].toID.groupID, profiler);
break;
}
}
catch
{
var str = "Crash while executing Entity Operation ".FastConcat(
entitiesOperations[i].type.ToString());
Svelto.Console.LogError(str.FastConcat(" ")
#if DEBUG && !PROFILE_SVELTO
.FastConcat(entitiesOperations[i].trace.ToString())
#endif
);
throw;
}
++numberOfOperations;
if ((uint) numberOfOperations >= (uint) _maxNumberOfOperationsPerFrame)
{
using (sample.Yield())
yield return true;
numberOfOperations = 0;
}
}
}
}
_groupedEntityToAdd.Swap();
if (_groupedEntityToAdd.AnyOtherEntityCreated())
{
using (var outerSampler = profiler.Sample("Add operations"))
{
try
{
using (profiler.Sample("Add entities to database"))
{
//each group is indexed by entity view type. for each type there is a dictionary indexed by entityID
foreach (var groupToSubmit in _groupedEntityToAdd.other)
{
var groupID = groupToSubmit.Key;
var groupDB = GetOrCreateDBGroup(groupID);
//add the entityComponents in the group
foreach (var entityComponentsToSubmit in groupToSubmit.Value)
{
var type = entityComponentsToSubmit.Key;
var targetTypeSafeDictionary = entityComponentsToSubmit.Value;
var wrapper = new RefWrapperType(type);
var dbDic = GetOrCreateTypeSafeDictionary(
groupID, groupDB, wrapper, targetTypeSafeDictionary);
//Fill the DB with the entity components generated this frame.
dbDic.AddEntitiesFromDictionary(targetTypeSafeDictionary, groupID, this);
}
}
}
//then submit everything in the engines, so that the DB is up to date with all the entity components
//created by the entity built
using (var sampler = profiler.Sample("Add entities to engines"))
{
foreach (var groupToSubmit in _groupedEntityToAdd.other)
{
var groupID = groupToSubmit.Key;
var groupDB = GetDBGroup(groupID);
//entityComponentsToSubmit is the array of components found in the groupID per component type.
//if there are N entities to submit, and M components type to add for each entity, this foreach will run NxM times.
foreach (var entityComponentsToSubmit in groupToSubmit.Value)
{
var realDic = groupDB[new RefWrapperType(entityComponentsToSubmit.Key)];
entityComponentsToSubmit.Value.ExecuteEnginesAddOrSwapCallbacks(
_reactiveEnginesAddRemove, realDic, null, groupID, in profiler);
numberOfOperations += entityComponentsToSubmit.Value.count;
if (numberOfOperations >= _maxNumberOfOperationsPerFrame)
{
using (outerSampler.Yield())
using (sampler.Yield())
{
yield return true;
}
numberOfOperations = 0;
}
}
}
}
}
finally
{
using (profiler.Sample("clear double buffering"))
{
//other can be cleared now, but let's avoid deleting the dictionary every time
_groupedEntityToAdd.ClearOther();
}
}
}
}
yield return false;
}
}
bool HasMadeNewStructuralChangesInThisIteration()
{
return _groupedEntityToAdd.AnyEntityCreated() || _entitiesOperations.count > 0;
}
readonly DoubleBufferedEntitiesToAdd _groupedEntityToAdd;
readonly FasterDictionary _entitiesOperations;
readonly FasterList _transientEntitiesOperations;
uint _maxNumberOfOperationsPerFrame;
}
}