Skip to content

Commit

Permalink
CloneEntity() - add indexed components to index when cloning
Browse files Browse the repository at this point in the history
  • Loading branch information
friflo committed Dec 9, 2024
1 parent c68495f commit eee4e77
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 12 deletions.
4 changes: 2 additions & 2 deletions src/ECS/Archetype/Archetype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,12 @@ internal static void MoveLastComponentsTo(Archetype arch, int newIndex, bool upd
}

/// <remarks>Must be used only on case all <see cref="ComponentTypes"/> are <see cref="ComponentType.IsBlittable"/></remarks>
internal static void CopyComponents(Archetype arch, CopyContext context)
internal static void CloneComponents(Archetype arch, CopyContext context)
{
var sourceIndex = context.source.compIndex;
var targetIndex = context.target.compIndex;
foreach (var sourceHeap in arch.structHeaps) {
sourceHeap.CopyComponent(sourceIndex, targetIndex, context);
sourceHeap.CloneComponent(sourceIndex, targetIndex, context);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/ECS/Archetype/StructHeap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ internal abstract class StructHeap : IComponentStash
internal abstract void ResizeComponents (int capacity, int count);
internal abstract void MoveComponent (int from, int to);
internal abstract void CopyComponentTo (int sourcePos, StructHeap target, int targetPos);
internal abstract void CopyComponent (int sourcePos, int targetPos, in CopyContext context);
internal abstract void CloneComponent (int sourcePos, int targetPos, in CopyContext context);
internal abstract void SetComponentDefault (int compIndex);
internal abstract void SetComponentsDefault (int compIndexStart, int count);
internal abstract object GetComponentDebug (int compIndex);
Expand Down
13 changes: 10 additions & 3 deletions src/ECS/Archetype/StructHeap.generic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,21 @@ internal override void CopyComponentTo(int sourcePos, StructHeap target, int tar
/// <see cref="ComponentType"/>'s.<br/>
/// If not <see cref="ComponentType.IsBlittable"/> serialization must be used.
/// </remarks>
internal override void CopyComponent(int sourcePos, int targetPos, in CopyContext context)
internal override void CloneComponent(int sourcePos, int targetPos, in CopyContext context)
{
var copyValue = CopyValueUtils<T>.CopyValue;
ref var source = ref components[sourcePos];
ref var target = ref components[targetPos];
if (copyValue == null) {
components[targetPos] = components[sourcePos];
target = source;
} else {
copyValue(source, ref target, context);
}
if (!StructInfo<T>.HasIndex) {
return;
}
copyValue(components[sourcePos], ref components[targetPos], context);
var targetEntity = context.target;
StoreIndex.AddIndex(targetEntity.store, targetEntity.Id, source);
}

internal override void SetComponentDefault (int compIndex) {
Expand Down
8 changes: 4 additions & 4 deletions src/ECS/Entity/Store/Entities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,12 @@ public Entity CloneEntity(Entity entity)
var clone = new Entity(this, id, revision);

// var isBlittable = IsBlittable(entity);

// todo optimize - serialize / deserialize only non blittable components and scripts
// if (true) {

var scriptTypeByType = Static.EntitySchema.ScriptTypeByType;
// CopyComponents() must be used only in case all component types are blittable
var context = new CopyContext(entity, clone);
Archetype.CopyComponents(archetype, context);
Archetype.CloneComponents(archetype, context);
if (clone.HasComponent<TreeNode>()) {
clone.GetComponent<TreeNode>() = default; // clear child ids. See child entities note in remarks.
}
Expand All @@ -109,7 +108,8 @@ public Entity CloneEntity(Entity entity)
scriptClone.entity = clone;
extension.AddScript(clone, scriptClone, scriptType);
}
/* } else {
/* keep old implementation using JSON serialization for reference
} else {
// --- serialize entity
var converter = EntityConverter.Default;
converter.EntityToDataEntity(entity, dataBuffer, false);
Expand Down
24 changes: 22 additions & 2 deletions src/Tests/ECS/Entity/Test_Entity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using Friflo.Engine.ECS;
using NUnit.Framework;
using Tests.ECS.Index;
using Tests.Utils;
using static NUnit.Framework.Assert;

Expand Down Expand Up @@ -204,7 +205,7 @@ public static void Assert_TryGetEntityById()
}

[Test]
public static void Test_EntityStore_CloneEntity()
public static void Test_EntityStore_CloneEntity_1()
{
var store = new EntityStore(PidType.RandomPids);
var entity = store.CreateEntity();
Expand Down Expand Up @@ -237,7 +238,7 @@ public static void Test_EntityStore_CloneEntity()
}

[Test]
public static void Test_EntityStore_CopyTo()
public static void Test_EntityStore_CloneEntity_2()
{
var store = new EntityStore();
var entity1 = store.CreateEntity();
Expand All @@ -250,6 +251,25 @@ public static void Test_EntityStore_CopyTo()
AreNotSame(list1, list2);
}

[Test]
public static void Test_EntityStore_CloneEntity_IndexedComponent()
{
var store = new EntityStore();
var index = store.ComponentIndex<IndexedInt,int>();
var entity = store.CreateEntity(1);

entity.AddComponent(new IndexedInt { value = 42 });
var entities = index[42];
AreEqual(1, entities.Count);
AreEqual("{ 1 }", entities.Debug());

var clone = store.CloneEntity(entity);
AreEqual(42, clone.GetComponent<IndexedInt>().value);
entities = index[42];
AreEqual(2, entities.Count);
AreEqual("{ 1, 2 }",entities.Debug());
}

[Test]
public static void Test_EntityStore_CloneEntity_component_exception()
{
Expand Down

0 comments on commit eee4e77

Please sign in to comment.