using System;
using System.Threading;
using Svelto.DataStructures;
namespace Svelto.ECS
{
///
/// Very naive fail safe, but at least it's simple to understand and safe
///
static class GroupCompoundInitializer
{
internal static readonly ThreadLocal isInitializing4 = new ThreadLocal();
internal static readonly ThreadLocal isInitializing3 = new ThreadLocal();
internal static readonly ThreadLocal isInitializing2 = new ThreadLocal();
}
public abstract class GroupCompound
where G1 : GroupTag where G2 : GroupTag where G3 : GroupTag where G4 : GroupTag
{
static readonly FasterList _Groups;
public static FasterReadOnlyList Groups => new FasterReadOnlyList(_Groups);
public static BuildGroup BuildGroup => new BuildGroup(_Groups[0]);
static GroupCompound()
{
if (GroupCompoundInitializer.isInitializing4.Value == false)
{
_Groups = new FasterList(1);
var Group = new ExclusiveGroup();
_Groups.Add(Group);
GroupCompound.Add(Group);
GroupCompound.Add(Group);
GroupCompound.Add(Group);
GroupCompound.Add(Group);
GroupCompound.Add(Group); // and must share the same array
GroupCompound.Add(Group);
GroupCompound.Add(Group);
GroupCompound.Add(Group);
GroupCompound.Add(Group);
GroupCompound.Add(Group);
//This is done here to be sure that the group is added once per group tag
//(if done inside the previous group compound it would be added multiple times)
GroupTag.Add(Group);
GroupTag.Add(Group);
GroupTag.Add(Group);
GroupTag.Add(Group);
#if DEBUG
GroupMap.idToName[(uint) Group] = $"Compound: {typeof(G1).Name}-{typeof(G2).Name}-{typeof(G3).Name}-{typeof(G4).Name} ID {(uint)Group}";
#endif
GroupCompoundInitializer.isInitializing4.Value = true;
//all the combinations must share the same group
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompoundInitializer.isInitializing4.Value = false;
}
}
public static void Add(ExclusiveGroupStruct @group)
{
for (int i = 0; i < _Groups.count; ++i)
if (_Groups[i] == group)
throw new Exception("temporary must be transformed in unit test");
_Groups.Add(group);
}
}
public abstract class GroupCompound
where G1 : GroupTag where G2 : GroupTag where G3 : GroupTag
{
static readonly FasterList _Groups;
public static FasterReadOnlyList Groups =>
new FasterReadOnlyList(_Groups);
public static BuildGroup BuildGroup => new BuildGroup(_Groups[0]);
public static void Add(ExclusiveGroupStruct group)
{
for (var i = 0; i < _Groups.count; ++i)
if (_Groups[i] == group)
throw new Exception("temporary must be transformed in unit test");
_Groups.Add(group);
}
static GroupCompound()
{
if (GroupCompoundInitializer.isInitializing3.Value == false)
{
_Groups = new FasterList(1);
var Group = new ExclusiveGroup();
_Groups.Add(Group);
GroupCompound.Add(Group); // and must share the same array
GroupCompound.Add(Group);
GroupCompound.Add(Group);
//This is done here to be sure that the group is added once per group tag
//(if done inside the previous group compound it would be added multiple times)
GroupTag.Add(Group);
GroupTag.Add(Group);
GroupTag.Add(Group);
#if DEBUG
GroupMap.idToName[(uint) Group] = $"Compound: {typeof(G1).Name}-{typeof(G2).Name}-{typeof(G3).Name} ID {(uint)Group}";
#endif
//all the combinations must share the same group
GroupCompoundInitializer.isInitializing3.Value = true;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompound._Groups = _Groups;
GroupCompoundInitializer.isInitializing3.Value = false;
}
}
}
public abstract class GroupCompound where G1 : GroupTag where G2 : GroupTag
{
static readonly FasterList _Groups;
public static FasterReadOnlyList Groups =>
new FasterReadOnlyList(_Groups);
public static BuildGroup BuildGroup => new BuildGroup(_Groups[0]);
public static void Add(ExclusiveGroupStruct group)
{
for (var i = 0; i < _Groups.count; ++i)
if (_Groups[i] == group)
throw new Exception("temporary must be transformed in unit test");
_Groups.Add(group);
}
static GroupCompound()
{
if (GroupCompoundInitializer.isInitializing2.Value == false)
{
var Group = new ExclusiveGroup();
_Groups = new FasterList(1);
_Groups.Add(Group);
//every abstract group preemptively adds this group, it may or may not be empty in future
GroupTag.Add(Group);
GroupTag.Add(Group);
#if DEBUG
GroupMap.idToName[(uint) Group] = $"Compound: {typeof(G1).Name}-{typeof(G2).Name} ID {(uint)Group}";
#endif
GroupCompoundInitializer.isInitializing2.Value = true;
GroupCompound._Groups = _Groups;
GroupCompoundInitializer.isInitializing2.Value = false;
}
}
}
///
///A Group Tag holds initially just a group, itself. However the number of groups can grow with the number of
///combinations of GroupTags including this one. This because a GroupTag is an adjective and different entities
///can use the same adjective together with other ones. However since I need to be able to iterate over all the
///groups with the same adjective, a group tag needs to hold all the groups sharing it.
///
///
public abstract class GroupTag where T : GroupTag
{
static readonly FasterList _Groups = new FasterList(1);
public static FasterReadOnlyList Groups =>
new FasterReadOnlyList(_Groups);
public static BuildGroup BuildGroup => new BuildGroup(_Groups[0]);
static GroupTag()
{
var group = new ExclusiveGroup();
_Groups.Add(group);
#if DEBUG
GroupMap.idToName[(uint) group] = $"Compound: {typeof(T).Name} ID {(uint)group}";
#endif
}
//Each time a new combination of group tags is found a new group is added.
internal static void Add(ExclusiveGroupStruct group)
{
for (var i = 0; i < _Groups.count; ++i)
if (_Groups[i] == group)
throw new Exception("temporary must be transformed in unit test");
_Groups.Add(group);
}
}
}