From 81b348c4525abdbbd0f176c7486cdc19c0024776 Mon Sep 17 00:00:00 2001 From: Pullusb Date: Tue, 6 Jul 2021 23:56:52 +0200 Subject: GPencil Tools: Canvas rotate improvement In camera view : New rotate canvas pivot mode from view center instead of camera center (enabled by default). Fix rotate canvas precision in free navigation. Also now compatible with region overlap toggled off. --- greasepencil_tools/__init__.py | 2 +- greasepencil_tools/prefs.py | 6 ++++ greasepencil_tools/rotate_canvas.py | 63 ++++++++++++++++++++++++++++++++++--- 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/greasepencil_tools/__init__.py b/greasepencil_tools/__init__.py index 494354d5..646f4862 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, 4, 3), +"version": (1, 5, 0), "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 270497b0..57cf0ee5 100644 --- a/greasepencil_tools/prefs.py +++ b/greasepencil_tools/prefs.py @@ -89,6 +89,11 @@ class GreasePencilAddonPrefs(bpy.types.AddonPreferences): name = "Use Hud", description = "Display angle lines and angle value as text on viewport", default = False) + + canvas_use_view_center: BoolProperty( + name = "Rotate From View Center In Camera", + description = "Rotate from view center in camera view, Else rotate from camera center", + default = True) ## Canvas rotate canvas_use_shortcut: BoolProperty( @@ -197,6 +202,7 @@ class GreasePencilAddonPrefs(bpy.types.AddonPreferences): else: box.label(text="No hotkey has been set automatically. Following operators needs to be set manually:", icon="ERROR") box.label(text="view3d.rotate_canvas") + box.prop(self, 'canvas_use_view_center') box.prop(self, 'canvas_use_hud') ## SCRUB TIMELINE diff --git a/greasepencil_tools/rotate_canvas.py b/greasepencil_tools/rotate_canvas.py index 12ee7339..0b46299d 100644 --- a/greasepencil_tools/rotate_canvas.py +++ b/greasepencil_tools/rotate_canvas.py @@ -43,6 +43,15 @@ def draw_callback_px(self, context): shader.uniform_float("color", (0.3, 0.7, 0.2, 0.5)) batch.draw(shader) + ## debug lines + # batch = batch_for_shader(shader, 'LINES', {"pos": [ + # (0,0), (context.area.width, context.area.height), + # (context.area.width, 0), (0, context.area.height) + # ]}) + # shader.bind() + # shader.uniform_float("color", (0.8, 0.1, 0.1, 0.5)) + # batch.draw(shader) + # restore opengl defaults bgl.glLineWidth(1) bgl.glDisable(bgl.GL_BLEND) @@ -111,7 +120,26 @@ class RC_OT_RotateCanvas(bpy.types.Operator): self.cam.matrix_world = self.cam_matrix self.cam.rotation_euler.rotate_axis("Z", self.angle) - else:#free view + 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 + + else: # free view context.space_data.region_3d.view_rotation = self._rotation rot = context.space_data.region_3d.view_rotation rot = rot.to_euler() @@ -139,20 +167,38 @@ class RC_OT_RotateCanvas(bpy.types.Operator): self.execute(context) if self.in_cam: self.cam.matrix_world = self.cam_matrix + context.space_data.region_3d.view_camera_offset = self.view_cam_offset else: context.space_data.region_3d.view_rotation = self._rotation return {'CANCELLED'} - return {'RUNNING_MODAL'} def invoke(self, context, event): self.current_area = context.area prefs = get_addon_prefs() self.hud = prefs.canvas_use_hud + self.use_view_center = prefs.canvas_use_view_center self.angle = 0.0 self.in_cam = context.region_data.view_perspective == 'CAMERA' + ## store ratio for view rotate correction + + # CORRECT UI OVERLAP FROM HEADER TOOLBAR + regs = context.area.regions + if context.preferences.system.use_region_overlap: + w = context.area.width + # minus tool header + h = context.area.height - regs[0].height + else: + # minus tool leftbar + sidebar right + 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 + if self.in_cam: # Get camera from scene self.cam = bpy.context.scene.camera @@ -161,8 +207,12 @@ 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: + self.center = mathutils.Vector((w/2, h/2)) + else: + self.center = self.get_center_view(context, self.cam) - self.center = self.get_center_view(context, self.cam) # store original rotation mode self.org_rotation_mode = self.cam.rotation_mode # set to euler to works with quaternions, restored at finish @@ -170,9 +220,13 @@ 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) else: - self.center = mathutils.Vector((context.area.width/2, context.area.height/2)) + self.center = mathutils.Vector((w/2, h/2)) + # self.center = mathutils.Vector((context.area.width/2, context.area.height/2)) # store current rotation self._rotation = context.space_data.region_3d.view_rotation.copy() @@ -188,6 +242,7 @@ class RC_OT_RotateCanvas(bpy.types.Operator): # Initializes the current vector with the same initial vector. self.vector_current = self.vector_initial.copy() + #Snap keys self.snap_ctrl = not prefs.use_ctrl self.snap_shift = not prefs.use_shift -- cgit v1.2.3