diff --git a/toonz/sources/common/tvrender/tglregions.cpp b/toonz/sources/common/tvrender/tglregions.cpp
index e489878..f698d84 100644
--- a/toonz/sources/common/tvrender/tglregions.cpp
+++ b/toonz/sources/common/tvrender/tglregions.cpp
@@ -16,6 +16,7 @@
 #include "tconvert.h"
 #include "tcurves.h"
 #include "tstrokeoutline.h"
+#include <QTime>
 
 #ifndef _WIN32
 #define CALLBACK
@@ -132,6 +133,108 @@ void drawControlPoints(const TVectorRenderData &rd, TStroke *stroke,
 
 #endif
 
+//-----------------------------------------------------------------------------
+
+void drawArrows(TStroke *stroke, bool onlyFirstPoint) {
+  double length = stroke->getLength(0.0, 1.0);
+  int points    = length / 20;
+  if (points < 2) points += 1;
+  double currentPosition = 0.0;
+
+  TPointD prePoint, point, postPoint;
+  glColor3d(1.0, 0.0, 0.0);
+  for (int i = 0; i <= points; i++) {
+    currentPosition = i / (double)points;
+    point           = stroke->getPointAtLength(length * currentPosition);
+    prePoint        = (i == 0) ? point : stroke->getPointAtLength(
+                                      length * (currentPosition - 0.02));
+    postPoint = (i == points) ? point : stroke->getPointAtLength(
+                                            length * (currentPosition + 0.02));
+
+    if (prePoint == postPoint) continue;
+
+    double radian =
+        std::atan2(postPoint.y - prePoint.y, postPoint.x - prePoint.x);
+    double degree = radian * 180.0 / 3.14159265;
+
+    glPushMatrix();
+    glTranslated(point.x, point.y, 0);
+    glRotated(degree, 0, 0, 1);
+    glBegin(GL_LINES);
+    glVertex2d(0, 0);
+    glVertex2d(-3, -3);
+    glVertex2d(0, 0);
+    glVertex2d(-3, 3);
+    glEnd();
+    glPopMatrix();
+
+    if (onlyFirstPoint) break;
+    // make the arrow blue from the second one
+    glColor3d(0.0, 0.0, 1.0);
+  }
+}
+
+//-----------------------------------------------------------------------------
+// Used for Guided Drawing
+void drawFirstControlPoint(const TVectorRenderData &rd, TStroke *stroke) {
+  TPointD p          = stroke->getPoint(0.0);
+  double length      = stroke->getLength(0.0, 1.0);
+  int msecs          = QTime::currentTime().msec();
+  double modifier    = (msecs / 100) * 0.1;
+  TPointD startPoint = stroke->getPointAtLength(length * modifier);
+  TPointD endPoint   = stroke->getPointAtLength(length * 0.10);
+  double j           = 0.025;
+
+  glPushMatrix();
+  tglMultMatrix(rd.m_aff);
+  if (!rd.m_animatedGuidedDrawing) glLineWidth(2.0f);
+  glColor3d(0.0, 1.0, 0.0);
+  if (!rd.m_animatedGuidedDrawing) {
+    drawArrows(stroke, false);
+  }
+
+  if (rd.m_animatedGuidedDrawing) {
+    drawArrows(stroke, true);
+    glColor3d(0.0, 1.0, 0.0);
+    j = 0.025 + modifier;
+    glBegin(GL_LINES);
+    // draw the first animated section
+    for (int i = 0; i < 8; i++) {
+      endPoint = stroke->getPointAtLength(length * j);
+      glVertex2d(startPoint.x, startPoint.y);
+      glVertex2d(endPoint.x, endPoint.y);
+      startPoint = endPoint;
+      j += 0.025;
+      if (j > 1) {
+        j -= 1;
+        startPoint = stroke->getPointAtLength(length * j);
+      }
+    }
+
+    modifier = modifier + 0.5;
+    if (modifier >= 1) modifier -= 1;
+    startPoint = stroke->getPointAtLength(length * modifier);
+    j          = 0.025 + modifier;
+
+    // draw another animated section
+    for (int i = 0; i < 8; i++) {
+      endPoint = stroke->getPointAtLength(length * j);
+      glVertex2d(startPoint.x, startPoint.y);
+      glVertex2d(endPoint.x, endPoint.y);
+      startPoint = endPoint;
+      j += 0.025;
+      if (j > 1) {
+        j -= 1;
+        startPoint = stroke->getPointAtLength(length * j);
+      }
+    }
+    glEnd();
+  }
+
+  glLineWidth(1.0f);
+  glPopMatrix();
+}
+
 //=============================================================================
 
 /*TPixel TransparencyCheckBlackBgInk = TPixel(255,255,255);
@@ -483,11 +586,20 @@ static void tglDoDraw(const TVectorRenderData &rd, const TStroke *s) {
       if (color.m != 0) visible = true;
     }
   }
-#if DISEGNO_OUTLINE == 0
-  if (visible)
-#endif
-    tglDraw(rd, s, false);
 
+  if (visible) {
+    // Change stroke color to blue if guided drawing
+    if (rd.m_showGuidedDrawing && rd.m_highLightNow) {
+      TVectorRenderData *newRd = new TVectorRenderData(
+          rd, rd.m_aff, rd.m_clippingRect, rd.m_palette, rd.m_guidedCf);
+      tglDraw(*newRd, s, false);
+      delete newRd;
+      TStroke *new_s = (TStroke *)s;
+      drawFirstControlPoint(rd, new_s);
+    } else {
+      tglDraw(rd, s, false);
+    }
+  }
 #ifdef _DEBUG
 // drawControlPoints(rd, vim->getStroke(i), sqrt(tglGetPixelSize2()), true);
 // assert(checkQuadraticDistance(vim->getStroke(i),true));
@@ -542,6 +654,11 @@ rdRegions.m_alphaChannel = rdRegions.m_antiAliasing = false;*/
           tglDoDraw(rdRegions, vim->getRegion(regionIndex));
     while (strokeIndex < vim->getStrokeCount() &&
            vim->sameGroup(strokeIndex, currStrokeIndex)) {
+      if (rd.m_indexToHighlight != strokeIndex) {
+        rd.m_highLightNow = false;
+      } else {
+        rd.m_highLightNow = true;
+      }
 #if DISEGNO_OUTLINE == 1
       CurrStrokeIndex = strokeIndex;
       CurrVimg        = vim;
diff --git a/toonz/sources/include/toonz/preferences.h b/toonz/sources/include/toonz/preferences.h
index 10c6094..17abd0c 100644
--- a/toonz/sources/include/toonz/preferences.h
+++ b/toonz/sources/include/toonz/preferences.h
@@ -329,6 +329,11 @@ public:
     return m_useNumpadForSwitchingStyles;
   }
 
+  void setGuidedDrawing(int status);
+  int getGuidedDrawing() { return m_guidedDrawingType; }
+  void setAnimatedGuidedDrawing(bool status);
+  bool getAnimatedGuidedDrawing() const { return m_animatedGuidedDrawing; }
+
   void enableNewLevelSizeToCameraSize(bool on);
   bool isNewLevelSizeToCameraSizeEnabled() const {
     return m_newLevelSizeToCameraSizeEnabled;
@@ -519,7 +524,7 @@ private:
       m_chunkSize, m_blanksCount, m_onionPaperThickness, m_step, m_shrink,
       m_textureSize, m_autocreationType, m_keyframeType, m_animationStep,
       m_ffmpegTimeout;  // seconds
-  int m_projectRoot, m_importPolicy, m_interfaceFontWeight;
+  int m_projectRoot, m_importPolicy, m_interfaceFontWeight, m_guidedDrawingType;
   QString m_currentLanguage, m_currentStyleSheet;
   int m_undoMemorySize,  // in megabytes
       m_dragCellsBehaviour, m_lineTestFpsCapture, m_defLevelType, m_xsheetStep,
@@ -531,7 +536,7 @@ private:
       m_rewindAfterPlaybackEnabled, m_fitToFlipbookEnabled, m_autosaveEnabled,
       m_autosaveSceneEnabled, m_autosaveOtherFilesEnabled,
       m_defaultViewerEnabled, m_pixelsOnly, m_showXSheetToolbar,
-      m_expandFunctionHeader, m_showColumnNumbers;
+      m_expandFunctionHeader, m_showColumnNumbers, m_animatedGuidedDrawing;
   bool m_rasterOptimizedMemory, m_saveUnpaintedInCleanup,
       m_askForOverrideRender, m_automaticSVNFolderRefreshEnabled, m_SVNEnabled,
       m_levelsBackupEnabled, m_minimizeSaveboxAfterEditing,
diff --git a/toonz/sources/include/toonz/stage.h b/toonz/sources/include/toonz/stage.h
index c490aa8..39abc4e 100644
--- a/toonz/sources/include/toonz/stage.h
+++ b/toonz/sources/include/toonz/stage.h
@@ -65,12 +65,14 @@ DVAPI void visit(Visitor &visitor, ToonzScene *scene, TXsheet *xsh, int row);
 //-----------------------------------------------------------------------------
 
 DVAPI void visit(Visitor &visitor, TXshSimpleLevel *level, const TFrameId &fid,
-                 const OnionSkinMask &osm, bool isPlaying);
+                 const OnionSkinMask &osm, bool isPlaying,
+                 int isGuidedDrawingEnabled = 0);
 
 //-----------------------------------------------------------------------------
 
 DVAPI void visit(Visitor &visitor, TXshLevel *level, const TFrameId &fid,
-                 const OnionSkinMask &osm, bool isPlaying);
+                 const OnionSkinMask &osm, bool isPlaying,
+                 double isGuidedDrawingEnabled = 0.0);
 
 //-----------------------------------------------------------------------------
 }  // namespace Stage
diff --git a/toonz/sources/include/toonz/stageplayer.h b/toonz/sources/include/toonz/stageplayer.h
index b5379b0..cdb6a8b 100644
--- a/toonz/sources/include/toonz/stageplayer.h
+++ b/toonz/sources/include/toonz/stageplayer.h
@@ -83,12 +83,15 @@ public:
                            //! of) the current column
   bool m_isCurrentXsheetLevel;  //!< Whether the player's xsheet is the \a
                                 //! current one
-
+  bool m_isEditingLevel;
+  bool m_isVisibleinOSM;  // Whether the current frame is in the onion skin
+  int m_isGuidedDrawingEnabled = 0;
   TXshSimpleLevel *m_sl;  //!< (not owned) The player's simple level
   TFrameId m_fid;         //!< The player's frame in m_sl
-
-  TXsheet *m_xsh;  //!< (not owned) The player's xsheet
-  int m_column;    //!< The player's xsheet column
+  TFrameId
+      m_currentFrameId;  // The current frame selected in the level or xsheet
+  TXsheet *m_xsh;        //!< (not owned) The player's xsheet
+  int m_column;          //!< The player's xsheet column
   int m_frame;  //!< The player's xhseet row (could be not the current, due to
                 //! onion skin?)
 
@@ -101,6 +104,8 @@ public:
 
   static double m_onionSkinFrontSize;
   static double m_onionSkinBackSize;
+  static double m_firstBackOnionSkin;
+  static double m_lastBackVisibleSkin;
 
   TPixel32 m_filterColor;
 
diff --git a/toonz/sources/include/toonz/stagevisitor.h b/toonz/sources/include/toonz/stagevisitor.h
index ec03556..4461362 100644
--- a/toonz/sources/include/toonz/stagevisitor.h
+++ b/toonz/sources/include/toonz/stagevisitor.h
@@ -126,12 +126,13 @@ struct DVAPI VisitArgs {
 
   const OnionSkinMask *m_osm;
   int m_xsheetLevel;
-
+  TFrameId m_currentFrameId;
   bool m_camera3d;
   bool m_isPlaying;
   bool m_onlyVisible;
   bool m_checkPreviewVisibility;
   bool m_rasterizePli;
+  int m_isGuidedDrawingEnabled;
 
 public:
   VisitArgs()
@@ -145,6 +146,7 @@ public:
       , m_isPlaying(false)
       , m_onlyVisible(false)
       , m_checkPreviewVisibility(false)
+      , m_isGuidedDrawingEnabled(0)
       , m_rasterizePli(false) {}
 };
 
diff --git a/toonz/sources/include/tvectorrenderdata.h b/toonz/sources/include/tvectorrenderdata.h
index 885879c..f59622a 100644
--- a/toonz/sources/include/tvectorrenderdata.h
+++ b/toonz/sources/include/tvectorrenderdata.h
@@ -49,6 +49,7 @@ public:
 public:
   const TColorFunction
       *m_cf;  //!< [\p not-owned] Transform to be used for drawing RGBM colors.
+  const TColorFunction *m_guidedCf;
   const TPalette *m_palette;  //!< [\p not-owned] Palette to be used for
                               //! translating color indexes to
   //!                 RGBM colors.
@@ -61,8 +62,9 @@ public:
   TPixel m_tCheckInk;    //!< Color to be used for <I>ink check</I> mode.
   TPixel m_tCheckPaint;  //!< Color to be used for <I>paint check</I> mode.
 
-  int m_colorCheckIndex;  //!< Color index to be highlighted in <I>color
-                          //! check</I> mode.
+  int m_colorCheckIndex;   //!< Color index to be highlighted in <I>color
+                           //! check</I> mode.
+  int m_indexToHighlight;  // for guided vector drawing
 
   bool m_alphaChannel,      //!< Whether alpha channel is enabled.
       m_antiAliasing,       //!< Whether antialiasing must be applied.
@@ -79,8 +81,12 @@ public:
                             //! rendered anyway.
       m_regionAntialias,    //!< Whether regions should be rendered with
                             //! antialiasing at boundaries.
-      m_isOfflineRender;    //!< Whether image rendering is in render or
+      m_isOfflineRender,    //!< Whether image rendering is in render or
                             //! camera-stand (preview) mode.
+      m_showGuidedDrawing,  // Whether this image is being used for guided
+                            // drawing
+      m_highLightNow;       // Show highlight on active stroke
+  bool m_animatedGuidedDrawing = false;
   //!  \deprecated  Use the above individual options instead.
   //!  \todo  Remove it ASAP.
 public:
@@ -111,7 +117,11 @@ public:
       , m_regionAntialias(false)  // No need for pretty region boundaries,
                                   // typically shadowed by strokes
       // This is also related to interference with the directly above param
-      , m_isOfflineRender(false) {}  // By definition
+      , m_isOfflineRender(false)  // By definition
+      , m_indexToHighlight(-1)
+      , m_highLightNow(false)
+      , m_guidedCf(0)
+      , m_showGuidedDrawing(false) {}
 
   TVectorRenderData(ProductionSettings, const TAffine &aff,
                     const TRect &clippingRect, const TPalette *palette,
@@ -137,7 +147,11 @@ public:
       , m_show0ThickStrokes(false)  // Invisible strokes must be invisible
       , m_regionAntialias(true)  // Pretty region boundaries under invisible or
                                  // semitransparent strokes
-      , m_isOfflineRender(true) {}  // By definition
+      , m_isOfflineRender(true)  // By definition
+      , m_indexToHighlight(-1)
+      , m_highLightNow(false)
+      , m_guidedCf(0)
+      , m_showGuidedDrawing(false) {}
 
   TVectorRenderData(const TVectorRenderData &other, const TAffine &aff,
                     const TRect &clippingRect, const TPalette *palette,
@@ -161,7 +175,11 @@ public:
       , m_is3dView(other.m_is3dView)
       , m_show0ThickStrokes(other.m_show0ThickStrokes)
       , m_regionAntialias(other.m_regionAntialias)
-      , m_isOfflineRender(other.m_isOfflineRender) {
+      , m_isOfflineRender(other.m_isOfflineRender)
+      , m_indexToHighlight(other.m_indexToHighlight)
+      , m_highLightNow(other.m_highLightNow)
+      , m_guidedCf(other.m_guidedCf)
+      , m_showGuidedDrawing(other.m_showGuidedDrawing) {
   }  //!< Constructs from explicit primary context settings while
      //!  copying the rest from another instance.
 
@@ -188,7 +206,11 @@ public:
       , m_is3dView(is3dView)
       , m_show0ThickStrokes(true)
       , m_regionAntialias(false)
-      , m_isOfflineRender(false) {
+      , m_isOfflineRender(false)
+      , m_indexToHighlight(-1)
+      , m_highLightNow(false)
+      , m_guidedCf(0)
+      , m_showGuidedDrawing(false) {
   }  //!< Constructs settings with default ViewerSettings.
      //!  \deprecated   Use constructors with explicit settings type tag.
 };
diff --git a/toonz/sources/toonz/preferencespopup.cpp b/toonz/sources/toonz/preferencespopup.cpp
index eb50118..2958b98 100644
--- a/toonz/sources/toonz/preferencespopup.cpp
+++ b/toonz/sources/toonz/preferencespopup.cpp
@@ -725,6 +725,12 @@ void PreferencesPopup::onOnionSkinDuringPlaybackChanged(int index) {
 
 //-----------------------------------------------------------------------------
 
+void PreferencesPopup::onGuidedDrawingStyleChanged(int index) {
+  m_pref->setAnimatedGuidedDrawing(index);
+}
+
+//-----------------------------------------------------------------------------
+
 void PreferencesPopup::onActualPixelOnSceneModeChanged(int index) {
   m_pref->enableActualPixelViewOnSceneEditingMode(index == Qt::Checked);
 }
@@ -1320,6 +1326,7 @@ PreferencesPopup::PreferencesPopup()
 
   int thickness         = m_pref->getOnionPaperThickness();
   m_onionPaperThickness = new DVGui::IntLineEdit(this, thickness, 0, 100);
+  m_guidedDrawingStyle  = new QComboBox(this);
 
   //--- Transparency Check ------------------------------
   categoryList->addItem(tr("Transparency Check"));
@@ -1619,6 +1626,10 @@ PreferencesPopup::PreferencesPopup()
   m_frontOnionColor->setEnabled(m_pref->isOnionSkinEnabled());
   m_backOnionColor->setEnabled(m_pref->isOnionSkinEnabled());
   m_inksOnly->setEnabled(m_pref->isOnionSkinEnabled());
+  QStringList guidedDrawingStyles;
+  guidedDrawingStyles << tr("Arrow Markers") << tr("Animated Guide");
+  m_guidedDrawingStyle->addItems(guidedDrawingStyles);
+  m_guidedDrawingStyle->setCurrentIndex(m_pref->getAnimatedGuidedDrawing());
 
   //--- Version Control ------------------------------
   m_enableVersionControl->setChecked(m_pref->isSVNEnabled());
@@ -2167,7 +2178,17 @@ PreferencesPopup::PreferencesPopup()
       onionLay->addWidget(m_inksOnly, 0, Qt::AlignLeft | Qt::AlignVCenter);
       onionLay->addWidget(m_onionSkinDuringPlayback, 0,
                           Qt::AlignLeft | Qt::AlignVCenter);
-
+      QGridLayout *guidedDrawingLay = new QGridLayout();
+      {
+        guidedDrawingLay->addWidget(new QLabel(tr("Vector Guided Style:")), 0,
+                                    0, Qt::AlignLeft | Qt::AlignVCenter);
+        guidedDrawingLay->addWidget(m_guidedDrawingStyle, 0, 1,
+                                    Qt::AlignLeft | Qt::AlignVCenter);
+        guidedDrawingLay->setColumnStretch(0, 0);
+        guidedDrawingLay->setColumnStretch(1, 0);
+        guidedDrawingLay->setColumnStretch(2, 1);
+      }
+      onionLay->addLayout(guidedDrawingLay, 0);
       onionLay->addStretch(1);
     }
     onionBox->setLayout(onionLay);
@@ -2474,7 +2495,8 @@ PreferencesPopup::PreferencesPopup()
                        SLOT(onOnionSkinDuringPlaybackChanged(int)));
   ret = ret && connect(m_onionPaperThickness, SIGNAL(editingFinished()),
                        SLOT(onOnionPaperThicknessChanged()));
-
+  ret = ret && connect(m_guidedDrawingStyle, SIGNAL(currentIndexChanged(int)),
+                       SLOT(onGuidedDrawingStyleChanged(int)));
   //--- Transparency Check ----------------------
   ret = ret && connect(m_transpCheckBgColor,
                        SIGNAL(colorChanged(const TPixel32 &, bool)),
diff --git a/toonz/sources/toonz/preferencespopup.h b/toonz/sources/toonz/preferencespopup.h
index 7da18cc..4dfb267 100644
--- a/toonz/sources/toonz/preferencespopup.h
+++ b/toonz/sources/toonz/preferencespopup.h
@@ -54,7 +54,8 @@ private:
   QComboBox *m_keyframeType, *m_cellsDragBehaviour, *m_defScanLevelType,
       *m_defLevelType, *m_autocreationType, *m_levelFormatNames,
       *m_columnIconOm, *m_unitOm, *m_cameraUnitOm, *m_importPolicy,
-      *m_interfaceFont, *m_interfaceFontWeight, *m_vectorSnappingTargetCB;
+      *m_interfaceFont, *m_interfaceFontWeight, *m_vectorSnappingTargetCB,
+      *m_guidedDrawingStyle;
 
   DVGui::MeasuredDoubleLineEdit *m_defLevelWidth, *m_defLevelHeight;
 
@@ -163,6 +164,7 @@ private slots:
   void onReplaceAfterSaveLevelAsChanged(int index);
   void onOnionSkinVisibilityChanged(int);
   void onOnionSkinDuringPlaybackChanged(int);
+  void onGuidedDrawingStyleChanged(int);
   void onActualPixelOnSceneModeChanged(int);
   void onMultiLayerStylePickerChanged(int);
   void onLevelNameOnEachMarkerChanged(int);
diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp
index 36acebe..e63e27a 100644
--- a/toonz/sources/toonz/sceneviewer.cpp
+++ b/toonz/sources/toonz/sceneviewer.cpp
@@ -65,6 +65,7 @@
 #include "tofflinegl.h"
 #include "tstopwatch.h"
 #include "trop.h"
+#include "tproperty.h"
 #include "timagecache.h"
 #include "trasterimage.h"
 #include "tstroke.h"
@@ -1592,6 +1593,9 @@ void SceneViewer::drawScene() {
   bool fillFullColorRaster = TXshSimpleLevel::m_fillFullColorRaster;
   TXshSimpleLevel::m_fillFullColorRaster = false;
 
+  // Guided Drawing Check
+  int useGuidedDrawing = Preferences::instance()->getGuidedDrawing();
+
   m_minZ = 0;
   if (is3DView()) {
     Stage::OpenGlPainter painter(getViewMatrix(), clipRect, m_visualSettings,
@@ -1615,6 +1619,14 @@ void SceneViewer::drawScene() {
     args.m_osm         = &osm;
     args.m_camera3d    = true;
     args.m_xsheetLevel = xsheetLevel;
+    args.m_currentFrameId =
+        app->getCurrentXsheet()
+            ->getXsheet()
+            ->getCell(app->getCurrentFrame()->getFrame(), args.m_col)
+            .getFrameId();
+    args.m_isGuidedDrawingEnabled = useGuidedDrawing;
+
+    // args.m_currentFrameId = app->getCurrentFrame()->getFid();
     Stage::visit(painter, args);
 
     m_minZ = painter.getMinZ();
@@ -1646,7 +1658,7 @@ void SceneViewer::drawScene() {
       Stage::visit(painter, app->getCurrentLevel()->getLevel(),
                    app->getCurrentFrame()->getFid(),
                    app->getCurrentOnionSkin()->getOnionSkinMask(),
-                   frameHandle->isPlaying());
+                   frameHandle->isPlaying(), useGuidedDrawing);
     } else {
       std::pair<TXsheet *, int> xr;
       int xsheetLevel = 0;
@@ -1665,6 +1677,12 @@ void SceneViewer::drawScene() {
       args.m_osm         = &osm;
       args.m_xsheetLevel = xsheetLevel;
       args.m_isPlaying   = frameHandle->isPlaying();
+      args.m_currentFrameId =
+          app->getCurrentXsheet()
+              ->getXsheet()
+              ->getCell(app->getCurrentFrame()->getFrame(), args.m_col)
+              .getFrameId();
+      args.m_isGuidedDrawingEnabled = useGuidedDrawing;
       Stage::visit(painter, args);
     }
 
diff --git a/toonz/sources/toonz/sceneviewercontextmenu.cpp b/toonz/sources/toonz/sceneviewercontextmenu.cpp
index 8211476..94ef1c3 100644
--- a/toonz/sources/toonz/sceneviewercontextmenu.cpp
+++ b/toonz/sources/toonz/sceneviewercontextmenu.cpp
@@ -176,7 +176,32 @@ SceneViewerContextMenu::SceneViewerContextMenu(SceneViewer *parent)
   if (Preferences::instance()->isOnionSkinEnabled() &&
       !parent->isPreviewEnabled())
     OnioniSkinMaskGUI::addOnionSkinCommand(this);
-
+  QMenu *guidedDrawingMenu = addMenu(tr("Vector Guided Drawing"));
+  int guidedDrawingStatus  = Preferences::instance()->getGuidedDrawing();
+  action                   = guidedDrawingMenu->addAction(tr("Off"));
+  action->setCheckable(true);
+  action->setChecked(guidedDrawingStatus == 0);
+  ret = ret &&
+        parent->connect(action, SIGNAL(triggered()), this,
+                        SLOT(setGuidedDrawingOff()));
+  action = guidedDrawingMenu->addAction(tr("Closest Drawing"));
+  action->setCheckable(true);
+  action->setChecked(guidedDrawingStatus == 1);
+  ret = ret &&
+        parent->connect(action, SIGNAL(triggered()), this,
+                        SLOT(setGuidedDrawingClosest()));
+  action = guidedDrawingMenu->addAction(tr("Farthest Drawing"));
+  action->setCheckable(true);
+  action->setChecked(guidedDrawingStatus == 2);
+  ret = ret &&
+        parent->connect(action, SIGNAL(triggered()), this,
+                        SLOT(setGuidedDrawingFarthest()));
+  action = guidedDrawingMenu->addAction(tr("All Drawings"));
+  action->setCheckable(true);
+  action->setChecked(guidedDrawingStatus == 3);
+  ret = ret &&
+        parent->connect(action, SIGNAL(triggered()), this,
+                        SLOT(setGuidedDrawingAll()));
   // Zero Thick
   if (!parent->isPreviewEnabled())
     ZeroThickToggleGui::addZeroThickCommand(this);
@@ -386,6 +411,26 @@ void SceneViewerContextMenu::onSetCurrent() {
 }
 
 //-----------------------------------------------------------------------------
+void SceneViewerContextMenu::setGuidedDrawingOff() {
+  Preferences::instance()->setGuidedDrawing(0);
+}
+
+//-----------------------------------------------------------------------------
+void SceneViewerContextMenu::setGuidedDrawingClosest() {
+  Preferences::instance()->setGuidedDrawing(1);
+}
+
+//-----------------------------------------------------------------------------
+void SceneViewerContextMenu::setGuidedDrawingFarthest() {
+  Preferences::instance()->setGuidedDrawing(2);
+}
+
+//-----------------------------------------------------------------------------
+void SceneViewerContextMenu::setGuidedDrawingAll() {
+  Preferences::instance()->setGuidedDrawing(3);
+}
+
+//-----------------------------------------------------------------------------
 
 void SceneViewerContextMenu::savePreviewedFrames() {
   Previewer::instance(m_viewer->getPreviewMode() ==
diff --git a/toonz/sources/toonz/sceneviewercontextmenu.h b/toonz/sources/toonz/sceneviewercontextmenu.h
index 09de03f..b4e05b0 100644
--- a/toonz/sources/toonz/sceneviewercontextmenu.h
+++ b/toonz/sources/toonz/sceneviewercontextmenu.h
@@ -31,6 +31,10 @@ public slots:
 
   void enterVectorImageGroup();
   void exitVectorImageGroup();
+  void setGuidedDrawingOff();
+  void setGuidedDrawingClosest();
+  void setGuidedDrawingFarthest();
+  void setGuidedDrawingAll();
 
   void onShowHide();
   void onSetCurrent();
diff --git a/toonz/sources/toonzlib/preferences.cpp b/toonz/sources/toonzlib/preferences.cpp
index 9256842..8edd6d6 100644
--- a/toonz/sources/toonzlib/preferences.cpp
+++ b/toonz/sources/toonzlib/preferences.cpp
@@ -322,6 +322,8 @@ Preferences::Preferences()
     , m_useArrowKeyToShiftCellSelection(false)
     , m_inputCellsWithoutDoubleClickingEnabled(false)
     , m_importPolicy(0)
+    , m_guidedDrawingType(0)
+    , m_animatedGuidedDrawing(false)
     , m_ignoreImageDpi(false)
     , m_watchFileSystem(true)
     , m_shortcutCommandsWhileRenamingCellEnabled(false) {
@@ -612,6 +614,8 @@ Preferences::Preferences()
   getValue(*m_settings, "interfaceFontWeight", m_interfaceFontWeight);
   getValue(*m_settings, "useNumpadForSwitchingStyles",
            m_useNumpadForSwitchingStyles);
+  getValue(*m_settings, "guidedDrawingType", m_guidedDrawingType);
+  getValue(*m_settings, "animatedGuidedDrawing", m_animatedGuidedDrawing);
   getValue(*m_settings, "newLevelSizeToCameraSizeEnabled",
            m_newLevelSizeToCameraSizeEnabled);
   getValue(*m_settings, "showXSheetToolbar", m_showXSheetToolbar);
@@ -1450,6 +1454,20 @@ void Preferences::enableUseNumpadForSwitchingStyles(bool on) {
 
 //-----------------------------------------------------------------
 
+void Preferences::setGuidedDrawing(int status) {
+  m_guidedDrawingType = status;
+  m_settings->setValue("guidedDrawingType", status);
+}
+
+//-----------------------------------------------------------------
+
+void Preferences::setAnimatedGuidedDrawing(bool status) {
+  m_animatedGuidedDrawing = status;
+  m_settings->setValue("animatedGuidedDrawing", status);
+}
+
+//-----------------------------------------------------------------
+
 void Preferences::enableNewLevelSizeToCameraSize(bool on) {
   m_newLevelSizeToCameraSizeEnabled = on;
   m_settings->setValue("newLevelSizeToCameraSizeEnabled", on ? "1" : "0");
diff --git a/toonz/sources/toonzlib/stage.cpp b/toonz/sources/toonzlib/stage.cpp
index 44801ac..cb9be4a 100644
--- a/toonz/sources/toonzlib/stage.cpp
+++ b/toonz/sources/toonzlib/stage.cpp
@@ -76,7 +76,8 @@ namespace {
 void updateOnionSkinSize(const PlayerSet &players) {
   assert(Player::m_onionSkinFrontSize == 0 && Player::m_onionSkinBackSize == 0);
   int i;
-  int maxOnionSkinFrontValue = 0, maxOnionSkinBackValue = 0;
+  int maxOnionSkinFrontValue = 0, maxOnionSkinBackValue = 0,
+      firstBackOnionSkin = 0, lastBackVisibleSkin = 0;
   for (i = 0; i < (int)players.size(); i++) {
     Player player = players[i];
     if (player.m_onionSkinDistance == c_noOnionSkin) continue;
@@ -86,9 +87,20 @@ void updateOnionSkinSize(const PlayerSet &players) {
     if (player.m_onionSkinDistance < 0 &&
         maxOnionSkinBackValue > player.m_onionSkinDistance)
       maxOnionSkinBackValue = player.m_onionSkinDistance;
+    if (firstBackOnionSkin == 0 && player.m_onionSkinDistance < 0)
+      firstBackOnionSkin = player.m_onionSkinDistance;
+    else if (player.m_onionSkinDistance < 0 &&
+             firstBackOnionSkin < player.m_onionSkinDistance)
+      firstBackOnionSkin = player.m_onionSkinDistance;
+    // Level Editing Mode can send players at a depth beyond what is visible.
+    if (player.m_onionSkinDistance < lastBackVisibleSkin &&
+        player.m_isVisibleinOSM)
+      lastBackVisibleSkin = player.m_onionSkinDistance;
   }
-  Player::m_onionSkinFrontSize = maxOnionSkinFrontValue;
-  Player::m_onionSkinBackSize  = maxOnionSkinBackValue;
+  Player::m_onionSkinFrontSize  = maxOnionSkinFrontValue;
+  Player::m_onionSkinBackSize   = maxOnionSkinBackValue;
+  Player::m_firstBackOnionSkin  = firstBackOnionSkin;
+  Player::m_lastBackVisibleSkin = lastBackVisibleSkin;
 }
 
 //-----------------------------------------------------------------------------
@@ -184,6 +196,9 @@ public:
   int m_currentXsheetLevel;   // level of the current xsheet, see: editInPlace
   int m_xsheetLevel;          // xsheet-level of the column being processed
 
+  // for guided drawing
+  TFrameId m_currentFrameId;
+  int m_isGuidedDrawingEnabled;
   std::vector<TXshColumn *> m_ancestors;
 
   const ImagePainter::VisualSettings *m_vs;
@@ -356,11 +371,13 @@ void StageBuilder::addCell(PlayerSet &players, ToonzScene *scene, TXsheet *xsh,
     // Build and store a player
 
     Player player;
-    player.m_sl     = sl;
-    player.m_fid    = cell.m_frameId;
-    player.m_xsh    = xsh;
-    player.m_column = col;
-    player.m_frame  = row;
+    player.m_sl                     = sl;
+    player.m_fid                    = cell.m_frameId;
+    player.m_xsh                    = xsh;
+    player.m_column                 = col;
+    player.m_frame                  = row;
+    player.m_currentFrameId         = m_currentFrameId;
+    player.m_isGuidedDrawingEnabled = m_isGuidedDrawingEnabled;
     player.m_dpiAff = sl ? getDpiAffine(sl, cell.m_frameId) : TAffine();
     player.m_onionSkinDistance   = m_onionSkinDistance;
     player.m_isCurrentColumn     = (m_currentColumnIndex == col);
@@ -632,12 +649,16 @@ void StageBuilder::addSimpleLevelFrame(PlayerSet &players,
       const TFrameId &fid2 = level->index2fid(rows[i]);
       if (fid2 == fid) continue;
       players.push_back(Player());
-      Player &player                = players.back();
-      player.m_sl                   = level;
-      player.m_frame                = level->guessIndex(fid);
-      player.m_fid                  = fid2;
-      player.m_isCurrentColumn      = true;
-      player.m_isCurrentXsheetLevel = true;
+      Player &player                  = players.back();
+      player.m_sl                     = level;
+      player.m_frame                  = level->guessIndex(fid);
+      player.m_fid                    = fid2;
+      player.m_isCurrentColumn        = true;
+      player.m_isCurrentXsheetLevel   = true;
+      player.m_isEditingLevel         = true;
+      player.m_currentFrameId         = m_currentFrameId;
+      player.m_isGuidedDrawingEnabled = m_isGuidedDrawingEnabled;
+      player.m_isVisibleinOSM         = rows[i] >= 0;
 #ifdef NUOVO_ONION
       player.m_onionSkinDistance = rows[i] - row;
 #else
@@ -655,6 +676,7 @@ void StageBuilder::addSimpleLevelFrame(PlayerSet &players,
     player.m_onionSkinDistance  = 0;
   player.m_isCurrentColumn      = true;
   player.m_isCurrentXsheetLevel = true;
+  player.m_isEditingLevel       = true;
   player.m_ancestorColumnIndex  = -1;
   player.m_dpiAff               = getDpiAffine(level, fid);
 }
@@ -713,18 +735,22 @@ void Stage::visit(Visitor &visitor, const VisitArgs &args) {
   bool isPlaying           = args.m_isPlaying;
 
   StageBuilder sb;
-  sb.m_vs                 = &visitor.m_vs;
-  TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId();
-  TStageObject *camera    = xsh->getStageObject(cameraId);
-  TAffine cameraAff       = camera->getPlacement(row);
-  double z                = camera->getZ(row);
-  sb.m_cameraPlacement    = ZPlacement(cameraAff, z);
-  sb.m_camera3d           = camera3d;
-  sb.m_currentColumnIndex = col;
-  sb.m_xsheetLevel        = xsheetLevel;
-  sb.m_onionSkinMask      = *osm;
-  Player::m_onionSkinFrontSize = 0;
-  Player::m_onionSkinBackSize  = 0;
+  sb.m_vs                     = &visitor.m_vs;
+  TStageObjectId cameraId     = xsh->getStageObjectTree()->getCurrentCameraId();
+  TStageObject *camera        = xsh->getStageObject(cameraId);
+  TAffine cameraAff           = camera->getPlacement(row);
+  double z                    = camera->getZ(row);
+  sb.m_cameraPlacement        = ZPlacement(cameraAff, z);
+  sb.m_camera3d               = camera3d;
+  sb.m_currentColumnIndex     = col;
+  sb.m_xsheetLevel            = xsheetLevel;
+  sb.m_onionSkinMask          = *osm;
+  sb.m_currentFrameId         = args.m_currentFrameId;
+  sb.m_isGuidedDrawingEnabled = args.m_isGuidedDrawingEnabled;
+  Player::m_onionSkinFrontSize  = 0;
+  Player::m_onionSkinBackSize   = 0;
+  Player::m_firstBackOnionSkin  = 0;
+  Player::m_lastBackVisibleSkin = 0;
   sb.addFrame(sb.m_players, scene, xsh, row, 0, args.m_onlyVisible,
               args.m_checkPreviewVisibility);
 
@@ -753,12 +779,17 @@ void Stage::visit(Visitor &visitor, ToonzScene *scene, TXsheet *xsh, int row) {
                 and \b StageBuilder::visit().
 */
 void Stage::visit(Visitor &visitor, TXshSimpleLevel *level, const TFrameId &fid,
-                  const OnionSkinMask &osm, bool isPlaying) {
+                  const OnionSkinMask &osm, bool isPlaying,
+                  int isGuidedDrawingEnabled) {
   StageBuilder sb;
-  sb.m_vs                      = &visitor.m_vs;
-  sb.m_onionSkinMask           = osm;
-  Player::m_onionSkinFrontSize = 0;
-  Player::m_onionSkinBackSize  = 0;
+  sb.m_vs                       = &visitor.m_vs;
+  sb.m_onionSkinMask            = osm;
+  sb.m_currentFrameId           = fid;
+  sb.m_isGuidedDrawingEnabled   = isGuidedDrawingEnabled;
+  Player::m_onionSkinFrontSize  = 0;
+  Player::m_onionSkinBackSize   = 0;
+  Player::m_firstBackOnionSkin  = 0;
+  Player::m_lastBackVisibleSkin = 0;
   sb.addSimpleLevelFrame(sb.m_players, level, fid);
   updateOnionSkinSize(sb.m_players);
   sb.visit(sb.m_players, visitor, isPlaying);
@@ -767,7 +798,9 @@ void Stage::visit(Visitor &visitor, TXshSimpleLevel *level, const TFrameId &fid,
 //-----------------------------------------------------------------------------
 
 void Stage::visit(Visitor &visitor, TXshLevel *level, const TFrameId &fid,
-                  const OnionSkinMask &osm, bool isPlaying) {
+                  const OnionSkinMask &osm, bool isPlaying,
+                  double isGuidedDrawingEnabled) {
   if (level && level->getSimpleLevel())
-    visit(visitor, level->getSimpleLevel(), fid, osm, isPlaying);
+    visit(visitor, level->getSimpleLevel(), fid, osm, isPlaying,
+          (int)isGuidedDrawingEnabled);
 }
diff --git a/toonz/sources/toonzlib/stageplayer.cpp b/toonz/sources/toonzlib/stageplayer.cpp
index 4419746..f7ea268 100644
--- a/toonz/sources/toonzlib/stageplayer.cpp
+++ b/toonz/sources/toonzlib/stageplayer.cpp
@@ -19,8 +19,10 @@ using namespace Stage;
 //    Stage::Player  implementation
 //*****************************************************************************************
 
-double Player::m_onionSkinFrontSize = 0;
-double Player::m_onionSkinBackSize  = 0;
+double Player::m_onionSkinFrontSize  = 0;
+double Player::m_onionSkinBackSize   = 0;
+double Player::m_firstBackOnionSkin  = 0;
+double Player::m_lastBackVisibleSkin = 0;
 
 //-----------------------------------------------------------------------------
 
@@ -32,6 +34,8 @@ Stage::Player::Player()
     , m_ancestorColumnIndex(-1)
     , m_isCurrentColumn(false)
     , m_isCurrentXsheetLevel(false)
+    , m_isEditingLevel(false)
+    , m_isVisibleinOSM(false)
     , m_sl()
     , m_xsh()
     , m_column(-1)
diff --git a/toonz/sources/toonzlib/stagevisitor.cpp b/toonz/sources/toonzlib/stagevisitor.cpp
index 29ccf07..8c7e4ce 100644
--- a/toonz/sources/toonzlib/stagevisitor.cpp
+++ b/toonz/sources/toonzlib/stagevisitor.cpp
@@ -48,6 +48,7 @@
 #include "toonz/autoclose.h"
 #include "toonz/txshleveltypes.h"
 #include "imagebuilders.h"
+#include "toonz/tframehandle.h"
 
 // Qt includes
 #include <QImage>
@@ -789,7 +790,7 @@ void RasterPainter::onVectorImage(TVectorImage *vi,
 
   const Preferences &prefs = *Preferences::instance();
 
-  TColorFunction *cf = 0;
+  TColorFunction *cf = 0, *guidedCf = 0;
   TPalette *vPalette = vi->getPalette();
   TPixel32 bgColor   = TPixel32::White;
 
@@ -833,13 +834,55 @@ void RasterPainter::onVectorImage(TVectorImage *vi,
                        true  // alpha enabled
                        );
 
-  rd.m_drawRegions       = !inksOnly;
-  rd.m_inkCheckEnabled   = tc & ToonzCheck::eInk;
-  rd.m_paintCheckEnabled = tc & ToonzCheck::ePaint;
-  rd.m_blackBgEnabled    = tc & ToonzCheck::eBlackBg;
-  rd.m_colorCheckIndex   = ToonzCheck::instance()->getColorIndex();
-  rd.m_show0ThickStrokes = prefs.getShow0ThickLines();
-  rd.m_regionAntialias   = prefs.getRegionAntialias();
+  rd.m_drawRegions           = !inksOnly;
+  rd.m_inkCheckEnabled       = tc & ToonzCheck::eInk;
+  rd.m_paintCheckEnabled     = tc & ToonzCheck::ePaint;
+  rd.m_blackBgEnabled        = tc & ToonzCheck::eBlackBg;
+  rd.m_colorCheckIndex       = ToonzCheck::instance()->getColorIndex();
+  rd.m_show0ThickStrokes     = prefs.getShow0ThickLines();
+  rd.m_regionAntialias       = prefs.getRegionAntialias();
+  rd.m_animatedGuidedDrawing = prefs.getAnimatedGuidedDrawing();
+  if (player.m_onionSkinDistance < 0 &&
+      (player.m_isCurrentColumn || player.m_isCurrentXsheetLevel)) {
+    if (player.m_isGuidedDrawingEnabled == 3         // show guides on all
+        || (player.m_isGuidedDrawingEnabled == 1 &&  // show guides on closest
+            player.m_onionSkinDistance == player.m_firstBackOnionSkin) ||
+        (player.m_isGuidedDrawingEnabled == 2 &&  // show guides on farthest
+         player.m_onionSkinDistance == player.m_onionSkinBackSize) ||
+        (player.m_isEditingLevel &&  // fix for level editing mode sending extra
+                                     // players
+         player.m_isGuidedDrawingEnabled == 2 &&
+         player.m_onionSkinDistance == player.m_lastBackVisibleSkin)) {
+      rd.m_showGuidedDrawing = player.m_isGuidedDrawingEnabled > 0;
+      int currentStrokeCount = 0;
+      int totalStrokes       = vi->getStrokeCount();
+      TXshSimpleLevel *sl    = player.m_sl;
+
+      if (sl) {
+        TImageP image          = sl->getFrame(player.m_currentFrameId, false);
+        TVectorImageP vecImage = image;
+        if (vecImage) currentStrokeCount = vecImage->getStrokeCount();
+        if (currentStrokeCount < totalStrokes)
+          rd.m_indexToHighlight = currentStrokeCount;
+
+        double guidedM[4] = {1.0, 1.0, 1.0, 1.0}, guidedC[4];
+        TPixel32 bgColor  = TPixel32::Blue;
+        guidedM[3] =
+            1.0 -
+            ((player.m_onionSkinDistance == 0)
+                 ? 0.1
+                 : OnionSkinMask::getOnionSkinFade(player.m_onionSkinDistance));
+
+        guidedC[0] = (1.0 - guidedM[3]) * bgColor.r,
+        guidedC[1] = (1.0 - guidedM[3]) * bgColor.g,
+        guidedC[2] = (1.0 - guidedM[3]) * bgColor.b;
+        guidedC[3] = 0.0;
+
+        guidedCf      = new TGenericColorFunction(guidedM, guidedC);
+        rd.m_guidedCf = guidedCf;
+      }
+    }
+  }
 
   if (tc & (ToonzCheck::eTransparency | ToonzCheck::eGap)) {
     TPixel dummy;
@@ -874,6 +917,7 @@ void RasterPainter::onVectorImage(TVectorImage *vi,
   vPalette->setFrame(oldFrame);
 
   delete cf;
+  delete guidedCf;
 }
 
 //-----------------------------------------------------