diff --git a/toonz/sources/include/tools/assistant.h b/toonz/sources/include/tools/assistant.h
index 5be247d..86686f8 100644
--- a/toonz/sources/include/tools/assistant.h
+++ b/toonz/sources/include/tools/assistant.h
@@ -192,11 +192,11 @@ public:
 
 
 //*****************************************************************************************
-//    TAssistant definition
+//    TAssistantBase definition
 //*****************************************************************************************
 
-class DVAPI TAssistant : public TMetaObjectHandler {
-  Q_DECLARE_TR_FUNCTIONS(TAssistant)
+class DVAPI TAssistantBase : public TMetaObjectHandler {
+  Q_DECLARE_TR_FUNCTIONS(TAssistantBase)
 protected:
   const TStringId m_idEnabled;
   const TStringId m_idPoints;
@@ -211,7 +211,7 @@ protected:
   mutable TPropertyGroup m_properties;
 
 public:
-  TAssistant(TMetaObject &object);
+  TAssistantBase(TMetaObject &object);
 
   static QString getLocalName()
     { return QString(); }
@@ -237,11 +237,6 @@ public:
   void setEnabled(bool x)
     { if (getEnabled() != x) data()[m_idEnabled].setBool(x); }
 
-  double getMagnetism() const
-    { return data()[m_idMagnetism].getDouble(); }
-  void setMagnetism(double x)
-    { if (getMagnetism() != x) data()[m_idMagnetism].setDouble(x); }
-
   inline void selectPoint(const TStringId &name) const
     { setPointSelection(name, true); }
   inline void deselectPoint(const TStringId &name) const
@@ -249,7 +244,7 @@ public:
   inline void selectAll() const
     { setAllPointsSelection(true); }
   inline void deselectAll() const
-  { setAllPointsSelection(false); }
+    { setAllPointsSelection(false); }
 
   TPropertyGroup& getProperties() const
     { return m_properties; }
@@ -300,7 +295,7 @@ protected:
   //! try to move point
   virtual void onMovePoint(TAssistantPoint &point, const TPointD &position);
   //! save object data to variant
-  virtual void onFixData();
+  void onFixData() override;
   //! load all properties from variant
   virtual void updateProperties();
   //! load single property from variant
@@ -326,10 +321,34 @@ protected:
 
 public:
   virtual void updateTranslation() const;
-  virtual void getGuidelines(const TPointD &position, const TAffine &toTool, TGuidelineList &outGuidelines) const;
   virtual void draw(TToolViewer *viewer, bool enabled) const;
   void draw(TToolViewer *viewer) const { draw(viewer, true); }
   virtual void drawEdit(TToolViewer *viewer) const;
+};
+
+
+//*****************************************************************************************
+//    TAssistant definition
+//*****************************************************************************************
+
+class DVAPI TAssistant : public TAssistantBase {
+protected:
+  const TStringId m_idMagnetism;
+
+  void onSetDefaults() override;
+  void onFixData() override;
+
+public:
+  TAssistant(TMetaObject &object);
+
+  double getMagnetism() const
+    { return data()[m_idMagnetism].getDouble(); }
+  void setMagnetism(double x)
+    { if (getMagnetism() != x) data()[m_idMagnetism].setDouble(x); }
+
+public:
+  void updateTranslation() const override;
+  virtual void getGuidelines(const TPointD &position, const TAffine &toTool, TGuidelineList &outGuidelines) const;
 
   static bool calcPerspectiveStep(
     double minStep,
diff --git a/toonz/sources/tnztools/assistant.cpp b/toonz/sources/tnztools/assistant.cpp
index d43d4c8..7171cfe 100644
--- a/toonz/sources/tnztools/assistant.cpp
+++ b/toonz/sources/tnztools/assistant.cpp
@@ -145,26 +145,24 @@ TAssistantType::createHandler(TMetaObject &obj) const
 
 
 //************************************************************************
-//    TAssistant implementation
+//    TAssistantBase implementation
 //************************************************************************
 
-TAssistant::TAssistant(TMetaObject &object):
+TAssistantBase::TAssistantBase(TMetaObject &object):
   TMetaObjectHandler(object),
   m_idEnabled("enabled"),
   m_idPoints("points"),
   m_idX("x"),
   m_idY("y"),
-  m_idMagnetism("magnetism"),
   m_basePoint()
 {
   addProperty( new TBoolProperty(m_idEnabled.str(), getEnabled()) );
-  addProperty( new TDoubleProperty(m_idMagnetism.str(), 0.0, 1.0, getMagnetism()) );
 }
 
 //---------------------------------------------------------------------------------------------------
 
 TAssistantPoint&
-TAssistant::addPoint(
+TAssistantBase::addPoint(
   const TStringId &name,
   TAssistantPoint::Type type,
   const TPointD &defPosition,
@@ -185,7 +183,7 @@ TAssistant::addPoint(
 //---------------------------------------------------------------------------------------------------
 
 TAssistantPoint&
-TAssistant::addPoint(
+TAssistantBase::addPoint(
   const TStringId &name,
   TAssistantPoint::Type type,
   const TPointD &defPosition,
@@ -195,35 +193,32 @@ TAssistant::addPoint(
 //---------------------------------------------------------------------------------------------------
 
 const TAssistantPoint&
-TAssistant::getBasePoint() const
+TAssistantBase::getBasePoint() const
   { assert(m_basePoint); return *m_basePoint; }
 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::addProperty(TProperty *p)
+TAssistantBase::addProperty(TProperty *p)
   { m_properties.add(p); }
 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::setTranslation(const TStringId &name, const QString &localName) const
+TAssistantBase::setTranslation(const TStringId &name, const QString &localName) const
   { m_properties.getProperty(name)->setQStringName( localName ); }
 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::updateTranslation() const {
-  setTranslation(m_idEnabled, tr("Enabled"));
-  setTranslation(m_idMagnetism, tr("Magnetism"));
-}
+TAssistantBase::updateTranslation() const
+  { setTranslation(m_idEnabled, tr("Enabled")); }
 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::onSetDefaults() {
+TAssistantBase::onSetDefaults() {
   setEnabled(true);
-  setMagnetism(1.0);
   for(TAssistantPointMap::iterator i = m_points.begin(); i != m_points.end(); ++i)
     i->second.position = i->second.defPosition;
   fixPoints();
@@ -233,13 +228,13 @@ TAssistant::onSetDefaults() {
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::fixPoints()
+TAssistantBase::fixPoints()
   { onFixPoints(); }
 
 //---------------------------------------------------------------------------------------------------
 
 bool
-TAssistant::move(const TPointD &position) {
+TAssistantBase::move(const TPointD &position) {
   TPointD d = position - getBasePoint().position;
   if (d != TPointD()) {
     for(TAssistantPointMap::iterator i = m_points.begin(); i != m_points.end(); ++i)
@@ -253,7 +248,7 @@ TAssistant::move(const TPointD &position) {
 //---------------------------------------------------------------------------------------------------
 
 bool
-TAssistant::movePoint(const TStringId &name, const TPointD &position) {
+TAssistantBase::movePoint(const TStringId &name, const TPointD &position) {
   TAssistantPointMap::iterator i = m_points.find(name);
   if (i != m_points.end() && i->second.position != position) {
     onMovePoint(i->second, position);
@@ -265,7 +260,7 @@ TAssistant::movePoint(const TStringId &name, const TPointD &position) {
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::setPointSelection(const TStringId &name, bool selected)  const {
+TAssistantBase::setPointSelection(const TStringId &name, bool selected)  const {
   if (const TAssistantPoint *p = findPoint(name))
     p->selected = selected;
 }
@@ -273,7 +268,7 @@ TAssistant::setPointSelection(const TStringId &name, bool selected)  const {
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::setAllPointsSelection(bool selected) const {
+TAssistantBase::setAllPointsSelection(bool selected) const {
   for(TAssistantPointMap::const_iterator i = points().begin(); i != points().end(); ++i)
     i->second.selected = selected;
 }
@@ -281,7 +276,7 @@ TAssistant::setAllPointsSelection(bool selected) const {
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::onDataChanged(const TVariant &value) {
+TAssistantBase::onDataChanged(const TVariant &value) {
   const TVariant& pointsData = data()[m_idPoints];
   TVariantPathEntry entry;
 
@@ -303,14 +298,13 @@ TAssistant::onDataChanged(const TVariant &value) {
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::onDataFieldChanged(const TStringId &name, const TVariant &value) {
-  updateProperty(name, value);
-}
+TAssistantBase::onDataFieldChanged(const TStringId &name, const TVariant &value)
+  { updateProperty(name, value); }
 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::onAllDataChanged() {
+TAssistantBase::onAllDataChanged() {
   const TVariant& pointsData = data()[m_idPoints];
   for(TAssistantPointMap::iterator i = m_points.begin(); i != m_points.end(); ++i) {
     const TVariant& pointData = pointsData[i->first];
@@ -325,32 +319,31 @@ TAssistant::onAllDataChanged() {
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::onFixPoints()
+TAssistantBase::onFixPoints()
   { }
 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::onMovePoint(TAssistantPoint &point, const TPointD &position)
+TAssistantBase::onMovePoint(TAssistantPoint &point, const TPointD &position)
   { point.position = position; }
 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::onFixData() {
+TAssistantBase::onFixData() {
   TVariant& pointsData = data()[m_idPoints];
   for(TAssistantPointMap::const_iterator i = points().begin(); i != points().end(); ++i) {
     TVariant& pointData = pointsData[i->first];
     pointData[m_idX].setDouble( i->second.position.x );
     pointData[m_idY].setDouble( i->second.position.y );
   }
-  setMagnetism( std::max(0.0, std::min(1.0, getMagnetism())) );
 }
 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::updateProperties() {
+TAssistantBase::updateProperties() {
   const TVariantMap &map = data().getMap();
   for(TVariantMap::const_iterator i = map.begin(); i != map.end(); ++i)
     if (i->first != m_idPoints)
@@ -360,7 +353,7 @@ TAssistant::updateProperties() {
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::updateProperty(const TStringId &name, const TVariant &value) {
+TAssistantBase::updateProperty(const TStringId &name, const TVariant &value) {
   TProperty *property = m_properties.getProperty(name);
   if (!property)
     return;
@@ -382,7 +375,7 @@ TAssistant::updateProperty(const TStringId &name, const TVariant &value) {
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::onPropertyChanged(const TStringId &name) {
+TAssistantBase::onPropertyChanged(const TStringId &name) {
   TProperty *property = m_properties.getProperty(name);
   if (!property)
     return;
@@ -407,19 +400,19 @@ TAssistant::onPropertyChanged(const TStringId &name) {
 //---------------------------------------------------------------------------------------------------
 
 double
-TAssistant::getDrawingAlpha(bool enabled) const
+TAssistantBase::getDrawingAlpha(bool enabled) const
   { return enabled && this->getEnabled() ? 0.5 : 0.25; }
 
 //---------------------------------------------------------------------------------------------------
 
 double
-TAssistant::getDrawingGridAlpha() const
+TAssistantBase::getDrawingGridAlpha() const
   { return 0.2; }
 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, double alpha) const {
+TAssistantBase::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, double alpha) const {
   double colorBlack[4] = { 0.0, 0.0, 0.0, alpha };
   double colorWhite[4] = { 1.0, 1.0, 1.0, alpha };
 
@@ -442,7 +435,7 @@ TAssistant::drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize, 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::drawMark(const TPointD &p, const TPointD &normal, double pixelSize, double alpha) const {
+TAssistantBase::drawMark(const TPointD &p, const TPointD &normal, double pixelSize, double alpha) const {
   TPointD d = normal*5*pixelSize;
   drawSegment(p - d,p + d, pixelSize, alpha);
 }
@@ -450,7 +443,7 @@ TAssistant::drawMark(const TPointD &p, const TPointD &normal, double pixelSize, 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::drawDot(const TPointD &p, double alpha) const {
+TAssistantBase::drawDot(const TPointD &p, double alpha) const {
   double colorBlack[4] = { 0.0, 0.0, 0.0, alpha };
   double colorWhite[4] = { 1.0, 1.0, 1.0, alpha };
 
@@ -475,7 +468,7 @@ TAssistant::drawDot(const TPointD &p, double alpha) const {
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::drawPoint(const TAssistantPoint &point, double pixelSize) const {
+TAssistantBase::drawPoint(const TAssistantPoint &point, double pixelSize) const {
   if (!point.visible) return;
 
   double radius = point.radius;
@@ -552,19 +545,13 @@ TAssistant::drawPoint(const TAssistantPoint &point, double pixelSize) const {
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::getGuidelines(const TPointD &position, const TAffine &toTool, TGuidelineList &outGuidelines) const
-  { }
-
-//---------------------------------------------------------------------------------------------------
-
-void
-TAssistant::draw(TToolViewer *viewer, bool enabled) const
+TAssistantBase::draw(TToolViewer *viewer, bool enabled) const
   { }
 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::drawEdit(TToolViewer *viewer) const {
+TAssistantBase::drawEdit(TToolViewer *viewer) const {
   // paint all points
   draw(viewer);
   double pixelSize = sqrt(tglGetPixelSize2());
@@ -572,6 +559,46 @@ TAssistant::drawEdit(TToolViewer *viewer) const {
     drawPoint(i->second, pixelSize);
 }
 
+
+//************************************************************************
+//    TAssistant implementation
+//************************************************************************
+
+TAssistant::TAssistant(TMetaObject &object):
+  TAssistantBase(object),
+  m_idMagnetism("magnetism")
+  { addProperty( new TDoubleProperty(m_idMagnetism.str(), 0.0, 1.0, getMagnetism()) ); }
+
+//---------------------------------------------------------------------------------------------------
+
+void
+TAssistant::updateTranslation() const {
+  TAssistantBase::updateTranslation();
+  setTranslation(m_idMagnetism, tr("Magnetism"));
+}
+
+//---------------------------------------------------------------------------------------------------
+
+void
+TAssistant::onSetDefaults() {
+  setMagnetism(1.0);
+  TAssistantBase::onSetDefaults();
+}
+
+//---------------------------------------------------------------------------------------------------
+
+void
+TAssistant::onFixData() {
+  TAssistantBase::onFixData();
+  setMagnetism( std::max(0.0, std::min(1.0, getMagnetism())) );
+}
+
+//---------------------------------------------------------------------------------------------------
+
+void
+TAssistant::getGuidelines(const TPointD&, const TAffine&, TGuidelineList&) const
+  { }
+
 //---------------------------------------------------------------------------------------------------
 
 bool
diff --git a/toonz/sources/tnztools/assistants/assistantellipse.cpp b/toonz/sources/tnztools/assistants/assistantellipse.cpp
index db6055e..e5b407b 100644
--- a/toonz/sources/tnztools/assistants/assistantellipse.cpp
+++ b/toonz/sources/tnztools/assistants/assistantellipse.cpp
@@ -57,6 +57,7 @@ public:
     { return tr("Ellipse"); }
 
   void updateTranslation() const override {
+    TAssistant::updateTranslation();
     setTranslation(m_idRestricktA, tr("Restrict A"));
     setTranslation(m_idRestricktB, tr("Restrict B"));
     setTranslation(m_idRepeat, tr("Repeat"));
diff --git a/toonz/sources/tnztools/assistants/assistantline.cpp b/toonz/sources/tnztools/assistants/assistantline.cpp
index d87134f..f0a1fd6 100644
--- a/toonz/sources/tnztools/assistants/assistantline.cpp
+++ b/toonz/sources/tnztools/assistants/assistantline.cpp
@@ -52,6 +52,7 @@ public:
     { return tr("Line"); }
 
   void updateTranslation() const override {
+    TAssistant::updateTranslation();
     setTranslation(m_idRestricktA, tr("Restrict A"));
     setTranslation(m_idRestricktB, tr("Restrict B"));
     setTranslation(m_idParallel, tr("Parallel"));
diff --git a/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp b/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp
index b660e60..61b0792 100644
--- a/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp
+++ b/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp
@@ -51,6 +51,7 @@ public:
     { return tr("Vanishing Point"); }
 
   void updateTranslation() const override {
+    TAssistant::updateTranslation();
     setTranslation(m_idPassThrough, tr("Pass Through"));
     setTranslation(m_idGrid, tr("Grid"));
     setTranslation(m_idPerspective, tr("Perspective"));