Newer
Older
# ***** BEGIN GPL LICENSE BLOCK *****
#
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENCE BLOCK *****
#
# -----------------------------------------------------------------------
# Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019
#
# Contains code which was inspired by the "Reset 3D View" plugin authored
# by Reiner Prokein (tiles) Copyright (c) 2014 (see T37718)
# -----------------------------------------------------------------------
#
import bpy
from bpy.types import Operator
from math import pi
from mathutils import Quaternion
from .pdt_functions import debug, euler_to_quaternion
class PDT_OT_ViewRot(Operator):
"""Rotate View by Absolute Coordinates."""
bl_idname = "pdt.viewrot"
bl_label = "Rotate View"
bl_options = {"REGISTER", "UNDO"}
bl_description = "View Rotation by Absolute Values"
def execute(self, context):
"""View Rotation by Absolute Values.
Note:
Rotations are converted to 3x3 Quaternion Rotation Matrix.
This is an Absolute Rotation, not an Incremental Orbit.
Uses pg.rotation_coords scene variable
Args:
context: Blender bpy.context instance.
Returns:
Status Set.
"""
scene = context.scene
pg = scene.pdt_pg
roll_value = euler_to_quaternion(
pg.rotation_coords.x * pi / 180,
pg.rotation_coords.y * pi / 180,
pg.rotation_coords.z * pi / 180,
)
context.region_data.view_rotation = roll_value
return {"FINISHED"}
class PDT_OT_ViewRotL(Operator):
"""Rotate View Left."""
bl_idname = "pdt.viewleft"
bl_label = "Rotate Left"
bl_options = {"REGISTER", "UNDO"}
bl_description = "View Orbit Left by Delta Value"
def execute(self, context):
"""View Orbit Left by Delta Value.
Note:
Uses pg.vrotangle scene variable
Orbits view to the left about its vertical axis
Args:
context: Blender bpy.context instance.
"""
scene = context.scene
pg = scene.pdt_pg
bpy.ops.view3d.view_orbit(angle=(pg.vrotangle * pi / 180), type="ORBITLEFT")
return {"FINISHED"}
class PDT_OT_ViewRotR(Operator):
"""Rotate View Right."""
bl_idname = "pdt.viewright"
bl_label = "Rotate Right"
bl_options = {"REGISTER", "UNDO"}
bl_description = "View Orbit Right by Delta Value"
def execute(self, context):
"""View Orbit Right by Delta Value.
Note:
Uses pg.vrotangle scene variable
Orbits view to the right about its vertical axis
Args:
context: Blender bpy.context instance.
Returns:
Status Set.
"""
scene = context.scene
pg = scene.pdt_pg
bpy.ops.view3d.view_orbit(angle=(pg.vrotangle * pi / 180), type="ORBITRIGHT")
return {"FINISHED"}
class PDT_OT_ViewRotU(Operator):
"""Rotate View Up."""
bl_idname = "pdt.viewup"
bl_label = "Rotate Up"
bl_options = {"REGISTER", "UNDO"}
bl_description = "View Orbit Up by Delta Value"
def execute(self, context):
"""View Orbit Up by Delta Value.
Note:
Uses pg.vrotangle scene variable
Orbits view up about its horizontal axis
Args:
context: Blender bpy.context instance.
Returns:
Status Set.
"""
scene = context.scene
pg = scene.pdt_pg
bpy.ops.view3d.view_orbit(angle=(pg.vrotangle * pi / 180), type="ORBITUP")
return {"FINISHED"}
class PDT_OT_ViewRotD(Operator):
"""Rotate View Down."""
bl_idname = "pdt.viewdown"
bl_label = "Rotate Down"
bl_options = {"REGISTER", "UNDO"}
bl_description = "View Orbit Down by Delta Value"
def execute(self, context):
"""View Orbit Down by Delta Value.
Note:
Uses pg.vrotangle scene variable
Orbits view down about its horizontal axis
Args:
context: Blender bpy.context instance.
Returns:
Status Set.
"""
scene = context.scene
pg = scene.pdt_pg
bpy.ops.view3d.view_orbit(angle=(pg.vrotangle * pi / 180), type="ORBITDOWN")
return {"FINISHED"}
class PDT_OT_ViewRoll(Operator):
"""Roll View."""
bl_idname = "pdt.viewroll"
bl_label = "Roll View"
bl_options = {"REGISTER", "UNDO"}
bl_description = "View Roll by Delta Value"
def execute(self, context):
"""View Roll by Delta Value.
Note:
Uses pg.vrotangle scene variable
Rolls view about its normal axis
Args:
context: Blender bpy.context instance.
Returns:
Status Set.
"""
scene = context.scene
pg = scene.pdt_pg
bpy.ops.view3d.view_roll(angle=(pg.vrotangle * pi / 180), type="ANGLE")
return {"FINISHED"}
class PDT_OT_ViewIso(Operator):
"""Set View Isometric."""
bl_idname = "pdt.viewiso"
bl_label = "Isometric View"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
"""Set Isometric View.
Note:
Set view orientation to Orthographic Isometric
Args:
context: Blender bpy.context instance.
Returns:
Status Set.
"""
# Rotate view 45 degrees about Z then 32.2644 about X
context.region_data.view_rotation = Quaternion((0.8205, 0.4247, -0.1759, -0.3399))
context.region_data.view_perspective = "ORTHO"
class PDT_OT_Reset3DView(Operator):
"""Reset Views to Factory Default."""
bl_idname = "pdt.reset_3d_view"
bl_label = "Reset 3D View"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Reset 3D View to Blender Defaults."
def execute(self, context):
"""Reset 3D View to Blender Defaults.
Args:
context: Blender bpy.context instance.
Returns:
Status Set.
"""
# The default view_distance to the origin when starting up Blender
default_view_distance = 17.986562728881836
default_view_distance = (
bpy.data.screens["Layout"].areas[-1].spaces[0].region_3d.view_distance
)
# The default view_matrix when starting up Blender
default_view_matrix = (
(0.41, -0.4017, 0.8188, 0.0),
(0.912, 0.1936, -0.3617, 0.0),
(-0.0133, 0.8950, 0.4458, 0.0),
(0.0, 0.0, -17.9866, 1.0),
view = context.region_data
debug(f"is_orthographic_side_view: {view.is_orthographic_side_view}")
if view.is_orthographic_side_view:
# When the view is orthographic, reset the distance and location.
# The rotation already fits.
debug(f"view_distance before reset: {view.view_distance}")
debug(f"view_location before reset: {view.view_location}")
view.view_distance = default_view_distance
view.view_location = (-0.0, -0.0, -0.0)
view.update()
debug(f"view_distance AFTER reset: {view.view_distance}")
debug(f"view_location AFTER reset: {view.view_location}")
else:
# Otherwise, the view matrix needs to be reset.
debug(f"view_matrix before reset:\n{view.view_matrix}")
view.view_matrix = default_view_matrix
view.view_distance = default_view_distance
view.update()
debug(f"view_matrix AFTER reset:\n{view.view_matrix}")