Files
GhostEngine/Ghost.Editor.Core/SceneGraph/SceneGraphHelpers.cs
Misaki 00b4e82ded ECS refactor: new ComponentSet, serialization, generators
Major ECS API overhaul: added ComponentSet, refactored ComponentRegistry, and updated all entity/component creation methods. Introduced robust custom serialization infrastructure and per-component source generators for registration and (de)serialization. Updated editor, engine, and test code to use new APIs. Improved code quality, naming, and performance throughout. Removed obsolete code and updated dependencies.
2025-12-20 20:41:40 +09:00

112 lines
4.4 KiB
C#

using Ghost.Engine.Components;
using Ghost.Entities;
namespace Ghost.Editor.Core.SceneGraph;
public class SceneGraphHelpers
{
/// <summary>
/// Creates a new <see cref="EntityNode"/> entity with default components.
/// </summary>
/// <param name="world">The world context where the entity will be created.</param>
/// <param name="entity">The entity to be wrapped in the <see cref="EntityNode"/>.</param>
public static EntityNode CreateEntityNode(WorldNode owner, Entity entity, string name)
{
owner.World.EntityManager.AddComponent(entity, LocalToWorld.Identity);
owner.World.EntityManager.AddComponent(entity, Hierarchy.Root);
return new EntityNode(owner, entity, name);
}
/// <summary>
/// Creates a new <see cref="Entity"/> and <see cref="EntityNode"/> entity with default components.
/// </summary>
/// <param name="owner">The world context where the entity will be created.</param>
public static EntityNode CreateEntityNode(WorldNode owner, string name)
{
var entity = owner.World.EntityManager.CreateEntity();
return CreateEntityNode(owner, entity, name);
}
/// <summary>
/// Attaches childEntity to parentEntity in the scene graph.
/// </summary>
/// <param name="world">The world context where the entities exist.</param>
/// <param name="parentNode">The parent entity to which the child will be attached.</param>
/// <param name="childNode">The child entity to be attached.</param>
public static void AttachChild(WorldNode scene, EntityNode parentNode, EntityNode childNode)
{
// 1) If the child already has a parent, detach it first
var childHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(childNode.Entity);
if (childHierarchy.parent != Entity.Invalid)
{
DetachFromParent(scene, childNode);
}
// 2) Link child to new parent
childHierarchy.parent = parentNode.Entity;
// 3) Insert child at the head of parent's child list
var parentHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(parentNode.Entity);
childHierarchy.nextSibling = parentHierarchy.firstChild;
parentHierarchy.firstChild = childNode.Entity;
// 4) Write back
scene.World.EntityManager.SetComponent(parentNode.Entity, parentHierarchy);
scene.World.EntityManager.SetComponent(childNode.Entity, childHierarchy);
// 5) Update children list in parent node
parentNode.AddChild(childNode);
}
/// <summary>
/// Detaches the specified entity from its parent in the scene graph.
/// </summary>
/// <param name="world">The world context where the entities exist.</param>
/// <param name="node">The entity to detach from its parent.</param>
public static void DetachFromParent(WorldNode scene, EntityNode node)
{
var hierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(node.Entity);
var parent = hierarchy.parent;
if (parent == Entity.Invalid)
{
return; // already root
}
var parentHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(parent);
// If entity is the first child, simply move head
if (parentHierarchy.firstChild == node.Entity)
{
parentHierarchy.firstChild = hierarchy.nextSibling;
}
else
{
// Otherwise, find the previous sibling in the linked list
var prevSibling = parentHierarchy.firstChild;
while (prevSibling != Entity.Invalid)
{
var prevHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(prevSibling);
if (prevHierarchy.nextSibling == node.Entity)
{
prevHierarchy.nextSibling = hierarchy.nextSibling;
scene.World.EntityManager.SetComponent(prevSibling, prevHierarchy);
break;
}
prevSibling = prevHierarchy.nextSibling;
}
}
// Clear child's references
hierarchy.parent = Entity.Invalid;
hierarchy.nextSibling = Entity.Invalid;
// Write back
scene.World.EntityManager.SetComponent(parent, parentHierarchy);
scene.World.EntityManager.SetComponent(node.Entity, hierarchy);
// Remove from parent's children list
scene.EntityNodeLookup[parent].RemoveChild(node);
}
}