Compare commits
	
		
			26 Commits
		
	
	
		
			dbd15cbbc2
			...
			988a6f67f2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 988a6f67f2 | |||
| 2f32038f04 | |||
| 4b756fa232 | |||
| 0db2cae1bb | |||
| 896f7876c1 | |||
| 56d3112e35 | |||
| 32ec2325dc | |||
| b42f1f1881 | |||
| f8096377b2 | |||
| a9fc819268 | |||
| 1d63391975 | |||
| 61ff0887e2 | |||
| 16344dccc7 | |||
| dc4bea3eef | |||
| d1b2723a70 | |||
| 2f5c04e66b | |||
| f753da1f87 | |||
| 6901159106 | |||
| 7469c9ab0c | |||
| ede90adbdc | |||
| eeaca3a6c7 | |||
| 3b984a0a4b | |||
| c5afb70b18 | |||
| 9d2a192f04 | |||
| 598debc233 | |||
| ab05a89175 | 
							
								
								
									
										6
									
								
								Engine.Core/Abstract/IBehaviour3D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Engine.Core/Abstract/IBehaviour3D.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface IBehaviour3D : IBehaviour
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ITransform3D Transform { get; }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								Engine.Core/Abstract/ICamera3D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								Engine.Core/Abstract/ICamera3D.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Represents a 3D camera in the engine.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public interface ICamera3D : IBehaviour3D
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Field of View (FOV) value of the camera
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    float FieldOfView { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Converts a position from screen coordinates to a <see cref="Ray3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="screenPosition">The position in screen coordinates.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Ray3D"/> originating from the camera to the screen position in world coordinates.</returns>
 | 
				
			||||||
 | 
					    Ray3D ScreenToWorldRay(Vector2D screenPosition);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Converts a position from world coordinates to screen coordinates.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="worldPosition">The position in world coordinates.</param>
 | 
				
			||||||
 | 
					    /// <returns>The position in screen coordinates.</returns>
 | 
				
			||||||
 | 
					    Vector2D WorldToScreenPosition(Vector3D worldPosition);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -16,10 +16,15 @@ public interface ITransform2D : IBehaviour
 | 
				
			|||||||
    Event<ITransform2D, ScaleChangedArguments> OnScaleChanged { get; }
 | 
					    Event<ITransform2D, ScaleChangedArguments> OnScaleChanged { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Event triggered when the <see cref="Rotation"/> of the <see cref="ITransform"/> changes.
 | 
					    /// Event triggered when the <see cref="Rotation"/> of the <see cref="ITransform2D"/> changes.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    Event<ITransform2D, RotationChangedArguments> OnRotationChanged { get; }
 | 
					    Event<ITransform2D, RotationChangedArguments> OnRotationChanged { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Event triggered when any of the properties of the <see cref="ITransform2D"/> gets updated.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Event<ITransform2D> OnTransformUpdated { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The <see cref="Vector2D"/> pointing upwards in world space.
 | 
					    /// The <see cref="Vector2D"/> pointing upwards in world space.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										105
									
								
								Engine.Core/Abstract/ITransform3D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								Engine.Core/Abstract/ITransform3D.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
				
			|||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Represents the transformation properties of an object such as position, scale, and rotation in 3D space.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public interface ITransform3D : IBehaviour
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Event triggered when the <see cref="Position"/> of the <see cref="ITransform3D"/> changes.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Event<ITransform3D, PositionChangedArguments> OnPositionChanged { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Event triggered when the <see cref="Scale"/> of the <see cref="ITransform3D"/> changes.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Event<ITransform3D, ScaleChangedArguments> OnScaleChanged { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Event triggered when the <see cref="Rotation"/> of the <see cref="ITransform3D"/> changes.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Event<ITransform3D, RotationChangedArguments> OnRotationChanged { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Event triggered when any of the properties of the <see cref="ITransform3D"/> gets updated.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Event<ITransform3D> OnTransformUpdated { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The <see cref="Vector3D"/> pointing upwards in world space.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Vector3D Up { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The <see cref="Vector3D"/> pointing upwards in world space.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Vector3D Down { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The <see cref="Vector3D"/> pointing upwards in world space.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Vector3D Left { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The <see cref="Vector3D"/> pointing upwards in world space.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Vector3D Right { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The <see cref="Vector3D"/> pointing forwards in world space.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Vector3D Forward { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The <see cref="Vector3D"/> pointing backwards in world space.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Vector3D Backward { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The world position of the <see cref="ITransform3D"/> in 3D space.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Vector3D Position { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The world scale of the <see cref="ITransform3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Vector3D Scale { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The world rotation of the <see cref="ITransform3D"/> in degrees.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Quaternion Rotation { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The local position of the <see cref="ITransform3D"/> in 3D space.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Vector3D LocalPosition { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The local scale of the <see cref="ITransform3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Vector3D LocalScale { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The local rotation of the <see cref="ITransform3D"/> in degrees.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    Quaternion LocalRotation { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Arguments for the event triggered when the <see cref="ITransform3D"/>'s rotation changes.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="PreviousPosition">The previous <see cref="Position"/> of the <see cref="ITransform3D"/>.</param>
 | 
				
			||||||
 | 
					    readonly record struct PositionChangedArguments(Vector3D PreviousPosition);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Arguments for the event triggered when the <see cref="ITransform3D"/>'s rotation changes.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="PreviousScale">The previous <see cref="Scale"/> of the <see cref="ITransform3D"/>.</param>
 | 
				
			||||||
 | 
					    readonly record struct ScaleChangedArguments(Vector3D PreviousScale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Arguments for the event triggered when the <see cref="ITransform3D"/>'s rotation changes.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="PreviousRotation">The previous <see cref="Rotation"/> of the <see cref="ITransform3D"/>.</param>
 | 
				
			||||||
 | 
					    readonly record struct RotationChangedArguments(Quaternion PreviousRotation);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,50 +1,103 @@
 | 
				
			|||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public abstract class Behaviour : BehaviourBase
 | 
					[System.Diagnostics.DebuggerDisplay("{GetType().Name, nq}, Priority: {Priority}, Initialized: {Initialized}")]
 | 
				
			||||||
 | 
					public abstract class Behaviour : BaseEntity, IBehaviour
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private readonly Event<IUniverseObject, IUniverseObject.EnteredUniverseArguments>.EventHandler delegateEnteredUniverse = null!;
 | 
					    public Event<IBehaviour, IBehaviour.PriorityChangedArguments> OnPriorityChanged { get; } = new();
 | 
				
			||||||
    private readonly Event<IUniverseObject, IUniverseObject.ExitedUniverseArguments>.EventHandler delegateExitedUniverse = null!;
 | 
					    public Event<IActive, IActive.ActiveChangedArguments> OnActiveChanged { get; } = new();
 | 
				
			||||||
 | 
					    public Event<IHasBehaviourController> OnBehaviourControllerAssigned { get; } = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Behaviour()
 | 
					    private readonly Event<IHasUniverseObject>.EventHandler delegateOnUniverseObjectAssigned = null!;
 | 
				
			||||||
 | 
					    private readonly Event<IActive, IActive.ActiveChangedArguments>.EventHandler delegateOnUniverseObjectActiveChanged = null!;
 | 
				
			||||||
 | 
					    private readonly Event<IStateEnable, IStateEnable.EnabledChangedArguments>.EventHandler delegateOnStateEnabledChanged = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IUniverse Universe => BehaviourController.UniverseObject.Universe;
 | 
				
			||||||
 | 
					    public IUniverseObject UniverseObject => BehaviourController.UniverseObject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private IBehaviourController _behaviourController = null!;
 | 
				
			||||||
 | 
					    public IBehaviourController BehaviourController => _behaviourController;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private int _priority = 0;
 | 
				
			||||||
 | 
					    public int Priority
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        OnInitialized.AddListener(OnInitialize);
 | 
					        get => _priority;
 | 
				
			||||||
        OnFinalized.AddListener(OnFinalize);
 | 
					        set
 | 
				
			||||||
        OnUnassigned.AddListener(OnUnassign);
 | 
					        {
 | 
				
			||||||
 | 
					            if (value == _priority)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        delegateEnteredUniverse = EnteredUniverse;
 | 
					            int previousPriority = _priority;
 | 
				
			||||||
        delegateExitedUniverse = ExitedUniverse;
 | 
					            _priority = value;
 | 
				
			||||||
 | 
					            OnPriorityChanged?.Invoke(this, new(previousPriority));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected virtual void OnUnassign() { }
 | 
					    private bool _isActive = false;
 | 
				
			||||||
    protected void OnUnassign(IAssignable assignable) => OnUnassign();
 | 
					    public bool IsActive => _isActive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected virtual void OnInitialize() { }
 | 
					    protected virtual void OnAssign(IBehaviourController behaviourController) { }
 | 
				
			||||||
    protected void OnInitialize(IInitializable _)
 | 
					    public bool Assign(IBehaviourController behaviourController)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        BehaviourController.UniverseObject.OnEnteredUniverse.AddListener(delegateEnteredUniverse);
 | 
					        if (IsInitialized)
 | 
				
			||||||
        BehaviourController.UniverseObject.OnExitedUniverse.AddListener(delegateExitedUniverse);
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        OnInitialize();
 | 
					        _behaviourController = behaviourController;
 | 
				
			||||||
 | 
					        OnAssign(behaviourController);
 | 
				
			||||||
        if (UniverseObject.IsInUniverse)
 | 
					        behaviourController.OnUniverseObjectAssigned.AddListener(delegateOnUniverseObjectAssigned);
 | 
				
			||||||
            EnteredUniverse(UniverseObject, new(Universe));
 | 
					        behaviourController.StateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
 | 
				
			||||||
 | 
					        if (behaviourController.UniverseObject is not null)
 | 
				
			||||||
 | 
					            OnUniverseObjectAssigned(behaviourController);
 | 
				
			||||||
 | 
					        OnBehaviourControllerAssigned?.Invoke(this);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected virtual void OnFinalize() { }
 | 
					    private void OnUniverseObjectAssigned(IHasUniverseObject sender)
 | 
				
			||||||
    protected void OnFinalize(IInitializable _)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        BehaviourController.UniverseObject.OnEnteredUniverse.RemoveListener(delegateEnteredUniverse);
 | 
					        sender.UniverseObject.OnActiveChanged.AddListener(delegateOnUniverseObjectActiveChanged);
 | 
				
			||||||
        BehaviourController.UniverseObject.OnExitedUniverse.RemoveListener(delegateExitedUniverse);
 | 
					        UpdateActive();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        OnFinalize();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (UniverseObject.IsInUniverse)
 | 
					 | 
				
			||||||
            ExitedUniverse(UniverseObject, new(Universe));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected virtual void OnEnteredUniverse(IUniverse universe) { }
 | 
					    protected override void OnAssign(IStateEnable stateEnable)
 | 
				
			||||||
    protected void EnteredUniverse(IUniverseObject sender, IUniverseObject.EnteredUniverseArguments args) => OnEnteredUniverse(args.Universe);
 | 
					    {
 | 
				
			||||||
 | 
					        base.OnAssign(stateEnable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected virtual void OnExitedUniverse(IUniverse universe) { }
 | 
					        stateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
 | 
				
			||||||
    protected void ExitedUniverse(IUniverseObject sender, IUniverseObject.ExitedUniverseArguments args) => OnExitedUniverse(args.Universe);
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void UnassignInternal()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        BehaviourController.UniverseObject.OnActiveChanged.RemoveListener(delegateOnUniverseObjectActiveChanged);
 | 
				
			||||||
 | 
					        StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
 | 
				
			||||||
 | 
					        BehaviourController.OnUniverseObjectAssigned.RemoveListener(delegateOnUniverseObjectAssigned);
 | 
				
			||||||
 | 
					        BehaviourController.StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
 | 
				
			||||||
 | 
					        base.UnassignInternal();
 | 
				
			||||||
 | 
					        _behaviourController = null!;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void InitializeInternal()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Debug.Assert.AssertBehaviourControllerAssigned(this);
 | 
				
			||||||
 | 
					        Debug.Assert.AssertStateEnableAssigned(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        UpdateActive();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnStateEnabledChanged(IStateEnable sender, IStateEnable.EnabledChangedArguments args) => UpdateActive();
 | 
				
			||||||
 | 
					    private void OnUniverseObjectActiveChanged(IActive sender, IActive.ActiveChangedArguments args) => UpdateActive();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void UpdateActive()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        bool previousActive = IsActive;
 | 
				
			||||||
 | 
					        _isActive = StateEnable.Enabled && _behaviourController.StateEnable.Enabled && _behaviourController.UniverseObject.IsActive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (previousActive != IsActive)
 | 
				
			||||||
 | 
					            OnActiveChanged?.Invoke(this, new(previousActive));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected Behaviour()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        delegateOnUniverseObjectAssigned = OnUniverseObjectAssigned;
 | 
				
			||||||
 | 
					        delegateOnUniverseObjectActiveChanged = OnUniverseObjectActiveChanged;
 | 
				
			||||||
 | 
					        delegateOnStateEnabledChanged = OnStateEnabledChanged;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public abstract class Behaviour2D : Behaviour, IBehaviour2D
 | 
					// TODO this should not use independent behaviour, the OnInitialize usage for getting the transform can cause very unexpected issues
 | 
				
			||||||
 | 
					public abstract class Behaviour2D : Internal.BehaviourIndependent, IBehaviour2D
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public ITransform2D Transform { get; private set; } = null!;
 | 
					    public ITransform2D Transform { get; private set; } = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,103 +0,0 @@
 | 
				
			|||||||
namespace Engine.Core;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("{GetType().Name, nq}, Priority: {Priority}, Initialized: {Initialized}")]
 | 
					 | 
				
			||||||
public abstract class BehaviourBase : BaseEntity, IBehaviour
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public Event<IBehaviour, IBehaviour.PriorityChangedArguments> OnPriorityChanged { get; } = new();
 | 
					 | 
				
			||||||
    public Event<IActive, IActive.ActiveChangedArguments> OnActiveChanged { get; } = new();
 | 
					 | 
				
			||||||
    public Event<IHasBehaviourController> OnBehaviourControllerAssigned { get; } = new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private readonly Event<IHasUniverseObject>.EventHandler delegateOnUniverseObjectAssigned = null!;
 | 
					 | 
				
			||||||
    private readonly Event<IActive, IActive.ActiveChangedArguments>.EventHandler delegateOnUniverseObjectActiveChanged = null!;
 | 
					 | 
				
			||||||
    private readonly Event<IStateEnable, IStateEnable.EnabledChangedArguments>.EventHandler delegateOnStateEnabledChanged = null!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public IUniverse Universe => BehaviourController.UniverseObject.Universe;
 | 
					 | 
				
			||||||
    public IUniverseObject UniverseObject => BehaviourController.UniverseObject;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private IBehaviourController _behaviourController = null!;
 | 
					 | 
				
			||||||
    public IBehaviourController BehaviourController => _behaviourController;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private int _priority = 0;
 | 
					 | 
				
			||||||
    public int Priority
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        get => _priority;
 | 
					 | 
				
			||||||
        set
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (value == _priority)
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            int previousPriority = _priority;
 | 
					 | 
				
			||||||
            _priority = value;
 | 
					 | 
				
			||||||
            OnPriorityChanged?.Invoke(this, new(previousPriority));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private bool _isActive = false;
 | 
					 | 
				
			||||||
    public bool IsActive => _isActive;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected virtual void OnAssign(IBehaviourController behaviourController) { }
 | 
					 | 
				
			||||||
    public bool Assign(IBehaviourController behaviourController)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (IsInitialized)
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        _behaviourController = behaviourController;
 | 
					 | 
				
			||||||
        OnAssign(behaviourController);
 | 
					 | 
				
			||||||
        behaviourController.OnUniverseObjectAssigned.AddListener(delegateOnUniverseObjectAssigned);
 | 
					 | 
				
			||||||
        behaviourController.StateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
 | 
					 | 
				
			||||||
        if (behaviourController.UniverseObject is not null)
 | 
					 | 
				
			||||||
            OnUniverseObjectAssigned(behaviourController);
 | 
					 | 
				
			||||||
        OnBehaviourControllerAssigned?.Invoke(this);
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void OnUniverseObjectAssigned(IHasUniverseObject sender)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        sender.UniverseObject.OnActiveChanged.AddListener(delegateOnUniverseObjectActiveChanged);
 | 
					 | 
				
			||||||
        UpdateActive();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected override void OnAssign(IStateEnable stateEnable)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        base.OnAssign(stateEnable);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        stateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected override void UnassignInternal()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        BehaviourController.UniverseObject.OnActiveChanged.RemoveListener(delegateOnUniverseObjectActiveChanged);
 | 
					 | 
				
			||||||
        StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
 | 
					 | 
				
			||||||
        BehaviourController.OnUniverseObjectAssigned.RemoveListener(delegateOnUniverseObjectAssigned);
 | 
					 | 
				
			||||||
        BehaviourController.StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
 | 
					 | 
				
			||||||
        base.UnassignInternal();
 | 
					 | 
				
			||||||
        _behaviourController = null!;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected override void InitializeInternal()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Debug.Assert.AssertBehaviourControllerAssigned(this);
 | 
					 | 
				
			||||||
        Debug.Assert.AssertStateEnableAssigned(this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        UpdateActive();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void OnStateEnabledChanged(IStateEnable sender, IStateEnable.EnabledChangedArguments args) => UpdateActive();
 | 
					 | 
				
			||||||
    private void OnUniverseObjectActiveChanged(IActive sender, IActive.ActiveChangedArguments args) => UpdateActive();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void UpdateActive()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        bool previousActive = IsActive;
 | 
					 | 
				
			||||||
        _isActive = StateEnable.Enabled && _behaviourController.StateEnable.Enabled && _behaviourController.UniverseObject.IsActive;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (previousActive != IsActive)
 | 
					 | 
				
			||||||
            OnActiveChanged?.Invoke(this, new(previousActive));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected BehaviourBase()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        delegateOnUniverseObjectAssigned = OnUniverseObjectAssigned;
 | 
					 | 
				
			||||||
        delegateOnUniverseObjectActiveChanged = OnUniverseObjectActiveChanged;
 | 
					 | 
				
			||||||
        delegateOnStateEnabledChanged = OnStateEnabledChanged;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										56
									
								
								Engine.Core/BehaviourInternal.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								Engine.Core/BehaviourInternal.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					namespace Engine.Core.Internal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// This behaviour can be used for core managers like <see cref="UpdateManager"/> etc. which need to be able to work even
 | 
				
			||||||
 | 
					/// in a very bare minimum setup without the presence of <see cref="UniverseEntranceManager"/> to set themselves up on universe entrance.
 | 
				
			||||||
 | 
					/// I recommend not using this unless you know what you are doing but it might come in handy for some use cases.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public abstract class BehaviourIndependent : Behaviour
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private readonly Event<IUniverseObject, IUniverseObject.EnteredUniverseArguments>.EventHandler delegateEnteredUniverse = null!;
 | 
				
			||||||
 | 
					    private readonly Event<IUniverseObject, IUniverseObject.ExitedUniverseArguments>.EventHandler delegateExitedUniverse = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BehaviourIndependent()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        OnInitialized.AddListener(OnInitialize);
 | 
				
			||||||
 | 
					        OnFinalized.AddListener(OnFinalize);
 | 
				
			||||||
 | 
					        OnUnassigned.AddListener(OnUnassign);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        delegateEnteredUniverse = EnteredUniverse;
 | 
				
			||||||
 | 
					        delegateExitedUniverse = ExitedUniverse;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected virtual void OnUnassign() { }
 | 
				
			||||||
 | 
					    protected void OnUnassign(IAssignable assignable) => OnUnassign();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected virtual void OnInitialize() { }
 | 
				
			||||||
 | 
					    protected void OnInitialize(IInitializable _)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        BehaviourController.UniverseObject.OnEnteredUniverse.AddListener(delegateEnteredUniverse);
 | 
				
			||||||
 | 
					        BehaviourController.UniverseObject.OnExitedUniverse.AddListener(delegateExitedUniverse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnInitialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (UniverseObject.IsInUniverse)
 | 
				
			||||||
 | 
					            EnteredUniverse(UniverseObject, new(Universe));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected virtual void OnFinalize() { }
 | 
				
			||||||
 | 
					    protected void OnFinalize(IInitializable _)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        BehaviourController.UniverseObject.OnEnteredUniverse.RemoveListener(delegateEnteredUniverse);
 | 
				
			||||||
 | 
					        BehaviourController.UniverseObject.OnExitedUniverse.RemoveListener(delegateExitedUniverse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnFinalize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (UniverseObject.IsInUniverse)
 | 
				
			||||||
 | 
					            ExitedUniverse(UniverseObject, new(Universe));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected virtual void OnEnteredUniverse(IUniverse universe) { }
 | 
				
			||||||
 | 
					    protected void EnteredUniverse(IUniverseObject sender, IUniverseObject.EnteredUniverseArguments args) => OnEnteredUniverse(args.Universe);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected virtual void OnExitedUniverse(IUniverse universe) { }
 | 
				
			||||||
 | 
					    protected void ExitedUniverse(IUniverseObject sender, IUniverseObject.ExitedUniverseArguments args) => OnExitedUniverse(args.Universe);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -4,6 +4,22 @@ namespace Engine.Core.Debug;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public static class Assert
 | 
					public static class Assert
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static void AssertTrue(bool value, string errorMessage)
 | 
				
			||||||
 | 
					        => System.Diagnostics.Debug.Assert(value, errorMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static void AssertFalse(bool value, string errorMessage)
 | 
				
			||||||
 | 
					        => System.Diagnostics.Debug.Assert(!value, errorMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static void AssertNull(object? value, string errorMessage)
 | 
				
			||||||
 | 
					        => System.Diagnostics.Debug.Assert(value is null, errorMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static void AssertNotNull(object? value, string errorMessage)
 | 
				
			||||||
 | 
					        => System.Diagnostics.Debug.Assert(value is not null, errorMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
    public static void AssertInitialized(IInitializable initializable)
 | 
					    public static void AssertInitialized(IInitializable initializable)
 | 
				
			||||||
        => System.Diagnostics.Debug.Assert(initializable.IsInitialized, $"{initializable.GetType().Name} must be initialized");
 | 
					        => System.Diagnostics.Debug.Assert(initializable.IsInitialized, $"{initializable.GetType().Name} must be initialized");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,4 +14,17 @@ public static class TransformExtensions
 | 
				
			|||||||
        if (localScale.HasValue) transform.LocalScale = localScale.Value;
 | 
					        if (localScale.HasValue) transform.LocalScale = localScale.Value;
 | 
				
			||||||
        return transform;
 | 
					        return transform;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static ITransform3D SetTransform(this ITransform3D transform,
 | 
				
			||||||
 | 
					        Vector3D? position = null, Quaternion? rotation = null, Vector3D? scale = null,
 | 
				
			||||||
 | 
					        Vector3D? localPosition = null, Quaternion? localRotation = null, Vector3D? localScale = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (position.HasValue) transform.Position = position.Value;
 | 
				
			||||||
 | 
					        if (rotation.HasValue) transform.Rotation = rotation.Value;
 | 
				
			||||||
 | 
					        if (scale.HasValue) transform.Scale = scale.Value;
 | 
				
			||||||
 | 
					        if (localPosition.HasValue) transform.LocalPosition = localPosition.Value;
 | 
				
			||||||
 | 
					        if (localRotation.HasValue) transform.LocalRotation = localRotation.Value;
 | 
				
			||||||
 | 
					        if (localScale.HasValue) transform.LocalScale = localScale.Value;
 | 
				
			||||||
 | 
					        return transform;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,111 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Engine.Core;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// <summary>
 | 
					 | 
				
			||||||
/// Represents an Axis-Aligned Bounding Box (AABB) in 2D space.
 | 
					 | 
				
			||||||
/// </summary>
 | 
					 | 
				
			||||||
/// <param name="lowerBoundary">The lower boundary of the <see cref="AABB"/>.</param>
 | 
					 | 
				
			||||||
/// <param name="upperBoundary">The upper boundary of the <see cref="AABB"/>.</param>
 | 
					 | 
				
			||||||
/// <remarks>
 | 
					 | 
				
			||||||
/// Initializes a new instance of the <see cref="AABB"/> struct with the specified lower and upper boundaries.
 | 
					 | 
				
			||||||
/// </remarks>
 | 
					 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("LowerBoundary: {LowerBoundary.ToString(), nq}, UpperBoundary: {UpperBoundary.ToString(), nq}")]
 | 
					 | 
				
			||||||
public readonly struct AABB(Vector2D lowerBoundary, Vector2D upperBoundary) : IEquatable<AABB>
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// The lower boundary of the <see cref="AABB"/>.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public readonly Vector2D LowerBoundary = lowerBoundary;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// The upper boundary of the <see cref="AABB"/>.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public readonly Vector2D UpperBoundary = upperBoundary;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Gets the center point of the <see cref="AABB"/>.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public readonly Vector2D Center => (LowerBoundary + UpperBoundary) * .5f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Gets the size of the <see cref="AABB"/>.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public readonly Vector2D Size => LowerBoundary.FromTo(UpperBoundary).Abs();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Gets half the size of the <see cref="AABB"/>.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    public readonly Vector2D SizeHalf => Size * .5f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static bool operator ==(AABB left, AABB right) => left.UpperBoundary == right.UpperBoundary && left.LowerBoundary == right.LowerBoundary;
 | 
					 | 
				
			||||||
    public static bool operator !=(AABB left, AABB right) => left.UpperBoundary != right.UpperBoundary || left.LowerBoundary != right.LowerBoundary;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Creates an <see cref="AABB"/> from a collection of <see cref="Vector2D"/>s.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    /// <param name="vectors">The collection of <see cref="Vector2D"/>s.</param>
 | 
					 | 
				
			||||||
    /// <returns>An <see cref="AABB"/> that bounds all the <see cref="Vector2D"/>s.</returns>
 | 
					 | 
				
			||||||
    public static AABB FromVectors(IEnumerable<Vector2D> vectors)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        int counter = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Vector2D lowerBoundary = new(float.MaxValue, float.MaxValue);
 | 
					 | 
				
			||||||
        Vector2D upperBoundary = new(float.MinValue, float.MinValue);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach (Vector2D vector in vectors)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            lowerBoundary = Vector2D.Min(lowerBoundary, vector);
 | 
					 | 
				
			||||||
            upperBoundary = Vector2D.Max(upperBoundary, vector);
 | 
					 | 
				
			||||||
            counter++;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (counter < 2)
 | 
					 | 
				
			||||||
            throw new System.ArgumentException($"Parameter {nameof(vectors)} must have at least 2 items.");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return new(lowerBoundary, upperBoundary);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Checks if two <see cref="AABB"/>s are approximately equal.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    /// <param name="left">The first <see cref="AABB"/>.</param>
 | 
					 | 
				
			||||||
    /// <param name="right">The second <see cref="AABB"/>.</param>
 | 
					 | 
				
			||||||
    /// <param name="epsilon">The epsilon range.</param>
 | 
					 | 
				
			||||||
    /// <returns><see cref="true"/> if the <see cref="AABB"/>s are approximately equal; otherwise, <see cref="false"/>.</returns>
 | 
					 | 
				
			||||||
    public static bool ApproximatelyEquals(AABB left, AABB right, float epsilon = float.Epsilon)
 | 
					 | 
				
			||||||
        => left.LowerBoundary.ApproximatelyEquals(right.LowerBoundary, epsilon) && left.UpperBoundary.ApproximatelyEquals(right.UpperBoundary, epsilon);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Determines whether the specified object is equal to the current <see cref="AABB"/>.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    /// <param name="obj">The object to compare with the current <see cref="AABB"/>.</param>
 | 
					 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="AABB"/>; otherwise, <see cref="false"/>.</returns>
 | 
					 | 
				
			||||||
    public override bool Equals(object? obj) => obj is AABB aabb && this == aabb;
 | 
					 | 
				
			||||||
    public bool Equals(AABB other) => this == other;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Generates a hash code for the <see cref="AABB"/>.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    /// <returns>A hash code for the <see cref="AABB"/>.</returns>
 | 
					 | 
				
			||||||
    public override int GetHashCode() => System.HashCode.Combine(LowerBoundary, UpperBoundary);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Converts the <see cref="AABB"/> to its string representation.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    /// <returns>A string representation of the <see cref="AABB"/>.</returns>
 | 
					 | 
				
			||||||
    public override string ToString() => $"{nameof(AABB)}({LowerBoundary}, {UpperBoundary})";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// <summary>
 | 
					 | 
				
			||||||
/// Provides extension methods for the <see cref="AABB"/> struct.
 | 
					 | 
				
			||||||
/// </summary>
 | 
					 | 
				
			||||||
public static class AABBExtensions
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /// <inheritdoc cref="AABB.ToAABB" />
 | 
					 | 
				
			||||||
    public static AABB ToAABB(this IEnumerable<Vector2D> vectors) => AABB.FromVectors(vectors);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <inheritdoc cref="AABB.ApproximatelyEquals" />
 | 
					 | 
				
			||||||
    public static bool ApproximatelyEquals(this AABB left, AABB right, float epsilon = float.Epsilon) => AABB.ApproximatelyEquals(left, right, epsilon);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										114
									
								
								Engine.Core/Primitives/AABB2D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								Engine.Core/Primitives/AABB2D.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Represents an Axis-Aligned Bounding Box (AABB) in 2D space.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					/// <param name="lowerBoundary">The lower boundary of the <see cref="AABB2D"/>.</param>
 | 
				
			||||||
 | 
					/// <param name="upperBoundary">The upper boundary of the <see cref="AABB2D"/>.</param>
 | 
				
			||||||
 | 
					/// <remarks>
 | 
				
			||||||
 | 
					/// Initializes a new instance of the <see cref="AABB2D"/> struct with the specified lower and upper boundaries.
 | 
				
			||||||
 | 
					/// </remarks>
 | 
				
			||||||
 | 
					[System.Diagnostics.DebuggerDisplay("LowerBoundary: {LowerBoundary.ToString(), nq}, UpperBoundary: {UpperBoundary.ToString(), nq}")]
 | 
				
			||||||
 | 
					public readonly struct AABB2D(Vector2D lowerBoundary, Vector2D upperBoundary) : IEquatable<AABB2D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The lower boundary of the <see cref="AABB2D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector2D LowerBoundary = lowerBoundary;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The upper boundary of the <see cref="AABB2D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector2D UpperBoundary = upperBoundary;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Gets the center point of the <see cref="AABB2D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector2D Center => (LowerBoundary + UpperBoundary) * .5f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Gets the size of the <see cref="AABB2D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector2D Size => LowerBoundary.FromTo(UpperBoundary).Abs();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Gets half the size of the <see cref="AABB2D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector2D SizeHalf => Size * .5f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator ==(AABB2D left, AABB2D right) => left.UpperBoundary == right.UpperBoundary && left.LowerBoundary == right.LowerBoundary;
 | 
				
			||||||
 | 
					    public static bool operator !=(AABB2D left, AABB2D right) => left.UpperBoundary != right.UpperBoundary || left.LowerBoundary != right.LowerBoundary;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static implicit operator AABB2D(Circle circle) => new(circle.Center - new Vector2D(circle.Radius, circle.Radius), circle.Center + new Vector2D(circle.Radius, circle.Radius));
 | 
				
			||||||
 | 
					    public static implicit operator AABB2D(Shape2D shape) => FromVectors(shape.Vertices);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Creates an <see cref="AABB2D"/> from a collection of <see cref="Vector2D"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vectors">The collection of <see cref="Vector2D"/>s.</param>
 | 
				
			||||||
 | 
					    /// <returns>An <see cref="AABB2D"/> that bounds all the <see cref="Vector2D"/>s.</returns>
 | 
				
			||||||
 | 
					    public static AABB2D FromVectors(IEnumerable<Vector2D> vectors)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int counter = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Vector2D lowerBoundary = new(float.MaxValue, float.MaxValue);
 | 
				
			||||||
 | 
					        Vector2D upperBoundary = new(float.MinValue, float.MinValue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach (Vector2D vector in vectors)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            lowerBoundary = Vector2D.Min(lowerBoundary, vector);
 | 
				
			||||||
 | 
					            upperBoundary = Vector2D.Max(upperBoundary, vector);
 | 
				
			||||||
 | 
					            counter++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (counter < 2)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"Parameter {nameof(vectors)} must have at least 2 items.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new(lowerBoundary, upperBoundary);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Checks if two <see cref="AABB2D"/>s are approximately equal.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="AABB2D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="AABB2D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="epsilon">The epsilon range.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the <see cref="AABB2D"/>s are approximately equal; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(AABB2D left, AABB2D right, float epsilon = float.Epsilon)
 | 
				
			||||||
 | 
					        => left.LowerBoundary.ApproximatelyEquals(right.LowerBoundary, epsilon) && left.UpperBoundary.ApproximatelyEquals(right.UpperBoundary, epsilon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Determines whether the specified object is equal to the current <see cref="AABB2D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="obj">The object to compare with the current <see cref="AABB2D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="AABB2D"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public override bool Equals(object? obj) => obj is AABB2D aabb && this == aabb;
 | 
				
			||||||
 | 
					    public bool Equals(AABB2D other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Generates a hash code for the <see cref="AABB2D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A hash code for the <see cref="AABB2D"/>.</returns>
 | 
				
			||||||
 | 
					    public override int GetHashCode() => System.HashCode.Combine(LowerBoundary, UpperBoundary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Converts the <see cref="AABB2D"/> to its string representation.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A string representation of the <see cref="AABB2D"/>.</returns>
 | 
				
			||||||
 | 
					    public override string ToString() => $"{nameof(AABB2D)}({LowerBoundary}, {UpperBoundary})";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Provides extension methods for the <see cref="AABB2D"/> struct.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public static class AABBExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="AABB2D.FromVectors" />
 | 
				
			||||||
 | 
					    public static AABB2D ToAABB(this IEnumerable<Vector2D> vectors) => AABB2D.FromVectors(vectors);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="AABB2D.ApproximatelyEquals" />
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(this AABB2D left, AABB2D right, float epsilon = float.Epsilon) => AABB2D.ApproximatelyEquals(left, right, epsilon);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										113
									
								
								Engine.Core/Primitives/AABB3D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								Engine.Core/Primitives/AABB3D.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Represents an Axis-Aligned Bounding Box (AABB) in 3D space.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					/// <param name="lowerBoundary">The lower boundary of the <see cref="AABB3D"/>.</param>
 | 
				
			||||||
 | 
					/// <param name="upperBoundary">The upper boundary of the <see cref="AABB3D"/>.</param>
 | 
				
			||||||
 | 
					/// <remarks>
 | 
				
			||||||
 | 
					/// Initializes a new instance of the <see cref="AABB3D"/> struct with the specified lower and upper boundaries.
 | 
				
			||||||
 | 
					/// </remarks>
 | 
				
			||||||
 | 
					[System.Diagnostics.DebuggerDisplay("LowerBoundary: {LowerBoundary.ToString(), nq}, UpperBoundary: {UpperBoundary.ToString(), nq}")]
 | 
				
			||||||
 | 
					public readonly struct AABB3D(Vector3D lowerBoundary, Vector3D upperBoundary) : IEquatable<AABB3D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The lower boundary of the <see cref="AABB3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector3D LowerBoundary = lowerBoundary;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The upper boundary of the <see cref="AABB3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector3D UpperBoundary = upperBoundary;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Gets the center point of the <see cref="AABB3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector3D Center => (LowerBoundary + UpperBoundary) * .5f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Gets the size of the <see cref="AABB3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector3D Size => LowerBoundary.FromTo(UpperBoundary).Abs();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Gets half the size of the <see cref="AABB3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector3D SizeHalf => Size * .5f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator ==(AABB3D left, AABB3D right) => left.UpperBoundary == right.UpperBoundary && left.LowerBoundary == right.LowerBoundary;
 | 
				
			||||||
 | 
					    public static bool operator !=(AABB3D left, AABB3D right) => left.UpperBoundary != right.UpperBoundary || left.LowerBoundary != right.LowerBoundary;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static implicit operator AABB3D(Sphere3D sphere) => new(sphere.Center - new Vector3D(sphere.Radius, sphere.Radius, sphere.Radius), sphere.Center + new Vector3D(sphere.Radius, sphere.Radius, sphere.Radius));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Creates an <see cref="AABB3D"/> from a collection of <see cref="Vector3D"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vectors">The collection of <see cref="Vector3D"/>s.</param>
 | 
				
			||||||
 | 
					    /// <returns>An <see cref="AABB3D"/> that bounds all the <see cref="Vector3D"/>s.</returns>
 | 
				
			||||||
 | 
					    public static AABB3D FromVectors(IEnumerable<Vector3D> vectors)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int counter = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Vector3D lowerBoundary = new(float.MaxValue, float.MaxValue, float.MaxValue);
 | 
				
			||||||
 | 
					        Vector3D upperBoundary = new(float.MinValue, float.MinValue, float.MinValue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach (Vector3D vector in vectors)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            lowerBoundary = Vector3D.Min(lowerBoundary, vector);
 | 
				
			||||||
 | 
					            upperBoundary = Vector3D.Max(upperBoundary, vector);
 | 
				
			||||||
 | 
					            counter++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (counter < 2)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"Parameter {nameof(vectors)} must have at least 2 items.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new(lowerBoundary, upperBoundary);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Checks if two <see cref="AABB3D"/>s are approximately equal.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="AABB3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="AABB3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="epsilon">The epsilon range.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the <see cref="AABB3D"/>s are approximately equal; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(AABB3D left, AABB3D right, float epsilon = float.Epsilon)
 | 
				
			||||||
 | 
					        => left.LowerBoundary.ApproximatelyEquals(right.LowerBoundary, epsilon) && left.UpperBoundary.ApproximatelyEquals(right.UpperBoundary, epsilon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Determines whether the specified object is equal to the current <see cref="AABB3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="obj">The object to compare with the current <see cref="AABB3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="AABB3D"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public override bool Equals(object? obj) => obj is AABB3D aabb && this == aabb;
 | 
				
			||||||
 | 
					    public bool Equals(AABB3D other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Generates a hash code for the <see cref="AABB3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A hash code for the <see cref="AABB3D"/>.</returns>
 | 
				
			||||||
 | 
					    public override int GetHashCode() => System.HashCode.Combine(LowerBoundary, UpperBoundary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Converts the <see cref="AABB3D"/> to its string representation.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A string representation of the <see cref="AABB3D"/>.</returns>
 | 
				
			||||||
 | 
					    public override string ToString() => $"{nameof(AABB3D)}({LowerBoundary}, {UpperBoundary})";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Provides extension methods for the <see cref="AABB3D"/> struct.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public static class AABB3DExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="AABB3D.FromVectors" />
 | 
				
			||||||
 | 
					    public static AABB3D ToAABB3D(this IEnumerable<Vector3D> vectors) => AABB3D.FromVectors(vectors);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="AABB3D.ApproximatelyEquals" />
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(this AABB3D left, AABB3D right, float epsilon = float.Epsilon) => AABB3D.ApproximatelyEquals(left, right, epsilon);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -15,7 +15,7 @@ namespace Engine.Core;
 | 
				
			|||||||
public readonly struct Circle(Vector2D center, float radius) : IEquatable<Circle>
 | 
					public readonly struct Circle(Vector2D center, float radius) : IEquatable<Circle>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The center of the circle.
 | 
					    /// The center of the <see cref="Circle"/>.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    public readonly Vector2D Center = center;
 | 
					    public readonly Vector2D Center = center;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -42,6 +42,8 @@ public readonly struct Circle(Vector2D center, float radius) : IEquatable<Circle
 | 
				
			|||||||
    public static bool operator ==(Circle left, Circle right) => left.Center == right.Center && left.Radius == right.Radius;
 | 
					    public static bool operator ==(Circle left, Circle right) => left.Center == right.Center && left.Radius == right.Radius;
 | 
				
			||||||
    public static bool operator !=(Circle left, Circle right) => left.Center != right.Center || left.Radius != right.Radius;
 | 
					    public static bool operator !=(Circle left, Circle right) => left.Center != right.Center || left.Radius != right.Radius;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static implicit operator Circle(Sphere3D sphere) => new(sphere.Center, sphere.Radius);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Sets the center of the <see cref="Circle"/>.
 | 
					    /// Sets the center of the <see cref="Circle"/>.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
@@ -118,7 +120,7 @@ public static class CircleExtensions
 | 
				
			|||||||
    public static Circle Displace(this Circle circle, Vector2D displaceVector) => Circle.Displace(circle, displaceVector);
 | 
					    public static Circle Displace(this Circle circle, Vector2D displaceVector) => Circle.Displace(circle, displaceVector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc cref="Circle.Project(Circle, Vector2D)" />
 | 
					    /// <inheritdoc cref="Circle.Project(Circle, Vector2D)" />
 | 
				
			||||||
    public static Projection1D ToProjection(this Circle circle, Vector2D projectionVector) => Circle.Project(circle, projectionVector);
 | 
					    public static Projection1D ProjectTo(this Circle circle, Vector2D projectionVector) => Circle.Project(circle, projectionVector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc cref="Circle.Transform(ITransform2D, Circle)" />
 | 
					    /// <inheritdoc cref="Circle.Transform(ITransform2D, Circle)" />
 | 
				
			||||||
    public static Circle Transform(this ITransform2D transform, Circle circle) => Circle.Transform(transform, circle);
 | 
					    public static Circle Transform(this ITransform2D transform, Circle circle) => Circle.Transform(transform, circle);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,15 +50,7 @@ public readonly struct Line2D(Vector2D from, Vector2D to) : IEquatable<Line2D>
 | 
				
			|||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The equation of the <see cref="Line2D"/> defined by this <see cref="Line2D"/> segment.
 | 
					    /// The equation of the <see cref="Line2D"/> defined by this <see cref="Line2D"/> segment.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    public static Line2DEquation GetLineEquation(Line2D line)
 | 
					    public static Line2DEquation GetLineEquation(Line2D line) => line;
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Vector2D slopeVector = line.From.FromTo(line.To);
 | 
					 | 
				
			||||||
        float slope = slopeVector.Y / slopeVector.X;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        float yOffset = line.From.Y - (slope * line.From.X);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return new Line2DEquation(slope, yOffset);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Determines whether the specified <see cref="Vector2D"/> lies on the <see cref="Line2D"/>.
 | 
					    /// Determines whether the specified <see cref="Vector2D"/> lies on the <see cref="Line2D"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,6 +26,16 @@ public readonly struct Line2DEquation(float slope, float offsetY) : IEquatable<L
 | 
				
			|||||||
    public static bool operator ==(Line2DEquation left, Line2DEquation right) => left.Slope == right.Slope && left.OffsetY == right.OffsetY;
 | 
					    public static bool operator ==(Line2DEquation left, Line2DEquation right) => left.Slope == right.Slope && left.OffsetY == right.OffsetY;
 | 
				
			||||||
    public static bool operator !=(Line2DEquation left, Line2DEquation right) => left.Slope != right.Slope || left.OffsetY != right.OffsetY;
 | 
					    public static bool operator !=(Line2DEquation left, Line2DEquation right) => left.Slope != right.Slope || left.OffsetY != right.OffsetY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static implicit operator Line2DEquation(Line2D line)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector2D slopeVector = line.From.FromTo(line.To);
 | 
				
			||||||
 | 
					        float slope = slopeVector.Y / slopeVector.X;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        float yOffset = line.From.Y - (slope * line.From.X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Line2DEquation(slope, yOffset);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Resolves the Y coordinate for a given X coordinate using the <see cref="Line2DEquation"/>.
 | 
					    /// Resolves the Y coordinate for a given X coordinate using the <see cref="Line2DEquation"/>.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										114
									
								
								Engine.Core/Primitives/Line3D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								Engine.Core/Primitives/Line3D.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Represents a 3D line segment defined by two endpoints.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					/// <param name="from">The starting point of the <see cref="Line3D"/> segment.</param>
 | 
				
			||||||
 | 
					/// <param name="to">The ending point of the <see cref="Line3D"/> segment.</param>
 | 
				
			||||||
 | 
					/// <remarks>
 | 
				
			||||||
 | 
					/// Initializes a new instance of the <see cref="Line3D"/> struct with the specified endpoints.
 | 
				
			||||||
 | 
					/// </remarks>
 | 
				
			||||||
 | 
					[System.Diagnostics.DebuggerDisplay("From: {From.ToString(),nq}, To: {To.ToString(),nq}, Direction: {Direction.ToString(),nq}, Length: {Length}")]
 | 
				
			||||||
 | 
					public readonly struct Line3D(Vector3D from, Vector3D to) : IEquatable<Line3D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The starting point of the <see cref="Line3D"/> segment.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector3D From = from;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The ending point of the <see cref="Line3D"/> segment.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector3D To = to;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The reversed <see cref="Line3D"/> segment.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Line3D Reversed => new(To, From);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The normalized direction <see cref="Vector3D"/> of the <see cref="Line3D"/> segment.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector3D Direction => From.FromTo(To).Normalize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The length of the <see cref="Line3D"/> segment.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly float Length => From.FromTo(To).Length();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The squared length of the <see cref="Line3D"/> segment.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly float LengthSquared => From.FromTo(To).LengthSquared();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator ==(Line3D left, Line3D right) => left.From == right.From && left.To == right.To;
 | 
				
			||||||
 | 
					    public static bool operator !=(Line3D left, Line3D right) => left.From != right.From || left.To != right.To;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Linearly interpolates between the two endpoints of the <see cref="Line3D"/> segment using parameter 't'.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static Vector3D Lerp(Line3D line, float t)
 | 
				
			||||||
 | 
					        => Vector3D.Lerp(line.From, line.To, t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the closest point on the <see cref="Line3D"/> segment to the specified point.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static Vector3D ClosestPointTo(Line3D line, Vector3D point)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3D lineRelativeVector = line.From.FromTo(line.To);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Vector3D lineDirection = lineRelativeVector.Normalized;
 | 
				
			||||||
 | 
					        Vector3D pointVector = line.From.FromTo(point);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        float dot = lineDirection.Dot(pointVector).Clamp(0f, lineRelativeVector.Magnitude);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return lineDirection * dot;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Checks if two <see cref="Line3D"/> segments are approximately equal.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Line3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Line3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="epsilon">The epsilon range.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the <see cref="Line3D"/>s are approximately equal; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(Line3D left, Line3D right, float epsilon = float.Epsilon)
 | 
				
			||||||
 | 
					        => left.From.ApproximatelyEquals(right.From, epsilon) && left.To.ApproximatelyEquals(right.To, epsilon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Determines whether the specified object is equal to the current <see cref="Line3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Line3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Line3D"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public override bool Equals(object? obj) => obj is Line3D line3D && this == line3D;
 | 
				
			||||||
 | 
					    public bool Equals(Line3D other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Generates a hash code for the <see cref="Line3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A hash code for the <see cref="Line3D"/>.</returns>
 | 
				
			||||||
 | 
					    public override int GetHashCode() => System.HashCode.Combine(From, To);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Converts the <see cref="Line3D"/> to its string representation.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A string representation of the <see cref="Line3D"/>.</returns>
 | 
				
			||||||
 | 
					    public override string ToString() => $"{nameof(Line3D)}({From}, {To})";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Provides extension methods for the <see cref="Line3D"/> struct.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public static class Line3DExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Line3D.Lerp(Line3D, float)" />
 | 
				
			||||||
 | 
					    public static Vector3D Lerp(this Line3D line, float t) => Line3D.Lerp(line, t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Line3D.ClosestPointTo(Line3D, Vector3D)" />
 | 
				
			||||||
 | 
					    public static Vector3D ClosestPointTo(this Line3D line, Vector3D point) => Line3D.ClosestPointTo(line, point);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Line3D.ApproximatelyEquals(Line3D, Line3D, float)" />
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(this Line3D left, Line3D right, float epsilon = float.Epsilon) => Line3D.ApproximatelyEquals(left, right, epsilon);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -79,6 +79,30 @@ public readonly struct Quaternion(float x, float y, float z, float w) : IEquatab
 | 
				
			|||||||
    public static implicit operator Quaternion(System.Numerics.Quaternion quaternion) => new(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
 | 
					    public static implicit operator Quaternion(System.Numerics.Quaternion quaternion) => new(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
 | 
				
			||||||
    public static implicit operator System.Numerics.Quaternion(Quaternion quaternion) => new(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
 | 
					    public static implicit operator System.Numerics.Quaternion(Quaternion quaternion) => new(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Get the Pitch, Yaw and Roll of the <see cref="Quaternion"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static Vector3D ToAngles(Quaternion quaternion)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Quaternion to Euler angles (in 3-2-1 sequence) conversion
 | 
				
			||||||
 | 
					        float sinr_cosp = 2f * (quaternion.W * quaternion.X + quaternion.Y * quaternion.Z);
 | 
				
			||||||
 | 
					        float cosr_cosp = 1f - 2f * (quaternion.X * quaternion.X + quaternion.Y * quaternion.Y);
 | 
				
			||||||
 | 
					        float pitch = MathF.Atan2(sinr_cosp, cosr_cosp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        float sinp = 2f * (quaternion.W * quaternion.Y - quaternion.Z * quaternion.X);
 | 
				
			||||||
 | 
					        float yaw;
 | 
				
			||||||
 | 
					        if (MathF.Abs(sinp) >= 1f)
 | 
				
			||||||
 | 
					            yaw = MathF.CopySign(MathF.PI / 2f, sinp);
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            yaw = MathF.Asin(sinp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        float siny_cosp = 2f * (quaternion.W * quaternion.Z + quaternion.X * quaternion.Y);
 | 
				
			||||||
 | 
					        float cosy_cosp = 1f - 2f * (quaternion.Y * quaternion.Y + quaternion.Z * quaternion.Z);
 | 
				
			||||||
 | 
					        float roll = MathF.Atan2(siny_cosp, cosy_cosp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Vector3D(pitch, yaw, roll) * Math.RadianToDegree;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Calculates the length of the <see cref="Quaternion"/>.
 | 
					    /// Calculates the length of the <see cref="Quaternion"/>.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
@@ -132,6 +156,15 @@ public readonly struct Quaternion(float x, float y, float z, float w) : IEquatab
 | 
				
			|||||||
    /// <returns>The normalized <see cref="Quaternion"/>.</returns>
 | 
					    /// <returns>The normalized <see cref="Quaternion"/>.</returns>
 | 
				
			||||||
    public static Quaternion Normalize(Quaternion quaternion) => quaternion / Length(quaternion);
 | 
					    public static Quaternion Normalize(Quaternion quaternion) => quaternion / Length(quaternion);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Rotates a <see cref="Quaternion"/> around a axis by the specified angle (in radians).
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Quaternion"/> to rotate.</param>
 | 
				
			||||||
 | 
					    /// <param name="axis">The <see cref="Quaternion"/> to rotate around.</param>
 | 
				
			||||||
 | 
					    /// <param name="angleInRadian">The angle to rotate by, in radians.</param>
 | 
				
			||||||
 | 
					    /// <returns>The rotated <see cref="Quaternion"/>.</returns>
 | 
				
			||||||
 | 
					    public static Quaternion Rotate(Quaternion vector, Vector3D axis, float angleInRadian) => vector * Quaternion.FromAxisAngle(axis, angleInRadian);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Inverts the direction of the <see cref="Quaternion"/>.
 | 
					    /// Inverts the direction of the <see cref="Quaternion"/>.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
@@ -154,8 +187,12 @@ public readonly struct Quaternion(float x, float y, float z, float w) : IEquatab
 | 
				
			|||||||
    /// <returns>The rotated <see cref="Vector3D"/>.</returns>
 | 
					    /// <returns>The rotated <see cref="Vector3D"/>.</returns>
 | 
				
			||||||
    public static Vector3D RotateVector(Vector3D vector, Quaternion quaternion)
 | 
					    public static Vector3D RotateVector(Vector3D vector, Quaternion quaternion)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Quaternion rotation = quaternion * new Quaternion(vector.X, vector.Y, vector.Z, 0) * Invert(quaternion);
 | 
					        // https://blog.molecular-matters.com/2013/05/24/a-faster-quaternion-vector-multiplication/
 | 
				
			||||||
        return new(rotation.X, rotation.Y, rotation.Z);
 | 
					        // t = 2 * cross(q.xyz, v)
 | 
				
			||||||
 | 
					        // v' = v + q.w * t + cross(q.xyz, t)
 | 
				
			||||||
 | 
					        Vector3D quaternionVector = new(quaternion.X, quaternion.Y, quaternion.Z);
 | 
				
			||||||
 | 
					        Vector3D t = 2f * quaternionVector.Cross(vector);
 | 
				
			||||||
 | 
					        return vector + quaternion.W * t + quaternionVector.Cross(t);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
@@ -210,9 +247,9 @@ public readonly struct Quaternion(float x, float y, float z, float w) : IEquatab
 | 
				
			|||||||
    /// <param name="axis">The axis of the rotation in <see cref="Vector3D"/>.</param>
 | 
					    /// <param name="axis">The axis of the rotation in <see cref="Vector3D"/>.</param>
 | 
				
			||||||
    /// <param name="angle">The angle in radians.</param>
 | 
					    /// <param name="angle">The angle in radians.</param>
 | 
				
			||||||
    /// <returns>The rotation <see cref="Quaternion"/> calculated by the given parameters.</returns>
 | 
					    /// <returns>The rotation <see cref="Quaternion"/> calculated by the given parameters.</returns>
 | 
				
			||||||
    public static Quaternion FromAxisAngle(Vector3D axis, float angle)
 | 
					    public static Quaternion FromAxisAngle(Vector3D axis, float angleInRadian)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        float halfAngle = angle * .5f;
 | 
					        float halfAngle = angleInRadian * .5f;
 | 
				
			||||||
        float sinHalf = Math.Sin(halfAngle);
 | 
					        float sinHalf = Math.Sin(halfAngle);
 | 
				
			||||||
        return new Quaternion(axis.X * sinHalf, axis.Y * sinHalf, axis.Z * sinHalf, Math.Cos(halfAngle));
 | 
					        return new Quaternion(axis.X * sinHalf, axis.Y * sinHalf, axis.Z * sinHalf, Math.Cos(halfAngle));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -310,6 +347,9 @@ public readonly struct Quaternion(float x, float y, float z, float w) : IEquatab
 | 
				
			|||||||
/// </summary>
 | 
					/// </summary>
 | 
				
			||||||
public static class QuaternionExtensions
 | 
					public static class QuaternionExtensions
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Quaternion.ToAngles(Quaternion)" />
 | 
				
			||||||
 | 
					    public static Vector3D ToAngles(this Quaternion quaternion) => Quaternion.ToAngles(quaternion);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc cref="Quaternion.Length(Quaternion)" />
 | 
					    /// <inheritdoc cref="Quaternion.Length(Quaternion)" />
 | 
				
			||||||
    public static float Length(this Quaternion quaternion) => Quaternion.Length(quaternion);
 | 
					    public static float Length(this Quaternion quaternion) => Quaternion.Length(quaternion);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -331,6 +371,9 @@ public static class QuaternionExtensions
 | 
				
			|||||||
    /// <inheritdoc cref="Quaternion.Normalize(Quaternion)" />
 | 
					    /// <inheritdoc cref="Quaternion.Normalize(Quaternion)" />
 | 
				
			||||||
    public static Quaternion Normalize(this Quaternion quaternion) => Quaternion.Normalize(quaternion);
 | 
					    public static Quaternion Normalize(this Quaternion quaternion) => Quaternion.Normalize(quaternion);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Quaternion.Rotate(Quaternion, Vector3D, float)" />
 | 
				
			||||||
 | 
					    public static Quaternion Rotate(this Quaternion vector, Vector3D normal, float angleInRadian) => Quaternion.Rotate(vector, normal, angleInRadian);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc cref="Quaternion.Invert(Quaternion)" />
 | 
					    /// <inheritdoc cref="Quaternion.Invert(Quaternion)" />
 | 
				
			||||||
    public static Quaternion Invert(this Quaternion quaternion) => Quaternion.Invert(quaternion);
 | 
					    public static Quaternion Invert(this Quaternion quaternion) => Quaternion.Invert(quaternion);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										109
									
								
								Engine.Core/Primitives/Ray3D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								Engine.Core/Primitives/Ray3D.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Represents an infinite ray in 3D space.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					/// <param name="Origin">The <see cref="Vector3D"/> in 3D space where the ray starts from.</param>
 | 
				
			||||||
 | 
					/// <param name="Direction">Normalized <see cref="Vector3D"/> indicating the ray's is direction.</param> 
 | 
				
			||||||
 | 
					public readonly struct Ray3D(Vector3D Origin, Vector3D Direction) : IEquatable<Ray3D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The starting point of the <see cref="Ray3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector3D Origin = Origin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The direction in which the <see cref="Ray3D"/> points. Should be a normalized vector.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector3D Direction = Direction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Gets a <see cref="Ray3D"/> with the same origin but with the direction reversed.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Ray3D Reversed => new(Origin, -Direction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator ==(Ray3D left, Ray3D right) => left.Origin == right.Origin && left.Direction == right.Direction;
 | 
				
			||||||
 | 
					    public static bool operator !=(Ray3D left, Ray3D right) => left.Origin != right.Origin || left.Direction != right.Direction;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public static implicit operator Ray3D(Line3D line) => new(line.From, line.From.FromTo(line.To).Normalized);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Constructs a <see cref="Line3D"/> from a <see cref="Ray3D"/>, extending from its origin in the <see cref="Ray3D"/>'s direction for a given distance.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="ray">The source <see cref="Ray3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="distance">The length of the line segment to create from the <see cref="Ray3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>A <see cref="Line3D"/> representing the segment of the <see cref="Ray3D"/>.</returns>
 | 
				
			||||||
 | 
					    public static Line3D GetLine(Ray3D ray, float distance)
 | 
				
			||||||
 | 
					        => new(ray.Origin, ray.Origin + ray.Direction * distance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Evaluates the point on the <see cref="Ray3D"/> at a specified distance from its origin.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="ray">The <see cref="Ray3D"/> to evaluate.</param>
 | 
				
			||||||
 | 
					    /// <param name="distanceFromOrigin">The distance from the origin along the <see cref="Ray3D"/>'s direction.</param>
 | 
				
			||||||
 | 
					    /// <returns>A <see cref="Vector3D"/> representing the point at the given distance on the <see cref="Ray3D"/>.</returns>
 | 
				
			||||||
 | 
					    public static Vector3D Evaluate(Ray3D ray, float distanceFromOrigin)
 | 
				
			||||||
 | 
					        => ray.Origin + ray.Direction * distanceFromOrigin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the closest point on the <see cref="Ray3D"/> to the specified point.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static Vector3D ClosestPointTo(Ray3D ray, Vector3D point)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3D originToPoint = ray.Origin.FromTo(point);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        float dot = ray.Direction.Dot(originToPoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ray.Origin + ray.Direction * dot;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Checks if two <see cref="Ray3D"/>s are approximately equal within a specified epsilon range.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Ray3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Ray3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="epsilon">The epsilon range.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the <see cref="Ray3D"/>s are approximately equal; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(Ray3D left, Ray3D right, float epsilon = float.Epsilon)
 | 
				
			||||||
 | 
					        => left.Origin.ApproximatelyEquals(right.Origin, epsilon) && left.Direction.ApproximatelyEquals(right.Direction, epsilon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Determines whether the specified object is equal to the current <see cref="Ray3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Ray3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Ray3D"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public override bool Equals(object? obj) => obj is Ray3D ray3D && this == ray3D;
 | 
				
			||||||
 | 
					    public bool Equals(Ray3D other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Generates a hash code for the <see cref="Ray3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A hash code for the <see cref="Ray3D"/>.</returns>
 | 
				
			||||||
 | 
					    public override int GetHashCode() => System.HashCode.Combine(Origin, Direction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Converts the <see cref="Ray3D"/> to its string representation.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A string representation of the <see cref="Ray3D"/>.</returns>
 | 
				
			||||||
 | 
					    public override string ToString() => $"{nameof(Ray3D)}({Origin}, {Direction})";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Provides extension methods for the <see cref="Ray3D"/> struct.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public static class Ray3DExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Ray3D.GetLine(Ray3D, float) />
 | 
				
			||||||
 | 
					    public static Line3D ToLine(this Ray3D ray, float distance) => Ray3D.GetLine(ray, distance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Ray3D.Evaluate(Ray3D, float) />
 | 
				
			||||||
 | 
					    public static Vector3D Evaluate(this Ray3D ray, float distanceFromOrigin) => Ray3D.Evaluate(ray, distanceFromOrigin);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Ray3D.ClosestPointTo(Ray3D, Vector3D) />
 | 
				
			||||||
 | 
					    public static Vector3D ClosestPointTo(this Ray3D ray, Vector3D point) => Ray3D.ClosestPointTo(ray, point);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Ray3D.ApproximatelyEquals(Ray3D, Ray3D, float)" />
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(this Ray3D left, Ray3D right, float epsilon = float.Epsilon) => Ray3D.ApproximatelyEquals(left, right, epsilon);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										131
									
								
								Engine.Core/Primitives/Sphere3D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								Engine.Core/Primitives/Sphere3D.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Diagnostics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Represents a 3D sphere.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					/// <param name="center">The center of the sphere.</param>
 | 
				
			||||||
 | 
					/// <param name="radius">The radius of the sphere.</param>
 | 
				
			||||||
 | 
					/// <remarks>
 | 
				
			||||||
 | 
					/// Initializes a new instance of the <see cref="Sphere3D"/> struct with the specified center and radius.
 | 
				
			||||||
 | 
					/// </remarks>
 | 
				
			||||||
 | 
					[DebuggerDisplay("Center: {Center.ToString(),nq}, Radius: {Radius}")]
 | 
				
			||||||
 | 
					public readonly struct Sphere3D(Vector3D center, float radius) : IEquatable<Sphere3D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The center of the <see cref="Sphere3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector3D Center = center;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The radius of the <see cref="Sphere3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly float Radius = radius;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Gets the squared radius of the <see cref="Sphere3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly float RadiusSquared => Radius * Radius;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Gets the diameter of the <see cref="Sphere3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly float Diameter => 2f * Radius;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// A predefined unit <see cref="Sphere3D"/> with a center at the origin and a radius of 1.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static readonly Sphere3D UnitSphere = new(Vector3D.Zero, 1f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static bool operator ==(Sphere3D left, Sphere3D right) => left.Center == right.Center && left.Radius == right.Radius;
 | 
				
			||||||
 | 
					    public static bool operator !=(Sphere3D left, Sphere3D right) => left.Center != right.Center || left.Radius != right.Radius;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Sets the center of the <see cref="Sphere3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static Sphere3D SetCenter(Sphere3D sphere, Vector3D center) => new(center, sphere.Radius);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Sets the radius of the <see cref="Sphere3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static Sphere3D SetRadius(Sphere3D sphere, float radius) => new(sphere.Center, radius);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Displaces the <see cref="Sphere3D"/> by the specified <see cref="Vector3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static Sphere3D Displace(Sphere3D sphere, Vector3D displaceVector) => new(sphere.Center + displaceVector, sphere.Radius);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Projects the <see cref="Sphere3D"/> onto the specified <see cref="Vector3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static Projection1D Project(Sphere3D sphere, Vector3D projectionVector)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        float projectedCenter = sphere.Center.Dot(projectionVector);
 | 
				
			||||||
 | 
					        return new(projectedCenter - sphere.Radius, projectedCenter + sphere.Radius);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Transforms the <see cref="Sphere3D"/> by the specified <see cref="ITransform3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static Sphere3D Transform(ITransform3D transform, Sphere3D sphere)
 | 
				
			||||||
 | 
					        => new(transform.Transform(sphere.Center), sphere.Radius * (transform.Scale.Magnitude / Vector3D.One.Magnitude));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Checks if two <see cref="Sphere3D"/>s are approximately equal.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Sphere3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Sphere3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="epsilon">The epsilon range.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the <see cref="Sphere3D"/>s are approximately equal; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(Sphere3D left, Sphere3D right, float epsilon = float.Epsilon)
 | 
				
			||||||
 | 
					        => left.Center.ApproximatelyEquals(right.Center, epsilon) && left.Radius.ApproximatelyEquals(right.Radius, epsilon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Determines whether the specified object is equal to the current <see cref="Sphere3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Sphere3D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Sphere3D"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public override bool Equals(object? obj) => obj is Sphere3D sphere && this == sphere;
 | 
				
			||||||
 | 
					    public bool Equals(Sphere3D other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Generates a hash code for the <see cref="Sphere3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A hash code for the <see cref="Sphere3D"/>.</returns>
 | 
				
			||||||
 | 
					    public override int GetHashCode() => System.HashCode.Combine(Center, Radius);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Converts the <see cref="Sphere3D"/> to its string representation.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A string representation of the <see cref="Sphere3D"/>.</returns>
 | 
				
			||||||
 | 
					    public override string ToString() => $"{nameof(Sphere3D)}({Center}, {Radius})";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Provides extension methods for the <see cref="Sphere3D"/> struct.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public static class SphereExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Sphere3D.SetCenter(Sphere3D, Vector3D)" />
 | 
				
			||||||
 | 
					    public static Sphere3D SetCenter(this Sphere3D sphere, Vector3D center) => Sphere3D.SetCenter(sphere, center);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Sphere3D.SetRadius(Sphere3D, float)" />
 | 
				
			||||||
 | 
					    public static Sphere3D SetRadius(this Sphere3D sphere, float radius) => Sphere3D.SetRadius(sphere, radius);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Sphere3D.Displace(Sphere3D, Vector3D)" />
 | 
				
			||||||
 | 
					    public static Sphere3D Displace(this Sphere3D sphere, Vector3D displaceVector) => Sphere3D.Displace(sphere, displaceVector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Sphere3D.Project(Sphere3D, Vector3D)" />
 | 
				
			||||||
 | 
					    public static Projection1D ProjectTo(this Sphere3D sphere, Vector3D projectionVector) => Sphere3D.Project(sphere, projectionVector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Sphere3D.Transform(ITransform3D, Sphere3D)" />
 | 
				
			||||||
 | 
					    public static Sphere3D Transform(this ITransform3D transform, Sphere3D sphere) => Sphere3D.Transform(transform, sphere);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Sphere3D.Transform(ITransform3D, Sphere3D)" />
 | 
				
			||||||
 | 
					    public static Sphere3D Transform(this Sphere3D sphere, ITransform3D transform) => Sphere3D.Transform(transform, sphere);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Sphere3D.ApproximatelyEquals(Sphere3D, Sphere3D, float)" />
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(this Sphere3D left, Sphere3D right, float epsilon = float.Epsilon) => Sphere3D.ApproximatelyEquals(left, right, epsilon);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -71,9 +71,6 @@ public readonly struct Vector2DInt(int x, int y) : IEquatable<Vector2DInt>
 | 
				
			|||||||
    public static Vector2DInt operator -(Vector2DInt vector) => new(0 - vector.X, 0 - vector.Y);
 | 
					    public static Vector2DInt operator -(Vector2DInt vector) => new(0 - vector.X, 0 - vector.Y);
 | 
				
			||||||
    public static Vector2DInt operator +(Vector2DInt left, Vector2DInt right) => new(left.X + right.X, left.Y + right.Y);
 | 
					    public static Vector2DInt operator +(Vector2DInt left, Vector2DInt right) => new(left.X + right.X, left.Y + right.Y);
 | 
				
			||||||
    public static Vector2DInt operator -(Vector2DInt left, Vector2DInt right) => new(left.X - right.X, left.Y - right.Y);
 | 
					    public static Vector2DInt operator -(Vector2DInt left, Vector2DInt right) => new(left.X - right.X, left.Y - right.Y);
 | 
				
			||||||
    public static Vector2DInt operator *(Vector2DInt vector, int value) => new(vector.X * value, vector.Y * value);
 | 
					 | 
				
			||||||
    public static Vector2DInt operator *(int value, Vector2DInt vector) => new(vector.X * value, vector.Y * value);
 | 
					 | 
				
			||||||
    public static Vector2DInt operator /(Vector2DInt vector, int value) => new(vector.X / value, vector.Y / value);
 | 
					 | 
				
			||||||
    public static bool operator ==(Vector2DInt left, Vector2DInt right) => left.X == right.X && left.Y == right.Y;
 | 
					    public static bool operator ==(Vector2DInt left, Vector2DInt right) => left.X == right.X && left.Y == right.Y;
 | 
				
			||||||
    public static bool operator !=(Vector2DInt left, Vector2DInt right) => left.X != right.X || left.Y != right.Y;
 | 
					    public static bool operator !=(Vector2DInt left, Vector2DInt right) => left.X != right.X || left.Y != right.Y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -125,22 +122,6 @@ public readonly struct Vector2DInt(int x, int y) : IEquatable<Vector2DInt>
 | 
				
			|||||||
    /// <returns>The result of subtracting the second <see cref="Vector2DInt"/> from the first.</returns>
 | 
					    /// <returns>The result of subtracting the second <see cref="Vector2DInt"/> from the first.</returns>
 | 
				
			||||||
    public static Vector2DInt Subtract(Vector2DInt left, Vector2DInt right) => left - right;
 | 
					    public static Vector2DInt Subtract(Vector2DInt left, Vector2DInt right) => left - right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Multiplies a <see cref="Vector2DInt"/> by a scalar value.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    /// <param name="vector">The <see cref="Vector2DInt"/>.</param>
 | 
					 | 
				
			||||||
    /// <param name="value">The scalar value.</param>
 | 
					 | 
				
			||||||
    /// <returns>The result of multiplying the <see cref="Vector2DInt"/> by the scalar value.</returns>
 | 
					 | 
				
			||||||
    public static Vector2DInt Multiply(Vector2DInt vector, int value) => vector * value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Divides a <see cref="Vector2DInt"/> by a scalar value.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    /// <param name="vector">The <see cref="Vector2DInt"/>.</param>
 | 
					 | 
				
			||||||
    /// <param name="value">The scalar value.</param>
 | 
					 | 
				
			||||||
    /// <returns>The result of dividing the <see cref="Vector2DInt"/> by the scalar value.</returns>
 | 
					 | 
				
			||||||
    public static Vector2DInt Divide(Vector2DInt vector, int value) => vector / value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Calculates the absolute value of each component of the vector.
 | 
					    /// Calculates the absolute value of each component of the vector.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
@@ -196,15 +177,6 @@ public readonly struct Vector2DInt(int x, int y) : IEquatable<Vector2DInt>
 | 
				
			|||||||
    /// <returns>A <see cref="Vector2DInt"/> with each component clamped between the corresponding components of the min and max <see cref="Vector2DInt"/>s.</returns>
 | 
					    /// <returns>A <see cref="Vector2DInt"/> with each component clamped between the corresponding components of the min and max <see cref="Vector2DInt"/>s.</returns>
 | 
				
			||||||
    public static Vector2DInt Clamp(Vector2DInt vector, Vector2DInt min, Vector2DInt max) => new(Engine.Core.Math.Clamp(vector.X, min.X, max.X), Engine.Core.Math.Clamp(vector.Y, min.Y, max.Y));
 | 
					    public static Vector2DInt Clamp(Vector2DInt vector, Vector2DInt min, Vector2DInt max) => new(Engine.Core.Math.Clamp(vector.X, min.X, max.X), Engine.Core.Math.Clamp(vector.Y, min.Y, max.Y));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Performs linear interpolation between two <see cref="Vector2DInt"/>s.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    /// <param name="from">The starting <see cref="Vector2DInt"/> (t = 0).</param>
 | 
					 | 
				
			||||||
    /// <param name="to">The ending <see cref="Vector2DInt"/> (t = 1).</param>
 | 
					 | 
				
			||||||
    /// <param name="t">The interpolation parameter.</param>
 | 
					 | 
				
			||||||
    /// <returns>The interpolated <see cref="Vector2DInt"/>.</returns>
 | 
					 | 
				
			||||||
    public static Vector2DInt Lerp(Vector2DInt from, Vector2DInt to, int t) => from + FromTo(from, to) * t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Calculates the cross product of two <see cref="Vector2DInt"/>s.
 | 
					    /// Calculates the cross product of two <see cref="Vector2DInt"/>s.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
@@ -265,12 +237,6 @@ public static class Vector2DIntExtensions
 | 
				
			|||||||
    /// <inheritdoc cref="Vector2DInt.Subtract(Vector2DInt, Vector2DInt)" />
 | 
					    /// <inheritdoc cref="Vector2DInt.Subtract(Vector2DInt, Vector2DInt)" />
 | 
				
			||||||
    public static Vector2DInt Subtract(this Vector2DInt vector, Vector2DInt vectorToSubtract) => Vector2DInt.Subtract(vector, vectorToSubtract);
 | 
					    public static Vector2DInt Subtract(this Vector2DInt vector, Vector2DInt vectorToSubtract) => Vector2DInt.Subtract(vector, vectorToSubtract);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc cref="Vector2DInt.Multiply(Vector2DInt, int)" />
 | 
					 | 
				
			||||||
    public static Vector2DInt Multiply(this Vector2DInt vector, int value) => Vector2DInt.Multiply(vector, value);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <inheritdoc cref="Vector2DInt.Divide(Vector2DInt, int)" />
 | 
					 | 
				
			||||||
    public static Vector2DInt Divide(this Vector2DInt vector, int value) => Vector2DInt.Divide(vector, value);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <inheritdoc cref="Vector2DInt.Abs(Vector2DInt)" />
 | 
					    /// <inheritdoc cref="Vector2DInt.Abs(Vector2DInt)" />
 | 
				
			||||||
    public static Vector2DInt Abs(this Vector2DInt vector) => Vector2DInt.Abs(vector);
 | 
					    public static Vector2DInt Abs(this Vector2DInt vector) => Vector2DInt.Abs(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -292,9 +258,6 @@ public static class Vector2DIntExtensions
 | 
				
			|||||||
    /// <inheritdoc cref="Vector2DInt.Clamp(Vector2DInt, Vector2DInt,Vector2DInt)" />
 | 
					    /// <inheritdoc cref="Vector2DInt.Clamp(Vector2DInt, Vector2DInt,Vector2DInt)" />
 | 
				
			||||||
    public static Vector2DInt Clamp(this Vector2DInt vector, Vector2DInt min, Vector2DInt max) => Vector2DInt.Clamp(vector, min, max);
 | 
					    public static Vector2DInt Clamp(this Vector2DInt vector, Vector2DInt min, Vector2DInt max) => Vector2DInt.Clamp(vector, min, max);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc cref="Vector2DInt.Lerp(Vector2DInt, Vector2DInt," />
 | 
					 | 
				
			||||||
    public static Vector2DInt Lerp(this Vector2DInt from, Vector2DInt to, int t) => Vector2DInt.Lerp(from, to, t);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <inheritdoc cref="Vector2DInt.Cross(Vector2DInt, Vector2DInt)" />
 | 
					    /// <inheritdoc cref="Vector2DInt.Cross(Vector2DInt, Vector2DInt)" />
 | 
				
			||||||
    public static int Cross(this Vector2DInt left, Vector2DInt right) => Vector2DInt.Cross(left, right);
 | 
					    public static int Cross(this Vector2DInt left, Vector2DInt right) => Vector2DInt.Cross(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -198,13 +198,13 @@ public readonly struct Vector3D(float x, float y, float z) : IEquatable<Vector3D
 | 
				
			|||||||
    public static Vector3D Scale(Vector3D vector, Vector3D scale) => new(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z);
 | 
					    public static Vector3D Scale(Vector3D vector, Vector3D scale) => new(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Rotates a <see cref="Vector3D"/> around a normal by the specified angle (in radians).
 | 
					    /// Rotates a <see cref="Vector3D"/> around a axis by the specified angle (in radians).
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="vector">The <see cref="Vector3D"/> to rotate.</param>
 | 
					    /// <param name="vector">The <see cref="Vector3D"/> to rotate.</param>
 | 
				
			||||||
    /// <param name="normal">The <see cref="Vector3D"/> to rotate around.</param>
 | 
					    /// <param name="axis">The <see cref="Vector3D"/> to rotate around.</param>
 | 
				
			||||||
    /// <param name="angleInRadian">The angle to rotate by, in radians.</param>
 | 
					    /// <param name="angleInRadian">The angle to rotate by, in radians.</param>
 | 
				
			||||||
    /// <returns>The rotated <see cref="Vector3D"/>.</returns>
 | 
					    /// <returns>The rotated <see cref="Vector3D"/>.</returns>
 | 
				
			||||||
    public static Vector3D Rotate(Vector3D vector, Vector3D normal, float angleInRadian) => vector * Math.Cos(angleInRadian) + Cross(normal, vector) * Math.Sin(angleInRadian) + normal * Dot(normal, vector) * (1f - Math.Cos(angleInRadian));
 | 
					    public static Vector3D Rotate(Vector3D vector, Vector3D axis, float angleInRadian) => vector * Math.Cos(angleInRadian) + Cross(axis, vector) * Math.Sin(angleInRadian) + axis * Dot(axis, vector) * (1f - Math.Cos(angleInRadian));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Returns the component-wise minimum of two <see cref="Vector3D"/>s.
 | 
					    /// Returns the component-wise minimum of two <see cref="Vector3D"/>s.
 | 
				
			||||||
@@ -264,6 +264,15 @@ public readonly struct Vector3D(float x, float y, float z) : IEquatable<Vector3D
 | 
				
			|||||||
    /// <returns>The dot product of the two <see cref="Vector3D"/>s.</returns>
 | 
					    /// <returns>The dot product of the two <see cref="Vector3D"/>s.</returns>
 | 
				
			||||||
    public static float Dot(Vector3D left, Vector3D right) => left.X * right.X + left.Y * right.Y + left.Z * right.Z;
 | 
					    public static float Dot(Vector3D left, Vector3D right) => left.X * right.X + left.Y * right.Y + left.Z * right.Z;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Transforms the <see cref="Vector3D"/> using the specified <see cref="ITransform3D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector3D"/> to transform.</param>
 | 
				
			||||||
 | 
					    /// <param name="transform">The <see cref="ITransform3D"/> to apply.</param>
 | 
				
			||||||
 | 
					    /// <returns>The transformed <see cref="Vector3D"/>.</returns>
 | 
				
			||||||
 | 
					    public static Vector3D Transform(Vector3D vector, ITransform3D transform)
 | 
				
			||||||
 | 
					        => Quaternion.RotateVector(vector, transform.Rotation).Add(transform.Position).Scale(transform.Scale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Checks if two <see cref="Vector3D"/>s are approximately equal within a specified epsilon range.
 | 
					    /// Checks if two <see cref="Vector3D"/>s are approximately equal within a specified epsilon range.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
@@ -363,6 +372,12 @@ public static class Vector3DExtensions
 | 
				
			|||||||
    /// <inheritdoc cref="Vector3D.Dot(Vector3D, Vector3D)" />
 | 
					    /// <inheritdoc cref="Vector3D.Dot(Vector3D, Vector3D)" />
 | 
				
			||||||
    public static float Dot(this Vector3D left, Vector3D right) => Vector3D.Dot(left, right);
 | 
					    public static float Dot(this Vector3D left, Vector3D right) => Vector3D.Dot(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3D.Transform(Vector3D, ITransform3D)" />
 | 
				
			||||||
 | 
					    public static Vector3D Transform(this Vector3D vector, ITransform3D transform) => Vector3D.Transform(vector, transform);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3D.Transform(Vector3D, ITransform3D)" />
 | 
				
			||||||
 | 
					    public static Vector3D Transform(this ITransform3D transform, Vector3D vector) => Vector3D.Transform(vector, transform);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc cref="Vector3D.ApproximatelyEquals(Vector3D, Vector3D, float)" />
 | 
					    /// <inheritdoc cref="Vector3D.ApproximatelyEquals(Vector3D, Vector3D, float)" />
 | 
				
			||||||
    public static bool ApproximatelyEquals(this Vector3D left, Vector3D right, float epsilon = float.Epsilon) => Vector3D.ApproximatelyEquals(left, right, epsilon);
 | 
					    public static bool ApproximatelyEquals(this Vector3D left, Vector3D right, float epsilon = float.Epsilon) => Vector3D.ApproximatelyEquals(left, right, epsilon);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,9 +81,6 @@ public readonly struct Vector3DInt(int x, int y, int z) : IEquatable<Vector3DInt
 | 
				
			|||||||
    public static Vector3DInt operator -(Vector3DInt vector) => new(0 - vector.X, 0 - vector.Y, 0 - vector.Z);
 | 
					    public static Vector3DInt operator -(Vector3DInt vector) => new(0 - vector.X, 0 - vector.Y, 0 - vector.Z);
 | 
				
			||||||
    public static Vector3DInt operator +(Vector3DInt left, Vector3DInt right) => new(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
 | 
					    public static Vector3DInt operator +(Vector3DInt left, Vector3DInt right) => new(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
 | 
				
			||||||
    public static Vector3DInt operator -(Vector3DInt left, Vector3DInt right) => new(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
 | 
					    public static Vector3DInt operator -(Vector3DInt left, Vector3DInt right) => new(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
 | 
				
			||||||
    public static Vector3DInt operator *(Vector3DInt vector, int value) => new(vector.X * value, vector.Y * value, vector.Z * value);
 | 
					 | 
				
			||||||
    public static Vector3DInt operator *(int value, Vector3DInt vector) => new(vector.X * value, vector.Y * value, vector.Z * value);
 | 
					 | 
				
			||||||
    public static Vector3DInt operator /(Vector3DInt vector, int value) => new(vector.X / value, vector.Y / value, vector.Z / value);
 | 
					 | 
				
			||||||
    public static bool operator ==(Vector3DInt left, Vector3DInt right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z;
 | 
					    public static bool operator ==(Vector3DInt left, Vector3DInt right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z;
 | 
				
			||||||
    public static bool operator !=(Vector3DInt left, Vector3DInt right) => left.X != right.X || left.Y != right.Y || left.Z != right.Z;
 | 
					    public static bool operator !=(Vector3DInt left, Vector3DInt right) => left.X != right.X || left.Y != right.Y || left.Z != right.Z;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -135,22 +132,6 @@ public readonly struct Vector3DInt(int x, int y, int z) : IEquatable<Vector3DInt
 | 
				
			|||||||
    /// <returns>The result of subtracting the second <see cref="Vector3DInt"/> from the first.</returns>
 | 
					    /// <returns>The result of subtracting the second <see cref="Vector3DInt"/> from the first.</returns>
 | 
				
			||||||
    public static Vector3DInt Subtract(Vector3DInt left, Vector3DInt right) => left - right;
 | 
					    public static Vector3DInt Subtract(Vector3DInt left, Vector3DInt right) => left - right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Multiplies a <see cref="Vector3DInt"/> by a scalar value.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    /// <param name="vector">The <see cref="Vector3DInt"/>.</param>
 | 
					 | 
				
			||||||
    /// <param name="value">The scalar value.</param>
 | 
					 | 
				
			||||||
    /// <returns>The result of multiplying the <see cref="Vector3DInt"/> by the scalar value.</returns>
 | 
					 | 
				
			||||||
    public static Vector3DInt Multiply(Vector3DInt vector, int value) => vector * value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Divides a <see cref="Vector3DInt"/> by a scalar value.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    /// <param name="vector">The <see cref="Vector3DInt"/>.</param>
 | 
					 | 
				
			||||||
    /// <param name="value">The scalar value.</param>
 | 
					 | 
				
			||||||
    /// <returns>The result of dividing the <see cref="Vector3DInt"/> by the scalar value.</returns>
 | 
					 | 
				
			||||||
    public static Vector3DInt Divide(Vector3DInt vector, int value) => vector / value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Calculates the absolute value of each component of the vector.
 | 
					    /// Calculates the absolute value of each component of the vector.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
@@ -199,15 +180,6 @@ public readonly struct Vector3DInt(int x, int y, int z) : IEquatable<Vector3DInt
 | 
				
			|||||||
    /// <returns>A <see cref="Vector3DInt"/> with each component clamped between the corresponding components of the min and max <see cref="Vector3DInt"/>s.</returns>
 | 
					    /// <returns>A <see cref="Vector3DInt"/> with each component clamped between the corresponding components of the min and max <see cref="Vector3DInt"/>s.</returns>
 | 
				
			||||||
    public static Vector3DInt Clamp(Vector3DInt vector, Vector3DInt min, Vector3DInt max) => new(Math.Clamp(vector.X, min.X, max.X), Math.Clamp(vector.Y, min.Y, max.Y), Math.Clamp(vector.Z, min.Z, max.Z));
 | 
					    public static Vector3DInt Clamp(Vector3DInt vector, Vector3DInt min, Vector3DInt max) => new(Math.Clamp(vector.X, min.X, max.X), Math.Clamp(vector.Y, min.Y, max.Y), Math.Clamp(vector.Z, min.Z, max.Z));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					 | 
				
			||||||
    /// Performs linear interpolation between two <see cref="Vector3DInt"/>s.
 | 
					 | 
				
			||||||
    /// </summary>
 | 
					 | 
				
			||||||
    /// <param name="from">The starting <see cref="Vector3DInt"/> (t = 0).</param>
 | 
					 | 
				
			||||||
    /// <param name="to">The ending <see cref="Vector3DInt"/> (t = 1).</param>
 | 
					 | 
				
			||||||
    /// <param name="t">The interpolation parameter.</param>
 | 
					 | 
				
			||||||
    /// <returns>The interpolated <see cref="Vector3DInt"/>.</returns>
 | 
					 | 
				
			||||||
    public static Vector3DInt Lerp(Vector3DInt from, Vector3DInt to, int t) => from + FromTo(from, to) * t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Calculates the cross product of two <see cref="Vector3DInt"/>s.
 | 
					    /// Calculates the cross product of two <see cref="Vector3DInt"/>s.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
@@ -276,12 +248,6 @@ public static class Vector3DIntExtensions
 | 
				
			|||||||
    /// <inheritdoc cref="Vector3DInt.Subtract(Vector3DInt, Vector3DInt)" />
 | 
					    /// <inheritdoc cref="Vector3DInt.Subtract(Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
    public static Vector3DInt Subtract(this Vector3DInt vector, Vector3DInt vectorToSubtract) => Vector3DInt.Subtract(vector, vectorToSubtract);
 | 
					    public static Vector3DInt Subtract(this Vector3DInt vector, Vector3DInt vectorToSubtract) => Vector3DInt.Subtract(vector, vectorToSubtract);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc cref="Vector3DInt.Multiply(Vector3DInt, int)" />
 | 
					 | 
				
			||||||
    public static Vector3DInt Multiply(this Vector3DInt vector, int value) => Vector3DInt.Multiply(vector, value);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <inheritdoc cref="Vector3DInt.Divide(Vector3DInt, int)" />
 | 
					 | 
				
			||||||
    public static Vector3DInt Divide(this Vector3DInt vector, int value) => Vector3DInt.Divide(vector, value);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <inheritdoc cref="Vector3DInt.Abs(Vector3DInt)" />
 | 
					    /// <inheritdoc cref="Vector3DInt.Abs(Vector3DInt)" />
 | 
				
			||||||
    public static Vector3DInt Abs(this Vector3DInt vector) => Vector3DInt.Abs(vector);
 | 
					    public static Vector3DInt Abs(this Vector3DInt vector) => Vector3DInt.Abs(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -300,9 +266,6 @@ public static class Vector3DIntExtensions
 | 
				
			|||||||
    /// <inheritdoc cref="Vector3DInt.Clamp(Vector3DInt, Vector3DInt, Vector3DInt)" />
 | 
					    /// <inheritdoc cref="Vector3DInt.Clamp(Vector3DInt, Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
    public static Vector3DInt Clamp(this Vector3DInt vector, Vector3DInt min, Vector3DInt max) => Vector3DInt.Clamp(vector, min, max);
 | 
					    public static Vector3DInt Clamp(this Vector3DInt vector, Vector3DInt min, Vector3DInt max) => Vector3DInt.Clamp(vector, min, max);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc cref="Vector3DInt.Lerp(Vector3DInt, Vector3DInt, int)" />
 | 
					 | 
				
			||||||
    public static Vector3DInt Lerp(this Vector3DInt from, Vector3DInt to, int t) => Vector3DInt.Lerp(from, to, t);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// <inheritdoc cref="Vector3DInt.Cross(Vector3DInt, Vector3DInt)" />
 | 
					    /// <inheritdoc cref="Vector3DInt.Cross(Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
    public static Vector3DInt Cross(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Cross(left, right);
 | 
					    public static Vector3DInt Cross(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Cross(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										318
									
								
								Engine.Core/Primitives/Vector4D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										318
									
								
								Engine.Core/Primitives/Vector4D.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,318 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Represents a four-dimensional vector.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					/// <param name="x">X position of the <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					/// <param name="y">Y position of the <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					/// <param name="z">Z position of the <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					/// <param name="w">W position of the <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					/// <remarks>
 | 
				
			||||||
 | 
					/// Initializes a new instance of the <see cref="Vector4D"/> struct with the specified positions.
 | 
				
			||||||
 | 
					/// </remarks>
 | 
				
			||||||
 | 
					[System.Diagnostics.DebuggerDisplay("{ToString(),nq}, Length: {Magnitude}, LengthSquared: {MagnitudeSquared}, Normalized: {Normalized.ToString(),nq}")]
 | 
				
			||||||
 | 
					public readonly struct Vector4D(float x, float y, float z, float w) : IEquatable<Vector4D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The X coordinate of the <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly float X = x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The Y coordinate of the <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly float Y = y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The Z coordinate of the <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly float Z = z;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The W coordinate of the <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly float W = w;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The magnitude (length) of the <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public float Magnitude => Length(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The squared magnitude (length) of the <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public float MagnitudeSquared => LengthSquared(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The normalized form of the <see cref="Vector4D"/> (a <see cref="Vector4D"/> with the same direction and a magnitude of 1).
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public Vector4D Normalized => Normalize(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the zero <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector4D Zero = new(0f, 0f, 0f, 0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the one <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector4D One = new(1f, 1f, 1f, 1f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit X <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector4D UnitX = new(1f, 0f, 0f, 0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit Y <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector4D UnitY = new(0f, 1f, 0f, 0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit Z <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector4D UnitZ = new(0f, 0f, 1f, 0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit W <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector4D UnitW = new(0f, 0f, 0f, 1f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Vector4D operator -(Vector4D vector) => new(0f - vector.X, 0f - vector.Y, 0f - vector.Z, 0f - vector.W);
 | 
				
			||||||
 | 
					    public static Vector4D operator +(Vector4D left, Vector4D right) => new(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
 | 
				
			||||||
 | 
					    public static Vector4D operator -(Vector4D left, Vector4D right) => new(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
 | 
				
			||||||
 | 
					    public static Vector4D operator *(Vector4D vector, float value) => new(vector.X * value, vector.Y * value, vector.Z * value, vector.W * value);
 | 
				
			||||||
 | 
					    public static Vector4D operator *(float value, Vector4D vector) => new(vector.X * value, vector.Y * value, vector.Z * value, vector.W * value);
 | 
				
			||||||
 | 
					    public static Vector4D operator /(Vector4D vector, float value) => new(vector.X / value, vector.Y / value, vector.Z / value, vector.W / value);
 | 
				
			||||||
 | 
					    public static bool operator ==(Vector4D left, Vector4D right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z && left.W == right.W;
 | 
				
			||||||
 | 
					    public static bool operator !=(Vector4D left, Vector4D right) => left.X != right.X || left.Y != right.Y || left.Z != right.Z || left.W != right.W;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static implicit operator System.Numerics.Vector4(Vector4D vector) => new(vector.X, vector.Y, vector.Z, vector.W);
 | 
				
			||||||
 | 
					    public static implicit operator Vector4D(System.Numerics.Vector4 vector) => new(vector.X, vector.Y, vector.Z, vector.W);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the length of the <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The length of the <see cref="Vector4D"/>.</returns>
 | 
				
			||||||
 | 
					    public static float Length(Vector4D vector) => Math.Sqrt(LengthSquared(vector));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the squared length of the <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The squared length of the <see cref="Vector4D"/>.</returns>
 | 
				
			||||||
 | 
					    public static float LengthSquared(Vector4D vector) => vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z + vector.W * vector.W;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the distance between two <see cref="Vector4D"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="from">The start <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="to">The end <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The distance between the two <see cref="Vector4D"/>s.</returns>
 | 
				
			||||||
 | 
					    public static float Distance(Vector4D from, Vector4D to) => Length(FromTo(from, to));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Inverts the direction of the <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The inverted <see cref="Vector4D"/>.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Invert(Vector4D vector) => -vector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Adds two <see cref="Vector4D"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The sum of the two <see cref="Vector4D"/>s.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Add(Vector4D left, Vector4D right) => left + right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Subtracts one <see cref="Vector4D"/> from another.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The <see cref="Vector4D"/> to subtract from.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The <see cref="Vector4D"/> to subtract.</param>
 | 
				
			||||||
 | 
					    /// <returns>The result of subtracting the second <see cref="Vector4D"/> from the first.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Subtract(Vector4D left, Vector4D right) => left - right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Multiplies a <see cref="Vector4D"/> by a scalar value.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="value">The scalar value.</param>
 | 
				
			||||||
 | 
					    /// <returns>The result of multiplying the <see cref="Vector4D"/> by the scalar value.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Multiply(Vector4D vector, float value) => vector * value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Divides a <see cref="Vector4D"/> by a scalar value.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="value">The scalar value.</param>
 | 
				
			||||||
 | 
					    /// <returns>The result of dividing the <see cref="Vector4D"/> by the scalar value.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Divide(Vector4D vector, float value) => vector / value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the absolute value of each component of the vector.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector4D"/> with each component's absolute value.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Abs(Vector4D vector) => new(Math.Abs(vector.X), Math.Abs(vector.Y), Math.Abs(vector.Z), Math.Abs(vector.W));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Normalizes the <see cref="Vector4D"/> (creates a unit <see cref="Vector4D"/> with the same direction).
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector4D"/> to normalize.</param>
 | 
				
			||||||
 | 
					    /// <returns>The normalized <see cref="Vector4D"/>.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Normalize(Vector4D vector) => vector / Length(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the <see cref="Vector4D"/> from one point to another.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="from">The starting point.</param>
 | 
				
			||||||
 | 
					    /// <param name="to">The ending point.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector4D"/> from the starting point to the ending point.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D FromTo(Vector4D from, Vector4D to) => to - from;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Scales a <see cref="Vector4D"/> by another <see cref="Vector4D"/> component-wise.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector4D"/> to scale.</param>
 | 
				
			||||||
 | 
					    /// <param name="scale">The <see cref="Vector4D"/> containing the scaling factors for each component.</param>
 | 
				
			||||||
 | 
					    /// <returns>The scaled <see cref="Vector4D"/>.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Scale(Vector4D vector, Vector4D scale) => new(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z, vector.W * scale.W);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Returns the component-wise minimum of two <see cref="Vector4D"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector4D"/> containing the minimum components from both input <see cref="Vector4D"/>s.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Min(Vector4D left, Vector4D right) => new((left.X < right.X) ? left.X : right.X, (left.Y < right.Y) ? left.Y : right.Y, (left.Z < right.Z) ? left.Z : right.Z, (left.W < right.W) ? left.W : right.W);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Returns the component-wise maximum of two <see cref="Vector4D"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector4D"/> containing the maximum components from both input <see cref="Vector4D"/>s.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Max(Vector4D left, Vector4D right) => new((left.X > right.X) ? left.X : right.X, (left.Y > right.Y) ? left.Y : right.Y, (left.Z > right.Z) ? left.Z : right.Z, (left.W > right.W) ? left.W : right.W);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Clamps each component of a <see cref="Vector4D"/> between the corresponding component of two other <see cref="Vector4D"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector4D"/> to clamp.</param>
 | 
				
			||||||
 | 
					    /// <param name="min">The <see cref="Vector4D"/> representing the minimum values for each component.</param>
 | 
				
			||||||
 | 
					    /// <param name="max">The <see cref="Vector4D"/> representing the maximum values for each component.</param>
 | 
				
			||||||
 | 
					    /// <returns>A <see cref="Vector4D"/> with each component clamped between the corresponding components of the min and max <see cref="Vector4D"/>s.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Clamp(Vector4D vector, Vector4D min, Vector4D max) => new(Math.Clamp(vector.X, min.X, max.X), Math.Clamp(vector.Y, min.Y, max.Y), Math.Clamp(vector.Z, min.Z, max.Z), Math.Clamp(vector.W, min.W, max.W));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Performs linear interpolation between two <see cref="Vector4D"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="from">The starting <see cref="Vector4D"/> (t = 0).</param>
 | 
				
			||||||
 | 
					    /// <param name="to">The ending <see cref="Vector4D"/> (t = 1).</param>
 | 
				
			||||||
 | 
					    /// <param name="t">The interpolation parameter.</param>
 | 
				
			||||||
 | 
					    /// <returns>The interpolated <see cref="Vector4D"/>.</returns>
 | 
				
			||||||
 | 
					    public static Vector4D Lerp(Vector4D from, Vector4D to, float t) => from + FromTo(from, to) * t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the dot product of two <see cref="Vector4D"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The dot product of the two <see cref="Vector4D"/>s.</returns>
 | 
				
			||||||
 | 
					    public static float Dot(Vector4D left, Vector4D right) => left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Checks if two <see cref="Vector4D"/>s are approximately equal within a specified epsilon range.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="epsilon">The epsilon range.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the <see cref="Vector4D"/>s are approximately equal; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(Vector4D left, Vector4D right, float epsilon = float.Epsilon)
 | 
				
			||||||
 | 
					        => left.X.ApproximatelyEquals(right.X, epsilon) && left.Y.ApproximatelyEquals(right.Y, epsilon) && left.Z.ApproximatelyEquals(right.Z, epsilon) && left.Z.ApproximatelyEquals(right.W, epsilon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Determines whether the specified object is equal to the current <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Vector4D"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Vector4D"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public override bool Equals(object? obj) => obj is Vector4D vector4D && this == vector4D;
 | 
				
			||||||
 | 
					    public bool Equals(Vector4D other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Generates a hash code for the <see cref="Vector4D"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A hash code for the <see cref="Vector4D"/>.</returns>
 | 
				
			||||||
 | 
					    public override int GetHashCode() => System.HashCode.Combine(X, Y, Z, W);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Converts the <see cref="Vector4D"/> to its string representation.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A string representation of the <see cref="Vector4D"/>.</returns>
 | 
				
			||||||
 | 
					    public override string ToString() => $"{nameof(Vector4D)}({X}, {Y}, {Z}, {W})";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Provides extension methods for <see cref="Vector4D"/> type.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public static class Vector4DExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Length(Vector4D)" />
 | 
				
			||||||
 | 
					    public static float Length(this Vector4D vector) => Vector4D.Length(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.LengthSquared(Vector4D)" />
 | 
				
			||||||
 | 
					    public static float LengthSquared(this Vector4D vector) => Vector4D.LengthSquared(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Distance(Vector4D, Vector4D)" />
 | 
				
			||||||
 | 
					    public static float Distance(this Vector4D from, Vector4D to) => Vector4D.Distance(from, to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Invert(Vector4D)" />
 | 
				
			||||||
 | 
					    public static Vector4D Invert(this Vector4D vector) => Vector4D.Invert(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Add(Vector4D, Vector4D)" />
 | 
				
			||||||
 | 
					    public static Vector4D Add(this Vector4D vector, Vector4D vectorToAdd) => Vector4D.Add(vector, vectorToAdd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Subtract(Vector4D, Vector4D)" />
 | 
				
			||||||
 | 
					    public static Vector4D Subtract(this Vector4D vector, Vector4D vectorToSubtract) => Vector4D.Subtract(vector, vectorToSubtract);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Multiply(Vector4D, float)" />
 | 
				
			||||||
 | 
					    public static Vector4D Multiply(this Vector4D vector, float value) => Vector4D.Multiply(vector, value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Divide(Vector4D, float)" />
 | 
				
			||||||
 | 
					    public static Vector4D Divide(this Vector4D vector, float value) => Vector4D.Divide(vector, value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Abs(Vector4D)" />
 | 
				
			||||||
 | 
					    public static Vector4D Abs(this Vector4D vector) => Vector4D.Abs(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Normalize(Vector4D)" />
 | 
				
			||||||
 | 
					    public static Vector4D Normalize(this Vector4D vector) => Vector4D.Normalize(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.FromTo(Vector4D, Vector4D)" />
 | 
				
			||||||
 | 
					    public static Vector4D FromTo(this Vector4D from, Vector4D to) => Vector4D.FromTo(from, to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Scale(Vector4D, Vector4D)" />
 | 
				
			||||||
 | 
					    public static Vector4D Scale(this Vector4D vector, Vector4D scale) => Vector4D.Scale(vector, scale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Min(Vector4D, Vector4D)" />
 | 
				
			||||||
 | 
					    public static Vector4D Min(this Vector4D left, Vector4D right) => Vector4D.Min(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Max(Vector4D, Vector4D)" />
 | 
				
			||||||
 | 
					    public static Vector4D Max(this Vector4D left, Vector4D right) => Vector4D.Max(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Clamp(Vector4D, Vector4D, Vector4D)" />
 | 
				
			||||||
 | 
					    public static Vector4D Clamp(this Vector4D vector, Vector4D min, Vector4D max) => Vector4D.Clamp(vector, min, max);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Lerp(Vector4D, Vector4D, float)" />
 | 
				
			||||||
 | 
					    public static Vector4D Lerp(this Vector4D from, Vector4D to, float t) => Vector4D.Lerp(from, to, t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.Dot(Vector4D, Vector4D)" />
 | 
				
			||||||
 | 
					    public static float Dot(this Vector4D left, Vector4D right) => Vector4D.Dot(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector4D.ApproximatelyEquals(Vector4D, Vector4D, float)" />
 | 
				
			||||||
 | 
					    public static bool ApproximatelyEquals(this Vector4D left, Vector4D right, float epsilon = float.Epsilon) => Vector4D.ApproximatelyEquals(left, right, epsilon);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,7 +2,7 @@ using System.Collections.Generic;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class DrawManager : Behaviour
 | 
					public class DrawManager : Behaviour, IEnterUniverse, IExitUniverse
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // We use Descending order because draw calls are running from last to first
 | 
					    // We use Descending order because draw calls are running from last to first
 | 
				
			||||||
    private static Comparer<int> SortByDescendingPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
 | 
					    private static Comparer<int> SortByDescendingPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
 | 
				
			||||||
@@ -30,7 +30,7 @@ public class DrawManager : Behaviour
 | 
				
			|||||||
            postDrawEntities[i].PostDraw();
 | 
					            postDrawEntities[i].PostDraw();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnEnteredUniverse(IUniverse universe)
 | 
					    public void EnterUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        preDrawEntities.Assign(universe);
 | 
					        preDrawEntities.Assign(universe);
 | 
				
			||||||
        drawEntities.Assign(universe);
 | 
					        drawEntities.Assign(universe);
 | 
				
			||||||
@@ -41,7 +41,7 @@ public class DrawManager : Behaviour
 | 
				
			|||||||
        universe.OnPostDraw.AddListener(OnPostDraw);
 | 
					        universe.OnPostDraw.AddListener(OnPostDraw);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe)
 | 
					    public void ExitUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        preDrawEntities.Unassign();
 | 
					        preDrawEntities.Unassign();
 | 
				
			||||||
        drawEntities.Unassign();
 | 
					        drawEntities.Unassign();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ using System.Collections.Generic;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class UniverseEntranceManager : Behaviour
 | 
					public class UniverseEntranceManager : Internal.BehaviourIndependent
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // We use Ascending order because we are using reverse for loop to call them
 | 
					    // We use Ascending order because we are using reverse for loop to call them
 | 
				
			||||||
    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
					    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ using System.Collections.Generic;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class UpdateManager : Behaviour
 | 
					public class UpdateManager : Behaviour, IEnterUniverse, IExitUniverse
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // We use Ascending order because we are using reverse for loop to call them
 | 
					    // We use Ascending order because we are using reverse for loop to call them
 | 
				
			||||||
    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
					    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
				
			||||||
@@ -16,7 +16,7 @@ public class UpdateManager : Behaviour
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private readonly List<IFirstFrameUpdate> toCallFirstFrameUpdates = new(32);
 | 
					    private readonly List<IFirstFrameUpdate> toCallFirstFrameUpdates = new(32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnEnteredUniverse(IUniverse universe)
 | 
					    public void EnterUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        firstFrameUpdates.Assign(universe);
 | 
					        firstFrameUpdates.Assign(universe);
 | 
				
			||||||
        lastFrameUpdates.Assign(universe);
 | 
					        lastFrameUpdates.Assign(universe);
 | 
				
			||||||
@@ -30,7 +30,7 @@ public class UpdateManager : Behaviour
 | 
				
			|||||||
        universe.OnPostUpdate.AddListener(OnPostUpdate);
 | 
					        universe.OnPostUpdate.AddListener(OnPostUpdate);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe)
 | 
					    public void ExitUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        firstFrameUpdates.Unassign();
 | 
					        firstFrameUpdates.Unassign();
 | 
				
			||||||
        lastFrameUpdates.Unassign();
 | 
					        lastFrameUpdates.Unassign();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ public class Transform2D : Behaviour, ITransform2D
 | 
				
			|||||||
    public Event<ITransform2D, ITransform2D.PositionChangedArguments> OnPositionChanged { get; } = new();
 | 
					    public Event<ITransform2D, ITransform2D.PositionChangedArguments> OnPositionChanged { get; } = new();
 | 
				
			||||||
    public Event<ITransform2D, ITransform2D.ScaleChangedArguments> OnScaleChanged { get; } = new();
 | 
					    public Event<ITransform2D, ITransform2D.ScaleChangedArguments> OnScaleChanged { get; } = new();
 | 
				
			||||||
    public Event<ITransform2D, ITransform2D.RotationChangedArguments> OnRotationChanged { get; } = new();
 | 
					    public Event<ITransform2D, ITransform2D.RotationChangedArguments> OnRotationChanged { get; } = new();
 | 
				
			||||||
 | 
					    public Event<ITransform2D> OnTransformUpdated { get; } = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Vector2D _position = Vector2D.Zero;
 | 
					    private Vector2D _position = Vector2D.Zero;
 | 
				
			||||||
    private Vector2D _scale = Vector2D.One;
 | 
					    private Vector2D _scale = Vector2D.One;
 | 
				
			||||||
@@ -36,7 +37,8 @@ public class Transform2D : Behaviour, ITransform2D
 | 
				
			|||||||
            _position = value;
 | 
					            _position = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            UpdateLocalPosition();
 | 
					            UpdateLocalPosition();
 | 
				
			||||||
            OnPositionChanged?.Invoke(this, new(previousPosition));
 | 
					            OnPositionChanged.Invoke(this, new(previousPosition));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -52,7 +54,8 @@ public class Transform2D : Behaviour, ITransform2D
 | 
				
			|||||||
            _scale = value;
 | 
					            _scale = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            UpdateLocalScale();
 | 
					            UpdateLocalScale();
 | 
				
			||||||
            OnScaleChanged?.Invoke(this, new(previousScale));
 | 
					            OnScaleChanged.Invoke(this, new(previousScale));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -68,7 +71,8 @@ public class Transform2D : Behaviour, ITransform2D
 | 
				
			|||||||
            _rotation = value;
 | 
					            _rotation = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            UpdateLocalRotation();
 | 
					            UpdateLocalRotation();
 | 
				
			||||||
            OnRotationChanged?.Invoke(this, new(previousRotation));
 | 
					            OnRotationChanged.Invoke(this, new(previousRotation));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,7 +88,8 @@ public class Transform2D : Behaviour, ITransform2D
 | 
				
			|||||||
            _localPosition = value;
 | 
					            _localPosition = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            UpdatePosition();
 | 
					            UpdatePosition();
 | 
				
			||||||
            OnPositionChanged?.Invoke(this, new(previousPosition));
 | 
					            OnPositionChanged.Invoke(this, new(previousPosition));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -102,8 +107,9 @@ public class Transform2D : Behaviour, ITransform2D
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            UpdateScale();
 | 
					            UpdateScale();
 | 
				
			||||||
            UpdatePosition();
 | 
					            UpdatePosition();
 | 
				
			||||||
            OnScaleChanged?.Invoke(this, new(previousScale));
 | 
					            OnScaleChanged.Invoke(this, new(previousScale));
 | 
				
			||||||
            OnPositionChanged?.Invoke(this, new(previousPosition));
 | 
					            OnPositionChanged.Invoke(this, new(previousPosition));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -119,7 +125,8 @@ public class Transform2D : Behaviour, ITransform2D
 | 
				
			|||||||
            _localRotation = value;
 | 
					            _localRotation = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            UpdateRotation();
 | 
					            UpdateRotation();
 | 
				
			||||||
            OnRotationChanged?.Invoke(this, new(previousRotation));
 | 
					            OnRotationChanged.Invoke(this, new(previousRotation));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -130,7 +137,8 @@ public class Transform2D : Behaviour, ITransform2D
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        UpdatePosition();
 | 
					        UpdatePosition();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        OnPositionChanged?.Invoke(this, args);
 | 
					        OnPositionChanged.Invoke(this, args);
 | 
				
			||||||
 | 
					        OnTransformUpdated.Invoke(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void RecalculateScale(ITransform2D _, ITransform2D.ScaleChangedArguments args)
 | 
					    private void RecalculateScale(ITransform2D _, ITransform2D.ScaleChangedArguments args)
 | 
				
			||||||
@@ -143,8 +151,9 @@ public class Transform2D : Behaviour, ITransform2D
 | 
				
			|||||||
        UpdateScale();
 | 
					        UpdateScale();
 | 
				
			||||||
        UpdatePosition();
 | 
					        UpdatePosition();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        OnScaleChanged?.Invoke(this, args);
 | 
					        OnScaleChanged.Invoke(this, args);
 | 
				
			||||||
        OnPositionChanged?.Invoke(this, new(previousPosition));
 | 
					        OnPositionChanged.Invoke(this, new(previousPosition));
 | 
				
			||||||
 | 
					        OnTransformUpdated.Invoke(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void RecalculateRotation(ITransform2D _, ITransform2D.RotationChangedArguments args)
 | 
					    private void RecalculateRotation(ITransform2D _, ITransform2D.RotationChangedArguments args)
 | 
				
			||||||
@@ -157,8 +166,9 @@ public class Transform2D : Behaviour, ITransform2D
 | 
				
			|||||||
        UpdateRotation();
 | 
					        UpdateRotation();
 | 
				
			||||||
        UpdatePosition();
 | 
					        UpdatePosition();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        OnRotationChanged?.Invoke(this, args);
 | 
					        OnRotationChanged.Invoke(this, args);
 | 
				
			||||||
        OnPositionChanged?.Invoke(this, new(previousPosition));
 | 
					        OnPositionChanged.Invoke(this, new(previousPosition));
 | 
				
			||||||
 | 
					        OnTransformUpdated.Invoke(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void UpdateLocalPosition()
 | 
					    private void UpdateLocalPosition()
 | 
				
			||||||
@@ -252,9 +262,10 @@ public class Transform2D : Behaviour, ITransform2D
 | 
				
			|||||||
        UpdateLocalScale();
 | 
					        UpdateLocalScale();
 | 
				
			||||||
        UpdateLocalRotation();
 | 
					        UpdateLocalRotation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        OnPositionChanged?.Invoke(this, new(Position));
 | 
					        OnPositionChanged.Invoke(this, new(Position));
 | 
				
			||||||
        OnScaleChanged?.Invoke(this, new(Scale));
 | 
					        OnScaleChanged.Invoke(this, new(Scale));
 | 
				
			||||||
        OnRotationChanged?.Invoke(this, new(Rotation));
 | 
					        OnRotationChanged.Invoke(this, new(Rotation));
 | 
				
			||||||
 | 
					        OnTransformUpdated.Invoke(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void LookForTransform2D(IBehaviourController sender, IBehaviourController.BehaviourAddedArguments args)
 | 
					    private void LookForTransform2D(IBehaviourController sender, IBehaviourController.BehaviourAddedArguments args)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										285
									
								
								Engine.Core/Transform3D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								Engine.Core/Transform3D.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,285 @@
 | 
				
			|||||||
 | 
					using Engine.Core.Serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[System.Diagnostics.DebuggerDisplay("Name: {UniverseObject.Name, nq} Position: {Position.ToString(), nq}, Scale: {Scale.ToString(), nq}, Rotation: {Rotation}")]
 | 
				
			||||||
 | 
					public class Transform3D : Behaviour, ITransform3D
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public Event<ITransform3D, ITransform3D.PositionChangedArguments> OnPositionChanged { get; } = new();
 | 
				
			||||||
 | 
					    public Event<ITransform3D, ITransform3D.ScaleChangedArguments> OnScaleChanged { get; } = new();
 | 
				
			||||||
 | 
					    public Event<ITransform3D, ITransform3D.RotationChangedArguments> OnRotationChanged { get; } = new();
 | 
				
			||||||
 | 
					    public Event<ITransform3D> OnTransformUpdated { get; } = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Vector3D _position = Vector3D.Zero;
 | 
				
			||||||
 | 
					    private Vector3D _scale = Vector3D.One;
 | 
				
			||||||
 | 
					    private Quaternion _rotation = Quaternion.Identity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [Serialize] private Vector3D _localPosition = Vector3D.Zero;
 | 
				
			||||||
 | 
					    [Serialize] private Vector3D _localScale = Vector3D.One;
 | 
				
			||||||
 | 
					    [Serialize] private Quaternion _localRotation = Quaternion.Identity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private ITransform3D? parentTransform = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Vector3D Up => Quaternion.RotateVector(Vector3D.Up, Rotation);
 | 
				
			||||||
 | 
					    public Vector3D Down => Quaternion.RotateVector(Vector3D.Down, Rotation);
 | 
				
			||||||
 | 
					    public Vector3D Left => Quaternion.RotateVector(Vector3D.Left, Rotation);
 | 
				
			||||||
 | 
					    public Vector3D Right => Quaternion.RotateVector(Vector3D.Right, Rotation);
 | 
				
			||||||
 | 
					    public Vector3D Forward => Quaternion.RotateVector(Vector3D.Forward, Rotation);
 | 
				
			||||||
 | 
					    public Vector3D Backward => Quaternion.RotateVector(Vector3D.Backward, Rotation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Vector3D Position
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _position;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (value == _position)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Vector3D previousPosition = _position;
 | 
				
			||||||
 | 
					            _position = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            UpdateLocalPosition();
 | 
				
			||||||
 | 
					            OnPositionChanged.Invoke(this, new(previousPosition));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Vector3D Scale
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _scale;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (value == _scale)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Vector3D previousScale = _scale;
 | 
				
			||||||
 | 
					            _scale = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            UpdateLocalScale();
 | 
				
			||||||
 | 
					            OnScaleChanged.Invoke(this, new(previousScale));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Quaternion Rotation
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _rotation;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (value == _rotation)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Quaternion previousRotation = _rotation;
 | 
				
			||||||
 | 
					            _rotation = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            UpdateLocalRotation();
 | 
				
			||||||
 | 
					            OnRotationChanged.Invoke(this, new(previousRotation));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Vector3D LocalPosition
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _localPosition;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (value == _localPosition)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Vector3D previousPosition = _position;
 | 
				
			||||||
 | 
					            _localPosition = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            UpdatePosition();
 | 
				
			||||||
 | 
					            OnPositionChanged.Invoke(this, new(previousPosition));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Vector3D LocalScale
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _localScale;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (value == _localScale)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Vector3D previousScale = _scale;
 | 
				
			||||||
 | 
					            Vector3D previousPosition = _position;
 | 
				
			||||||
 | 
					            _localScale = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            UpdateScale();
 | 
				
			||||||
 | 
					            UpdatePosition();
 | 
				
			||||||
 | 
					            OnScaleChanged.Invoke(this, new(previousScale));
 | 
				
			||||||
 | 
					            OnPositionChanged.Invoke(this, new(previousPosition));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Quaternion LocalRotation
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _localRotation;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (value == _localRotation)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Quaternion previousRotation = _rotation;
 | 
				
			||||||
 | 
					            _localRotation = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            UpdateRotation();
 | 
				
			||||||
 | 
					            OnRotationChanged.Invoke(this, new(previousRotation));
 | 
				
			||||||
 | 
					            OnTransformUpdated.Invoke(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void RecalculatePosition(ITransform3D _, ITransform3D.PositionChangedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (parentTransform is null)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        UpdatePosition();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnPositionChanged.Invoke(this, args);
 | 
				
			||||||
 | 
					        OnTransformUpdated.Invoke(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void RecalculateScale(ITransform3D _, ITransform3D.ScaleChangedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (parentTransform is null)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Vector3D previousPosition = _position;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        UpdateScale();
 | 
				
			||||||
 | 
					        UpdatePosition();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnScaleChanged.Invoke(this, args);
 | 
				
			||||||
 | 
					        OnPositionChanged.Invoke(this, new(previousPosition));
 | 
				
			||||||
 | 
					        OnTransformUpdated.Invoke(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void RecalculateRotation(ITransform3D _, ITransform3D.RotationChangedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (parentTransform is null)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Vector3D previousPosition = Position;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        UpdateRotation();
 | 
				
			||||||
 | 
					        UpdatePosition();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnRotationChanged.Invoke(this, args);
 | 
				
			||||||
 | 
					        OnPositionChanged.Invoke(this, new(previousPosition));
 | 
				
			||||||
 | 
					        OnTransformUpdated.Invoke(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void UpdateLocalPosition()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (parentTransform is null)
 | 
				
			||||||
 | 
					            _localPosition = Position;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            _localPosition = parentTransform.Position.FromTo(Position).Scale(parentTransform.Scale);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void UpdateLocalScale()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (parentTransform is null)
 | 
				
			||||||
 | 
					            _localScale = Scale;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            _localScale = Scale.Scale(new(1f / parentTransform.Scale.X, 1f / parentTransform.Scale.Y, 1f / parentTransform.Scale.Z));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void UpdateLocalRotation()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (parentTransform is null)
 | 
				
			||||||
 | 
					            _localRotation = Rotation;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            _localRotation = Rotation * parentTransform.Rotation.Invert();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void UpdatePosition()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (parentTransform is null)
 | 
				
			||||||
 | 
					            _position = LocalPosition;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            _position = parentTransform.Position + Quaternion.RotateVector(LocalPosition.Scale(new(parentTransform.Scale.X, parentTransform.Scale.Y, parentTransform.Scale.Z)), parentTransform.Rotation);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void UpdateScale()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (parentTransform is null)
 | 
				
			||||||
 | 
					            _scale = LocalScale;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            _scale = (parentTransform?.Scale ?? Vector3D.One).Scale(_localScale);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void UpdateRotation()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (parentTransform is null)
 | 
				
			||||||
 | 
					            _rotation = LocalRotation;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            _rotation = parentTransform.Rotation * LocalRotation;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void InitializeInternal()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        UpdateReferences(UniverseObject.Parent);
 | 
				
			||||||
 | 
					        UniverseObject.OnParentChanged.AddListener(OnParentChanged);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void FinalizeInternal()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        UniverseObject.OnParentChanged.RemoveListener(OnParentChanged);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void UpdateReferences(IUniverseObject? parent)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ITransform3D? previousParent = parentTransform;
 | 
				
			||||||
 | 
					        if (previousParent is not null)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            previousParent.OnPositionChanged.RemoveListener(RecalculatePosition);
 | 
				
			||||||
 | 
					            previousParent.OnScaleChanged.RemoveListener(RecalculateScale);
 | 
				
			||||||
 | 
					            previousParent.OnRotationChanged.RemoveListener(RecalculateRotation);
 | 
				
			||||||
 | 
					            previousParent.BehaviourController.UniverseObject.OnParentChanged.RemoveListener(OnParentChanged);
 | 
				
			||||||
 | 
					            previousParent.BehaviourController.OnBehaviourAdded.RemoveListener(LookForTransform3D);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        parentTransform = parent?.BehaviourController.GetBehaviour<ITransform3D>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (parentTransform is not null)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            parentTransform.OnPositionChanged.AddListener(RecalculatePosition);
 | 
				
			||||||
 | 
					            parentTransform.OnScaleChanged.AddListener(RecalculateScale);
 | 
				
			||||||
 | 
					            parentTransform.OnRotationChanged.AddListener(RecalculateRotation);
 | 
				
			||||||
 | 
					            parentTransform.BehaviourController.UniverseObject.OnParentChanged.AddListener(OnParentChanged);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            UpdatePosition();
 | 
				
			||||||
 | 
					            UpdateScale();
 | 
				
			||||||
 | 
					            UpdateRotation();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            UniverseObject.Parent?.BehaviourController.OnBehaviourAdded.AddListener(LookForTransform3D);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        UpdateLocalPosition();
 | 
				
			||||||
 | 
					        UpdateLocalScale();
 | 
				
			||||||
 | 
					        UpdateLocalRotation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnPositionChanged.Invoke(this, new(Position));
 | 
				
			||||||
 | 
					        OnScaleChanged.Invoke(this, new(Scale));
 | 
				
			||||||
 | 
					        OnRotationChanged.Invoke(this, new(Rotation));
 | 
				
			||||||
 | 
					        OnTransformUpdated.Invoke(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void LookForTransform3D(IBehaviourController sender, IBehaviourController.BehaviourAddedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (args.BehaviourAdded is not ITransform3D)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        UpdateReferences(UniverseObject.Parent);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnParentChanged(IUniverseObject sender, IUniverseObject.ParentChangedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        UpdateReferences(args.CurrentParent);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -56,17 +56,17 @@ public class LiteNetLibClient : LiteNetLibCommunicatorBase, INetworkCommunicator
 | 
				
			|||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnEnteredUniverse(IUniverse universe)
 | 
					    public override void EnterUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        base.OnEnteredUniverse(universe);
 | 
					        base.EnterUniverse(universe);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cancellationTokenSource = new CancellationTokenSource();
 | 
					        cancellationTokenSource = new CancellationTokenSource();
 | 
				
			||||||
        PollEvents(cancellationTokenSource.Token);
 | 
					        PollEvents(cancellationTokenSource.Token);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe)
 | 
					    public override void ExitUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        base.OnExitedUniverse(universe);
 | 
					        base.ExitUniverse(universe);
 | 
				
			||||||
        cancellationTokenSource?.Cancel();
 | 
					        cancellationTokenSource?.Cancel();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +1,15 @@
 | 
				
			|||||||
using System.Reflection;
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					using Engine.Core.Debug;
 | 
				
			||||||
 | 
					using Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using LiteNetLib;
 | 
					using LiteNetLib;
 | 
				
			||||||
using LiteNetLib.Utils;
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					 | 
				
			||||||
using Engine.Core.Debug;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public abstract class LiteNetLibCommunicatorBase : Behaviour, INetworkCommunicator
 | 
					public abstract class LiteNetLibCommunicatorBase : Behaviour, IEnterUniverse, IExitUniverse, INetworkCommunicator
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    protected readonly NetPacketProcessor netPacketProcessor = new();
 | 
					    protected readonly NetPacketProcessor netPacketProcessor = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,15 +33,13 @@ public abstract class LiteNetLibCommunicatorBase : Behaviour, INetworkCommunicat
 | 
				
			|||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnEnteredUniverse(IUniverse universe)
 | 
					    public virtual void EnterUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        base.OnEnteredUniverse(universe);
 | 
					 | 
				
			||||||
        logger = universe.FindBehaviour<ILogger>();
 | 
					        logger = universe.FindBehaviour<ILogger>();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe)
 | 
					    public virtual void ExitUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        base.OnExitedUniverse(universe);
 | 
					 | 
				
			||||||
        logger = null;
 | 
					        logger = null;
 | 
				
			||||||
        Stop();
 | 
					        Stop();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -143,19 +142,28 @@ public abstract class LiteNetLibCommunicatorBase : Behaviour, INetworkCommunicat
 | 
				
			|||||||
    private void SetupEnginePackets()
 | 
					    private void SetupEnginePackets()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // I know, ugly af. I need to find a better way
 | 
					        // I know, ugly af. I need to find a better way
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(AABBNetPacker.Write, AABBNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(AABB2DNetPacker.Write, AABB2DNetPacker.Read);
 | 
				
			||||||
 | 
					        netPacketProcessor.RegisterNestedType(AABB3DNetPacker.Write, AABB3DNetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(CircleNetPacker.Write, CircleNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(CircleNetPacker.Write, CircleNetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(ColorHSVNetPacker.Write, ColorHSVNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(ColorHSVNetPacker.Write, ColorHSVNetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(ColorRGBANetPacker.Write, ColorRGBANetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(ColorHSVANetPacker.Write, ColorHSVANetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(ColorRGBNetPacker.Write, ColorRGBNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(ColorRGBNetPacker.Write, ColorRGBNetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(Line2DEquationNetPacker.Write, Line2DEquationNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(ColorRGBANetPacker.Write, ColorRGBANetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(Line2DNetPacker.Write, Line2DNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(Line2DNetPacker.Write, Line2DNetPacker.Read);
 | 
				
			||||||
 | 
					        netPacketProcessor.RegisterNestedType(Line2DEquationNetPacker.Write, Line2DEquationNetPacker.Read);
 | 
				
			||||||
 | 
					        netPacketProcessor.RegisterNestedType(Line3DNetPacker.Write, Line3DNetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(Projection1DNetPacker.Write, Projection1DNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(Projection1DNetPacker.Write, Projection1DNetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(QuaternionNetPacker.Write, QuaternionNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(QuaternionNetPacker.Write, QuaternionNetPacker.Read);
 | 
				
			||||||
 | 
					        netPacketProcessor.RegisterNestedType(Ray2DNetPacker.Write, Ray2DNetPacker.Read);
 | 
				
			||||||
 | 
					        netPacketProcessor.RegisterNestedType(Ray3DNetPacker.Write, Ray3DNetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(Shape2DNetPacker.Write, Shape2DNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(Shape2DNetPacker.Write, Shape2DNetPacker.Read);
 | 
				
			||||||
 | 
					        netPacketProcessor.RegisterNestedType(Sphere3DNetPacker.Write, Sphere3DNetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(TriangleNetPacker.Write, TriangleNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(TriangleNetPacker.Write, TriangleNetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(Vector2DNetPacker.Write, Vector2DNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(Vector2DNetPacker.Write, Vector2DNetPacker.Read);
 | 
				
			||||||
 | 
					        netPacketProcessor.RegisterNestedType(Vector2DIntNetPacker.Write, Vector2DIntNetPacker.Read);
 | 
				
			||||||
        netPacketProcessor.RegisterNestedType(Vector3DNetPacker.Write, Vector3DNetPacker.Read);
 | 
					        netPacketProcessor.RegisterNestedType(Vector3DNetPacker.Write, Vector3DNetPacker.Read);
 | 
				
			||||||
 | 
					        netPacketProcessor.RegisterNestedType(Vector3DIntNetPacker.Write, Vector3DIntNetPacker.Read);
 | 
				
			||||||
 | 
					        netPacketProcessor.RegisterNestedType(Vector4DNetPacker.Write, Vector4DNetPacker.Read);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public INetworkCommunicator SubscribeToPackets<T>(Event<IConnection, T>.EventHandler callback)
 | 
					    public INetworkCommunicator SubscribeToPackets<T>(Event<IConnection, T>.EventHandler callback)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -88,15 +88,15 @@ public class LiteNetLibServer : LiteNetLibCommunicatorBase, INetworkCommunicator
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private void PollEvents(IUniverse sender, IUniverse.UpdateArguments args) => Manager.PollEvents();
 | 
					    private void PollEvents(IUniverse sender, IUniverse.UpdateArguments args) => Manager.PollEvents();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnEnteredUniverse(IUniverse universe)
 | 
					    public override void EnterUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        base.OnEnteredUniverse(universe);
 | 
					        base.EnterUniverse(universe);
 | 
				
			||||||
        universe.OnPostUpdate.AddListener(PollEvents);
 | 
					        universe.OnPostUpdate.AddListener(PollEvents);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe)
 | 
					    public override void ExitUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        base.OnExitedUniverse(universe);
 | 
					        base.ExitUniverse(universe);
 | 
				
			||||||
        universe.OnPostUpdate.RemoveListener(PollEvents);
 | 
					        universe.OnPostUpdate.RemoveListener(PollEvents);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,21 +2,21 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class AABBNetPacker
 | 
					internal static class AABB2DNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    internal static void Write(NetDataWriter writer, AABB data)
 | 
					    internal static void Write(NetDataWriter writer, AABB2D data)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Vector2DNetPacker.Write(writer, data.LowerBoundary);
 | 
					        Vector2DNetPacker.Write(writer, data.LowerBoundary);
 | 
				
			||||||
        Vector2DNetPacker.Write(writer, data.UpperBoundary);
 | 
					        Vector2DNetPacker.Write(writer, data.UpperBoundary);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    internal static AABB Read(NetDataReader reader)
 | 
					    internal static AABB2D Read(NetDataReader reader)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Vector2D lowerBoundary = Vector2DNetPacker.Read(reader);
 | 
					        Vector2D lowerBoundary = Vector2DNetPacker.Read(reader);
 | 
				
			||||||
        Vector2D upperBoundary = Vector2DNetPacker.Read(reader);
 | 
					        Vector2D upperBoundary = Vector2DNetPacker.Read(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return new AABB(lowerBoundary, upperBoundary);
 | 
					        return new AABB2D(lowerBoundary, upperBoundary);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal static class AABB3DNetPacker
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    internal static void Write(NetDataWriter writer, AABB3D data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3DNetPacker.Write(writer, data.LowerBoundary);
 | 
				
			||||||
 | 
					        Vector3DNetPacker.Write(writer, data.UpperBoundary);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal static AABB3D Read(NetDataReader reader)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3D lowerBoundary = Vector3DNetPacker.Read(reader);
 | 
				
			||||||
 | 
					        Vector3D upperBoundary = Vector3DNetPacker.Read(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new AABB3D(lowerBoundary, upperBoundary);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class CircleNetPacker
 | 
					internal static class CircleNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal static class ColorHSVANetPacker
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    internal static void Write(NetDataWriter writer, ColorHSVA data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        writer.Put(data.Hue);
 | 
				
			||||||
 | 
					        writer.Put(data.Saturation);
 | 
				
			||||||
 | 
					        writer.Put(data.Value);
 | 
				
			||||||
 | 
					        writer.Put(data.Alpha);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal static ColorHSVA Read(NetDataReader reader)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        float hue = reader.GetFloat();
 | 
				
			||||||
 | 
					        float saturation = reader.GetFloat();
 | 
				
			||||||
 | 
					        float value = reader.GetFloat();
 | 
				
			||||||
 | 
					        float alpha = reader.GetFloat();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new ColorHSVA(hue, saturation, value, alpha);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class ColorHSVNetPacker
 | 
					internal static class ColorHSVNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class ColorRGBANetPacker
 | 
					internal static class ColorRGBANetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class ColorRGBNetPacker
 | 
					internal static class ColorRGBNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class Line2DEquationNetPacker
 | 
					internal static class Line2DEquationNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class Line2DNetPacker
 | 
					internal static class Line2DNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal static class Line3DNetPacker
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    internal static void Write(NetDataWriter writer, Line3D data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3DNetPacker.Write(writer, data.From);
 | 
				
			||||||
 | 
					        Vector3DNetPacker.Write(writer, data.To);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal static Line3D Read(NetDataReader reader)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3D from = Vector3DNetPacker.Read(reader);
 | 
				
			||||||
 | 
					        Vector3D to = Vector3DNetPacker.Read(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Line3D(from, to);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class Projection1DNetPacker
 | 
					internal static class Projection1DNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class QuaternionNetPacker
 | 
					internal static class QuaternionNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal static class Ray2DNetPacker
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    internal static void Write(NetDataWriter writer, Ray2D data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector2DNetPacker.Write(writer, data.Origin);
 | 
				
			||||||
 | 
					        Vector2DNetPacker.Write(writer, data.Direction);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal static Ray2D Read(NetDataReader reader)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector2D from = Vector2DNetPacker.Read(reader);
 | 
				
			||||||
 | 
					        Vector2D direction = Vector2DNetPacker.Read(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Ray2D(from, direction);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal static class Ray3DNetPacker
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    internal static void Write(NetDataWriter writer, Ray3D data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3DNetPacker.Write(writer, data.Origin);
 | 
				
			||||||
 | 
					        Vector3DNetPacker.Write(writer, data.Direction);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal static Ray3D Read(NetDataReader reader)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3D from = Vector3DNetPacker.Read(reader);
 | 
				
			||||||
 | 
					        Vector3D direction = Vector3DNetPacker.Read(reader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Ray3D(from, direction);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class Shape2DNetPacker
 | 
					internal static class Shape2DNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal static class Sphere3DNetPacker
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    internal static void Write(NetDataWriter writer, Sphere3D data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3DNetPacker.Write(writer, data.Center);
 | 
				
			||||||
 | 
					        writer.Put(data.Radius);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal static Sphere3D Read(NetDataReader reader)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3D center = Vector3DNetPacker.Read(reader);
 | 
				
			||||||
 | 
					        float radius = reader.GetFloat();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Sphere3D(center, radius);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class TriangleNetPacker
 | 
					internal static class TriangleNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal static class Vector2DIntNetPacker
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    internal static void Write(NetDataWriter writer, Vector2DInt data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        writer.Put(data.X);
 | 
				
			||||||
 | 
					        writer.Put(data.Y);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal static Vector2DInt Read(NetDataReader reader)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int x = reader.GetInt();
 | 
				
			||||||
 | 
					        int y = reader.GetInt();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Vector2DInt(x, y);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class Vector2DNetPacker
 | 
					internal static class Vector2DNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal static class Vector3DIntNetPacker
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    internal static void Write(NetDataWriter writer, Vector3DInt data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        writer.Put(data.X);
 | 
				
			||||||
 | 
					        writer.Put(data.Y);
 | 
				
			||||||
 | 
					        writer.Put(data.Z);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal static Vector3DInt Read(NetDataReader reader)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int x = reader.GetInt();
 | 
				
			||||||
 | 
					        int y = reader.GetInt();
 | 
				
			||||||
 | 
					        int z = reader.GetInt();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Vector3DInt(x, y, z);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,7 +2,7 @@ using LiteNetLib.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Network;
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal static class Vector3DNetPacker
 | 
					internal static class Vector3DNetPacker
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					using LiteNetLib.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Network.Packers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal static class Vector4DNetPacker
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    internal static void Write(NetDataWriter writer, Vector4D data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        writer.Put(data.X);
 | 
				
			||||||
 | 
					        writer.Put(data.Y);
 | 
				
			||||||
 | 
					        writer.Put(data.Z);
 | 
				
			||||||
 | 
					        writer.Put(data.W);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal static Vector4D Read(NetDataReader reader)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        float x = reader.GetFloat();
 | 
				
			||||||
 | 
					        float y = reader.GetFloat();
 | 
				
			||||||
 | 
					        float z = reader.GetFloat();
 | 
				
			||||||
 | 
					        float w = reader.GetFloat();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Vector4D(x, y, z, w);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -10,13 +10,13 @@ namespace Engine.Integration.MonoGame;
 | 
				
			|||||||
public interface ISpriteBatch
 | 
					public interface ISpriteBatch
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    void Begin(SpriteSortMode sortMode = SpriteSortMode.Deferred, BlendState? blendState = null, SamplerState? samplerState = null, DepthStencilState? depthStencilState = null, RasterizerState? rasterizerState = null, Effect? effect = null, Matrix? transformMatrix = null);
 | 
					    void Begin(SpriteSortMode sortMode = SpriteSortMode.Deferred, BlendState? blendState = null, SamplerState? samplerState = null, DepthStencilState? depthStencilState = null, RasterizerState? rasterizerState = null, Effect? effect = null, Matrix? transformMatrix = null);
 | 
				
			||||||
    void Draw(Texture2D texture, Vector2D position, AABB? sourceAABB, Color color, float rotation, Vector2D origin, Vector2D scale, SpriteEffects effects, float layerDepth);
 | 
					    void Draw(Texture2D texture, Vector2D position, AABB2D? sourceAABB, Color color, float rotation, Vector2D origin, Vector2D scale, SpriteEffects effects, float layerDepth);
 | 
				
			||||||
    void Draw(Texture2D texture, Vector2D position, AABB? sourceAABB, Color color, float rotation, Vector2D origin, float scale, SpriteEffects effects, float layerDepth);
 | 
					    void Draw(Texture2D texture, Vector2D position, AABB2D? sourceAABB, Color color, float rotation, Vector2D origin, float scale, SpriteEffects effects, float layerDepth);
 | 
				
			||||||
    void Draw(Texture2D texture, AABB destinationAABB, AABB? sourceAABB, Color color, float rotation, Vector2D origin, SpriteEffects effects, float layerDepth);
 | 
					    void Draw(Texture2D texture, AABB2D destinationAABB, AABB2D? sourceAABB, Color color, float rotation, Vector2D origin, SpriteEffects effects, float layerDepth);
 | 
				
			||||||
    void Draw(Texture2D texture, Vector2D position, AABB? sourceAABB, Color color);
 | 
					    void Draw(Texture2D texture, Vector2D position, AABB2D? sourceAABB, Color color);
 | 
				
			||||||
    void Draw(Texture2D texture, AABB destinationAABB, AABB? sourceAABB, Color color);
 | 
					    void Draw(Texture2D texture, AABB2D destinationAABB, AABB2D? sourceAABB, Color color);
 | 
				
			||||||
    void Draw(Texture2D texture, Vector2D position, Color color);
 | 
					    void Draw(Texture2D texture, Vector2D position, Color color);
 | 
				
			||||||
    void Draw(Texture2D texture, AABB destinationAABB, Color color);
 | 
					    void Draw(Texture2D texture, AABB2D destinationAABB, Color color);
 | 
				
			||||||
    void DrawString(SpriteFont spriteFont, string text, Vector2D position, Color color);
 | 
					    void DrawString(SpriteFont spriteFont, string text, Vector2D position, Color color);
 | 
				
			||||||
    void DrawString(SpriteFont spriteFont, string text, Vector2D position, Color color, float rotation, Vector2D origin, float scale, SpriteEffects effects, float layerDepth);
 | 
					    void DrawString(SpriteFont spriteFont, string text, Vector2D position, Color color, float rotation, Vector2D origin, float scale, SpriteEffects effects, float layerDepth);
 | 
				
			||||||
    void DrawString(SpriteFont spriteFont, string text, Vector2D position, Color color, float rotation, Vector2D origin, Vector2D scale, SpriteEffects effects, float layerDepth);
 | 
					    void DrawString(SpriteFont spriteFont, string text, Vector2D position, Color color, float rotation, Vector2D origin, Vector2D scale, SpriteEffects effects, float layerDepth);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ using Engine.Core;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Integration.MonoGame;
 | 
					namespace Engine.Integration.MonoGame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class LoadContentManager : Behaviour, IFirstFrameUpdate
 | 
					public class LoadContentManager : Behaviour, IEnterUniverse, IExitUniverse, IFirstFrameUpdate
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // We use Ascending order because we are using reverse for loop to call them
 | 
					    // We use Ascending order because we are using reverse for loop to call them
 | 
				
			||||||
    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
					    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
				
			||||||
@@ -20,14 +20,14 @@ public class LoadContentManager : Behaviour, IFirstFrameUpdate
 | 
				
			|||||||
        monoGameWindowContainer = Universe.FindRequiredBehaviour<MonoGameWindowContainer>();
 | 
					        monoGameWindowContainer = Universe.FindRequiredBehaviour<MonoGameWindowContainer>();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnEnteredUniverse(IUniverse universe)
 | 
					    public void EnterUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        loadContents.Assign(universe);
 | 
					        loadContents.Assign(universe);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        universe.OnPreUpdate.AddListener(OnPreUpdate);
 | 
					        universe.OnPreUpdate.AddListener(OnPreUpdate);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe)
 | 
					    public void ExitUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        loadContents.Unassign();
 | 
					        loadContents.Unassign();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,11 +5,11 @@ using Engine.Core;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Integration.MonoGame;
 | 
					namespace Engine.Integration.MonoGame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class MonoGameCamera2D : BehaviourBase, ICamera2D, IFirstFrameUpdate, IPreDraw
 | 
					public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, IPreDraw
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public event MatrixTransformChangedArguments? OnMatrixTransformChanged = null;
 | 
					    public Event<MonoGameCamera2D> OnMatrixTransformChanged { get; } = new();
 | 
				
			||||||
    public event ViewportChangedArguments? OnViewportChanged = null;
 | 
					    public Event<MonoGameCamera2D> OnViewportChanged { get; } = new();
 | 
				
			||||||
    public event ZoomChangedArguments? OnZoomChanged = null;
 | 
					    public Event<MonoGameCamera2D> OnZoomChanged { get; } = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Matrix _matrixTransform = Matrix.Identity;
 | 
					    private Matrix _matrixTransform = Matrix.Identity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,7 +28,7 @@ public class MonoGameCamera2D : BehaviourBase, ICamera2D, IFirstFrameUpdate, IPr
 | 
				
			|||||||
                return;
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _matrixTransform = value;
 | 
					            _matrixTransform = value;
 | 
				
			||||||
            OnMatrixTransformChanged?.Invoke(this);
 | 
					            OnMatrixTransformChanged.Invoke(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -47,7 +47,7 @@ public class MonoGameCamera2D : BehaviourBase, ICamera2D, IFirstFrameUpdate, IPr
 | 
				
			|||||||
                return;
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _viewport = value;
 | 
					            _viewport = value;
 | 
				
			||||||
            OnViewportChanged?.Invoke(this);
 | 
					            OnViewportChanged.Invoke(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -62,7 +62,7 @@ public class MonoGameCamera2D : BehaviourBase, ICamera2D, IFirstFrameUpdate, IPr
 | 
				
			|||||||
                return;
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _zoom = newValue;
 | 
					            _zoom = newValue;
 | 
				
			||||||
            OnZoomChanged?.Invoke(this);
 | 
					            OnZoomChanged.Invoke(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -102,8 +102,4 @@ public class MonoGameCamera2D : BehaviourBase, ICamera2D, IFirstFrameUpdate, IPr
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    protected sealed override void InitializeInternal() => Transform = BehaviourController.GetRequiredBehaviour<ITransform2D>();
 | 
					    protected sealed override void InitializeInternal() => Transform = BehaviourController.GetRequiredBehaviour<ITransform2D>();
 | 
				
			||||||
    protected sealed override void FinalizeInternal() => Transform = null!;
 | 
					    protected sealed override void FinalizeInternal() => Transform = null!;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public delegate void MatrixTransformChangedArguments(MonoGameCamera2D sender);
 | 
					 | 
				
			||||||
    public delegate void ViewportChangedArguments(MonoGameCamera2D sender);
 | 
					 | 
				
			||||||
    public delegate void ZoomChangedArguments(MonoGameCamera2D sender);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,131 @@
 | 
				
			|||||||
 | 
					using Microsoft.Xna.Framework;
 | 
				
			||||||
 | 
					using Microsoft.Xna.Framework.Graphics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Integration.MonoGame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class MonoGameCamera3D : Behaviour, ICamera3D, IFirstFrameUpdate, IPreDraw
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public Event<MonoGameCamera3D, ViewChangedArguments> OnViewChanged { get; } = new();
 | 
				
			||||||
 | 
					    public Event<MonoGameCamera3D, ProjectionChangedArguments> OnProjectionChanged { get; } = new();
 | 
				
			||||||
 | 
					    public Event<MonoGameCamera3D, ViewportChangedArguments> OnViewportChanged { get; } = new();
 | 
				
			||||||
 | 
					    public Event<MonoGameCamera3D, FieldOfViewChangedArguments> OnFieldOfViewChanged { get; } = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Matrix _view = Matrix.Identity;
 | 
				
			||||||
 | 
					    private Matrix _projection = Matrix.Identity;
 | 
				
			||||||
 | 
					    private Viewport _viewport = default;
 | 
				
			||||||
 | 
					    private float _fieldOfView = 1f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public GraphicsDeviceManager Graphics { get; private set; } = null!;
 | 
				
			||||||
 | 
					    public ITransform3D Transform { get; private set; } = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Matrix View
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _view;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (_view == value)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Matrix previousView = _view;
 | 
				
			||||||
 | 
					            _view = value;
 | 
				
			||||||
 | 
					            OnViewChanged.Invoke(this, new(previousView));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public Matrix Projection
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _projection;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (_projection == value)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Matrix previousProjection = _projection;
 | 
				
			||||||
 | 
					            _projection = value;
 | 
				
			||||||
 | 
					            OnProjectionChanged.Invoke(this, new(previousProjection));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Vector3D Position
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => Transform.Position;
 | 
				
			||||||
 | 
					        set => Transform.Position = value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Viewport Viewport
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _viewport;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (_viewport.Equals(value))
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Viewport previousViewport = _viewport;
 | 
				
			||||||
 | 
					            _viewport = value;
 | 
				
			||||||
 | 
					            OnViewportChanged.Invoke(this, new(previousViewport));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public float FieldOfView
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => _fieldOfView;
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            float newValue = Math.Max(0.1f, value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (_fieldOfView == newValue)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            float previousFieldOfView = _fieldOfView;
 | 
				
			||||||
 | 
					            _fieldOfView = newValue;
 | 
				
			||||||
 | 
					            OnFieldOfViewChanged.Invoke(this, new(previousFieldOfView));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Engine.Core.Quaternion Rotation
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => Transform.Rotation;
 | 
				
			||||||
 | 
					        set => Transform.Rotation = value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO This causes delay since OnPreDraw calls assuming this is called in in Update 
 | 
				
			||||||
 | 
					    public Ray3D ScreenToWorldRay(Vector2D screenPosition)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3 nearPoint = new(screenPosition.X, screenPosition.Y, 0f);
 | 
				
			||||||
 | 
					        Vector3 farPoint = new(screenPosition.X, screenPosition.Y, 1f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Vector3 worldNear = Viewport.Unproject(nearPoint, _projection, _view, Matrix.Identity);
 | 
				
			||||||
 | 
					        Vector3 worldFar = Viewport.Unproject(farPoint, _projection, _view, Matrix.Identity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Vector3 direction = Vector3.Normalize(worldFar - worldNear);
 | 
				
			||||||
 | 
					        return new(worldNear.ToVector3D(), direction.ToVector3D());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Vector2D WorldToScreenPosition(Vector3D worldPosition) => Viewport.Project(worldPosition.ToVector3(), _projection, _view, Matrix.Identity).ToVector3D();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void FirstActiveFrame()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Graphics = BehaviourController.UniverseObject.Universe.FindRequiredBehaviour<MonoGameWindowContainer>().Window.Graphics;
 | 
				
			||||||
 | 
					        Viewport = Graphics.GraphicsDevice.Viewport;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void PreDraw()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3 cameraPosition = Position.ToVector3();
 | 
				
			||||||
 | 
					        View = Matrix.CreateLookAt(
 | 
				
			||||||
 | 
					            cameraPosition,
 | 
				
			||||||
 | 
					            Transform.Forward.ToVector3() + cameraPosition,
 | 
				
			||||||
 | 
					            Transform.Up.ToVector3()
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Viewport.AspectRatio, 0.1f, 100f);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected sealed override void InitializeInternal() => Transform = BehaviourController.GetRequiredBehaviour<ITransform3D>();
 | 
				
			||||||
 | 
					    protected sealed override void FinalizeInternal() => Transform = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public readonly record struct ViewChangedArguments(Matrix PreviousView);
 | 
				
			||||||
 | 
					    public readonly record struct ProjectionChangedArguments(Matrix PreviousProjection);
 | 
				
			||||||
 | 
					    public readonly record struct ViewportChangedArguments(Viewport PreviousViewport);
 | 
				
			||||||
 | 
					    public readonly record struct FieldOfViewChangedArguments(float PreviousFieldOfView);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -14,25 +14,25 @@ public class SpriteBatchWrapper(GraphicsDevice graphicsDevice) : ISpriteBatch
 | 
				
			|||||||
    public void Begin(SpriteSortMode sortMode = SpriteSortMode.Deferred, BlendState? blendState = null, SamplerState? samplerState = null, DepthStencilState? depthStencilState = null, RasterizerState? rasterizerState = null, Effect? effect = null, Matrix? transformMatrix = null)
 | 
					    public void Begin(SpriteSortMode sortMode = SpriteSortMode.Deferred, BlendState? blendState = null, SamplerState? samplerState = null, DepthStencilState? depthStencilState = null, RasterizerState? rasterizerState = null, Effect? effect = null, Matrix? transformMatrix = null)
 | 
				
			||||||
        => spriteBatch.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, transformMatrix);
 | 
					        => spriteBatch.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, transformMatrix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void Draw(Texture2D texture, Vector2D position, AABB? sourceAABB, Color color, float rotation, Vector2D origin, Vector2D scale, SpriteEffects effects, float layerDepth)
 | 
					    public void Draw(Texture2D texture, Vector2D position, AABB2D? sourceAABB, Color color, float rotation, Vector2D origin, Vector2D scale, SpriteEffects effects, float layerDepth)
 | 
				
			||||||
        => spriteBatch.Draw(texture, position.ToDisplayVector2(), sourceAABB?.ToRectangle(), color, rotation, origin.ToDisplayVector2(), scale.ToDisplayVector2(), effects, layerDepth);
 | 
					        => spriteBatch.Draw(texture, position.ToDisplayVector2(), sourceAABB?.ToRectangle(), color, rotation, origin.ToDisplayVector2(), scale.ToDisplayVector2(), effects, layerDepth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void Draw(Texture2D texture, Vector2D position, AABB? sourceAABB, Color color, float rotation, Vector2D origin, float scale, SpriteEffects effects, float layerDepth)
 | 
					    public void Draw(Texture2D texture, Vector2D position, AABB2D? sourceAABB, Color color, float rotation, Vector2D origin, float scale, SpriteEffects effects, float layerDepth)
 | 
				
			||||||
        => spriteBatch.Draw(texture, position.ToDisplayVector2(), sourceAABB?.ToRectangle(), color, rotation, origin.ToDisplayVector2(), scale, effects, layerDepth);
 | 
					        => spriteBatch.Draw(texture, position.ToDisplayVector2(), sourceAABB?.ToRectangle(), color, rotation, origin.ToDisplayVector2(), scale, effects, layerDepth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void Draw(Texture2D texture, AABB destinationAABB, AABB? sourceAABB, Color color, float rotation, Vector2D origin, SpriteEffects effects, float layerDepth)
 | 
					    public void Draw(Texture2D texture, AABB2D destinationAABB, AABB2D? sourceAABB, Color color, float rotation, Vector2D origin, SpriteEffects effects, float layerDepth)
 | 
				
			||||||
        => spriteBatch.Draw(texture, destinationAABB.ToRectangle(), sourceAABB?.ToRectangle(), color, rotation, origin.ToDisplayVector2(), effects, layerDepth);
 | 
					        => spriteBatch.Draw(texture, destinationAABB.ToRectangle(), sourceAABB?.ToRectangle(), color, rotation, origin.ToDisplayVector2(), effects, layerDepth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void Draw(Texture2D texture, Vector2D position, AABB? sourceAABB, Color color)
 | 
					    public void Draw(Texture2D texture, Vector2D position, AABB2D? sourceAABB, Color color)
 | 
				
			||||||
        => spriteBatch.Draw(texture, position.ToDisplayVector2(), sourceAABB?.ToRectangle(), color);
 | 
					        => spriteBatch.Draw(texture, position.ToDisplayVector2(), sourceAABB?.ToRectangle(), color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void Draw(Texture2D texture, AABB destinationAABB, AABB? sourceAABB, Color color)
 | 
					    public void Draw(Texture2D texture, AABB2D destinationAABB, AABB2D? sourceAABB, Color color)
 | 
				
			||||||
        => spriteBatch.Draw(texture, destinationAABB.ToRectangle(), sourceAABB?.ToRectangle(), color);
 | 
					        => spriteBatch.Draw(texture, destinationAABB.ToRectangle(), sourceAABB?.ToRectangle(), color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void Draw(Texture2D texture, Vector2D position, Color color)
 | 
					    public void Draw(Texture2D texture, Vector2D position, Color color)
 | 
				
			||||||
        => spriteBatch.Draw(texture, position.ToDisplayVector2(), color);
 | 
					        => spriteBatch.Draw(texture, position.ToDisplayVector2(), color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void Draw(Texture2D texture, AABB destinationAABB, Color color)
 | 
					    public void Draw(Texture2D texture, AABB2D destinationAABB, Color color)
 | 
				
			||||||
        => spriteBatch.Draw(texture, destinationAABB.ToRectangle(), color);
 | 
					        => spriteBatch.Draw(texture, destinationAABB.ToRectangle(), color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void DrawString(SpriteFont spriteFont, string text, Vector2D position, Color color)
 | 
					    public void DrawString(SpriteFont spriteFont, string text, Vector2D position, Color color)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ using Engine.Core;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Integration.MonoGame;
 | 
					namespace Engine.Integration.MonoGame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class SpriteBatcher : BehaviourBase, IFirstFrameUpdate, IDraw
 | 
					public class SpriteBatcher : Behaviour, IFirstFrameUpdate, IDraw
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private static Comparer<int> SortByPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
 | 
					    private static Comparer<int> SortByPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
 | 
				
			||||||
    private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
 | 
					    private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@ using Engine.Core;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Integration.MonoGame;
 | 
					namespace Engine.Integration.MonoGame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class TriangleBatcher : BehaviourBase, ITriangleBatch, IFirstFrameUpdate, IDraw
 | 
					public class TriangleBatcher : Behaviour, ITriangleBatch, IFirstFrameUpdate, IDraw
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
					    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
				
			||||||
    private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
 | 
					    private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,15 @@ public static class EngineConverterExtensions
 | 
				
			|||||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
    public static Vector2 ToVector2(this Vector2D vector) => new(vector.X, vector.Y);
 | 
					    public static Vector2 ToVector2(this Vector2D vector) => new(vector.X, vector.Y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static Vector3D ToVector3D(this Vector3 vector) => new(vector.X, vector.Y, vector.Z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static Vector3 ToVector3(this Vector3D vector) => new(vector.X, vector.Y, vector.Z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
 | 
					    public static Microsoft.Xna.Framework.Quaternion ToXnaQuaternion(this Core.Quaternion quaternion) => new(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
    public static Vector2 ToDisplayVector2(this Vector2D vector) => vector.Scale(screenScale).ToVector2();
 | 
					    public static Vector2 ToDisplayVector2(this Vector2D vector) => vector.Scale(screenScale).ToVector2();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,7 +60,7 @@ public static class EngineConverterExtensions
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
					    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
				
			||||||
    public static Rectangle ToRectangle(this AABB aabb) => new()
 | 
					    public static Rectangle ToRectangle(this AABB2D aabb) => new()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        X = (int)(aabb.LowerBoundary.X * screenScale.X),
 | 
					        X = (int)(aabb.LowerBoundary.X * screenScale.X),
 | 
				
			||||||
        Y = (int)(aabb.LowerBoundary.Y * screenScale.Y),
 | 
					        Y = (int)(aabb.LowerBoundary.Y * screenScale.Y),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ using Engine.Core.Serialization;
 | 
				
			|||||||
namespace Engine.Integration.MonoGame;
 | 
					namespace Engine.Integration.MonoGame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[IgnoreSerialization]
 | 
					[IgnoreSerialization]
 | 
				
			||||||
public class MonoGameWindowContainer(MonoGameWindow GameWindow) : BehaviourBase
 | 
					public class MonoGameWindowContainer(MonoGameWindow GameWindow) : Behaviour
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public MonoGameWindow Window { get; } = GameWindow;
 | 
					    public MonoGameWindow Window { get; } = GameWindow;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,33 +8,33 @@ using YamlDotNet.Serialization;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Serializers.Yaml;
 | 
					namespace Engine.Serializers.Yaml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class AABBConverter : EngineTypeYamlSerializerBase<AABB>
 | 
					public class AABB2DConverter : EngineTypeYamlSerializerBase<AABB2D>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public override AABB Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
 | 
					    public override AABB2D Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parser.Consume<MappingStart>();
 | 
					        parser.Consume<MappingStart>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (parser.Consume<Scalar>().Value.CompareTo(nameof(AABB.LowerBoundary)) != 0)
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(AABB2D.LowerBoundary)) != 0)
 | 
				
			||||||
            throw new ArgumentException($"{nameof(AABB)} mapping must start with {nameof(AABB.LowerBoundary)}");
 | 
					            throw new ArgumentException($"{nameof(AABB2D)} mapping must start with {nameof(AABB2D.LowerBoundary)}");
 | 
				
			||||||
        Vector2D lowerBoundary = (Vector2D)rootDeserializer(typeof(Vector2D))!;
 | 
					        Vector2D lowerBoundary = (Vector2D)rootDeserializer(typeof(Vector2D))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (parser.Consume<Scalar>().Value.CompareTo(nameof(AABB.UpperBoundary)) != 0)
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(AABB2D.UpperBoundary)) != 0)
 | 
				
			||||||
            throw new ArgumentException($"{nameof(AABB)} mapping must end with {nameof(AABB.UpperBoundary)}");
 | 
					            throw new ArgumentException($"{nameof(AABB2D)} mapping must end with {nameof(AABB2D.UpperBoundary)}");
 | 
				
			||||||
        Vector2D upperBoundary = (Vector2D)rootDeserializer(typeof(Vector2D))!;
 | 
					        Vector2D upperBoundary = (Vector2D)rootDeserializer(typeof(Vector2D))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        parser.Consume<MappingEnd>();
 | 
					        parser.Consume<MappingEnd>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return new AABB(lowerBoundary, upperBoundary);
 | 
					        return new AABB2D(lowerBoundary, upperBoundary);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
 | 
					    public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        AABB aabb = (AABB)value!;
 | 
					        AABB2D aabb = (AABB2D)value!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        emitter.Emit(new MappingStart());
 | 
					        emitter.Emit(new MappingStart());
 | 
				
			||||||
        emitter.Emit(new Scalar(nameof(AABB.LowerBoundary)));
 | 
					        emitter.Emit(new Scalar(nameof(AABB2D.LowerBoundary)));
 | 
				
			||||||
        serializer(aabb.LowerBoundary, typeof(Vector2D));
 | 
					        serializer(aabb.LowerBoundary, typeof(Vector2D));
 | 
				
			||||||
        emitter.Emit(new Scalar(nameof(AABB.UpperBoundary)));
 | 
					        emitter.Emit(new Scalar(nameof(AABB2D.UpperBoundary)));
 | 
				
			||||||
        serializer(aabb.UpperBoundary, typeof(Vector2D));
 | 
					        serializer(aabb.UpperBoundary, typeof(Vector2D));
 | 
				
			||||||
        emitter.Emit(new MappingEnd());
 | 
					        emitter.Emit(new MappingEnd());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using YamlDotNet.Core;
 | 
				
			||||||
 | 
					using YamlDotNet.Core.Events;
 | 
				
			||||||
 | 
					using YamlDotNet.Serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Serializers.Yaml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class AABB3DConverter : EngineTypeYamlSerializerBase<AABB3D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public override AABB3D Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parser.Consume<MappingStart>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(AABB3D.LowerBoundary)) != 0)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"{nameof(AABB3D)} mapping must start with {nameof(AABB3D.LowerBoundary)}");
 | 
				
			||||||
 | 
					        Vector3D lowerBoundary = (Vector3D)rootDeserializer(typeof(Vector3D))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(AABB3D.UpperBoundary)) != 0)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"{nameof(AABB3D)} mapping must end with {nameof(AABB3D.UpperBoundary)}");
 | 
				
			||||||
 | 
					        Vector3D upperBoundary = (Vector3D)rootDeserializer(typeof(Vector3D))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        parser.Consume<MappingEnd>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new AABB3D(lowerBoundary, upperBoundary);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        AABB3D aabb = (AABB3D)value!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        emitter.Emit(new MappingStart());
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar(nameof(AABB3D.LowerBoundary)));
 | 
				
			||||||
 | 
					        serializer(aabb.LowerBoundary, typeof(Vector3D));
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar(nameof(AABB3D.UpperBoundary)));
 | 
				
			||||||
 | 
					        serializer(aabb.UpperBoundary, typeof(Vector3D));
 | 
				
			||||||
 | 
					        emitter.Emit(new MappingEnd());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using YamlDotNet.Core;
 | 
				
			||||||
 | 
					using YamlDotNet.Core.Events;
 | 
				
			||||||
 | 
					using YamlDotNet.Serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Serializers.Yaml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ColorHSVAConverter : EngineTypeYamlSerializerBase<ColorHSVA>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static readonly int SUBSTRING_START_LENGTH = nameof(ColorHSVA).Length + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override ColorHSVA Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        string value = parser.Consume<Scalar>().Value;
 | 
				
			||||||
 | 
					        string insideParenthesis = value[SUBSTRING_START_LENGTH..^1];
 | 
				
			||||||
 | 
					        string[] values = insideParenthesis.Split(", ");
 | 
				
			||||||
 | 
					        return new ColorHSVA(float.Parse(values[0]), float.Parse(values[1]), float.Parse(values[2]), float.Parse(values[3]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ColorHSVA hsva = (ColorHSVA)value!;
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar($"{nameof(ColorHSVA)}({hsva.Hue}, {hsva.Saturation}, {hsva.Value}, {hsva.Alpha})"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using YamlDotNet.Core;
 | 
				
			||||||
 | 
					using YamlDotNet.Core.Events;
 | 
				
			||||||
 | 
					using YamlDotNet.Serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Serializers.Yaml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Line3DConverter : EngineTypeYamlSerializerBase<Line3D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public override Line3D Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parser.Consume<MappingStart>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(Line3D.From)) != 0)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"{nameof(Line3D)} mapping must start with {nameof(Line3D.From)}");
 | 
				
			||||||
 | 
					        Vector3D from = (Vector3D)rootDeserializer(typeof(Vector3D))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(Line3D.To)) != 0)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"{nameof(Line3D)} mapping must end with {nameof(Line3D.To)}");
 | 
				
			||||||
 | 
					        Vector3D to = (Vector3D)rootDeserializer(typeof(Vector3D))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        parser.Consume<MappingEnd>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Line3D(from, to);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Line3D line3D = (Line3D)value!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        emitter.Emit(new MappingStart());
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar(nameof(Line3D.From)));
 | 
				
			||||||
 | 
					        serializer(line3D.From, typeof(Vector3D));
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar(nameof(Line3D.To)));
 | 
				
			||||||
 | 
					        serializer(line3D.To, typeof(Vector3D));
 | 
				
			||||||
 | 
					        emitter.Emit(new MappingEnd());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using YamlDotNet.Core;
 | 
				
			||||||
 | 
					using YamlDotNet.Core.Events;
 | 
				
			||||||
 | 
					using YamlDotNet.Serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Serializers.Yaml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Ray2DConverter : EngineTypeYamlSerializerBase<Ray2D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public override Ray2D Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parser.Consume<MappingStart>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(Ray2D.Origin)) != 0)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"{nameof(Ray2D)} mapping must start with {nameof(Ray2D.Origin)}");
 | 
				
			||||||
 | 
					        Vector2D origin = (Vector2D)rootDeserializer(typeof(Vector2D))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(Ray2D.Direction)) != 0)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"{nameof(Ray2D)} mapping must end with {nameof(Ray2D.Direction)}");
 | 
				
			||||||
 | 
					        Vector2D direction = (Vector2D)rootDeserializer(typeof(Vector2D))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        parser.Consume<MappingEnd>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Ray2D(origin, direction);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Ray2D ray2D = (Ray2D)value!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        emitter.Emit(new MappingStart());
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar(nameof(ray2D.Origin)));
 | 
				
			||||||
 | 
					        serializer(ray2D.Origin, typeof(Vector2D));
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar(nameof(ray2D.Direction)));
 | 
				
			||||||
 | 
					        serializer(ray2D.Direction, typeof(Vector2D));
 | 
				
			||||||
 | 
					        emitter.Emit(new MappingEnd());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using YamlDotNet.Core;
 | 
				
			||||||
 | 
					using YamlDotNet.Core.Events;
 | 
				
			||||||
 | 
					using YamlDotNet.Serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Serializers.Yaml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Ray3DConverter : EngineTypeYamlSerializerBase<Ray3D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public override Ray3D Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parser.Consume<MappingStart>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(Ray3D.Origin)) != 0)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"{nameof(Ray3D)} mapping must start with {nameof(Ray3D.Origin)}");
 | 
				
			||||||
 | 
					        Vector3D origin = (Vector3D)rootDeserializer(typeof(Vector3D))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(Ray3D.Direction)) != 0)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"{nameof(Ray3D)} mapping must end with {nameof(Ray3D.Direction)}");
 | 
				
			||||||
 | 
					        Vector3D direction = (Vector3D)rootDeserializer(typeof(Vector3D))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        parser.Consume<MappingEnd>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Ray3D(origin, direction);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Ray3D ray3D = (Ray3D)value!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        emitter.Emit(new MappingStart());
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar(nameof(ray3D.Origin)));
 | 
				
			||||||
 | 
					        serializer(ray3D.Origin, typeof(Vector3D));
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar(nameof(ray3D.Direction)));
 | 
				
			||||||
 | 
					        serializer(ray3D.Direction, typeof(Vector3D));
 | 
				
			||||||
 | 
					        emitter.Emit(new MappingEnd());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using YamlDotNet.Core;
 | 
				
			||||||
 | 
					using YamlDotNet.Core.Events;
 | 
				
			||||||
 | 
					using YamlDotNet.Serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Serializers.Yaml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Sphere3DConverter : EngineTypeYamlSerializerBase<Sphere3D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public override Sphere3D Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parser.Consume<MappingStart>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(Sphere3D.Center)) != 0)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"{nameof(Sphere3D)} mapping must start with {nameof(Sphere3D.Center)}");
 | 
				
			||||||
 | 
					        Vector3D lowerBoundary = (Vector3D)rootDeserializer(typeof(Vector3D))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (parser.Consume<Scalar>().Value.CompareTo(nameof(Sphere3D.Radius)) != 0)
 | 
				
			||||||
 | 
					            throw new ArgumentException($"{nameof(Sphere3D)} mapping must end with {nameof(Sphere3D.Radius)}");
 | 
				
			||||||
 | 
					        float radius = (float)rootDeserializer(typeof(float))!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        parser.Consume<MappingEnd>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Sphere3D(lowerBoundary, radius);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Sphere3D sphere = (Sphere3D)value!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        emitter.Emit(new MappingStart());
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar(nameof(Sphere3D.Center)));
 | 
				
			||||||
 | 
					        serializer(sphere.Center, typeof(Vector3D));
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar(nameof(Sphere3D.Radius)));
 | 
				
			||||||
 | 
					        serializer(sphere.Radius, typeof(float));
 | 
				
			||||||
 | 
					        emitter.Emit(new MappingEnd());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using YamlDotNet.Core;
 | 
				
			||||||
 | 
					using YamlDotNet.Core.Events;
 | 
				
			||||||
 | 
					using YamlDotNet.Serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Serializers.Yaml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Vector2DIntConverter : EngineTypeYamlSerializerBase<Vector2DInt>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static readonly int SUBSTRING_START_LENGTH = nameof(Vector2DInt).Length + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override Vector2DInt Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        string value = parser.Consume<Scalar>().Value;
 | 
				
			||||||
 | 
					        string insideParenthesis = value[SUBSTRING_START_LENGTH..^1];
 | 
				
			||||||
 | 
					        string[] values = insideParenthesis.Split(", ");
 | 
				
			||||||
 | 
					        return new Vector2DInt(int.Parse(values[0]), int.Parse(values[1]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector2DInt vector2DInt = (Vector2DInt)value!;
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar($"{nameof(Vector2DInt)}({vector2DInt.X}, {vector2DInt.Y})"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using YamlDotNet.Core;
 | 
				
			||||||
 | 
					using YamlDotNet.Core.Events;
 | 
				
			||||||
 | 
					using YamlDotNet.Serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Serializers.Yaml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Vector3DIntConverter : EngineTypeYamlSerializerBase<Vector3DInt>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static readonly int SUBSTRING_START_LENGTH = nameof(Vector3DInt).Length + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override Vector3DInt Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        string value = parser.Consume<Scalar>().Value;
 | 
				
			||||||
 | 
					        string insideParenthesis = value[SUBSTRING_START_LENGTH..^1];
 | 
				
			||||||
 | 
					        string[] values = insideParenthesis.Split(", ");
 | 
				
			||||||
 | 
					        return new Vector3DInt(int.Parse(values[0]), int.Parse(values[1]), int.Parse(values[2]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector3DInt vector3DInt = (Vector3DInt)value!;
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar($"{nameof(Vector3DInt)}({vector3DInt.X}, {vector3DInt.Y}, {vector3DInt.Z})"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using YamlDotNet.Core;
 | 
				
			||||||
 | 
					using YamlDotNet.Core.Events;
 | 
				
			||||||
 | 
					using YamlDotNet.Serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Serializers.Yaml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Vector4DConverter : EngineTypeYamlSerializerBase<Vector4D>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static readonly int SUBSTRING_START_LENGTH = nameof(Vector4D).Length + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override Vector4D Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        string value = parser.Consume<Scalar>().Value;
 | 
				
			||||||
 | 
					        string insideParenthesis = value[SUBSTRING_START_LENGTH..^1];
 | 
				
			||||||
 | 
					        string[] values = insideParenthesis.Split(", ");
 | 
				
			||||||
 | 
					        return new Vector4D(float.Parse(values[0]), float.Parse(values[1]), float.Parse(values[2]), float.Parse(values[3]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Vector4D vector4D = (Vector4D)value!;
 | 
				
			||||||
 | 
					        emitter.Emit(new Scalar($"{nameof(Vector4D)}({vector4D.X}, {vector4D.Y}, {vector4D.Z}, {vector4D.W})"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 Submodule Engine.Integration/YamlDotNet updated: b8ac2a98ff...62048d7abe
									
								
							@@ -73,7 +73,7 @@ public class CollisionDetector2D : ICollisionDetector2D
 | 
				
			|||||||
            Vector2D projectionVector = vertices[indexProjection].FromTo(vertices[(indexProjection + 1) % count]).Perpendicular().Normalized;
 | 
					            Vector2D projectionVector = vertices[indexProjection].FromTo(vertices[(indexProjection + 1) % count]).Perpendicular().Normalized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Projection1D shapeProjection = shapeCollider.ShapeWorld.ToProjection(projectionVector);
 | 
					            Projection1D shapeProjection = shapeCollider.ShapeWorld.ToProjection(projectionVector);
 | 
				
			||||||
            Projection1D circleProjection = circleCollider.CircleWorld.ToProjection(projectionVector);
 | 
					            Projection1D circleProjection = circleCollider.CircleWorld.ProjectTo(projectionVector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!shapeProjection.Overlaps(circleProjection, out float depth))
 | 
					            if (!shapeProjection.Overlaps(circleProjection, out float depth))
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
@@ -86,7 +86,7 @@ public class CollisionDetector2D : ICollisionDetector2D
 | 
				
			|||||||
            Vector2D shapeToCircleProjectionVector = shapeCollider.Transform.Position.FromTo(circleCollider.CircleWorld.Center).Normalized;
 | 
					            Vector2D shapeToCircleProjectionVector = shapeCollider.Transform.Position.FromTo(circleCollider.CircleWorld.Center).Normalized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Projection1D shapeProjection = shapeCollider.ShapeWorld.ToProjection(shapeToCircleProjectionVector);
 | 
					            Projection1D shapeProjection = shapeCollider.ShapeWorld.ToProjection(shapeToCircleProjectionVector);
 | 
				
			||||||
            Projection1D circleProjection = circleCollider.CircleWorld.ToProjection(shapeToCircleProjectionVector);
 | 
					            Projection1D circleProjection = circleCollider.CircleWorld.ProjectTo(shapeToCircleProjectionVector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!shapeProjection.Overlaps(circleProjection, out float depth))
 | 
					            if (!shapeProjection.Overlaps(circleProjection, out float depth))
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
@@ -104,8 +104,8 @@ public class CollisionDetector2D : ICollisionDetector2D
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        Vector2D leftToRightCenterProjectionVector = left.CircleWorld.Center.FromTo(right.CircleWorld.Center).Normalized;
 | 
					        Vector2D leftToRightCenterProjectionVector = left.CircleWorld.Center.FromTo(right.CircleWorld.Center).Normalized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Projection1D leftProjection = left.CircleWorld.ToProjection(leftToRightCenterProjectionVector);
 | 
					        Projection1D leftProjection = left.CircleWorld.ProjectTo(leftToRightCenterProjectionVector);
 | 
				
			||||||
        Projection1D rightProjection = right.CircleWorld.ToProjection(leftToRightCenterProjectionVector);
 | 
					        Projection1D rightProjection = right.CircleWorld.ProjectTo(leftToRightCenterProjectionVector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool collision = leftProjection.Overlaps(rightProjection, out float depth);
 | 
					        bool collision = leftProjection.Overlaps(rightProjection, out float depth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,11 +68,11 @@ public static class Physics2D
 | 
				
			|||||||
        return isOverlapping;
 | 
					        return isOverlapping;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static bool Overlaps(this AABB aabb, Vector2D point)
 | 
					    public static bool Overlaps(this AABB2D aabb, Vector2D point)
 | 
				
			||||||
        => point.X >= aabb.LowerBoundary.X && point.X <= aabb.UpperBoundary.X &&
 | 
					        => point.X >= aabb.LowerBoundary.X && point.X <= aabb.UpperBoundary.X &&
 | 
				
			||||||
            point.Y >= aabb.LowerBoundary.Y && point.Y <= aabb.UpperBoundary.Y;
 | 
					            point.Y >= aabb.LowerBoundary.Y && point.Y <= aabb.UpperBoundary.Y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static bool Overlaps(this AABB left, AABB right)
 | 
					    public static bool Overlaps(this AABB2D left, AABB2D right)
 | 
				
			||||||
        => left.LowerBoundary.X <= right.UpperBoundary.X && left.UpperBoundary.X >= right.LowerBoundary.X &&
 | 
					        => left.LowerBoundary.X <= right.UpperBoundary.X && left.UpperBoundary.X >= right.LowerBoundary.X &&
 | 
				
			||||||
            left.LowerBoundary.Y <= right.UpperBoundary.Y && left.UpperBoundary.Y >= right.LowerBoundary.Y;
 | 
					            left.LowerBoundary.Y <= right.UpperBoundary.Y && left.UpperBoundary.Y >= right.LowerBoundary.Y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ using Engine.Core;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Physics2D;
 | 
					namespace Engine.Physics2D;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class PhysicsEngine2D : Behaviour, IPreUpdate, IPhysicsEngine2D
 | 
					public class PhysicsEngine2D : Behaviour, IEnterUniverse, IExitUniverse, IPreUpdate, IPhysicsEngine2D
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public Event<IPhysicsEngine2D, float> OnPhysicsIteration { get; } = new();
 | 
					    public Event<IPhysicsEngine2D, float> OnPhysicsIteration { get; } = new();
 | 
				
			||||||
    public Event<IPhysicsEngine2D, float> OnPhysicsStep { get; } = new();
 | 
					    public Event<IPhysicsEngine2D, float> OnPhysicsStep { get; } = new();
 | 
				
			||||||
@@ -224,7 +224,7 @@ public class PhysicsEngine2D : Behaviour, IPreUpdate, IPhysicsEngine2D
 | 
				
			|||||||
        rigidBody.Transform.Rotation += rigidBody.AngularVelocity * intervalDeltaTime;
 | 
					        rigidBody.Transform.Rotation += rigidBody.AngularVelocity * intervalDeltaTime;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnEnteredUniverse(IUniverse universe)
 | 
					    public void EnterUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        physicsPreUpdateCollector.Assign(universe);
 | 
					        physicsPreUpdateCollector.Assign(universe);
 | 
				
			||||||
        physicsUpdateCollector.Assign(universe);
 | 
					        physicsUpdateCollector.Assign(universe);
 | 
				
			||||||
@@ -234,7 +234,7 @@ public class PhysicsEngine2D : Behaviour, IPreUpdate, IPhysicsEngine2D
 | 
				
			|||||||
        rigidBodyCollector.Assign(universe);
 | 
					        rigidBodyCollector.Assign(universe);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe)
 | 
					    public void ExitUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        physicsPreUpdateCollector.Unassign();
 | 
					        physicsPreUpdateCollector.Unassign();
 | 
				
			||||||
        physicsUpdateCollector.Unassign();
 | 
					        physicsUpdateCollector.Unassign();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@ namespace Engine.Systems.Network;
 | 
				
			|||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
/// Intermediary manager that looks up in it's hierarchy for a <see cref="INetworkCommunicator"/> to route/broadcast it's received packets to their destinations.
 | 
					/// Intermediary manager that looks up in it's hierarchy for a <see cref="INetworkCommunicator"/> to route/broadcast it's received packets to their destinations.
 | 
				
			||||||
/// </summary>
 | 
					/// </summary>
 | 
				
			||||||
public class NetworkManager : Behaviour, INetworkManager
 | 
					public class NetworkManager : Behaviour, IEnterUniverse, IExitUniverse, INetworkManager
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private readonly Dictionary<Type, Dictionary<Type, List<MethodInfo>>> clientPacketArrivalMethods = [];
 | 
					    private readonly Dictionary<Type, Dictionary<Type, List<MethodInfo>>> clientPacketArrivalMethods = [];
 | 
				
			||||||
    private readonly Dictionary<Type, Dictionary<Type, List<MethodInfo>>> serverPacketArrivalMethods = [];
 | 
					    private readonly Dictionary<Type, Dictionary<Type, List<MethodInfo>>> serverPacketArrivalMethods = [];
 | 
				
			||||||
@@ -230,8 +230,8 @@ public class NetworkManager : Behaviour, INetworkManager
 | 
				
			|||||||
        UnregisterPacketRoutersFor(removedBehaviour, serverPacketRouters, serverPacketArrivalMethods);
 | 
					        UnregisterPacketRoutersFor(removedBehaviour, serverPacketRouters, serverPacketArrivalMethods);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe) => _networkEntityCollector.Unassign();
 | 
					    public void ExitUniverse(IUniverse universe) => _networkEntityCollector.Unassign();
 | 
				
			||||||
    protected override void OnEnteredUniverse(IUniverse universe)
 | 
					    public void EnterUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _networkEntityCollector.Assign(universe);
 | 
					        _networkEntityCollector.Assign(universe);
 | 
				
			||||||
        NetworkCommunicator = BehaviourController.GetRequiredBehaviourInParent<INetworkCommunicator>();
 | 
					        NetworkCommunicator = BehaviourController.GetRequiredBehaviourInParent<INetworkCommunicator>();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ using Engine.Core;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Time;
 | 
					namespace Engine.Systems.Time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class Stopwatch : Behaviour, IUpdate, IStopwatch
 | 
					public class Stopwatch : Behaviour, IUpdate, IEnterUniverse, IExitUniverse, IStopwatch
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public Event<IReadOnlyStopwatch> OnStarted { get; } = new();
 | 
					    public Event<IReadOnlyStopwatch> OnStarted { get; } = new();
 | 
				
			||||||
    public Event<IReadOnlyStopwatch, IReadOnlyStopwatch.StopwatchDeltaArguments> OnDelta { get; } = new();
 | 
					    public Event<IReadOnlyStopwatch, IReadOnlyStopwatch.StopwatchDeltaArguments> OnDelta { get; } = new();
 | 
				
			||||||
@@ -49,7 +49,7 @@ public class Stopwatch : Behaviour, IUpdate, IStopwatch
 | 
				
			|||||||
        OnDelta?.Invoke(this, new(delta));
 | 
					        OnDelta?.Invoke(this, new(delta));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnEnteredUniverse(IUniverse universe)
 | 
					    public void EnterUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!shouldBeTicking || State is TimerState.Ticking)
 | 
					        if (!shouldBeTicking || State is TimerState.Ticking)
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
@@ -60,7 +60,7 @@ public class Stopwatch : Behaviour, IUpdate, IStopwatch
 | 
				
			|||||||
            StartStopwatch();
 | 
					            StartStopwatch();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe)
 | 
					    public void ExitUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!shouldBeTicking || State is not TimerState.Ticking)
 | 
					        if (!shouldBeTicking || State is not TimerState.Ticking)
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
@@ -88,8 +88,10 @@ public class Stopwatch : Behaviour, IUpdate, IStopwatch
 | 
				
			|||||||
        OnStarted?.Invoke(this);
 | 
					        OnStarted?.Invoke(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnFinalize()
 | 
					    protected override void FinalizeInternal()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        base.FinalizeInternal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Time = 0f;
 | 
					        Time = 0f;
 | 
				
			||||||
        State = TimerState.Idle;
 | 
					        State = TimerState.Idle;
 | 
				
			||||||
        shouldBeTicking = false;
 | 
					        shouldBeTicking = false;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,9 +30,9 @@ public class TickerStopwatch : Stopwatch, ITicker
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnFinalize()
 | 
					    protected override void FinalizeInternal()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        base.OnFinalize();
 | 
					        base.FinalizeInternal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TickCounter = 0;
 | 
					        TickCounter = 0;
 | 
				
			||||||
        nextTick = 0f;
 | 
					        nextTick = 0f;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,9 +30,9 @@ public class TickerTimer : Timer, ITicker
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnFinalize()
 | 
					    protected override void FinalizeInternal()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        base.OnFinalize();
 | 
					        base.FinalizeInternal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TickCounter = 0;
 | 
					        TickCounter = 0;
 | 
				
			||||||
        nextTick = 0f;
 | 
					        nextTick = 0f;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ using Engine.Core;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Time;
 | 
					namespace Engine.Systems.Time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class Timer : Behaviour, IUpdate, ITimer
 | 
					public class Timer : Behaviour, IUpdate, IEnterUniverse, IExitUniverse, ITimer
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public Event<IReadOnlyTimer> OnStarted { get; } = new();
 | 
					    public Event<IReadOnlyTimer> OnStarted { get; } = new();
 | 
				
			||||||
    public Event<IReadOnlyTimer, IReadOnlyTimer.TimerDeltaArguments> OnDelta { get; } = new();
 | 
					    public Event<IReadOnlyTimer, IReadOnlyTimer.TimerDeltaArguments> OnDelta { get; } = new();
 | 
				
			||||||
@@ -67,7 +67,7 @@ public class Timer : Behaviour, IUpdate, ITimer
 | 
				
			|||||||
            Stop();
 | 
					            Stop();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnEnteredUniverse(IUniverse universe)
 | 
					    public void EnterUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!shouldBeTicking || State is TimerState.Ticking)
 | 
					        if (!shouldBeTicking || State is TimerState.Ticking)
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
@@ -78,7 +78,7 @@ public class Timer : Behaviour, IUpdate, ITimer
 | 
				
			|||||||
            StartTimer();
 | 
					            StartTimer();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe)
 | 
					    public void ExitUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!shouldBeTicking || State is not TimerState.Ticking)
 | 
					        if (!shouldBeTicking || State is not TimerState.Ticking)
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
@@ -106,8 +106,10 @@ public class Timer : Behaviour, IUpdate, ITimer
 | 
				
			|||||||
        OnStarted?.Invoke(this);
 | 
					        OnStarted?.Invoke(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnFinalize()
 | 
					    protected override void FinalizeInternal()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        base.FinalizeInternal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        StartTime = 0f;
 | 
					        StartTime = 0f;
 | 
				
			||||||
        Remaining = 0f;
 | 
					        Remaining = 0f;
 | 
				
			||||||
        State = TimerState.Idle;
 | 
					        State = TimerState.Idle;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Tween;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public static class TweenAABB2DExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static readonly BoxedPool<AABB2D> boxedAABBPool = new(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static ITween TweenAABB(this AABB2D initialAABB, ITweenManager tweenManager, float duration, AABB2D targetAABB, System.Action<AABB2D> setMethod)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Boxed<AABB2D> boxedInitial = boxedAABBPool.Get(initialAABB);
 | 
				
			||||||
 | 
					        Boxed<AABB2D> boxedTarget = boxedAABBPool.Get(targetAABB);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(new AABB2D(boxedInitial.Value.LowerBoundary.Lerp(boxedTarget.Value.LowerBoundary, t), boxedInitial.Value.UpperBoundary.Lerp(boxedTarget.Value.UpperBoundary, t))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tween.OnComplete(() =>
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boxedAABBPool.Return(boxedInitial);
 | 
				
			||||||
 | 
					            boxedAABBPool.Return(boxedTarget);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return tween;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Tween;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public static class TweenAABB3DExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static readonly BoxedPool<AABB3D> boxedAABBPool = new(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static ITween TweenAABB(this AABB3D initialAABB, ITweenManager tweenManager, float duration, AABB3D targetAABB, System.Action<AABB3D> setMethod)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Boxed<AABB3D> boxedInitial = boxedAABBPool.Get(initialAABB);
 | 
				
			||||||
 | 
					        Boxed<AABB3D> boxedTarget = boxedAABBPool.Get(targetAABB);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(new AABB3D(boxedInitial.Value.LowerBoundary.Lerp(boxedTarget.Value.LowerBoundary, t), boxedInitial.Value.UpperBoundary.Lerp(boxedTarget.Value.UpperBoundary, t))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tween.OnComplete(() =>
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boxedAABBPool.Return(boxedInitial);
 | 
				
			||||||
 | 
					            boxedAABBPool.Return(boxedTarget);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return tween;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,24 +0,0 @@
 | 
				
			|||||||
using Engine.Core;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Engine.Systems.Tween;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public static class TweenAABBExtensions
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private static readonly BoxedPool<AABB> boxedAABBPool = new(2);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static ITween TweenAABB(this AABB initialAABB, ITweenManager tweenManager, float duration, AABB targetAABB, System.Action<AABB> setMethod)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Boxed<AABB> boxedInitial = boxedAABBPool.Get(initialAABB);
 | 
					 | 
				
			||||||
        Boxed<AABB> boxedTarget = boxedAABBPool.Get(targetAABB);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(new AABB(boxedInitial.Value.LowerBoundary.Lerp(boxedTarget.Value.LowerBoundary, t), boxedInitial.Value.UpperBoundary.Lerp(boxedTarget.Value.UpperBoundary, t))));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        tween.OnComplete(() =>
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            boxedAABBPool.Return(boxedInitial);
 | 
					 | 
				
			||||||
            boxedAABBPool.Return(boxedTarget);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return tween;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Tween;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public static class TweenLine3DExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static readonly BoxedPool<Line3D> boxedLine3DPool = new(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static ITween TweenLine3D(this Line3D initialLine3D, ITweenManager tweenManager, float duration, Line3D targetLine3D, System.Action<Line3D> setMethod)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Boxed<Line3D> boxedInitial = boxedLine3DPool.Get(initialLine3D);
 | 
				
			||||||
 | 
					        Boxed<Line3D> boxedTarget = boxedLine3DPool.Get(targetLine3D);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ITween tween = tweenManager.StartTween(duration,
 | 
				
			||||||
 | 
					            t => setMethod?.Invoke(
 | 
				
			||||||
 | 
					                new Line3D(
 | 
				
			||||||
 | 
					                    boxedInitial.Value.From.Lerp(boxedTarget.Value.From, t),
 | 
				
			||||||
 | 
					                    boxedInitial.Value.To.Lerp(boxedTarget.Value.To, t)
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tween.OnComplete(() =>
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boxedLine3DPool.Return(boxedInitial);
 | 
				
			||||||
 | 
					            boxedLine3DPool.Return(boxedTarget);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return tween;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Tween;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public static class TweenRay2DExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static readonly BoxedPool<Ray2D> boxedRay2DPool = new(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static ITween TweenRay2D(this Ray2D initialRay2D, ITweenManager tweenManager, float duration, Ray2D targetRay2D, System.Action<Ray2D> setMethod)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Boxed<Ray2D> boxedInitial = boxedRay2DPool.Get(initialRay2D);
 | 
				
			||||||
 | 
					        Boxed<Ray2D> boxedTarget = boxedRay2DPool.Get(targetRay2D);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ITween tween = tweenManager.StartTween(duration,
 | 
				
			||||||
 | 
					            t => setMethod?.Invoke(
 | 
				
			||||||
 | 
					                new Ray2D(
 | 
				
			||||||
 | 
					                    boxedInitial.Value.Origin.Lerp(boxedTarget.Value.Origin, t),
 | 
				
			||||||
 | 
					                    boxedInitial.Value.Direction.Lerp(boxedTarget.Value.Direction, t).Normalized
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tween.OnComplete(() =>
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boxedRay2DPool.Return(boxedInitial);
 | 
				
			||||||
 | 
					            boxedRay2DPool.Return(boxedTarget);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return tween;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Tween;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public static class TweenRay3DExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static readonly BoxedPool<Ray3D> boxedRay3DPool = new(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static ITween TweenRay3D(this Ray3D initialRay3D, ITweenManager tweenManager, float duration, Ray3D targetRay3D, System.Action<Ray3D> setMethod)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Boxed<Ray3D> boxedInitial = boxedRay3DPool.Get(initialRay3D);
 | 
				
			||||||
 | 
					        Boxed<Ray3D> boxedTarget = boxedRay3DPool.Get(targetRay3D);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ITween tween = tweenManager.StartTween(duration,
 | 
				
			||||||
 | 
					            t => setMethod?.Invoke(
 | 
				
			||||||
 | 
					                new Ray3D(
 | 
				
			||||||
 | 
					                    boxedInitial.Value.Origin.Lerp(boxedTarget.Value.Origin, t),
 | 
				
			||||||
 | 
					                    boxedInitial.Value.Direction.Lerp(boxedTarget.Value.Direction, t).Normalized
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tween.OnComplete(() =>
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boxedRay3DPool.Return(boxedInitial);
 | 
				
			||||||
 | 
					            boxedRay3DPool.Return(boxedTarget);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return tween;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Tween;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public static class TweenSphere3DExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static readonly BoxedPool<Sphere3D> boxedSphere3DPool = new(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static ITween TweenSphere3D(this Sphere3D initialSphere3D, ITweenManager tweenManager, float duration, Sphere3D targetSphere3D, System.Action<Sphere3D> setMethod)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Boxed<Sphere3D> boxedInitial = boxedSphere3DPool.Get(initialSphere3D);
 | 
				
			||||||
 | 
					        Boxed<Sphere3D> boxedTarget = boxedSphere3DPool.Get(targetSphere3D);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ITween tween = tweenManager.StartTween(duration,
 | 
				
			||||||
 | 
					            t => setMethod?.Invoke(
 | 
				
			||||||
 | 
					                new Sphere3D(
 | 
				
			||||||
 | 
					                    boxedInitial.Value.Center.Lerp(boxedTarget.Value.Center, t),
 | 
				
			||||||
 | 
					                    boxedInitial.Value.Diameter.Lerp(boxedTarget.Value.Diameter, t)
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tween.OnComplete(() =>
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boxedSphere3DPool.Return(boxedInitial);
 | 
				
			||||||
 | 
					            boxedSphere3DPool.Return(boxedTarget);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return tween;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Systems.Tween;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public static class TweenVector4DExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private static readonly BoxedPool<Vector4D> boxedVector4DPool = new(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static ITween TweenVector4D(this Vector4D initialVector4D, ITweenManager tweenManager, float duration, Vector4D targetVector4D, System.Action<Vector4D> setMethod)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Boxed<Vector4D> boxedInitial = boxedVector4DPool.Get(initialVector4D);
 | 
				
			||||||
 | 
					        Boxed<Vector4D> boxedTarget = boxedVector4DPool.Get(targetVector4D);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(boxedInitial.Value.Lerp(boxedTarget.Value, t)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tween.OnComplete(() =>
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boxedVector4DPool.Return(boxedInitial);
 | 
				
			||||||
 | 
					            boxedVector4DPool.Return(boxedTarget);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return tween;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,7 +5,7 @@ using Engine.Core;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Systems.Tween;
 | 
					namespace Engine.Systems.Tween;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class TweenManager : Behaviour, ITweenManager
 | 
					public class TweenManager : Behaviour, IEnterUniverse, IExitUniverse, ITweenManager
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private CoroutineManager coroutineManager = null!;
 | 
					    private CoroutineManager coroutineManager = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -73,12 +73,12 @@ public class TweenManager : Behaviour, ITweenManager
 | 
				
			|||||||
        Return((Tween)tween);
 | 
					        Return((Tween)tween);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnEnteredUniverse(IUniverse universe)
 | 
					    public void EnterUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        coroutineManager = universe.FindRequiredBehaviour<CoroutineManager>();
 | 
					        coroutineManager = universe.FindRequiredBehaviour<CoroutineManager>();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected override void OnExitedUniverse(IUniverse universe)
 | 
					    public void ExitUniverse(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        coroutineManager = null!;
 | 
					        coroutineManager = null!;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user