/*
	ZStandardParticleStorageAllocator.h
	Author: James Russell <jcrussell@762studios.com>

	Purpose: Standard particle type allocator.  Stores particle data as an array of structs containing particle data.

	Changelog
	2011/09/11 - creation (jcrussell)
*/

#pragma once

#ifndef _ZSTANDARDPARTICLESTORAGEALLOCATOR_H
#define _ZSTANDARDPARTICLESTORAGEALLOCATOR_H

#include <ZRendererUtil/ZParticleStorageAllocator.h>

//Struct containing our per-particle data
struct ZStandardParticle
{
	//Particle mass (sign indicates charge)
	int Mass;

	//Particle Energy (when zero or less, dead)
	int Energy;

	//Particle Position (offset from emitter transform)
	ZVector3f Position;

	//Particle Facing (only matters if not billboarding)
	ZVector3f Facing;

	//Particle Velocity
	ZVector3f Velocity;

	//Particle Scaling
	ZVector2f Scale;

	//Particle Color (per vertex, includes alpha)
	// 3 --- 2
	// |     |
	// 0 --- 1
	ZVector4f Color[4];

	//Texture data (U, V, texture width and height)
	ZVector3f TextureData;

	//Particle Id
	size_t Id;

	//Default Constructor
	ZStandardParticle()
		: Mass(1), Energy(0), 
		  Position(0, 0, 0), Facing(0, 0, 0),
		  Velocity(0, 0, 0), Scale(0, 0),
		  TextureData(0, 0, 0), Id(0)
	{
		for (int i = 0; i < 4; ++i)
		{
			Color[i].Data[0] = 0;
			Color[i].Data[1] = 0;
			Color[i].Data[2] = 0;
			Color[i].Data[3] = 0;
		}
	}
};

class ZStandardParticleStorageAllocator : public ZParticleStorageAllocator
{
protected:
	//The next inactive particle
	int NextInactive;

	//The current particle group
	size_t CurrentGroup;

	//The current particle within the current group
	size_t CurrentParticle;
		
	//Array containing particle storage
	ZArray<ZStandardParticle> ParticleData;

	//Array containing indices for particles that have been activated (must be cleared manually)
	ZArray<int> NewParticles;

public:
	/*
	Constructor.
	*/
	ZStandardParticleStorageAllocator();

	/*
	Destructor.
	*/
	virtual ~ZStandardParticleStorageAllocator();

	/*
	public ZStandardParticleStorageAllocator::ActivateParticle
	
	Activates a particle contained in storage and returns the index of the activated particle.  This
	sets the particle id.
	
	@param _group - the group number this particle is being activated with
	@return (int) - index to the activated particle
	@context (all)
	*/
	int ActivateParticle(size_t _group);

	/*
	public ZStandardParticleStorageAllocator::DeactivateParticle
	
	Deactivates a particle given the index to the particle in storage.
	
	@param _index - index to the particle in storage
	@return (void)
	@context (all)
	*/
	void DeactivateParticle(size_t _index);

	/*
	public ZStandardParticleStorageAllocator::GetActiveParticleCount
	
	Gets the number of currently active particles.  So long as only the methods
	ActivateParticle and DeactivateParticle have been used, they are guaranteed 
	to be sequential in the ParticleData array and starting at index 0.

	@return (int) - number of active particles
	@context (all)
	*/
	int GetActiveParticleCount();

	/*
	public ZStandardParticleStorageAllocator::GetParticleData
	
	Gets a reference to the array containing particle data.
	
	@return (ZArray<ZStandardParticle>&) - the particle data array
	@context (all)
	*/
	ZArray<ZStandardParticle>& GetParticleData();

	/*
	public ZStandardParticleStorageAllocator::GetNewParticles
	
	Gets an array containing indices that correspond to newly activated particles.  Should be 
	cleared by the spawn strategy when updated.
	
	@return (ZArray<int>&) - list of indices to particles that have been activated
	@context (all)
	*/
	ZArray<int>& GetNewParticles();

	//Subclass Override
	virtual void AllocateParticleStorage( ZParticleEmitter* _emitter, size_t _maxParticles );

	//Subclass Override
	virtual void DeallocateParticleStorage();

	//Subclass Override
	virtual ZString GetParticleFormat();

	//Subclass Override
	virtual void Update(ZParticleEffect *_effect, ZParticleEmitter *_emitter, size_t _dt);
};

#endif
 
