using System;
using System.Runtime.CompilerServices;
using Svelto.DataStructures;
using Svelto.Utilities;
namespace Svelto.ECS
{
class EntitiesOperations
{
///
/// Todo: need to go back here and add a ton of comments
///
public EntitiesOperations()
{
_thisSubmissionInfo.Init();
_lastSubmittedInfo.Init();
_newGroupDictionary = NewGroupDictionary;
_newGroupsDictionary = NewGroupsDictionary;
_recycleDictionary = RecycleDictionary;
_newList = NewList;
_clearList = ClearList;
_newGroupsDictionaryWithCaller = NewGroupsDictionaryWithCaller;
_recycleGroupDictionaryWithCaller = RecycleGroupDictionaryWithCaller;
_recycleDicitionaryWithCaller = RecycleDicitionaryWithCaller;
_newListWithCaller = NewListWithCaller;
_clearListWithCaller = ClearListWithCaller;
}
public void QueueRemoveGroupOperation(ExclusiveBuildGroup groupID, string caller)
{
_thisSubmissionInfo._groupsToRemove.Add((groupID, caller));
}
public void QueueRemoveOperation(EGID entityEgid, IComponentBuilder[] componentBuilders, string caller)
{
_thisSubmissionInfo._entitiesRemoved.Add(entityEgid);
//todo: limit the number of dictionaries that can be cached
//recycle or create dictionaries of components per group
var removedComponentsPerType = _thisSubmissionInfo._currentRemoveEntitiesOperations.RecycleOrAdd(
entityEgid.groupID, _newGroupsDictionary, _recycleDictionary);
foreach (var operation in componentBuilders)
{
removedComponentsPerType //recycle or create dictionaries per component type
.RecycleOrAdd(operation.getComponentID, _newList, _clearList)
//add entity to remove
.Add((entityEgid.entityID, caller));
}
}
public void QueueSwapGroupOperation(ExclusiveBuildGroup fromGroupID, ExclusiveBuildGroup toGroupID, string caller)
{
_thisSubmissionInfo._groupsToSwap.Add((fromGroupID, toGroupID, caller));
}
public void QueueSwapOperation(EGID fromID, EGID toID, IComponentBuilder[] componentBuilders, string caller)
{
_thisSubmissionInfo._entitiesSwapped.Add((fromID, toID));
//todo: limit the number of dictionaries that can be cached
//recycle or create dictionaries of components per group
//Get the dictionary that holds the entities that are swapping from fromID
var swappedComponentsPerType = _thisSubmissionInfo._currentSwapEntitiesOperations.RecycleOrAdd(
fromID.groupID, _newGroupsDictionaryWithCaller, _recycleGroupDictionaryWithCaller);
var componentBuildersLength = componentBuilders.Length - 1;
for (var index = componentBuildersLength; index >= 0; index--)
{
var operation = componentBuilders[index];
//Get the dictionary for each component that holds the list of entities to swap
swappedComponentsPerType //recycle or create dictionaries per component type
.RecycleOrAdd(operation.getComponentID, _newGroupDictionary, _recycleDicitionaryWithCaller)
//recycle or create list of entities to swap
.RecycleOrAdd(toID.groupID, _newListWithCaller, _clearListWithCaller)
//add entity to swap
.Add((fromID.entityID, toID.entityID, caller));
}
}
[MethodImpl(MethodImplOptions.Synchronized)]
public bool AnyOperationQueued()
{
return _thisSubmissionInfo.AnyOperationQueued();
}
public void ExecuteRemoveAndSwappingOperations(Action>>>, FasterList<(EGID, EGID)>,
EnginesRoot> swapEntities, Action>>,
FasterList, EnginesRoot> removeEntities, Action removeGroup,
Action swapGroup, EnginesRoot enginesRoot)
{
(_thisSubmissionInfo, _lastSubmittedInfo) = (_lastSubmittedInfo, _thisSubmissionInfo);
/// todo: entity references should be updated before calling all the methods to avoid callbacks handling
/// references that should be marked as invalid.
foreach (var (group, caller) in _lastSubmittedInfo._groupsToRemove)
try
{
removeGroup(group, enginesRoot);
}
catch
{
var str = "Crash while removing a whole group on ".FastConcat(group.ToString())
.FastConcat(" from : ", caller);
Console.LogError(str);
throw;
}
foreach (var (fromGroup, toGroup, caller) in _lastSubmittedInfo._groupsToSwap)
try
{
swapGroup(fromGroup, toGroup, enginesRoot);
}
catch
{
var str = "Crash while swapping a whole group on "
.FastConcat(fromGroup.ToString(), " ", toGroup.ToString()).FastConcat(" from : ", caller);
Console.LogError(str);
throw;
}
if (_lastSubmittedInfo._entitiesSwapped.count > 0)
swapEntities(_lastSubmittedInfo._currentSwapEntitiesOperations, _lastSubmittedInfo._entitiesSwapped
, enginesRoot);
if (_lastSubmittedInfo._entitiesRemoved.count > 0)
removeEntities(_lastSubmittedInfo._currentRemoveEntitiesOperations, _lastSubmittedInfo._entitiesRemoved
, enginesRoot);
_lastSubmittedInfo.Clear();
}
FasterDictionary> NewGroupsDictionary()
{
return new FasterDictionary>();
}
void RecycleDictionary(ref FasterDictionary> recycled)
{
recycled.Recycle();
}
FasterList<(uint, string)> NewList()
{
return new FasterList<(uint, string)>();
}
void ClearList(ref FasterList<(uint, string)> target)
{
target.Clear();
}
void RecycleDicitionaryWithCaller(ref FasterDictionary> target)
{
target.Recycle();
}
void ClearListWithCaller(ref FasterList<(uint, uint, string)> target)
{
target.Clear();
}
FasterList<(uint, uint, string)> NewListWithCaller()
{
return new FasterList<(uint, uint, string)>();
}
FasterDictionary>> NewGroupsDictionaryWithCaller()
{
return new FasterDictionary>>();
}
void RecycleGroupDictionaryWithCaller(ref FasterDictionary>> recycled)
{
recycled.Recycle();
}
FasterDictionary> NewGroupDictionary()
{
return new FasterDictionary>();
}
struct Info
{
//from group //actual component type
internal FasterDictionary>>>
_currentSwapEntitiesOperations;
internal FasterDictionary>> _currentRemoveEntitiesOperations;
internal FasterList<(EGID, EGID)> _entitiesSwapped;
internal FasterList _entitiesRemoved;
public FasterList<(ExclusiveBuildGroup, ExclusiveBuildGroup, string)> _groupsToSwap;
public FasterList<(ExclusiveBuildGroup, string)> _groupsToRemove;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal bool AnyOperationQueued()
{
return _entitiesSwapped.count > 0 || _entitiesRemoved.count > 0 || _groupsToSwap.count > 0
|| _groupsToRemove.count > 0;
}
internal void Clear()
{
_currentSwapEntitiesOperations.Recycle();
_currentRemoveEntitiesOperations.Recycle();
_entitiesSwapped.Clear();
_entitiesRemoved.Clear();
_groupsToRemove.Clear();
_groupsToSwap.Clear();
}
internal void Init()
{
_entitiesSwapped = new FasterList<(EGID, EGID)>();
_entitiesRemoved = new FasterList();
_groupsToRemove = new FasterList<(ExclusiveBuildGroup, string)>();
_groupsToSwap = new FasterList<(ExclusiveBuildGroup, ExclusiveBuildGroup, string)>();
_currentSwapEntitiesOperations =
new FasterDictionary>>>();
_currentRemoveEntitiesOperations =
new FasterDictionary>>();
}
}
Info _lastSubmittedInfo;
Info _thisSubmissionInfo;
readonly Func>> _newGroupDictionary;
readonly Func>> _newGroupsDictionary;
readonly ActionRef>> _recycleDictionary;
readonly Func> _newList;
readonly ActionRef> _clearList;
readonly Func>>> _newGroupsDictionaryWithCaller;
readonly ActionRef>>> _recycleGroupDictionaryWithCaller;
readonly ActionRef>> _recycleDicitionaryWithCaller;
readonly Func> _newListWithCaller;
readonly ActionRef> _clearListWithCaller;
}
}