[Bf-extensions-cvs] [8f83df5e] master: GPencil Tools: Fix jumpy rotate reset in cam view

Pullusb noreply at git.blender.org
Wed Jan 26 20:52:40 CET 2022


Commit: 8f83df5eae2efe4f8439a8344cde753ffb203320
Author: Pullusb
Date:   Wed Jan 26 20:52:22 2022 +0100
Branches: master
https://developer.blender.org/rBA8f83df5eae2efe4f8439a8344cde753ffb203320

GPencil Tools: Fix jumpy rotate reset in cam view

Using the shortcut to reset rotation in camera view (default: quick 'cltr + alt + MMB'), the viewport stay centered, even with a pan.

Previously, the view would jump by following cam rotation.

===================================================================

M	greasepencil_tools/__init__.py
M	greasepencil_tools/rotate_canvas.py

===================================================================

diff --git a/greasepencil_tools/__init__.py b/greasepencil_tools/__init__.py
index 64274c3b..54c7262b 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, 5, 3),
+"version": (1, 5, 4),
 "blender": (2, 91, 0),
 "location": "Sidebar > Grease Pencil > Grease Pencil Tools",
 "warning": "",
diff --git a/greasepencil_tools/rotate_canvas.py b/greasepencil_tools/rotate_canvas.py
index 7969972c..f89e006e 100644
--- a/greasepencil_tools/rotate_canvas.py
+++ b/greasepencil_tools/rotate_canvas.py
@@ -84,6 +84,25 @@ class RC_OT_RotateCanvas(bpy.types.Operator):
 
         return mathutils.Vector((center_x, center_y))
 
+    def set_cam_view_offset_from_angle(self, context, angle):
+        '''apply inverse of the rotation on view offset in cam rotate from view center'''
+        neg = -angle
+        rot_mat2d = mathutils.Matrix([[math.cos(neg), -math.sin(neg)], [math.sin(neg), math.cos(neg)]])
+
+        # scale_mat = mathutils.Matrix([[1.0, 0.0], [0.0, self.ratio]])
+        new_cam_offset = self.view_cam_offset.copy()
+
+        ## area deformation correction
+        new_cam_offset = mathutils.Vector((new_cam_offset[0], new_cam_offset[1] * self.ratio))
+
+        ## rotate by matrix
+        new_cam_offset.rotate(rot_mat2d)
+
+        ## area deformation restore
+        new_cam_offset = mathutils.Vector((new_cam_offset[0], new_cam_offset[1] * self.ratio_inv))
+        
+        context.space_data.region_3d.view_camera_offset = new_cam_offset
+
     def execute(self, context):
         if self.hud:
             bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
@@ -121,23 +140,8 @@ class RC_OT_RotateCanvas(bpy.types.Operator):
                 self.cam.rotation_euler.rotate_axis("Z", self.angle)
 
                 if self.use_view_center:
-                    ## apply inverse of the rotation on view offset in cam rotate from view center
-                    neg = -self.angle
-                    rot_mat2d = mathutils.Matrix([[math.cos(neg), -math.sin(neg)], [math.sin(neg), math.cos(neg)]])
-
-                    # scale_mat = mathutils.Matrix([[1.0, 0.0], [0.0, self.ratio]])
-                    new_cam_offset = self.view_cam_offset.copy()
-
-                    ## area deformation correction
-                    new_cam_offset = mathutils.Vector((new_cam_offset[0], new_cam_offset[1] * self.ratio))
-
-                    ## rotate by matrix
-                    new_cam_offset.rotate(rot_mat2d)
-
-                    ## area deformation restore
-                    new_cam_offset = mathutils.Vector((new_cam_offset[0], new_cam_offset[1] * self.ratio_inv))
-
-                    context.space_data.region_3d.view_camera_offset = new_cam_offset
+                    ## apply inverse rotation on view offset
+                    self.set_cam_view_offset_from_angle(context, self.angle)
 
             else: # free view
                 context.space_data.region_3d.view_rotation = self._rotation
@@ -150,14 +154,24 @@ class RC_OT_RotateCanvas(bpy.types.Operator):
             # Trigger reset : Less than 150ms and less than 2 degrees move
             if time() - self.timer < 0.15 and abs(math.degrees(self.angle)) < 2:
                 # self.report({'INFO'}, 'Reset')
-                aim = context.space_data.region_3d.view_rotation @ mathutils.Vector((0.0, 0.0, 1.0))#view vector
-                z_up_quat = aim.to_track_quat('Z','Y')#track Z, up Y
+                aim = context.space_data.region_3d.view_rotation @ mathutils.Vector((0.0, 0.0, 1.0)) # view vector
+                z_up_quat = aim.to_track_quat('Z','Y') # track Z, up Y
                 if self.in_cam:
+
+                    q = self.cam.matrix_world.to_quaternion() # store current rotation
+
                     if self.cam.parent:
+                        q = self.cam.parent.matrix_world.inverted().to_quaternion() @ q
                         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')
+
+                    # get diff angle (might be better way to get view axis rot diff)
+                    diff_angle = q.rotation_difference(cam_quat).to_euler('ZXY').z
+                    # print('diff_angle: ', math.degrees(diff_angle))
+                    self.set_cam_view_offset_from_angle(context, diff_angle)
+
                 else:
                     context.space_data.region_3d.view_rotation = z_up_quat
             self.execute(context)
@@ -187,7 +201,7 @@ class RC_OT_RotateCanvas(bpy.types.Operator):
         # CORRECT UI OVERLAP FROM HEADER TOOLBAR
         regs = context.area.regions
         if context.preferences.system.use_region_overlap:
-            w = context.area.width
+            w = context.area.width 
             # minus tool header
             h = context.area.height - regs[0].height
         else:
@@ -195,9 +209,9 @@ class RC_OT_RotateCanvas(bpy.types.Operator):
             w = context.area.width - regs[2].width - regs[3].width
             # minus tool header + header
             h = context.area.height - regs[0].height - regs[1].height
-
+        
         self.ratio = h / w
-        self.ratio_inv = w / h
+        self.ratio_inv = w / h    
 
         if self.in_cam:
             # Get camera from scene
@@ -207,8 +221,8 @@ class RC_OT_RotateCanvas(bpy.types.Operator):
             if self.cam.lock_rotation[:] != (False, False, False):
                 self.report({'WARNING'}, 'Camera rotation is locked')
                 return {'CANCELLED'}
-
-            if self.use_view_center:
+            
+            if self.use_view_center:                
                 self.center = mathutils.Vector((w/2, h/2))
             else:
                 self.center = self.get_center_view(context, self.cam)
@@ -220,7 +234,7 @@ class RC_OT_RotateCanvas(bpy.types.Operator):
             # store camera matrix world
             self.cam_matrix = self.cam.matrix_world.copy()
             # self.cam_init_euler = self.cam.rotation_euler.copy()
-
+            
             ## initialize current view_offset in camera
             self.view_cam_offset = mathutils.Vector(context.space_data.region_3d.view_camera_offset)
 
@@ -235,7 +249,7 @@ class RC_OT_RotateCanvas(bpy.types.Operator):
         self.pos_current = mathutils.Vector((event.mouse_region_x, event.mouse_region_y))
 
         self.initial_pos = self.pos_current# for draw debug, else no need
-        # Calculate initial vector
+        # Calculate inital vector
         self.vector_initial = self.pos_current - self.center
         self.vector_initial.normalize()



More information about the Bf-extensions-cvs mailing list