transfer relations in order
							parent
							
								
									3cba3e047c
								
							
						
					
					
						commit
						2aa8fc87e7
					
				|  | @ -6,11 +6,13 @@ namespace MoonTools.ECS | |||
| { | ||||
| 	internal class RelationDepot | ||||
| 	{ | ||||
| 		private EntityStorage EntityStorage; | ||||
| 		private TypeIndices RelationTypeIndices; | ||||
| 		private RelationStorage[] storages = new RelationStorage[256]; | ||||
| 
 | ||||
| 		public RelationDepot(TypeIndices relationTypeIndices) | ||||
| 		public RelationDepot(EntityStorage entityStorage, TypeIndices relationTypeIndices) | ||||
| 		{ | ||||
| 			EntityStorage = entityStorage; | ||||
| 			RelationTypeIndices = relationTypeIndices; | ||||
| 		} | ||||
| 
 | ||||
|  | @ -123,26 +125,11 @@ namespace MoonTools.ECS | |||
| 			storages[relationTypeIndex].Set(entityA, entityB, relationData); | ||||
| 		} | ||||
| 
 | ||||
| 		public int GetStorageIndex(int relationTypeIndex, int entityA, int entityB) | ||||
| 		{ | ||||
| 			return storages[relationTypeIndex].GetStorageIndex(entityA, entityB); | ||||
| 		} | ||||
| 
 | ||||
| 		public unsafe void* Get(int relationTypeIndex, int relationStorageIndex) | ||||
| 		{ | ||||
| 			return storages[relationTypeIndex].Get(relationStorageIndex); | ||||
| 		} | ||||
| 
 | ||||
| 		public void UnrelateAll(int entityID, int relationTypeIndex) | ||||
| 		{ | ||||
| 			storages[relationTypeIndex].UnrelateAll(entityID); | ||||
| 		} | ||||
| 
 | ||||
| 		public ReverseSpanEnumerator<Entity> OutRelations(int entityID, int relationTypeIndex) | ||||
| 		{ | ||||
| 			return storages[relationTypeIndex].OutRelations(entityID); | ||||
| 		} | ||||
| 
 | ||||
| 		public void Clear() | ||||
| 		{ | ||||
| 			for (var i = 0; i < storages.Length; i += 1) | ||||
|  | @ -174,5 +161,33 @@ namespace MoonTools.ECS | |||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public unsafe void TransferStorage(Dictionary<int, int> worldToTransferID, RelationDepot other) | ||||
| 		{ | ||||
| 			for (var i = 0; i < storages.Length; i += 1) | ||||
| 			{ | ||||
| 				if (storages[i] != null) | ||||
| 				{ | ||||
| 					foreach (var (a, b) in storages[i].All()) | ||||
| 					{ | ||||
| 						if (worldToTransferID.TryGetValue(a, out var otherA)) | ||||
| 						{ | ||||
| 							if (worldToTransferID.TryGetValue(b, out var otherB)) | ||||
| 							{ | ||||
| 								var storageIndex = storages[i].GetStorageIndex(a, b); | ||||
| 								var relationData = storages[i].Get(storageIndex); | ||||
| 								other.Set(otherA, otherB, i, relationData); | ||||
| 								other.EntityStorage.AddRelationKind(otherA, i); | ||||
| 								other.EntityStorage.AddRelationKind(otherB, i); | ||||
| 							} | ||||
| 							else | ||||
| 							{ | ||||
| 								throw new InvalidOperationException($"Missing transfer entity! {EntityStorage.Tag(a.ID)} related to {EntityStorage.Tag(b.ID)}"); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ namespace MoonTools.ECS | |||
| 		public abstract int GetStorageIndex(int entityA, int entityB); | ||||
| 		public abstract unsafe void* Get(int relationStorageIndex); | ||||
| 		public abstract void UnrelateAll(int entityID); | ||||
| 		public abstract ReverseSpanEnumerator<Entity> OutRelations(int entityID); | ||||
| 		public abstract ReverseSpanEnumerator<(Entity, Entity)> All(); | ||||
| 		public abstract RelationStorage CreateStorage(); | ||||
| 		public abstract void Clear(); | ||||
| 	} | ||||
|  | @ -38,7 +38,7 @@ namespace MoonTools.ECS | |||
| 			relationDatas = (TRelation*) NativeMemory.Alloc((nuint) (capacity * Unsafe.SizeOf<TRelation>())); | ||||
| 		} | ||||
| 
 | ||||
| 		public ReverseSpanEnumerator<(Entity, Entity)> All() | ||||
| 		public override ReverseSpanEnumerator<(Entity, Entity)> All() | ||||
| 		{ | ||||
| 			return new ReverseSpanEnumerator<(Entity, Entity)>(new Span<(Entity, Entity)>(relations, count)); | ||||
| 		} | ||||
|  | @ -91,7 +91,7 @@ namespace MoonTools.ECS | |||
| 			return indices.ContainsKey(relation); | ||||
| 		} | ||||
| 
 | ||||
| 		public override ReverseSpanEnumerator<Entity> OutRelations(int entityID) | ||||
| 		public ReverseSpanEnumerator<Entity> OutRelations(int entityID) | ||||
| 		{ | ||||
| 			if (outRelations.TryGetValue(entityID, out var entityOutRelations)) | ||||
| 			{ | ||||
|  |  | |||
							
								
								
									
										38
									
								
								src/World.cs
								
								
								
								
							
							
						
						
									
										38
									
								
								src/World.cs
								
								
								
								
							|  | @ -17,7 +17,7 @@ namespace MoonTools.ECS | |||
| 		public World() | ||||
| 		{ | ||||
| 			ComponentDepot = new ComponentDepot(ComponentTypeIndices); | ||||
| 			RelationDepot = new RelationDepot(RelationTypeIndices); | ||||
| 			RelationDepot = new RelationDepot(EntityStorage, RelationTypeIndices); | ||||
| 			FilterStorage = new FilterStorage(EntityStorage, ComponentTypeIndices); | ||||
| 		} | ||||
| 
 | ||||
|  | @ -79,14 +79,6 @@ namespace MoonTools.ECS | |||
| 			EntityStorage.AddRelationKind(entityB.ID, relationTypeIndex); | ||||
| 		} | ||||
| 
 | ||||
| 		// untyped version for Transfer | ||||
| 		internal unsafe void Relate(Entity entityA, Entity entityB, int relationTypeIndex, void* relationData) | ||||
| 		{ | ||||
| 			RelationDepot.Set(entityA, entityB, relationTypeIndex, relationData); | ||||
| 			EntityStorage.AddRelationKind(entityA.ID, relationTypeIndex); | ||||
| 			EntityStorage.AddRelationKind(entityB.ID, relationTypeIndex); | ||||
| 		} | ||||
| 
 | ||||
| 		public void Unrelate<TRelationKind>(in Entity entityA, in Entity entityB) where TRelationKind : unmanaged | ||||
| 		{ | ||||
| 			var (aEmpty, bEmpty) = RelationDepot.Remove<TRelationKind>(entityA, entityB); | ||||
|  | @ -177,31 +169,8 @@ namespace MoonTools.ECS | |||
| 				WorldToTransferID.Add(entity.ID, otherWorldEntity.ID); | ||||
| 			} | ||||
| 
 | ||||
| 			// FIXME: make sure this preserves relation order, should probably do something similar to filter storage | ||||
| 			// set relations before components so filters don't freak out | ||||
| 			foreach (var entity in filter.Entities) | ||||
| 			{ | ||||
| 				var otherWorldEntityA = WorldToTransferID[entity.ID]; | ||||
| 
 | ||||
| 				foreach (var relationTypeIndex in EntityStorage.RelationTypeIndices(entity.ID)) | ||||
| 				{ | ||||
| 					foreach (var entityB in RelationDepot.OutRelations(entity.ID, relationTypeIndex)) | ||||
| 					{ | ||||
| 						var storageIndex = RelationDepot.GetStorageIndex(relationTypeIndex, entity.ID, entityB); | ||||
| 
 | ||||
| 						int otherWorldEntityB; | ||||
| 						if (WorldToTransferID.TryGetValue(entityB, out otherWorldEntityB)) | ||||
| 						{ | ||||
| 							other.Relate(otherWorldEntityA, otherWorldEntityB, relationTypeIndex, RelationDepot.Get(relationTypeIndex, storageIndex)); | ||||
| 						} | ||||
| 						else | ||||
| 						{ | ||||
| 							// related entity is not in the filter | ||||
| 							throw new Exception($"Missing transfer entity! {EntityStorage.Tag(entity.ID)} related to {EntityStorage.Tag(entityB.ID)}"); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			// transfer relations | ||||
| 			RelationDepot.TransferStorage(WorldToTransferID, other.RelationDepot); | ||||
| 
 | ||||
| 			// set components | ||||
| 			foreach (var entity in filter.Entities) | ||||
|  | @ -214,6 +183,7 @@ namespace MoonTools.ECS | |||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			// transfer filters last so callbacks trigger correctly | ||||
| 			FilterStorage.TransferStorage(WorldToTransferID, other.FilterStorage); | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue