diff --git a/src/ECS/Archetype/Archetype.cs b/src/ECS/Archetype/Archetype.cs
index 612493e2..543eb1e9 100644
--- a/src/ECS/Archetype/Archetype.cs
+++ b/src/ECS/Archetype/Archetype.cs
@@ -308,12 +308,12 @@ internal static void MoveLastComponentsTo(Archetype arch, int newIndex, bool upd
}
/// Must be used only on case all are
- 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);
}
}
diff --git a/src/ECS/Archetype/StructHeap.cs b/src/ECS/Archetype/StructHeap.cs
index c48bc680..ac32db36 100644
--- a/src/ECS/Archetype/StructHeap.cs
+++ b/src/ECS/Archetype/StructHeap.cs
@@ -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);
diff --git a/src/ECS/Archetype/StructHeap.generic.cs b/src/ECS/Archetype/StructHeap.generic.cs
index f2badfa9..33c8c4fc 100644
--- a/src/ECS/Archetype/StructHeap.generic.cs
+++ b/src/ECS/Archetype/StructHeap.generic.cs
@@ -78,14 +78,21 @@ internal override void CopyComponentTo(int sourcePos, StructHeap target, int tar
/// 's.
/// If not serialization must be used.
///
- 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.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.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) {
diff --git a/src/ECS/Entity/Store/Entities.cs b/src/ECS/Entity/Store/Entities.cs
index eebe6b6a..b187b0d9 100644
--- a/src/ECS/Entity/Store/Entities.cs
+++ b/src/ECS/Entity/Store/Entities.cs
@@ -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()) {
clone.GetComponent() = default; // clear child ids. See child entities note in remarks.
}
@@ -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);
diff --git a/src/Tests/ECS/Entity/Test_Entity.cs b/src/Tests/ECS/Entity/Test_Entity.cs
index 8a933bbb..0808d4fd 100644
--- a/src/Tests/ECS/Entity/Test_Entity.cs
+++ b/src/Tests/ECS/Entity/Test_Entity.cs
@@ -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;
@@ -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();
@@ -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();
@@ -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();
+ 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().value);
+ entities = index[42];
+ AreEqual(2, entities.Count);
+ AreEqual("{ 1, 2 }",entities.Debug());
+ }
+
[Test]
public static void Test_EntityStore_CloneEntity_component_exception()
{