Last active
January 11, 2024 10:50
-
-
Save SEVEZ/7c9251661a00afc667bc to your computer and use it in GitHub Desktop.
Switch between perspective and matching orthographic view. The latest version is v3. #Release
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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() |
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.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The fact the script is falling over so early in the code suggests to me the custom command cannot find the script?