namespace X3DTK {
namespace MESH {

template<class MData, class VData, class EData, class FData, bool RW>
TemplateVerticesDrawerCoreVisitor<MData, VData, EData, FData, RW>::TemplateVerticesDrawerCoreVisitor()
{
  // Enter and leave functions.
  define(Recorder<Transform>::getEnterFunction(&TemplateVerticesDrawerCoreVisitor::enterTransform));
  define(Recorder<TemplateMesh<MData, VData, EData, FData, RW> >::getEnterFunction(&TemplateVerticesDrawerCoreVisitor::enterMesh));
  define(Recorder<Transform>::getLeaveFunction(&TemplateVerticesDrawerCoreVisitor::leaveTransform));
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateVerticesDrawerCoreVisitor<MData, VData, EData, FData, RW>::enterMesh(TemplateMesh<MData, VData, EData, FData, RW> *M)
{
  TemplateVerticesDrawerStateVariables<MData, VData, EData, FData, RW> *stateVariables = Singleton<TemplateVerticesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance();
  stateVariables->storeMesh(M);
  int meshId = stateVariables->getCurrentMeshId();

  if (stateVariables->getSelectionMode())
    glPushName(meshId);

  glColor3f(1.0f, 0.9f, 0.8f);
  if (stateVariables->getSelectionMode())
    glPointSize(5.0f);
  else
    glPointSize(1.0f);
   
  glDisable(GL_LIGHTING);  

  const typename TemplateMesh<MData, VData, EData, FData, RW>::MFVertex &vertices = M->getVertices();

  if (stateVariables->getSelectionMode())
  {
    for (typename TemplateMesh<MData, VData, EData, FData, RW>::MFVertex::const_iterator v = vertices.begin(), end = vertices.end() ; v != end; ++v)
    {
      glPushName((*v)->getIndex());
      #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED
      SFPoint3f point = (*v)->template ogetData<MESH::VertexPointData>().getPoint();
      #else
      SFPoint3f point = (*v)->data().getPoint();
      #endif
      glRasterPos3fv(point.f_data());  
      glPopName();
    }
    glPopName();
  }
  else
  {
    glBegin(GL_POINTS);
    for (typename TemplateMesh<MData, VData, EData, FData, RW>::MFVertex::const_iterator v = vertices.begin(), end = vertices.end() ; v != end; ++v)
    {
      #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED
      SFPoint3f point = (*v)->template ogetData<MESH::VertexPointData>().getPoint();
      #else
      SFPoint3f point = (*v)->data().getPoint();
      #endif
      glVertex3fv(point.f_data());
    }
    glEnd();
  } 
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateVerticesDrawerCoreVisitor<MData, VData, EData, FData, RW>::enterTransform(Transform *T)
{
  TemplateVerticesDrawerStateVariables<MData, VData, EData, FData, RW> *stateVariables = Singleton<TemplateVerticesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance();
  glMatrixMode(GL_MODELVIEW);
  stateVariables->pushMatrix(T->getTransform());
  glPushMatrix();
  glMultMatrixf(T->getTransform().toFloat16());
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateVerticesDrawerCoreVisitor<MData, VData, EData, FData, RW>::leaveTransform(Transform *)
{
  TemplateVerticesDrawerStateVariables<MData, VData, EData, FData, RW> *stateVariables = Singleton<TemplateVerticesDrawerStateVariables<MData, VData, EData, FData, RW> >::getInstance();
  glMatrixMode(GL_MODELVIEW);
  stateVariables->popMatrix();
  glPopMatrix();
}

}
}
