#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