public DynamicEntityDescriptorInfo(FasterList <IEntityViewBuilder> extraEntityViews)
        {
            Check.Require(extraEntityViews.Count > 0,
                          "don't use a DynamicEntityDescriptorInfo if you don't need to use extra EntityViews");

            var descriptor = new TType();
            var length     = descriptor.entityViewsToBuild.Length;

            entityViewsToBuild = new IEntityViewBuilder[length + extraEntityViews.Count];

            Array.Copy(descriptor.entityViewsToBuild, 0, entityViewsToBuild, 0, length);
            Array.Copy(extraEntityViews.ToArrayFast(), 0, entityViewsToBuild, length, extraEntityViews.Count);

            name = descriptor.ToString();
        }
        public DynamicEntityDescriptorInfo(FasterList <IEntityViewBuilder> extraEntityViews)
        {
            Check.Require(extraEntityViews.Count > 0,
                          "don't use a DynamicEntityDescriptorInfo if you don't need to use extra EntityViews");

            var defaultEntityViewsToBuild = EntityDescriptorTemplate <TType> .Default.entityViewsToBuild;
            var length = defaultEntityViewsToBuild.Length;

            entityViewsToBuild = new IEntityViewBuilder[length + extraEntityViews.Count];

            Array.Copy(defaultEntityViewsToBuild, 0, entityViewsToBuild, 0, length);
            Array.Copy(extraEntityViews.ToArrayFast(), 0, entityViewsToBuild, length, extraEntityViews.Count);

            name = EntityDescriptorTemplate <TType> .Default.name;
        }
        static void ExecuteRoutines(FasterList <IEnumerator> list)
        {
            var count    = list.Count;
            var routines = list.ToArrayFast();

            for (int i = 0; i < count; i++)
            {
                var ret = routines[i].MoveNext();
                if (ret == false)
                {
                    list.UnorderedRemoveAt(i);
                    count--;
                    i--;
                }
            }
        }
示例#4
0
        public void DequeueAllInto(FasterList <T> list)
        {
            int i = list.Count;

            _lockQ.EnterWriteLock();
            list.ExpandBy((uint)_queue.Count);
            var array = list.ToArrayFast();

            try
            {
                while (_queue.Count > 0)
                {
                    array[i++] = _queue.Dequeue();
                }
            }
            finally
            {
                _lockQ.ExitWriteLock();
            }
        }
示例#5
0
        public void DequeueAllInto(FasterList <T> list)
        {
            uint i = (uint)list.count;

            list.IncrementCountBy((uint)_queue.Count);
            var array = list.ToArrayFast(out _);

            _lockQ.EnterWriteLock();

            try
            {
                while (_queue.Count > 0)
                {
                    array[i++] = _queue.Dequeue();
                }
            }
            finally
            {
                _lockQ.ExitWriteLock();
            }
        }
示例#6
0
        public DynamicEntityDescriptorInfo(FasterList <IEntityBuilder> extraEntities) : this()
        {
            DBC.ECS.Check.Require(extraEntities.Count > 0,
                                  "don't use a DynamicEntityDescriptorInfo if you don't need to use extra EntityViews");

            var defaultEntities = EntityDescriptorTemplate <TType> .descriptor.entitiesToBuild;
            var length          = defaultEntities.Length;

            entitiesToBuild = new IEntityBuilder[length + extraEntities.Count + 1];

            Array.Copy(defaultEntities, 0, entitiesToBuild, 0, length);
            Array.Copy(extraEntities.ToArrayFast(), 0, entitiesToBuild, length, extraEntities.Count);

            var _builder = new EntityBuilder <EntityInfoView>
            {
                _initializer = new EntityInfoView {
                    entitiesToBuild = entitiesToBuild
                }
            };

            entitiesToBuild[entitiesToBuild.Length - 1] = _builder;
        }
示例#7
0
        static GroupCompound()
        {
            if (GroupCompoundInitializer.isInitializing4.Value == false)
            {
                _Groups = new FasterList <ExclusiveGroupStruct>(1);

                var Group = new ExclusiveGroup();
                _Groups.Add(Group);
                _GroupsHashSet = new HashSet <ExclusiveGroupStruct>(_Groups.ToArrayFast(out _));

                GroupCompound <G1, G2, G3> .Add(Group);

                GroupCompound <G1, G2, G4> .Add(Group);

                GroupCompound <G1, G3, G4> .Add(Group);

                GroupCompound <G2, G3, G4> .Add(Group);

                GroupCompound <G1, G2> .Add(Group); //<G1/G2> and <G2/G1> must share the same array

                GroupCompound <G1, G3> .Add(Group);

                GroupCompound <G1, G4> .Add(Group);

                GroupCompound <G2, G3> .Add(Group);

                GroupCompound <G2, G4> .Add(Group);

                GroupCompound <G3, G4> .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 <G1> .Add(Group);

                GroupTag <G2> .Add(Group);

                GroupTag <G3> .Add(Group);

                GroupTag <G4> .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 and group hashset
                GroupCompound <G1, G2, G4, G3> ._Groups = _Groups;
                GroupCompound <G1, G3, G2, G4> ._Groups = _Groups;
                GroupCompound <G1, G3, G4, G2> ._Groups = _Groups;
                GroupCompound <G1, G4, G2, G3> ._Groups = _Groups;
                GroupCompound <G2, G1, G3, G4> ._Groups = _Groups;
                GroupCompound <G2, G3, G4, G1> ._Groups = _Groups;
                GroupCompound <G3, G1, G2, G4> ._Groups = _Groups;
                GroupCompound <G4, G1, G2, G3> ._Groups = _Groups;
                GroupCompound <G1, G4, G3, G2> ._Groups = _Groups;
                GroupCompound <G2, G1, G4, G3> ._Groups = _Groups;
                GroupCompound <G2, G4, G3, G1> ._Groups = _Groups;
                GroupCompound <G3, G1, G4, G2> ._Groups = _Groups;
                GroupCompound <G4, G1, G3, G2> ._Groups = _Groups;
                GroupCompound <G2, G3, G1, G4> ._Groups = _Groups;
                GroupCompound <G3, G4, G1, G2> ._Groups = _Groups;
                GroupCompound <G2, G4, G1, G3> ._Groups = _Groups;
                GroupCompound <G3, G2, G1, G4> ._Groups = _Groups;
                GroupCompound <G3, G2, G4, G1> ._Groups = _Groups;
                GroupCompound <G3, G4, G2, G1> ._Groups = _Groups;
                GroupCompound <G4, G2, G1, G3> ._Groups = _Groups;
                GroupCompound <G4, G2, G3, G1> ._Groups = _Groups;
                GroupCompound <G4, G3, G1, G2> ._Groups = _Groups;
                GroupCompound <G4, G3, G2, G1> ._Groups = _Groups;

                GroupCompound <G1, G2, G4, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G3, G2, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G3, G4, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G4, G2, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G1, G3, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G3, G4, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G1, G2, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G1, G2, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G4, G3, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G1, G4, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G4, G3, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G1, G4, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G1, G3, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G3, G1, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G4, G1, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G4, G1, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G2, G1, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G2, G4, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G4, G2, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G2, G1, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G2, G3, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G3, G1, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G3, G2, G1> ._GroupsHashSet = _GroupsHashSet;

                GroupCompoundInitializer.isInitializing4.Value = false;
            }
        }
 public void ExtendWith(FasterList <IComponentBuilder> extraEntities)
 {
     _componentsToBuild = Construct(extraEntities.count, extraEntities.ToArrayFast(out _));
 }
示例#9
0
        void SubmitEntityViews()
        {
            using (var profiler = new PlatformProfiler("Svelto.ECS - Entities Submission"))
            {
                if (_entitiesOperations.Count > 0)
                {
                    using (profiler.Sample("Remove and Swap operations"))
                    {
                        _transientEntitiesOperations.FastClear();
                        var entitySubmitOperations = _entitiesOperations.GetValuesArray(out var count);
                        _transientEntitiesOperations.AddRange(entitySubmitOperations, count);
                        _entitiesOperations.FastClear();

                        var entitiesOperations = _transientEntitiesOperations.ToArrayFast();
                        for (var i = 0; i < _transientEntitiesOperations.Count; i++)
                        {
                            try
                            {
                                switch (entitiesOperations[i].type)
                                {
                                case EntitySubmitOperationType.Swap:
                                    SwapEntityGroup(entitiesOperations[i].builders,
                                                    entitiesOperations[i].entityDescriptor,
                                                    entitiesOperations[i].fromID,
                                                    entitiesOperations[i].toID);
                                    break;

                                case EntitySubmitOperationType.Remove:
                                    MoveEntity(entitiesOperations[i].builders,
                                               entitiesOperations[i].fromID,
                                               entitiesOperations[i].entityDescriptor, null);
                                    break;

                                case EntitySubmitOperationType.RemoveGroup:
                                    if (entitiesOperations[i].entityDescriptor == null)
                                    {
                                        RemoveGroupAndEntitiesFromDB(entitiesOperations[i].fromID.groupID);
                                    }
                                    else
                                    {
                                        RemoveGroupAndEntitiesFromDB(entitiesOperations[i].fromID.groupID,
                                                                     entitiesOperations[i].entityDescriptor);
                                    }

                                    break;
                                }
                            }
                            catch (Exception e)
                            {
                                var str = "Crash while executing Entity Operation "
                                          .FastConcat(entitiesOperations[i].type.ToString());
#if RELAXED_ECS && !PROFILER
                                Console.LogException(str.FastConcat(" "
#if DEBUG && !PROFILER
                                                                    , entitiesOperations[i].trace
#endif
                                                                    ), e);
#else
                                throw new ECSException(str.FastConcat(" ")
#if DEBUG && !PROFILER
                                                       .FastConcat(entitiesOperations[i].trace)
#endif
                                                       , e);
#endif
                            }
                        }
                    }
                }

                if (_groupedEntityToAdd.currentEntitiesCreatedPerGroup.Count > 0)
                {
                    using (profiler.Sample("Add operations"))
                    {
                        //use other as source from now on current will be use to write new entityViews
                        _groupedEntityToAdd.Swap();

                        try
                        {
                            //Note: if N entity of the same type are added on the same frame the Add callback is called
                            //N times on the same frame. if the Add callback builds a new entity, that entity will not
                            //be available in the database until the N callbacks are done. Solving this could be
                            //complicated as callback and database update must be interleaved.
                            AddEntityViewsToTheDBAndSuitableEngines(_groupedEntityToAdd, profiler);
                        }
                        finally
                        {
                            //other can be cleared now, but let's avoid deleting the dictionary every time
                            _groupedEntityToAdd.ClearOther();
                        }
                    }
                }
            }
        }
示例#10
0
        static GroupCompound()
        {
            //avoid race conditions if compounds are using on multiple thread
            if (Interlocked.CompareExchange(ref isInitializing, 1, 0) == 0 &&
                GroupCompoundInitializer.skipStaticCompoundConstructorsWith4Tags.Value == false)
            {
                var group = new ExclusiveGroup(); //todo: it's a bit of a waste to create a class here even if this is a static constructor

                _Groups = new FasterList <ExclusiveGroupStruct>(1);
                _Groups.Add(group);

#if DEBUG
                var name =
                    $"Compound: {typeof(G1).Name}-{typeof(G2).Name}-{typeof(G3).Name}-{typeof(G4).Name} ID {(uint) group.id}";
                GroupNamesMap.idToName[group] = name;
#endif
                //The hashname is independent from the actual group ID. this is fundamental because it is want
                //guarantees the hash to be the same across different machines
                GroupHashMap.RegisterGroup(group, typeof(GroupCompound <G1, G2, G3, G4>).FullName);

                _GroupsHashSet = new HashSet <ExclusiveGroupStruct>(_Groups.ToArrayFast(out _));

                GroupCompoundInitializer.skipStaticCompoundConstructorsWith4Tags.Value = true;

                //all the permutations must share the same group and group hashset. Warm them up, avoid call the
                //constructors again, set the desired value
                GroupCompound <G1, G2, G4, G3> ._Groups = _Groups;
                GroupCompound <G1, G3, G2, G4> ._Groups = _Groups;
                GroupCompound <G1, G3, G4, G2> ._Groups = _Groups;
                GroupCompound <G1, G4, G2, G3> ._Groups = _Groups;
                GroupCompound <G2, G1, G3, G4> ._Groups = _Groups;
                GroupCompound <G2, G3, G4, G1> ._Groups = _Groups;
                GroupCompound <G3, G1, G2, G4> ._Groups = _Groups;
                GroupCompound <G4, G1, G2, G3> ._Groups = _Groups;
                GroupCompound <G1, G4, G3, G2> ._Groups = _Groups;
                GroupCompound <G2, G1, G4, G3> ._Groups = _Groups;
                GroupCompound <G2, G4, G3, G1> ._Groups = _Groups;
                GroupCompound <G3, G1, G4, G2> ._Groups = _Groups;
                GroupCompound <G4, G1, G3, G2> ._Groups = _Groups;
                GroupCompound <G2, G3, G1, G4> ._Groups = _Groups;
                GroupCompound <G3, G4, G1, G2> ._Groups = _Groups;
                GroupCompound <G2, G4, G1, G3> ._Groups = _Groups;
                GroupCompound <G3, G2, G1, G4> ._Groups = _Groups;
                GroupCompound <G3, G2, G4, G1> ._Groups = _Groups;
                GroupCompound <G3, G4, G2, G1> ._Groups = _Groups;
                GroupCompound <G4, G2, G1, G3> ._Groups = _Groups;
                GroupCompound <G4, G2, G3, G1> ._Groups = _Groups;
                GroupCompound <G4, G3, G1, G2> ._Groups = _Groups;
                GroupCompound <G4, G3, G2, G1> ._Groups = _Groups;

                //all the permutations are warmed up now
                GroupCompoundInitializer.skipStaticCompoundConstructorsWith4Tags.Value = false;

                GroupCompound <G1, G2, G4, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G3, G2, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G3, G4, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G4, G2, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G1, G3, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G3, G4, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G1, G2, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G1, G2, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G4, G3, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G1, G4, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G4, G3, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G1, G4, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G1, G3, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G3, G1, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G4, G1, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G4, G1, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G2, G1, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G2, G4, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G4, G2, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G2, G1, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G2, G3, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G3, G1, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G3, G2, G1> ._GroupsHashSet = _GroupsHashSet;

                GroupCompound <G1, G2, G3> .Add(group);

                GroupCompound <G1, G2, G4> .Add(group);

                GroupCompound <G1, G3, G4> .Add(group);

                GroupCompound <G2, G3, G4> .Add(group);

                GroupCompound <G1, G2> .Add(group); //<G1/G2> and <G2/G1> must share the same array

                GroupCompound <G1, G3> .Add(group);

                GroupCompound <G1, G4> .Add(group);

                GroupCompound <G2, G3> .Add(group);

                GroupCompound <G2, G4> .Add(group);

                GroupCompound <G3, G4> .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 <G1> .Add(group);

                GroupTag <G2> .Add(group);

                GroupTag <G3> .Add(group);

                GroupTag <G4> .Add(group);
            }
        }
示例#11
0
 public void AddRange(FasterList <T> items)
 {
     AddRange(items.ToArrayFast(), (uint)items.Count);
 }
示例#12
0
        static GroupCompound()
        {
            //avoid race conditions if compounds are using on multiple thread
            if (Interlocked.CompareExchange(ref isInitializing, 1, 0) == 0 &&
                GroupCompoundInitializer.skipStaticCompoundConstructorsWith4Tags.Value == false)
            {
                _Groups = new FasterList <ExclusiveGroupStruct>(1);

                var group = new ExclusiveGroup();
                _Groups.Add(group);

                var name =
                    $"Compound: {typeof(G1).Name}-{typeof(G2).Name}-{typeof(G3).Name}-{typeof(G4).Name} ID {(uint) group}";
#if DEBUG
                GroupNamesMap.idToName[(uint)group] = name;
#endif
                GroupHashMap.RegisterGroup(group, name);

                _GroupsHashSet = new HashSet <ExclusiveGroupStruct>(_Groups.ToArrayFast(out _));

                GroupCompoundInitializer.skipStaticCompoundConstructorsWith4Tags.Value = true;

                //all the permutations must share the same group and group hashset. Warm them up, avoid call the
                //constructors again, set the desired value
                GroupCompound <G1, G2, G4, G3> ._Groups = _Groups;
                GroupCompound <G1, G3, G2, G4> ._Groups = _Groups;
                GroupCompound <G1, G3, G4, G2> ._Groups = _Groups;
                GroupCompound <G1, G4, G2, G3> ._Groups = _Groups;
                GroupCompound <G2, G1, G3, G4> ._Groups = _Groups;
                GroupCompound <G2, G3, G4, G1> ._Groups = _Groups;
                GroupCompound <G3, G1, G2, G4> ._Groups = _Groups;
                GroupCompound <G4, G1, G2, G3> ._Groups = _Groups;
                GroupCompound <G1, G4, G3, G2> ._Groups = _Groups;
                GroupCompound <G2, G1, G4, G3> ._Groups = _Groups;
                GroupCompound <G2, G4, G3, G1> ._Groups = _Groups;
                GroupCompound <G3, G1, G4, G2> ._Groups = _Groups;
                GroupCompound <G4, G1, G3, G2> ._Groups = _Groups;
                GroupCompound <G2, G3, G1, G4> ._Groups = _Groups;
                GroupCompound <G3, G4, G1, G2> ._Groups = _Groups;
                GroupCompound <G2, G4, G1, G3> ._Groups = _Groups;
                GroupCompound <G3, G2, G1, G4> ._Groups = _Groups;
                GroupCompound <G3, G2, G4, G1> ._Groups = _Groups;
                GroupCompound <G3, G4, G2, G1> ._Groups = _Groups;
                GroupCompound <G4, G2, G1, G3> ._Groups = _Groups;
                GroupCompound <G4, G2, G3, G1> ._Groups = _Groups;
                GroupCompound <G4, G3, G1, G2> ._Groups = _Groups;
                GroupCompound <G4, G3, G2, G1> ._Groups = _Groups;

                //all the permutations are warmed up now
                GroupCompoundInitializer.skipStaticCompoundConstructorsWith4Tags.Value = false;

                GroupCompound <G1, G2, G4, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G3, G2, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G3, G4, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G4, G2, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G1, G3, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G3, G4, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G1, G2, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G1, G2, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G1, G4, G3, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G1, G4, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G4, G3, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G1, G4, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G1, G3, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G3, G1, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G4, G1, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G2, G4, G1, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G2, G1, G4> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G2, G4, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G3, G4, G2, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G2, G1, G3> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G2, G3, G1> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G3, G1, G2> ._GroupsHashSet = _GroupsHashSet;
                GroupCompound <G4, G3, G2, G1> ._GroupsHashSet = _GroupsHashSet;

                GroupCompound <G1, G2, G3> .Add(group);

                GroupCompound <G1, G2, G4> .Add(group);

                GroupCompound <G1, G3, G4> .Add(group);

                GroupCompound <G2, G3, G4> .Add(group);

                GroupCompound <G1, G2> .Add(group); //<G1/G2> and <G2/G1> must share the same array

                GroupCompound <G1, G3> .Add(group);

                GroupCompound <G1, G4> .Add(group);

                GroupCompound <G2, G3> .Add(group);

                GroupCompound <G2, G4> .Add(group);

                GroupCompound <G3, G4> .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 <G1> .Add(group);

                GroupTag <G2> .Add(group);

                GroupTag <G3> .Add(group);

                GroupTag <G4> .Add(group);
            }
        }