3D Print Toolbox: Add Align to XY Plane
[blender-addons.git] / space_view3d_3d_navigation.py
blobcc06f851ee3759afd948270fcfd32baf6e7640e6
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 # 3D NAVIGATION TOOLBAR v1.2 - 3Dview Addon - Blender 2.5x
4 # contributed to by: Demohero, uriel, jbelcik, meta-androcto
6 bl_info = {
7 "name": "3D Navigation",
8 "author": "Demohero, uriel",
9 "version": (1, 2, 6),
10 "blender": (2, 92, 0),
11 "location": "View3D > Sidebar > View Tab",
12 "description": "Navigate the Camera & 3D Viewport from the Sidebar",
13 "warning": "",
14 "doc_url": "{BLENDER_MANUAL_URL}/addons/3d_view/3d_navigation.html",
15 "category": "3D View",
18 import bpy
19 from bpy.types import (
20 AddonPreferences,
21 Operator,
22 Panel,
24 from bpy.props import StringProperty
27 # main class of this toolbar
29 # re-ordered (reversed) Orbit Operators
30 class VIEW3D_OT_OrbitUpView1(Operator):
31 bl_idname = "opr.orbit_up_view1"
32 bl_label = "Orbit Up View"
33 bl_description = "Orbit the view towards you"
35 def execute(self, context):
36 bpy.ops.view3d.view_orbit(type='ORBITUP')
37 return {'FINISHED'}
40 class VIEW3D_OT_OrbitLeftView1(Operator):
41 bl_idname = "opr.orbit_left_view1"
42 bl_label = "Orbit Left View"
43 bl_description = "Orbit the view around to your Right"
45 def execute(self, context):
46 bpy.ops.view3d.view_orbit(type='ORBITLEFT')
47 return {'FINISHED'}
50 class VIEW3D_OT_OrbitRightView1(Operator):
51 bl_idname = "opr.orbit_right_view1"
52 bl_label = "Orbit Right View"
53 bl_description = "Orbit the view around to your Left"
55 def execute(self, context):
56 bpy.ops.view3d.view_orbit(type='ORBITRIGHT')
57 return {'FINISHED'}
60 class VIEW3D_OT_OrbitDownView1(Operator):
61 bl_idname = "opr.orbit_down_view1"
62 bl_label = "Orbit Down View"
63 bl_description = "Orbit the view away from you"
65 def execute(self, context):
66 bpy.ops.view3d.view_orbit(type='ORBITDOWN')
67 return {'FINISHED'}
70 # re-ordered (reversed) Pan Operators
71 # just pass the enum from the VIEW3D_PT_pan_navigation1 Panel
72 class VIEW3D_OT_PanUpViewsAll(Operator):
73 bl_idname = "opr.pan_up_views_all"
74 bl_label = "Pan View"
75 bl_description = "Pan the 3D View"
77 panning: StringProperty(
78 default="PANUP",
79 options={"HIDDEN"}
82 def execute(self, context):
83 try:
84 bpy.ops.view3d.view_pan("INVOKE_REGION_WIN", type=self.panning)
85 except Exception as e:
86 self.report({"WARNING"},
87 "Pan Views could not be completed. Operation Cancelled")
88 print("\n[3D Navigation]\nOperator: opr.pan_up_views_all\n {}\n".format(e))
90 return {"CANCELLED"}
92 return {'FINISHED'}
95 # Zoom Operators
96 class VIEW3D_OT_ZoomInView1(Operator):
97 bl_idname = "opr.zoom_in_view1"
98 bl_label = "Zoom In View"
99 bl_description = "Zoom In the View/Camera View"
101 def execute(self, context):
102 bpy.ops.view3d.zoom(delta=1)
103 return {'FINISHED'}
106 class VIEW3D_OT_ZoomOutView1(Operator):
107 bl_idname = "opr.zoom_out_view1"
108 bl_label = "Zoom Out View"
109 bl_description = "Zoom out In the View/Camera View"
111 def execute(self, context):
112 bpy.ops.view3d.zoom(delta=-1)
113 return {'FINISHED'}
116 # Roll Operators
117 class VIEW3D_OT_RollLeftView1(Operator):
118 bl_idname = "opr.roll_left_view1"
119 bl_label = "Roll Left View"
120 bl_description = "Roll the view Left"
122 def execute(self, context):
123 bpy.ops.view3d.view_roll(angle=-0.261799)
124 return {'FINISHED'}
127 class VIEW3D_OT_RollRightView1(Operator):
128 bl_idname = "opr.roll_right_view1"
129 bl_label = "Roll Right View"
130 bl_description = "Roll the view Right"
132 def execute(self, context):
133 bpy.ops.view3d.view_roll(angle=0.261799)
134 return {'FINISHED'}
137 # View Operators
138 class VIEW3D_OT_LeftViewpoint1(Operator):
139 bl_idname = "opr.left_viewpoint1"
140 bl_label = "Left Viewpoint"
141 bl_description = "View from the Left"
143 def execute(self, context):
144 bpy.ops.view3d.view_axis(type='LEFT')
145 return {'FINISHED'}
148 class VIEW3D_OT_RightViewpoint1(Operator):
149 bl_idname = "opr.right_viewpoint1"
150 bl_label = "Right Viewpoint"
151 bl_description = "View from the Right"
153 def execute(self, context):
154 bpy.ops.view3d.view_axis(type='RIGHT')
155 return {'FINISHED'}
158 class VIEW3D_OT_FrontViewpoint1(Operator):
159 bl_idname = "opr.front_viewpoint1"
160 bl_label = "Front Viewpoint"
161 bl_description = "View from the Front"
163 def execute(self, context):
164 bpy.ops.view3d.view_axis(type='FRONT')
165 return {'FINISHED'}
168 class VIEW3D_OT_BackViewpoint1(Operator):
169 bl_idname = "opr.back_viewpoint1"
170 bl_label = "Back Viewpoint"
171 bl_description = "View from the Back"
173 def execute(self, context):
174 bpy.ops.view3d.view_axis(type='BACK')
175 return {'FINISHED'}
178 class VIEW3D_OT_TopViewpoint1(Operator):
179 bl_idname = "opr.top_viewpoint1"
180 bl_label = "Top Viewpoint"
181 bl_description = "View from the Top"
183 def execute(self, context):
184 bpy.ops.view3d.view_axis(type='TOP')
185 return {'FINISHED'}
188 class VIEW3D_OT_BottomViewpoint1(Operator):
189 bl_idname = "opr.bottom_viewpoint1"
190 bl_label = "Bottom Viewpoint"
191 bl_description = "View from the Bottom"
193 def execute(self, context):
194 bpy.ops.view3d.view_axis(type='BOTTOM')
195 return {'FINISHED'}
198 # Panel class of this toolbar
199 class VIEW3D_PT_3dnavigationPanel(Panel):
200 bl_space_type = "VIEW_3D"
201 bl_region_type = "UI"
202 bl_label = "3D Navigation"
203 bl_category = "View"
204 bl_options = {'DEFAULT_CLOSED'}
206 def draw(self, context):
207 layout = self.layout
208 view = context.space_data
210 # Triple buttons
211 col = layout.column(align=True)
212 col.operator("view3d.localview", text="View Global/Local")
213 col.operator("view3d.view_persportho", text="Perspective/Orthographic")
214 col.operator("view3d.view_camera", text="View Camera", icon='CAMERA_DATA')
216 # group of 6 buttons
217 col = layout.column(align=True)
218 col.label(text="Align view from:", icon="VIEW3D")
219 row = col.row()
220 row.operator("view3d.view_axis", text="Front").type = 'FRONT'
221 row.operator("view3d.view_axis", text="Back").type = 'BACK'
222 row = col.row()
223 row.operator("view3d.view_axis", text="Left").type = 'LEFT'
224 row.operator("view3d.view_axis", text="Right").type = 'RIGHT'
225 row = col.row()
226 row.operator("view3d.view_axis", text="Top").type = 'TOP'
227 row.operator("view3d.view_axis", text="Bottom").type = 'BOTTOM'
229 # group of 2 buttons
230 col = layout.column(align=True)
231 col.label(text="Lock View to Object:", icon="LOCKED")
232 col.prop(view, "lock_object", text="")
233 col.operator("view3d.view_selected", text="View to Selected")
235 col = layout.column(align=True)
236 col.label(text="Cursor:", icon='PIVOT_CURSOR')
237 row = col.row(align=True)
238 row.operator("view3d.snap_cursor_to_center", text="World Origin")
239 row.operator("view3d.view_center_cursor", text="View")
240 col.operator("view3d.snap_cursor_to_selected", text="Cursor to Selected")
243 class VIEW3D_PT_3dnavigationPanel2(Panel):
244 bl_space_type = "VIEW_3D"
245 bl_region_type = "UI"
246 bl_label = "Pan Orbit Zoom Roll"
247 bl_category = "View"
248 bl_options = {'DEFAULT_CLOSED'}
250 def draw(self, context):
251 layout = self.layout
252 layout.label(text="Screen View Perspective")
254 row = layout.row()
255 row.label(text="Pan:")
256 row = layout.row()
258 row.operator("opr.pan_up_views_all", text="Up",
259 icon="TRIA_UP").panning = "PANDOWN"
260 row.operator("opr.pan_up_views_all", text="Down",
261 icon="TRIA_DOWN").panning = "PANUP"
263 row = layout.row()
264 row.operator("opr.pan_up_views_all", text="Left",
265 icon="BACK").panning = "PANRIGHT"
266 row.operator("opr.pan_up_views_all", text="Right",
267 icon="FORWARD").panning = "PANLEFT"
269 row = layout.row()
270 row.label(text="Orbit:")
271 row = layout.row()
272 row.operator("opr.orbit_down_view1", text="Up", icon="TRIA_UP")
273 row.operator("opr.orbit_up_view1", text="Down", icon="TRIA_DOWN")
275 row = layout.row()
276 row.operator("opr.orbit_right_view1", text="Left", icon="BACK")
277 row.operator("opr.orbit_left_view1", text="Right", icon="FORWARD")
279 row = layout.row()
280 row.label(text="Zoom:")
281 row = layout.row()
282 row.operator("opr.zoom_in_view1", text="In", icon='ADD')
283 row.operator("opr.zoom_out_view1", text="Out", icon='REMOVE')
285 row = layout.row()
286 row.label(text="Roll:")
287 row = layout.row()
288 row.operator("opr.roll_left_view1", text="Left", icon="LOOP_BACK")
289 row.operator("opr.roll_right_view1", text="Right", icon="LOOP_FORWARDS")
292 # Add-ons Preferences Update Panel
294 # Define Panel classes for updating
295 panels = (
296 VIEW3D_PT_3dnavigationPanel,
297 VIEW3D_PT_3dnavigationPanel2,
301 def update_panel(self, context):
302 message = ": Updating Panel locations has failed"
303 try:
304 for panel in panels:
305 if "bl_rna" in panel.__dict__:
306 bpy.utils.unregister_class(panel)
308 for panel in panels:
309 panel.bl_category = context.preferences.addons[__name__].preferences.category
310 bpy.utils.register_class(panel)
312 except Exception as e:
313 print("\n[{}]\n{}\n\nError:\n{}".format(__name__, message, e))
314 pass
317 class NavAddonPreferences(AddonPreferences):
318 # this must match the addon name, use '__package__'
319 # when defining this in a submodule of a python package.
320 bl_idname = __name__
322 category: StringProperty(
323 name="Tab Category",
324 description="Choose a name for the category of the panel",
325 default="View",
326 update=update_panel
329 def draw(self, context):
330 layout = self.layout
332 row = layout.row()
333 col = row.column()
334 col.label(text="Tab Category:")
335 col.prop(self, "category", text="")
338 classes = (
339 VIEW3D_PT_3dnavigationPanel,
340 VIEW3D_PT_3dnavigationPanel2,
341 VIEW3D_OT_OrbitUpView1,
342 VIEW3D_OT_OrbitLeftView1,
343 VIEW3D_OT_OrbitRightView1,
344 VIEW3D_OT_OrbitDownView1,
345 VIEW3D_OT_ZoomInView1,
346 VIEW3D_OT_ZoomOutView1,
347 VIEW3D_OT_RollLeftView1,
348 VIEW3D_OT_RollRightView1,
349 VIEW3D_OT_LeftViewpoint1,
350 VIEW3D_OT_RightViewpoint1,
351 VIEW3D_OT_FrontViewpoint1,
352 VIEW3D_OT_BackViewpoint1,
353 VIEW3D_OT_TopViewpoint1,
354 VIEW3D_OT_BottomViewpoint1,
355 VIEW3D_OT_PanUpViewsAll,
356 NavAddonPreferences,
360 # Register
361 def register():
362 for cls in classes:
363 bpy.utils.register_class(cls)
364 update_panel(None, bpy.context)
367 def unregister():
368 for cls in classes:
369 bpy.utils.unregister_class(cls)
372 if __name__ == "__main__":
373 register()