private ParticleSystem()
		{
			activeSpawnDetails = ParticleSpawnValues.Default;
			userSpawnDetails = ParticleSpawnValues.Default;
			userSpawnDetailsBuffer = ParticleSpawnValues.Default;

			this.threadAction = new SystemThreadAction();
			this.threadAction.system = this;
			this.drawProc = new SystemDrawProc();
			this.globalValues = new float[16];
		}
		//called on the task thread
		internal void UpdateParticles()
		{
			List<ParticleStore> sortedList = ComputeDependantOrderForFrame();

			//first time updating?
			if (timeStep == 0 && this.systemLogic.OnceEmitter != null)
			{
				uint totalParticles = 0;
				for (int i = 0; i < particleStore.Length; i++)
					totalParticles += particleStore[i].Count;

				if (totalParticles > 0) // special case, the OnceEmitter has created particles, need to run a processor pass first
					RunProcessorLogic(sortedList);
			}

			//update the particle types
			for (int i = 0; i < sortedList.Count; i++)
				sortedList[i].Update(this, timeStep);

			//spawn from here
			activeSpawnDetails = this.userSpawnDetailsBuffer;

			if (systemLogic.FrameEmitter != null)
				systemLogic.FrameEmitter.Run(this, timeStep);

			foreach (ParticleSystemTrigger trigger in this.triggers)
				trigger.Run(timeStep, ref activeSpawnDetails);

			foreach (ParticleSystemToggleTrigger toggle in this.toggles)
				toggle.Run(timeStep, ref activeSpawnDetails);

			//run the processor
			RunProcessorLogic(sortedList);

			for (int i = 0; i < this.particleStore.Length; i++)
				this.particleStore[i].ClearTypeEmitDependance();

			renderStepCount++;
			timeStep++;
		}
		internal void GetSpawnDetails(out ParticleSpawnValues details)
		{
			details = activeSpawnDetails;
		}
		//creates the particle system storage classes (store all particle life data)
		private void Initalise(ParticleSystemData systemData, Type processorType)
		{
			if (systemData == null)
				throw new ArgumentNullException();

			this.systemData = systemData;
			this.enabled = true;

			//build the triggers
			this.triggers = new ParticleSystemTrigger[systemData.SystemLogicData.Triggers.Length];
			for (int i = 0; i < this.triggers.Length; i++)
				this.triggers[i] = new ParticleSystemTrigger(this, i);

			this.toggles = new ParticleSystemToggleTrigger[systemData.SystemLogicData.ToggleTriggers.Length];
			for (int i = 0; i < this.toggles.Length; i++)
				this.toggles[i] = new ParticleSystemToggleTrigger(this, i);


			this.systemLogic = systemData.SystemLogicData;

			//create the storage for the particle instances
			if (processorType == null)
				this.particleStore = systemData.CreateParticleProfilerStore();
			else
				this.particleStore = systemData.CreateParticleStore(processorType);

			this.particleStoreSortedDrawOrder = new List<ParticleStore>[4];
			//fill with a few empty entires
			for (int i = 0; i < particleStoreSortedDrawOrder.Length; i++)
				particleStoreSortedDrawOrder[i] = new List<ParticleStore>(particleStore.Length);

			typeDependancyList = new int[this.particleStore.Length * 2];


			activeSpawnDetails = this.userSpawnDetails;

			//run the 'once' emitter
			if (this.systemLogic.OnceEmitter != null)
				this.systemLogic.OnceEmitter.Run(this, 0);
		}
		//setup the shaders that copy or add particles
		public int SetMoveShaderEnabled(DrawState state, GpuParticleProcessor target, GpuParticleProcessor moveSource, Vector4[] constants, ParticleSpawnValues[] initialData, int count, int startIndex)
		{
			if (constants != null)
			{
				if (constantCache == null)
				{
					constantCache = state.Application.UserValues[ConstantCacheName] as ConstantCache;
					if (constantCache == null)
					{
						constantCache = new ConstantCache();
						state.Application.UserValues[ConstantCacheName] = constantCache;
					}
				}

				Vector4[] buffer = null;
				int copyCount = 0;

				int regCount = count;

				if (initialData != null)
					regCount = Math.Min(240, count * 5); //adding requires potentially lots of space

				if (count > 128)
				{
					copyCount = Math.Min(240, regCount);
					buffer = constantCache.buffer240;
				}
				else if (regCount > 64)
				{
					copyCount = Math.Min(128, regCount);
					buffer = constantCache.buffer128;
				}
				else if (regCount > 32)
				{
					copyCount = Math.Min(64, regCount);
					buffer = constantCache.buffer64;
				}
				else if (regCount > 16)
				{
					copyCount = Math.Min(32, regCount);
					buffer = constantCache.buffer32;
				}
				else
				{
					copyCount = Math.Min(16, regCount);
					buffer = constantCache.buffer16;
				}


				if (initialData != null)
					this.enabledAddVS = true;
				else
					this.enabledMoveVS = true;

				this.vsMoveConstants = buffer;

				//write from the 7th index on
				int index = ConstantCacheOffset;

				if (initialData != null)
				{
					//initial data gets rather complex.
					//the initial particle data is huge (64bytes), but often there is loads of duplicates.
					//
					//the constants array also doesn't use the 'y' value.
					//So, the starting info will be put in a dictionary, to remove duplicates.
					//Then, the y value will be used to write indices to read from.

					//at this point, the copyCount value is useless.

					spawnIndices.Clear();
					int space = buffer.Length - index;
					int written = 0;
					float indexF = 0;

					int endIndex = count + startIndex;

					//copy as many entries as possible
					copyCount = 0;
					float offset = 0;

					for (int i = startIndex; i < endIndex; i++)
					{
						float dataIndex;

						if (written == space)
							break;

						if (!spawnIndices.TryGetValue(initialData[i], out dataIndex))
						{
							//have to write data
							if (written + 5 > space)
								break;

							Vector4 value = constants[i];
							value.Y = indexF;

							buffer[index++] = value;
							spawnIndices.Add(initialData[i], indexF);

							written += 5;
							indexF += 4;//value takes 4 registers
						}
						else
						{
							//this is a duplicate
							Vector4 value = constants[i];
							value.Y = dataIndex;

							buffer[index++] = value;

							written ++;
						}
						copyCount++;
						offset++;
					}

					//thats as much as can be written
					//fill in the details...

					//offset the indices with the starting point to read from
					for (int i = 0; i < copyCount; i++)
						buffer[ConstantCacheOffset + i].Y += offset;

					indexF = 0;
					foreach (ParticleSpawnValues value in spawnIndices.Keys)
					{
						//this should be in logical order

						if (indexF != spawnIndices[value])
							throw new InvalidOperationException();
						indexF += 4;

						buffer[index++] = value.PositionSize;
						buffer[index++] = value.VelocityRotation;
						buffer[index++] = value.Colour;
						buffer[index++] = value.UserValues;
					}
				}
				else
				{
					for (int i = 0; i < copyCount; i++)
						buffer[index++] = constants[startIndex++];
				}

				//write target size into index 4 XY
				//write destination size into index 5 XY

				moveSource = moveSource ?? target;

				buffer[4] = new Vector4(target.ResolutionX, target.ResolutionY, 1.0f / target.ResolutionX, 1.0f / target.ResolutionY);
				buffer[5] = new Vector4(moveSource.ResolutionX, moveSource.ResolutionY, 1.0f / moveSource.ResolutionX, 1.0f / moveSource.ResolutionY);
			
				return copyCount;
			}
			else
			{
				this.vsMoveConstants = null;
				this.enabledMoveVS = false;
				this.enabledAddVS = false;
				return 0;
			}
		}