Commit 7bb2d103 authored by Pierre Kraemer's avatar Pierre Kraemer

SCHNApps: first version of attributes auto update

parent 9da47178
...@@ -28,8 +28,6 @@ public slots: ...@@ -28,8 +28,6 @@ public slots:
void addMapToList(MapHandlerGen* m); void addMapToList(MapHandlerGen* m);
void removeMapFromList(MapHandlerGen* m); void removeMapFromList(MapHandlerGen* m);
void addAttributeToList(unsigned int orbit, const QString& nameAttr); void addAttributeToList(unsigned int orbit, const QString& nameAttr);
void attributeModified(unsigned int orbit, QString nameAttr);
}; };
} // namespace SCHNApps } // namespace SCHNApps
......
...@@ -38,18 +38,22 @@ public: ...@@ -38,18 +38,22 @@ public:
virtual void wheelEvent(View* view, QWheelEvent* event) {} virtual void wheelEvent(View* view, QWheelEvent* event) {}
public slots: public slots:
void mapAdded(MapHandlerGen* map);
void mapRemoved(MapHandlerGen* map);
void attributeModified(unsigned int orbit, QString nameAttr);
void openComputeNormalDialog(); void openComputeNormalDialog();
void openComputeCurvatureDialog(); void openComputeCurvatureDialog();
void computeNormalFromDialog(); void computeNormalFromDialog();
void computeCurvatureFromDialog(); void computeCurvatureFromDialog();
void computeNormal( void computeNormal(const QString& mapName,
const QString& mapName,
const QString& positionAttributeName = "position", const QString& positionAttributeName = "position",
const QString& normalAttributeName = "normal", const QString& normalAttributeName = "normal",
bool createNormalVBO = true bool createNormalVBO = true,
); bool autoUpdateNormal = true);
void computeCurvature( void computeCurvature(
const QString& mapName, const QString& mapName,
const QString& positionAttributeName = "position", const QString& positionAttributeName = "position",
...@@ -63,7 +67,12 @@ public slots: ...@@ -63,7 +67,12 @@ public slots:
bool createkmaxVBO = true, bool createkmaxVBO = true,
bool createKminVBO = true, bool createKminVBO = true,
bool createkminVBO = true, bool createkminVBO = true,
bool createKnormalVBO = true bool createKnormalVBO = true,
bool autoUpdateKmax = true,
bool autoUpdatekmax = true,
bool autoUpdateKmin = true,
bool autoUpdatekmin = true,
bool autoUpdateKnormal = true
); );
private: private:
...@@ -76,9 +85,13 @@ private: ...@@ -76,9 +85,13 @@ private:
struct ComputeNormalParameters struct ComputeNormalParameters
{ {
ComputeNormalParameters() {} ComputeNormalParameters() {}
ComputeNormalParameters(QString p, QString n) : positionName(p), normalName(n) {} ComputeNormalParameters(QString p, QString n, bool vbo, bool update) :
positionName(p), normalName(n), createVBO(vbo), autoUpdate(update)
{}
QString positionName; QString positionName;
QString normalName; QString normalName;
bool createVBO;
bool autoUpdate;
}; };
QHash<QString, ComputeNormalParameters> computeNormalLastParameters; QHash<QString, ComputeNormalParameters> computeNormalLastParameters;
}; };
......
...@@ -105,15 +105,6 @@ void ComputeNormalDialog::addAttributeToList(unsigned int orbit, const QString& ...@@ -105,15 +105,6 @@ void ComputeNormalDialog::addAttributeToList(unsigned int orbit, const QString&
} }
} }
void ComputeNormalDialog::attributeModified(unsigned int orbit, QString nameAttr)
{
MapHandlerGen* map = static_cast<MapHandlerGen*>(QObject::sender());
// if(orbit == VERTEX && nameAttr == )
// {
// }
}
} // namespace SCHNApps } // namespace SCHNApps
} // namespace CGoGN } // namespace CGoGN
...@@ -25,9 +25,36 @@ bool DifferentialPropertiesPlugin::enable() ...@@ -25,9 +25,36 @@ bool DifferentialPropertiesPlugin::enable()
connect(m_computeCurvatureDialog, SIGNAL(accepted()), this, SLOT(computeCurvatureFromDialog())); connect(m_computeCurvatureDialog, SIGNAL(accepted()), this, SLOT(computeCurvatureFromDialog()));
connect(m_computeCurvatureDialog->button_apply, SIGNAL(clicked()), this, SLOT(computeCurvatureFromDialog())); connect(m_computeCurvatureDialog->button_apply, SIGNAL(clicked()), this, SLOT(computeCurvatureFromDialog()));
connect(m_window, SIGNAL(mapAdded(MapHandlerGen*)), this, SLOT(mapAdded(MapHandlerGen*)));
connect(m_window, SIGNAL(mapRemoved(MapHandlerGen*)), this, SLOT(mapRemoved(MapHandlerGen*)));
return true; return true;
} }
void DifferentialPropertiesPlugin::mapAdded(MapHandlerGen *map)
{
connect(map, SIGNAL(attributeModified(unsigned int, QString)), this, SLOT(attributeModified(unsigned int, QString)));
}
void DifferentialPropertiesPlugin::mapRemoved(MapHandlerGen *map)
{
disconnect(map, SIGNAL(attributeModified(unsigned int, QString)), this, SLOT(attributeModified(unsigned int, QString)));
}
void DifferentialPropertiesPlugin::attributeModified(unsigned int orbit, QString nameAttr)
{
if(orbit == VERTEX)
{
MapHandlerGen* map = static_cast<MapHandlerGen*>(QObject::sender());
if(computeNormalLastParameters.contains(map->getName()))
{
ComputeNormalParameters& params = computeNormalLastParameters[map->getName()];
if(params.positionName == nameAttr && params.autoUpdate)
computeNormal(map->getName(), params.positionName, params.normalName, params.createVBO);
}
}
}
void DifferentialPropertiesPlugin::openComputeNormalDialog() void DifferentialPropertiesPlugin::openComputeNormalDialog()
{ {
m_computeNormalDialog->show(); m_computeNormalDialog->show();
...@@ -46,6 +73,7 @@ void DifferentialPropertiesPlugin::computeNormalFromDialog() ...@@ -46,6 +73,7 @@ void DifferentialPropertiesPlugin::computeNormalFromDialog()
const QString& mapName = currentItems[0]->text(); const QString& mapName = currentItems[0]->text();
QString positionName = m_computeNormalDialog->combo_positionAttribute->currentText(); QString positionName = m_computeNormalDialog->combo_positionAttribute->currentText();
QString normalName; QString normalName;
if(m_computeNormalDialog->normalAttributeName->text().isEmpty()) if(m_computeNormalDialog->normalAttributeName->text().isEmpty())
normalName = m_computeNormalDialog->combo_normalAttribute->currentText(); normalName = m_computeNormalDialog->combo_normalAttribute->currentText();
...@@ -54,7 +82,9 @@ void DifferentialPropertiesPlugin::computeNormalFromDialog() ...@@ -54,7 +82,9 @@ void DifferentialPropertiesPlugin::computeNormalFromDialog()
bool createVBO = (m_computeNormalDialog->check_createVBO->checkState() == Qt::Checked); bool createVBO = (m_computeNormalDialog->check_createVBO->checkState() == Qt::Checked);
computeNormal(mapName, positionName, normalName, createVBO); bool autoUpdate = (currentItems[0]->checkState() == Qt::Checked);
computeNormal(mapName, positionName, normalName, createVBO, autoUpdate);
} }
} }
...@@ -73,39 +103,34 @@ void DifferentialPropertiesPlugin::computeCurvatureFromDialog() ...@@ -73,39 +103,34 @@ void DifferentialPropertiesPlugin::computeCurvatureFromDialog()
KmaxName = m_computeCurvatureDialog->combo_KmaxAttribute->currentText(); KmaxName = m_computeCurvatureDialog->combo_KmaxAttribute->currentText();
else else
KmaxName = m_computeCurvatureDialog->KmaxAttributeName->text(); KmaxName = m_computeCurvatureDialog->KmaxAttributeName->text();
bool KmaxVBO = (m_computeCurvatureDialog->check_KmaxCreateVBO->checkState() == Qt::Checked);
QString kmaxName; QString kmaxName;
if(m_computeCurvatureDialog->kmaxAttributeName->text().isEmpty()) if(m_computeCurvatureDialog->kmaxAttributeName->text().isEmpty())
kmaxName = m_computeCurvatureDialog->combo_kmaxAttribute->currentText(); kmaxName = m_computeCurvatureDialog->combo_kmaxAttribute->currentText();
else else
kmaxName = m_computeCurvatureDialog->kmaxAttributeName->text(); kmaxName = m_computeCurvatureDialog->kmaxAttributeName->text();
bool kmaxVBO = (m_computeCurvatureDialog->check_kmaxCreateVBO->checkState() == Qt::Checked);
QString KminName; QString KminName;
if(m_computeCurvatureDialog->KminAttributeName->text().isEmpty()) if(m_computeCurvatureDialog->KminAttributeName->text().isEmpty())
KminName = m_computeCurvatureDialog->combo_KminAttribute->currentText(); KminName = m_computeCurvatureDialog->combo_KminAttribute->currentText();
else else
KminName = m_computeCurvatureDialog->KminAttributeName->text(); KminName = m_computeCurvatureDialog->KminAttributeName->text();
bool KminVBO = (m_computeCurvatureDialog->check_KminCreateVBO->checkState() == Qt::Checked);
QString kminName; QString kminName;
if(m_computeCurvatureDialog->kminAttributeName->text().isEmpty()) if(m_computeCurvatureDialog->kminAttributeName->text().isEmpty())
kminName = m_computeCurvatureDialog->combo_kminAttribute->currentText(); kminName = m_computeCurvatureDialog->combo_kminAttribute->currentText();
else else
kminName = m_computeCurvatureDialog->kminAttributeName->text(); kminName = m_computeCurvatureDialog->kminAttributeName->text();
bool kminVBO = (m_computeCurvatureDialog->check_kminCreateVBO->checkState() == Qt::Checked);
QString KnormalName; QString KnormalName;
if(m_computeCurvatureDialog->KnormalAttributeName->text().isEmpty()) if(m_computeCurvatureDialog->KnormalAttributeName->text().isEmpty())
KnormalName = m_computeCurvatureDialog->combo_KnormalAttribute->currentText(); KnormalName = m_computeCurvatureDialog->combo_KnormalAttribute->currentText();
else else
KnormalName = m_computeCurvatureDialog->KnormalAttributeName->text(); KnormalName = m_computeCurvatureDialog->KnormalAttributeName->text();
bool KmaxVBO = (m_computeCurvatureDialog->check_KmaxCreateVBO->checkState() == Qt::Checked);
bool kmaxVBO = (m_computeCurvatureDialog->check_kmaxCreateVBO->checkState() == Qt::Checked);
bool KminVBO = (m_computeCurvatureDialog->check_KminCreateVBO->checkState() == Qt::Checked);
bool kminVBO = (m_computeCurvatureDialog->check_kminCreateVBO->checkState() == Qt::Checked);
bool KnormalVBO = (m_computeCurvatureDialog->check_KnormalCreateVBO->checkState() == Qt::Checked); bool KnormalVBO = (m_computeCurvatureDialog->check_KnormalCreateVBO->checkState() == Qt::Checked);
computeCurvature( computeCurvature(
...@@ -119,7 +144,8 @@ void DifferentialPropertiesPlugin::computeNormal( ...@@ -119,7 +144,8 @@ void DifferentialPropertiesPlugin::computeNormal(
const QString& mapName, const QString& mapName,
const QString& positionAttributeName, const QString& positionAttributeName,
const QString& normalAttributeName, const QString& normalAttributeName,
bool createNormalVBO) bool createNormalVBO,
bool autoUpdateNormal)
{ {
MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_window->getMap(mapName)); MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_window->getMap(mapName));
if(mh == NULL) if(mh == NULL)
...@@ -140,7 +166,9 @@ void DifferentialPropertiesPlugin::computeNormal( ...@@ -140,7 +166,9 @@ void DifferentialPropertiesPlugin::computeNormal(
mh->createVBO(normal); mh->createVBO(normal);
computeNormalLastParameters[mapName] = computeNormalLastParameters[mapName] =
ComputeNormalParameters(positionAttributeName, normalAttributeName) ; ComputeNormalParameters(positionAttributeName, normalAttributeName, createNormalVBO, autoUpdateNormal) ;
mh->notifyAttributeModification(normal);
QList<View*> views = mh->getLinkedViews(); QList<View*> views = mh->getLinkedViews();
foreach(View* view, views) foreach(View* view, views)
...@@ -160,7 +188,12 @@ void DifferentialPropertiesPlugin::computeCurvature( ...@@ -160,7 +188,12 @@ void DifferentialPropertiesPlugin::computeCurvature(
bool createkmaxVBO, bool createkmaxVBO,
bool createKminVBO, bool createKminVBO,
bool createkminVBO, bool createkminVBO,
bool createKnormalVBO) bool createKnormalVBO,
bool autoUpdateKmax,
bool autoUpdatekmax,
bool autoUpdateKmin,
bool autoUpdatekmin,
bool autoUpdateKnormal)
{ {
MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_window->getMap(mapName)); MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_window->getMap(mapName));
if(mh == NULL) if(mh == NULL)
......
...@@ -4,9 +4,11 @@ ...@@ -4,9 +4,11 @@
#include "plugin.h" #include "plugin.h"
using namespace CGoGN; namespace CGoGN
using namespace SCHNApps; {
namespace SCHNApps
{
class ImportSurfacePlugin : public Plugin class ImportSurfacePlugin : public Plugin
{ {
...@@ -42,4 +44,8 @@ private: ...@@ -42,4 +44,8 @@ private:
QAction* importAction; QAction* importAction;
}; };
} // namespace SCHNApps
} // namespace CGoGN
#endif #endif
...@@ -7,6 +7,12 @@ ...@@ -7,6 +7,12 @@
#include <QFileDialog> #include <QFileDialog>
#include <QFileInfo> #include <QFileInfo>
namespace CGoGN
{
namespace SCHNApps
{
bool ImportSurfacePlugin::enable() bool ImportSurfacePlugin::enable()
{ {
importAction = new QAction("import", this); importAction = new QAction("import", this);
...@@ -30,12 +36,15 @@ MapHandlerGen* ImportSurfacePlugin::importFromFile(const QString& fileName) ...@@ -30,12 +36,15 @@ MapHandlerGen* ImportSurfacePlugin::importFromFile(const QString& fileName)
Algo::Surface::Import::importMesh<PFP2>(*map, fileName.toStdString(), attrNames); Algo::Surface::Import::importMesh<PFP2>(*map, fileName.toStdString(), attrNames);
// get vertex position attribute // get vertex position attribute
VertexAttribute<PFP2::VEC3> position = map->getAttribute<PFP2::VEC3, CGoGN::VERTEX>(attrNames[0]); VertexAttribute<PFP2::VEC3> position = map->getAttribute<PFP2::VEC3, VERTEX>(attrNames[0]);
mh->registerAttribute<PFP2::VEC3, VERTEX>(position); mh->registerAttribute(position);
// create VBO for vertex position attribute // create VBO for vertex position attribute
mh->createVBO(position); mh->createVBO(position);
// update corresponding VBO & emit attribute update signal
mh->notifyAttributeModification(position);
// compute map bounding box // compute map bounding box
mh->updateBB(position); mh->updateBB(position);
} }
...@@ -56,3 +65,7 @@ Q_EXPORT_PLUGIN2(ImportSurfacePlugin, ImportSurfacePlugin) ...@@ -56,3 +65,7 @@ Q_EXPORT_PLUGIN2(ImportSurfacePlugin, ImportSurfacePlugin)
#else #else
Q_EXPORT_PLUGIN2(ImportSurfacePluginD, ImportSurfacePlugin) Q_EXPORT_PLUGIN2(ImportSurfacePluginD, ImportSurfacePlugin)
#endif #endif
} // namespace SCHNApps
} // namespace CGoGN
...@@ -4,9 +4,11 @@ ...@@ -4,9 +4,11 @@
#include "plugin.h" #include "plugin.h"
using namespace CGoGN; namespace CGoGN
using namespace SCHNApps; {
namespace SCHNApps
{
class ImportVolumePlugin : public Plugin class ImportVolumePlugin : public Plugin
{ {
...@@ -42,4 +44,8 @@ private: ...@@ -42,4 +44,8 @@ private:
QAction* importAction; QAction* importAction;
}; };
} // namespace SCHNApps
} // namespace CGoGN
#endif #endif
...@@ -7,6 +7,12 @@ ...@@ -7,6 +7,12 @@
#include <QFileDialog> #include <QFileDialog>
#include <QFileInfo> #include <QFileInfo>
namespace CGoGN
{
namespace SCHNApps
{
bool ImportVolumePlugin::enable() bool ImportVolumePlugin::enable()
{ {
importAction = new QAction("import", this); importAction = new QAction("import", this);
...@@ -30,12 +36,15 @@ MapHandlerGen* ImportVolumePlugin::importFromFile(const QString& fileName) ...@@ -30,12 +36,15 @@ MapHandlerGen* ImportVolumePlugin::importFromFile(const QString& fileName)
Algo::Volume::Import::importMesh<PFP3>(*map, fileName.toStdString(), attrNames); Algo::Volume::Import::importMesh<PFP3>(*map, fileName.toStdString(), attrNames);
// get vertex position attribute // get vertex position attribute
VertexAttribute<PFP3::VEC3> position = map->getAttribute<PFP3::VEC3, CGoGN::VERTEX>(attrNames[0]); VertexAttribute<PFP3::VEC3> position = map->getAttribute<PFP3::VEC3, VERTEX>(attrNames[0]);
mh->registerAttribute<PFP2::VEC3, VERTEX>(position); mh->registerAttribute(position);
// create VBO for vertex position attribute // create VBO for vertex position attribute
mh->createVBO(position); mh->createVBO(position);
// update corresponding VBO & emit attribute update signal
mh->notifyAttributeModification(position);
// compute map bounding box // compute map bounding box
mh->updateBB(position); mh->updateBB(position);
} }
...@@ -56,3 +65,7 @@ Q_EXPORT_PLUGIN2(ImportVolumePlugin, ImportVolumePlugin) ...@@ -56,3 +65,7 @@ Q_EXPORT_PLUGIN2(ImportVolumePlugin, ImportVolumePlugin)
#else #else
Q_EXPORT_PLUGIN2(ImportVolumePluginD, ImportVolumePlugin) Q_EXPORT_PLUGIN2(ImportVolumePluginD, ImportVolumePlugin)
#endif #endif
} // namespace SCHNApps
} // namespace CGoGN
...@@ -38,11 +38,24 @@ public: ...@@ -38,11 +38,24 @@ public:
public slots: public slots:
void openSubdivideSurfaceDialog(); void openSubdivideSurfaceDialog();
void subdivideSurface(); void subdivideSurfaceFromDialog();
void loopSubdivision(PFP2::MAP* map, VertexAttribute<PFP2::VEC3>& position); void loopSubdivision(
void CCSubdivision(PFP2::MAP* map, VertexAttribute<PFP2::VEC3>& position); const QString& mapName,
void trianguleFaces(PFP2::MAP* map, VertexAttribute<PFP2::VEC3>& position); const QString& positionAttributeName = "position"
);
void CCSubdivision(
const QString& mapName,
const QString& positionAttributeName = "position"
);
void trianguleFaces(
const QString& mapName,
const QString& positionAttributeName = "position"
);
// void loopSubdivision(PFP2::MAP* map, VertexAttribute<PFP2::VEC3>& position);
// void CCSubdivision(PFP2::MAP* map, VertexAttribute<PFP2::VEC3>& position);
// void trianguleFaces(PFP2::MAP* map, VertexAttribute<PFP2::VEC3>& position);
private: private:
SubdivideSurfaceDialog* m_subdivideSurfaceDialog; SubdivideSurfaceDialog* m_subdivideSurfaceDialog;
......
...@@ -20,8 +20,8 @@ bool SubdivideSurfacePlugin::enable() ...@@ -20,8 +20,8 @@ bool SubdivideSurfacePlugin::enable()
connect(m_subdivideSurfaceAction, SIGNAL(triggered()), this, SLOT(openSubdivideSurfaceDialog())); connect(m_subdivideSurfaceAction, SIGNAL(triggered()), this, SLOT(openSubdivideSurfaceDialog()));
connect(m_subdivideSurfaceDialog, SIGNAL(accepted()), this, SLOT(subdivideSurface())); connect(m_subdivideSurfaceDialog, SIGNAL(accepted()), this, SLOT(subdivideSurfaceFromDialog()));
connect(m_subdivideSurfaceDialog->button_apply, SIGNAL(clicked()), this, SLOT(subdivideSurface())); connect(m_subdivideSurfaceDialog->button_apply, SIGNAL(clicked()), this, SLOT(subdivideSurfaceFromDialog()));
return true; return true;
} }
...@@ -31,50 +31,90 @@ void SubdivideSurfacePlugin::openSubdivideSurfaceDialog() ...@@ -31,50 +31,90 @@ void SubdivideSurfacePlugin::openSubdivideSurfaceDialog()
m_subdivideSurfaceDialog->show(); m_subdivideSurfaceDialog->show();
} }
void SubdivideSurfacePlugin::subdivideSurface() void SubdivideSurfacePlugin::subdivideSurfaceFromDialog()
{ {
QList<QListWidgetItem*> currentItems = m_subdivideSurfaceDialog->mapList->selectedItems(); QList<QListWidgetItem*> currentItems = m_subdivideSurfaceDialog->mapList->selectedItems();
if(!currentItems.empty()) if(!currentItems.empty())
{ {
const QString& mapname = currentItems[0]->text(); const QString& mapName = currentItems[0]->text();
MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_window->getMap(mapname)); const QString& positionName = m_subdivideSurfaceDialog->combo_positionAttribute->currentText();
PFP2::MAP* map = mh->getMap();
std::string positionName = m_subdivideSurfaceDialog->combo_positionAttribute->currentText().toStdString();
VertexAttribute<PFP2::VEC3> position = map->getAttribute<PFP2::VEC3, VERTEX>(positionName);
if(m_subdivideSurfaceDialog->radio_Loop->isChecked()) if(m_subdivideSurfaceDialog->radio_Loop->isChecked())
loopSubdivision(map, position); loopSubdivision(mapName, positionName);
else if(m_subdivideSurfaceDialog->radio_CC->isChecked()) else if(m_subdivideSurfaceDialog->radio_CC->isChecked())
CCSubdivision(map, position); CCSubdivision(mapName, positionName);
else if(m_subdivideSurfaceDialog->radio_trianguleFaces->isChecked()) else if(m_subdivideSurfaceDialog->radio_trianguleFaces->isChecked())
trianguleFaces(map, position); trianguleFaces(mapName, positionName);
mh->setPrimitiveDirty(Algo::Render::GL2::POINTS);
mh->setPrimitiveDirty(Algo::Render::GL2::LINES);
mh->setPrimitiveDirty(Algo::Render::GL2::TRIANGLES);
mh->updateVBO(position);
QList<View*> views = mh->getLinkedViews();
foreach(View* view, views)
view->updateGL();
} }
} }
void SubdivideSurfacePlugin::loopSubdivision(PFP2::MAP* map, VertexAttribute<PFP2::VEC3>& position) void SubdivideSurfacePlugin::loopSubdivision(
const QString& mapName,
const QString& positionAttributeName)
{ {
MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_window->getMap(mapName));
if(mh == NULL)
return;
VertexAttribute<PFP2::VEC3> position = mh->getAttribute<PFP2::VEC3, VERTEX>(positionAttributeName);
if(!position.isValid())
return;
PFP2::MAP* map = mh->getMap();
Algo::Surface::Modelisation::LoopSubdivision<PFP2>(*map, position); Algo::Surface::Modelisation::LoopSubdivision<PFP2>(*map, position);
mh->notifyAttributeModification(position);
mh->notifyConnectivityModification();
QList<View*> views = mh->getLinkedViews();
foreach(View* view, views)
view->updateGL();
} }
void SubdivideSurfacePlugin::CCSubdivision(PFP2::MAP* map, VertexAttribute<PFP2::VEC3>& position) void SubdivideSurfacePlugin::CCSubdivision(
const QString& mapName,
const QString& positionAttributeName)
{ {
MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_window->getMap(mapName));