using System.Collections; namespace HalfEdgeMesh; partial class Mesh { public VertexData CreateVertexData( string name ) where TData : struct => VertexList.CreateDataStream>( name ); public FaceData CreateFaceData( string name ) where TData : struct => FaceList.CreateDataStream>( name ); public HalfEdgeData CreateHalfEdgeData( string name ) where TData : struct => HalfEdgeList.CreateDataStream>( name ); } internal interface IDataStream { internal void Allocate( IHandle hSource ); internal void AllocateMultiple( int count ); } internal sealed class VertexData : ComponentData where TData : struct { } internal sealed class FaceData : ComponentData where TData : struct { } internal sealed class HalfEdgeData : ComponentData where TData : struct { } internal abstract class ComponentData : IEnumerable, IDataStream where T : struct where THandle : IHandle { internal readonly List _list = new(); public IEnumerator GetEnumerator() => _list.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public int Count => _list.Count; public T this[THandle hHandle] { get => hHandle.Index >= 0 && hHandle.Index < Count ? _list[hHandle.Index] : default; set { if ( hHandle.Index >= 0 && hHandle.Index < Count ) _list[hHandle.Index] = value; } } public void CopyFrom( T[] source ) { int count = Math.Min( _list.Count, source.Length ); for ( int i = 0; i < count; i++ ) _list[i] = source[i]; } void IDataStream.Allocate( IHandle hSource ) { _list.Add( hSource is not null && hSource.IsValid && hSource.Index < Count ? _list[hSource.Index] : default ); } void IDataStream.AllocateMultiple( int count ) { _list.Capacity += count; for ( var i = 0; i < count; i++ ) _list.Add( default ); } } internal class ComponentList : IEnumerable { private readonly List _list = new(); private readonly List _active = new(); private readonly Dictionary _streams = new(); public int Count => _list.Count; public IEnumerator GetEnumerator() => _list.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public IEnumerable ActiveList => Enumerable.Range( 0, Count ).Where( x => _active[x] ); public T this[int index] { get => _list[index]; internal set => _list[index] = value; } public int Allocate( T component, IHandle hSource ) { _list.Add( component ); _active.Add( true ); foreach ( var stream in _streams.Values ) stream.Allocate( hSource ); return Count - 1; } public void AllocateMultiple( int count, T component ) { _list.Capacity += count; for ( var i = 0; i < count; i++ ) { _list.Add( component ); _active.Add( true ); } foreach ( var stream in _streams.Values ) stream.AllocateMultiple( count ); } public void Deallocate( IHandle hHandle ) { _active[hHandle.Index] = false; } public bool IsAllocated( IHandle hHandle ) { var index = hHandle.Index; if ( index < 0 || index >= _active.Count ) return false; return _active[hHandle.Index]; } public TDataStream CreateDataStream( string name ) where TDataStream : IDataStream, new() { if ( _streams.ContainsKey( name ) ) throw new ArgumentException( "A stream with the same name already exists.", nameof( name ) ); var stream = new TDataStream(); stream.AllocateMultiple( _list.Count ); _streams[name] = stream; return stream; } }