7
$\begingroup$

Is it possible to access the alignment of the view from python? (e.g 'TOP', 'FRONT', 'RIGHT', etc.)

I looked in the api docs, but the closest I could find was view_perspective.

$\endgroup$
1

3 Answers 3

12
$\begingroup$

Looking at the implementation of view3d.viewnumpad in view3d_edit.c, it's just switch-ing over FRONT, BACK, etc. enumerations and setting the view matrix accordingly. The only way I found is through deducing the orientation from view matrix in Python, in the following barebones example using either view_matrix:

import math

def get_view_orientation_from_matrix(view_matrix):
    r = lambda x: round(x, 2)
    view_rot = view_matrix.to_euler()

    orientation_dict = {(0.0, 0.0, 0.0) : 'TOP',
                        (r(math.pi), 0.0, 0.0) : 'BOTTOM',
                        (r(-math.pi/2), 0.0, 0.0) : 'FRONT',
                        (r(math.pi/2), 0.0, r(-math.pi)) : 'BACK',
                        (r(-math.pi/2), r(math.pi/2), 0.0) : 'LEFT',
                        (r(-math.pi/2), r(-math.pi/2), 0.0) : 'RIGHT'}

    return orientation_dict.get(tuple(map(r, view_rot)), 'UNDEFINED')

... or view_rotation as @WChargin suggested, seeing that it's normalized as stated in API docs:

def get_view_orientation_from_quaternion(view_quat):
    r = lambda x: round(x, 3)
    view_rot = view_quat.to_euler()

    orientation_dict = {(0.0, 0.0, 0.0) : 'TOP',
                        (r(math.pi), 0.0, 0.0) : 'BOTTOM',
                        (r(math.pi/2), 0.0, 0.0) : 'FRONT',
                        (r(math.pi/2), 0.0, r(math.pi)) : 'BACK',
                        (r(math.pi/2), 0.0, r(-math.pi/2)) : 'LEFT',
                        (r(math.pi/2), 0.0, r(math.pi/2)) : 'RIGHT'}

    return orientation_dict.get(tuple(map(r, view_rot)), 'UNDEFINED')

It currently ignores perspective/orthogonal and camera view, but that can be easily deduced from the region's other variables.

enter image description here

$\endgroup$
3
  • $\begingroup$ Where are you getting the pi/2 from? Those vectors aren't even normalized (e.g., 2pi^2/4 is not 1). You probably mean sqrt(2) for the ones with two nonzero components and 1 for the ones with just one... $\endgroup$
    – wchargin
    Commented Oct 21, 2013 at 3:15
  • $\begingroup$ Especially considering the #define M_SQRT1_2 0.70710678118654752440 in conjunction with axis_set_view(C, v3d, ar, 0.0, 0.0, -M_SQRT1_2, -M_SQRT1_2, viewnum, nextperspo, align_active, smooth_viewtx); (for example). $\endgroup$
    – wchargin
    Commented Oct 21, 2013 at 3:17
  • $\begingroup$ I get these constants the stupid way: executing each view shortcuts, and see the resulting matrix :D On second thought, maybe I should've used view_rotation.to_euler() as you suggested. $\endgroup$
    – Adhi
    Commented Oct 21, 2013 at 4:26
7
$\begingroup$

Based on Adhi's solution, here's a complete operator to print all view3d perspectives like shown in the left-upper corner:

import bpy
import math


def main(context):
    view_orientations = []

    for area in context.screen.areas:
        if area.type == 'VIEW_3D':
            r3d = area.spaces.active.region_3d # fine for right-upper quadview view
            view_matrix = r3d.view_matrix

            view_orientation = get_view_orientation_from_matrix(view_matrix).capitalize()
            view_orientation += " " + r3d.view_perspective.capitalize()
            if area.spaces.active.local_view is not None:
                view_orientation += " (Local)"

            view_orientations.append(view_orientation)

    return view_orientations


def get_view_orientation_from_matrix(view_matrix):
    r = lambda x: round(x, 2)
    view_rot = view_matrix.to_euler()

    orientation_dict = {(0.0, 0.0, 0.0) : 'TOP',
                        (r(math.pi), 0.0, 0.0) : 'BOTTOM',
                        (r(-math.pi/2), 0.0, 0.0) : 'FRONT',
                        (r(math.pi/2), 0.0, r(-math.pi)) : 'BACK',
                        (r(-math.pi/2), r(math.pi/2), 0.0) : 'LEFT',
                        (r(-math.pi/2), r(-math.pi/2), 0.0) : 'RIGHT'}

    return orientation_dict.get(tuple(map(r, view_rot)), 'USER')


class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"

    def execute(self, context):
        print("\n".join(main(context)))
        return {'FINISHED'}


def register():
    bpy.utils.register_class(SimpleOperator)


def unregister():
    bpy.utils.unregister_class(SimpleOperator)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.simple_operator()

Note: does only take the right-upper view in quadview mode into account.

$\endgroup$
1
$\begingroup$

It doesn't look like there's a clean way to do it.

Here's an excerpt of the painting code for the 3D viewport:

// view3d_draw.c:803
// in method: view3d_get_name
switch (rv3d->view) {
    case RV3D_VIEW_FRONT:
        if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho");
        else name = IFACE_("Front Persp");
        break;
    case RV3D_VIEW_BACK:
        if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho");
        else name = IFACE_("Back Persp");
        break;
    // etc ...
}
return name;

As you can see, it's simply checking these manually and looking them up (the IFACE_ is for localization). The string is never stored in a value anywhere.

You could perform a similar check in Python using the view_rotation property. See this answer for a starting point.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .