using System.Collections;
namespace Sandbox;
///
/// An ordered collection of unique objects with add/remove callbacks.
/// Maintains insertion order and provides change notifications.
///
public class SelectionSystem : IEnumerable
{
// Value is always false and unused - we only need the ordered key collection
private OrderedDictionary _list { get; } = new();
// Random hash code that changes when the collection is modified
int _hashCode = Random.Shared.Int( 0, 4096 );
///
/// Invoked when an item is added to the selection.
///
public Action OnItemAdded { get; set; }
///
/// Invoked when an item is removed from the selection.
///
public Action OnItemRemoved { get; set; }
///
/// Gets a hash code that changes whenever the collection is modified.
/// Useful for detecting selection changes.
///
public override int GetHashCode() => _hashCode;
///
/// Returns an enumerator that iterates through the selected objects in order.
///
public IEnumerator GetEnumerator()
{
return _list.Keys.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _list.Keys.GetEnumerator();
}
///
/// Gets the number of selected objects.
///
public int Count => _list.Count;
///
/// Removes all objects from the selection, invoking OnItemRemoved for each.
///
public virtual void Clear()
{
if ( !_list.Any() )
return;
foreach ( var kvp in _list )
{
OnItemRemoved?.Invoke( kvp.Key );
}
_list.Clear();
_hashCode++;
}
///
/// Adds an object to the selection.
///
/// The object to add
/// True if the object was added, false if it was already selected
public virtual bool Add( object obj )
{
if ( _list.TryAdd( obj, false ) )
{
_hashCode++;
OnItemAdded?.Invoke( obj );
return true;
}
return false;
}
///
/// Clears the selection and sets it to a single object.
///
/// The object to select
/// True if the selection changed, false if it was already the only selected object
public virtual bool Set( object obj )
{
if ( _list.Count == 1 && _list.Keys.First() == obj )
return false;
Clear();
Add( obj );
return true;
}
///
/// Removes an object from the selection.
///
/// The object to remove
/// True if the object was removed, false if it wasn't selected
public virtual bool Remove( object obj )
{
if ( _list.Remove( obj ) )
{
_hashCode++;
OnItemRemoved?.Invoke( obj );
return true;
}
return false;
}
///
/// Checks if an object is in the selection.
///
/// The object to check
/// True if the object is selected
public virtual bool Contains( object obj )
{
return _list.ContainsKey( obj );
}
///
/// Checks if the selection contains any objects.
///
/// True if there are any selected objects
public virtual bool Any() => _list.Count != 0;
}