namespace Sandbox; /// /// Help to implement a component that completely overrides the transform. This is useful for scenarios /// where you will want to keep the local transform of a GameObject, but want to offset based on that /// for some reason. /// Having multiple of these on one GameObject is not supported, and will result in weirdness. /// public abstract class TransformProxyComponent : Component { protected override void OnEnabled() { Transform.Proxy = new ComponentProxy( this ); } protected override void OnDisabled() { if ( Transform.Proxy is ComponentProxy cp && cp.Target == this ) { Transform.Proxy = null; } } /// /// Override to provide the local transform /// public abstract Transform GetLocalTransform(); /// /// Called when the local transform is being set /// public virtual void SetLocalTransform( in Transform value ) { } /// /// Override to provide the world transform. The default implementation will calculate it using GetLocalTransform() based on the parent. /// public virtual Transform GetWorldTransform() { if ( GameObject?.Parent is GameObject parent ) { return parent.WorldTransform.ToWorld( GetLocalTransform() ); } return global::Transform.Zero; } /// /// Called when the world transform is being set /// public virtual void SetWorldTransform( Transform value ) { } /// /// Tell our other components, and our children that our transform has changed. This will /// update things like Renderers to update their render positions. /// public void MarkTransformChanged() { Transform.TransformChanged(); } } file class ComponentProxy : TransformProxy { public TransformProxyComponent Target { get; } public ComponentProxy( TransformProxyComponent target ) { Target = target; } public override Transform GetLocalTransform() => Target.GetLocalTransform(); public override void SetLocalTransform( in Transform value ) => Target.SetLocalTransform( value ); public override Transform GetWorldTransform() => Target.GetWorldTransform(); public override void SetWorldTransform( Transform value ) => Target.SetWorldTransform( value ); }