-
-
Save SEVEZ/7c9251661a00afc667bc to your computer and use it in GitHub Desktop.
# Latest version, uses Tumble Pivot Point viewport | |
# feature, and proprietary algorithm, works in all recent | |
# versions of Maya, Python 2.7 / 3+. Gives more predictable | |
# and stable results. | |
# Pavel Sevets 2022 | |
import maya.cmds as mc | |
import maya.api.OpenMaya as om | |
from math import pi | |
def PS_perspOrthoToggle(): | |
if mc.contextInfo( 'tumbleContext', ex=1, ): | |
mc.tumbleCtx( 'tumbleContext', e=1, ot=1, asp=1, lt=0 ) | |
panel = mc.getPanel( wf=1 ) | |
if 'modelPanel' not in panel: return 1 | |
cam = mc.modelPanel( panel, q=1, cam=1 ) | |
if mc.objectType( cam, i='camera' ): | |
cam = mc.listRelatives( cam, p=1 )[0] | |
if not mc.camera( cam, q=1, o=1 ): | |
# store camera's FOV in custom attribute | |
if not mc.attributeQuery( 'p2oFOV', node=cam, ex=1 ): | |
mc.addAttr( cam, ln='p2oFOV', at='float', dv=0, h=1 ) | |
mc.setAttr( cam + '.p2oFOV', mc.camera( cam, q=1, hfv=1 ) ) | |
# camera's transformation matrix | |
M = om.MMatrix( mc.xform( cam, q=1, ws=1, m=1 ) ) | |
M = om.MTransformationMatrix( M ) | |
# quantize camera rotation to 90 degrees | |
oro = mc.xform( cam, q=1, ws=1, ro=1 ) | |
cro = [ round( r / 90.0 ) * pi / 2.0 for r in oro ] | |
oro = [ r * pi / 180.0 for r in oro ] | |
# calculating local space quaternion | |
# to correct camera's orientation | |
q1 = om.MEulerRotation( oro ).asMatrix() | |
q1 = om.MTransformationMatrix( q1 ).rotation(1) | |
q2 = om.MEulerRotation( cro ).asMatrix() | |
q2 = om.MTransformationMatrix( q2 ).rotation(1) | |
q = q2 * q1.inverse() | |
# rotate matrix with quaternion | |
M.rotateBy( q, om.MSpace.kObject ) | |
# get camera's tumble pivot and rotate pivot | |
tp = om.MVector( mc.camera( cam, q=1, wci=1 ) ) | |
tr = om.MVector( mc.xform( cam, q=1, ws=1, rp=1 ) ) | |
# recalc tumble pivot position | |
# in camera's local space | |
tp = M.asMatrix() * ( tp - tr ) | |
# rotate camera around it's tumble pivot | |
tp -= q.inverse().asMatrix() * tp | |
# translate camera to the new position | |
M.translateBy( tp, om.MSpace.kObject ) | |
# apply modified transform via matrix | |
mc.xform( cam, ws=1, m=M.asMatrix() ) | |
mc.viewPlace( cam, up=mc.camera( cam, q=1, wup=1 ), o=1 ) | |
# make manip aligned to screen axes | |
# comment two lines below to keep manip intact | |
rot = mc.xform( cam, q=1, ro=1, ws=1, a=1 ) | |
mc.manipPivot( o=rot ) | |
else: | |
ow = mc.camera( cam, q=1, ow=1 ) | |
coi = mc.camera( cam, q=1, coi=1 ) | |
M = om.MMatrix( mc.xform( cam, q=1, ws=1, m=1 ) ) | |
M = om.MTransformationMatrix( M ).asRotateMatrix() | |
v = M.inverse() * om.MVector( 0.0, 0.0, -1.0 ) | |
tp = v * ( coi - ow ) | |
# correct camera's roll if | |
# it's upside down or tilted | |
wup = om.MVector( mc.camera( cam, q=1, wup=1 ) ) | |
# uncomment below to turn off roll correction | |
#''' | |
M = om.MMatrix( mc.xform( cam, q=1, ws=1, m=1 ) ) | |
M = om.MTransformationMatrix( M ).asRotateMatrix() | |
v = M.inverse() * om.MVector( 0.0, 0.0, -1.0 ) | |
N = v ^ om.MVector( 0.0, 1.0, 0.0 ) | |
if N.length() >= 1E-5: | |
K = - ( N * wup ) / ( N * N ) | |
P = ( wup + K * N ).normal() | |
if P * om.MVector( 0.0, 1.0, 0.0 ) < 0.0: | |
P *= -1.0 | |
wup = P | |
# uncomment below to turn off roll correction | |
#''' | |
mc.xform( cam, ws=1, r=1, t=tp ) | |
mc.camera( cam, e=1, coi=ow ) | |
mc.viewPlace( cam, up=wup, p=1 ) | |
if mc.attributeQuery( 'p2oFOV', node=cam, ex=1 ): | |
mc.viewPlace( cam, fov=mc.getAttr( cam + '.p2oFOV' ) ) | |
return 0 | |
# PS_perspOrthoToggle() |
# Old Pymel based version | |
# Based on scripts by James Drew, Davide Alidosi from | |
# http://www.creativecrash.com/maya/script/persptoortho | |
# and Deniseich from | |
# http://www.creativecrash.com/maya/script/full-130-scripts-for-modeling-uv-video-tutorials-for-each | |
import maya.cmds as mc | |
import pymel.core.datatypes as dt | |
global gP2Ofov | |
def PS_perspOrthoToggle (): | |
#this gets the current active camera | |
cam = mc.modelPanel( mc.getPanel( wf=1 ), q=1, cam=1 ) | |
# cam = mc.modelPanel( 'modelPanel4', q=1, cam=1 ) | |
#if current camera is in orthographic mode return to perspective mode | |
if mc.camera( cam, q=1, o=1 ): | |
gP2Oow = mc.camera( cam, q=1, ow=1 ) | |
gP2Ocoi = mc.camera( cam, q=1, coi=1 ) | |
v = dt.TransformationMatrix( mc.xform( cam, q=1, ws=1, m=1 ) ).asRotateMatrix().inverse() * dt.Vector(0,0,-1) | |
tp = v * ( gP2Ocoi - gP2Oow ) | |
mc.xform( cam, ws=1, r=1, t=tp ) | |
mc.camera( cam, e=1, coi=gP2Oow ) | |
mc.camera( cam, e=1, o=0 ) | |
global gP2Ofov | |
if gP2Ofov: mc.camera( cam, e=1, hfv=gP2Ofov ) | |
else: | |
#stores camera attributes for returning to persp | |
gP2Otr = mc.xform( cam, q=1, ws=1, t=1 ) | |
gP2Oro = mc.xform( cam, q=1, ws=1, ro=1 ) | |
gP2Ocoi = mc.camera( cam, q=1, coi=1 ) | |
global gP2Ofov | |
gP2Ofov = mc.camera( cam, q=1, hfv=1 ) | |
mc.camera( cam, e=1, o=1 ) | |
mc.camera( cam, e=1, ow=gP2Ocoi ) | |
v = dt.TransformationMatrix( mc.xform( cam, q=1, ws=1, m=1 ) ).asRotateMatrix().inverse() * dt.Vector(0,0,-1) | |
#quantize camera rotation to 90 degrees | |
cro = [ round( ri / 90 ) * 90 for ri in gP2Oro ] | |
mc.xform( cam, ws=1, ro=cro ) | |
# match camera position to objects on screen | |
cp = dt.Vector( gP2Otr ) | |
tp = cp + v * gP2Ocoi | |
def _c( a, b ): return 1 if a > b else -1 | |
np = tp + gP2Ocoi * dt.Vector( _c( cp.x, tp.x ), _c( cp.y, tp.y ), _c( cp.z, tp.z ) ) | |
av = abs( v ) | |
n = av.index( max( av ) )[0] | |
tp[n] = np[n] | |
mc.xform( cam, ws=1, a=1, t=tp ) | |
#PS_perspOrthoToggle() |
# This version works with Maya API 2.0 and has no delay at start | |
# Based on scripts by James Drew, Davide Alidosi from | |
# http://www.creativecrash.com/maya/script/persptoortho | |
# and Deniseich from | |
# http://www.creativecrash.com/maya/script/full-130-scripts-for-modeling-uv-video-tutorials-for-each | |
import maya.cmds as mc | |
import maya.api.OpenMaya as om | |
global gP2Ofov | |
gP2Ofov = None | |
def PS_perspOrthoToggle (): | |
#this gets the current active camera | |
cam = mc.modelPanel( mc.getPanel( wf=1 ), q=1, cam=1 ) | |
# cam = mc.modelPanel( 'modelPanel4', q=1, cam=1 ) | |
#if current camera is in orthographic mode return to perspective mode | |
if mc.camera( cam, q=1, o=1 ): | |
gP2Oow = mc.camera( cam, q=1, ow=1 ) | |
gP2Ocoi = mc.camera( cam, q=1, coi=1 ) | |
M = om.MMatrix( mc.xform( cam, q=1, ws=1, m=1 ) ) | |
v = om.MTransformationMatrix( M ).asRotateMatrix().inverse() * om.MVector( 0.0, 0.0, -1.0 ) | |
tp = v * ( gP2Ocoi - gP2Oow ) | |
mc.xform( cam, ws=1, r=1, t=[ tp.x, tp.y, tp.z ] ) | |
mc.camera( cam, e=1, coi=gP2Oow ) | |
mc.camera( cam, e=1, o=0 ) | |
global gP2Ofov | |
if gP2Ofov: mc.camera( cam, e=1, hfv=gP2Ofov ) | |
else: | |
#stores camera attributes for returning to persp | |
gP2Otr = mc.xform( cam, q=1, ws=1, t=1 ) | |
gP2Oro = mc.xform( cam, q=1, ws=1, ro=1 ) | |
gP2Ocoi = mc.camera( cam, q=1, coi=1 ) | |
global gP2Ofov | |
gP2Ofov = mc.camera( cam, q=1, hfv=1 ) | |
mc.camera( cam, e=1, o=1 ) | |
mc.camera( cam, e=1, ow=gP2Ocoi ) | |
M = om.MMatrix( mc.xform( cam, q=1, ws=1, m=1 ) ) | |
v = om.MTransformationMatrix( M ).asRotateMatrix().inverse() * om.MVector( 0.0, 0.0, -1.0 ) | |
#quantize camera rotation to 90 degrees | |
cro = [ round( ri / 90 ) * 90 for ri in gP2Oro ] | |
mc.xform( cam, ws=1, ro=cro ) | |
# match camera position to objects on screen | |
cp = om.MVector( gP2Otr[0], gP2Otr[1], gP2Otr[2] ) | |
tp = cp + v * gP2Ocoi | |
def _c( a, b ): return 1 if a > b else -1 | |
np = tp + om.MVector( _c( cp.x, tp.x ), _c( cp.y, tp.y ), _c( cp.z, tp.z ) ) * gP2Ocoi | |
av = [ abs( v.x ), abs( v.y ), abs( v.z ) ] | |
m = max( av ) | |
if m == av[0]: | |
tp.x = np.x | |
elif m == av[1]: | |
tp.y = np.y | |
else: | |
tp.z = np.z | |
mc.xform( cam, ws=1, a=1, t=[ tp.x, tp.y, tp.z ] ) | |
#PS_perspOrthoToggle() |
Hello guys, and apologies for late response. Uploaded an updated version, works in all recent versions of Maya, and Python 2.7 / 3+. Download v3 and use the same way as before. This version relies on Tumble Pivot point feature and uses a proprietary algorithm now. Proven to give a more predictable and stable result. Cheers
P.S. If you prefer to have your current manipulator axes intact when switching, comment out lines 72 and 73 by putting # in the beginning of the commands.
Thank you!! :)
Sadly, I have the same "# Error: name 'gP2Ofov' is used prior to global declaration" as before...
Hello guys, and apologies for late response. Uploaded an updated version, works in all recent versions of Maya, and Python 2.7 / 3+. Download v3 and use the same way as before. This version relies on Tumble Pivot point feature and uses a proprietary algorithm now. Proven to give a more predictable and stable result. Cheers
P.S. If you prefer to have your current manipulator axes intact when switching, comment out lines 72 and 73 by putting # in the beginning of the commands.
Thank You :)
Thank you!! :)
Sadly, I have the same "# Error: name 'gP2Ofov' is used prior to global declaration" as before...
Which maya version you're using. It works fine for me, tested on 2018 and 2020.
Download v3, not v2. GitHub doesn’t let me reorder the files, alas.
Download v3, not v2. GitHub doesn’t let me reorder the files, so v3 is in the bottom.
Ah, right!! I was using v2. :) Thanks. It works now!
Hello guys, and apologies for late response. Uploaded an updated version, works in all recent versions of Maya, and Python 2.7 / 3+. Download v3 and use the same way as before. This version relies on Tumble Pivot point feature and uses a proprietary algorithm now. Proven to give a more predictable and stable result. Cheers
P.S. If you prefer to have your current manipulator axes intact when switching, comment out lines 72 and 73 by putting # in the beginning of the commands.
Thank you very much. Everything works. Great job :)
Thank you!!!!!!!!!! for all your efforts, everything works perfectly!!!!!!!
v3 has been updated - there was a small problem with maintaining the scale after zooming an ortho view and then switching from ortho to persp.
Hello,
Thanks for maintaining this script!
I'd like to have this functionality as I recently got into blender but now find myself back in maya for a project. I miss this a lot.
I have downloaded v3 and copied it into my documents maya version (2020) scripts folder.
I am unsure what I do with the python code but figured it might be a runtime command which I add via the hotkey editor? This way I can assign a hotkey to the command?
I've set the Tumble Tool settings advised but I get the following code:
# Error: line 1: ImportError: file <maya console> line 1: No module named PS_perspOrthoToggle #
Anyway, it's not working and I'm not sure if I've set it up correctly so asking for your help.
Thanks in advance.
Error: line 1: ImportError: file line 1: No module named PS_perspOrthoToggle
The fact the script is falling over so early in the code suggests to me the custom command cannot find the script?
Hey,
Thanks for getting back to me so quickly. Much appreciated.
This is what I have so far, I figured I was on the right track. Can you see anything wrong with how I have it setup?
change script name from PS_perspOrthoToggl_v3.py to PS_perspOrthoToggl.py
Ahhhh I have to rename the script file it self !
Nice. Works well now.
For the record the downloaded file is named
PS_perspOrthoToggl_v3.py
I had to rename it to
PS_perspOrthoToggle.py
Confusion over.
Got it. Thanks both.
Error: name 'gP2Ofov' is used prior to global declaration