// Liquid3D - Moteur 3D C++ NDS par Morukutsu
// Surcouche de l'ulibrary de Brunni
// Version alpha 1

#include "../L3DTypes.h"
#include <ulib/ulib.h>

#ifndef _H_L3DSCENENODE
#define _H_L3DSCENENODE

#define SCENENODE_MAX_CHILDREN		8

#define NODETYPE_CUBE		0
#define NODETYPE_CAM		1
#define NODETYPE_MD2MESH	2
#define NODETYPE_BINMESH	3
#define NODETYPE_SKYDOME	4

namespace L3D
{
	// - - - - - - - - -
	// Classe CSceneNode - noeud pour le scene manager
	// - - - - - - - - - 
	class CSceneNode
	{
	public:
		CSceneNode()
		{ 
			mScaleEns = mScaleObj = v3d(4096, 4096, 4096);
			for(unsigned int k = 0; k < SCENENODE_MAX_CHILDREN; k++)
				mChildren[k] = NULL;
			mAlpha = 31;
			mChildrenCount = 0;
			mSpecularColor = mAmbientColor = mEmissiveColor = 0;
		}
		//Modifie la matrice de transformation de cet objet uniquement
		void TranslateObj(v3d trans) { mPosObj = trans; };
		void RotateObj(v3d rot) { mRotObj = rot; };
		void ScaleObj(v3d scale) { mScaleObj = scale; };
		//Modifie la matrice de transformation de cet objet et de tout ses fils
		void Translate(v3d trans) { mPosEns = trans; };
		void Rotate(v3d rot) { mRotEns = rot; };
		void Scale(v3d scale) { mScaleEns = scale; };
		//Attache un noeud à celui ci si il y a de la place
		void Bind(CSceneNode* child) 
		{ 
			//On cherche la 1ère place libre
			for(int k = 0; k < SCENENODE_MAX_CHILDREN; k++)
			{
				if(mChildren[k] == NULL)
				{
					mChildren[k] = child;
					mChildrenCount++;
					break;
				}
			}
		}
		void Unbind(CSceneNode* child)
		{
			for(unsigned int k = 0; k < SCENENODE_MAX_CHILDREN; k++)
			if(mChildren[k] == child)
			{
				//On prend le dernier noeud qu'on va mettre à la place de celui-ci
				mChildren[k] = mChildren[mChildrenCount-1];
				mChildren[mChildrenCount-1] = NULL;
				mChildrenCount--;
				break;
			}
		}
		void SetMaterial(int glMat, int value)
		{
			switch(glMat)
			{
			case GL_SPECULAR:
				mSpecularColor = value;
				break;
			case GL_AMBIENT:
				mAmbientColor = value;
				break;
			case GL_EMISSION:
				mEmissiveColor = value;
				break;
			}
		}
		//Fonctons spécifiques aux différents types de noeuds
		virtual void Draw() = 0;
		virtual void Update() = 0;

	public:
		v3d mPosEns, mRotEns, mScaleEns;				//Matrice de transformation de cet objet et de ses fils
		v3d mPosObj, mRotObj, mScaleObj;				//Matrice de transformation de cet objet
		CSceneNode* mChildren[SCENENODE_MAX_CHILDREN];	//Noeuds enfants
		unsigned int mChildrenCount;					//Nombre de noeuds enfants
		int mAlpha;										//Valeur alpha du noeud (0-31) (0 = wireframe, 1 = presque transparent, 31 = visible)
		int mNodeType;									//Type de noeud
		
		//Matériaux
		int mSpecularColor, mAmbientColor, mEmissiveColor;
		//SetMaterial
	};
};

#endif