Move by custom space (pivot orientation)

I am working on a simple script that creates a widget with XYZ inputs the same way as there is “Input line menu of operation” with relative transform, but it works only in World/Object/Component space orientation.
I want the XYZ relative transform was according to Custom space orientation of pivot. Example:
Select a vertex > press D > change orientation as I need > run a simple script that moves the vertex by 5 units along the custom X pivot orientation, not the world X space.

I suppose the answer to this question could merit a Nobel Prize. :smiley:
Nothing on Google/Reddit, or in any documentation, not even AI can solve it. :smiley:

Not completely sure but I think when you change a pivot orientation you need to bake it after if you want that change to be permanent.

I have not tried it, but maybe an idea could be to:

  1. Select the desired transform/vertex.
  2. Change the pivot orientation (using “D”).
  3. Bake the pivot orientation (maya.cmds has a manipPivot command with a bakeOri flag - I guess it does the same as the Modify > Bake Pivot option).
  4. Use the user UI input to move the transform/vertex along the new pivot axis. I think you can use the Object (Component if it’s a vertex maybe) space, as the pivot orientation has been baked.

If you would like the pivot changes in step 2 to not be permanent you could try using the manipPivot command again to cache the original pivot orientation and restore it after step 4.

Hope it helps! :slight_smile:

Thanks for the reply, but that doesn’t work. As I understand it, Bake Pivot only sets the origin of the object to the world origin. I guess the only way is to query the custom pivot orientation for example, using MEL (manipPivot -o -53.016245 -8.746521 40.409131;), and then somehow calculate the direction relative to world space.

I haven’t worked much with pivots in Maya so not sure what you mean by this. In any case, I’ve seen the pivot rotation seems to be baked into the rotation channel of the transform and not the World Rotate Pivot attribute. Maybe adding those two would give you the new pivot orientation :thinking:

Another way to approach this could be to create a temporary object (e.g., locator). After the pivot change you would match the locator rotation to the new pivot orientation and perform all the user-driven operations on that locator. This way you can modify its transform in object mode and it should move along the desired axis. When done, just snap the translation of your transform/vertex to that locator and delete the locator.

I found how to get the local space translation and rotation of the current custom move axes:

from maya import cmds

tran = cmds.manipMoveContext("Move", query=True, translate=True)
rot = cmds.manipMoveContext("Move", query=True, orientAxes=True)

print("Tran", tran)
print("Rot", rot)

Using those values, you should be able to figure out what you need.
I’d probably use that info to build a matrix. Then it’d be easy to find the position relative to that matrix and convert it back into the object’s space.

Sorry I don’t have time to give you more than that. I enjoy doing this kind of thing.
Also, I don’t like that I have to hard-code the name “Move” into that, but it’s probably OK.

1 Like

One tech artist helped me find the solution. :slight_smile:

from maya import cmds

# Get existing translation values for the current axis mode
v = cmds.manipMoveContext('Move', query=True, translate=True)

# Translate one additional unit along tool's Y axis
v[1] += 1.0

# Apply new values
cmds.manipMoveContext('Move', edit=True, translate=(v[0], v[1], v[2]))```
1 Like

Nice! Much easier than what I came up with.

I know I said I didn’t have the time, but I couldn’t help myself :blush:

from maya.api import OpenMaya as om2
from maya import cmds

# Get the data
tran = cmds.manipMoveContext("Move", query=True, translate=True)
rot = cmds.manipMoveContext("Move", query=True, orientAxes=True)

# Use openMaya matrix stuff to build the matrix
rotMat = om2.MEulerRotation(rot[0], rot[1], rot[2]).asMatrix()
tranTMat = om2.MTransformationMatrix()
tranTMat.setTranslation(om2.MVector(tran), om2.MSpace.kWorld)
mat = tranTMat.asMatrix() * rotMat

# Build a locator exactly where the custom manip is
# Just for display purposes. This isn't really needed
loc = cmds.spaceLocator()
cmds.xform(loc, m=mat, ws=True)

This builds a worldspace matrix exactly where the custom manip context is.

2 Likes

And one more to snap the pivot of one object to a worldspace matrix including the orientation.

from maya.api import OpenMaya as om2
from maya import cmds

def snapPivot(obj, pivotTarget):
    tarMat = om2.MMatrix(cmds.xform(pivotTarget, q=1, matrix=1, worldSpace=1))
    objMat = om2.MMatrix(cmds.xform(obj, q=1, matrix=1, worldSpace=1))

    tar_rot = list(om2.MTransformationMatrix(tarMat).rotation())
    tar_tran = list(tarMat * objMat.inverse())[12:15]

    cmds.select(obj, replace=True)
    cmds.manipMoveContext("Move", orientAxes=tar_rot, e=True)
    cmds.xform(obj, pivots=tar_tran)
    cmds.manipMoveContext("Move", mode=6, e=True)
2 Likes