diff --git a/greasepencil_tools/__init__.py b/greasepencil_tools/__init__.py
index e5135422773dab85740c795b69de35f8dd5e3309..9ac882ba98934b0f667eda2ede94343b1e003649 100644
--- a/greasepencil_tools/__init__.py
+++ b/greasepencil_tools/__init__.py
@@ -21,7 +21,7 @@ bl_info = {
 "name": "Grease Pencil Tools",
 "description": "Extra tools for Grease Pencil",
 "author": "Samuel Bernou, Antonio Vazquez, Daniel Martinez Lara, Matias Mendiola",
-"version": (1, 2, 1),
+"version": (1, 2, 2),
 "blender": (2, 91, 0),
 "location": "Sidebar > Grease Pencil > Grease Pencil Tools",
 "warning": "",
diff --git a/greasepencil_tools/prefs.py b/greasepencil_tools/prefs.py
index b8b9894d7ea28ffaab3da0bb7219d2aa05a7fa6c..fff0f18cef1f0ab7ee0a1de27b4dfd5ff464edb6 100644
--- a/greasepencil_tools/prefs.py
+++ b/greasepencil_tools/prefs.py
@@ -245,14 +245,19 @@ def unregister_keymaps():
 
 ### REGISTER ---
 
+classes = (
+    GPTS_timeline_settings,
+    GreasePencilAddonPrefs,
+)
+
 def register():
-    bpy.utils.register_class(GPTS_timeline_settings)
-    bpy.utils.register_class(GreasePencilAddonPrefs)
+    for cls in classes:
+        bpy.utils.register_class(cls)
     # Force box deform running to false
     bpy.context.preferences.addons[os.path.splitext(__name__)[0]].preferences.boxdeform_running = False
     register_keymaps()
 
 def unregister():
     unregister_keymaps()
-    bpy.utils.unregister_class(GreasePencilAddonPrefs)
-    bpy.utils.unregister_class(GPTS_timeline_settings)
+    for cls in reversed(classes):
+        bpy.utils.unregister_class(cls)
diff --git a/greasepencil_tools/rotate_canvas.py b/greasepencil_tools/rotate_canvas.py
index aec6e9003973421ee98add76401c716bb5cedce6..e2ada531da1e284ceb62585cd78834b73f0ccba8 100644
--- a/greasepencil_tools/rotate_canvas.py
+++ b/greasepencil_tools/rotate_canvas.py
@@ -95,7 +95,15 @@ class RC_OT_RotateCanvas(bpy.types.Operator):
             if not self.angle:
                 # self.report({'INFO'}, 'Reset')
                 aim = context.space_data.region_3d.view_rotation @ mathutils.Vector((0.0, 0.0, 1.0))#view vector
-                context.space_data.region_3d.view_rotation = aim.to_track_quat('Z','Y')#track Z, up Y
+                z_up_quat = aim.to_track_quat('Z','Y')#track Z, up Y
+                if self.in_cam:
+                    if self.cam.parent:
+                        cam_quat = self.cam.parent.matrix_world.inverted().to_quaternion() @ z_up_quat
+                    else:
+                        cam_quat = z_up_quat
+                    self.cam.rotation_euler = cam_quat.to_euler('XYZ')
+                else:
+                    context.space_data.region_3d.view_rotation = z_up_quat
             self.execute(context)
             return {'FINISHED'}
 
diff --git a/greasepencil_tools/timeline_scrub.py b/greasepencil_tools/timeline_scrub.py
index 1f89f4d1c1c60659da2198bfbfdfcf089949dea6..dfffdeaadbfc427c082dd73d194b95f339bf8bba 100644
--- a/greasepencil_tools/timeline_scrub.py
+++ b/greasepencil_tools/timeline_scrub.py
@@ -143,8 +143,17 @@ class GPTS_OT_time_scrub(bpy.types.Operator):
         self.snap_on = False
         self.mouse = (event.mouse_region_x, event.mouse_region_y)
         self.init_mouse_x = self.cursor_x = event.mouse_region_x
+        
         # self.init_mouse_y = event.mouse_region_y # only to display init frame text
         self.init_frame = self.new_frame = context.scene.frame_current
+        self.lock_range = context.scene.lock_frame_selection_to_range
+        if context.scene.use_preview_range:
+            self.f_start = context.scene.frame_preview_start
+            self.f_end = context.scene.frame_preview_end
+        else:
+            self.f_start = context.scene.frame_start
+            self.f_end = context.scene.frame_end
+            
         self.offset = 0
         self.pos = []
 
@@ -181,17 +190,13 @@ class GPTS_OT_time_scrub(bpy.types.Operator):
                     for frame in layer.frames:
                         if frame.frame_number not in self.pos:
                             self.pos.append(frame.frame_number)
+        
 
         # Add start and end to snap on
-        if context.scene.use_preview_range:
-            play_bounds = [context.scene.frame_preview_start,
-                           context.scene.frame_preview_end]
-        else:
-            play_bounds = [context.scene.frame_start, context.scene.frame_end]
+
 
         # Also snap on play bounds (sliced off for keyframe display)
-        self.pos += play_bounds
-        self.pos = np.asarray(self.pos)
+        self.pos += [self.f_start, self.f_end]
 
         # Disable Onion skin
         self.active_space_data = context.space_data
@@ -240,9 +245,9 @@ class GPTS_OT_time_scrub(bpy.types.Operator):
         # Add start/end boundary bracket to HUD
 
         start_x = self.init_mouse_x + \
-            (play_bounds[0] - self.init_frame) * self.px_step
+            (self.f_start - self.init_frame) * self.px_step
         end_x = self.init_mouse_x + \
-            (play_bounds[1] - self.init_frame) * self.px_step
+            (self.f_end - self.init_frame) * self.px_step
 
         # start
         up = (start_x, my - (bound_h/2))
@@ -318,6 +323,15 @@ class GPTS_OT_time_scrub(bpy.types.Operator):
             self.batch_keyframes = batch_for_shader(
                 shader, 'TRIS', {"pos": shaped_key}, indices=indices)
 
+        # Trim snapping list of frame outside of frame range if range lock activated
+        # (after drawing batch so those are still showed)
+        if self.lock_range:
+            self.pos = [i for i in self.pos if self.f_start <= i <= self.f_end]
+        
+        # convert frame list to array for numpy snap utility
+        self.pos = np.asarray(self.pos)
+
+
         args = (self, context)
         self.viewtype = None
         self.spacetype = 'WINDOW'  # is PREVIEW for VSE, needed for handler remove
@@ -371,6 +385,14 @@ class GPTS_OT_time_scrub(bpy.types.Operator):
             if self.snap_on or mod_snap:
                 self.new_frame = nearest(self.pos, self.new_frame)
 
+            # frame range restriction
+            if self.lock_range:
+                if self.new_frame < self.f_start:
+                    self.new_frame = self.f_start
+                elif self.new_frame > self.f_end:
+                    self.new_frame = self.f_end
+
+            # context.scene.frame_set(self.new_frame)
             context.scene.frame_current = self.new_frame
 
             # - recalculate offset to snap cursor to frame