Skip to content

Instantly share code, notes, and snippets.

@fredrikaverpil
Last active February 27, 2023 21:15
Show Gist options
  • Save fredrikaverpil/731e5d43c35d6372e19864243c6e0231 to your computer and use it in GitHub Desktop.
Save fredrikaverpil/731e5d43c35d6372e19864243c6e0231 to your computer and use it in GitHub Desktop.
On Maya click: 2d coordinates to 3d world coordinates
import maya.api.OpenMaya as om
import maya.api.OpenMayaUI as omui
import maya.cmds as cmds
# Maya Python API:
# http://help.autodesk.com/view/MAYAUL/2017/ENU/?guid=__py_ref_index_html
def onPress():
"""Take x,y from mouse click, convert into 3d world coordinates"""
vpX, vpY, _ = cmds.draggerContext(ctx, query=True, anchorPoint=True)
position = om.MPoint() # 3D point with double-precision coordinates
direction = om.MVector() # 3D vector with double-precision coordinates
# This takes vpX and vpY as input and outputs position and direction
# values for the active view.
# - M3dView: provides methods for working with 3D model views
# - active3dView(): Returns the active view in the form of a class
# - viewToWorld: Takes a point in port coordinates and
# returns a corresponding ray in world coordinates
omui.M3dView().active3dView().viewToWorld(
int(vpX),
int(vpY),
position, # world point
direction) # world vector
for mesh in cmds.ls(type='mesh'):
# Create a list which can hold MObjects, MPlugs, MDagPaths
selectionList = om.MSelectionList()
selectionList.add(mesh) # Add mesh to list
dagPath = selectionList.getDagPath(0) # Path to a DAG node
fnMesh = om.MFnMesh(dagPath) # Function set for operation on meshes
# Find the closest intersection with the mesh and of a ray (starting
# at raySource and travelling in rayDirection).
# The maxParam and testBothDirections flags can be used to control
# the radius of the search around the raySource point.
intersection = fnMesh.closestIntersection(
om.MFloatPoint(position), # raySource
om.MFloatVector(direction), # rayDirection
om.MSpace.kWorld, # space
99999, # maxParam
False) # testBothDirections
# Extract the different values from the intersection result
hitPoint, hitRayParam, hitFace, hitTriangle, \
hitBary1, hitBary2 = intersection
# Extract x, y, z world coordinates of the hitPoint result
x, y, z, _ = hitPoint
if (x, y, z) != (0.0, 0.0, 0.0):
print(x, y, z) # Print the world coordinates
# Name of dragger context
ctx = 'Click2dTo3dCtx'
# Delete dragger context if it already exists
if cmds.draggerContext(ctx, exists=True):
cmds.deleteUI(ctx)
# Create dragger context and set it to the active tool
cmds.draggerContext(ctx, pressCommand=onPress, name=ctx, cursor='crossHair')
cmds.setToolTo(ctx)
@cgside
Copy link

cgside commented Jun 9, 2022

Hey there. Thank you for this. I am having a problem with your code, with a simple scene with a few cubes I get the error:

Error: cannot unpack non-iterable NoneType object
Traceback (most recent call last):
File "", line 49, in onPress
TypeError: cannot unpack non-iterable NoneType object #

Do I need to update the code somehow? Thank you

@fredrikaverpil
Copy link
Author

@cgside hi there. It was a long time ago I wrote this script and I no longer have access to Maya, so I unfortunately cannot help you.

@DangoWang
Copy link

add these codes under line "# Extract the different values from the intersection result":
if not intersection:
continue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment