using MoonTools.ECS; using Nerfed.Runtime.Components; using Nerfed.Runtime.Util; using System.Numerics; // TODO: // Explore if having a WorldTransform and LocalTransfom component each holding position, rotation, scale values and the matricies is useful. // Often you need to either get or set these values. // If so, we probably need a utility funciton to do so. Since changing these values means that we need to update all the related data + children as well. // TODO: // When modifying transform all the children need to be updated as well. namespace Nerfed.Runtime.Systems { public class LocalToWorldSystem : MoonTools.ECS.System { private readonly Filter rootEntitiesFilter; public LocalToWorldSystem(World world) : base(world) { rootEntitiesFilter = FilterBuilder.Include().Exclude().Build(); } public override void Update(TimeSpan delta) { Matrix4x4 rootMatrix = Matrix4x4.Identity; foreach (Entity entity in rootEntitiesFilter.Entities) { UpdateWorldTransform(entity, rootMatrix); } } private void UpdateWorldTransform(in Entity entity, Matrix4x4 localToWorldMatrix) { // TODO: Only update dirty transforms. // If a parent is dirty all the children need to update their localToWorld matrix. // How do we check if something is dirty? How do we know if a LocalTransform has been changed? if (Has(entity)) { LocalTransform localTransform = Get(entity); localToWorldMatrix = Matrix4x4.Multiply(localToWorldMatrix, localTransform.TRS()); LocalToWorld localToWorld = new(localToWorldMatrix); Set(entity, localToWorld); //Log.Info($"Entity {entity} | local position {localTransform.position} | world position {localToWorldMatrix.Translation}"); } ReverseSpanEnumerator childEntities = World.OutRelations(entity); foreach (Entity childEntity in childEntities) { UpdateWorldTransform(childEntity, localToWorldMatrix); } } } }