Skip to content

Commit 830ebd8

Browse files
committed
reworked the insert
1 parent bf9d195 commit 830ebd8

1 file changed

Lines changed: 73 additions & 15 deletions

File tree

src/TinyEcs/Archetype.cs

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -341,10 +341,19 @@ internal EcsID Remove(ref EcsRecord record)
341341
internal Archetype InsertVertex(Archetype left, ComponentInfo[] sign, EcsID id)
342342
{
343343
var vertex = new Archetype(left._world, sign, _comparer);
344-
var a = left.All.Length < vertex.All.Length ? left : vertex;
345-
var b = left.All.Length < vertex.All.Length ? vertex : left;
346-
MakeEdges(a, b, id);
347-
InsertVertex(vertex);
344+
var leftIsSubset = left.All.Length < vertex.All.Length;
345+
346+
if (leftIsSubset)
347+
{
348+
ConnectSubsetSuperset(left, vertex, id, true);
349+
InsertVertex(vertex, left);
350+
}
351+
else
352+
{
353+
ConnectSubsetSuperset(vertex, left, id, false);
354+
InsertVertex(vertex, null);
355+
}
356+
348357
return vertex;
349358
}
350359

@@ -413,35 +422,84 @@ internal void RemoveEmptyArchetypes(ref int removed, Dictionary<EcsID, Archetype
413422
}
414423
}
415424

416-
private static void MakeEdges(Archetype left, Archetype right, EcsID id)
425+
private static void ConnectSubsetSuperset(Archetype subset, Archetype superset, EcsID id, bool registerInSubsetAdd)
426+
{
427+
if (registerInSubsetAdd)
428+
{
429+
var addEdges = CollectionsMarshal.AsSpan(subset._add);
430+
var exists = false;
431+
foreach (ref var edge in addEdges)
432+
{
433+
if (edge.Archetype == superset && edge.Id == id)
434+
{
435+
exists = true;
436+
break;
437+
}
438+
}
439+
440+
if (!exists)
441+
{
442+
subset._add.Add(new EcsEdge { Archetype = superset, Id = id });
443+
}
444+
}
445+
446+
var removeEdges = CollectionsMarshal.AsSpan(superset._remove);
447+
foreach (ref var edge in removeEdges)
448+
{
449+
if (edge.Archetype == subset && edge.Id == id)
450+
return;
451+
}
452+
453+
superset._remove.Add(new EcsEdge { Archetype = subset, Id = id });
454+
}
455+
456+
private static void AddEdgeOnly(Archetype subset, Archetype superset, EcsID id)
417457
{
418-
// Check if edge already exists to avoid duplicates
419-
foreach (ref var edge in CollectionsMarshal.AsSpan(left._add))
458+
var addEdges = CollectionsMarshal.AsSpan(subset._add);
459+
foreach (ref var edge in addEdges)
420460
{
421-
if (edge.Archetype == right && edge.Id == id)
422-
return; // Edge already exists
461+
if (edge.Archetype == superset && edge.Id == id)
462+
return;
423463
}
424464

425-
left._add.Add(new EcsEdge() { Archetype = right, Id = id });
426-
right._remove.Add(new EcsEdge() { Archetype = left, Id = id });
465+
subset._add.Add(new EcsEdge { Archetype = superset, Id = id });
427466
}
428467

429-
private void InsertVertex(Archetype newNode)
468+
private void InsertVertex(Archetype newNode, Archetype? preferredParent)
430469
{
431470
var all = newNode.All;
432471
if (all.Length == 0)
433472
return;
434473

435474
var world = newNode._world;
436-
for (var i = 0; i < all.Length; ++i)
475+
var addParent = preferredParent;
476+
477+
for (var i = all.Length - 1; i >= 0; --i)
437478
{
438479
ref readonly var component = ref all[i];
439480
var subsetId = newNode.ComputeHashWithout(component.ID);
440481

441-
if (world.TryGetArchetype(subsetId, out var subset))
482+
if (!world.TryGetArchetype(subsetId, out var subset))
483+
continue;
484+
485+
var register = false;
486+
if (preferredParent != null && ReferenceEquals(subset, preferredParent))
487+
{
488+
register = true;
489+
addParent = preferredParent;
490+
}
491+
else if (addParent == null)
442492
{
443-
MakeEdges(subset!, newNode, component.ID);
493+
addParent = subset;
494+
register = true;
444495
}
496+
497+
ConnectSubsetSuperset(subset!, newNode, component.ID, register);
498+
}
499+
500+
if (addParent == null)
501+
{
502+
AddEdgeOnly(this, newNode, all[^1].ID);
445503
}
446504
}
447505

0 commit comments

Comments
 (0)