1 # SPDX-License-Identifier: GPL-2.0-or-later
6 class VIEW3D_OT_rotate_custom_pivot(bpy
.types
.Operator
):
7 bl_idname
= "view3d.rotate_custom_pivot"
8 bl_label
= "Rotate the view"
9 bl_options
= {'BLOCKING', 'GRAB_CURSOR'}
11 __slots__
= 'rv3d', 'init_coord', 'pos1', 'view_rot'
13 pivot
: bpy
.props
.FloatVectorProperty("Pivot", subtype
='XYZ')
14 g_up_axis
: bpy
.props
.FloatVectorProperty(
15 "up_axis", default
=(0.0, 0.0, 1.0), subtype
='XYZ')
16 sensitivity
: bpy
.props
.FloatProperty("sensitivity", default
=0.007)
18 def modal(self
, context
, event
):
19 from mathutils
import Matrix
20 if event
.type in {'MOUSEMOVE', 'INBETWEEN_MOUSEMOVE'}:
21 dx
= self
.init_coord
[0] - event
.mouse_region_x
22 dy
= self
.init_coord
[1] - event
.mouse_region_y
23 rot_ver
= Matrix
.Rotation(-dx
*
24 self
.sensitivity
, 3, self
.g_up_axis
)
25 rot_hor
= Matrix
.Rotation(
26 dy
* self
.sensitivity
, 3, self
.view_rot
[0])
27 rot_mat
= rot_hor
@ rot_ver
28 view_matrix
= self
.view_rot
@ rot_mat
30 pos
= self
.pos1
@ rot_mat
+ self
.pivot
31 qua
= view_matrix
.to_quaternion()
34 self
.rv3d
.view_location
= pos
35 self
.rv3d
.view_rotation
= qua
37 context
.area
.tag_redraw()
38 return {'RUNNING_MODAL'}
42 def invoke(self
, context
, event
):
43 self
.rv3d
= context
.region_data
44 self
.init_coord
= event
.mouse_region_x
, event
.mouse_region_y
45 self
.pos1
= self
.rv3d
.view_location
- self
.pivot
46 self
.view_rot
= self
.rv3d
.view_matrix
.to_3x3()
48 context
.window_manager
.modal_handler_add(self
)
49 return {'RUNNING_MODAL'}
52 class VIEW3D_OT_zoom_custom_target(bpy
.types
.Operator
):
53 bl_idname
= "view3d.zoom_custom_target"
54 bl_label
= "Zoom the view"
55 bl_options
= {'BLOCKING', 'GRAB_CURSOR'}
57 __slots__
= 'rv3d', 'init_dist', 'delta', 'init_loc'
59 target
: bpy
.props
.FloatVectorProperty("target", subtype
='XYZ')
60 delta
: bpy
.props
.IntProperty("delta", default
=0)
63 def modal(self
, context
, event
):
64 if event
.value
== 'PRESS' and event
.type in {'MOUSEMOVE', 'INBETWEEN_MOUSEMOVE'}:
65 if not hasattr(self
, "init_mouse_region_y"):
66 self
.init_mouse_region_y
= event
.mouse_region_y
67 self
.heigt_up
= context
.area
.height
- self
.init_mouse_region_y
68 self
.rv3d
.view_location
= self
.target
70 fac
= (event
.mouse_region_y
-
71 self
.init_mouse_region_y
) / self
.heigt_up
74 delta
= -self
.delta
if context
.preferences
.inputs
.invert_zoom_wheel
else self
.delta
75 fac
= self
.step_factor
* delta
78 self
.rv3d
.view_location
= self
.init_loc
+ \
79 (self
.target
- self
.init_loc
) * fac
80 self
.rv3d
.view_distance
= self
.init_dist
- self
.init_dist
* fac
82 context
.area
.tag_redraw()
85 def invoke(self
, context
, event
):
86 v3d
= context
.space_data
87 dist_range
= (v3d
.clip_start
, v3d
.clip_end
)
88 self
.rv3d
= context
.region_data
89 self
.init_dist
= self
.rv3d
.view_distance
90 delta
= -self
.delta
if context
.preferences
.inputs
.invert_zoom_wheel
else self
.delta
91 if ((delta
<= 0 and self
.init_dist
< dist_range
[1]) or (delta
> 0 and self
.init_dist
> dist_range
[0])):
92 self
.init_loc
= self
.rv3d
.view_location
.copy()
94 context
.window_manager
.modal_handler_add(self
)
95 return {'RUNNING_MODAL'}