#ifndef DEF_TX_OBJECT
 #define DEF_TX_OBJECT

//------------------------------------------//
//		TKA4 Main Object Graph classes		//
//				26. 10. 2007				//
//------------------------------------------//


//--- Includes
#include "gl_add.h"

#include "TX_World.h"
//=== Includes 


//--- Defines
#define TwoSqrt  1.4142135623730950488016887242097
#define PI       3.1415926535897932384626433832795
#define PI2      6.283185307179586476925286766559
//=== Defines


//--- Direction of Execution ---//
enum EDirection { 
	d_for,	// Forward
	d_both,	// Forward & Bacward
	d_back,	// Never try to use it!
	
	d_shader,

	d_nothing
};

//------------------------------------


//--- txEngine
class txEngine;	



//--- OBJ Matrix ---//
	class txObjMatrix {
	public:
		GLfloat  t[3];
		GLfloat  r[3];
		GLfloat  s[3];
		
	public : 
		txObjMatrix(){ t[0]=t[1]=t[2]=r[0]=r[1]=r[2]=0; s[0]=s[1]=s[2]=1; };
		
		virtual inline void ZoomIn() { s[2] = s[1] = s[0]+=0.1; };
		virtual inline void ZoomOut() { s[2] = s[1] = s[0]-=0.1; };

		virtual inline void Apply() {
			glTranslatef (t[0], t[1], t[2]);

			glRotatef (r[0], 1, 0, 0);
			glRotatef (r[1], 0, 1, 0);
			glRotatef (r[2], 0, 0, 1);

			glScalef (s[0], s[1], s[2]);
		}
	};
//=== OBJ Matrix ===//



//--- OBJ Color ---//
	class txObjColor {
	public:
		GLfloat  diff[4];
		GLfloat  ambi[4];
		GLfloat  spec[4];
		GLfloat  emis[4];
		GLfloat	 shine;
	
		int *shc;
		txShader *sh;
	
	public : 
		txObjColor(){ 
			shine = 5.0;
			diff[0]=diff[1]=diff[2]=diff[3]=1.0;
			ambi[0]=ambi[1]=ambi[2]=ambi[3]=1.0;
			spec[0]=spec[1]=spec[2]=spec[3]=1.0;
			emis[0]=emis[1]=emis[2]=emis[3]=0.0;
		};
		
		virtual inline void Apply() {
			glColor3fv(diff);

			glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambi);
			glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
			glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
			glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emis);
			glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, shine);

			if (sh)
			if (*shc>0) {
				for (int i = 0; i<*shc; i++) {
					sh[i].Disable();
					
					sh[i].SetData(SV_DIFF_COLOR, diff, 1);
					sh[i].SetData(SV_AMBI_COLOR, ambi, 1);
					sh[i].SetData(SV_SPEC_COLOR, spec, 1);
					sh[i].SetData(SV_EMIS_COLOR, emis, 1);
					sh[i].SetUniformFloat(SV_SHINE_COLOR, shine);
					
					sh[i].Enable();
				}
			}
		};

	};
//=== OBJ Matrix ===//




//---  Abstract Class Object TX  ---//
/*	Base for all Graph Objects.	   */
class txObject {
	friend txEngine;
	
	protected:
		EDirection dir;
		txObject *prev, *next;
		txWorld *World;

	public: 
		txObjMatrix	matrix;
		txObjColor	color;

	public:
		//--- Con-De-structers
		txObject() { prev = NULL; next = NULL; dir = d_for; };

		virtual ~txObject() { };
				
		//--- Executes
		virtual void  Execute_Init() {};
		virtual void  Execute_Forward() {};
		virtual void  Execute_Backward() {};
		
		//--- Other
		EDirection inline  GetDirection() { return dir; };
		void inline  SetDirection(EDirection d) { dir=d; };
};


#endif