1 # SPDX-FileCopyrightText: 2019-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
8 class VIEW3D_OT_rotate_custom_pivot(bpy
.types
.Operator
):
9 bl_idname
= "view3d.rotate_custom_pivot"
10 bl_label
= "Rotate the view"
11 bl_options
= {'BLOCKING', 'GRAB_CURSOR'}
13 __slots__
= 'rv3d', 'init_coord', 'pos1', 'view_rot'
15 pivot
: bpy
.props
.FloatVectorProperty("Pivot", subtype
='XYZ')
16 g_up_axis
: bpy
.props
.FloatVectorProperty(
17 "up_axis", default
=(0.0, 0.0, 1.0), subtype
='XYZ')
18 sensitivity
: bpy
.props
.FloatProperty("sensitivity", default
=0.007)
20 def modal(self
, context
, event
):
21 from mathutils
import Matrix
22 if event
.type in {'MOUSEMOVE', 'INBETWEEN_MOUSEMOVE'}:
23 dx
= self
.init_coord
[0] - event
.mouse_region_x
24 dy
= self
.init_coord
[1] - event
.mouse_region_y
25 rot_ver
= Matrix
.Rotation(-dx
*
26 self
.sensitivity
, 3, self
.g_up_axis
)
27 rot_hor
= Matrix
.Rotation(
28 dy
* self
.sensitivity
, 3, self
.view_rot
[0])
29 rot_mat
= rot_hor
@ rot_ver
30 view_matrix
= self
.view_rot
@ rot_mat
32 pos
= self
.pos1
@ rot_mat
+ self
.pivot
33 qua
= view_matrix
.to_quaternion()
36 self
.rv3d
.view_location
= pos
37 self
.rv3d
.view_rotation
= qua
39 context
.area
.tag_redraw()
40 return {'RUNNING_MODAL'}
44 def invoke(self
, context
, event
):
45 self
.rv3d
= context
.region_data
46 self
.init_coord
= event
.mouse_region_x
, event
.mouse_region_y
47 self
.pos1
= self
.rv3d
.view_location
- self
.pivot
48 self
.view_rot
= self
.rv3d
.view_matrix
.to_3x3()
50 context
.window_manager
.modal_handler_add(self
)
51 return {'RUNNING_MODAL'}
54 class VIEW3D_OT_zoom_custom_target(bpy
.types
.Operator
):
55 bl_idname
= "view3d.zoom_custom_target"
56 bl_label
= "Zoom the view"
57 bl_options
= {'BLOCKING', 'GRAB_CURSOR'}
59 __slots__
= 'rv3d', 'init_dist', 'delta', 'init_loc'
61 target
: bpy
.props
.FloatVectorProperty("target", subtype
='XYZ')
62 delta
: bpy
.props
.IntProperty("delta", default
=0)
65 def modal(self
, context
, event
):
66 if event
.value
== 'PRESS' and event
.type in {'MOUSEMOVE', 'INBETWEEN_MOUSEMOVE'}:
67 if not hasattr(self
, "init_mouse_region_y"):
68 self
.init_mouse_region_y
= event
.mouse_region_y
69 self
.heigt_up
= context
.area
.height
- self
.init_mouse_region_y
70 self
.rv3d
.view_location
= self
.target
72 fac
= (event
.mouse_region_y
-
73 self
.init_mouse_region_y
) / self
.heigt_up
76 delta
= -self
.delta
if context
.preferences
.inputs
.invert_zoom_wheel
else self
.delta
77 fac
= self
.step_factor
* delta
80 self
.rv3d
.view_location
= self
.init_loc
+ \
81 (self
.target
- self
.init_loc
) * fac
82 self
.rv3d
.view_distance
= self
.init_dist
- self
.init_dist
* fac
84 context
.area
.tag_redraw()
87 def invoke(self
, context
, event
):
88 v3d
= context
.space_data
89 dist_range
= (v3d
.clip_start
, v3d
.clip_end
)
90 self
.rv3d
= context
.region_data
91 self
.init_dist
= self
.rv3d
.view_distance
92 delta
= -self
.delta
if context
.preferences
.inputs
.invert_zoom_wheel
else self
.delta
93 if ((delta
<= 0 and self
.init_dist
< dist_range
[1]) or (delta
> 0 and self
.init_dist
> dist_range
[0])):
94 self
.init_loc
= self
.rv3d
.view_location
.copy()
96 context
.window_manager
.modal_handler_add(self
)
97 return {'RUNNING_MODAL'}