This repository has been archived on 2023-02-02. You can view files and clone it, but cannot push or open issues or pull requests.
mfgames-gallium-cil/src/MfGames.Gallium/SplitEntityExtensions.cs

299 lines
10 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
namespace MfGames.Gallium;
/// <summary>
/// Extension methods for IEnumerable&lt;Entity&gt; that split the entity into two
/// sequences, one that contains the
/// various components and the other list which does not.
/// </summary>
public static class SplitEntityExtensions
{
/// <summary>
/// Splits the enumeration of entities into two separate enumerations, ones that
/// have the given generic components
/// and those which do not.
/// </summary>
/// <param name="entities">The entities to split into two lists.</param>
/// <param name="test">
/// An additional test function to determine if the entity is
/// included in the has list. If null, then entities with all the components will
/// be included.
/// </param>
/// <typeparam name="T1">
/// A component to require to be in included in the first
/// list.
/// </typeparam>
/// <returns>A pair of enumerations, ones with the components and ones without.</returns>
public static SplitEntityEnumerations SplitEntity
<T1>(
this IEnumerable<Entity> entities,
Func<Entity, T1, bool>? test = null)
{
test ??= (
e,
v1) => true;
return entities.SplitEntity(
typeof(T1),
(
e,
v1) => test(e, (T1)v1));
}
/// <summary>
/// Splits the enumeration of entities into two separate enumerations, ones that
/// have the given generic components
/// and those which do not.
/// </summary>
/// <param name="entities">The entities to split into two lists.</param>
/// <param name="test">
/// An additional test function to determine if the entity is
/// included in the has list. If null, then entities with all the components will
/// be included.
/// </param>
/// <typeparam name="T1">
/// A component to require to be in included in the first list.
/// </typeparam>
/// <typeparam name="T2">
/// A component to require to be in included in the first list.
/// </typeparam>
/// <returns>A pair of enumerations, ones with the components and ones without.</returns>
public static SplitEntityEnumerations SplitEntity
<T1, T2>(
this IEnumerable<Entity> entities,
Func<Entity, T1, T2, bool>? test = null)
{
test ??= (
e,
v1,
v2) => true;
return entities.SplitEntity(
typeof(T1),
typeof(T2),
(
e,
v1,
v2) => test(e, (T1)v1, (T2)v2));
}
/// <summary>
/// Splits the enumeration of entities into two separate enumerations, ones that
/// have the given generic components
/// and those which do not.
/// </summary>
/// <param name="entities">The entities to split into two lists.</param>
/// <param name="test">
/// An additional test function to determine if the entity is
/// included in the has list. If null, then entities with all the components will
/// be included.
/// </param>
/// <typeparam name="T1">
/// A component to require to be in included in the first list.
/// </typeparam>
/// <typeparam name="T2">
/// A component to require to be in included in the first list.
/// </typeparam>
/// <typeparam name="T3">
/// A component to require to be in included in the first list.
/// </typeparam>
/// <returns>A pair of enumerations, ones with the components and ones without.</returns>
public static SplitEntityEnumerations SplitEntity
<T1, T2, T3>(
this IEnumerable<Entity> entities,
Func<Entity, T1, T2, T3, bool>? test = null)
{
test ??= (
e,
v1,
v2,
v3) => true;
return entities.SplitEntity(
typeof(T1),
typeof(T2),
typeof(T3),
(
e,
v1,
v2,
v3) => test(e, (T1)v1, (T2)v2, (T3)v3));
}
/// <summary>
/// Splits the enumeration of entities into two separate enumerations, ones that
/// have the given generic components
/// and those which do not.
/// </summary>
/// <param name="entities">The entities to split into two lists.</param>
/// <param name="test">
/// An additional test function to determine if the entity is
/// included in the has list. If null, then entities with all the components will
/// be included.
/// </param>
/// <typeparam name="T1">
/// A component to require to be in included in the first list.
/// </typeparam>
/// <typeparam name="T2">
/// A component to require to be in included in the first list.
/// </typeparam>
/// <typeparam name="T3">
/// A component to require to be in included in the first list.
/// </typeparam>
/// <typeparam name="T4">
/// A component to require to be in included in the first list.
/// </typeparam>
/// <returns>A pair of enumerations, ones with the components and ones without.</returns>
public static SplitEntityEnumerations SplitEntity
<T1, T2, T3, T4>(
this IEnumerable<Entity> entities,
Func<Entity, T1, T2, T3, T4, bool>? test = null)
{
test ??= (
e,
v1,
v2,
v3,
v4) => true;
return entities.SplitEntity(
typeof(T1),
typeof(T2),
typeof(T3),
typeof(T4),
(
e,
v1,
v2,
v3,
v4) => test(e, (T1)v1, (T2)v2, (T3)v3, (T4)v4));
}
/// <summary>
/// Splits the enumeration of entities into two separate enumerations, ones that
/// have the given component types and those which do not.
/// </summary>
/// <param name="entities">The entities to split into two lists.</param>
/// <param name="t1">The type of a required component.</param>
/// <param name="test">
/// An additional test function to determine if the entity is
/// included in the has list. If null, then entities with all the components will
/// be included.
/// </param>
/// <returns>A pair of enumerations, ones with the components and ones without.</returns>
public static SplitEntityEnumerations SplitEntity(
this IEnumerable<Entity> entities,
Type t1,
Func<Entity, object, bool> test)
{
return SplitEntity(entities, a => a.Has(t1) && test(a, a.Get<object>(t1)));
}
/// <summary>
/// Splits the enumeration of entities into two separate enumerations, ones that
/// have the given component types and those which do not.
/// </summary>
/// <param name="entities">The entities to split into two lists.</param>
/// <param name="t1">The type of a required component.</param>
/// <param name="t2">The type of a required component.</param>
/// <param name="test">
/// An additional test function to determine if the entity is
/// included in the has list. If null, then entities with all the components will
/// be included.
/// </param>
/// <returns>A pair of enumerations, ones with the components and ones without.</returns>
public static SplitEntityEnumerations SplitEntity(
this IEnumerable<Entity> entities,
Type t1,
Type t2,
Func<Entity, object, object, bool> test)
{
return SplitEntity(entities, a => a.HasAll(t1, t2));
}
/// <summary>
/// Splits the enumeration of entities into two separate enumerations, ones that
/// have the given component types and those which do not.
/// </summary>
/// <param name="entities">The entities to split into two lists.</param>
/// <param name="t1">The type of a required component.</param>
/// <param name="t2">The type of a required component.</param>
/// <param name="t3">The type of a required component.</param>
/// <param name="test">
/// An additional test function to determine if the entity is
/// included in the has list. If null, then entities with all the components will
/// be included.
/// </param>
/// <returns>A pair of enumerations, ones with the components and ones without.</returns>
public static SplitEntityEnumerations SplitEntity(
this IEnumerable<Entity> entities,
Type t1,
Type t2,
Type t3,
Func<Entity, object, object, object, bool> test)
{
return SplitEntity(entities, a => a.HasAll(t1, t2, t3));
}
/// <summary>
/// Splits the enumeration of entities into two separate enumerations, ones that
/// have the given component types and those which do not.
/// </summary>
/// <param name="entities">The entities to split into two lists.</param>
/// <param name="t1">The type of a required component.</param>
/// <param name="t2">The type of a required component.</param>
/// <param name="t3">The type of a required component.</param>
/// <param name="t4">The type of a required component.</param>
/// <param name="test">
/// An additional test function to determine if the entity is
/// included in the has list. If null, then entities with all the components will
/// be included.
/// </param>
/// <returns>A pair of enumerations, ones with the components and ones without.</returns>
public static SplitEntityEnumerations SplitEntity(
this IEnumerable<Entity> entities,
Type t1,
Type t2,
Type t3,
Type t4,
Func<Entity, object, object, object, object, bool> test)
{
return SplitEntity(
entities,
a => a.HasAll(t1, t2, t3, t4)
&& test(
a,
a.Get<object>(t1),
a.Get<object>(t2),
a.Get<object>(t3),
a.Get<object>(t4)));
}
private static SplitEntityEnumerations SplitEntity(
IEnumerable<Entity> entities,
Func<Entity, bool> keySelector)
{
if (entities == null)
{
throw new ArgumentNullException(nameof(entities));
}
IEnumerable<IGrouping<bool, Entity>> group = entities
.GroupBy(keySelector, a => a)
.ToList();
IEnumerable<Entity>? has = group
.Where(a => a.Key)
.SelectMany(a => a);
IEnumerable<Entity>? hasNot = group
.Where(a => !a.Key)
.SelectMany(a => a);
return new SplitEntityEnumerations(has, hasNot);
}
}