diff --git a/toonz/sources/tnztools/CMakeLists.txt b/toonz/sources/tnztools/CMakeLists.txt
index db7abdf..368aa99 100644
--- a/toonz/sources/tnztools/CMakeLists.txt
+++ b/toonz/sources/tnztools/CMakeLists.txt
@@ -145,6 +145,7 @@ set(SOURCES
     assistants/replicatoraffine.cpp
     assistants/replicatorgrid.cpp
     assistants/replicatormirror.cpp
+    assistants/replicatorstar.cpp
     editassistantstool.cpp
 )
 
diff --git a/toonz/sources/tnztools/assistants/replicatoraffine.cpp b/toonz/sources/tnztools/assistants/replicatoraffine.cpp
index e5e06f1..1318070 100644
--- a/toonz/sources/tnztools/assistants/replicatoraffine.cpp
+++ b/toonz/sources/tnztools/assistants/replicatoraffine.cpp
@@ -280,6 +280,7 @@ public:
   
   void draw(TToolViewer*, bool enabled) const override {
     double alpha = getDrawingAlpha(enabled);
+    double gridAlpha = getDrawingGridAlpha();
     double pixelSize = sqrt(tglGetPixelSize2());
 
     TPointD c = m_center0.position;
@@ -295,8 +296,8 @@ public:
     TAffine t;
     for(int i = getCount(); i > 0; --i) {
       t = aff * t;
-      drawSegment(t*c, t*a, pixelSize, alpha);
-      drawSegment(t*c, t*b, pixelSize, alpha);
+      drawSegment(t*c, t*a, pixelSize, gridAlpha);
+      drawSegment(t*c, t*b, pixelSize, gridAlpha);
     }
     
     // draw inverted clones
@@ -304,8 +305,8 @@ public:
     aff = aff.inv();
     for(int i = getCountInv(); i > 0; --i) {
       t = aff * t;
-      drawSegment(t*c, t*a, pixelSize, alpha);
-      drawSegment(t*c, t*b, pixelSize, alpha);
+      drawSegment(t*c, t*a, pixelSize, gridAlpha);
+      drawSegment(t*c, t*b, pixelSize, gridAlpha);
     }
   }
 };
diff --git a/toonz/sources/tnztools/assistants/replicatorgrid.cpp b/toonz/sources/tnztools/assistants/replicatorgrid.cpp
index 7e731fb..ef26802 100644
--- a/toonz/sources/tnztools/assistants/replicatorgrid.cpp
+++ b/toonz/sources/tnztools/assistants/replicatorgrid.cpp
@@ -14,7 +14,7 @@
 //*****************************************************************************************
 
 class TReplicatorGrid final : public TReplicator {
-  Q_DECLARE_TR_FUNCTIONS(TReplicatorAffine)
+  Q_DECLARE_TR_FUNCTIONS(TReplicatorGrid)
 public:
   const TStringId m_idFixAngle;
   const TStringId m_idFixSkew;
@@ -232,6 +232,7 @@ public:
   
   void draw(TToolViewer*, bool enabled) const override {
     double alpha = getDrawingAlpha(enabled);
+    double gridAlpha = getDrawingGridAlpha();
     double pixelSize = sqrt(tglGetPixelSize2());
 
     TPointD c = m_center.position;
@@ -257,13 +258,13 @@ public:
     for(int ia = a0; ia < a1; ++ia) {
       TPointD o = c + da*ia + db*ib;
       if (ia || ib) {
-        drawSegment(o, o + da*0.2, pixelSize, alpha);
-        drawSegment(o, o + db*0.2, pixelSize, alpha);
+        drawSegment(o, o + da*0.2, pixelSize, gridAlpha);
+        drawSegment(o, o + db*0.2, pixelSize, gridAlpha);
       }
       if (mirrorA && (ib || ia != 1))
-        drawSegment(o - da*0.2, o, pixelSize, alpha);
+        drawSegment(o - da*0.2, o, pixelSize, gridAlpha);
       if (mirrorB && (ia || ib != 1))
-        drawSegment(o - db*0.2, o, pixelSize, alpha);
+        drawSegment(o - db*0.2, o, pixelSize, gridAlpha);
     }
   }
 };
diff --git a/toonz/sources/tnztools/assistants/replicatormirror.cpp b/toonz/sources/tnztools/assistants/replicatormirror.cpp
index 138f41c..3963377 100644
--- a/toonz/sources/tnztools/assistants/replicatormirror.cpp
+++ b/toonz/sources/tnztools/assistants/replicatormirror.cpp
@@ -15,7 +15,7 @@
 //*****************************************************************************************
 
 class TReplicatorMirror final : public TReplicator {
-  Q_DECLARE_TR_FUNCTIONS(TReplicatorAffine)
+  Q_DECLARE_TR_FUNCTIONS(TReplicatorMirror)
 public:
   const TStringId m_idDiscreteAngle;
   const TStringId m_idPressure;
@@ -72,6 +72,7 @@ protected:
 
   TPointD fixB() const {
     TPointD b = m_b.position;
+    
     if (getDiscreteAngle()) {
       TPointD d = b - m_a.position;
       double l = norm2(d);
@@ -83,6 +84,10 @@ protected:
         b.y = sin(angle)*l + m_a.position.y;
       }
     }
+    
+    if (areAlmostEqual(b, m_a.position))
+      b = m_a.position + TPointD(1, 0);
+    
     return b;
   }
   
@@ -90,8 +95,6 @@ protected:
   TAffine getAffine(const TAffine &toTool = TAffine()) const {
     TPointD c = toTool*m_a.position;
     TPointD x = toTool*fixB() - c;
-    if (!(norm2(x) > TConsts::epsilon*TConsts::epsilon))
-      x = TPointD(1, 0);
     TPointD y(-x.y, x.x);
     
     TAffine t0( x.x,  y.x, c.x,
diff --git a/toonz/sources/tnztools/assistants/replicatorstar.cpp b/toonz/sources/tnztools/assistants/replicatorstar.cpp
new file mode 100644
index 0000000..b4aeb89
--- /dev/null
+++ b/toonz/sources/tnztools/assistants/replicatorstar.cpp
@@ -0,0 +1,199 @@
+
+
+// TnzTools includes
+#include <tools/replicator.h>
+#include <tools/modifiers/modifierclone.h>
+#include <tools/assistants/guidelineline.h>
+
+
+// TnzCore includes
+#include <tgl.h>
+
+
+//*****************************************************************************************
+//    TReplicatorStar implementation
+//*****************************************************************************************
+
+class TReplicatorStar final : public TReplicator {
+  Q_DECLARE_TR_FUNCTIONS(TReplicatorStar)
+public:
+  const TStringId m_idDiscreteAngle;
+  const TStringId m_idMirror;
+  const TStringId m_idCount;
+
+protected:
+  TAssistantPoint &m_center;
+  TAssistantPoint &m_a;
+
+public:
+  TReplicatorStar(TMetaObject &object):
+    TReplicator(object),
+    m_idDiscreteAngle("discreteAngle"),
+    m_idMirror("mirror"),
+    m_idCount("count"),
+    m_center( addPoint("center", TAssistantPoint::CircleCross) ),
+    m_a     ( addPoint("a",      TAssistantPoint::Circle, TPointD(80, 0)) )
+  {
+    addProperty( new TBoolProperty(m_idDiscreteAngle.str(), getDiscreteAngle()) );
+    addProperty( new TBoolProperty(m_idMirror.str(),        getMirror()) );
+    addProperty( createCountProperty(m_idCount, getCount(), 2) );
+  }
+
+  
+  static QString getLocalName()
+    { return tr("Replicator Star"); }
+
+    
+  void updateTranslation() const override {
+    TReplicator::updateTranslation();
+    setTranslation(m_idDiscreteAngle, tr("Discrete Angle"));
+    setTranslation(m_idMirror, tr("Mirror"));
+    setTranslation(m_idCount, tr("Count"));
+  }
+
+  
+  inline bool getDiscreteAngle() const
+    { return data()[m_idDiscreteAngle].getBool(); }
+  inline bool getMirror() const
+    { return data()[m_idMirror].getBool(); }
+  inline int getCount() const
+    { return (int)data()[m_idCount].getDouble(); }
+
+protected:
+  inline void setCount(int x)
+    { if (getCount() != (double)x) data()[m_idCount].setDouble((double)x); }
+
+    
+  void onSetDefaults() override {
+    setCount(6);
+    TReplicator::onSetDefaults();
+  }
+
+  
+  void onFixData() override {
+    TReplicator::onFixData();
+    setCount( std::max(1, std::min(multiplierSoftLimit - 1, getCount())) );
+  }
+
+
+  TPointD fixA() const {
+    TPointD a = m_a.position;
+    
+    if (getDiscreteAngle()) {
+      TPointD d = a - m_center.position;
+      double l = norm2(d);
+      if (l > TConsts::epsilon*TConsts::epsilon) {
+        l = sqrt(l);
+        int count = getCount();
+        if (count > 0) {
+          double angle = atan2(d.y, d.x);
+          angle = round(angle*2*count/M_PI)*M_PI/(2*count);
+          a.x = cos(angle)*l + m_center.position.x;
+          a.y = sin(angle)*l + m_center.position.y;
+        }
+      }
+    }
+    
+    if (areAlmostEqual(a, m_center.position))
+      a = m_center.position + TPointD(1, 0);
+    
+    return a;
+  }
+
+  
+  void onMovePoint(TAssistantPoint &point, const TPointD &position) override {
+    if (&point == &m_center)
+      m_a.position += position - m_center.position;
+    point.position = position;
+  }
+  
+  
+public:
+  int getMultipler() const override
+    { return getCount() + 1; }
+  
+  
+  void getModifiers(
+    const TAffine &toTool,
+    TInputModifier::List &outModifiers ) const override
+  {
+    int count = getCount();
+    bool mirror = getMirror();
+
+    TPointD c = toTool*m_center.position;
+    TPointD x = toTool*fixA() - c;
+    TPointD y(-x.y, x.x);
+
+    TAffine t1( x.x,  y.x, c.x,
+                x.y,  y.y, c.y );
+    TAffine t2( x.x, -y.x, c.x,
+                x.y, -y.y, c.y );
+    
+    TAffine t0 = t1.inv();
+    TRotation r(360.0/getCount());
+                          
+    TModifierClone *modifier = new TModifierClone();
+    for(int i = 0; i < count; ++i) {
+      if (i)
+        modifier->transforms.push_back(TTrackTransform(t1*t0));
+      if (mirror) {
+        modifier->transforms.push_back(TTrackTransform(t2*t0));
+        t2 *= r;
+      }
+      t1 *= r;
+    }
+    
+    outModifiers.push_back(modifier);
+  }
+
+  
+  void draw(TToolViewer*, bool enabled) const override {
+    double alpha = getDrawingAlpha(enabled);
+    double gridAlpha = getDrawingGridAlpha();
+    double pixelSize = sqrt(tglGetPixelSize2());
+
+    int count = getCount();
+    bool mirror = getMirror();
+
+    TPointD c = m_center.position;
+    TPointD a = fixA();
+    TPointD d = normalize(a - c);
+    
+    double spacing = 10*pixelSize;
+    double l = spacing*count/M_2PI;
+    
+    TPointD p0 = c + d*l;
+    TPointD p1 = p0 + d;
+    TRotation r(360.0/count);
+    
+    TAffine4 modelview, projection;
+    glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a);
+    glGetDoublev(GL_PROJECTION_MATRIX, projection.a);
+
+    TAffine matrix = (projection*modelview).get2d();
+    TAffine matrixInv = matrix.inv();
+    const TRectD oneBox(-1.0, -1.0, 1.0, 1.0);
+    
+    for(int i = 0; i < count; ++i) {
+      TPointD pp0 = matrix*p0;
+      TPointD pp1 = matrix*p1;
+      if (TGuidelineLine::truncateRay(oneBox, pp0, pp1))
+        drawSegment(matrixInv*pp0, matrixInv*pp1, pixelSize, i ? gridAlpha : alpha);
+      p0 = r*(p0 - c) + c;
+      p1 = r*(p1 - c) + c;
+    }
+    
+    TPointD p = TPointD(-d.y, d.x);
+    drawSegment( (mirror ? a+p*15 : a), a-p*15, pixelSize, alpha );
+    
+    drawSegment(c - d*10, c + d*10, pixelSize, alpha);
+    drawSegment(c - p*10, c + p*10, pixelSize, alpha);
+  }
+};
+
+
+//*****************************************************************************************
+//    Registration
+//*****************************************************************************************
+
+static TAssistantTypeT<TReplicatorStar> replicatorStar("replicatorStar");