DragonECS/src/EcsPipeline.Builder.cs

919 lines
38 KiB
C#
Raw Normal View History

2024-06-25 22:02:39 +08:00
using DCFApixels.DragonECS.Internal;
using DCFApixels.DragonECS.RunnersCore;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
2024-08-12 21:36:21 +08:00
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
2024-07-08 20:31:42 +08:00
using static DCFApixels.DragonECS.EcsConsts;
namespace DCFApixels.DragonECS
{
2024-08-12 21:36:21 +08:00
[MetaColor(MetaColor.DragonRose)]
[MetaGroup(PACK_GROUP, OTHER_GROUP)]
[MetaDescription(AUTHOR, "...")]
public interface IEcsAddParams
{
AddParams AddParams { get; }
}
[Serializable]
[StructLayout(LayoutKind.Auto)]
public struct AddParams : IEquatable<AddParams>
{
public static readonly AddParams Default = new AddParams();
2024-08-14 20:39:55 +08:00
public string layerName;
public int sortOrder;
public bool isUnique;
public AddParamsOverwriteFlags overrideFlags;
2024-08-12 21:36:21 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-08-14 20:39:55 +08:00
public AddParams(string layerName)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
this.layerName = layerName;
this.sortOrder = default;
this.isUnique = default;
overrideFlags = AddParamsOverwriteFlags.LayerName;
2024-08-12 21:36:21 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-08-14 20:39:55 +08:00
public AddParams(int sortOrder)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
this.layerName = default;
this.sortOrder = sortOrder;
this.isUnique = default;
overrideFlags = AddParamsOverwriteFlags.SortOrder;
2024-08-12 21:36:21 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-08-14 20:39:55 +08:00
public AddParams(bool isUnique)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
this.layerName = default;
this.sortOrder = default;
this.isUnique = isUnique;
overrideFlags = AddParamsOverwriteFlags.IsUnique;
2024-08-12 21:36:21 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-08-14 20:39:55 +08:00
public AddParams(string layerName, int sortOrder)
{
this.layerName = layerName;
this.sortOrder = sortOrder;
this.isUnique = default;
overrideFlags = AddParamsOverwriteFlags.LayerName | AddParamsOverwriteFlags.SortOrder;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public AddParams(string layerName, bool isUnique)
{
this.layerName = layerName;
this.sortOrder = default;
this.isUnique = isUnique;
overrideFlags = AddParamsOverwriteFlags.LayerName | AddParamsOverwriteFlags.IsUnique;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public AddParams(int sortOrder, bool isUnique)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
this.layerName = default;
this.sortOrder = sortOrder;
this.isUnique = isUnique;
overrideFlags = AddParamsOverwriteFlags.SortOrder | AddParamsOverwriteFlags.IsUnique;
2024-08-12 21:36:21 +08:00
}
2024-08-14 20:39:55 +08:00
2024-08-12 21:36:21 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-08-14 20:39:55 +08:00
public AddParams(string layerName, int sortOrder, bool isUnique)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
this.layerName = layerName;
this.sortOrder = sortOrder;
this.isUnique = isUnique;
overrideFlags = AddParamsOverwriteFlags.All;
2024-08-12 21:36:21 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-08-14 20:39:55 +08:00
public AddParams(string layerName, int sortOrder, bool isUnique, AddParamsOverwriteFlags overrideFlags)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
this.layerName = layerName;
this.sortOrder = sortOrder;
this.isUnique = isUnique;
this.overrideFlags = overrideFlags;
2024-08-12 21:36:21 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(AddParams other)
{
2024-08-14 20:39:55 +08:00
return sortOrder == other.sortOrder &&
layerName == other.layerName &&
isUnique == other.isUnique;
2024-08-12 21:36:21 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is AddParams && Equals((AddParams)obj);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
2024-08-14 20:39:55 +08:00
return HashCode.Combine(sortOrder, layerName, isUnique);
2024-08-12 21:36:21 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString()
{
2024-08-14 20:39:55 +08:00
return (overrideFlags.IsLayerName() ? "" : $"{layerName}, ") +
(overrideFlags.IsSortOrder() ? "" : $"{sortOrder}, ") +
(overrideFlags.IsIsUnique() ? "" : $"{isUnique}, ");
2024-08-12 21:36:21 +08:00
}
2024-08-14 20:39:55 +08:00
public AddParams Overwrite(AddParams other)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
AddParams result = this;
if (other.overrideFlags.IsLayerName())
{
result.layerName = other.layerName;
result.overrideFlags |= AddParamsOverwriteFlags.LayerName;
}
if (other.overrideFlags.IsSortOrder())
{
result.sortOrder = other.sortOrder;
result.overrideFlags |= AddParamsOverwriteFlags.SortOrder;
}
if (other.overrideFlags.IsIsUnique())
{
result.isUnique = other.isUnique;
result.overrideFlags |= AddParamsOverwriteFlags.IsUnique;
}
return result;
2024-08-12 21:36:21 +08:00
}
2024-08-14 20:39:55 +08:00
2024-08-12 21:36:21 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-08-14 20:39:55 +08:00
public static implicit operator AddParams(string a) { return new AddParams(a); }
2024-08-12 21:36:21 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-08-14 20:39:55 +08:00
public static implicit operator AddParams(int a) { return new AddParams(a); }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator AddParams(bool a) { return new AddParams(a); }
}
[Flags]
public enum AddParamsOverwriteFlags
{
None = 0,
LayerName = 1 << 0,
SortOrder = 1 << 1,
IsUnique = 1 << 2,
All = LayerName | SortOrder | IsUnique,
}
public static class AddParamsFlagsUtility
{
public static bool IsLayerName(this AddParamsOverwriteFlags flags) { return (flags & AddParamsOverwriteFlags.LayerName) != 0; }
public static bool IsSortOrder(this AddParamsOverwriteFlags flags) { return (flags & AddParamsOverwriteFlags.SortOrder) != 0; }
public static bool IsIsUnique(this AddParamsOverwriteFlags flags) { return (flags & AddParamsOverwriteFlags.IsUnique) != 0; }
2024-08-12 21:36:21 +08:00
}
2024-08-14 20:39:55 +08:00
public sealed partial class EcsPipeline
{
public class Builder : IEcsModule
{
2024-06-25 22:02:39 +08:00
private SystemRecord[] _systemRecords = new SystemRecord[256];
private int _systemRecordsCount = 0;
private int _systemRecordsInrement = 0;
2024-07-08 20:31:42 +08:00
private readonly Dictionary<string, LayerSystemsList> _layerLists = new Dictionary<string, LayerSystemsList>(8);
private readonly List<InitDeclaredRunner> _initDeclaredRunners = new List<InitDeclaredRunner>(4);
2024-06-25 22:02:39 +08:00
public readonly LayerList Layers;
public readonly Injector.Builder Injector;
public readonly Configurator Configs;
2024-08-14 20:39:55 +08:00
private AddParams _defaultAddParams;
2024-07-08 20:31:42 +08:00
#region Properties
2024-06-25 22:02:39 +08:00
private ReadOnlySpan<SystemRecord> SystemRecords
{
get { return new ReadOnlySpan<SystemRecord>(_systemRecords, 0, _systemRecordsCount); }
}
2024-07-08 20:31:42 +08:00
#endregion
#region Constructors
public Builder(IConfigContainerWriter config = null)
{
if (config == null) { config = new ConfigContainer(); }
Configs = new Configurator(config, this);
Injector = new Injector.Builder(this);
Injector.AddNode<object>();
Injector.AddNode<EcsWorld>();
Injector.AddNode<EcsAspect>();
Injector.AddNode<EcsPipeline>();
2024-07-08 20:31:42 +08:00
Layers = new LayerList(this, PRE_BEGIN_LAYER, BEGIN_LAYER, BASIC_LAYER, END_LAYER, POST_END_LAYER);
}
#endregion
2024-08-14 20:39:55 +08:00
#region Add IEcsProcess
public Builder Add(IEcsProcess system, string layerName)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
return AddSystem_Internal(system, new AddParams(layerName: layerName));
2024-08-12 21:36:21 +08:00
}
2024-08-14 20:39:55 +08:00
public Builder Add(IEcsProcess system, int sortOrder)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
return AddSystem_Internal(system, new AddParams(sortOrder: sortOrder));
2024-08-12 21:36:21 +08:00
}
2024-08-14 20:39:55 +08:00
public Builder Add(IEcsProcess system, bool isUnique)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
return AddSystem_Internal(system, new AddParams(isUnique: isUnique));
2024-08-12 21:36:21 +08:00
}
2024-08-14 20:39:55 +08:00
public Builder Add(IEcsProcess system, string layerName, int sortOrder)
{
2024-08-14 20:39:55 +08:00
return AddSystem_Internal(system, new AddParams(layerName: layerName, sortOrder: sortOrder));
}
2024-08-14 20:39:55 +08:00
public Builder Add(IEcsProcess system, string layerName, bool isUnique)
{
2024-08-14 20:39:55 +08:00
return AddSystem_Internal(system, new AddParams(layerName: layerName, isUnique: isUnique));
}
2024-08-14 20:39:55 +08:00
public Builder Add(IEcsProcess system, int sortOrder, bool isUnique)
{
2024-08-14 20:39:55 +08:00
return AddSystem_Internal(system, new AddParams(sortOrder: sortOrder, isUnique: isUnique));
}
2024-08-14 20:39:55 +08:00
public Builder Add(IEcsProcess system, string layerName, int sortOrder, bool isUnique)
{
2024-08-14 20:39:55 +08:00
return AddSystem_Internal(system, new AddParams(layerName: layerName, sortOrder: sortOrder, isUnique: isUnique));
}
2024-08-14 20:39:55 +08:00
public Builder AddUnique(IEcsProcess system, string layerName)
{
2024-08-14 20:39:55 +08:00
return AddSystem_Internal(system, new AddParams(layerName: layerName, isUnique: true));
}
public Builder AddUnique(IEcsProcess system, int sortOrder)
{
return AddSystem_Internal(system, new AddParams(sortOrder: sortOrder, isUnique: true));
}
public Builder AddUnique(IEcsProcess system, string layerName, int sortOrder)
{
return AddSystem_Internal(system, new AddParams(layerName: layerName, sortOrder: sortOrder, isUnique: true));
}
public Builder Add(IEcsProcess system, AddParams parameters)
{
return AddSystem_Internal(system, parameters);
}
private Stack<IEcsProcess> _moduleSystemsStack = null;
private Builder AddSystem_Internal(IEcsProcess system, AddParams settedAddParams)
{
AddParams prms = _defaultAddParams;
if (system is IEcsAddParams overrideInterface)
{
2024-08-14 20:39:55 +08:00
prms = prms.Overwrite(overrideInterface.AddParams);
}
2024-08-14 20:39:55 +08:00
prms = prms.Overwrite(settedAddParams);
if (system is IEcsModule module)//если система одновременно явялется и системой и модулем то за один Add будет вызван Add и AddModule
{
2024-08-14 20:39:55 +08:00
if (_moduleSystemsStack == null)
{
_moduleSystemsStack = new Stack<IEcsProcess>(4);
}
if (_moduleSystemsStack.Count <= 0 && system != _moduleSystemsStack.Peek())
{
_moduleSystemsStack.Push(system);
AddModule_Internal(module, prms);
_moduleSystemsStack.Pop();
return this;
}
}
2024-08-14 20:39:55 +08:00
AddRecord_Internal(system, prms.layerName, prms.sortOrder, prms.isUnique, _systemRecordsInrement++);
return this;
}
2024-08-07 10:40:31 +08:00
private void AddRecord_Internal(IEcsProcess system, string layer, int sortOrder, bool isUnique, int addOrder)
2024-06-25 22:02:39 +08:00
{
SystemRecord record = new SystemRecord(system, layer, addOrder, sortOrder, isUnique);
2024-06-25 23:35:51 +08:00
if (_layerLists.TryGetValue(layer, out LayerSystemsList list) == false)
2024-06-25 22:02:39 +08:00
{
list = new LayerSystemsList(layer);
_layerLists.Add(layer, list);
}
list.lasyInitSystemsCount++;
if (_systemRecords.Length <= _systemRecordsCount)
{
Array.Resize(ref _systemRecords, _systemRecordsCount << 1);
}
_systemRecords[_systemRecordsCount++] = record;
}
#endregion
2024-08-14 20:39:55 +08:00
#region AddModule IEcsModule
public Builder AddModule(IEcsModule module, string layerName)
2024-07-08 20:31:42 +08:00
{
2024-08-14 20:39:55 +08:00
return AddModule_Internal(module, new AddParams(layerName: layerName));
2024-07-08 20:31:42 +08:00
}
2024-08-14 20:39:55 +08:00
public Builder AddModule(IEcsModule module, int sortOrder)
{
2024-08-14 20:39:55 +08:00
return AddModule_Internal(module, new AddParams(sortOrder: sortOrder));
2024-08-07 10:40:31 +08:00
}
2024-08-14 20:39:55 +08:00
public Builder AddModule(IEcsModule module, bool isUnique)
2024-08-07 10:40:31 +08:00
{
2024-08-14 20:39:55 +08:00
return AddModule_Internal(module, new AddParams(isUnique: isUnique));
2024-07-08 20:31:42 +08:00
}
2024-08-14 20:39:55 +08:00
public Builder AddModule(IEcsModule module, string layerName, int sortOrder)
2024-08-07 10:40:31 +08:00
{
2024-08-14 20:39:55 +08:00
return AddModule_Internal(module, new AddParams(layerName: layerName, sortOrder: sortOrder));
2024-08-07 10:40:31 +08:00
}
2024-08-14 20:39:55 +08:00
public Builder AddModule(IEcsModule module, string layerName, bool isUnique)
2024-07-08 20:31:42 +08:00
{
2024-08-14 20:39:55 +08:00
return AddModule_Internal(module, new AddParams(layerName: layerName, isUnique: isUnique));
}
public Builder AddModule(IEcsModule module, int sortOrder, bool isUnique)
{
return AddModule_Internal(module, new AddParams(sortOrder: sortOrder, isUnique: isUnique));
}
public Builder AddModule(IEcsModule module, string layerName, int sortOrder, bool isUnique)
{
return AddModule_Internal(module, new AddParams(layerName: layerName, sortOrder: sortOrder, isUnique: isUnique));
}
public Builder AddModuleUnique(IEcsModule module, string layerName)
{
return AddModule_Internal(module, new AddParams(layerName: layerName, isUnique: true));
}
public Builder AddModuleUnique(IEcsModule module, int sortOrder)
{
return AddModule_Internal(module, new AddParams(sortOrder: sortOrder, isUnique: true));
}
public Builder AddModuleUnique(IEcsModule module, string layerName, int sortOrder)
{
return AddModule_Internal(module, new AddParams(layerName: layerName, sortOrder: sortOrder, isUnique: true));
}
public Builder AddModule(IEcsModule module, AddParams parameters)
{
return AddModule_Internal(module, parameters);
}
private Builder AddModule_Internal(IEcsModule module, AddParams settedAddParams)
{
AddParams prms = _defaultAddParams;
if (module is IEcsAddParams overrideInterface)
2024-07-08 20:31:42 +08:00
{
2024-08-14 20:39:55 +08:00
prms = prms.Overwrite(overrideInterface.AddParams);
2024-07-08 20:31:42 +08:00
}
2024-08-14 20:39:55 +08:00
_defaultAddParams = prms.Overwrite(settedAddParams);
2024-07-08 20:31:42 +08:00
module.Import(this);
2024-08-14 20:39:55 +08:00
2024-08-12 21:36:21 +08:00
return this;
}
#endregion
2024-08-14 20:39:55 +08:00
#region Add Raw
public Builder Add(object raw, string layerName)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
return AddRaw_Internal(raw, new AddParams(layerName: layerName));
2024-08-12 21:36:21 +08:00
}
2024-08-14 20:39:55 +08:00
public Builder Add(object raw, int sortOrder)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
return AddRaw_Internal(raw, new AddParams(sortOrder: sortOrder));
2024-08-12 21:36:21 +08:00
}
2024-08-14 20:39:55 +08:00
public Builder Add(object raw, bool isUnique)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
return AddRaw_Internal(raw, new AddParams(isUnique: isUnique));
2024-08-12 21:36:21 +08:00
}
2024-08-14 20:39:55 +08:00
public Builder Add(object raw, string layerName, int sortOrder)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
return AddRaw_Internal(raw, new AddParams(layerName: layerName, sortOrder: sortOrder));
2024-08-12 21:36:21 +08:00
}
2024-08-14 20:39:55 +08:00
public Builder Add(object raw, string layerName, bool isUnique)
2024-08-12 21:36:21 +08:00
{
2024-08-14 20:39:55 +08:00
return AddRaw_Internal(raw, new AddParams(layerName: layerName, isUnique: isUnique));
}
public Builder Add(object raw, int sortOrder, bool isUnique)
{
return AddRaw_Internal(raw, new AddParams(sortOrder: sortOrder, isUnique: isUnique));
}
public Builder Add(object raw, string layerName, int sortOrder, bool isUnique)
{
return AddRaw_Internal(raw, new AddParams(layerName: layerName, sortOrder: sortOrder, isUnique: isUnique));
}
public Builder AddUnique(object raw, string layerName)
{
return AddRaw_Internal(raw, new AddParams(layerName: layerName, isUnique: true));
}
public Builder AddUnique(object raw, int sortOrder)
{
return AddRaw_Internal(raw, new AddParams(sortOrder: sortOrder, isUnique: true));
}
public Builder AddUnique(object raw, string layerName, int sortOrder)
{
return AddRaw_Internal(raw, new AddParams(layerName: layerName, sortOrder: sortOrder, isUnique: true));
}
public Builder Add(object raw, AddParams parameters)
{
return AddRaw_Internal(raw, parameters);
}
private Builder AddRaw_Internal(object raw, AddParams settedAddParams)
{
switch (raw)
{
case IEcsProcess system: return AddSystem_Internal(system, settedAddParams);
case IEcsModule module: return AddModule_Internal(module, settedAddParams);
default: Throw.UndefinedException(); return this;
}
}
2024-07-08 20:31:42 +08:00
#endregion
#region Add other
public Builder AddRunner<TRunner>() where TRunner : EcsRunner, IEcsRunner, new()
{
_initDeclaredRunners.Add(new InitDeclaredRunner<TRunner>());
return this;
}
void IEcsModule.Import(Builder into)
{
into.MergeWith(this);
}
private void MergeWith(Builder other)
{
Injector.Add(other.Injector);
foreach (var declaredRunners in other._initDeclaredRunners)
{
_initDeclaredRunners.Add(declaredRunners);
}
foreach (var config in other.Configs.Instance.GetAllConfigs())
{
Configs.Instance.Set(config.Key, config.Value);
}
Layers.MergeWith(other.Layers);
2024-06-25 22:02:39 +08:00
//_systemRecordsInrement + otherRecord.addOrder смещает порядок так что новые системы встают в конец очереди, но сохраняют порядок addOrder
foreach (var otherRecord in other.SystemRecords)
{
2024-08-07 10:40:31 +08:00
AddRecord_Internal(otherRecord.system, otherRecord.layer, otherRecord.sortOrder, otherRecord.isUnique, _systemRecordsInrement + otherRecord.addOrder);
}
2024-06-25 22:02:39 +08:00
_systemRecordsInrement += other._systemRecordsInrement;
}
#endregion
#region Remove
2024-06-25 22:02:39 +08:00
private void RemoveAt(int index)
{
ref var slot = ref _systemRecords[index];
_layerLists[slot.layer].lasyInitSystemsCount--;
slot = _systemRecords[--_systemRecordsCount];
}
public Builder Remove<TSystem>()
{
2024-06-25 22:02:39 +08:00
for (int i = 0; i < _systemRecordsCount; i++)
{
2024-06-25 22:02:39 +08:00
if (_systemRecords[i].system is TSystem)
{
RemoveAt(i--);
}
}
return this;
}
#endregion
#region Build
2024-06-25 22:02:39 +08:00
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
private EcsProfilerMarker _buildBarker = new EcsProfilerMarker("EcsPipeline.Build");
#endif
public EcsPipeline Build()
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
_buildBarker.Begin();
#endif
2024-06-25 22:02:39 +08:00
LayerSystemsList basicLayerList;
if (_layerLists.TryGetValue(BASIC_LAYER, out basicLayerList) == false)
{
basicLayerList = new LayerSystemsList(BASIC_LAYER);
_layerLists.Add(BASIC_LAYER, basicLayerList);
}
HashSet<Type> uniqueSystemsSet = new HashSet<Type>();
int allSystemsLength = 0;
2024-06-25 22:02:39 +08:00
foreach (var item in _layerLists)
{
2024-06-25 22:02:39 +08:00
if (item.Key == BASIC_LAYER) { continue; }
if (!Layers.Contains(item.Key))
{
2024-06-25 22:02:39 +08:00
basicLayerList.lasyInitSystemsCount += item.Value.lasyInitSystemsCount;
}
else
{
2024-06-25 22:02:39 +08:00
item.Value.Init();
allSystemsLength += item.Value.lasyInitSystemsCount + 1;
}
}
2024-06-25 22:02:39 +08:00
allSystemsLength += basicLayerList.lasyInitSystemsCount + 1;
basicLayerList.Init();
for (int i = 0, iMax = _systemRecordsCount; i < iMax; i++)
{
ref var record = ref _systemRecords[i];
var list = _layerLists[record.layer];
2024-06-25 23:35:51 +08:00
if (list.IsInit == false)
2024-06-25 22:02:39 +08:00
{
list = basicLayerList;
}
2024-06-25 23:35:51 +08:00
if (record.isUnique == false || uniqueSystemsSet.Add(record.system.GetType()))
2024-06-25 22:02:39 +08:00
{
list.Add(record.system, record.addOrder, record.sortOrder, record.isUnique);
}
}
IEcsProcess[] allSystems = new IEcsProcess[allSystemsLength];
{
int i = 0;
foreach (var item in Layers)
{
2024-06-25 22:02:39 +08:00
if (_layerLists.TryGetValue(item, out var list) && list.IsInit)
{
2024-06-25 22:02:39 +08:00
list.Sort();
for (int j = 0; j < list.recordsCount; j++)
{
allSystems[i++] = list.records[j].system;
}
}
}
}
EcsPipeline pipeline = new EcsPipeline(Configs.Instance.GetContainer(), Injector, allSystems);
foreach (var item in _initDeclaredRunners)
{
item.Declare(pipeline);
}
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
_buildBarker.End();
#endif
return pipeline;
}
#endregion
#region InitDeclaredRunner
private abstract class InitDeclaredRunner
{
public abstract void Declare(EcsPipeline pipeline);
}
private class InitDeclaredRunner<T> : InitDeclaredRunner where T : EcsRunner, IEcsRunner, new()
{
public override void Declare(EcsPipeline pipeline)
{
pipeline.GetRunnerInstance<T>();
}
}
#endregion
#region Configurator
public class Configurator
{
private readonly IConfigContainerWriter _configs;
private readonly Builder _builder;
public Configurator(IConfigContainerWriter configs, Builder builder)
{
_configs = configs;
_builder = builder;
}
public IConfigContainerWriter Instance
{
get { return _configs; }
}
public Builder Set<T>(T value)
{
_configs.Set(value);
return _builder;
}
}
#endregion
#region LayerList
public class LayerList : IEnumerable<string>
{
private const string ADD_LAYER = nameof(ADD_LAYER); // автоматический слой нужный только для метода Add
private Builder _source;
private List<string> _layers;
private string _basicLayerName;
public int Count { get { return _layers.Count; } }
public object this[int index] { get { return _layers[index]; } }
public LayerList(Builder source, string basicLayerName)
{
_source = source;
_layers = new List<string>(16) { basicLayerName, ADD_LAYER };
_basicLayerName = basicLayerName;
}
2024-07-08 20:31:42 +08:00
public LayerList(Builder source, string preBeginlayer, string beginlayer, string basicLayer, string endLayer, string postEndLayer)
{
_source = source;
_layers = new List<string>(16) { preBeginlayer, beginlayer, basicLayer, ADD_LAYER, endLayer, postEndLayer };
_basicLayerName = basicLayer;
}
public Builder Add(string newLayer) { return Insert(ADD_LAYER, newLayer); }
public Builder Insert(string targetLayer, string newLayer)
{
if (Contains(newLayer)) { return _source; }
int index = _layers.IndexOf(targetLayer);
if (index < 0)
{
throw new KeyNotFoundException($"Layer {targetLayer} not found");
}
_layers.Insert(index, newLayer);
return _source;
}
public Builder InsertAfter(string targetLayer, string newLayer)
{
if (Contains(newLayer)) { return _source; }
if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER
{
targetLayer = ADD_LAYER;
}
int index = _layers.IndexOf(targetLayer);
if (index < 0)
{
throw new KeyNotFoundException($"Layer {targetLayer} not found");
}
if (++index >= _layers.Count)
{
_layers.Add(newLayer);
}
else
{
_layers.Insert(index, newLayer);
}
return _source;
}
public Builder Move(string targetLayer, string movingLayer)
{
_layers.Remove(movingLayer);
return Insert(targetLayer, movingLayer);
}
public Builder MoveAfter(string targetLayer, string movingLayer)
{
if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER
{
targetLayer = ADD_LAYER;
}
_layers.Remove(movingLayer);
return InsertAfter(targetLayer, movingLayer);
}
public Builder Add(params string[] newLayers) { return Insert(ADD_LAYER, newLayers); }
public Builder Insert(string targetLayer, params string[] newLayers)
{
int index = _layers.IndexOf(targetLayer);
if (index < 0)
{
throw new KeyNotFoundException($"Layer {targetLayer} not found");
}
_layers.InsertRange(index, newLayers.Where(o => !Contains(o)));
return _source;
}
public Builder InsertAfter(string targetLayer, params string[] newLayers)
{
int index = _layers.IndexOf(targetLayer);
if (index < 0)
{
throw new KeyNotFoundException($"Layer {targetLayer} not found");
}
if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER
{
targetLayer = ADD_LAYER;
}
if (++index >= _layers.Count)
{
_layers.AddRange(newLayers.Where(o => !Contains(o)));
}
else
{
_layers.InsertRange(index, newLayers.Where(o => !Contains(o)));
}
return _source;
}
public Builder Move(string targetLayer, params string[] movingLayers)
{
foreach (var movingLayer in movingLayers)
{
_layers.Remove(movingLayer);
}
return Insert(targetLayer, movingLayers);
}
public Builder MoveAfter(string targetLayer, params string[] movingLayers)
{
if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER
{
targetLayer = ADD_LAYER;
}
foreach (var movingLayer in movingLayers)
{
_layers.Remove(movingLayer);
}
return InsertAfter(targetLayer, movingLayers);
}
2024-06-26 00:07:31 +08:00
public void MergeWith(IReadOnlyList<string> other)
{
HashSet<string> seen = new HashSet<string>();
List<string> result = new List<string>();
List<string> listA = _layers;
2024-06-26 00:07:31 +08:00
IReadOnlyList<string> listB = other;
foreach (string item in listA)
{
seen.Add(item);
}
foreach (string item in listB)
{
if (seen.Add(item) == false)
{
seen.Remove(item);
}
}
int i = 0, j = 0;
while (i < listA.Count || j < listB.Count)
{
while (i < listA.Count && seen.Contains(listA[i]))
{
result.Add(listA[i]);
i++;
}
while (j < listB.Count && seen.Contains(listB[j]))
{
result.Add(listB[j]);
j++;
}
if (i < listA.Count) { i++; }
if (j < listB.Count)
{
result.Add(listB[j]);
j++;
}
}
_layers = result;
}
2024-06-26 00:07:31 +08:00
public void MergeWith(LayerList other)
{
MergeWith(other._layers);
}
public bool Contains(string layer) { return _layers.Contains(layer); }
public List<string>.Enumerator GetEnumerator() { return _layers.GetEnumerator(); }
IEnumerator<string> IEnumerable<string>.GetEnumerator() { return _layers.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return _layers.GetEnumerator(); }
}
#endregion
#region SystemsList
2024-06-25 22:02:39 +08:00
private class LayerSystemsList
{
2024-06-25 22:02:39 +08:00
public int lasyInitSystemsCount = 0;
public Item[] records = null;
public int recordsCount = 0;
2024-06-25 20:24:11 +08:00
2024-08-07 10:40:31 +08:00
//отслеживание осортированности систем
private int _lastSortOrder;
private int _lastAddOrder;
2024-06-25 22:02:39 +08:00
private bool _isSorted = true;
private string _layerName;
public bool IsInit { get { return records != null; } }
public bool IsSorted { get { return _isSorted; } }
public ReadOnlySpan<Item> Records { get { return new ReadOnlySpan<Item>(records, 1, recordsCount - 1); } }
public LayerSystemsList(string layerName) { _layerName = layerName; }
public void Init()
{
2024-06-25 22:02:39 +08:00
if (IsInit) { Throw.UndefinedException(); }
records = new Item[lasyInitSystemsCount + 1];
Add(new SystemsLayerMarkerSystem(_layerName), int.MinValue, int.MinValue, false);
}
2024-06-25 22:02:39 +08:00
public void AddList(LayerSystemsList other)
{
for (int i = 1; i < other.recordsCount; i++)
{
var otherRecord = other.records[i];
2024-08-07 10:40:31 +08:00
AddItem_Internal(otherRecord);
}
}
public void Add(IEcsProcess system, int addOrder, int sortOrder, bool isUnique)
{
2024-08-07 10:40:31 +08:00
AddItem_Internal(new Item(system, addOrder, sortOrder, isUnique));
2024-06-25 22:02:39 +08:00
}
2024-08-07 10:40:31 +08:00
private void AddItem_Internal(Item item)
2024-06-25 22:02:39 +08:00
{
if (_isSorted)
{
if (recordsCount <= 1)
{
_lastSortOrder = item.sortOrder;
2024-08-07 10:40:31 +08:00
_lastAddOrder = item.addOrder;
2024-08-14 20:39:55 +08:00
}
2024-08-07 10:40:31 +08:00
else if (_lastSortOrder > item.sortOrder || _lastAddOrder > item.addOrder)
{
_isSorted = false;
}
2024-08-07 10:40:31 +08:00
else
{
2024-08-07 10:40:31 +08:00
_lastSortOrder = item.sortOrder;
_lastAddOrder = item.addOrder;
}
}
if (records.Length <= recordsCount)
{
Array.Resize(ref records, recordsCount << 1);
}
2024-06-25 22:02:39 +08:00
records[recordsCount++] = item;
}
public void RemoveAll<T>()
{
2024-06-25 22:02:39 +08:00
for (int i = 0; i < recordsCount; i++)
{
2024-06-25 22:02:39 +08:00
if (records[i].system is T)
{
2024-06-25 22:02:39 +08:00
records[i] = records[--recordsCount];
}
}
2024-06-25 22:02:39 +08:00
_isSorted = false;
}
public void Sort()
{
2024-06-25 22:02:39 +08:00
if (_isSorted) { return; }
//Игнорирую первую систему, так как это чисто система с названием слоя
Array.Sort(records, 1, recordsCount - 1);
2024-06-25 22:02:39 +08:00
_isSorted = true;
2024-08-07 10:40:31 +08:00
_lastSortOrder = records[recordsCount - 1].sortOrder;
_lastAddOrder = records[recordsCount - 1].addOrder;
}
}
2024-06-25 22:02:39 +08:00
private readonly struct Item : IComparable<Item>
{
public readonly IEcsProcess system;
2024-06-25 22:02:39 +08:00
public readonly int addOrder;
2024-06-25 20:24:11 +08:00
public readonly int sortOrder;
2024-06-25 15:31:25 +08:00
public readonly bool isUnique;
2024-06-25 22:02:39 +08:00
public Item(IEcsProcess system, int addOrder, int sortOrder, bool isUnique)
{
this.system = system;
2024-06-25 22:02:39 +08:00
this.addOrder = addOrder;
2024-06-25 20:24:11 +08:00
this.sortOrder = sortOrder;
2024-06-25 15:31:25 +08:00
this.isUnique = isUnique;
}
2024-06-25 22:02:39 +08:00
public int CompareTo(Item other)
2024-06-25 20:24:11 +08:00
{
int c = sortOrder - other.sortOrder;
2024-06-25 22:02:39 +08:00
return c == 0 ? addOrder - other.addOrder : c;
2024-06-25 20:24:11 +08:00
}
}
#endregion
2024-06-25 22:02:39 +08:00
#region SerializableTemplate
public EcsPipelineTemplate GenerateSerializableTemplate()
{
Array.Sort(_systemRecords, 0, _systemRecordsCount);
var records = SystemRecords;
EcsPipelineTemplate result = new EcsPipelineTemplate();
result.layers = new string[Layers.Count];
result.systems = new EcsPipelineTemplate.SystemRecord[records.Length];
for (int i = 0; i < records.Length; i++)
{
var r = records[i];
result.systems[i] = new EcsPipelineTemplate.SystemRecord(r.system, r.layer, r.sortOrder, r.isUnique);
}
2024-06-25 22:02:39 +08:00
return result;
}
#endregion
2024-08-14 20:39:55 +08:00
[StructLayout(LayoutKind.Auto)]
private readonly struct SystemRecord : IComparable<SystemRecord>
2024-06-25 22:02:39 +08:00
{
public readonly IEcsProcess system;
public readonly string layer;
public readonly int addOrder;
public readonly int sortOrder;
public readonly bool isUnique;
public SystemRecord(IEcsProcess system, string layer, int addOrder, int sortOrder, bool isUnique)
{
this.system = system;
this.layer = layer;
this.addOrder = addOrder;
this.sortOrder = sortOrder;
this.isUnique = isUnique;
}
public int CompareTo(SystemRecord other)
{
int c = sortOrder - other.sortOrder;
return c == 0 ? addOrder - other.addOrder : c;
}
2024-06-25 22:02:39 +08:00
}
}
}
}