/*	Renegade Scripts.dll
	Base class and helper classes for scene (post-processing) shaders
	Copyright 2007 Mark Sararu, Jonathan Wilson

	This file is part of the Renegade scripts.dll
	The Renegade scripts.dll is free software; you can redistribute it and/or modify it under
	the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2, or (at your option) any later
	version. See the file COPYING for more details.
	In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence.
	Only the source code to the module(s) containing the licenced code has to be released.
*/
class SceneShaderControllerClass;
class SceneShaderRegistrarClass;
class SceneShaderEditorClass;
extern SceneShaderControllerClass* SceneShaderController;
extern SceneShaderRegistrarClass* SceneShaderRegistrar;

#ifndef SDBEDIT
struct SceneShaderRenderInfo
{
	IDirect3DSurface9* OutputSurface;
	IDirect3DTexture9* SceneBuffer;
	IDirect3DTexture9* InputBuffer;
	float Width, Height;
	float UScale, VScale;
};
#endif
class EffectClass;
class SceneShaderClass
{
friend class SceneShaderControllerClass; 
protected:
#ifndef SDBEDIT
	EffectClass *Effect;
#endif
public:
	unsigned int UID;
	char *Name;
	char *FXFilename;
	bool Initialized;
	bool Enabled;
	void *PrivateData;
	SceneShaderClass();
	virtual ~SceneShaderClass();
	virtual void Load(ChunkLoadClass& cload);
	virtual void Save(ChunkSaveClass& csave);
	inline void SetName(char *name)
	{
		if (Name)
		{
			delete[] Name;
		}
		Name = name;
	};
	inline void SetFXFilename(char *fxfilename)
	{
		if (FXFilename)
		{
			delete[] FXFilename;
		}
		FXFilename = fxfilename;
	};
#ifdef SDBEDIT
	virtual SceneShaderEditorClass* GetEditor();
#endif
#ifndef SDBEDIT
	virtual void Initialize();
	virtual bool Validate();
	virtual void OnDeviceLost();
	virtual void OnDeviceReset();
	virtual void OnCustom(unsigned int eventid, float parameter);
	virtual void Render(SceneShaderRenderInfo *render);
#endif
};
#ifndef SDBEDIT
class SceneShaderRenderClass
{
protected:
	IDirect3DSurface9* BackBufferRT;
	IDirect3DSurface9* DepthBuffer;
	IDirect3DTexture9* BackBuffer;
 	IDirect3DSurface9* EffectBufferRT;
	IDirect3DTexture9* EffectBuffer;
	SceneShaderRenderInfo RenderInfo;
public:
	SceneShaderRenderClass();
	void PrepareBuffers();
	void OnDeviceLost();
	void Render(SceneShaderClass* shader);
	void RequestNewBuffer(SceneShaderRenderInfo** renderinfo);
};
#endif
class SceneShaderControllerClass
{
protected:
	SimpleDynVecClass<SceneShaderClass *> *Shaders;
	SceneShaderClass *LoadSceneShader(ChunkLoadClass& cload);
#ifndef SDBEDIT
	SceneShaderClass *ActiveShader;
	bool ScopeShaderActive;
	SceneShaderClass *ScopeShader;
	SceneShaderRenderClass *RenderShader;
#endif
public:
	bool DatabaseLoaded;
	SceneShaderControllerClass();
	~SceneShaderControllerClass();
	void LoadDatabase(FileClass *file);
	void SaveDatabase(FileClass *file);
	void UnloadDatabase();
	unsigned int GetShaderCount();
	SceneShaderClass* GetShaderByIndex(unsigned int index);
	void AddShader(SceneShaderClass* shader);
	void DeleteShader(SceneShaderClass* shader);
	void DeleteShaderByIndex(unsigned int index);
#ifndef SDBEDIT
	void IntializeShaders();
	void OnDeviceLost();
	void OnDeviceReset();
	void OnCustom(unsigned int eventid, float parameter); 
	void OnFrameStart();
	void OnFrameEnd();
	void RequestNewBuffer(SceneShaderRenderInfo** renderinfo);
#endif
};

#ifndef SDBEDIT
class SceneShaderInitTask: public ResourceLoadTask
{
protected:
	void LoadResource();
public:
	SceneShaderInitTask(SceneShaderClass *sceneshader);
};
#endif

class SceneShaderFactory;
class SceneShaderRegistrarClass
{
protected:
	SimpleDynVecClass<SceneShaderFactory *> *Factories;
public:
	int FactoryCount;
	SceneShaderRegistrarClass();
	~SceneShaderRegistrarClass();
	void RegisterFactory(SceneShaderFactory *factory);
	SceneShaderFactory* GetFactory(unsigned int chunkid);
	SceneShaderFactory* GetFactoryByIndex(int index);
};
	
class SceneShaderFactory 
{
public:
	SceneShaderFactory::SceneShaderFactory(unsigned int chunkid)
	{
	 	Chunk_ID = chunkid;
		Editable = false;
		Editor_Name = (char*) NULL;
		if (!SceneShaderRegistrar)
		{
			SceneShaderRegistrar = new SceneShaderRegistrarClass();
		}
		SceneShaderRegistrar->RegisterFactory(this);
	}
	SceneShaderFactory::SceneShaderFactory(unsigned int chunkid,const char* editorname)
	{
	 	Chunk_ID = chunkid;
		Editable = true;
		Editor_Name = (char*) editorname;
		if (!SceneShaderRegistrar)
		{
			SceneShaderRegistrar = new SceneShaderRegistrarClass();
		}
		SceneShaderRegistrar->RegisterFactory(this);
	}
	unsigned int Chunk_ID;
	bool Editable;
	char* Editor_Name;
	virtual SceneShaderClass* Load(ChunkLoadClass& cload) = 0;
	virtual SceneShaderClass* CreateNew() = 0;
};

template <class T> class SceneShaderRegistrant: public SceneShaderFactory 
{
public:
	SceneShaderRegistrant(unsigned int chunkid): SceneShaderFactory(chunkid){};
	SceneShaderRegistrant(unsigned int chunkid,const char* editorname): SceneShaderFactory(chunkid,editorname){};
	SceneShaderClass* Load(ChunkLoadClass& cload)
	{
		SceneShaderClass *shader = new T;
		shader->Load(cload);
		return shader;
	};
	SceneShaderClass* CreateNew()
	{
		SceneShaderClass *shader = new T;
		return shader;
	};
};

#define EVENT_ENABLESHADER 1000
#define EVENT_SETSHADER 1001
#define EVENT_ENABLESCOPESHADER 1002
#define EVENT_SETSCOPESHADER 1003

#define CHUNK_SCENESHADER 1000
#define MC_SCENESHADER_UID 100
#define MC_SCENESHADER_NAME 101
#define MC_SCENESHADER_FXFILENAME 102
