2024-10-13 00:08:01 +02:00
using MoonTools.ECS ;
using Nerfed.Runtime.Components ;
using Nerfed.Runtime.Util ;
using System.Numerics ;
2024-10-13 01:05:46 +02:00
// 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.
2024-10-13 00:08:01 +02:00
namespace Nerfed.Runtime.Systems
{
2024-10-13 01:05:46 +02:00
public class LocalToWorldSystem : MoonTools . ECS . System
2024-10-13 00:08:01 +02:00
{
private readonly Filter rootEntitiesFilter ;
2024-10-13 01:05:46 +02:00
public LocalToWorldSystem ( World world ) : base ( world )
2024-10-13 00:08:01 +02:00
{
rootEntitiesFilter = FilterBuilder . Include < LocalTransform > ( ) . Exclude < Parent > ( ) . 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 , in Matrix4x4 parentLocalToWorld )
{
// TODO: Only update dirty transforms.
2024-10-13 01:05:46 +02:00
// 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?
2024-10-13 00:08:01 +02:00
LocalTransform localTransform = Get < LocalTransform > ( entity ) ;
Matrix4x4 localToWorldMatrix = Matrix4x4 . Multiply ( parentLocalToWorld , localTransform . TRS ( ) ) ;
LocalToWorld localToWorld = new ( localToWorldMatrix ) ;
Set ( entity , localToWorld ) ;
Log . Info ( $"Entity {entity} | local position {localTransform.position} | world position {localToWorldMatrix.Translation}" ) ;
ReverseSpanEnumerator < Entity > childEntities = World . OutRelations < ChildRelation > ( entity ) ;
foreach ( Entity childEntity in childEntities )
{
UpdateWorldTransform ( childEntity , localToWorldMatrix ) ;
}
}
}
}