diff --git a/GlitchyEngine/src/World/Components/Components.bf b/GlitchyEngine/src/World/Components/Components.bf index 41d0c70..fb1aae7 100644 --- a/GlitchyEngine/src/World/Components/Components.bf +++ b/GlitchyEngine/src/World/Components/Components.bf @@ -9,6 +9,13 @@ using Mono; namespace GlitchyEngine.World { + /// Components that implement this interface provide custom copy logic. + interface ICopyComponent + { + /// Copies the data from source to target. + concrete static void Copy(T* source, T* target); + } + [AttributeUsage(.Struct, .ReflectAttribute, ReflectUser=.Methods | .NonStaticFields)] struct ComponentAttribute : Attribute { diff --git a/GlitchyEngine/src/World/Components/TextRendererComponent.bf b/GlitchyEngine/src/World/Components/TextRendererComponent.bf index 5984b92..56a1715 100644 --- a/GlitchyEngine/src/World/Components/TextRendererComponent.bf +++ b/GlitchyEngine/src/World/Components/TextRendererComponent.bf @@ -8,7 +8,7 @@ enum TextRendererFlags NeedsRebuild = 2 } -struct TextRendererComponent : IDisposableComponent +struct TextRendererComponent : IDisposableComponent, ICopyComponent { private String _text; @@ -51,4 +51,12 @@ struct TextRendererComponent : IDisposableComponent delete _text; _preparedText?.ReleaseRef(); } + + public static void Copy(Self* source, Self* target) + { + target.Text = source.Text; + + target._flags = source._flags; + target.NeedsRebuild = true; + } } diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index 167de44..f878110 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -151,6 +151,7 @@ namespace GlitchyEngine.World CopyComponents(this, target); CopyComponents(this, target); CopyComponents(this, target); + CopyComponents(this, target); CopyComponents(this, target); CopyComponents(this, target); @@ -193,25 +194,27 @@ namespace GlitchyEngine.World //target.SetViewportSize(_viewportWidth, _viewportHeight); } + /// Copies the all components of type TComponent from source scene to the corresponding entities in target scene. private static void CopyComponents(Scene source, Scene target) where TComponent : struct, new { for (let (sourceHandle, sourceComponent) in source._ecsWorld.Enumerate()) { Entity sourceEntity = .(sourceHandle, source); - Entity targetEntity = target.GetEntityByID(sourceEntity.UUID); + Result targetEntityResult = target.GetEntityByID(sourceEntity.UUID); - if (targetEntity.TryGetComponent(let targetComponent)) + if (targetEntityResult case .Ok(let targetEntity)) { - *targetComponent = *sourceComponent; + CopyComponent(sourceEntity, targetEntity); } else { - targetEntity.AddComponent(*sourceComponent); + Log.EngineLogger.Error($"Tried to copy component \"{typeof(TComponent)}\" of entity \"{sourceEntity.UUID}\", but there is no entity with the same ID in the target scene."); } } } + /// Copy POD components that don't need any extra care. private static void CopyComponent(Entity source, Entity target) where TComponent : struct, new { if (source.TryGetComponent(let sourceComponent)) @@ -227,6 +230,22 @@ namespace GlitchyEngine.World } } + /// Copy components that have custom copy methods. + private static void CopyComponent(Entity source, Entity target) where TComponent : struct, new, ICopyComponent + { + if (source.TryGetComponent(let sourceComponent)) + { + TComponent* targetComponent = null; + + if (!target.TryGetComponent(out targetComponent)) + { + targetComponent = target.AddComponent(); + } + + TComponent.Copy(sourceComponent, targetComponent); + } + } + /** * Starts the scene. * @param startRuntime If true, the script runtime will be started. @@ -955,6 +974,7 @@ namespace GlitchyEngine.World CopyComponent(original, copy); CopyComponent(original, copy); CopyComponent(original, copy); + CopyComponent(original, copy); CopyComponent(original, copy); CopyComponent(original, copy);