namespace X3DTK {
namespace MESH {

template<class MData, class VData, class EData, class FData, bool RW>
TemplateFacesDrawer<MData, VData, EData, FData, RW>::TemplateFacesDrawer()
: X3DOnePassProcessor()
{
  setGraphTraversal(new DFSGraphTraversal());
  setComponentVisitor(new TemplateFacesDrawerCoreVisitor<MData, VData, EData, FData, RW>());
}

template<class MData, class VData, class EData, class FData, bool RW>
TemplateFacesDrawer<MData, VData, EData, FData, RW>::~TemplateFacesDrawer()
{
  Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::removeInstance();
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateFacesDrawer<MData, VData, EData, FData, RW>::changeModel()
{
  Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->clearGLNodes();
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateFacesDrawer<MData, VData, EData, FData, RW>::draw(X3DNode *N, bool selection)
{
  #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED
  if (VData::template find<MESH::VertexPointData>())
  #endif
  {
    Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->setDrawingSelected(false);
    Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->setSelectionMode(selection);
    Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->init();
    traverse(N);
    Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->finish(); 
  }  
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateFacesDrawer<MData, VData, EData, FData, RW>::drawSelected(X3DNode *N)
{
  glDepthFunc(GL_LEQUAL);
  #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED
  if (VData::template find<MESH::VertexPointData>())
  #endif
  {
    Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->setDrawingSelected(true);
    Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->setSelectionMode(false);
    Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->initSelected();
    traverse(N);
  }  
  glDepthFunc(GL_LESS);
}

template<class MData, class VData, class EData, class FData, bool RW>
TemplateMesh<MData, VData, EData, FData, RW> *TemplateFacesDrawer<MData, VData, EData, FData, RW>::getMesh(int i) const 
{
  return Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->getMesh(i);
}

template<class MData, class VData, class EData, class FData, bool RW>
const SFMatrix34f &TemplateFacesDrawer<MData, VData, EData, FData, RW>::getMatrix(int i) const 
{
  return Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->getMatrix(i);
}

template<class MData, class VData, class EData, class FData, bool RW>
SFTemplateFace<MData, VData, EData, FData, RW> *TemplateFacesDrawer<MData, VData, EData, FData, RW>::getFaceOfMesh(int i, int j) const 
{
  return (Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->getMesh(j)->getFaces())[i];
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateFacesDrawer<MData, VData, EData, FData, RW>::setRenderingMode(FaceMode mode)
{
  Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->setRenderingMode(mode);
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateFacesDrawer<MData, VData, EData, FData, RW>::setSelectedNodes(const MFNode &selectedNodes)
{
  Singleton<TemplateFacesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance()->setSelectedNodes(selectedNodes);
}

}
}  
