#region CPL License /* Nuclex Framework Copyright (C) 2002-2009 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using Microsoft.Xna.Framework; namespace Nuclex.Graphics.SpecialEffects.Particles { /// Manages a collection of particle affectors /// Data type of the particles public class AffectorCollection : ICollection>, ICollection { #region class Enumerator /// Enumerates over all affectors in the collection private class Enumerator : IEnumerator>, IEnumerator { /// Initializes a new affector collection enumerator /// /// Coalescable affectors that will be enumerated /// /// /// Non-coalescable affectors that will be enumerated /// public Enumerator( List> coalescableAffectors, List> noncoalescableAffectors ) { this.coalescableAffectors = coalescableAffectors; this.nonCoalescableAffectors = noncoalescableAffectors; Reset(); } /// Returns the item at the enumerator's current position public IParticleAffector Current { get { if(this.index == -1) { throw new InvalidOperationException( "The enumerator is not on a valid position" ); } return this.currentList[this.index]; } } /// Advances the enumerator to the next item /// /// True if the next item has been selected, false if the end of /// the enumeration has been reached /// public bool MoveNext() { if(this.index == -1) { if(this.currentList == null) { this.currentList = this.coalescableAffectors; } else { return false; } } if(index >= this.currentList.Count - 1) { if(ReferenceEquals(this.currentList, this.coalescableAffectors)) { this.currentList = this.nonCoalescableAffectors; if(this.nonCoalescableAffectors.Count == 0) { this.index = -1; return false; } else { this.index = 0; return true; } } else { this.index = -1; return false; } } ++this.index; return true; } /// Resets the enumerator to its initial position public void Reset() { this.currentList = null; this.index = -1; } /// Immediately releases all resources owned by the enumerator public void Dispose() { } /// Returns the item at the enumerator's current position object IEnumerator.Current { get { return Current; } } /// Coalescable affectors being enumerated private List> coalescableAffectors; /// Non-coalescable affectors being enumerated private List> nonCoalescableAffectors; /// List being currently enumerated private List> currentList; /// Current enumeration index private int index; } #endregion // class Enumerator /// Initializes a new collection of affectors internal AffectorCollection() { this.coalescableAffectors = new List>(); this.noncoalescableAffectors = new List>(); } /// Adds an affector to the collection /// Affector that will be added to the collection public void Add(IParticleAffector affector) { if(affector.IsCoalescable) { this.coalescableAffectors.Add(affector); } else { this.noncoalescableAffectors.Add(affector); } } /// Removes all affectors from the collection public void Clear() { this.coalescableAffectors.Clear(); this.noncoalescableAffectors.Clear(); } /// /// Determines whether the collection contains the specified affector /// /// Affector that will be looked up in the collection /// True if the collection contains the specified affector public bool Contains(IParticleAffector affector) { if(affector.IsCoalescable) { return this.coalescableAffectors.Contains(affector); } else { return this.noncoalescableAffectors.Contains(affector); } } /// Copies the contents of the collection into an array /// Array the collection's contents will be copied to /// Index at which writing to the array will begin public void CopyTo(IParticleAffector[] array, int start) { int end = start + Count; if(end > array.Length) { throw new IndexOutOfRangeException("Array is too small to contain all items"); } this.coalescableAffectors.CopyTo(array, start); this.noncoalescableAffectors.CopyTo(array, start + this.coalescableAffectors.Count); } /// Number of affectors currently contained in the collection public int Count { get { return this.coalescableAffectors.Count + this.noncoalescableAffectors.Count; } } /// Whether the collection is read-only public bool IsReadOnly { get { return false; } } /// Removes an affector from the collection /// Affector that will be removed from the collection /// True if the affector was found and removed public bool Remove(IParticleAffector affector) { if(affector.IsCoalescable) { return this.coalescableAffectors.Remove(affector); } else { return this.noncoalescableAffectors.Remove(affector); } } /// Creates an enumerator for the affectors in the collection /// /// A new enumerator that will iterate over all affectors in the collection /// public IEnumerator> GetEnumerator() { return new Enumerator(this.coalescableAffectors, this.noncoalescableAffectors); } /// Copies the contents of the collection into an array /// Array the collection's contents will be copied to /// Index at which writing to the array will begin void ICollection.CopyTo(Array array, int start) { int end = start + Count; if(end > array.Length) { throw new IndexOutOfRangeException("Array is too small to contain all items"); } (this.coalescableAffectors as ICollection).CopyTo(array, start); (this.noncoalescableAffectors as ICollection).CopyTo( array, start + this.coalescableAffectors.Count ); } /// Whether the collection is synchronized bool ICollection.IsSynchronized { get { return false; } } /// The synchronization root for this collection object ICollection.SyncRoot { get { return this; } } /// Creates an enumerator for the affectors in the collection /// /// A new enumerator that will iterate over all affectors in the collection /// IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(this.coalescableAffectors, this.noncoalescableAffectors); } /// All coalescable affectors registered in the collection internal List> CoalescableAffectors { get { return this.coalescableAffectors; } } /// All non-coalescable affectors registered in the collection internal List> NoncoalescableAffectors { get { return this.noncoalescableAffectors; } } /// Coalescable affectors registered to the particle system private List> coalescableAffectors; /// Non-coalescable affectors registered to the particle system private List> noncoalescableAffectors; } } // namespace Nuclex.Graphics.SpecialEffects.Particles