// ---------------------------------------------------------------------------
#ifndef TOpenGLAPPanelH
#define TOpenGLAPPanelH
// ---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>

#include "gl.h"  /* Include local "gl.h". Don't include borland <GL/gl.h>. */
#include "glu.h"
#include "BMPTexture.hpp"
#include "OpenGLAPFont3D.hpp"
#include "OpenGLAPFont2D.hpp"

// ---------------------------------------------------------------------------
class TOpenGLAPPanel : public TCustomPanel {
private:
	// ---- Enumerations
	enum TPFDPixelTypes {
		f_PFD_TYPE_RGBA, f_PFD_TYPE_COLORINDEX
	};

	enum TPFDFlags {
		f_PFD_DRAW_TO_WINDOW, f_PFD_DRAW_TO_BITMAP, f_PFD_SUPPORT_GDI,
		f_PFD_SUPPORT_OPENGL, f_PFD_GENERIC_ACCELERATED, f_PFD_GENERIC_FORMAT,
		f_PFD_NEED_PALETTE, f_PFD_NEED_SYSTEM_PALETTE, f_PFD_DOUBLEBUFFER,
		f_PFD_STEREO, f_PFD_SUPPORT_COMPOSITION, f_PFD_SWAP_LAYER_BUFFERS
	};

	enum TOpenGLSwapBuffers {
		Auto, Manual
	};

	enum TOpenGLPrintScale {
		pglNone, pglPrintToFit, pglProportional
	};

	enum TFont3DFormat {
		f_WGL_FONT_LINES, f_WGL_FONT_POLYGONS
	};

	// ---- Types
	typedef Set<TPFDFlags, f_PFD_DRAW_TO_WINDOW,
		f_PFD_SWAP_LAYER_BUFFERS>TPFDFlagsSet;
	// ---- Variables
	HPALETTE Palette;

	TPFDFlagsSet FdwFlags;
	UnicodeString	FVersion;
	bool DoubleBuffer;
	bool AutoSwapbuffers;
	TPFDPixelTypes FiPixelType;
	BYTE SavedPixelType;
	BYTE FcColorBits;
	BYTE FcDepthBits;
	BYTE FcAccBits;
	TOpenGLSwapBuffers FSwapBuffers;

	TOpenGLPrintScale FOpenGLPrintScale;
	int FOpenGLPixelsPerInch;

	bool Font3DEnabled;
	TFont * Font3DType;
	int Font3DFirstGylph;
	int Font3DNumGylph;
	float Font3DMaxDeviation;
	float Font3DExtrusion;
	TFont3DFormat Font3DFormat;
	int SavedFont3DFormat;
	OpenGLAPFont3D * Font3DDefault;

	bool Font2DEnabled;
	TFont * Font2DType;
	int Font2DFirstGylph;
	int Font2DNumGylph;
	OpenGLAPFont2D * Font2DDefault;
	char SystemMessage[255];

	// ---- Performance variables for frame calculation
	LARGE_INTEGER Frequency;
	bool Ffps_Enabled;
	bool FToolWindow;
	bool FBorder;
	bool FAllowResize;
	bool FAllowMoving;
	bool AllowCreateParms;
	// ---- Multi Sample	Support
	bool FMultiSample;
	bool arbMultisampleSupported;
	unsigned int 	FMultiSampleSettings;

	// ---- Error Message
	UnicodeString 	FLastError;

	// ---- Methods
	int MultiSamplePixelFormat(void);
	bool CreateGLContext(void);
	void DestroyGLContext(void);
	bool ConstructPalette(PIXELFORMATDESCRIPTOR &pfd);
	void Create3DFont(void);
	void Create2DFont(void);

	// ---- Property Medthods
	void __fastcall SetToolWindow(const bool Value);
	void __fastcall SetBorder(const bool Value);
	void __fastcall SetAllowResize(const bool Value);
	void __fastcall SetPFDPixelType(const TPFDPixelTypes Value);
	void __fastcall SetPFDFlags(const TPFDFlagsSet Value);

	void __fastcall SetPFDNumColorBits(const BYTE Value);
	void __fastcall SetPFDNumDepthBits(const BYTE Value);
	void __fastcall SetPFDNumAccBits(const BYTE Value);

	void __fastcall SetOpenGLPrintScale(const TOpenGLPrintScale Value);
	void __fastcall SetOpenGLPixelsPerInch(const int Value);

	void __fastcall SetFont3DType(TFont* Value);
	void __fastcall SetFont3DFormat(const TFont3DFormat Value);
	void __fastcall SetFont(TFont* Value);

protected:
	// ---- Variables
	TNotifyEvent FOnPaint, FOnResize, FOnInit, FOnPreInit;
	TGetStrProc	 FOnError;

	// ---- Inherited or Overidden Methods
	virtual void __fastcall CreateParams(TCreateParams &Params);
	virtual void __fastcall Paint();
	void __fastcall Error (UnicodeString LastError);
	DYNAMIC void __fastcall Resize();
	void __fastcall WMCreate(TWMCreate &Message);
	void __fastcall WMPaletteChanged(TWMPaletteChanged &Message);
	void __fastcall WMQueryNewPalette(TWMQueryNewPalette &Message);
	void __fastcall WMDestroy(TWMDestroy &Message);
	void __fastcall WMMove(TWMMove &Message);
	void __fastcall WMEraseBkgnd(TWMEraseBkgnd &Message);

public:
	HDC DisplayDeviceContext;
	HGLRC GLRenderingContext;
	// ----
	int Fps;
	PIXELFORMATDESCRIPTOR dpf; // described pixel format for public use

	__fastcall TOpenGLAPPanel(TComponent* Owner);
	__fastcall ~TOpenGLAPPanel();

	bool __fastcall MakeOpenGLPanelCurrent(void);
	void __fastcall MakeOpenGLPanelNotCurrent(void);
	void __fastcall SwapBuffers(void);
	bool __fastcall PanelShareLists(TOpenGLAPPanel *WithOpenGLPanel);
	OpenGLAPFont3D * __fastcall Create3DFont(TFont *Font, int FirstGylph,
		int NumGylph, float Deviation, float Extrusion, int Format);
	void __fastcall Get3DTextSize(char *Text, GLdouble *XYZ);
	void __fastcall Get3DTextSize(OpenGLAPFont3D *Font, char *Text,
		GLdouble *XYZ);
	void __fastcall Draw3DText(char *Text);
	void __fastcall Draw3DText(OpenGLAPFont3D * Font, char *Text);
	OpenGLAPFont2D * __fastcall Create2DFont(TFont *Font, int FirstGylph,
		int NumGylph);
	void __fastcall Draw2DText(char *Text);
	void __fastcall Draw2DText(OpenGLAPFont2D * Font, char *Text);

	BMPTexture * __fastcall LoadBMPTexture(UnicodeString FileName,
		Boolean WithAlpha);
	int __fastcall LoadTGA(UnicodeString FileName, // ---- Filename
		byte **pixels, unsigned int *width, unsigned int *height,
		unsigned int *format);
	void __fastcall PrinTOpenGLAPPanel(void);
	void __fastcall SaveOpenGLPanelToFile(const UnicodeString FileName);
	bool __fastcall QueryOpenGLExtention(UnicodeString ExtentionName);
	int __fastcall GetDisplayBPP(void);
	bool __fastcall SetDisplayBPP(int);

__published:
	// ---- Inherited Properties
	__property Caption;
	__property Alignment;
	__property Align;
	__property DragCursor;
	__property DragMode;
	__property Enabled;
	__property ParentFont;
	__property ParentShowHint;
	__property PopupMenu;
	__property ShowHint;
	__property TabOrder;
	__property TabStop;
	__property Visible;

	// ...Added Properites
	__property UnicodeString	Version = {read=FVersion};

	__property TPFDPixelTypes PixelType = {
		read = FiPixelType, write = SetPFDPixelType, default = f_PFD_TYPE_RGBA};

	__property TPFDFlagsSet PFDFlags = {
		read = FdwFlags, write = SetPFDFlags, nodefault};

	__property BYTE cColorBits = {
		read = FcColorBits, write = SetPFDNumColorBits, default = 32};

	__property BYTE cDepthBits = {
		read = FcDepthBits, write = SetPFDNumDepthBits, default = 32};

	__property BYTE cAccBits = {
		read = FcAccBits, write = SetPFDNumAccBits, default = 8};

	__property bool MultiSample = {
		read = FMultiSample, write = FMultiSample, default = Auto};
	__property unsigned int MultiSampleSettings = {
		read = FMultiSampleSettings, write = FMultiSampleSettings, default = 4};

	__property TOpenGLSwapBuffers GLSwapBuffers = {
		read = FSwapBuffers, write = FSwapBuffers, default = Auto};

	__property int PixelsPerInch = {
		read = FOpenGLPixelsPerInch, write = SetOpenGLPixelsPerInch,
		default = 96};

	__property TOpenGLPrintScale PrintScale = {
		read = FOpenGLPrintScale, write = SetOpenGLPrintScale, default =
			pglProportional};

	__property bool Font3D_Enabled = {
		read = Font3DEnabled, write = Font3DEnabled, default = false};

	__property TFont * Font3D_Type = {read = Font3DType, write = SetFont3DType};

	__property int Font3D_FirstGylph = {
		read = Font3DFirstGylph, write = Font3DFirstGylph, default = 32};

	__property int Font3D_NumGylph = {
		read = Font3DNumGylph, write = Font3DNumGylph, default = 96};

	__property float Font3D_MaxDeviation = {
		read = Font3DMaxDeviation, write = Font3DMaxDeviation};

	__property float Font3D_Extrustion = {
		read = Font3DExtrusion, write = Font3DExtrusion};

	__property TFont3DFormat Font3D_Format = {
		read = Font3DFormat, write = SetFont3DFormat, default =
			f_WGL_FONT_POLYGONS};

	__property bool Font2D_Enabled = {
		read = Font2DEnabled, write = Font2DEnabled, default = false};

	__property TFont * Font2D_Type = {read = Font2DType, write = SetFont};

	__property int Font2D_FirstGylph = {
		read = Font2DFirstGylph, write = Font2DFirstGylph, default = 32};

	__property int Font2D_NumGylph = {
		read = Font2DNumGylph, write = Font2DNumGylph, default = 96};
	__property bool Fps_Enabled = {
		read = Ffps_Enabled, write = Ffps_Enabled, default = false};

	__property bool Border = {read = FBorder, write = SetBorder, default = false
	};
	__property bool ToolWindow = {
		read = FToolWindow, write = SetToolWindow, default = false};
	__property bool AllowResize = {
		read = FAllowResize, write = SetAllowResize, default = false};
	__property bool AllowMoving = {
		read = FAllowMoving, write = FAllowMoving, default = false};

	// ---- Inherited Events
	__property OnClick;
	__property OnDblClick;
	__property OnDragDrop;
	__property OnDragOver;
	__property OnStartDrag;
	__property OnEndDrag;
	__property OnEnter;
	__property OnExit;
	__property OnMouseDown;
	__property OnMouseMove;
	__property OnMouseUp;
	__property OnMouseWheel;
	__property OnMouseWheelUp;
	__property OnMouseWheelDown;
	__property OnMouseActivate;
	__property OnMouseEnter;
	__property OnMouseLeave;

	// ---- Added Events
	__property TNotifyEvent OnInit = {read = FOnInit, write = FOnInit};
	__property TNotifyEvent OnPreInit = {read = FOnPreInit, write = FOnPreInit};
	__property TGetStrProc  OnError = {read = FOnError, write = FOnError};

	// ---- Overidden Events
	__property TNotifyEvent OnResize = {read = FOnResize, write = FOnResize};
	__property TNotifyEvent OnPaint = {read = FOnPaint, write = FOnPaint};

	// ---- Message Maps
	BEGIN_MESSAGE_MAP VCL_MESSAGE_HANDLER(WM_CREATE, TWMCreate, WMCreate)
		VCL_MESSAGE_HANDLER(WM_DESTROY, TWMDestroy, WMDestroy)
		VCL_MESSAGE_HANDLER(WM_MOVING, TWMMove, WMMove) VCL_MESSAGE_HANDLER
		(WM_PALETTECHANGED, TWMPaletteChanged, WMPaletteChanged)
		VCL_MESSAGE_HANDLER(WM_QUERYNEWPALETTE, TWMQueryNewPalette,
		WMQueryNewPalette) VCL_MESSAGE_HANDLER(WM_ERASEBKGND, TWMEraseBkgnd,
		WMEraseBkgnd) END_MESSAGE_MAP(TCustomPanel)
};
// ---------------------------------------------------------------------------
#endif

// ---------------------------------------------------------------------------
