1 ### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 3
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 # ##### END GPL LICENSE BLOCK #####
21 class VIEW3D_OT_rotate_custom_pivot(bpy
.types
.Operator
):
22 bl_idname
= "view3d.rotate_custom_pivot"
23 bl_label
= "Rotate the view"
24 bl_options
= {'BLOCKING', 'GRAB_CURSOR'}
26 __slots__
= 'rv3d', 'init_coord', 'pos1', 'view_rot'
28 pivot
: bpy
.props
.FloatVectorProperty("Pivot", subtype
='XYZ')
29 g_up_axis
: bpy
.props
.FloatVectorProperty("up_axis", default
=(0.0, 0.0, 1.0), subtype
='XYZ')
30 sensitivity
: bpy
.props
.FloatProperty("sensitivity", default
=0.007)
32 def modal(self
, context
, event
):
33 from mathutils
import Matrix
34 if event
.value
== 'PRESS' and event
.type in {'MOUSEMOVE', 'INBETWEEN_MOUSEMOVE'}:
35 dx
= self
.init_coord
[0] - event
.mouse_region_x
36 dy
= self
.init_coord
[1] - event
.mouse_region_y
37 rot_ver
= Matrix
.Rotation(-dx
* self
.sensitivity
, 3, self
.g_up_axis
)
38 rot_hor
= Matrix
.Rotation(dy
* self
.sensitivity
, 3, self
.view_rot
[0])
39 rot_mat
= rot_hor
@ rot_ver
40 view_matrix
= self
.view_rot
@ rot_mat
42 pos
= self
.pos1
@ rot_mat
+ self
.pivot
43 qua
= view_matrix
.to_quaternion()
46 self
.rv3d
.view_location
= pos
47 self
.rv3d
.view_rotation
= qua
49 context
.area
.tag_redraw()
50 return {'RUNNING_MODAL'}
54 def invoke(self
, context
, event
):
55 self
.rv3d
= context
.region_data
56 self
.init_coord
= event
.mouse_region_x
, event
.mouse_region_y
57 self
.pos1
= self
.rv3d
.view_location
- self
.pivot
58 self
.view_rot
= self
.rv3d
.view_matrix
.to_3x3()
60 context
.window_manager
.modal_handler_add(self
)
61 return {'RUNNING_MODAL'}
64 class VIEW3D_OT_zoom_custom_target(bpy
.types
.Operator
):
65 bl_idname
= "view3d.zoom_custom_target"
66 bl_label
= "Zoom the view"
67 bl_options
= {'BLOCKING', 'GRAB_CURSOR'}
69 __slots__
= 'rv3d', 'init_dist', 'delta', 'init_loc'
71 target
: bpy
.props
.FloatVectorProperty("target", subtype
='XYZ')
72 delta
: bpy
.props
.IntProperty("delta", default
=0)
75 def modal(self
, context
, event
):
76 if event
.value
== 'PRESS' and event
.type in {'MOUSEMOVE', 'INBETWEEN_MOUSEMOVE'}:
77 if not hasattr(self
, "init_mouse_region_y"):
78 self
.init_mouse_region_y
= event
.mouse_region_y
79 self
.heigt_up
= context
.area
.height
- self
.init_mouse_region_y
80 self
.rv3d
.view_location
= self
.target
82 fac
= (event
.mouse_region_y
- self
.init_mouse_region_y
) / self
.heigt_up
85 fac
= self
.step_factor
* self
.delta
88 self
.rv3d
.view_location
= self
.init_loc
+ (self
.target
- self
.init_loc
) * fac
89 self
.rv3d
.view_distance
= self
.init_dist
- self
.init_dist
* fac
91 context
.area
.tag_redraw()
94 def invoke(self
, context
, event
):
95 v3d
= context
.space_data
96 dist_range
= (v3d
.clip_start
, v3d
.clip_end
)
97 self
.rv3d
= context
.region_data
98 self
.init_dist
= self
.rv3d
.view_distance
99 if ((self
.delta
<= 0 and self
.init_dist
< dist_range
[1]) or
100 (self
.delta
> 0 and self
.init_dist
> dist_range
[0])):
101 self
.init_loc
= self
.rv3d
.view_location
.copy()
103 context
.window_manager
.modal_handler_add(self
)
104 return {'RUNNING_MODAL'}