Compare commits
	
		
			20 Commits
		
	
	
		
			4c542df401
			...
			dbd15cbbc2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| dbd15cbbc2 | |||
| e051f5cfb4 | |||
| e70b7f112f | |||
| f55ba499b6 | |||
| b75f30f864 | |||
| 6f1f30bd53 | |||
| 92a5c276a4 | |||
| 69bc6573d1 | |||
| 28bc022587 | |||
| 25db60e436 | |||
| 7c62440bba | |||
| 4bec7bce6e | |||
| 8d31372c24 | |||
| a2e704916e | |||
| c7d170fad9 | |||
| 9ccf7b754d | |||
| e3d4899112 | |||
| 566c16d09c | |||
| ae9d4f02ef | |||
| e77772cbc2 | 
							
								
								
									
										2
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,3 @@
 | 
				
			|||||||
[submodule "Engine.Integration/YamlDotNet"]
 | 
					[submodule "Engine.Integration/YamlDotNet"]
 | 
				
			||||||
	path = Engine.Integration/YamlDotNet
 | 
						path = Engine.Integration/YamlDotNet
 | 
				
			||||||
	url = git@github.com:Syntriax/YamlDotNet.git
 | 
						url = https://github.com/Syntriax/YamlDotNet.git
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,67 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Engine.Core;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class ActiveBehaviourCollectorSorted<T> : ActiveBehaviourCollector<T> where T : class, IBehaviour
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private IComparer<T>? _sortBy = null;
 | 
					 | 
				
			||||||
    public IComparer<T>? SortBy
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        get => _sortBy;
 | 
					 | 
				
			||||||
        set
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            _sortBy = value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (value is not null)
 | 
					 | 
				
			||||||
                activeBehaviours.Sort(value);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected override void AddBehaviour(T behaviour)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (SortBy is null)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            activeBehaviours.Add(behaviour);
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        int insertionIndex = activeBehaviours.BinarySearch(behaviour, SortBy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (insertionIndex < 0)
 | 
					 | 
				
			||||||
            insertionIndex = ~insertionIndex;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        activeBehaviours.Insert(insertionIndex, behaviour);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected override void OnBehaviourAdd(IBehaviour behaviour)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected override void OnBehaviourRemove(IBehaviour behaviour)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        T behaviour = (T)sender;
 | 
					 | 
				
			||||||
        activeBehaviours.Remove(behaviour);
 | 
					 | 
				
			||||||
        AddBehaviour(behaviour);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public ActiveBehaviourCollectorSorted()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        delegateOnPriorityChanged = OnPriorityChanged;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public ActiveBehaviourCollectorSorted(IUniverse universe, Comparison<T> sortBy) : base(universe)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        delegateOnPriorityChanged = OnPriorityChanged;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        SortBy = Comparer<T>.Create(sortBy);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,67 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Engine.Core;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class BehaviourCollectorSorted<T> : BehaviourCollector<T> where T : class
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private IComparer<T>? _sortBy = null;
 | 
					 | 
				
			||||||
    public IComparer<T>? SortBy
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        get => _sortBy;
 | 
					 | 
				
			||||||
        set
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            _sortBy = value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (value is not null)
 | 
					 | 
				
			||||||
                behaviours.Sort(value);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected override void AddBehaviour(T behaviour)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (SortBy is null)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            behaviours.Add(behaviour);
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        int insertionIndex = behaviours.BinarySearch(behaviour, SortBy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (insertionIndex < 0)
 | 
					 | 
				
			||||||
            insertionIndex = ~insertionIndex;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        behaviours.Insert(insertionIndex, behaviour);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected override void OnBehaviourAdd(IBehaviour behaviour)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected override void OnBehaviourRemove(IBehaviour behaviour)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        T behaviour = (T)sender;
 | 
					 | 
				
			||||||
        behaviours.Remove(behaviour);
 | 
					 | 
				
			||||||
        AddBehaviour(behaviour);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public BehaviourCollectorSorted()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        delegateOnPriorityChanged = OnPriorityChanged;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public BehaviourCollectorSorted(IUniverse universe, Comparison<T> sortBy) : base(universe)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        delegateOnPriorityChanged = OnPriorityChanged;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        SortBy = Comparer<T>.Create(sortBy);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										16
									
								
								Engine.Core/Collectors/ActiveBehaviourCollector.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Engine.Core/Collectors/ActiveBehaviourCollector.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ActiveBehaviourCollector<T> : ActiveBehaviourCollectorBase<T> where T : class, IBehaviour
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected readonly FastList<T> activeBehaviours = new(32);
 | 
				
			||||||
 | 
					    public override T this[Index index] => activeBehaviours[index];
 | 
				
			||||||
 | 
					    public override int Count => activeBehaviours.Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ActiveBehaviourCollector() { }
 | 
				
			||||||
 | 
					    public ActiveBehaviourCollector(IUniverse universe) : base(universe) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void AddBehaviour(T behaviour) => activeBehaviours.Add(behaviour);
 | 
				
			||||||
 | 
					    protected override bool RemoveBehaviour(T tBehaviour) => activeBehaviours.Remove(tBehaviour);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,12 +3,10 @@ using System.Collections.Generic;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : class, IBehaviour
 | 
					public abstract class ActiveBehaviourCollectorBase<T> : IBehaviourCollector<T> where T : class, IBehaviour
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
 | 
					    protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = new(32);
 | 
				
			||||||
    public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
 | 
					    protected readonly FastList<T> monitoringBehaviours = new(32);
 | 
				
			||||||
    public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
 | 
					 | 
				
			||||||
    public Event<IAssignable>? OnUnassigned { get; } = new();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
 | 
					    private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
 | 
				
			||||||
    private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
 | 
					    private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
 | 
				
			||||||
@@ -16,80 +14,16 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
 | 
				
			|||||||
    private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
 | 
					    private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
 | 
				
			||||||
    private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
 | 
					    private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly FastList<T> monitoringBehaviours = new(32);
 | 
					    public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
 | 
				
			||||||
    protected readonly FastList<T> activeBehaviours = new(32);
 | 
					    public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
 | 
				
			||||||
    protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = new(32);
 | 
					    public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
 | 
				
			||||||
 | 
					    public Event<IAssignable>? OnUnassigned { get; } = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public abstract int Count { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public abstract T this[Index index] { get; }
 | 
				
			||||||
    public IUniverse Universe { get; private set; } = null!;
 | 
					    public IUniverse Universe { get; private set; } = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        IUniverseObject universeObject = args.UniverseObjectRegistered;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
 | 
					 | 
				
			||||||
        universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (int i = 0; i < universeObject.BehaviourController.Count; i++)
 | 
					 | 
				
			||||||
            OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        IUniverseObject universeObject = args.UniverseObjectUnregistered;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
 | 
					 | 
				
			||||||
        universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (int i = 0; i < universeObject.BehaviourController.Count; i++)
 | 
					 | 
				
			||||||
            OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
 | 
					 | 
				
			||||||
    private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (args.BehaviourAdded is not T tBehaviour)
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        monitoringBehaviours.Add(tBehaviour);
 | 
					 | 
				
			||||||
        monitoringActiveToBehaviour.Add(tBehaviour, tBehaviour);
 | 
					 | 
				
			||||||
        tBehaviour.OnActiveChanged.AddListener(delegateOnBehaviourStateChanged);
 | 
					 | 
				
			||||||
        OnBehaviourStateChanged(tBehaviour, new(!tBehaviour.IsActive));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected virtual void AddBehaviour(T behaviour) => activeBehaviours.Add(behaviour);
 | 
					 | 
				
			||||||
    private void OnBehaviourStateChanged(IActive sender, IActive.ActiveChangedArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        T behaviour = monitoringActiveToBehaviour[sender];
 | 
					 | 
				
			||||||
        if (sender.IsActive)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            AddBehaviour(behaviour);
 | 
					 | 
				
			||||||
            OnBehaviourAdd(behaviour);
 | 
					 | 
				
			||||||
            OnCollected?.Invoke(this, new(behaviour));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (activeBehaviours.Remove(behaviour))
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            OnBehaviourRemove(behaviour);
 | 
					 | 
				
			||||||
            OnRemoved?.Invoke(this, new(behaviour));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
 | 
					 | 
				
			||||||
    private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (args.BehaviourRemoved is not T tBehaviour)
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!monitoringBehaviours.Remove(tBehaviour) || !monitoringActiveToBehaviour.Remove(tBehaviour))
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        tBehaviour.OnActiveChanged.RemoveListener(delegateOnBehaviourStateChanged);
 | 
					 | 
				
			||||||
        if (activeBehaviours.Remove(tBehaviour))
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            OnBehaviourRemove(tBehaviour);
 | 
					 | 
				
			||||||
            OnRemoved?.Invoke(this, new(tBehaviour));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public bool Assign(IUniverse universe)
 | 
					    public bool Assign(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (Universe is not null)
 | 
					        if (Universe is not null)
 | 
				
			||||||
@@ -123,10 +57,75 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
 | 
				
			|||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public int Count => activeBehaviours.Count;
 | 
					    protected abstract void AddBehaviour(T behaviour);
 | 
				
			||||||
    public T this[Index index] => activeBehaviours[index];
 | 
					    protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
 | 
				
			||||||
 | 
					    private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (args.BehaviourAdded is not T tBehaviour)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ActiveBehaviourCollector()
 | 
					        monitoringBehaviours.Add(tBehaviour);
 | 
				
			||||||
 | 
					        monitoringActiveToBehaviour.Add(tBehaviour, tBehaviour);
 | 
				
			||||||
 | 
					        tBehaviour.OnActiveChanged.AddListener(delegateOnBehaviourStateChanged);
 | 
				
			||||||
 | 
					        OnBehaviourStateChanged(tBehaviour, new(!tBehaviour.IsActive));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected abstract bool RemoveBehaviour(T behaviour);
 | 
				
			||||||
 | 
					    protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
 | 
				
			||||||
 | 
					    private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (args.BehaviourRemoved is not T tBehaviour)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!monitoringBehaviours.Remove(tBehaviour) || !monitoringActiveToBehaviour.Remove(tBehaviour))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tBehaviour.OnActiveChanged.RemoveListener(delegateOnBehaviourStateChanged);
 | 
				
			||||||
 | 
					        if (!RemoveBehaviour(tBehaviour))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnBehaviourRemove(tBehaviour);
 | 
				
			||||||
 | 
					        OnRemoved?.Invoke(this, new(tBehaviour));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    private void OnBehaviourStateChanged(IActive sender, IActive.ActiveChangedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        T behaviour = monitoringActiveToBehaviour[sender];
 | 
				
			||||||
 | 
					        if (sender.IsActive)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            AddBehaviour(behaviour);
 | 
				
			||||||
 | 
					            OnBehaviourAdd(behaviour);
 | 
				
			||||||
 | 
					            OnCollected?.Invoke(this, new(behaviour));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (RemoveBehaviour(behaviour))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            OnBehaviourRemove(behaviour);
 | 
				
			||||||
 | 
					            OnRemoved?.Invoke(this, new(behaviour));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        IUniverseObject universeObject = args.UniverseObjectRegistered;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
 | 
				
			||||||
 | 
					        universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < universeObject.BehaviourController.Count; i++)
 | 
				
			||||||
 | 
					            OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        IUniverseObject universeObject = args.UniverseObjectUnregistered;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
 | 
				
			||||||
 | 
					        universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < universeObject.BehaviourController.Count; i++)
 | 
				
			||||||
 | 
					            OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ActiveBehaviourCollectorBase()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        delegateOnBehaviourAdded = OnBehaviourAdded;
 | 
					        delegateOnBehaviourAdded = OnBehaviourAdded;
 | 
				
			||||||
        delegateOnBehaviourRemoved = OnBehaviourRemoved;
 | 
					        delegateOnBehaviourRemoved = OnBehaviourRemoved;
 | 
				
			||||||
@@ -135,7 +134,7 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
 | 
				
			|||||||
        delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
 | 
					        delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ActiveBehaviourCollector(IUniverse universe)
 | 
					    public ActiveBehaviourCollectorBase(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        delegateOnBehaviourAdded = OnBehaviourAdded;
 | 
					        delegateOnBehaviourAdded = OnBehaviourAdded;
 | 
				
			||||||
        delegateOnBehaviourRemoved = OnBehaviourRemoved;
 | 
					        delegateOnBehaviourRemoved = OnBehaviourRemoved;
 | 
				
			||||||
							
								
								
									
										104
									
								
								Engine.Core/Collectors/ActiveBehaviourCollectorOrdered.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								Engine.Core/Collectors/ActiveBehaviourCollectorOrdered.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,104 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ActiveBehaviourCollectorOrdered<TIndex, TItem> : ActiveBehaviourCollector<TItem> where TItem : class, IBehaviour where TIndex : IComparable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly SortedDictionary<TIndex, FastList<TItem>> behaviours = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly Func<TItem, TIndex> getIndexFunc = null!;
 | 
				
			||||||
 | 
					    private readonly IComparer<TIndex> sortBy = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private int count = 0;
 | 
				
			||||||
 | 
					    public override int Count => count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override TItem this[Index index]
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            int actualIndex = index.IsFromEnd
 | 
				
			||||||
 | 
					                ? count - index.Value
 | 
				
			||||||
 | 
					                : index.Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (actualIndex < 0 || actualIndex >= count)
 | 
				
			||||||
 | 
					                throw new IndexOutOfRangeException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int leftIndex = actualIndex;
 | 
				
			||||||
 | 
					            foreach ((TIndex i, FastList<TItem> list) in behaviours)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (leftIndex < list.Count)
 | 
				
			||||||
 | 
					                    return list[leftIndex];
 | 
				
			||||||
 | 
					                leftIndex -= list.Count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            throw new IndexOutOfRangeException();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override bool RemoveBehaviour(TItem tBehaviour)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        TIndex index = getIndexFunc(tBehaviour);
 | 
				
			||||||
 | 
					        if (!behaviours.TryGetValue(index, out FastList<TItem>? list))
 | 
				
			||||||
 | 
					            throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!list.Remove(tBehaviour))
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        count--;
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void AddBehaviour(TItem behaviour)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        TIndex key = getIndexFunc(behaviour);
 | 
				
			||||||
 | 
					        if (!behaviours.TryGetValue(key, out FastList<TItem>? list))
 | 
				
			||||||
 | 
					            behaviours[key] = list = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        count++;
 | 
				
			||||||
 | 
					        list.Add(behaviour);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnBehaviourAdd(IBehaviour behaviour) => behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
 | 
				
			||||||
 | 
					    protected override void OnBehaviourRemove(IBehaviour behaviour) => behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        TItem behaviour = (TItem)sender;
 | 
				
			||||||
 | 
					        RemoveBehaviour(behaviour);
 | 
				
			||||||
 | 
					        AddBehaviour(behaviour);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ActiveBehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        delegateOnPriorityChanged = OnPriorityChanged;
 | 
				
			||||||
 | 
					        this.getIndexFunc = getIndexFunc;
 | 
				
			||||||
 | 
					        this.sortBy = Comparer<TIndex>.Create(sortBy);
 | 
				
			||||||
 | 
					        behaviours = new(this.sortBy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ActiveBehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) : base(universe)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        delegateOnPriorityChanged = OnPriorityChanged;
 | 
				
			||||||
 | 
					        this.getIndexFunc = getIndexFunc;
 | 
				
			||||||
 | 
					        this.sortBy = Comparer<TIndex>.Create(sortBy);
 | 
				
			||||||
 | 
					        behaviours = new(this.sortBy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ActiveBehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this.getIndexFunc = getIndexFunc;
 | 
				
			||||||
 | 
					        delegateOnPriorityChanged = OnPriorityChanged;
 | 
				
			||||||
 | 
					        this.sortBy = sortBy;
 | 
				
			||||||
 | 
					        behaviours = new(sortBy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ActiveBehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) : base(universe)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        delegateOnPriorityChanged = OnPriorityChanged;
 | 
				
			||||||
 | 
					        this.getIndexFunc = getIndexFunc;
 | 
				
			||||||
 | 
					        this.sortBy = sortBy;
 | 
				
			||||||
 | 
					        behaviours = new(sortBy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								Engine.Core/Collectors/BehaviourCollector.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								Engine.Core/Collectors/BehaviourCollector.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class BehaviourCollector<T> : BehaviourCollectorBase<T> where T : class
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected readonly FastList<T> behaviours = new(32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override T this[Index index] => behaviours[index];
 | 
				
			||||||
 | 
					    public override int Count => behaviours.Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void AddBehaviour(T behaviour) => behaviours.Add(behaviour);
 | 
				
			||||||
 | 
					    protected override bool RemoveBehaviour(T tBehaviour) => behaviours.Remove(tBehaviour);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BehaviourCollector() { }
 | 
				
			||||||
 | 
					    public BehaviourCollector(IUniverse universe) : base(universe) { }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,70 +2,24 @@ using System;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
 | 
					public abstract class BehaviourCollectorBase<T> : IBehaviourCollector<T> where T : class
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
 | 
					 | 
				
			||||||
    public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
 | 
					 | 
				
			||||||
    public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
 | 
					 | 
				
			||||||
    public Event<IAssignable>? OnUnassigned { get; } = new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
 | 
					    private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
 | 
				
			||||||
    private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
 | 
					    private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
 | 
				
			||||||
    private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
 | 
					    private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
 | 
				
			||||||
    private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
 | 
					    private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected readonly FastList<T> behaviours = new(32);
 | 
					    public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
 | 
				
			||||||
 | 
					    public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
 | 
				
			||||||
 | 
					    public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
 | 
				
			||||||
 | 
					    public Event<IAssignable>? OnUnassigned { get; } = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public IUniverse Universe { get; private set; } = null!;
 | 
					    public IUniverse Universe { get; private set; } = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
 | 
					    public abstract int Count { get; }
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        IUniverseObject universeObject = args.UniverseObjectRegistered;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
 | 
					    public abstract T this[Index index] { get; }
 | 
				
			||||||
        universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (int i = 0; i < universeObject.BehaviourController.Count; i++)
 | 
					 | 
				
			||||||
            OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        IUniverseObject universeObject = args.UniverseObjectUnregistered;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
 | 
					 | 
				
			||||||
        universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (int i = 0; i < universeObject.BehaviourController.Count; i++)
 | 
					 | 
				
			||||||
            OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected virtual void AddBehaviour(T behaviour) => behaviours.Add(behaviour);
 | 
					 | 
				
			||||||
    protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
 | 
					 | 
				
			||||||
    private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (args.BehaviourAdded is not T tBehaviour)
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        AddBehaviour(tBehaviour);
 | 
					 | 
				
			||||||
        OnBehaviourAdd(args.BehaviourAdded);
 | 
					 | 
				
			||||||
        OnCollected?.Invoke(this, new(tBehaviour));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
 | 
					 | 
				
			||||||
    private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (args.BehaviourRemoved is not T tBehaviour)
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!behaviours.Remove(tBehaviour))
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        OnBehaviourRemove(args.BehaviourRemoved);
 | 
					 | 
				
			||||||
        OnRemoved?.Invoke(this, new(tBehaviour));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected virtual void OnAssign(IUniverse universe) { }
 | 
					 | 
				
			||||||
    public bool Assign(IUniverse universe)
 | 
					    public bool Assign(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (Universe is not null)
 | 
					        if (Universe is not null)
 | 
				
			||||||
@@ -100,10 +54,57 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
 | 
				
			|||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public int Count => behaviours.Count;
 | 
					    protected virtual void OnAssign(IUniverse universe) { }
 | 
				
			||||||
    public T this[Index index] => behaviours[index];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public BehaviourCollector()
 | 
					    protected abstract void AddBehaviour(T behaviour);
 | 
				
			||||||
 | 
					    protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
 | 
				
			||||||
 | 
					    private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (args.BehaviourAdded is not T tBehaviour)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        AddBehaviour(tBehaviour);
 | 
				
			||||||
 | 
					        OnBehaviourAdd(args.BehaviourAdded);
 | 
				
			||||||
 | 
					        OnCollected?.Invoke(this, new(tBehaviour));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected abstract bool RemoveBehaviour(T tBehaviour);
 | 
				
			||||||
 | 
					    protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
 | 
				
			||||||
 | 
					    private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (args.BehaviourRemoved is not T tBehaviour)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!RemoveBehaviour(tBehaviour))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OnBehaviourRemove(args.BehaviourRemoved);
 | 
				
			||||||
 | 
					        OnRemoved?.Invoke(this, new(tBehaviour));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        IUniverseObject universeObject = args.UniverseObjectRegistered;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
 | 
				
			||||||
 | 
					        universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < universeObject.BehaviourController.Count; i++)
 | 
				
			||||||
 | 
					            OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        IUniverseObject universeObject = args.UniverseObjectUnregistered;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
 | 
				
			||||||
 | 
					        universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < universeObject.BehaviourController.Count; i++)
 | 
				
			||||||
 | 
					            OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BehaviourCollectorBase()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        delegateOnBehaviourAdded = OnBehaviourAdded;
 | 
					        delegateOnBehaviourAdded = OnBehaviourAdded;
 | 
				
			||||||
        delegateOnBehaviourRemoved = OnBehaviourRemoved;
 | 
					        delegateOnBehaviourRemoved = OnBehaviourRemoved;
 | 
				
			||||||
@@ -111,7 +112,7 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
 | 
				
			|||||||
        delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
 | 
					        delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public BehaviourCollector(IUniverse universe)
 | 
					    public BehaviourCollectorBase(IUniverse universe)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        delegateOnBehaviourAdded = OnBehaviourAdded;
 | 
					        delegateOnBehaviourAdded = OnBehaviourAdded;
 | 
				
			||||||
        delegateOnBehaviourRemoved = OnBehaviourRemoved;
 | 
					        delegateOnBehaviourRemoved = OnBehaviourRemoved;
 | 
				
			||||||
							
								
								
									
										104
									
								
								Engine.Core/Collectors/BehaviourCollectorOrdered.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								Engine.Core/Collectors/BehaviourCollectorOrdered.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,104 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class BehaviourCollectorOrdered<TIndex, TItem> : BehaviourCollectorBase<TItem> where TItem : class where TIndex : IComparable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly SortedDictionary<TIndex, FastList<TItem>> behaviours = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly Func<TItem, TIndex> getIndexFunc = null!;
 | 
				
			||||||
 | 
					    private readonly IComparer<TIndex> sortBy = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private int count = 0;
 | 
				
			||||||
 | 
					    public override int Count => count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override TItem this[Index index]
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            int actualIndex = index.IsFromEnd
 | 
				
			||||||
 | 
					                ? count - index.Value
 | 
				
			||||||
 | 
					                : index.Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (actualIndex < 0 || actualIndex >= count)
 | 
				
			||||||
 | 
					                throw new IndexOutOfRangeException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int leftIndex = actualIndex;
 | 
				
			||||||
 | 
					            foreach ((TIndex i, FastList<TItem> list) in behaviours)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (leftIndex < list.Count)
 | 
				
			||||||
 | 
					                    return list[leftIndex];
 | 
				
			||||||
 | 
					                leftIndex -= list.Count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            throw new IndexOutOfRangeException();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override bool RemoveBehaviour(TItem tBehaviour)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        TIndex index = getIndexFunc(tBehaviour);
 | 
				
			||||||
 | 
					        if (!behaviours.TryGetValue(index, out FastList<TItem>? list))
 | 
				
			||||||
 | 
					            throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!list.Remove(tBehaviour))
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        count--;
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void AddBehaviour(TItem behaviour)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        TIndex key = getIndexFunc(behaviour);
 | 
				
			||||||
 | 
					        if (!behaviours.TryGetValue(key, out FastList<TItem>? list))
 | 
				
			||||||
 | 
					            behaviours[key] = list = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        count++;
 | 
				
			||||||
 | 
					        list.Add(behaviour);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected override void OnBehaviourAdd(IBehaviour behaviour) => behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
 | 
				
			||||||
 | 
					    protected override void OnBehaviourRemove(IBehaviour behaviour) => behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        TItem behaviour = (TItem)sender;
 | 
				
			||||||
 | 
					        RemoveBehaviour(behaviour);
 | 
				
			||||||
 | 
					        AddBehaviour(behaviour);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        delegateOnPriorityChanged = OnPriorityChanged;
 | 
				
			||||||
 | 
					        this.getIndexFunc = getIndexFunc;
 | 
				
			||||||
 | 
					        this.sortBy = Comparer<TIndex>.Create(sortBy);
 | 
				
			||||||
 | 
					        behaviours = new(this.sortBy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) : base(universe)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        delegateOnPriorityChanged = OnPriorityChanged;
 | 
				
			||||||
 | 
					        this.getIndexFunc = getIndexFunc;
 | 
				
			||||||
 | 
					        this.sortBy = Comparer<TIndex>.Create(sortBy);
 | 
				
			||||||
 | 
					        behaviours = new(this.sortBy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this.getIndexFunc = getIndexFunc;
 | 
				
			||||||
 | 
					        delegateOnPriorityChanged = OnPriorityChanged;
 | 
				
			||||||
 | 
					        this.sortBy = sortBy;
 | 
				
			||||||
 | 
					        behaviours = new(sortBy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) : base(universe)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        delegateOnPriorityChanged = OnPriorityChanged;
 | 
				
			||||||
 | 
					        this.getIndexFunc = getIndexFunc;
 | 
				
			||||||
 | 
					        this.sortBy = sortBy;
 | 
				
			||||||
 | 
					        behaviours = new(sortBy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,17 +3,30 @@ using System.Collections.Generic;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class FastList<T> : IReadOnlyList<T>, IEnumerable<T> where T : notnull
 | 
					public class FastList<T> : IList<T>, IReadOnlyList<T>, IEnumerable<T> where T : notnull
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private readonly List<T> items = [];
 | 
					    private readonly List<T> items = [];
 | 
				
			||||||
    private readonly Dictionary<T, int> indexMap = [];
 | 
					    private readonly Dictionary<T, int> indexMap = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public bool IsReadOnly { get; set; } = false;
 | 
				
			||||||
    public int Count => items.Count;
 | 
					    public int Count => items.Count;
 | 
				
			||||||
 | 
					    public T this[int index]
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get => items[index];
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (IsReadOnly)
 | 
				
			||||||
 | 
					                throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public T this[int index] => items[index];
 | 
					            items[index] = value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void Add(T item)
 | 
					    public void Add(T item)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if (IsReadOnly)
 | 
				
			||||||
 | 
					            throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        indexMap[item] = items.Count;
 | 
					        indexMap[item] = items.Count;
 | 
				
			||||||
        items.Add(item);
 | 
					        items.Add(item);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -21,6 +34,9 @@ public class FastList<T> : IReadOnlyList<T>, IEnumerable<T> where T : notnull
 | 
				
			|||||||
    public void RemoveAt(int i) => Remove(items[i], i);
 | 
					    public void RemoveAt(int i) => Remove(items[i], i);
 | 
				
			||||||
    public bool Remove(T item)
 | 
					    public bool Remove(T item)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if (IsReadOnly)
 | 
				
			||||||
 | 
					            throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!indexMap.TryGetValue(item, out int index))
 | 
					        if (!indexMap.TryGetValue(item, out int index))
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -43,6 +59,9 @@ public class FastList<T> : IReadOnlyList<T>, IEnumerable<T> where T : notnull
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public void Insert(int index, T item)
 | 
					    public void Insert(int index, T item)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if (IsReadOnly)
 | 
				
			||||||
 | 
					            throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        items.Insert(index, item);
 | 
					        items.Insert(index, item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (int i = index; i < items.Count; i++)
 | 
					        for (int i = index; i < items.Count; i++)
 | 
				
			||||||
@@ -51,21 +70,30 @@ public class FastList<T> : IReadOnlyList<T>, IEnumerable<T> where T : notnull
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public void Clear()
 | 
					    public void Clear()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if (IsReadOnly)
 | 
				
			||||||
 | 
					            throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        items.Clear();
 | 
					        items.Clear();
 | 
				
			||||||
        indexMap.Clear();
 | 
					        indexMap.Clear();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public bool Contains(T item) => indexMap.ContainsKey(item);
 | 
					    public bool Contains(T item) => indexMap.ContainsKey(item);
 | 
				
			||||||
 | 
					    public int IndexOf(T item) => items.IndexOf(item);
 | 
				
			||||||
    public int BinarySearch(T item, IComparer<T>? comparer = null) => items.BinarySearch(item, comparer);
 | 
					    public int BinarySearch(T item, IComparer<T>? comparer = null) => items.BinarySearch(item, comparer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void Sort(IComparer<T> comparer)
 | 
					    public void Sort(IComparer<T> comparer)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if (IsReadOnly)
 | 
				
			||||||
 | 
					            throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        items.Sort(comparer);
 | 
					        items.Sort(comparer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (int i = 0; i < items.Count; i++)
 | 
					        for (int i = 0; i < items.Count; i++)
 | 
				
			||||||
            indexMap[items[i]] = i;
 | 
					            indexMap[items[i]] = i;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void CopyTo(T[] array, int arrayIndex) => items.CopyTo(array, arrayIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
 | 
					    public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
 | 
				
			||||||
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 | 
					    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										172
									
								
								Engine.Core/Helpers/FastListOrdered.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								Engine.Core/Helpers/FastListOrdered.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,172 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// TODO This is VEERY experimental, and doesn't work well with the indices access. Use with caution
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					/// <typeparam name="TIndex"></typeparam>
 | 
				
			||||||
 | 
					/// <typeparam name="TItem"></typeparam>
 | 
				
			||||||
 | 
					public class FastListOrdered<TIndex, TItem> : IList<TItem>, IReadOnlyList<TItem>, IEnumerable<TItem> where TItem : notnull where TIndex : IComparable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private readonly SortedDictionary<TIndex, FastList<TItem>> items = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly Func<TItem, TIndex> getIndexFunc = null!;
 | 
				
			||||||
 | 
					    private readonly IComparer<TIndex> sortBy = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private int count = 0;
 | 
				
			||||||
 | 
					    public int Count => count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public bool IsReadOnly { get; set; } = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public TItem this[int index]
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get { (TIndex tIndex, int i) = GetAt(index); return items[tIndex][i]; }
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (IsReadOnly)
 | 
				
			||||||
 | 
					                throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					            (TIndex tIndex, int i) = GetAt(index); items[tIndex][i] = value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private (TIndex TIndex, int i) GetAt(Index index)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int actualIndex = index.IsFromEnd
 | 
				
			||||||
 | 
					                ? count - index.Value
 | 
				
			||||||
 | 
					                : index.Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (actualIndex < 0 || actualIndex >= count)
 | 
				
			||||||
 | 
					            throw new IndexOutOfRangeException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int leftIndex = actualIndex;
 | 
				
			||||||
 | 
					        foreach ((TIndex i, FastList<TItem> list) in items)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (leftIndex < list.Count)
 | 
				
			||||||
 | 
					                return (i, leftIndex);
 | 
				
			||||||
 | 
					            leftIndex -= list.Count;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        throw new IndexOutOfRangeException();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public int IndexOf(TItem item)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int indexCounter = 0;
 | 
				
			||||||
 | 
					        foreach ((TIndex index, FastList<TItem> list) in items)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            int i = list.IndexOf(item);
 | 
				
			||||||
 | 
					            if (i != -1)
 | 
				
			||||||
 | 
					                return indexCounter + i;
 | 
				
			||||||
 | 
					            indexCounter += list.Count;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Add(TItem item)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (IsReadOnly)
 | 
				
			||||||
 | 
					            throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TIndex key = getIndexFunc(item);
 | 
				
			||||||
 | 
					        if (!items.TryGetValue(key, out FastList<TItem>? list))
 | 
				
			||||||
 | 
					            items[key] = list = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        list.Add(item);
 | 
				
			||||||
 | 
					        count++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Insert(int index, TItem item)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (IsReadOnly)
 | 
				
			||||||
 | 
					            throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TIndex tIndex = getIndexFunc(item);
 | 
				
			||||||
 | 
					        if (!items.TryGetValue(tIndex, out FastList<TItem>? list))
 | 
				
			||||||
 | 
					            items[tIndex] = list = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        list.Insert(index, item);
 | 
				
			||||||
 | 
					        count++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public bool Remove(TItem item)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (IsReadOnly)
 | 
				
			||||||
 | 
					            throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TIndex index = getIndexFunc(item);
 | 
				
			||||||
 | 
					        if (!items.TryGetValue(index, out FastList<TItem>? list))
 | 
				
			||||||
 | 
					            throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!list.Remove(item))
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        count--;
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void RemoveAt(int index)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (IsReadOnly)
 | 
				
			||||||
 | 
					            throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        (TIndex tIndex, int i) = GetAt(index);
 | 
				
			||||||
 | 
					        items[tIndex].RemoveAt(i);
 | 
				
			||||||
 | 
					        count--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Clear()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (IsReadOnly)
 | 
				
			||||||
 | 
					            throw new System.Data.ReadOnlyException();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach ((TIndex index, FastList<TItem> list) in items)
 | 
				
			||||||
 | 
					            list.Clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        count = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public bool Contains(TItem item)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        foreach ((TIndex index, FastList<TItem> list) in items)
 | 
				
			||||||
 | 
					            if (list.Contains(item))
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void CopyTo(TItem[] array, int arrayIndex)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int indexCounter = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach ((TIndex index, FastList<TItem> list) in items)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            list.CopyTo(array, indexCounter);
 | 
				
			||||||
 | 
					            indexCounter += list.Count;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public IEnumerator<TItem> GetEnumerator()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        foreach ((TIndex index, FastList<TItem> list) in items)
 | 
				
			||||||
 | 
					            foreach (TItem item in list)
 | 
				
			||||||
 | 
					                yield return item;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public FastListOrdered(Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this.getIndexFunc = getIndexFunc;
 | 
				
			||||||
 | 
					        this.sortBy = Comparer<TIndex>.Create(sortBy);
 | 
				
			||||||
 | 
					        items = new(this.sortBy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public FastListOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this.getIndexFunc = getIndexFunc;
 | 
				
			||||||
 | 
					        this.sortBy = sortBy;
 | 
				
			||||||
 | 
					        items = new(sortBy);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -240,21 +240,33 @@ public static class Math
 | 
				
			|||||||
    public static T Lerp<T>(T x, T y, T t) where T : IFloatingPoint<T> => x + (y - x) * t;
 | 
					    public static T Lerp<T>(T x, T y, T t) where T : IFloatingPoint<T> => x + (y - x) * t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Rounds a number to a specified number of fractional digits.
 | 
					    /// Rounds a number to the closest integer.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="x">The number to round.</param>
 | 
					    /// <param name="x">The number to round.</param>
 | 
				
			||||||
    /// <param name="digits">The number of fractional digits in the return value.</param>
 | 
					    /// <param name="roundMode">Specification for how to round <paramref name="x"/> if it is midway between two other numbers.</param>
 | 
				
			||||||
    /// <param name="mode">Specification for how to round <paramref name="x"/> if it is midway between two other numbers.</param>
 | 
					    /// <returns>The number <paramref name="x"/> rounded to the closest integer.</returns>
 | 
				
			||||||
    /// <returns>The number <paramref name="x"/> rounded to <paramref name="digits"/> fractional digits.</returns>
 | 
					    public static float Round(float x, RoundMode roundMode) => RoundToInt(x, roundMode);
 | 
				
			||||||
    public static float Round(float x, int digits, MidpointRounding mode) => MathF.Round(x, digits, mode);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Rounds a number to an integer.
 | 
					    /// Rounds a number to the closest integer.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="x">The number to round.</param>
 | 
					    /// <param name="x">The number to round.</param>
 | 
				
			||||||
    /// <param name="roundMode">Specification for how to round <paramref name="x"/> if it's midway between two numbers</param>
 | 
					    /// <param name="roundMode">Specification for how to round <paramref name="x"/> if it's midway between two numbers</param>
 | 
				
			||||||
    /// <returns></returns>
 | 
					    /// <returns>The number <paramref name="x"/> rounded to the closest integer.</returns>
 | 
				
			||||||
    public static int RoundToInt(float x, RoundMode roundMode = RoundMode.Ceil) => (int)MathF.Round(x, 0, roundMode == RoundMode.Ceil ? MidpointRounding.ToPositiveInfinity : MidpointRounding.ToNegativeInfinity);
 | 
					    public static int RoundToInt(float x, RoundMode roundMode = RoundMode.Ceil)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        float remainder = x.Mod(1f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (remainder == .5f)
 | 
				
			||||||
 | 
					            if (roundMode == RoundMode.Floor)
 | 
				
			||||||
 | 
					                return (int)x;
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                return (int)(x + .5f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (x < 0f)
 | 
				
			||||||
 | 
					            return (int)(x - .5f);
 | 
				
			||||||
 | 
					        return (int)(x + .5f);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    public enum RoundMode { Ceil, Floor };
 | 
					    public enum RoundMode { Ceil, Floor };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,7 +81,7 @@ public static class MathExtensions
 | 
				
			|||||||
    public static T Lerp<T>(this T x, T y, T t) where T : IFloatingPoint<T> => Math.Lerp(x, y, t);
 | 
					    public static T Lerp<T>(this T x, T y, T t) where T : IFloatingPoint<T> => Math.Lerp(x, y, t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc cref="Math.Round(float, int, MidpointRounding)" />
 | 
					    /// <inheritdoc cref="Math.Round(float, int, MidpointRounding)" />
 | 
				
			||||||
    public static float Round(this float x, int digits, MidpointRounding mode) => Math.Round(x, digits, mode);
 | 
					    public static float Round(this float x, Math.RoundMode mode) => Math.Round(x, mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <inheritdoc cref="Math.RoundToInt(float, Math.RoundMode)" />
 | 
					    /// <inheritdoc cref="Math.RoundToInt(float, Math.RoundMode)" />
 | 
				
			||||||
    public static int RoundToInt(this float x, Math.RoundMode roundMode = Math.RoundMode.Ceil) => Math.RoundToInt(x, roundMode);
 | 
					    public static int RoundToInt(this float x, Math.RoundMode roundMode = Math.RoundMode.Ceil) => Math.RoundToInt(x, roundMode);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
@@ -11,7 +12,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="AABB"/> struct with the specified lower and upper boundaries.
 | 
					/// Initializes a new instance of the <see cref="AABB"/> struct with the specified lower and upper boundaries.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("LowerBoundary: {LowerBoundary.ToString(), nq}, UpperBoundary: {UpperBoundary.ToString(), nq}")]
 | 
					[System.Diagnostics.DebuggerDisplay("LowerBoundary: {LowerBoundary.ToString(), nq}, UpperBoundary: {UpperBoundary.ToString(), nq}")]
 | 
				
			||||||
public readonly struct AABB(Vector2D lowerBoundary, Vector2D upperBoundary)
 | 
					public readonly struct AABB(Vector2D lowerBoundary, Vector2D upperBoundary) : IEquatable<AABB>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The lower boundary of the <see cref="AABB"/>.
 | 
					    /// The lower boundary of the <see cref="AABB"/>.
 | 
				
			||||||
@@ -82,6 +83,7 @@ public readonly struct AABB(Vector2D lowerBoundary, Vector2D upperBoundary)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="AABB"/>.</param>
 | 
					    /// <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>
 | 
					    /// <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 override bool Equals(object? obj) => obj is AABB aabb && this == aabb;
 | 
				
			||||||
 | 
					    public bool Equals(AABB other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="AABB"/>.
 | 
					    /// Generates a hash code for the <see cref="AABB"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
using System.Diagnostics;
 | 
					using System.Diagnostics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
@@ -11,7 +12,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="Circle"/> struct with the specified center and radius.
 | 
					/// Initializes a new instance of the <see cref="Circle"/> struct with the specified center and radius.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[DebuggerDisplay("Center: {Center.ToString(),nq}, Radius: {Radius}")]
 | 
					[DebuggerDisplay("Center: {Center.ToString(),nq}, Radius: {Radius}")]
 | 
				
			||||||
public readonly struct Circle(Vector2D center, float radius)
 | 
					public readonly struct Circle(Vector2D center, float radius) : IEquatable<Circle>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The center of the circle.
 | 
					    /// The center of the circle.
 | 
				
			||||||
@@ -87,6 +88,7 @@ public readonly struct Circle(Vector2D center, float radius)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="Circle"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Circle"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Circle"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Circle"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is Circle circle && this == circle;
 | 
					    public override bool Equals(object? obj) => obj is Circle circle && this == circle;
 | 
				
			||||||
 | 
					    public bool Equals(Circle other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="Circle"/>.
 | 
					    /// Generates a hash code for the <see cref="Circle"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -10,7 +12,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="ColorHSV"/> struct with the specified values.
 | 
					/// Initializes a new instance of the <see cref="ColorHSV"/> struct with the specified values.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
 | 
					[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
 | 
				
			||||||
public readonly struct ColorHSV(float hue, float saturation, float value)
 | 
					public readonly struct ColorHSV(float hue, float saturation, float value) : IEquatable<ColorHSV>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The Hue value of the <see cref="ColorHSV"/>.
 | 
					    /// The Hue value of the <see cref="ColorHSV"/>.
 | 
				
			||||||
@@ -112,6 +114,7 @@ public readonly struct ColorHSV(float hue, float saturation, float value)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="ColorHSV"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="ColorHSV"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="ColorHSV"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="ColorHSV"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is ColorHSV colorHSV && this == colorHSV;
 | 
					    public override bool Equals(object? obj) => obj is ColorHSV colorHSV && this == colorHSV;
 | 
				
			||||||
 | 
					    public bool Equals(ColorHSV other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="ColorHSV"/>.
 | 
					    /// Generates a hash code for the <see cref="ColorHSV"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -11,7 +13,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="ColorHSVA"/> struct with the specified values.
 | 
					/// Initializes a new instance of the <see cref="ColorHSVA"/> struct with the specified values.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
 | 
					[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
 | 
				
			||||||
public readonly struct ColorHSVA(float hue, float saturation, float value, float alpha = 1)
 | 
					public readonly struct ColorHSVA(float hue, float saturation, float value, float alpha = 1) : IEquatable<ColorHSVA>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The Hue value of the <see cref="ColorHSVA"/>.
 | 
					    /// The Hue value of the <see cref="ColorHSVA"/>.
 | 
				
			||||||
@@ -150,6 +152,7 @@ public readonly struct ColorHSVA(float hue, float saturation, float value, float
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="ColorHSVA"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="ColorHSVA"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="ColorHSVA"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="ColorHSVA"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is ColorHSVA colorHSVA && this == colorHSVA;
 | 
					    public override bool Equals(object? obj) => obj is ColorHSVA colorHSVA && this == colorHSVA;
 | 
				
			||||||
 | 
					    public bool Equals(ColorHSVA other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="ColorHSVA"/>.
 | 
					    /// Generates a hash code for the <see cref="ColorHSVA"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -10,7 +12,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="ColorRGB"/> struct with the specified values.
 | 
					/// Initializes a new instance of the <see cref="ColorRGB"/> struct with the specified values.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
 | 
					[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
 | 
				
			||||||
public readonly struct ColorRGB(byte r, byte g, byte b)
 | 
					public readonly struct ColorRGB(byte r, byte g, byte b) : IEquatable<ColorRGB>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The Red value of the <see cref="ColorRGB"/>.
 | 
					    /// The Red value of the <see cref="ColorRGB"/>.
 | 
				
			||||||
@@ -102,6 +104,7 @@ public readonly struct ColorRGB(byte r, byte g, byte b)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="ColorRGB"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="ColorRGB"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="ColorRGB"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="ColorRGB"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is ColorRGB colorRGB && this == colorRGB;
 | 
					    public override bool Equals(object? obj) => obj is ColorRGB colorRGB && this == colorRGB;
 | 
				
			||||||
 | 
					    public bool Equals(ColorRGB other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="ColorRGB"/>.
 | 
					    /// Generates a hash code for the <see cref="ColorRGB"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -11,7 +13,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="ColorRGBA"/> struct with the specified values.
 | 
					/// Initializes a new instance of the <see cref="ColorRGBA"/> struct with the specified values.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
 | 
					[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
 | 
				
			||||||
public readonly struct ColorRGBA(byte r, byte g, byte b, byte a = 255)
 | 
					public readonly struct ColorRGBA(byte r, byte g, byte b, byte a = 255) : IEquatable<ColorRGBA>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The Red value of the <see cref="ColorRGBA"/>.
 | 
					    /// The Red value of the <see cref="ColorRGBA"/>.
 | 
				
			||||||
@@ -132,6 +134,7 @@ public readonly struct ColorRGBA(byte r, byte g, byte b, byte a = 255)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="ColorRGBA"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="ColorRGBA"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="ColorRGBA"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="ColorRGBA"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is ColorRGBA colorRGBA && this == colorRGBA;
 | 
					    public override bool Equals(object? obj) => obj is ColorRGBA colorRGBA && this == colorRGBA;
 | 
				
			||||||
 | 
					    public bool Equals(ColorRGBA other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="ColorRGBA"/>.
 | 
					    /// Generates a hash code for the <see cref="ColorRGBA"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
using System.Diagnostics.CodeAnalysis;
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
@@ -11,7 +12,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="Line2D"/> struct with the specified endpoints.
 | 
					/// Initializes a new instance of the <see cref="Line2D"/> struct with the specified endpoints.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("From: {From.ToString(),nq}, To: {To.ToString(),nq}, Direction: {Direction.ToString(),nq}, Length: {Length}")]
 | 
					[System.Diagnostics.DebuggerDisplay("From: {From.ToString(),nq}, To: {To.ToString(),nq}, Direction: {Direction.ToString(),nq}, Length: {Length}")]
 | 
				
			||||||
public readonly struct Line2D(Vector2D from, Vector2D to)
 | 
					public readonly struct Line2D(Vector2D from, Vector2D to) : IEquatable<Line2D>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The starting point of the <see cref="Line2D"/> segment.
 | 
					    /// The starting point of the <see cref="Line2D"/> segment.
 | 
				
			||||||
@@ -196,6 +197,7 @@ public readonly struct Line2D(Vector2D from, Vector2D to)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="Line2D"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Line2D"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Line2D"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Line2D"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is Line2D line2D && this == line2D;
 | 
					    public override bool Equals(object? obj) => obj is Line2D line2D && this == line2D;
 | 
				
			||||||
 | 
					    public bool Equals(Line2D other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="Line2D"/>.
 | 
					    /// Generates a hash code for the <see cref="Line2D"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -9,7 +11,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="Line2DEquation"/> struct with the specified slope and Y intercept.
 | 
					/// Initializes a new instance of the <see cref="Line2DEquation"/> struct with the specified slope and Y intercept.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("y = {Slope}x + {OffsetY}")]
 | 
					[System.Diagnostics.DebuggerDisplay("y = {Slope}x + {OffsetY}")]
 | 
				
			||||||
public readonly struct Line2DEquation(float slope, float offsetY)
 | 
					public readonly struct Line2DEquation(float slope, float offsetY) : IEquatable<Line2DEquation>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The slope of the <see cref="Line2DEquation"/>.
 | 
					    /// The slope of the <see cref="Line2DEquation"/>.
 | 
				
			||||||
@@ -48,6 +50,7 @@ public readonly struct Line2DEquation(float slope, float offsetY)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="Line2DEquation"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Line2DEquation"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Line2DEquation"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Line2DEquation"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is Line2DEquation lineEquation && this == lineEquation;
 | 
					    public override bool Equals(object? obj) => obj is Line2DEquation lineEquation && this == lineEquation;
 | 
				
			||||||
 | 
					    public bool Equals(Line2DEquation other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="Line2DEquation"/>.
 | 
					    /// Generates a hash code for the <see cref="Line2DEquation"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -9,7 +11,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="Projection1D"/> struct with the specified minimum and maximum values.
 | 
					/// Initializes a new instance of the <see cref="Projection1D"/> struct with the specified minimum and maximum values.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("Min: {Min}, Max: {Max}")]
 | 
					[System.Diagnostics.DebuggerDisplay("Min: {Min}, Max: {Max}")]
 | 
				
			||||||
public readonly struct Projection1D(float min, float max)
 | 
					public readonly struct Projection1D(float min, float max) : IEquatable<Projection1D>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Gets the minimum value of the projection.
 | 
					    /// Gets the minimum value of the projection.
 | 
				
			||||||
@@ -90,6 +92,7 @@ public readonly struct Projection1D(float min, float max)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="Projection1D"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Projection1D"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Projection1D"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Projection1D"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is Projection1D projection1D && this == projection1D;
 | 
					    public override bool Equals(object? obj) => obj is Projection1D projection1D && this == projection1D;
 | 
				
			||||||
 | 
					    public bool Equals(Projection1D other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="Projection1D"/>.
 | 
					    /// Generates a hash code for the <see cref="Projection1D"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -11,7 +13,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="Quaternion"/> struct with the specified positions.
 | 
					/// Initializes a new instance of the <see cref="Quaternion"/> struct with the specified positions.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("{ToString(),nq}, Length: {Magnitude}, LengthSquared: {MagnitudeSquared}, Normalized: {Normalized.ToString(),nq}")]
 | 
					[System.Diagnostics.DebuggerDisplay("{ToString(),nq}, Length: {Magnitude}, LengthSquared: {MagnitudeSquared}, Normalized: {Normalized.ToString(),nq}")]
 | 
				
			||||||
public readonly struct Quaternion(float x, float y, float z, float w)
 | 
					public readonly struct Quaternion(float x, float y, float z, float w) : IEquatable<Quaternion>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The X(i) imaginary of the <see cref="Quaternion"/>.
 | 
					    /// The X(i) imaginary of the <see cref="Quaternion"/>.
 | 
				
			||||||
@@ -288,6 +290,7 @@ public readonly struct Quaternion(float x, float y, float z, float w)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="Quaternion"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Quaternion"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Quaternion"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Quaternion"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is Quaternion quaternion && this == quaternion;
 | 
					    public override bool Equals(object? obj) => obj is Quaternion quaternion && this == quaternion;
 | 
				
			||||||
 | 
					    public bool Equals(Quaternion other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="Quaternion"/>.
 | 
					    /// Generates a hash code for the <see cref="Quaternion"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -5,7 +7,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// </summary>
 | 
					/// </summary>
 | 
				
			||||||
/// <param name="Origin">The <see cref="Vector2D"/> in 2D space where the ray starts from.</param>
 | 
					/// <param name="Origin">The <see cref="Vector2D"/> in 2D space where the ray starts from.</param>
 | 
				
			||||||
/// <param name="Direction">Normalized <see cref="Vector2D"/> indicating the ray's is direction.</param> 
 | 
					/// <param name="Direction">Normalized <see cref="Vector2D"/> indicating the ray's is direction.</param> 
 | 
				
			||||||
public readonly struct Ray2D(Vector2D Origin, Vector2D Direction)
 | 
					public readonly struct Ray2D(Vector2D Origin, Vector2D Direction) : IEquatable<Ray2D>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The starting point of the <see cref="Ray2D"/>.
 | 
					    /// The starting point of the <see cref="Ray2D"/>.
 | 
				
			||||||
@@ -72,6 +74,7 @@ public readonly struct Ray2D(Vector2D Origin, Vector2D Direction)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="Ray2D"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Ray2D"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Ray2D"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Ray2D"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is Ray2D ray2D && this == ray2D;
 | 
					    public override bool Equals(object? obj) => obj is Ray2D ray2D && this == ray2D;
 | 
				
			||||||
 | 
					    public bool Equals(Ray2D other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="Ray2D"/>.
 | 
					    /// Generates a hash code for the <see cref="Ray2D"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,9 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("A: {A.ToString(), nq}, B: {B.ToString(), nq}, B: {C.ToString(), nq}")]
 | 
					[System.Diagnostics.DebuggerDisplay("A: {A.ToString(), nq}, B: {B.ToString(), nq}, B: {C.ToString(), nq}")]
 | 
				
			||||||
public readonly struct Triangle(Vector2D A, Vector2D B, Vector2D C)
 | 
					public readonly struct Triangle(Vector2D A, Vector2D B, Vector2D C) : IEquatable<Triangle>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public readonly Vector2D A { get; init; } = A;
 | 
					    public readonly Vector2D A { get; init; } = A;
 | 
				
			||||||
    public readonly Vector2D B { get; init; } = B;
 | 
					    public readonly Vector2D B { get; init; } = B;
 | 
				
			||||||
@@ -54,6 +56,7 @@ public readonly struct Triangle(Vector2D A, Vector2D B, Vector2D C)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="Triangle"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Triangle"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Triangle"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Triangle"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is Triangle triangle && this == triangle;
 | 
					    public override bool Equals(object? obj) => obj is Triangle triangle && this == triangle;
 | 
				
			||||||
 | 
					    public bool Equals(Triangle other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="Triangle"/>.
 | 
					    /// Generates a hash code for the <see cref="Triangle"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -9,7 +11,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="Vector2D"/> struct with the specified positions.
 | 
					/// Initializes a new instance of the <see cref="Vector2D"/> struct with the specified positions.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("{ToString(),nq}, Length: {Magnitude}, LengthSquared: {MagnitudeSquared}, Normalized: {Normalized.ToString(),nq}")]
 | 
					[System.Diagnostics.DebuggerDisplay("{ToString(),nq}, Length: {Magnitude}, LengthSquared: {MagnitudeSquared}, Normalized: {Normalized.ToString(),nq}")]
 | 
				
			||||||
public readonly struct Vector2D(float x, float y)
 | 
					public readonly struct Vector2D(float x, float y) : IEquatable<Vector2D>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The X coordinate of the <see cref="Vector2D"/>.
 | 
					    /// The X coordinate of the <see cref="Vector2D"/>.
 | 
				
			||||||
@@ -82,6 +84,7 @@ public readonly struct Vector2D(float x, float y)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public static implicit operator System.Numerics.Vector2(Vector2D vector) => new(vector.X, vector.Y);
 | 
					    public static implicit operator System.Numerics.Vector2(Vector2D vector) => new(vector.X, vector.Y);
 | 
				
			||||||
    public static implicit operator Vector2D(System.Numerics.Vector2 vector) => new(vector.X, vector.Y);
 | 
					    public static implicit operator Vector2D(System.Numerics.Vector2 vector) => new(vector.X, vector.Y);
 | 
				
			||||||
 | 
					    public static implicit operator Vector2D(Vector2DInt vector) => new(vector.X, vector.Y);
 | 
				
			||||||
    public static implicit operator Vector2D(Vector3D vector) => new(vector.X, vector.Y);
 | 
					    public static implicit operator Vector2D(Vector3D vector) => new(vector.X, vector.Y);
 | 
				
			||||||
    public static implicit operator Vector2D(System.Numerics.Vector3 vector) => new(vector.X, vector.Y);
 | 
					    public static implicit operator Vector2D(System.Numerics.Vector3 vector) => new(vector.X, vector.Y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -308,6 +311,7 @@ public readonly struct Vector2D(float x, float y)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="Vector2D"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Vector2D"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Vector2D"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Vector2D"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is Vector2D vector2D && this == vector2D;
 | 
					    public override bool Equals(object? obj) => obj is Vector2D vector2D && this == vector2D;
 | 
				
			||||||
 | 
					    public bool Equals(Vector2D other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="Vector2D"/>.
 | 
					    /// Generates a hash code for the <see cref="Vector2D"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										306
									
								
								Engine.Core/Primitives/Vector2DInt.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								Engine.Core/Primitives/Vector2DInt.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,306 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Represents a two-dimensional integer vector.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					/// <param name="x">X position of the <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					/// <param name="y">Y position of the <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					/// <remarks>
 | 
				
			||||||
 | 
					/// Initializes a new instance of the <see cref="Vector2DInt"/> struct with the specified positions.
 | 
				
			||||||
 | 
					/// </remarks>
 | 
				
			||||||
 | 
					[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
 | 
				
			||||||
 | 
					public readonly struct Vector2DInt(int x, int y) : IEquatable<Vector2DInt>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The X coordinate of the <see cref="Vector2DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly int X = x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The Y coordinate of the <see cref="Vector2DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly int Y = y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The magnitude (length) of the <see cref="Vector2DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public float Magnitude => Length(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The squared magnitude (length) of the <see cref="Vector2DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public float MagnitudeSquared => LengthSquared(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Gets a <see cref="Vector2DInt"/> with the direction reversed.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly Vector2DInt Reversed => -this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit <see cref="Vector2DInt"/> pointing upwards.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector2DInt Up = new(0, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit <see cref="Vector2DInt"/> pointing downwards.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector2DInt Down = new(0, -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit <see cref="Vector2DInt"/> pointing leftwards.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector2DInt Left = new(-1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit <see cref="Vector2DInt"/> pointing rightwards.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector2DInt Right = new(1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the zero <see cref="Vector2DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector2DInt Zero = new(0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the <see cref="Vector2DInt"/> with both components equal to 1.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector2DInt One = new(1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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 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 implicit operator Vector2DInt(Vector2D vector) => new(vector.X.RoundToInt(), vector.Y.RoundToInt());
 | 
				
			||||||
 | 
					    public static implicit operator Vector2DInt(Vector3DInt vector) => new(vector.X, vector.Y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the length of the <see cref="Vector2DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The length of the <see cref="Vector2DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public static float Length(Vector2DInt vector) => Engine.Core.Math.Sqrt(LengthSquared(vector));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the squared length of the <see cref="Vector2DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The squared length of the <see cref="Vector2DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public static float LengthSquared(Vector2DInt vector) => vector.X * vector.X + vector.Y * vector.Y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the distance between two <see cref="Vector2DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="from">The start <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="to">The end <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The distance between the two <see cref="Vector2DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static float Distance(Vector2DInt from, Vector2DInt to) => Length(FromTo(from, to));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Inverts the direction of the <see cref="Vector2DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The inverted <see cref="Vector2DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public static Vector2DInt Invert(Vector2DInt vector) => -vector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Adds two <see cref="Vector2DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The sum of the two <see cref="Vector2DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static Vector2DInt Add(Vector2DInt left, Vector2DInt right) => left + right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Subtracts one <see cref="Vector2DInt"/> from another.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The <see cref="Vector2DInt"/> to subtract from.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The <see cref="Vector2DInt"/> to subtract.</param>
 | 
				
			||||||
 | 
					    /// <returns>The result of subtracting the second <see cref="Vector2DInt"/> from the first.</returns>
 | 
				
			||||||
 | 
					    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>
 | 
				
			||||||
 | 
					    /// Calculates the absolute value of each component of the vector.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector2DInt"/> with each component's absolute value.</returns>
 | 
				
			||||||
 | 
					    public static Vector2DInt Abs(Vector2DInt vector) => new(Engine.Core.Math.Abs(vector.X), Engine.Core.Math.Abs(vector.Y));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the <see cref="Vector2DInt"/> from one point to another.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="from">The starting point.</param>
 | 
				
			||||||
 | 
					    /// <param name="to">The ending point.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector2DInt"/> from the starting point to the ending point.</returns>
 | 
				
			||||||
 | 
					    public static Vector2DInt FromTo(Vector2DInt from, Vector2DInt to) => to - from;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Scales a <see cref="Vector2DInt"/> by another <see cref="Vector2DInt"/> component-wise.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector2DInt"/> to scale.</param>
 | 
				
			||||||
 | 
					    /// <param name="scale">The <see cref="Vector2DInt"/> containing the scaling factors for each component.</param>
 | 
				
			||||||
 | 
					    /// <returns>The scaled <see cref="Vector2DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public static Vector2DInt Scale(Vector2DInt vector, Vector2DInt scale) => new(vector.X * scale.X, vector.Y * scale.Y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates a perpendicular <see cref="Vector2DInt"/> to the given <see cref="Vector2DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The input <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>A <see cref="Vector2DInt"/> perpendicular to the input <see cref="Vector2DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public static Vector2DInt Perpendicular(Vector2DInt vector) => new(-vector.Y, vector.X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Returns the component-wise minimum of two <see cref="Vector2DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector2DInt"/> containing the minimum components from both input <see cref="Vector2DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static Vector2DInt Min(Vector2DInt left, Vector2DInt right) => new((left.X < right.X) ? left.X : right.X, (left.Y < right.Y) ? left.Y : right.Y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Returns the component-wise maximum of two <see cref="Vector2DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector2DInt"/> containing the maximum components from both input <see cref="Vector2DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static Vector2DInt Max(Vector2DInt left, Vector2DInt right) => new((left.X > right.X) ? left.X : right.X, (left.Y > right.Y) ? left.Y : right.Y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Clamps each component of a <see cref="Vector2DInt"/> between the corresponding component of two other <see cref="Vector2DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector2DInt"/> to clamp.</param>
 | 
				
			||||||
 | 
					    /// <param name="min">The <see cref="Vector2DInt"/> representing the minimum values for each component.</param>
 | 
				
			||||||
 | 
					    /// <param name="max">The <see cref="Vector2DInt"/> representing the maximum values for each component.</param>
 | 
				
			||||||
 | 
					    /// <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));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <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>
 | 
				
			||||||
 | 
					    /// Calculates the cross product of two <see cref="Vector2DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The cross product of the two <see cref="Vector2DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static int Cross(Vector2DInt left, Vector2DInt right) => left.X * right.Y - left.Y * right.X;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the dot product of two <see cref="Vector2DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The dot product of the two <see cref="Vector2DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static int Dot(Vector2DInt left, Vector2DInt right) => left.X * right.X + left.Y * right.Y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Determines whether the specified object is equal to the current <see cref="Vector2DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Vector2DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Vector2DInt"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public override bool Equals(object? obj) => obj is Vector2DInt vector2DInt && this == vector2DInt;
 | 
				
			||||||
 | 
					    public bool Equals(Vector2DInt other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Generates a hash code for the <see cref="Vector2DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A hash code for the <see cref="Vector2DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public override int GetHashCode() => System.HashCode.Combine(X, Y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Converts the <see cref="Vector2DInt"/> to its string representation.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A string representation of the <see cref="Vector2DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public override string ToString() => $"{nameof(Vector2DInt)}({X}, {Y})";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Provides extension methods for <see cref="Vector2DInt"/> type.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public static class Vector2DIntExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.Length(Vector2DInt)" />
 | 
				
			||||||
 | 
					    public static float Length(this Vector2DInt vector) => Vector2DInt.Length(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.LengthSquared(this vector) => Vector2DInt/>
 | 
				
			||||||
 | 
					    public static float LengthSquared(this Vector2DInt vector) => Vector2DInt.LengthSquared(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.Distance(Vector2DInt, Vector2DInt)" />
 | 
				
			||||||
 | 
					    public static float Distance(this Vector2DInt from, Vector2DInt to) => Vector2DInt.Distance(from, to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.Invert(this vector) => Vector2DInt/>
 | 
				
			||||||
 | 
					    public static Vector2DInt Invert(this Vector2DInt vector) => Vector2DInt.Invert(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.Add(Vector2DInt, Vector2DInt)" />
 | 
				
			||||||
 | 
					    public static Vector2DInt Add(this Vector2DInt vector, Vector2DInt vectorToAdd) => Vector2DInt.Add(vector, vectorToAdd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.Subtract(Vector2DInt, Vector2DInt)" />
 | 
				
			||||||
 | 
					    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)" />
 | 
				
			||||||
 | 
					    public static Vector2DInt Abs(this Vector2DInt vector) => Vector2DInt.Abs(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.FromTo(Vector2DInt, Vector2DInt)" />
 | 
				
			||||||
 | 
					    public static Vector2DInt FromTo(this Vector2DInt from, Vector2DInt to) => Vector2DInt.FromTo(from, to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.Scale(Vector2DInt, Vector2DInt)" />
 | 
				
			||||||
 | 
					    public static Vector2DInt Scale(this Vector2DInt vector, Vector2DInt scale) => Vector2DInt.Scale(vector, scale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.Perpendicular(Vector2DInt)" />
 | 
				
			||||||
 | 
					    public static Vector2DInt Perpendicular(this Vector2DInt vector) => Vector2DInt.Perpendicular(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.Min(Vector2DInt, Vector2DInt)" />
 | 
				
			||||||
 | 
					    public static Vector2DInt Min(this Vector2DInt left, Vector2DInt right) => Vector2DInt.Min(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.Max(Vector2DInt, Vector2DInt)" />
 | 
				
			||||||
 | 
					    public static Vector2DInt Max(this Vector2DInt left, Vector2DInt right) => Vector2DInt.Max(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.Clamp(Vector2DInt, Vector2DInt,Vector2DInt)" />
 | 
				
			||||||
 | 
					    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)" />
 | 
				
			||||||
 | 
					    public static int Cross(this Vector2DInt left, Vector2DInt right) => Vector2DInt.Cross(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2D.Angle(Vector2D, Vector2D)" />
 | 
				
			||||||
 | 
					    public static float AngleBetween(this Vector2D left, Vector2D right) => Vector2D.Angle(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector2DInt.Dot(Vector2DInt, Vector2DInt)" />
 | 
				
			||||||
 | 
					    public static int Dot(this Vector2DInt left, Vector2DInt right) => Vector2DInt.Dot(left, right);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -10,7 +12,7 @@ namespace Engine.Core;
 | 
				
			|||||||
/// Initializes a new instance of the <see cref="Vector3D"/> struct with the specified positions.
 | 
					/// Initializes a new instance of the <see cref="Vector3D"/> struct with the specified positions.
 | 
				
			||||||
/// </remarks>
 | 
					/// </remarks>
 | 
				
			||||||
[System.Diagnostics.DebuggerDisplay("{ToString(),nq}, Length: {Magnitude}, LengthSquared: {MagnitudeSquared}, Normalized: {Normalized.ToString(),nq}")]
 | 
					[System.Diagnostics.DebuggerDisplay("{ToString(),nq}, Length: {Magnitude}, LengthSquared: {MagnitudeSquared}, Normalized: {Normalized.ToString(),nq}")]
 | 
				
			||||||
public readonly struct Vector3D(float x, float y, float z)
 | 
					public readonly struct Vector3D(float x, float y, float z) : IEquatable<Vector3D>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// The X coordinate of the <see cref="Vector3D"/>.
 | 
					    /// The X coordinate of the <see cref="Vector3D"/>.
 | 
				
			||||||
@@ -92,6 +94,7 @@ public readonly struct Vector3D(float x, float y, float z)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public static implicit operator System.Numerics.Vector3(Vector3D vector) => new(vector.X, vector.Y, vector.Z);
 | 
					    public static implicit operator System.Numerics.Vector3(Vector3D vector) => new(vector.X, vector.Y, vector.Z);
 | 
				
			||||||
    public static implicit operator Vector3D(System.Numerics.Vector3 vector) => new(vector.X, vector.Y, vector.Z);
 | 
					    public static implicit operator Vector3D(System.Numerics.Vector3 vector) => new(vector.X, vector.Y, vector.Z);
 | 
				
			||||||
 | 
					    public static implicit operator Vector3D(Vector3DInt vector) => new(vector.X, vector.Y, vector.Z);
 | 
				
			||||||
    public static implicit operator Vector3D(Vector2D vector) => new(vector.X, vector.Y, 0f);
 | 
					    public static implicit operator Vector3D(Vector2D vector) => new(vector.X, vector.Y, 0f);
 | 
				
			||||||
    public static implicit operator Vector3D(System.Numerics.Vector2 vector) => new(vector.X, vector.Y, 0f);
 | 
					    public static implicit operator Vector3D(System.Numerics.Vector2 vector) => new(vector.X, vector.Y, 0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -277,6 +280,7 @@ public readonly struct Vector3D(float x, float y, float z)
 | 
				
			|||||||
    /// <param name="obj">The object to compare with the current <see cref="Vector3D"/>.</param>
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Vector3D"/>.</param>
 | 
				
			||||||
    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Vector3D"/>; otherwise, <see cref="false"/>.</returns>
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Vector3D"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
    public override bool Equals(object? obj) => obj is Vector3D vector3D && this == vector3D;
 | 
					    public override bool Equals(object? obj) => obj is Vector3D vector3D && this == vector3D;
 | 
				
			||||||
 | 
					    public bool Equals(Vector3D other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Generates a hash code for the <see cref="Vector3D"/>.
 | 
					    /// Generates a hash code for the <see cref="Vector3D"/>.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										314
									
								
								Engine.Core/Primitives/Vector3DInt.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										314
									
								
								Engine.Core/Primitives/Vector3DInt.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,314 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Represents a three-dimensional integer vector.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					/// <param name="x">X position of the <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					/// <param name="y">Y position of the <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					/// <param name="z">Z position of the <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					/// <remarks>
 | 
				
			||||||
 | 
					/// Initializes a new instance of the <see cref="Vector3DInt"/> struct with the specified positions.
 | 
				
			||||||
 | 
					/// </remarks>
 | 
				
			||||||
 | 
					[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
 | 
				
			||||||
 | 
					public readonly struct Vector3DInt(int x, int y, int z) : IEquatable<Vector3DInt>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The X coordinate of the <see cref="Vector3DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly int X = x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The Y coordinate of the <see cref="Vector3DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly int Y = y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The Z coordinate of the <see cref="Vector3DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly int Z = z;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The magnitude (length) of the <see cref="Vector3DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public float Magnitude => Length(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// The squared magnitude (length) of the <see cref="Vector3DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public float MagnitudeSquared => LengthSquared(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit <see cref="Vector3DInt"/> pointing upwards.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector3DInt Up = new(0, 1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit <see cref="Vector3DInt"/> pointing downwards.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector3DInt Down = new(0, -1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit <see cref="Vector3DInt"/> pointing leftwards.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector3DInt Left = new(-1, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit <see cref="Vector3DInt"/> pointing rightwards.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector3DInt Right = new(1, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit <see cref="Vector3DInt"/> pointing forwards.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector3DInt Forward = new(0, 0, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the unit <see cref="Vector3DInt"/> pointing backwards.
 | 
				
			||||||
 | 
					    public readonly static Vector3DInt Backward = new(0, 0, -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the zero <see cref="Vector3DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector3DInt Zero = new(0, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Represents the <see cref="Vector3DInt"/> with both components equal to 1.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public readonly static Vector3DInt One = new(1, 1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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 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 implicit operator Vector3DInt(Vector3D vector) => new(vector.X.RoundToInt(), vector.Y.RoundToInt(), vector.Z.RoundToInt());
 | 
				
			||||||
 | 
					    public static implicit operator Vector3DInt(Vector2DInt vector) => new(vector.X, vector.Y, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the length of the <see cref="Vector3DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The length of the <see cref="Vector3DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public static float Length(Vector3DInt vector) => Math.Sqrt(LengthSquared(vector));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the squared length of the <see cref="Vector3DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The squared length of the <see cref="Vector3DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public static float LengthSquared(Vector3DInt vector) => vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the distance between two <see cref="Vector3DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="from">The start <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="to">The end <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The distance between the two <see cref="Vector3DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static float Distance(Vector3DInt from, Vector3DInt to) => Length(FromTo(from, to));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Inverts the direction of the <see cref="Vector3DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The inverted <see cref="Vector3DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public static Vector3DInt Invert(Vector3DInt vector) => -vector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Adds two <see cref="Vector3DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The sum of the two <see cref="Vector3DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static Vector3DInt Add(Vector3DInt left, Vector3DInt right) => left + right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Subtracts one <see cref="Vector3DInt"/> from another.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The <see cref="Vector3DInt"/> to subtract from.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The <see cref="Vector3DInt"/> to subtract.</param>
 | 
				
			||||||
 | 
					    /// <returns>The result of subtracting the second <see cref="Vector3DInt"/> from the first.</returns>
 | 
				
			||||||
 | 
					    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>
 | 
				
			||||||
 | 
					    /// Calculates the absolute value of each component of the vector.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector3DInt"/> with each component's absolute value.</returns>
 | 
				
			||||||
 | 
					    public static Vector3DInt Abs(Vector3DInt vector) => new(Math.Abs(vector.X), Math.Abs(vector.Y), Math.Abs(vector.Z));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the <see cref="Vector3DInt"/> from one point to another.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="from">The starting point.</param>
 | 
				
			||||||
 | 
					    /// <param name="to">The ending point.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector3DInt"/> from the starting point to the ending point.</returns>
 | 
				
			||||||
 | 
					    public static Vector3DInt FromTo(Vector3DInt from, Vector3DInt to) => to - from;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Scales a <see cref="Vector3DInt"/> by another <see cref="Vector3DInt"/> component-wise.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector3DInt"/> to scale.</param>
 | 
				
			||||||
 | 
					    /// <param name="scale">The <see cref="Vector3DInt"/> containing the scaling factors for each component.</param>
 | 
				
			||||||
 | 
					    /// <returns>The scaled <see cref="Vector3DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public static Vector3DInt Scale(Vector3DInt vector, Vector3DInt scale) => new(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Returns the component-wise minimum of two <see cref="Vector3DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector3DInt"/> containing the minimum components from both input <see cref="Vector3DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static Vector3DInt Min(Vector3DInt left, Vector3DInt 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Returns the component-wise maximum of two <see cref="Vector3DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The <see cref="Vector3DInt"/> containing the maximum components from both input <see cref="Vector3DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static Vector3DInt Max(Vector3DInt left, Vector3DInt 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Clamps each component of a <see cref="Vector3DInt"/> between the corresponding component of two other <see cref="Vector3DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="vector">The <see cref="Vector3DInt"/> to clamp.</param>
 | 
				
			||||||
 | 
					    /// <param name="min">The <see cref="Vector3DInt"/> representing the minimum values for each component.</param>
 | 
				
			||||||
 | 
					    /// <param name="max">The <see cref="Vector3DInt"/> representing the maximum values for each component.</param>
 | 
				
			||||||
 | 
					    /// <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));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <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>
 | 
				
			||||||
 | 
					    /// Calculates the cross product of two <see cref="Vector3DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The cross product of the two <see cref="Vector3DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static Vector3DInt Cross(Vector3DInt left, Vector3DInt right) => new(left.Y * right.Z - left.Z * right.Y, left.Z * right.X - left.X * right.Z, left.X * right.Y - left.Y * right.X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the angle between two <see cref="Vector3DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The angle between the two <see cref="Vector3DInt"/>s in radians.</returns>
 | 
				
			||||||
 | 
					    public static float Angle(Vector3DInt left, Vector3DInt right) => Math.Acos(Dot(left, right) / (Length(left) * Length(right)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Calculates the dot product of two <see cref="Vector3DInt"/>s.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="left">The first <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <param name="right">The second <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns>The dot product of the two <see cref="Vector3DInt"/>s.</returns>
 | 
				
			||||||
 | 
					    public static int Dot(Vector3DInt left, Vector3DInt right) => left.X * right.X + left.Y * right.Y + left.Z * right.Z;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Determines whether the specified object is equal to the current <see cref="Vector3DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="obj">The object to compare with the current <see cref="Vector3DInt"/>.</param>
 | 
				
			||||||
 | 
					    /// <returns><see cref="true"/> if the specified object is equal to the current <see cref="Vector3DInt"/>; otherwise, <see cref="false"/>.</returns>
 | 
				
			||||||
 | 
					    public override bool Equals(object? obj) => obj is Vector3DInt vector3D && this == vector3D;
 | 
				
			||||||
 | 
					    public bool Equals(Vector3DInt other) => this == other;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Generates a hash code for the <see cref="Vector3DInt"/>.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A hash code for the <see cref="Vector3DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public override int GetHashCode() => System.HashCode.Combine(X, Y, Z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Converts the <see cref="Vector3DInt"/> to its string representation.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <returns>A string representation of the <see cref="Vector3DInt"/>.</returns>
 | 
				
			||||||
 | 
					    public override string ToString() => $"{nameof(Vector3DInt)}({X}, {Y}, {Z})";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// <summary>
 | 
				
			||||||
 | 
					/// Provides extension methods for <see cref="Vector3DInt"/> type.
 | 
				
			||||||
 | 
					/// </summary>
 | 
				
			||||||
 | 
					public static class Vector3DIntExtensions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.Length(Vector3DInt)" />
 | 
				
			||||||
 | 
					    public static float Length(this Vector3DInt vector) => Vector3DInt.Length(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.LengthSquared(Vector3DInt)" />
 | 
				
			||||||
 | 
					    public static float LengthSquared(this Vector3DInt vector) => Vector3DInt.LengthSquared(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.Distance(Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
 | 
					    public static float Distance(this Vector3DInt from, Vector3DInt to) => Vector3DInt.Distance(from, to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.Invert(Vector3DInt)" />
 | 
				
			||||||
 | 
					    public static Vector3DInt Invert(this Vector3DInt vector) => Vector3DInt.Invert(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.Add(Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
 | 
					    public static Vector3DInt Add(this Vector3DInt vector, Vector3DInt vectorToAdd) => Vector3DInt.Add(vector, vectorToAdd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.Subtract(Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
 | 
					    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)" />
 | 
				
			||||||
 | 
					    public static Vector3DInt Abs(this Vector3DInt vector) => Vector3DInt.Abs(vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.FromTo(Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
 | 
					    public static Vector3DInt FromTo(this Vector3DInt from, Vector3DInt to) => Vector3DInt.FromTo(from, to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.Scale(Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
 | 
					    public static Vector3DInt Scale(this Vector3DInt vector, Vector3DInt scale) => Vector3DInt.Scale(vector, scale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.Min(Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
 | 
					    public static Vector3DInt Min(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Min(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.Max(Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
 | 
					    public static Vector3DInt Max(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Max(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.Clamp(Vector3DInt, Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
 | 
					    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)" />
 | 
				
			||||||
 | 
					    public static Vector3DInt Cross(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Cross(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.Angle(Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
 | 
					    public static float AngleBetween(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Angle(left, right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <inheritdoc cref="Vector3DInt.Dot(Vector3DInt, Vector3DInt)" />
 | 
				
			||||||
 | 
					    public static int Dot(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Dot(left, right);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,11 +5,12 @@ namespace Engine.Core;
 | 
				
			|||||||
public class DrawManager : Behaviour
 | 
					public class DrawManager : Behaviour
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // 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<IBehaviour> SortByDescendingPriority() => Comparer<IBehaviour>.Create((x, y) => y.Priority.CompareTo(x.Priority));
 | 
					    private static Comparer<int> SortByDescendingPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
 | 
				
			||||||
 | 
					    private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<IPreDraw> preDrawEntities = new() { SortBy = SortByDescendingPriority() };
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, IPreDraw> preDrawEntities = new(GetPriority(), SortByDescendingPriority());
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<IDraw> drawEntities = new() { SortBy = SortByDescendingPriority() };
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, IDraw> drawEntities = new(GetPriority(), SortByDescendingPriority());
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<IPostDraw> postDrawEntities = new() { SortBy = SortByDescendingPriority() };
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, IPostDraw> postDrawEntities = new(GetPriority(), SortByDescendingPriority());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void OnPreDraw(IUniverse sender)
 | 
					    private void OnPreDraw(IUniverse sender)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,10 +5,11 @@ namespace Engine.Core;
 | 
				
			|||||||
public class UniverseEntranceManager : Behaviour
 | 
					public class UniverseEntranceManager : Behaviour
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // 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<IBehaviour> SortByAscendingPriority() => Comparer<IBehaviour>.Create((x, y) => x.Priority.CompareTo(y.Priority));
 | 
					    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
				
			||||||
 | 
					    private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<IEnterUniverse> enterUniverses = new() { SortBy = SortByAscendingPriority() };
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, IEnterUniverse> enterUniverses = new(GetPriority(), SortByAscendingPriority());
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<IExitUniverse> exitUniverses = new() { SortBy = SortByAscendingPriority() };
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, IExitUniverse> exitUniverses = new(GetPriority(), SortByAscendingPriority());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly List<IEnterUniverse> toCallEnterUniverses = new(32);
 | 
					    private readonly List<IEnterUniverse> toCallEnterUniverses = new(32);
 | 
				
			||||||
    private readonly List<IExitUniverse> toCallExitUniverses = new(32);
 | 
					    private readonly List<IExitUniverse> toCallExitUniverses = new(32);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,3 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
@@ -6,13 +5,14 @@ namespace Engine.Core;
 | 
				
			|||||||
public class UpdateManager : Behaviour
 | 
					public class UpdateManager : Behaviour
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // 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<IBehaviour> SortByAscendingPriority() => Comparer<IBehaviour>.Create((x, y) => x.Priority.CompareTo(y.Priority));
 | 
					    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
				
			||||||
 | 
					    private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<IFirstFrameUpdate> firstFrameUpdates = new() { SortBy = SortByAscendingPriority() };
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, IFirstFrameUpdate> firstFrameUpdates = new(GetPriority(), SortByAscendingPriority());
 | 
				
			||||||
    private readonly ActiveBehaviourCollector<ILastFrameUpdate> lastFrameUpdates = new();
 | 
					    private readonly ActiveBehaviourCollector<ILastFrameUpdate> lastFrameUpdates = new();
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<IPreUpdate> preUpdateEntities = new() { SortBy = SortByAscendingPriority() };
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, IPreUpdate> preUpdateEntities = new(GetPriority(), SortByAscendingPriority());
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<IUpdate> updateEntities = new() { SortBy = SortByAscendingPriority() };
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, IUpdate> updateEntities = new(GetPriority(), SortByAscendingPriority());
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<IPostUpdate> postUpdateEntities = new() { SortBy = SortByAscendingPriority() };
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, IPostUpdate> postUpdateEntities = new(GetPriority(), SortByAscendingPriority());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly List<IFirstFrameUpdate> toCallFirstFrameUpdates = new(32);
 | 
					    private readonly List<IFirstFrameUpdate> toCallFirstFrameUpdates = new(32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ public class Universe : BaseEntity, IUniverse
 | 
				
			|||||||
    private readonly Event<IInitializable>.EventHandler delegateOnUniverseObjectFinalize = null!;
 | 
					    private readonly Event<IInitializable>.EventHandler delegateOnUniverseObjectFinalize = null!;
 | 
				
			||||||
    private readonly Event<IUniverseObject, IUniverseObject.ExitedUniverseArguments>.EventHandler delegateOnUniverseObjectExitedUniverse = null!;
 | 
					    private readonly Event<IUniverseObject, IUniverseObject.ExitedUniverseArguments>.EventHandler delegateOnUniverseObjectExitedUniverse = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly List<IUniverseObject> _universeObjects = new(Constants.UNIVERSE_OBJECTS_SIZE_INITIAL);
 | 
					    private readonly FastList<IUniverseObject> _universeObjects = new(Constants.UNIVERSE_OBJECTS_SIZE_INITIAL);
 | 
				
			||||||
    private float _timeScale = 1f;
 | 
					    private float _timeScale = 1f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Universe()
 | 
					    public Universe()
 | 
				
			||||||
@@ -131,9 +131,10 @@ public class Universe : BaseEntity, IUniverse
 | 
				
			|||||||
        UnscaledTime = engineTime;
 | 
					        UnscaledTime = engineTime;
 | 
				
			||||||
        Time = new(TimeSpan.FromTicks((long)(Time.TimeSinceStart.Ticks + engineTime.DeltaSpan.Ticks * TimeScale)), TimeSpan.FromTicks((long)(engineTime.DeltaSpan.Ticks * TimeScale)));
 | 
					        Time = new(TimeSpan.FromTicks((long)(Time.TimeSinceStart.Ticks + engineTime.DeltaSpan.Ticks * TimeScale)), TimeSpan.FromTicks((long)(engineTime.DeltaSpan.Ticks * TimeScale)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        OnPreUpdate?.Invoke(this, new(Time));
 | 
					        IUniverse.UpdateArguments args = new(Time);
 | 
				
			||||||
        OnUpdate?.Invoke(this, new(Time));
 | 
					        OnPreUpdate?.Invoke(this, args);
 | 
				
			||||||
        OnPostUpdate?.Invoke(this, new(Time));
 | 
					        OnUpdate?.Invoke(this, args);
 | 
				
			||||||
 | 
					        OnPostUpdate?.Invoke(this, args);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void Draw()
 | 
					    public void Draw()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,7 @@ public class UniverseObject : BaseEntity, IUniverseObject
 | 
				
			|||||||
    private IUniverse _universe = null!;
 | 
					    private IUniverse _universe = null!;
 | 
				
			||||||
    private IBehaviourController _behaviourController = null!;
 | 
					    private IBehaviourController _behaviourController = null!;
 | 
				
			||||||
    private bool _isActive = false;
 | 
					    private bool _isActive = false;
 | 
				
			||||||
    private readonly List<IUniverseObject> _children = [];
 | 
					    private readonly FastList<IUniverseObject> _children = [];
 | 
				
			||||||
    private IUniverseObject? _parent = null;
 | 
					    private IUniverseObject? _parent = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public IReadOnlyList<IUniverseObject> Children => _children;
 | 
					    public IReadOnlyList<IUniverseObject> Children => _children;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ using System;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Engine.Core;
 | 
					namespace Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public readonly struct UniverseTime(TimeSpan TimeSinceStart, TimeSpan TimeDelta)
 | 
					public readonly record struct UniverseTime(TimeSpan TimeSinceStart, TimeSpan TimeDelta)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public readonly TimeSpan TimeSinceStart = TimeSinceStart;
 | 
					    public readonly TimeSpan TimeSinceStart = TimeSinceStart;
 | 
				
			||||||
    public readonly TimeSpan DeltaSpan = TimeDelta;
 | 
					    public readonly TimeSpan DeltaSpan = TimeDelta;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using Engine.Core;
 | 
					using Engine.Core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Engine.Integration.MonoGame;
 | 
					namespace Engine.Integration.MonoGame;
 | 
				
			||||||
@@ -6,9 +7,10 @@ namespace Engine.Integration.MonoGame;
 | 
				
			|||||||
public class LoadContentManager : Behaviour, IFirstFrameUpdate
 | 
					public class LoadContentManager : Behaviour, 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<IBehaviour> SortByAscendingPriority() => Comparer<IBehaviour>.Create((x, y) => x.Priority.CompareTo(y.Priority));
 | 
					    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
				
			||||||
 | 
					    private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<ILoadContent> loadContents = new() { SortBy = SortByAscendingPriority() };
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, ILoadContent> loadContents = new(GetPriority(), SortByAscendingPriority());
 | 
				
			||||||
    private readonly List<ILoadContent> toCallLoadContents = new(32);
 | 
					    private readonly List<ILoadContent> toCallLoadContents = new(32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private MonoGameWindowContainer monoGameWindowContainer = null!;
 | 
					    private MonoGameWindowContainer monoGameWindowContainer = null!;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,12 +6,13 @@ namespace Engine.Integration.MonoGame;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class SpriteBatcher : BehaviourBase, IFirstFrameUpdate, IDraw
 | 
					public class SpriteBatcher : BehaviourBase, IFirstFrameUpdate, IDraw
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private static Comparer<IBehaviour> SortByPriority() => Comparer<IBehaviour>.Create((x, y) => y.Priority.CompareTo(x.Priority));
 | 
					    private static Comparer<int> SortByPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
 | 
				
			||||||
 | 
					    private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private ISpriteBatch spriteBatch = null!;
 | 
					    private ISpriteBatch spriteBatch = null!;
 | 
				
			||||||
    private MonoGameCamera2D camera2D = null!;
 | 
					    private MonoGameCamera2D camera2D = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<IDrawableSprite> drawableSprites = new() { SortBy = SortByPriority() };
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, IDrawableSprite> drawableSprites = new(GetPriority(), SortByPriority());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void FirstActiveFrame()
 | 
					    public void FirstActiveFrame()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,11 +8,13 @@ namespace Engine.Integration.MonoGame;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class TriangleBatcher : BehaviourBase, ITriangleBatch, IFirstFrameUpdate, IDraw
 | 
					public class TriangleBatcher : BehaviourBase, ITriangleBatch, IFirstFrameUpdate, IDraw
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private static Comparer<IBehaviour> SortByAscendingPriority() => Comparer<IBehaviour>.Create((x, y) => x.Priority.CompareTo(y.Priority));
 | 
					    private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
 | 
				
			||||||
 | 
					    private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private TriangleBatch triangleBatch = null!;
 | 
					    private TriangleBatch triangleBatch = null!;
 | 
				
			||||||
    private MonoGameCamera2D camera2D = null!;
 | 
					    private MonoGameCamera2D camera2D = null!;
 | 
				
			||||||
    private readonly ActiveBehaviourCollectorSorted<IDrawableTriangle> drawableShapes = new() { SortBy = SortByAscendingPriority() };
 | 
					
 | 
				
			||||||
 | 
					    private readonly ActiveBehaviourCollectorOrdered<int, IDrawableTriangle> drawableShapes = new(GetPriority(), SortByAscendingPriority());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void FirstActiveFrame()
 | 
					    public void FirstActiveFrame()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,7 @@ public class TriangleBatch : ITriangleBatch
 | 
				
			|||||||
        this.graphicsDevice = graphicsDevice;
 | 
					        this.graphicsDevice = graphicsDevice;
 | 
				
			||||||
        basicEffect = new(graphicsDevice);
 | 
					        basicEffect = new(graphicsDevice);
 | 
				
			||||||
        basicEffect.VertexColorEnabled = true;
 | 
					        basicEffect.VertexColorEnabled = true;
 | 
				
			||||||
 | 
					        vertexBuffer = new VertexBuffer(graphicsDevice, typeof(VertexPositionColor), 1024, BufferUsage.WriteOnly);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void Draw(Triangle triangle, ColorRGBA colorRGBA)
 | 
					    public void Draw(Triangle triangle, ColorRGBA colorRGBA)
 | 
				
			||||||
@@ -64,7 +65,6 @@ public class TriangleBatch : ITriangleBatch
 | 
				
			|||||||
        graphicsDevice.RasterizerState = rasterizerState;
 | 
					        graphicsDevice.RasterizerState = rasterizerState;
 | 
				
			||||||
        basicEffect.Projection = _projection;
 | 
					        basicEffect.Projection = _projection;
 | 
				
			||||||
        basicEffect.View = _view;
 | 
					        basicEffect.View = _view;
 | 
				
			||||||
        vertexBuffer = new VertexBuffer(graphicsDevice, typeof(VertexPositionColor), 1024, BufferUsage.WriteOnly);
 | 
					 | 
				
			||||||
        vertexBuffer.SetData(vertices);
 | 
					        vertexBuffer.SetData(vertices);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        graphicsDevice.SetVertexBuffer(vertexBuffer);
 | 
					        graphicsDevice.SetVertexBuffer(vertexBuffer);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,11 +17,12 @@ public class PhysicsEngine2D : Behaviour, IPreUpdate, IPhysicsEngine2D
 | 
				
			|||||||
    protected readonly ICollisionResolver2D collisionResolver = null!;
 | 
					    protected readonly ICollisionResolver2D collisionResolver = null!;
 | 
				
			||||||
    protected readonly IRaycastResolver2D raycastResolver = null!;
 | 
					    protected readonly IRaycastResolver2D raycastResolver = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static Comparer<IBehaviour> SortByPriority() => Comparer<IBehaviour>.Create((x, y) => y.Priority.CompareTo(x.Priority));
 | 
					    private static Comparer<int> SortByPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
 | 
				
			||||||
    protected ActiveBehaviourCollectorSorted<IPrePhysicsUpdate> physicsPreUpdateCollector = new() { SortBy = SortByPriority() };
 | 
					    private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
 | 
				
			||||||
    protected ActiveBehaviourCollectorSorted<IPhysicsUpdate> physicsUpdateCollector = new() { SortBy = SortByPriority() };
 | 
					    protected ActiveBehaviourCollectorOrdered<int, IPrePhysicsUpdate> physicsPreUpdateCollector = new(GetPriority(), SortByPriority());
 | 
				
			||||||
    protected ActiveBehaviourCollectorSorted<IPhysicsIteration> physicsIterationCollector = new() { SortBy = SortByPriority() };
 | 
					    protected ActiveBehaviourCollectorOrdered<int, IPhysicsUpdate> physicsUpdateCollector = new(GetPriority(), SortByPriority());
 | 
				
			||||||
    protected ActiveBehaviourCollectorSorted<IPostPhysicsUpdate> physicsPostUpdateCollector = new() { SortBy = SortByPriority() };
 | 
					    protected ActiveBehaviourCollectorOrdered<int, IPhysicsIteration> physicsIterationCollector = new(GetPriority(), SortByPriority());
 | 
				
			||||||
 | 
					    protected ActiveBehaviourCollectorOrdered<int, IPostPhysicsUpdate> physicsPostUpdateCollector = new(GetPriority(), SortByPriority());
 | 
				
			||||||
    protected BehaviourCollector<IRigidBody2D> rigidBodyCollector = new();
 | 
					    protected BehaviourCollector<IRigidBody2D> rigidBodyCollector = new();
 | 
				
			||||||
    protected BehaviourCollector<ICollider2D> colliderCollector = new();
 | 
					    protected BehaviourCollector<ICollider2D> colliderCollector = new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
 Submodule Engine.Serializers/YamlDotNet deleted from 62048d7abe
									
								
							
		Reference in New Issue
	
	Block a user