namespace X3DTK {
namespace MESH {

template<class MData, class VData, class EData, class FData, bool RW>
TemplateNormalsUpdater<MData, VData, EData, FData, RW>::TemplateNormalsUpdater()
: X3DMultiPassProcessor()
{
  setGraphTraversal("Faces", new DFSGraphTraversal());
  setGraphTraversal("Vertices", new DFSGraphTraversal());

  setComponentVisitor("Faces", new TemplateNormalsUpdaterFacesCoreVisitor<MData, VData, EData, FData, RW>());
  setComponentVisitor("Vertices", new TemplateNormalsUpdaterVerticesCoreVisitor<MData, VData, EData, FData, RW>());
}

template<class MData, class VData, class EData, class FData, bool RW>
TemplateNormalsUpdater<MData, VData, EData, FData, RW>::~TemplateNormalsUpdater()
{
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateNormalsUpdater<MData, VData, EData, FData, RW>::updateNormals(Scene *S)
{
  updateNormals(static_cast<X3DNode *>(S));
  
  S->getProcessHistory().addEntry("MESH::TemplateNormalsUpdater");
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateNormalsUpdater<MData, VData, EData, FData, RW>::updateNormals(X3DNode *N)
{
  #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED
  if (VData::template find<MESH::VertexNormalData>() 
   && FData::template find<MESH::FaceNormalData>())
  #endif 
  {
    traverse("Faces", N);
  }
  #ifdef TEMPLATE_SPECIALIZATION_SUPPORTED
  if (VData::template find<MESH::VertexNormalData>() 
   && FData::template find<MESH::FaceNormalData>())
  #endif 
  { 
    traverse("Vertices", N);
  }  
}

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

}
}
