Skip to content
Snippets Groups Projects
pdt_view.py 8.24 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ***** 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
    
    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.
    
    
            Returns:
                Status Set.
    
            """
    
            scene = context.scene
            pg = scene.pdt_pg
    
            bpy.ops.view3d.view_orbit(angle=(pg.vrotangle * pi / 180), type="ORBITLEFT")
    
    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")
    
    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")
    
    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")
    
    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")
    
    class PDT_OT_ViewIso(Operator):
        """Set View Isometric."""
    
    
        bl_idname = "pdt.viewiso"
        bl_label = "Isometric View"
        bl_options = {"REGISTER", "UNDO"}
    
        bl_description = "Isometric View."
    
    
        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"
    
            return {"FINISHED"}
    
    
    
    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}")
    
            return {"FINISHED"}