diff --git a/toonz/sources/common/tmetaimage/tmetaimage.cpp b/toonz/sources/common/tmetaimage/tmetaimage.cpp
index b3e48e8..1a43f6e 100644
--- a/toonz/sources/common/tmetaimage/tmetaimage.cpp
+++ b/toonz/sources/common/tmetaimage/tmetaimage.cpp
@@ -5,85 +5,161 @@
 
 //---------------------------------------------------------
 
+TMetaObjectType::TMetaObjectType(const TStringId &name): name(name)
+  { registerAlias(name); }
+
+TMetaObjectType::~TMetaObjectType() {
+  // TMetaObject::unregisterType(*this);
+}
+
+void
+TMetaObjectType::registerAlias(const TStringId &alias)
+  { TMetaObject::registerType(alias, *this); }
+
+void
+TMetaObjectType::unregisterAlias(const TStringId &alias) {
+  TMetaObject::Registry::const_iterator i = TMetaObject::getRegistry().find(alias);
+  if (i == TMetaObject::getRegistry().end() || i->second != this) {
+    std::cerr << "warning: trying to unregister not-registered alias (" << alias.str()
+              << ") of type of TMetaObject (" << name.str() << ") " << name.str() << std::endl;
+  } else {
+    TMetaObject::unregisterType(alias);
+  }
+}
+
+//---------------------------------------------------------
+
 TMetaObject::TMetaObject(const TMetaObject &other):
+  m_typeLink(linkedMap().end()),
+  m_previous(),
+  m_next(),
+  m_typeDesc(),
   m_handler(),
   m_data(*this, other.data())
-    { setType(other.getType()); }
-
-//---------------------------------------------------------
+    { linkToType(TStringId()); setType(other.getType()); }
 
 TMetaObject::TMetaObject(const TStringId &typeName, const TVariant &data):
+  m_typeLink(linkedMap().end()),
+  m_previous(),
+  m_next(),
+  m_typeDesc(),
   m_handler(),
   m_data(*this, data)
-    { setType(typeName); }
-
-//---------------------------------------------------------
+    { linkToType(TStringId()); setType(typeName); }
 
 TMetaObject::TMetaObject(const std::string &typeName, const TVariant &data):
+  m_typeLink(linkedMap().end()),
+  m_previous(),
+  m_next(),
+  m_typeDesc(),
   m_handler(),
   m_data(*this, data)
-    { setType(typeName); }
-
-//---------------------------------------------------------
+    { linkToType(TStringId()); setType(typeName); }
 
 TMetaObject::~TMetaObject()
-  { resetType(); }
+  { resetType(); unlinkFromType(); }
 
-//---------------------------------------------------------
+TMetaObject::LinkedMap&
+TMetaObject::linkedMap()
+  { static LinkedMap linkedMap; return linkedMap; }
+
+void
+TMetaObject::linkToType(const TStringId &type) {
+  m_typeLink = linkedMap().insert( LinkedMap::value_type(type, LinkedList()) ).first;
+  m_previous = m_typeLink->second.last;
+  m_next = 0;
+  (m_previous ? m_previous->m_next : m_typeLink->second.first) = this;
+  m_typeLink->second.last = this;
+}
+
+void
+TMetaObject::unlinkFromType() {
+  (m_previous ? m_previous->m_next : m_typeLink->second.first) = m_next;
+  (m_next     ? m_next->m_previous : m_typeLink->second.last ) = m_previous;
+  m_typeLink = linkedMap().end();
+  m_previous = m_next = 0;
+}
+
+void
+TMetaObject::rewrap(const TStringId &type) {
+  const TMetaObjectType *typeDesc = findType(type);
+  if (typeDesc == m_typeDesc) return;
+  if (m_handler) delete m_handler;
+  m_typeDesc = typeDesc;
+  m_handler  = m_typeDesc ? m_typeDesc->createHandler(*this) : 0;
+  onVariantChanged(m_data);
+}
+
+void
+TMetaObject::rewrapAll(const TStringId &type) {
+  LinkedMap::const_iterator it = linkedMap().find(type);
+  if (it != linkedMap().end())
+    for(TMetaObject *i = it->second.first; i; i = i->m_next)
+      i->rewrap(it->first);
+}
 
 void
 TMetaObject::setType(const TStringId &name) {
-  if (m_type != name) {
-    if (m_handler) delete m_handler;
-    m_type = name;
-    Registry::const_iterator i = registry().find(m_type);
-    m_handler = i == registry().end() ? NULL : i->second(*this);
-    onVariantChanged(m_data);
+  if (m_typeLink->first != name) {
+    unlinkFromType();
+    linkToType(name);
+    rewrap(name);
   }
 }
 
-//---------------------------------------------------------
-
 void
 TMetaObject::onVariantChanged(const TVariant &value)
   { if (m_handler) m_handler->dataChanged(value); }
 
-//---------------------------------------------------------
-
 void
 TMetaObject::setDefaults()
   { m_data.reset(); if (m_handler) m_handler->setDefaults(); }
 
-//---------------------------------------------------------
-
 TMetaObject*
 TMetaObject::clone() const
   { return new TMetaObject(*this); }
 
-//---------------------------------------------------------
-
 TMetaObject::Registry&
-TMetaObject::registry() {
-  static Registry registry;
-  return registry;
-}
-
-//---------------------------------------------------------
+TMetaObject::registry()
+  { static Registry registry; return registry; }
 
 void
-TMetaObject::registerType(const TStringId &typeName, Fabric fabric) {
-  if (registry().count(typeName))
-    std::cerr << "warning: type of TMetaObject are already registered: " << typeName.str() << std::endl;
-  registry()[typeName] = fabric;
+TMetaObject::registerType(const TStringId &name, const TMetaObjectType &type) {
+  if (registry().count(name))
+    std::cerr << "warning: type of TMetaObject are already registered: " << name.str() << std::endl;
+  registry()[name] = &type;
+
+  LinkedMap::const_iterator it = linkedMap().find(name);
+  if (it != linkedMap().end())
+    for(TMetaObject *i = it->second.first; i; i = i->m_next)
+      i->rewrap(name);
+  rewrapAll(name);
 }
 
-//---------------------------------------------------------
+void
+TMetaObject::unregisterType(const TStringId &name) {
+  if (!registry().count(name))
+    std::cerr << "warning: trying to unregister non-registered alias of type of TMetaObject: " << name.str() << std::endl;
+  registry().erase(name);
+  rewrapAll(name);
+}
 
 void
-TMetaObject::unregisterType(const TStringId &typeName) {
-  if (!registry().count(typeName))
-    std::cerr << "warning: trying to unregister non-registered type of TMetaObject: " << typeName.str() << std::endl;
-  registry().erase(typeName);
+TMetaObject::unregisterType(const TMetaObjectType &type) {
+  Registry &r = registry();
+  size_t s = r.size();
+  for(Registry::iterator i = r.begin(); i != r.end();)
+    if (i->second == &type)
+      { r.erase(i++); rewrapAll(i->first); } else ++i;
+  if (s == r.size())
+    std::cerr << "warning: trying to unregister non-registered type of TMetaObject: " << type.name.str() << std::endl;
+}
+
+const TMetaObjectType*
+TMetaObject::findType(const TStringId &name) {
+  const Registry &r = getRegistry();
+  Registry::const_iterator i = r.find(name);
+  return i == r.end() ? 0 : i->second;
 }
 
 //---------------------------------------------------------
@@ -91,8 +167,6 @@ TMetaObject::unregisterType(const TStringId &typeName) {
 TMetaImage::TMetaImage()
   { }
 
-//---------------------------------------------------------
-
 TMetaImage::TMetaImage(const TMetaImage &other) {
   Reader reader(other);
   m_objects.reserve(reader->size());
@@ -101,19 +175,13 @@ TMetaImage::TMetaImage(const TMetaImage &other) {
       m_objects.push_back( TMetaObjectP((*i)->clone()) );
 }
 
-//---------------------------------------------------------
-
 TMetaImage::~TMetaImage()
   { }
 
-//---------------------------------------------------------
-
 TImage*
 TMetaImage::cloneImage() const
   { return new TMetaImage(*this); }
 
-//---------------------------------------------------------
-
 TRectD
 TMetaImage::getBBox() const
   { return TRectD(); }
diff --git a/toonz/sources/include/tmetaimage.h b/toonz/sources/include/tmetaimage.h
index 09a5cc0..5726d1a 100644
--- a/toonz/sources/include/tmetaimage.h
+++ b/toonz/sources/include/tmetaimage.h
@@ -9,6 +9,7 @@
 #include "tvariant.h"
 #include "tconstwrapper.h"
 
+#include <QString>
 #include <QReadLocker>
 #include <QWriteLocker>
 #include <QReadWriteLock>
@@ -37,28 +38,52 @@ typedef TConstArrayWrapperT<TMetaObjectPC, TMetaObjectP> TMetaObjectListCW; // T
 
 //-------------------------------------------------------------------
 
+class DVAPI TMetaObjectType {
+public:
+  const TStringId name;
+
+  TMetaObjectType(const TStringId &name);
+  virtual ~TMetaObjectType();
+
+  void registerAlias(const TStringId &alias);
+  void unregisterAlias(const TStringId &alias);
+
+  virtual TMetaObjectHandler* createHandler(TMetaObject &obj) const
+    { return 0; }
+  virtual QString getLocalName() const
+    { return QString::fromStdString(name.str()); }
+};
+
+//-------------------------------------------------------------------
+
 class DVAPI TMetaObject: public TSmartObject, public TVariantOwner {
 public:
   typedef TMetaObjectHandler* (*Fabric)(TMetaObject&);
-  typedef std::map<TStringId, Fabric> Registry;
+  typedef std::map<TStringId, const TMetaObjectType*> Registry;
 
-  template<typename T>
-  class Registrator {
-  public:
-    typedef T Type;
-    static TMetaObjectHandler* fabric(TMetaObject &obj)
-      { return new Type(obj); }
-    Registrator(const std::string &typeName)
-      { registerType(typeName, fabric); }
-    Registrator(const TStringId &typeName)
-      { registerType(typeName, fabric); }
+  struct LinkedList {
+    TMetaObject *first, *last;
+    LinkedList(): first(), last() { }
   };
+  typedef std::map<TStringId, LinkedList> LinkedMap;
+  typedef LinkedMap::iterator LinkedMapEntry;
 
 private:
-  TStringId m_type;
+  LinkedMapEntry m_typeLink;
+  TMetaObject *m_previous, *m_next;
+  const TMetaObjectType *m_typeDesc;
   TMetaObjectHandler *m_handler;
   TVariant m_data;
 
+  static Registry& registry();
+  static LinkedMap& linkedMap();
+
+  static void rewrapAll(const TStringId &type);
+  void rewrap(const TStringId &type);
+
+  void linkToType(const TStringId &type);
+  void unlinkFromType();
+
   TMetaObject(const TMetaObject &other);
 
 public:
@@ -71,10 +96,13 @@ public:
     { setType(TStringId(name)); }
   inline void resetType()
     { setType(TStringId()); }
+
+  inline const TMetaObjectType* getTypeDesc() const
+    { return m_typeDesc; }
   inline const TStringId& getType() const
-    { return m_type; }
+    { return m_typeLink->first; }
   inline const std::string& getTypeName() const
-    { return m_type.str(); }
+    { return getType().str(); }
   inline const TVariant& data() const
     { return m_data; }
   inline TVariant& data()
@@ -96,13 +124,12 @@ public:
 
   virtual TMetaObject* clone() const;
 
-  static Registry& registry();
-  static void registerType(const TStringId &name, Fabric fabric);
-  static void unregisterType(const TStringId &name);
-  inline static void registerType(const std::string &name, Fabric fabric)
-    { registerType(TStringId(name), fabric); }
-  inline static void unregisterType(const std::string &name)
-    { unregisterType(TStringId::find(name)); }
+public:
+  static const Registry& getRegistry() { return registry(); }
+  static void registerType(const TStringId &name, const TMetaObjectType &type); //!< register new or add alias
+  static void unregisterType(const TStringId &name); //!< unregister single alias
+  static void unregisterType(const TMetaObjectType &type); //!< unregister all aliases
+  static const TMetaObjectType* findType(const TStringId &name);
 };
 
 //-------------------------------------------------------------------
@@ -119,17 +146,30 @@ protected:
 
 private:
   TMetaObject &m_object;
+  const TMetaObjectType &m_typeDesc;
   TAtomicVar m_locks;
 
 public:
   TMetaObjectHandler(TMetaObject &object):
-    m_object(object) { }
+    m_object(object),
+    m_typeDesc(*m_object.getTypeDesc())
+      { assert(m_object.getTypeDesc()); }
   virtual ~TMetaObjectHandler() { }
 
+  inline const TMetaObjectType& getTypeDesc() const
+    { return m_typeDesc; }
+  inline const TStringId& getType() const
+    { return getTypeDesc().name; }
+  inline const std::string& getTypeName() const
+    { return getType().str(); }
   inline const TMetaObject& object() const
     { return m_object; }
   inline TMetaObject& object()
     { return m_object; }
+  inline const TStringId& getAlias() const
+    { return object().getType(); }
+  inline const std::string& getAliasName() const
+    { return getAlias().str(); }
   inline const TVariant& data() const
     { return object().data(); }
   inline TVariant& data()
diff --git a/toonz/sources/include/tools/assistant.h b/toonz/sources/include/tools/assistant.h
index e2edc22..5f88920 100644
--- a/toonz/sources/include/tools/assistant.h
+++ b/toonz/sources/include/tools/assistant.h
@@ -12,6 +12,9 @@
 #include <tmetaimage.h>
 #include <tproperty.h>
 
+// Qt includes
+#include <QCoreApplication>
+
 // std includes
 #include <vector>
 #include <string>
@@ -47,6 +50,7 @@ typedef std::vector<TAssistantPoint> TAssistantPointList;
 
 //===================================================================
 
+
 //*****************************************************************************************
 //    TGuideline definition
 //*****************************************************************************************
@@ -88,11 +92,79 @@ public:
   TAssistantPoint(Type type, const TPointD &position, double radius);
 };
 
+
+//*****************************************************************************************
+//    TAssistantType definition
+//*****************************************************************************************
+
+class DVAPI TAssistantType: public TMetaObjectType {
+public:
+  TAssistantType(const TStringId &name):
+    TMetaObjectType(name) { }
+  TMetaObjectHandler* createHandler(TMetaObject &obj) const override;
+  virtual TAssistant* createAssistant(TMetaObject &obj) const
+    { return 0; }
+};
+
+
+//*****************************************************************************************
+//    TAssistantTypeT definition
+//*****************************************************************************************
+
+template<typename T>
+class TAssistantTypeT: public TAssistantType {
+public:
+  typedef T Type;
+
+  explicit TAssistantTypeT(
+    const TStringId &name,
+    const TStringId &alias1 = TStringId(),
+    const TStringId &alias2 = TStringId(),
+    const TStringId &alias3 = TStringId(),
+    const TStringId &alias4 = TStringId(),
+    const TStringId &alias5 = TStringId()
+  ):
+    TAssistantType(TStringId(name))
+  {
+    if (alias1) registerAlias(alias1);
+    if (alias2) registerAlias(alias2);
+    if (alias3) registerAlias(alias3);
+    if (alias4) registerAlias(alias4);
+    if (alias5) registerAlias(alias5);
+  }
+
+  explicit TAssistantTypeT(
+    const std::string &name,
+    const std::string &alias1 = std::string(),
+    const std::string &alias2 = std::string(),
+    const std::string &alias3 = std::string(),
+    const std::string &alias4 = std::string(),
+    const std::string &alias5 = std::string()
+  ):
+    TAssistantType(TStringId(name))
+  {
+    if (!alias1.empty()) registerAlias(TStringId(alias1));
+    if (!alias2.empty()) registerAlias(TStringId(alias2));
+    if (!alias3.empty()) registerAlias(TStringId(alias3));
+    if (!alias4.empty()) registerAlias(TStringId(alias4));
+    if (!alias5.empty()) registerAlias(TStringId(alias5));
+  }
+
+  TAssistant* createAssistant(TMetaObject &obj) const override
+    { return new Type(obj); }
+  QString getLocalName() const override {
+    QString localName = Type::getLocalName();
+    return localName.isEmpty() ? QString::fromStdString(name.str()) : localName;
+  }
+};
+
+
 //*****************************************************************************************
 //    TAssistant definition
 //*****************************************************************************************
 
 class DVAPI TAssistant : public TMetaObjectHandler {
+  Q_DECLARE_TR_FUNCTIONS(TAssistant)
 protected:
   const TStringId m_idEnabled;
   const TStringId m_idPoints;
@@ -109,6 +181,9 @@ public:
 
   static const TPointD& blank();
 
+  static QString getLocalName()
+    { return QString(); }
+
   inline const TAssistantPointList& points() const
     { return m_points; }
   inline const int pointsCount() const
@@ -165,9 +240,11 @@ protected:
   void drawSegment(const TPointD &p0, const TPointD &p1, double pixelSize) const;
   void drawPoint(const TAssistantPoint &point, double pixelSize) const;
 
-  void addProperty(TProperty *p, const std::string &title);
+  void addProperty(TProperty *p);
+  void setTranslation(const TStringId &name, const QString &localName) const;
 
 public:
+  virtual void updateTranslation() const;
   virtual void getGuidelines(const TPointD &position, const TAffine &toTool, TGuidelineList &outGuidelines) const;
   virtual void draw(TToolViewer *viewer) const;
   virtual void drawEdit(TToolViewer *viewer) const;
diff --git a/toonz/sources/tnztools/CMakeLists.txt b/toonz/sources/tnztools/CMakeLists.txt
index 8f0d9fc..5d6d83c 100644
--- a/toonz/sources/tnztools/CMakeLists.txt
+++ b/toonz/sources/tnztools/CMakeLists.txt
@@ -54,6 +54,8 @@ set(HEADERS
     ../include/tools/modifiers/modifiertangents.h
     ../include/tools/modifiers/modifiertest.h
     ../include/tools/modifiers/modifiersegmentation.h
+    ../include/tools/modifiers/modifierassistants.h
+    assistants/guidelineline.h
 )
 
 set(SOURCES
diff --git a/toonz/sources/tnztools/assistant.cpp b/toonz/sources/tnztools/assistant.cpp
index e2f299c..2a4af8a 100644
--- a/toonz/sources/tnztools/assistant.cpp
+++ b/toonz/sources/tnztools/assistant.cpp
@@ -118,6 +118,15 @@ TAssistantPoint::TAssistantPoint(
 
 
 //************************************************************************
+//    TAssistantType implementation
+//************************************************************************
+
+TMetaObjectHandler*
+TAssistantType::createHandler(TMetaObject &obj) const
+  { return createAssistant(obj); }
+
+
+//************************************************************************
 //    TAssistant implementation
 //************************************************************************
 
@@ -129,18 +138,28 @@ TAssistant::TAssistant(TMetaObject &object):
   m_idY("y"),
   m_idMagnetism("magnetism")
 {
-  addProperty( new TBoolProperty(m_idEnabled.str(), getEnabled()),
-               "Enabled" );
-  addProperty( new TDoubleProperty(m_idMagnetism.str(), 0.0, 1.0, getMagnetism()),
-               "Magnetism" );
+  addProperty( new TBoolProperty(m_idEnabled.str(), getEnabled()) );
+  addProperty( new TDoubleProperty(m_idMagnetism.str(), 0.0, 1.0, getMagnetism()) );
 }
 
 //---------------------------------------------------------------------------------------------------
 
 void
-TAssistant::addProperty(TProperty *p, const std::string &title) {
-  p->setQStringName( QString::fromStdString(title) );
-  m_properties.add(p);
+TAssistant::addProperty(TProperty *p)
+  { m_properties.add(p); }
+
+//---------------------------------------------------------------------------------------------------
+
+void
+TAssistant::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"));
 }
 
 //---------------------------------------------------------------------------------------------------
diff --git a/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp b/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp
index 73489c0..2d5fb4b 100644
--- a/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp
+++ b/toonz/sources/tnztools/assistants/assistantvanishingpoint.cpp
@@ -1,49 +1,54 @@
 
 
-#include "assistantvanishingpoint.h"
 #include "guidelineline.h"
 
-// TnzCore includes
-#include "tgl.h"
+// TnzTools includes
+#include <tools/assistant.h>
 
+// TnzCore includes
+#include <tgl.h>
 
 
 //*****************************************************************************************
-//    Registration
+//    TAssistantVanishingPoint implementation
 //*****************************************************************************************
 
-static TMetaObject::Registrator<TAssistantVanishingPoint> assistantVanishingPoint("assistantVanishingPoint");
-
+class DVAPI TAssistantVanishingPoint final : public TAssistant {
+  Q_DECLARE_TR_FUNCTIONS(TAssistantVanishingPoint)
+public:
+  TAssistantVanishingPoint(TMetaObject &object):
+    TAssistant(object)
+  {
+    m_points.push_back(TAssistantPoint(
+      TAssistantPoint::CircleCross ));
+  }
+
+  static QString getLocalName()
+    { return tr("Vanishing Point"); }
+
+  void getGuidelines(
+    const TPointD &position,
+    const TAffine &toTool,
+    TGuidelineList &outGuidelines ) const override
+  {
+    outGuidelines.push_back(TGuidelineP(
+      new TGuidelineInfiniteLine(
+        toTool*m_points.front().position,
+        position )));
+  }
+
+  void draw(TToolViewer *viewer) const override {
+    double pixelSize = sqrt(tglGetPixelSize2());
+    const TPointD &p = m_points.front().position;
+    TPointD dx(20.0*pixelSize, 0.0);
+    TPointD dy(0.0, 10.0*pixelSize);
+    drawSegment(p-dx-dy, p+dx+dy, pixelSize);
+    drawSegment(p-dx+dy, p+dx-dy, pixelSize);
+  }
+};
 
 //*****************************************************************************************
-//    TAssistantVanishingPoint implementation
+//    Registration
 //*****************************************************************************************
 
-TAssistantVanishingPoint::TAssistantVanishingPoint(TMetaObject &object):
-  TAssistant(object)
-{
-  m_points.push_back(TAssistantPoint(
-    TAssistantPoint::CircleCross ));
-}
-
-void
-TAssistantVanishingPoint::getGuidelines(
-  const TPointD &position,
-  const TAffine &toTool,
-  TGuidelineList &outGuidelines ) const
-{
-  outGuidelines.push_back(TGuidelineP(
-    new TGuidelineInfiniteLine(
-      toTool*m_points.front().position,
-      position )));
-}
-
-void
-TAssistantVanishingPoint::draw(TToolViewer *viewer) const {
-  double pixelSize = sqrt(tglGetPixelSize2());
-  const TPointD &p = m_points.front().position;
-  TPointD dx(20.0*pixelSize, 0.0);
-  TPointD dy(0.0, 10.0*pixelSize);
-  drawSegment(p-dx-dy, p+dx+dy, pixelSize);
-  drawSegment(p-dx+dy, p+dx-dy, pixelSize);
-}
+static TAssistantTypeT<TAssistantVanishingPoint> assistantVanishingPoint("assistantVanishingPoint");
diff --git a/toonz/sources/tnztools/assistants/assistantvanishingpoint.h b/toonz/sources/tnztools/assistants/assistantvanishingpoint.h
deleted file mode 100644
index cbd3568..0000000
--- a/toonz/sources/tnztools/assistants/assistantvanishingpoint.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#pragma once
-
-#ifndef ASSISTANTVANISHINGPOINT_INCLUDED
-#define ASSISTANTVANISHINGPOINT_INCLUDED
-
-// TnzTools includes
-#include <tools/assistant.h>
-
-
-#undef DVAPI
-#undef DVVAR
-#ifdef TNZTOOLS_EXPORTS
-#define DVAPI DV_EXPORT_API
-#define DVVAR DV_EXPORT_VAR
-#else
-#define DVAPI DV_IMPORT_API
-#define DVVAR DV_IMPORT_VAR
-#endif
-
-
-//===================================================================
-
-//*****************************************************************************************
-//    TAssistantVanishingPoint definition
-//*****************************************************************************************
-
-class DVAPI TAssistantVanishingPoint final : public TAssistant {
-public:
-  TAssistantVanishingPoint(TMetaObject &object);
-  virtual void getGuidelines(const TPointD &position, const TAffine &toTool, TGuidelineList &outGuidelines) const override;
-  virtual void draw(TToolViewer *viewer) const override;
-};
-
-#endif
diff --git a/toonz/sources/tnztools/editassistantstool.cpp b/toonz/sources/tnztools/editassistantstool.cpp
index 93b56ac..23f80d6 100644
--- a/toonz/sources/tnztools/editassistantstool.cpp
+++ b/toonz/sources/tnztools/editassistantstool.cpp
@@ -98,20 +98,16 @@ public:
 
 class EditAssistantsTool final : public TTool {
   Q_DECLARE_TR_FUNCTIONS(EditAssistantsTool)
-public:
-  typedef std::map<TStringId, std::string> TypeMap;
-
+protected:
   enum Mode {
     ModeImage,
     ModeAssistant,
     ModePoint
   };
 
-protected:
   TPropertyGroup m_allProperties;
   TPropertyGroup m_toolProperties;
   TEnumProperty m_assistantType;
-  TypeMap m_typeToName;
   TStringId m_newAssisnantType;
 
   bool           m_dragging;
@@ -152,8 +148,6 @@ public:
     m_writeAssistant()
   {
     bind(MetaImage);
-    addAssistantType("", "--");
-    addAssistantType("assistantVanishingPoint", "Vanishing Point");
     m_toolProperties.bind(m_assistantType);
     updateTranslation();
   }
@@ -168,35 +162,45 @@ public:
   void onImageChanged() override
     { getViewer()->GLInvalidateAll(); }
 
+  void updateAssistantTypes() {
+    std::wstring value = m_assistantType.getValue();
+
+    m_assistantType.deleteAllValues();
+    m_assistantType.addValueWithUIName(L"", tr("--"));
+
+    const TMetaObject::Registry &registry = TMetaObject::getRegistry();
+    for(TMetaObject::Registry::const_iterator i = registry.begin(); i != registry.end(); ++i)
+      if (const TAssistantType *assistantType = dynamic_cast<const TAssistantType*>(i->second))
+        if (assistantType->name)
+          m_assistantType.addValueWithUIName(
+            to_wstring(assistantType->name.str()),
+            assistantType->getLocalName() );
+
+    if (m_assistantType.indexOf(value) >= 0)
+      m_assistantType.setValue(value);
+  }
+
   TPropertyGroup* getProperties(int) override {
     m_allProperties.clear();
     for(int i = 0; i < m_toolProperties.getPropertyCount(); ++i)
       m_allProperties.bind( *m_toolProperties.getProperty(i) );
     if (Closer closer = read(ModeAssistant)) {
+      m_readAssistant->updateTranslation();
       TPropertyGroup &assistantProperties = m_readAssistant->getProperties();
       for(int i = 0; i < assistantProperties.getPropertyCount(); ++i)
         m_allProperties.bind( *assistantProperties.getProperty(i) );
     }
-    updateTranslation();
     return &m_allProperties;
   }
 
-  void addAssistantType(const std::string &typeName, const std::string &name) {
-    if (m_typeToName.insert( TypeMap::value_type(TStringId(typeName), name) ).second)
-      m_assistantType.addValueWithUIName(
-        to_wstring(typeName),
-        QString::fromStdString(name) );
-  }
+  void onActivate() override
+    { updateAssistantTypes(); }
 
   void updateTranslation() override {
-    for(TypeMap::const_iterator i = m_typeToName.begin(); i != m_typeToName.end(); ++i)
-      m_assistantType.setItemUIName(
-        to_wstring(i->first.str()),
-        tr(i->second.c_str()) );
-    for(int i = 0; i < m_allProperties.getPropertyCount(); ++i) {
-      TProperty *p = m_allProperties.getProperty(i);
-      //p->setQStringName( tr( p->getUINameOrig().c_str() ) );
-    }
+    m_assistantType.setQStringName( tr("Assistant Type") );
+    updateAssistantTypes();
+    if (Closer closer = read(ModeAssistant))
+      m_readAssistant->updateTranslation();
   }
 
   bool onPropertyChanged(std::string name/*, bool addToUndo*/) override {
@@ -317,7 +321,6 @@ protected:
   Closer::Args write(Mode mode, bool touch = false)
     { openWrite(mode, touch); return Closer::Args(*this); }
 
-public:
   void updateOptionsBox()
     { getApplication()->getCurrentTool()->notifyToolOptionsBoxChanged(); }
 
@@ -346,7 +349,7 @@ public:
         for(int j = 0; j < assistant->pointsCount() && m_currentAssistantIndex < 0; ++j) {
           const TAssistantPoint &p = assistant->points()[j];
           TPointD offset = p.position - position;
-          if (norm(offset) <= p.radius*pixelSize) {
+          if (norm2(offset) <= p.radius*p.radius*pixelSize*pixelSize) {
             m_currentAssistant.set(*i);
             m_currentAssistantIndex = i - (*m_reader)->begin();
             m_currentPointIndex = j;