diff options
author | Pullusb <bernou.samuel@gmail.com> | 2022-01-26 22:52:22 +0300 |
---|---|---|
committer | Pullusb <bernou.samuel@gmail.com> | 2022-01-26 22:52:22 +0300 |
commit | 8f83df5eae2efe4f8439a8344cde753ffb203320 (patch) | |
tree | 2556eefad50ff9e0bca31dbc77a7bbae724d0ec1 | |
parent | 692611358a9189c2f54f916c42a08e1ddf54bb84 (diff) |
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.
-rw-r--r-- | greasepencil_tools/__init__.py | 2 | ||||
-rw-r--r-- | greasepencil_tools/rotate_canvas.py | 66 |
2 files changed, 41 insertions, 27 deletions
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() |