@@ -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