Improved copying of components

This commit is contained in:
Simon Lübeß
2024-03-17 20:28:41 +01:00
parent a2c7bf7d06
commit 930d289565
3 changed files with 40 additions and 5 deletions
@@ -9,6 +9,13 @@ using Mono;
namespace GlitchyEngine.World namespace GlitchyEngine.World
{ {
/// Components that implement this interface provide custom copy logic.
interface ICopyComponent<T>
{
/// Copies the data from source to target.
concrete static void Copy(T* source, T* target);
}
[AttributeUsage(.Struct, .ReflectAttribute, ReflectUser=.Methods | .NonStaticFields)] [AttributeUsage(.Struct, .ReflectAttribute, ReflectUser=.Methods | .NonStaticFields)]
struct ComponentAttribute : Attribute struct ComponentAttribute : Attribute
{ {
@@ -8,7 +8,7 @@ enum TextRendererFlags
NeedsRebuild = 2 NeedsRebuild = 2
} }
struct TextRendererComponent : IDisposableComponent struct TextRendererComponent : IDisposableComponent, ICopyComponent<TextRendererComponent>
{ {
private String _text; private String _text;
@@ -51,4 +51,12 @@ struct TextRendererComponent : IDisposableComponent
delete _text; delete _text;
_preparedText?.ReleaseRef(); _preparedText?.ReleaseRef();
} }
public static void Copy(Self* source, Self* target)
{
target.Text = source.Text;
target._flags = source._flags;
target.NeedsRebuild = true;
}
} }
+24 -4
View File
@@ -151,6 +151,7 @@ namespace GlitchyEngine.World
CopyComponents<MeshComponent>(this, target); CopyComponents<MeshComponent>(this, target);
CopyComponents<SpriteRendererComponent>(this, target); CopyComponents<SpriteRendererComponent>(this, target);
CopyComponents<CircleRendererComponent>(this, target); CopyComponents<CircleRendererComponent>(this, target);
CopyComponents<TextRendererComponent>(this, target);
CopyComponents<CameraComponent>(this, target); CopyComponents<CameraComponent>(this, target);
CopyComponents<LightComponent>(this, target); CopyComponents<LightComponent>(this, target);
@@ -193,25 +194,27 @@ namespace GlitchyEngine.World
//target.SetViewportSize(_viewportWidth, _viewportHeight); //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<TComponent>(Scene source, Scene target) where TComponent : struct, new private static void CopyComponents<TComponent>(Scene source, Scene target) where TComponent : struct, new
{ {
for (let (sourceHandle, sourceComponent) in source._ecsWorld.Enumerate<TComponent>()) for (let (sourceHandle, sourceComponent) in source._ecsWorld.Enumerate<TComponent>())
{ {
Entity sourceEntity = .(sourceHandle, source); Entity sourceEntity = .(sourceHandle, source);
Entity targetEntity = target.GetEntityByID(sourceEntity.UUID); Result<Entity> targetEntityResult = target.GetEntityByID(sourceEntity.UUID);
if (targetEntity.TryGetComponent<TComponent>(let targetComponent)) if (targetEntityResult case .Ok(let targetEntity))
{ {
*targetComponent = *sourceComponent; CopyComponent<TComponent>(sourceEntity, targetEntity);
} }
else else
{ {
targetEntity.AddComponent<TComponent>(*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<TComponent>(Entity source, Entity target) where TComponent : struct, new private static void CopyComponent<TComponent>(Entity source, Entity target) where TComponent : struct, new
{ {
if (source.TryGetComponent<TComponent>(let sourceComponent)) if (source.TryGetComponent<TComponent>(let sourceComponent))
@@ -227,6 +230,22 @@ namespace GlitchyEngine.World
} }
} }
/// Copy components that have custom copy methods.
private static void CopyComponent<TComponent>(Entity source, Entity target) where TComponent : struct, new, ICopyComponent<TComponent>
{
if (source.TryGetComponent<TComponent>(let sourceComponent))
{
TComponent* targetComponent = null;
if (!target.TryGetComponent<TComponent>(out targetComponent))
{
targetComponent = target.AddComponent<TComponent>();
}
TComponent.Copy(sourceComponent, targetComponent);
}
}
/** /**
* Starts the scene. * Starts the scene.
* @param startRuntime If true, the script runtime will be started. * @param startRuntime If true, the script runtime will be started.
@@ -955,6 +974,7 @@ namespace GlitchyEngine.World
CopyComponent<MeshComponent>(original, copy); CopyComponent<MeshComponent>(original, copy);
CopyComponent<SpriteRendererComponent>(original, copy); CopyComponent<SpriteRendererComponent>(original, copy);
CopyComponent<CircleRendererComponent>(original, copy); CopyComponent<CircleRendererComponent>(original, copy);
CopyComponent<TextRendererComponent>(original, copy);
CopyComponent<CameraComponent>(original, copy); CopyComponent<CameraComponent>(original, copy);
CopyComponent<LightComponent>(original, copy); CopyComponent<LightComponent>(original, copy);