当前位置:   article > 正文

instantDrag for Maya脚本 (移动模型时沿目标模型移动)_maya怎么沿着边移动

maya怎么沿着边移动

​​

只需单击 Maya 中的命令按钮一次,即可在移动模型时沿目标模型移动

​InstantDrag allow user to simply click and drag mesh on another surface.
 

It can work in any situation. no mesh pre-select is required, once the tool is activated, just simply click and drag on any mesh which is on top of another surface.

hotKey for quick adjustment:

## hotKey :

## + Ctrl ----> rotate

## + Shift & Ctrl ----> scale

## + Shift ----> duplicate current mesh

## + Alt ----> snap to face center or vertex

## + Alt & Shilt ----> force center pivot and snap mesh to surface

let me know what you think, and happy to hear any suggestions to make the tool simple but more functional.

version Note
1.03 reMap hotkey so it's easier to use

1.02 add instant duplicate

1.01 fix bug when there is no mesh underneath at initial click

1.0 First version for public test

Maya运行Python:

##--------------------------------------------------------------------------

##

## ScriptName : instantDrag

## Contents : click and drag model on top of surface

## Author : Joe Wu

## URL : http://im3djoe.com

## Since : 2022/01/

## Version : 1.0 First version for public test

## : 1.01 fix bug when there is no mesh underneath at initial click

## : 1.02 add instant duplicate

## : 1.03 reMap hotkey

## Install :

## copy and paste entire code to a pyhotn script editor

## run it.

## or

## drag entire code to shelf to make a button.

##--------------------------------------------------------------------------

## hotKey :

## + Ctrl ----> rotate

## + Shift & Ctrl ----> scale

## + Shift ----> duplicate current mesh

## + Alt ----> snap to face center or vertex

## + Alt & Shilt ----> force center pivot and snap mesh to surface

##

##--------------------------------------------------------------------------

import maya.cmds as mc

import maya.mel as mel

import maya.OpenMaya as om

import maya.OpenMayaUI as omui

from maya.OpenMaya import MGlobal

import math

from pymel.core.datatypes import Vector, Matrix, Point

import pymel.core as pm

import re

def instantDrag():

cleanList = ('instPicker','instRot')

for c in cleanList:

if mc.objExists(c):

mc.delete(c)

global ctx

ctx = 'Click2dTo3dCtx'

if mc.draggerContext(ctx, exists=True):

mc.deleteUI(ctx)

mc.draggerContext(ctx, pressCommand = instDragPick, rc = instDragClean, dragCommand = instDragMove, name=ctx, cursor='crossHair',undoMode='step')

mc.setToolTo(ctx)

def instDragPick():

global ctx

global currentRotRecord

global screenX,screenY

global checkScreenMeshList

global storeCameraPosition

global storePos2

global storeDir

global storeMeshNode

global storeWRotX

global storeWRotY

global storeWRotZ

global parentDir

global storeMeshNode

global targetMeshName

global instDul

instDul = 0

vpX, vpY, _ = mc.draggerContext(ctx, query=True, anchorPoint=True)

screenX = vpX

screenY = vpY

pos = om.MPoint()

dir = om.MVector()

hitpoint = om.MFloatPoint()

omui.M3dView().active3dView().viewToWorld(int(vpX), int(vpY), pos, dir)

pos2 = om.MFloatPoint(pos.x, pos.y, pos.z)

view = omui.M3dView.active3dView()

cam = om.MDagPath()

view.getCamera(cam)

camPath = cam.fullPathName()

cameraTrans = mc.listRelatives(camPath,type='transform',p=True)

storeCameraPosition = mc.xform(cameraTrans,q=1,ws=1,rp=1)

checkHit = 0

finalMesh = []

shortDistance = 10000000000

distanceBetween = 1000000000

hitFacePtr = om.MScriptUtil().asIntPtr()

hitFace = []

checkScreenMeshList = screenVisPoly()

for mesh in checkScreenMeshList:

selectionList = om.MSelectionList()

selectionList.add(mesh)

dagPath = om.MDagPath()

selectionList.getDagPath(0, dagPath)

fnMesh = om.MFnMesh(dagPath)

intersection = fnMesh.closestIntersection(

om.MFloatPoint(pos2),

om.MFloatVector(dir),

None,

None,

False,

om.MSpace.kWorld,

99999,

False,

None,

hitpoint,

None,

hitFacePtr,

None,

None,

None)

if intersection:

x = hitpoint.x

y = hitpoint.y

z = hitpoint.z

distanceBetween = math.sqrt( ((float(storeCameraPosition[0]) - x)**2) + ((float(storeCameraPosition[1]) - y)**2) + ((float(storeCameraPosition[2]) - z)**2))

if distanceBetween < shortDistance:

shortDistance = distanceBetween

finalMesh = mesh

#finalMesh = mc.ls(sl=1,fl=1,l=1)

if len(finalMesh) > 0:

storeMeshNode=mc.listRelatives(finalMesh,type='transform',p=True,f=True)

shapeNode = mc.listRelatives(storeMeshNode[0], fullPath=True,ad=True )

parentDir = '|'.join(storeMeshNode[0].split('|')[0:-1])

targetMeshName = storeMeshNode[0].split('|')[-1]

for s in shapeNode:

if s in checkScreenMeshList:

checkScreenMeshList.remove(s)

finalX = []

finalY = []

finalZ = []

hitFace = []

snapMesh = []

shortDistance = 10000000000

distanceBetween = 1000000000

for snap in checkScreenMeshList:

selectionList = om.MSelectionList()

selectionList.add(snap)

dagPath = om.MDagPath()

selectionList.getDagPath(0, dagPath)

fnMesh = om.MFnMesh(dagPath)

intersection = fnMesh.closestIntersection(

om.MFloatPoint(pos2),

om.MFloatVector(dir),

None,

None,

False,

om.MSpace.kWorld,

99999,

False,

None,

hitpoint,

None,

hitFacePtr,

None,

None,

None)

if intersection:

x = hitpoint.x

y = hitpoint.y

z = hitpoint.z

distanceBetween = math.sqrt( ((float(storeCameraPosition[0]) - x)**2) + ((float(storeCameraPosition[1]) - y)**2) + ((float(storeCameraPosition[2]) - z)**2))

if distanceBetween < shortDistance:

shortDistance = distanceBetween

snapMesh = snap

finalX = x

finalY = y

finalZ = z

hitFace = om.MScriptUtil(hitFacePtr).asInt()

if hitFace:

hitFaceName = (snapMesh + '.f[' + str(hitFace) +']')

rx, ry, rz = checkFaceAngle(hitFaceName)

mc.group(empty=1,n ='instPicker')

mc.duplicate('instPicker')

mc.rename('instRot')

mc.parent('instRot','instPicker')

mc.setAttr('instPicker.translateX', finalX)

mc.setAttr('instPicker.translateY', finalY)

mc.setAttr('instPicker.translateZ', finalZ)

mc.setAttr('instPicker.rotateX', rx)

mc.setAttr('instPicker.rotateY', ry)

mc.setAttr('instPicker.rotateZ', rz)

mc.parent(storeMeshNode[0],'instRot')

else:

mc.group(empty=1,n ='instPicker')

mc.duplicate('instPicker')

mc.rename('instRot')

mc.parent('instRot','instPicker')

mc.select('instPicker',storeMeshNode[0])

mc.matchTransform(pos=1,rot=1)

mc.parent(storeMeshNode[0],'instRot')

mc.select('instPicker|instRot|'+targetMeshName)

mc.refresh(cv=True,f=True)

def instDragClean():

global parentDir

global targetMeshName

global instDul

if mc.objExists('instPicker'):

if len(parentDir) == 0:

mc.select('instPicker|instRot|'+targetMeshName)

mc.parent(w=1)

else:

mc.parent(('|instPicker|instRot|'+targetMeshName),(parentDir))

cleanList = ('instPicker','instRot')

for c in cleanList:

if mc.objExists(c):

mc.delete(c)

instDul = 0

def instDragMove():

global storeMeshNode

if storeMeshNode:

if mc.objExists('instPicker'):

global ctx

global screenX,screenY

global storeCameraPosition

global checkScreenMeshList

global storeWRotX

global storeWRotY

global storeWRotZ

global parentDir

global targetMeshName

global instDul

modifiers = mc.getModifiers()

if (modifiers == 4):

#press Ctrl

vpX, vpY, _ = mc.draggerContext(ctx, query=True, dragPoint=True)

distanceCheck = vpX - screenX

screenX = vpX

currentRoteY = mc.getAttr('instRot.rotateY')

if distanceCheck > 0.1:

currentRoteY = currentRoteY + 1

elif distanceCheck < 0.1:

currentRoteY = currentRoteY - 1

mc.setAttr('instRot.rotateY',currentRoteY)

elif(modifiers == 5):

#press Shift

vpX, vpY, _ = mc.draggerContext(ctx, query=True, dragPoint=True)

distanceCheck = vpX - screenX

screenX = vpX

currentScale = mc.getAttr('instRot.scaleX')

if distanceCheck > 0.1:

currentScale = currentScale + 0.01

elif distanceCheck < 0.1:

currentScale = currentScale - 0.01

mc.setAttr('instRot.scaleX',currentScale)

mc.setAttr('instRot.scaleY',currentScale)

mc.setAttr('instRot.scaleZ',currentScale)

elif(modifiers == 9):

#press Alt + Shift

#force snap to surface

targetPivot = mc.xform(('|instPicker|instRot|'+targetMeshName),q=1, rp=1, ws=1)

sourcePivot = mc.xform(('instRot'),q=1, rp=1, ws=1)

if targetPivot != sourcePivot:

mc.xform(('|instPicker|instRot|'+targetMeshName),cpc=1)

mc.matchTransform(('|instPicker|instRot|'+targetMeshName),'instRot',pos=1)

elif(modifiers == 1):

#press Alt + Ctrl

if instDul == 0:

newD = mc.duplicate(('|instPicker|instRot|'+targetMeshName),rr=1)

if len(parentDir) == 0:

mc.select('instPicker|instRot|'+targetMeshName)

mc.parent(w=1)

else:

mc.parent(('|instPicker|instRot|'+targetMeshName),(parentDir))

targetMeshName = newD[0]

mc.select(targetMeshName)

instDul = 1

mc.refresh(cv=True,f=True)

else:

instDul = 0

vpX, vpY, _ = mc.draggerContext(ctx, query=True, dragPoint=True)

pos = om.MPoint()

dir = om.MVector()

hitpoint = om.MFloatPoint()

omui.M3dView().active3dView().viewToWorld(int(vpX), int(vpY), pos, dir)

pos2 = om.MFloatPoint(pos.x, pos.y, pos.z)

checkHit = 0

finalMesh = []

finalX = 0

finalY = 0

finalZ = 0

shortDistance = 10000000000

distanceBetween = 1000000000

hitFacePtr = om.MScriptUtil().asIntPtr()

hitFace = []

for mesh in checkScreenMeshList:

selectionList = om.MSelectionList()

selectionList.add(mesh)

dagPath = om.MDagPath()

selectionList.getDagPath(0, dagPath)

fnMesh = om.MFnMesh(dagPath)

intersection = fnMesh.closestIntersection(

om.MFloatPoint(pos2),

om.MFloatVector(dir),

None,

None,

False,

om.MSpace.kWorld,

99999,

False,

None,

hitpoint,

None,

hitFacePtr,

None,

None,

None)

if intersection:

x = hitpoint.x

y = hitpoint.y

z = hitpoint.z

distanceBetween = math.sqrt( ((float(storeCameraPosition[0]) - x)**2) + ((float(storeCameraPosition[1]) - y)**2) + ((float(storeCameraPosition[2]) - z)**2))

if distanceBetween < shortDistance:

shortDistance = distanceBetween

finalMesh = mesh

hitFace = om.MScriptUtil(hitFacePtr).asInt()

finalX = x

finalY = y

finalZ = z

hitFaceName = (finalMesh + '.f[' + str(hitFace) +']')

if (modifiers == 8):

cpX,cpY,cpZ = getPolyFaceCenter(hitFaceName)

checkFaceCenterDist = math.sqrt( ((cpX - finalX)**2) + ((cpY- finalY)**2) + ((cpZ - finalZ)**2))

cvX = 0

cvY = 0

cvZ = 0

shortDistanceCheck = 10000

checkCVDistance = 10000

cvList = (mc.polyInfo(hitFaceName , fv=True )[0]).split(':')[-1].split(' ')

cvList = [x for x in cvList if x.strip()]

mostCloseCVPoint = []

for v in cvList:

checkNumber = ''.join([n for n in v.split('|')[-1] if n.isdigit()])

if len(checkNumber) > 0:

cvPoint = (finalMesh + '.vtx[' + str(checkNumber) +']')

cvPosition = mc.pointPosition(cvPoint)

checkCVDistance = math.sqrt( ((float(cvPosition[0]) - finalX)**2) + ((float(cvPosition[1]) - finalY)**2) + ((float(cvPosition[2]) - finalZ)**2))

if checkCVDistance < shortDistanceCheck:

shortDistanceCheck = checkCVDistance

cvX = float(cvPosition[0])

cvY = float(cvPosition[1])

cvZ = float(cvPosition[2])

mostCloseCVPoint = cvPoint

if shortDistanceCheck < checkFaceCenterDist:

mc.setAttr('instPicker.translateX', cvX)

mc.setAttr('instPicker.translateY', cvY)

mc.setAttr('instPicker.translateZ', cvZ)

rx,ry,rz = avgVertexNormalAngle(mostCloseCVPoint)

mc.setAttr('instPicker.rotateX', rx)

mc.setAttr('instPicker.rotateY', ry)

mc.setAttr('instPicker.rotateZ', rz)

else:

mc.setAttr('instPicker.translateX', cpX)

mc.setAttr('instPicker.translateY', cpY)

mc.setAttr('instPicker.translateZ', cpZ)

rx, ry, rz = checkFaceAngle(hitFaceName)

mc.setAttr('instPicker.rotateX', rx)

mc.setAttr('instPicker.rotateY', ry)

mc.setAttr('instPicker.rotateZ', rz)

else:

mc.setAttr('instPicker.translateX', finalX)

mc.setAttr('instPicker.translateY', finalY)

mc.setAttr('instPicker.translateZ', finalZ)

rx, ry, rz = checkFaceAngle(hitFaceName)

mc.setAttr('instPicker.rotateX', rx)

mc.setAttr('instPicker.rotateY', ry)

mc.setAttr('instPicker.rotateZ', rz)

mc.refresh(cv=True,f=True)

def avgVertexNormalAngle(vertexName):

shapeNode = mc.listRelatives(vertexName, fullPath=True , parent=True )

transformNode = mc.listRelatives(shapeNode[0], fullPath=True , parent=True )

faceList = (mc.polyInfo(vertexName , vf=True )[0]).split(':')[-1].split(' ')

faceList = [x for x in faceList if x.strip()]

getMeAngle=[]

sumX = 0

sumY = 0

sumZ = 0

for f in faceList:

checkNumber = ''.join([n for n in f.split('|')[-1] if n.isdigit()])

if len(checkNumber) > 0:

rx, ry, rz = checkFaceAngle((transformNode[0] + '.f[' + str(checkNumber) +']'))

sumX = sumX + rx

sumY = sumY + ry

sumZ = sumZ + rz

avgX = sumX /len(faceList)

avgY = sumY /len(faceList)

avgZ = sumZ /len(faceList)

return avgX, avgY, avgZ

def getPolyFaceCenter(faceName):

meshFaceName = faceName.split('.')[0]

findVtx = mc.polyInfo(faceName, fv=1)

getNumber = []

checkNumber = ((findVtx[0].split(':')[1]).split('\n')[0]).split(' ')

for c in checkNumber:

findNumber = ''.join([n for n in c.split('|')[-1] if n.isdigit()])

if findNumber:

getNumber.append(findNumber)

centerX = 0

centerY = 0

centerZ = 0

for g in getNumber:

x,y,z = mc.pointPosition((meshFaceName + '.vtx['+g + ']'),w=1)

centerX = centerX + x

centerY = centerY + y

centerZ = centerZ + z

centerX = centerX/len(getNumber)

centerY = centerY/len(getNumber)

centerZ = centerZ/len(getNumber)

return centerX,centerY,centerZ

def screenVisPoly():

commonList= []

view = omui.M3dView.active3dView()

om.MGlobal.selectFromScreen(0, 0, view.portWidth(), view.portHeight(), om.MGlobal.kReplaceList)

objects = om.MSelectionList()

sel = om.MSelectionList()

om.MGlobal.getActiveSelectionList(objects)

om.MGlobal.setActiveSelectionList(sel, om.MGlobal.kReplaceList)

fromScreen = []

objects.getSelectionStrings(fromScreen)

shapesOnScreen = mc.listRelatives(fromScreen, shapes=True,f=True)

meshList = mc.ls(type='mesh',l=True)#only polygon

if len(meshList)>0 and shapesOnScreen is not None:

commonList = list(set(meshList) & set(shapesOnScreen))

return commonList

else:

commonList = []

return commonList

def checkFaceAngle(faceName):

shapeNode = mc.listRelatives(faceName, fullPath=True , parent=True )

transformNode = mc.listRelatives(shapeNode[0], fullPath=True , parent=True )

obj_matrix = Matrix(mc.xform(transformNode, query=True, worldSpace=True, matrix=True))

face_normals_text = mc.polyInfo(faceName, faceNormals=True)[0]

face_normals = [float(digit) for digit in re.findall(r'-?\d*\.\d*', face_normals_text)]

v = Vector(face_normals) * obj_matrix

upvector = om.MVector (0,1,0)

getHitNormal = v

quat = om.MQuaternion(upvector, getHitNormal)

quatAsEuler = om.MEulerRotation()

quatAsEuler = quat.asEulerRotation()

rx, ry, rz = math.degrees(quatAsEuler.x), math.degrees(quatAsEuler.y), math.degrees(quatAsEuler.z)

return rx, ry, rz

def avgVertexNormalAngle(vertexName):

shapeNode = mc.listRelatives(vertexName, fullPath=True , parent=True )

transformNode = mc.listRelatives(shapeNode[0], fullPath=True , parent=True )

faceList = (mc.polyInfo(vertexName , vf=True )[0]).split(':')[-1].split(' ')

faceList = [x for x in faceList if x.strip()]

getMeAngle=[]

sumX = 0

sumY = 0

sumZ = 0

for f in faceList:

checkNumber = ''.join([n for n in f.split('|')[-1] if n.isdigit()])

if len(checkNumber) > 0:

rx, ry, rz = checkFaceAngle((transformNode[0] + '.f[' + str(checkNumber) +']'))

sumX = sumX + rx

sumY = sumY + ry

sumZ = sumZ + rz

avgX = sumX /len(faceList)

avgY = sumY /len(faceList)

avgZ = sumZ /len(faceList)

return avgX, avgY, avgZ

instantDrag()​​​​

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号