diff --git a/src/Archetype.cs b/src/Archetype.cs index ae64090..d3020cb 100644 --- a/src/Archetype.cs +++ b/src/Archetype.cs @@ -336,7 +336,7 @@ internal int FindMatch(ReadOnlySpan searching) ref readonly var current = ref currents[i]; ref readonly var search = ref searching[j]; - if (_comparer.Compare(current.ID, search.ID) == 0) + if (current.ID.CompareTo(search.ID) == 0) { if (search.Op != TermOp.With) return -1; diff --git a/tools/TinyEcs.Generator/Program.cs b/tools/TinyEcs.Generator/Program.cs index 546c253..3701fe7 100644 --- a/tools/TinyEcs.Generator/Program.cs +++ b/tools/TinyEcs.Generator/Program.cs @@ -107,49 +107,39 @@ public partial {className}{filter} sb.AppendLine($@" public void Query<{typeParams}>({delegateName}<{typeParams}> fn) {whereParams} {{ - var hash = Lookup.Query<{(i > 0 ? "(" : "")}{typeParams}{(i > 0 ? ")" : "")}{filterMethod}>.Hash; var terms = Lookup.Query<{(i > 0 ? "(" : "")}{typeParams}{(i > 0 ? ")" : "")}{filterMethod}>.Terms.AsSpan(); - var withouts = Lookup.Query<{(i > 0 ? "(" : "")}{typeParams}{(i > 0 ? ")" : "")}{filterMethod}>.Withouts; - var arch = {(withFilter ? "_world." : "")}FindArchetype(hash, terms); - if (arch == null) return; - InternalQuery(arch, fn, terms, withouts); - - static void InternalQuery - ( - Archetype arch, - {delegateName}<{typeParams}> fn, - ReadOnlySpan terms, - IDictionary withouts - ) + var query = new QueryInternal({(withFilter ? "_world." : "")}Archetypes, terms); + + foreach (var arch in query) {{ - if (arch.Count > 0) + {columnIndices} + + foreach (ref readonly var chunk in arch) {{ - {columnIndices} + {fieldList} + ref var last = ref Unsafe.Add(ref t0A, chunk.Count - 4); + ref var last2 = ref Unsafe.Add(ref t0A, chunk.Count); - foreach (ref readonly var chunk in arch) + while (Unsafe.IsAddressLessThan(ref t0A, ref last)) {{ - {fieldList} - ref var last = ref Unsafe.Add(ref t0A, chunk.Count); - - while (Unsafe.IsAddressLessThan(ref t0A, ref last)) - {{ - fn({signCallback}); - {advanceField} - }} - }} - }} + fn({signCallback}); + {advanceField} - var span = CollectionsMarshal.AsSpan(arch._edgesRight); + fn({signCallback}); + {advanceField} - ref var start = ref MemoryMarshal.GetReference(span); - ref var end = ref Unsafe.Add(ref start, span.Length); + fn({signCallback}); + {advanceField} - while (Unsafe.IsAddressLessThan(ref start, ref end)) - {{ - if (!withouts.ContainsKey(start.ComponentID)) - InternalQuery(start.Archetype, fn, terms, withouts); + fn({signCallback}); + {advanceField} + }} - start = ref Unsafe.Add(ref start, 1); + while (Unsafe.IsAddressLessThan(ref t0A, ref last2)) + {{ + fn({signCallback}); + {advanceField} + }} }} }} }} @@ -161,6 +151,104 @@ IDictionary withouts return sb.ToString(); } + // static string GenerateFilterQuery(bool withFilter, bool withEntityView) + // { + // var className = withFilter ? "struct FilterQuery" : "class World"; + // var filter = withFilter ? "" : ""; + // var filterMethod = withFilter ? ", TFilter" : ""; + // var delegateName = withEntityView ? "QueryFilterDelegateWithEntity" : "QueryFilterDelegate"; + + // var sb = new StringBuilder(); + // sb.AppendLine($@" + // public partial {className}{filter} + // {{ + // "); + + // for (var i = 0; i < MAX_GENERICS; ++i) + // { + // var typeParams = GenerateSequence(i + 1, ", ", j => $"T{j}"); + // var whereParams = GenerateSequence(i + 1, " ",j => $"where T{j} : struct"); + // var columnIndices = GenerateSequence(i + 1, "\n" , j => $"var column{j} = arch.GetComponentIndex();"); + // var fieldList = (withEntityView ? "ref var entityA = ref chunk.Entities[0];\n" : "") + + // GenerateSequence(i + 1, "\n" , j => $"ref var t{j}A = ref chunk.GetReference(column{j});"); + // var signCallback = (withEntityView ? "entityA, " : "") + + // GenerateSequence(i + 1, ", " , j => $"ref t{j}A"); + // var advanceField = (withEntityView ? "entityA = ref Unsafe.Add(ref entityA, 1);\n" : "") + + // GenerateSequence(i + 1, "\n" , j => $"t{j}A = ref Unsafe.Add(ref t{j}A, 1);"); + + // sb.AppendLine($@" + // public void Query<{typeParams}>({delegateName}<{typeParams}> fn) {whereParams} + // {{ + // var hash = Lookup.Query<{(i > 0 ? "(" : "")}{typeParams}{(i > 0 ? ")" : "")}{filterMethod}>.Hash; + // var terms = Lookup.Query<{(i > 0 ? "(" : "")}{typeParams}{(i > 0 ? ")" : "")}{filterMethod}>.Terms.AsSpan(); + // var withouts = Lookup.Query<{(i > 0 ? "(" : "")}{typeParams}{(i > 0 ? ")" : "")}{filterMethod}>.Withouts; + // var arch = {(withFilter ? "_world." : "")}FindArchetype(hash, terms); + // if (arch == null) return; + // InternalQuery(arch, fn, terms, withouts); + + // static void InternalQuery + // ( + // Archetype arch, + // {delegateName}<{typeParams}> fn, + // ReadOnlySpan terms, + // IDictionary withouts + // ) + // {{ + // if (arch.Count > 0) + // {{ + // {columnIndices} + + // foreach (ref readonly var chunk in arch) + // {{ + // {fieldList} + // ref var last = ref Unsafe.Add(ref t0A, chunk.Count - 4); + // ref var last2 = ref Unsafe.Add(ref t0A, chunk.Count); + + // while (Unsafe.IsAddressLessThan(ref t0A, ref last)) + // {{ + // fn({signCallback}); + // {advanceField} + + // fn({signCallback}); + // {advanceField} + + // fn({signCallback}); + // {advanceField} + + // fn({signCallback}); + // {advanceField} + // }} + + // while (Unsafe.IsAddressLessThan(ref t0A, ref last2)) + // {{ + // fn({signCallback}); + // {advanceField} + // }} + // }} + // }} + + // var span = CollectionsMarshal.AsSpan(arch._edgesRight); + + // ref var start = ref MemoryMarshal.GetReference(span); + // ref var end = ref Unsafe.Add(ref start, span.Length); + + // while (Unsafe.IsAddressLessThan(ref start, ref end)) + // {{ + // if (!withouts.ContainsKey(start.ComponentID)) + // InternalQuery(start.Archetype, fn, terms, withouts); + + // start = ref Unsafe.Add(ref start, 1); + // }} + // }} + // }} + // "); + // } + + // sb.AppendLine("}"); + + // return sb.ToString(); + // } + static string GenerateSequence(int count, string separator, Func generator) { var sb = new StringBuilder();