Development Merge 2025.10.18 #4
@@ -45,30 +45,71 @@ namespace Syntriax.Engine.Core;
 | 
				
			|||||||
/// </summary>
 | 
					/// </summary>
 | 
				
			||||||
public class Event
 | 
					public class Event
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private readonly List<EventHandler> listeners = null!;
 | 
					    // We use Ascending order because draw calls are running from last to first
 | 
				
			||||||
    private readonly List<EventHandler> onceListeners = null!;
 | 
					    private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly List<ListenerData> listeners = null!;
 | 
				
			||||||
 | 
					    private readonly List<ListenerData> onceListeners = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Subscribes the callback to be invoked whenever the event is triggered.
 | 
					    /// Subscribes the callback to be invoked whenever the event is triggered.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback to be called when the event is triggered.</param>
 | 
					    /// <param name="listener">The callback to be called when the event is triggered.</param>
 | 
				
			||||||
    public void AddListener(EventHandler listener) => listeners.Add(listener);
 | 
					    /// <param name="priority">Priority of the callback.</param>
 | 
				
			||||||
 | 
					    public void AddListener(EventHandler listener, int priority = 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ListenerData listenerData = new(listener, priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int insertIndex = listeners.BinarySearch(listenerData, SortByAscendingPriority);
 | 
				
			||||||
 | 
					        if (insertIndex < 0)
 | 
				
			||||||
 | 
					            insertIndex = ~insertIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        listeners.Insert(insertIndex, listenerData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Subscribes the callback to be invoked the next time the event is triggered. The callback will be called only once.
 | 
					    /// Subscribes the callback to be invoked the next time the event is triggered. The callback will be called only once.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback to be called the next time the event is triggered.</param>
 | 
					    /// <param name="listener">The callback to be called the next time the event is triggered.</param>
 | 
				
			||||||
    public void AddOneTimeListener(EventHandler listener) => onceListeners.Add(listener);
 | 
					    /// <param name="priority">Priority of the callback.</param>
 | 
				
			||||||
 | 
					    public void AddOneTimeListener(EventHandler listener, int priority = 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ListenerData listenerData = new(listener, priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int insertIndex = onceListeners.BinarySearch(listenerData, SortByAscendingPriority);
 | 
				
			||||||
 | 
					        if (insertIndex < 0)
 | 
				
			||||||
 | 
					            insertIndex = ~insertIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        onceListeners.Insert(insertIndex, listenerData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Unsubscribes the callback that was previously registered by <see cref="AddListener(EventHandler)"/>.
 | 
					    /// Unsubscribes the callback that was previously registered by <see cref="AddListener(EventHandler)"/>.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback that was previously registered by <see cref="AddListener(EventHandler)"/></param>
 | 
					    /// <param name="listener">The callback that was previously registered by <see cref="AddListener(EventHandler)"/></param>
 | 
				
			||||||
    public void RemoveListener(EventHandler listener) => listeners.Remove(listener);
 | 
					    public void RemoveListener(EventHandler listener)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (int i = listeners.Count - 1; i >= 0; i--)
 | 
				
			||||||
 | 
					            if (listeners[i].Callback == listener)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                listeners.RemoveAt(i);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Unsubscribes the callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
					    /// Unsubscribes the callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/></param>
 | 
					    /// <param name="listener">The callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/></param>
 | 
				
			||||||
    public void RemoveOneTimeListener(EventHandler listener) => onceListeners.Remove(listener);
 | 
					    public void RemoveOneTimeListener(EventHandler listener)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (int i = 0; i < onceListeners.Count; i++)
 | 
				
			||||||
 | 
					            if (onceListeners[i].Callback == listener)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                onceListeners.RemoveAt(i);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Unsubscribes all listeners that was previously registered by either <see cref="AddListener(EventHandler)"/> or <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
					    /// Unsubscribes all listeners that was previously registered by either <see cref="AddListener(EventHandler)"/> or <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
				
			||||||
@@ -81,19 +122,19 @@ public class Event
 | 
				
			|||||||
    public void Invoke()
 | 
					    public void Invoke()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        for (int i = listeners.Count - 1; i >= 0; i--)
 | 
					        for (int i = listeners.Count - 1; i >= 0; i--)
 | 
				
			||||||
            try { listeners[i].Invoke(); }
 | 
					            try { listeners[i].Callback.Invoke(); }
 | 
				
			||||||
            catch (Exception exception)
 | 
					            catch (Exception exception)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                string methodCallRepresentation = $"{listeners[i].Method.DeclaringType?.FullName}.{listeners[i].Method.Name}()";
 | 
					                string methodCallRepresentation = $"{listeners[i].Callback.Method.DeclaringType?.FullName}.{listeners[i].Callback.Method.Name}()";
 | 
				
			||||||
                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
					                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (int i = onceListeners.Count - 1; i >= 0; i--)
 | 
					        for (int i = onceListeners.Count - 1; i >= 0; i--)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            try { onceListeners[i].Invoke(); }
 | 
					            try { onceListeners[i].Callback.Invoke(); }
 | 
				
			||||||
            catch (Exception exception)
 | 
					            catch (Exception exception)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                string methodCallRepresentation = $"{onceListeners[i].Method.DeclaringType?.FullName}.{onceListeners[i].Method.Name}()";
 | 
					                string methodCallRepresentation = $"{onceListeners[i].Callback.Method.DeclaringType?.FullName}.{onceListeners[i].Callback.Method.Name}()";
 | 
				
			||||||
                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
					                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            onceListeners.RemoveAt(i);
 | 
					            onceListeners.RemoveAt(i);
 | 
				
			||||||
@@ -113,6 +154,7 @@ public class Event
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public delegate void EventHandler();
 | 
					    public delegate void EventHandler();
 | 
				
			||||||
 | 
					    private record struct ListenerData(EventHandler Callback, int Priority);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -159,30 +201,71 @@ public class Event
 | 
				
			|||||||
/// <typeparam name="TSender">Sender type</typeparam>
 | 
					/// <typeparam name="TSender">Sender type</typeparam>
 | 
				
			||||||
public class Event<TSender>
 | 
					public class Event<TSender>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private readonly List<EventHandler> listeners = null!;
 | 
					    // We use Ascending order because draw calls are running from last to first
 | 
				
			||||||
    private readonly List<EventHandler> onceListeners = null!;
 | 
					    private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly List<ListenerData> listeners = null!;
 | 
				
			||||||
 | 
					    private readonly List<ListenerData> onceListeners = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Subscribes the callback to be invoked whenever the event is triggered.
 | 
					    /// Subscribes the callback to be invoked whenever the event is triggered.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback to be called when the event is triggered.</param>
 | 
					    /// <param name="listener">The callback to be called when the event is triggered.</param>
 | 
				
			||||||
    public void AddListener(EventHandler listener) => listeners.Add(listener);
 | 
					    /// <param name="priority">Priority of the callback.</param>
 | 
				
			||||||
 | 
					    public void AddListener(EventHandler listener, int priority = 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ListenerData listenerData = new(listener, priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int insertIndex = listeners.BinarySearch(listenerData, SortByAscendingPriority);
 | 
				
			||||||
 | 
					        if (insertIndex < 0)
 | 
				
			||||||
 | 
					            insertIndex = ~insertIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        listeners.Insert(insertIndex, listenerData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Subscribes the callback to be invoked the next time the event is triggered. The callback will be called only once.
 | 
					    /// Subscribes the callback to be invoked the next time the event is triggered. The callback will be called only once.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback to be called the next time the event is triggered.</param>
 | 
					    /// <param name="listener">The callback to be called the next time the event is triggered.</param>
 | 
				
			||||||
    public void AddOneTimeListener(EventHandler listener) => onceListeners.Add(listener);
 | 
					    /// <param name="priority">Priority of the callback.</param>
 | 
				
			||||||
 | 
					    public void AddOneTimeListener(EventHandler listener, int priority = 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ListenerData listenerData = new(listener, priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int insertIndex = onceListeners.BinarySearch(listenerData, SortByAscendingPriority);
 | 
				
			||||||
 | 
					        if (insertIndex < 0)
 | 
				
			||||||
 | 
					            insertIndex = ~insertIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        onceListeners.Insert(insertIndex, listenerData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Unsubscribes the callback that was previously registered by <see cref="AddListener(EventHandler)"/>.
 | 
					    /// Unsubscribes the callback that was previously registered by <see cref="AddListener(EventHandler)"/>.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback that was previously registered by <see cref="AddListener(EventHandler)"/></param>
 | 
					    /// <param name="listener">The callback that was previously registered by <see cref="AddListener(EventHandler)"/></param>
 | 
				
			||||||
    public void RemoveListener(EventHandler listener) => listeners.Remove(listener);
 | 
					    public void RemoveListener(EventHandler listener)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (int i = listeners.Count - 1; i >= 0; i--)
 | 
				
			||||||
 | 
					            if (listeners[i].Callback == listener)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                listeners.RemoveAt(i);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Unsubscribes the callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
					    /// Unsubscribes the callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/></param>
 | 
					    /// <param name="listener">The callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/></param>
 | 
				
			||||||
    public void RemoveOneTimeListener(EventHandler listener) => onceListeners.Remove(listener);
 | 
					    public void RemoveOneTimeListener(EventHandler listener)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (int i = 0; i < onceListeners.Count; i++)
 | 
				
			||||||
 | 
					            if (onceListeners[i].Callback == listener)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                onceListeners.RemoveAt(i);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Unsubscribes all listeners that was previously registered by either <see cref="AddListener(EventHandler)"/> or <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
					    /// Unsubscribes all listeners that was previously registered by either <see cref="AddListener(EventHandler)"/> or <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
				
			||||||
@@ -196,19 +279,19 @@ public class Event<TSender>
 | 
				
			|||||||
    public void Invoke(TSender sender)
 | 
					    public void Invoke(TSender sender)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        for (int i = listeners.Count - 1; i >= 0; i--)
 | 
					        for (int i = listeners.Count - 1; i >= 0; i--)
 | 
				
			||||||
            try { listeners[i].Invoke(sender); }
 | 
					            try { listeners[i].Callback.Invoke(sender); }
 | 
				
			||||||
            catch (Exception exception)
 | 
					            catch (Exception exception)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                string methodCallRepresentation = $"{listeners[i].Method.DeclaringType?.FullName}.{listeners[i].Method.Name}({sender})";
 | 
					                string methodCallRepresentation = $"{listeners[i].Callback.Method.DeclaringType?.FullName}.{listeners[i].Callback.Method.Name}({sender})";
 | 
				
			||||||
                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
					                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (int i = onceListeners.Count - 1; i >= 0; i--)
 | 
					        for (int i = onceListeners.Count - 1; i >= 0; i--)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            try { onceListeners[i].Invoke(sender); }
 | 
					            try { onceListeners[i].Callback.Invoke(sender); }
 | 
				
			||||||
            catch (Exception exception)
 | 
					            catch (Exception exception)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                string methodCallRepresentation = $"{onceListeners[i].Method.DeclaringType?.FullName}.{onceListeners[i].Method.Name}({sender})";
 | 
					                string methodCallRepresentation = $"{onceListeners[i].Callback.Method.DeclaringType?.FullName}.{onceListeners[i].Callback.Method.Name}({sender})";
 | 
				
			||||||
                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
					                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            onceListeners.RemoveAt(i);
 | 
					            onceListeners.RemoveAt(i);
 | 
				
			||||||
@@ -228,6 +311,7 @@ public class Event<TSender>
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public delegate void EventHandler(TSender sender);
 | 
					    public delegate void EventHandler(TSender sender);
 | 
				
			||||||
 | 
					    private record struct ListenerData(EventHandler Callback, int Priority);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <summary>
 | 
					/// <summary>
 | 
				
			||||||
@@ -281,30 +365,71 @@ public class Event<TSender>
 | 
				
			|||||||
/// <typeparam name="TSender">Sender type</typeparam>
 | 
					/// <typeparam name="TSender">Sender type</typeparam>
 | 
				
			||||||
public class Event<TSender, TArguments>
 | 
					public class Event<TSender, TArguments>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private readonly List<EventHandler> listeners = null!;
 | 
					    // We use Ascending order because draw calls are running from last to first
 | 
				
			||||||
    private readonly List<EventHandler> onceListeners = null!;
 | 
					    private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly List<ListenerData> listeners = null!;
 | 
				
			||||||
 | 
					    private readonly List<ListenerData> onceListeners = null!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Subscribes the callback to be invoked whenever the event is triggered.
 | 
					    /// Subscribes the callback to be invoked whenever the event is triggered.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback to be called when the event is triggered.</param>
 | 
					    /// <param name="listener">The callback to be called when the event is triggered.</param>
 | 
				
			||||||
    public void AddListener(EventHandler listener) => listeners.Add(listener);
 | 
					    /// <param name="priority">Priority of the callback.</param>
 | 
				
			||||||
 | 
					    public void AddListener(EventHandler listener, int priority = 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ListenerData listenerData = new(listener, priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int insertIndex = listeners.BinarySearch(listenerData, SortByAscendingPriority);
 | 
				
			||||||
 | 
					        if (insertIndex < 0)
 | 
				
			||||||
 | 
					            insertIndex = ~insertIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        listeners.Insert(insertIndex, listenerData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Subscribes the callback to be invoked the next time the event is triggered. The callback will be called only once.
 | 
					    /// Subscribes the callback to be invoked the next time the event is triggered. The callback will be called only once.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback to be called the next time the event is triggered.</param>
 | 
					    /// <param name="listener">The callback to be called the next time the event is triggered.</param>
 | 
				
			||||||
    public void AddOneTimeListener(EventHandler listener) => onceListeners.Add(listener);
 | 
					    /// <param name="priority">Priority of the callback.</param>
 | 
				
			||||||
 | 
					    public void AddOneTimeListener(EventHandler listener, int priority = 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ListenerData listenerData = new(listener, priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int insertIndex = onceListeners.BinarySearch(listenerData, SortByAscendingPriority);
 | 
				
			||||||
 | 
					        if (insertIndex < 0)
 | 
				
			||||||
 | 
					            insertIndex = ~insertIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        onceListeners.Insert(insertIndex, listenerData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Unsubscribes the callback that was previously registered by <see cref="AddListener(EventHandler)"/>.
 | 
					    /// Unsubscribes the callback that was previously registered by <see cref="AddListener(EventHandler)"/>.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback that was previously registered by <see cref="AddListener(EventHandler)"/></param>
 | 
					    /// <param name="listener">The callback that was previously registered by <see cref="AddListener(EventHandler)"/></param>
 | 
				
			||||||
    public void RemoveListener(EventHandler listener) => listeners.Remove(listener);
 | 
					    public void RemoveListener(EventHandler listener)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (int i = listeners.Count - 1; i >= 0; i--)
 | 
				
			||||||
 | 
					            if (listeners[i].Callback == listener)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                listeners.RemoveAt(i);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Unsubscribes the callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
					    /// Unsubscribes the callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    /// <param name="listener">The callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/></param>
 | 
					    /// <param name="listener">The callback that was previously registered by <see cref="AddOneTimeListener(EventHandler)"/></param>
 | 
				
			||||||
    public void RemoveOneTimeListener(EventHandler listener) => onceListeners.Remove(listener);
 | 
					    public void RemoveOneTimeListener(EventHandler listener)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (int i = 0; i < onceListeners.Count; i++)
 | 
				
			||||||
 | 
					            if (onceListeners[i].Callback == listener)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                onceListeners.RemoveAt(i);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Unsubscribes all listeners that was previously registered by either <see cref="AddListener(EventHandler)"/> or <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
					    /// Unsubscribes all listeners that was previously registered by either <see cref="AddListener(EventHandler)"/> or <see cref="AddOneTimeListener(EventHandler)"/>.
 | 
				
			||||||
@@ -319,19 +444,19 @@ public class Event<TSender, TArguments>
 | 
				
			|||||||
    public void Invoke(TSender sender, TArguments args)
 | 
					    public void Invoke(TSender sender, TArguments args)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        for (int i = listeners.Count - 1; i >= 0; i--)
 | 
					        for (int i = listeners.Count - 1; i >= 0; i--)
 | 
				
			||||||
            try { listeners[i].Invoke(sender, args); }
 | 
					            try { listeners[i].Callback.Invoke(sender, args); }
 | 
				
			||||||
            catch (Exception exception)
 | 
					            catch (Exception exception)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                string methodCallRepresentation = $"{listeners[i].Method.DeclaringType?.FullName}.{listeners[i].Method.Name}({string.Join(", ", sender, args)})";
 | 
					                string methodCallRepresentation = $"{listeners[i].Callback.Method.DeclaringType?.FullName}.{listeners[i].Callback.Method.Name}({string.Join(", ", sender, args)})";
 | 
				
			||||||
                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
					                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (int i = onceListeners.Count - 1; i >= 0; i--)
 | 
					        for (int i = onceListeners.Count - 1; i >= 0; i--)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            try { onceListeners[i].Invoke(sender, args); }
 | 
					            try { onceListeners[i].Callback.Invoke(sender, args); }
 | 
				
			||||||
            catch (Exception exception)
 | 
					            catch (Exception exception)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                string methodCallRepresentation = $"{onceListeners[i].Method.DeclaringType?.FullName}.{onceListeners[i].Method.Name}({string.Join(", ", sender, args)})";
 | 
					                string methodCallRepresentation = $"{onceListeners[i].Callback.Method.DeclaringType?.FullName}.{onceListeners[i].Callback.Method.Name}({string.Join(", ", sender, args)})";
 | 
				
			||||||
                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
					                Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            onceListeners.RemoveAt(i);
 | 
					            onceListeners.RemoveAt(i);
 | 
				
			||||||
@@ -351,4 +476,5 @@ public class Event<TSender, TArguments>
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public delegate void EventHandler(TSender sender, TArguments args);
 | 
					    public delegate void EventHandler(TSender sender, TArguments args);
 | 
				
			||||||
 | 
					    private record struct ListenerData(EventHandler Callback, int Priority);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user