/* Renegade Scripts.dll
	Base 3D drawing related engine classes and calls
	Copyright 2007 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 TextureLoadTaskClass;
class FontCharsClass;
class Font3DInstanceClass;
class Font3DDataClass;

class ShaderClass {
	enum AlphaTestType {
		ALPHATEST_DISABLE = 0x0,
		ALPHATEST_ENABLE = 0x1,
		ALPHATEST_MAX = 0x2,
	};
	enum DepthCompareType {
		PASS_NEVER = 0x0,
		PASS_LESS = 0x1,
		PASS_EQUAL = 0x2,
		PASS_LEQUAL = 0x3,
		PASS_GREATER = 0x4,
		PASS_NOTEQUAL = 0x5,
		PASS_GEQUAL = 0x6,
		PASS_ALWAYS = 0x7,
		PASS_MAX = 0x8,
	};
	enum DepthMaskType {
		DEPTH_WRITE_DISABLE = 0x0,
		DEPTH_WRITE_ENABLE = 0x1,
		DEPTH_WRITE_MAX = 0x2,
	};
	enum ColorMaskType {
		COLOR_WRITE_DISABLE = 0x0,
		COLOR_WRITE_ENABLE = 0x1,
		COLOR_WRITE_MAX = 0x2,
	};
	enum DetailAlphaFuncType {
		DETAILALPHA_DISABLE = 0x0,
		DETAILALPHA_DETAIL = 0x1,
		DETAILALPHA_SCALE = 0x2,
		DETAILALPHA_INVSCALE = 0x3,
		DETAILALPHA_MAX = 0x4,
	};
	enum DetailColorFuncType {
		DETAILCOLOR_DISABLE = 0x0,
		DETAILCOLOR_DETAIL = 0x1,
		DETAILCOLOR_SCALE = 0x2,
		DETAILCOLOR_INVSCALE = 0x3,
		DETAILCOLOR_ADD = 0x4,
		DETAILCOLOR_SUB = 0x5,
		DETAILCOLOR_SUBR = 0x6,
		DETAILCOLOR_BLEND = 0x7,
		DETAILCOLOR_DETAILBLEND = 0x8,
		DETAILCOLOR_MAX = 0x9,
	};
	enum CullModeType {
		CULL_MODE_DISABLE = 0x0,
		CULL_MODE_ENABLE = 0x1,
		CULL_MODE_MAX = 0x2,
	};
	enum NPatchEnableType {
		NPATCH_DISABLE = 0x0,
		NPATCH_ENABLE = 0x1,
		NPATCH_TYPE_MAX = 0x2,
	};
	enum DstBlendFuncType {
		DSTBLEND_ZERO = 0x0,
		DSTBLEND_ONE = 0x1,
		DSTBLEND_SRC_COLOR = 0x2,
		DSTBLEND_ONE_MINUS_SRC_COLOR = 0x3,
		DSTBLEND_SRC_ALPHA = 0x4,
		DSTBLEND_ONE_MINUS_SRC_ALPHA = 0x5,
		DSTBLEND_MAX = 0x6,
	};
	enum FogFuncType {
		FOG_DISABLE = 0x0,
		FOG_ENABLE = 0x1,
		FOG_SCALE_FRAGMENT = 0x2,
		FOG_WHITE = 0x3,
		FOG_MAX = 0x4,
	};
	enum PriGradientType {
		GRADIENT_DISABLE = 0x0,
		GRADIENT_MODULATE = 0x1,
		GRADIENT_ADD = 0x2,
		GRADIENT_BUMPENVMAP = 0x3,
		GRADIENT_BUMPENVMAPLUMINANCE = 0x4,
		GRADIENT_DOTPRODUCT3 = 0x5,
		GRADIENT_MAX = 0x6,
	};
	enum SecGradientType {
		SECONDARY_GRADIENT_DISABLE = 0x0,
		SECONDARY_GRADIENT_ENABLE = 0x1,
		SECONDARY_GRADIENT_MAX = 0x2,
	};
	enum SrcBlendFuncType {
		SRCBLEND_ZERO = 0x0,
		SRCBLEND_ONE = 0x1,
		SRCBLEND_SRC_ALPHA = 0x2,
		SRCBLEND_ONE_MINUS_SRC_ALPHA = 0x3,
		SRCBLEND_MAX = 0x4,
	};
	enum TexturingType {
		TEXTURING_DISABLE = 0x0,
		TEXTURING_ENABLE = 0x1,
		TEXTURING_MAX = 0x2,
	};
	enum StaticSortCategoryType {
		SSCAT_OPAQUE = 0x0,
		SSCAT_ALPHA_TEST = 0x1,
		SSCAT_ADDITIVE = 0x2,
		SSCAT_OTHER = 0x3,
	};
	enum {
		MASK_DEPTHCOMPARE = 0x7,
		MASK_DEPTHMASK = 0x8,
		MASK_COLORMASK = 0x10,
		MASK_DSTBLEND = 0xe0,
		MASK_FOG = 0x300,
		MASK_PRIGRADIENT = 0x1c00,
		MASK_SECGRADIENT = 0x2000,
		MASK_SRCBLEND = 0xc000,
		MASK_TEXTURING = 0x10000,
		MASK_NPATCHENABLE = 0x20000,
		MASK_ALPHATEST = 0x40000,
		MASK_CULLMODE = 0x80000,
		MASK_POSTDETAILCOLORFUNC = 0xf00000,
		MASK_POSTDETAILALPHAFUNC = 0x7000000,
	};
public:
	unsigned int ShaderBits;
	void Apply();
};

enum WW3DFormat {
	WW3D_FORMAT_UNKNOWN = 0x0,
	WW3D_FORMAT_R8G8B8 = 0x1,
	WW3D_FORMAT_A8R8G8B8 = 0x2,
	WW3D_FORMAT_X8R8G8B8 = 0x3,
	WW3D_FORMAT_R5G6B5 = 0x4,
	WW3D_FORMAT_X1R5G5B5 = 0x5,
	WW3D_FORMAT_A1R5G5B5 = 0x6,
	WW3D_FORMAT_A4R4G4B4 = 0x7,
	WW3D_FORMAT_R3G3B2 = 0x8,
	WW3D_FORMAT_A8 = 0x9,
	WW3D_FORMAT_A8R3G3B2 = 0xa,
	WW3D_FORMAT_X4R4G4B4 = 0xb,
	WW3D_FORMAT_A8P8 = 0xc,
	WW3D_FORMAT_P8 = 0xd,
	WW3D_FORMAT_L8 = 0xe,
	WW3D_FORMAT_A8L8 = 0xf,
	WW3D_FORMAT_A4L4 = 0x10,
	WW3D_FORMAT_U8V8 = 0x11,
	WW3D_FORMAT_L6V5U5 = 0x12,
	WW3D_FORMAT_X8L8V8U8 = 0x13,
	WW3D_FORMAT_DXT1 = 0x14,
	WW3D_FORMAT_DXT2 = 0x15,
	WW3D_FORMAT_DXT3 = 0x16,
	WW3D_FORMAT_DXT4 = 0x17,
	WW3D_FORMAT_DXT5 = 0x18,
	WW3D_FORMAT_COUNT = 0x19,
};

enum MipCountType {
	MIP_LEVELS_ALL = 0x0,
	MIP_LEVELS_1 = 0x1,
	MIP_LEVELS_2 = 0x2,
	MIP_LEVELS_3 = 0x3,
	MIP_LEVELS_4 = 0x4,
	MIP_LEVELS_5 = 0x5,
	MIP_LEVELS_6 = 0x6,
	MIP_LEVELS_7 = 0x7,
	MIP_LEVELS_8 = 0x8,
	MIP_LEVELS_10 = 0x9,
	MIP_LEVELS_11 = 0xa,
	MIP_LEVELS_12 = 0xb,
	MIP_LEVELS_MAX = 0xc,
};

enum PoolType {
	POOL_DEFAULT = 0x0,
	POOL_MANAGED = 0x1,
	POOL_SYSTEMMEM = 0x2,
};

enum FilterType {
	FILTER_TYPE_NONE = 0x0,
	FILTER_TYPE_FAST = 0x1,
	FILTER_TYPE_BEST = 0x2,
	FILTER_TYPE_DEFAULT = 0x3,
	FILTER_TYPE_COUNT = 0x4,
};

enum TxtAddrMode {
	TEXTURE_ADDRESS_REPEAT = 0x0,
	TEXTURE_ADDRESS_CLAMP = 0x1,
};

enum ColorSourceType {
	MATERIAL = 0x0,
	COLOR1 = 0x1,
	COLOR2 = 0x2,
};

enum PresetType {
	PRELIT_DIFFUSE = 0x0,
	PRELIT_NODIFFUSE = 0x1,
	PRESET_COUNT = 0x2,
};

enum MappingType {
	MAPPING_NONE = 0xff,
	MAPPING_UV = 0x0,
	MAPPING_ENVIRONMENT = 0x1,
};

enum FlagsType {
	DEPTH_CUE = 0x0,
	DEPTH_CUE_TO_ALPHA = 0x1,
	COPY_SPECULAR_TO_DIFFUSE = 0x2,
};

class TextureClass: public RefCountClass {
public:
	FilterType TextureMinFilter;
	FilterType TextureMagFilter;
	FilterType MipMapFilter;
	TxtAddrMode UAddressMode;
	TxtAddrMode VAddressMode;
	myIDirect3DTexture8 *D3DTexture;
	bool Initialized;
	StringClass Name;
	StringClass FullPath;
	unsigned int texture_id;
	bool IsLightmap;
	bool IsProcedural;
	bool IsCompressionAllowed;
	unsigned int InactivationTime;
	unsigned int Time1;
	unsigned int Time2;
	unsigned int LastAccessed;
	WW3DFormat TextureFormat;
	unsigned int Width;
	unsigned int Height;
	PoolType Pool;
	bool Dirty;
	MipCountType MipLevelCount;
	TextureLoadTaskClass *TextureLoadTask;
	TextureLoadTaskClass *TextureLoadTask2;
	virtual TextureClass::~TextureClass();
	void Init();
	bool Is_Missing_Texture();
};

class DX8Caps {
public:
	int WidthLimit;
	int HeightLimit;
	D3DCAPS8 Caps;
	bool UseTnL;
	bool SupportDXTC;
	bool supportGamma;
	bool SupportNPatches;
	bool SupportBumpEnvmap;
	bool SupportBumpEnvmapLuminance;
	bool SupportTextureFormat[25];
	bool SupportRenderToTextureFormat[25];
	bool SupportZBias;
	bool SupportAnisotropicFiltering;
	bool SupportMultiTexture;
	bool SupportFog;
	unsigned int MaxTexturesPerPass;
	unsigned int VertexShaderVersion; // Outdated, do not use
	unsigned int PixelShaderVersion; // Outdated, do not use
	unsigned int DeviceNumber;
	unsigned int DriverBuildNum;
	unsigned int DriverStatus;
	unsigned int VendorNumber;
	StringClass DriverFilename;
	myIDirect3D8 *D3D;
	StringClass VideoCardSpecString;
	StringClass VideoCardName;
};

class Render2DClass {
public:
	Vector2 CoordinateScale;
	Vector2 CoordinateOffset;
	Vector2 BiasedCoordinateOffset;
	TextureClass *Texture;
	ShaderClass Shader;
	DynamicVectorClass<unsigned short> Indices;
	unsigned short IndiciesData[0x3C];
	DynamicVectorClass<Vector2> Vertices;
	Vector2 VerticiesData[0x3C];
	DynamicVectorClass<Vector2> UVCoordinates;
	Vector2 UVCoordinatesData[0x3C];
	DynamicVectorClass<unsigned long> Colors;
	unsigned long ColorsData[0x3C];
	bool IsHidden;
	float ZValue;
public:
	Render2DClass()
	{
	}
	Render2DClass(TextureClass *texture);
	virtual ~Render2DClass();
	virtual void Reset();
	void Render();
	void Set_Coordinate_Range(RectClass const &r);
	void Set_Texture(char const *texture);
	void Add_Quad(RectClass const &screen, RectClass const &uv, unsigned long color);
	void Add_Quad(RectClass const &screen, unsigned long color);
	void Add_Line(Vector2 const &start, Vector2 const &end, float width, unsigned long color);
	void Update_Bias();
};

class SurfaceClass : public RefCountClass {
	myIDirect3DSurface8 *D3DSurface;
	WW3DFormat SurfaceFormat;
public:
	struct SurfaceDescription {
		WW3DFormat Format;
		unsigned int Width;
		unsigned int Height;
	};
	SurfaceClass(unsigned int width,unsigned int height,WW3DFormat format);
	void Get_Description(SurfaceDescription& surface_desc);
	void *Lock(int* pitch);
	void *Lock_ReadOnly(int* pitch);
	void Unlock();
	IDirect3DSurface9 *Peek_D3D_Surface();
	WW3DFormat Get_Surface_Format();
	~SurfaceClass();
};

class Render2DTextClass : public Render2DClass {
	Font3DInstanceClass *Font;
	Vector2 Location;
	Vector2 Cursor;
	float WrapWidth;
	RectClass DrawExtents;
	RectClass TotalExtents;
	RectClass BlockUV;
	RectClass ClipRect;
	bool IsClippedEnabled;
public:
	Render2DTextClass(Font3DInstanceClass *font);
	~Render2DTextClass();
	void Reset();
	void Draw_Text(char const *text, unsigned long color);
};
class Vector2i {
public:
	int I;
	int J;
};

class Render2DSentenceClass {
	struct SentenceDataStruct {
		SurfaceClass *Surface;
		RectClass ScreenRect;
		RectClass UVRect;
	};
	struct PendingSurfaceStruct {
		SurfaceClass *Surface;
		DynamicVectorClass<Render2DClass *> Renderers;
	};
	struct RendererDataStruct {
		Render2DClass *Renderer;
		SurfaceClass *Surface;
	};
	DynamicVectorClass<SentenceDataStruct> SentenceData;
	DynamicVectorClass<PendingSurfaceStruct> PendingSurfaces;
	DynamicVectorClass<RendererDataStruct> Renderers;
	RendererDataStruct RenderersData[0x10];
	FontCharsClass *Font;
	Vector2 BaseLocation;
	Vector2 Location;
	Vector2 Cursor;
	Vector2i TextureOffset;
	int TextureStartX;
	int CurrTextureSize;
	int TextureSizeHint;
	SurfaceClass *CurSurface;
	bool MonoSpaced;
	float WrapWidth;
	bool Centered;
	RectClass ClipRect;
	RectClass DrawExtents;
	bool IsClippedEnabled;
	unsigned short *LockedPtr;
	int LockedStride;
	TextureClass *CurTexture;
	ShaderClass Shader;
public:
	Render2DSentenceClass();
	~Render2DSentenceClass();
	virtual void Reset();
	void Render();
	void Build_Sentence(wchar_t const *sentence);
	void Set_Location(Vector2 const &location);
	void Draw_Sentence(unsigned long color);
	void Set_Font(FontCharsClass *font);
};

typedef void (*ScriptNotify) (int ID,int notify);
void InitEngine3DRE(unsigned int exe);
void Set_DX8_Transform(D3DTRANSFORMSTATETYPE transform,Matrix4& m);
void Get_DX8_Transform(D3DTRANSFORMSTATETYPE transform,Matrix4& m);
Render2DSentenceClass *CreateRender2DSentenceClass(unsigned int font);
void Render2DSentenceDrawSentence(Render2DSentenceClass *r,const wchar_t *sentence,Vector2 *position,unsigned long color);
Render2DTextClass *CreateRender2DTextClass(const char *texture);
Render2DClass *CreateRender2DClass();
extern IDirect3DDevice9 *Direct3DDevice; //Current Direct3D9 Device 
extern myIDirect3DDevice8 **Direct3DDevice8; //Current Direct3D8 Device (Do not normally use)
extern DX8Caps *CurrentCaps; //Current caps bits
#define DEBUG_COLOR1 D3DCOLOR_XRGB(200,100,100)
#define DEBUG_COLOR2 D3DCOLOR_XRGB(100,200,100)
#define DEBUG_COLOR3 D3DCOLOR_XRGB(100,100,200)
int DebugEventStart(D3DCOLOR color, wchar_t *message,...); //Add a debug event
int DebugEventEnd(); //End a debug event
void DebugEventMarker(D3DCOLOR color, wchar_t *message,...); //Add a debug marker
int DebugGetStatus(); //Get debug status
TextureClass *_stdcall Load_Texture(const char *path,MipCountType mip,WW3DFormat format, bool IsCompressionAllowed); //Load a texture
void _stdcall Free_Texture(TextureClass *texture); //Free a texture
extern RectClass *ScreenResolution; //Current screen resolution
//stuff thats in here because the custom HUD code needs it
extern ReferenceableClass<ScriptableGameObj> **TheStar; //The current player object
extern unsigned int *CompassPos; //current compass position
extern GameObject **BracketObj; //current radar targeting bracket obj
void Seconds_To_Hms(float secs, int &hours, int &minutes, int &seconds); //Convert seconds to HMS
extern float *RadarIntensity; //radar intensity
extern unsigned int *SyncTime; //Current sync time
extern bool *IsNighttime; //Is it nighttime on the current map

extern FontCharsClass **Fonts;