66using System . Linq ;
77using Xunit ;
88using Stride . Core ;
9+ using Stride . Core . Annotations ;
910using Stride . Engine . Design ;
1011using Stride . Rendering ;
1112
@@ -129,8 +130,6 @@ public void TestMultipleComponents()
129130 [ Fact ]
130131 public void TestEntityAndPrefabClone ( )
131132 {
132- Prefab prefab = null ;
133-
134133 var entity = new Entity ( "Parent" ) ;
135134 var childEntity = new Entity ( "Child" ) ;
136135 entity . AddChild ( childEntity ) ;
@@ -141,17 +140,25 @@ public void TestEntityAndPrefabClone()
141140
142141 var newEntity = entity . Clone ( ) ;
143142
144- // NOTE: THE CODE AFTER THIS IS EXECUTED TWO TIMES
145- // 1st time: newEntity = entity.Clone();
146- // 2nd time: newEntity = prefab.Instantiate()[0];
147- check_new_Entity :
143+ CheckEntity ( newEntity ) ;
144+
145+ // Check prefab cloning
146+ var prefab = new Prefab ( ) ;
147+ prefab . Entities . Add ( entity ) ;
148+ var newEntities = prefab . Instantiate ( ) ;
149+ Assert . Single ( newEntities ) ;
150+
151+ CheckEntity ( newEntities [ 0 ] ) ;
152+ return ;
153+
154+ void CheckEntity ( [ NotNull ] Entity e )
148155 {
149- Assert . Single ( newEntity . Transform . Children ) ;
150- var newChildEntity = newEntity . Transform . Children [ 0 ] . Entity ;
156+ Assert . Single ( e . Transform . Children ) ;
157+ var newChildEntity = e . Transform . Children [ 0 ] . Entity ;
151158 Assert . Equal ( "Child" , newChildEntity . Name ) ;
152159
153- Assert . NotNull ( newEntity . Get < CustomEntityComponent > ( ) ) ;
154- var newCustom = newEntity . Get < CustomEntityComponent > ( ) ;
160+ Assert . NotNull ( e . Get < CustomEntityComponent > ( ) ) ;
161+ var newCustom = e . Get < CustomEntityComponent > ( ) ;
155162
156163 // Make sure that the old component and the new component are different
157164 Assert . NotEqual ( custom , newCustom ) ;
@@ -162,19 +169,37 @@ public void TestEntityAndPrefabClone()
162169 // Verify that objects references outside the Entity/Component hierarchy are not cloned (shared)
163170 Assert . Equal ( custom . CustomObject , newCustom . CustomObject ) ;
164171 }
172+ }
165173
166- // Woot, ugly test using a goto, avoid factorizing code in a delegate method, ugly but effective, goto FTW
167- if ( prefab == null )
174+ [ Fact ]
175+ public void TestCloningBehavior ( )
176+ {
177+ var externalEntity = new Entity ( ) ;
178+ var sourceEntity = new Entity ( ) ;
179+ var sourceComponent = new EntityComponentWithPrefab
168180 {
169- // Check prefab cloning
170- prefab = new Prefab ( ) ;
171- prefab . Entities . Add ( entity ) ;
172- var newEntities = prefab . Instantiate ( ) ;
173- Assert . Single ( newEntities ) ;
174-
175- newEntity = newEntities [ 0 ] ;
176- goto check_new_Entity ;
177- }
181+ Prefab = new Prefab ( ) ,
182+ ExternalEntityRef = externalEntity ,
183+ // Not yet supported, see commented out ExternalComponentRef declaration further and PR #2914
184+ //ExternalComponentRef = externalEntity.Transform
185+ } ;
186+ sourceComponent . Prefab . Entities . Add ( sourceEntity ) ;
187+ sourceEntity . Add ( sourceComponent ) ;
188+
189+ var clonedComponent = sourceComponent . Prefab . Instantiate ( ) [ 0 ] . Get < EntityComponentWithPrefab > ( ) ;
190+
191+ // Validate that cloning did clone the entity
192+ Assert . NotEqual ( clonedComponent . Entity , sourceComponent . Entity ) ;
193+
194+ // References to prefabs should not be deep cloned as they are content types
195+ Assert . Equal ( clonedComponent . Prefab , sourceComponent . Prefab ) ;
196+
197+ // References to entities outside this one's hierarchy should not clone the entity referenced, it should point to the same reference
198+ Assert . Equal ( clonedComponent . ExternalEntityRef , sourceComponent . ExternalEntityRef ) ;
199+
200+ // References to entity component outside this one's hierarchy should not clone the component referenced, it should point to the same reference
201+ // Not yet supported, see commented out ExternalComponentRef declaration further and PR #2914
202+ /*Assert.Equal(clonedComponent.ExternalComponentRef, sourceComponent.ExternalComponentRef);*/
178203 }
179204
180205 private class DelegateEntityComponentNotify : EntityManager
@@ -270,4 +295,20 @@ public abstract class CustomEntityComponentBase : EntityComponent
270295 {
271296 public Action < CustomEntityComponentEventArgs > Changed ;
272297 }
298+
299+ [ DataContract ]
300+ public class EntityComponentWithPrefab : EntityComponent
301+ {
302+ public required Prefab Prefab { get ; set ; }
303+ public required Entity ExternalEntityRef { get ; set ; }
304+
305+ /* TODO:
306+ * References to entity component outside of a prefab's hierarchy should not clone the component referenced, it should point to the same reference.
307+ * More work is required on that front, particularly with EntityComponent which does not have a specific serializer,
308+ * we would need one that derive from DataContentSerializerWithReuse to properly filter external references.
309+ * The serializer for TransformComponent derives from a simple DataSerializer for example.
310+ * See also PR #2914
311+ */
312+ /*public required TransformComponent ExternalComponentRef { get; set; }*/
313+ }
273314}
0 commit comments