Last active
October 13, 2018 13:24
-
-
Save Onefabis/2916fe6cf4e0048b0ff08d748938dfd5 to your computer and use it in GitHub Desktop.
Inserts object inside mesh just in the middle of the of the intersection of the camera ray and all geo in the scene
This file contains hidden or 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
| ''' | |
| Instructions: | |
| To run the script just ise the code: | |
| ________________________________________________________________ | |
| import inMeshPlace | |
| inMeshPlace.start() | |
| ________________________________________________________________ | |
| This script works in 3 modes: | |
| 1. If you run the script without any mesh selected, it will insert object in the approximate point of the ray that intersect all visible meshes in the scene. | |
| 2. If you run the script with one/many selected meshes, it will insert object in the approximate point of the ray that intersect all selected meshes in the scene. | |
| 3. If you select components and run the script, it will consider in computations only that component, i.e. it will compute approximate point under cursor only that was already selected. | |
| Nota bene: | |
| If you've clicked in the mesh and changed your mind about exact position, you can slide cursor before LMB release | |
| ''' | |
| import maya.api.OpenMaya as om2 | |
| import maya.OpenMayaUI as omui | |
| import maya.api.OpenMayaUI as omui2 | |
| import maya.cmds as mc | |
| from functools import partial | |
| try: | |
| from PySide import QtGui, QtCore | |
| import shiboken as shiboken | |
| from shiboken import wrapInstance | |
| except ImportError: | |
| from PySide2 import QtGui, QtCore | |
| import PySide2.QtWidgets as QtWidgets | |
| import shiboken2 as shiboken | |
| from shiboken2 import wrapInstance | |
| class InMeshPlace( object ): | |
| def __init__( self ): | |
| self.obj = 'joint' | |
| def UI( self ): | |
| winName = 'InMeshPlace' | |
| if mc.window( winName, ex=1 ): | |
| mc.deleteUI( winName ) | |
| mainWin = mc.window( winName, s=1, mxb=0, mnb=0 ) | |
| mainLayout = mc.formLayout( p=mainWin ) | |
| objects = [ 'joint', 'spaceLocator', 'group', 'circle', 'polyCube' ] | |
| self.inplaceTF = mc.textField( cc=partial(self.insetText, 0 ), p=mainLayout ) | |
| mc.popupMenu() | |
| for o in xrange( len(objects) ): | |
| exec( 'self.menuItem%i = mc.menuItem( l="%s", c=partial(self.insetText,"%s") ) ' % ( o, objects[o], objects[o] ) ) in globals(), locals() | |
| self.inplaceBN = mc.button( l='Place', h=30, c=lambda *x: self.startContext(1) ) | |
| if mc.optionVar( ex='inmeshplace' ): | |
| txt = mc.optionVar( q='inmeshplace' ) | |
| mc.textField( self.inplaceTF, e=1, tx=txt ) | |
| mainWindow = shiboken.wrapInstance( long( omui.MQtUtil.findControl(mainWin) ), QtWidgets.QWidget ) | |
| mainWindow.setStyleSheet( 'QWidget {background-color:#3a404e;}' ) | |
| widgets = mainWindow.findChildren(QtWidgets.QWidget) | |
| for w in widgets: | |
| wtType = w.metaObject().className() | |
| if wtType == 'QmayaField': | |
| w.setStyleSheet( 'QmayaField {background-color:#282e35; border: 1px solid #1e2328; border-radius: 3px; color: #9dbfd5 }' ) | |
| elif wtType == 'QPushButton': | |
| w.setStyleSheet( 'QPushButton {background-color:#495572; border: 1px solid #4a6288; border-radius: 3px; color: #aac6dc }' ) | |
| mc.formLayout( mainLayout, e=1, af=( self.inplaceTF, "top", 15 ) ) | |
| mc.formLayout( mainLayout, e=1, af=( self.inplaceTF, "left", 15 ) ) | |
| mc.formLayout( mainLayout, e=1, af=( self.inplaceTF, "right", 15 ) ) | |
| mc.formLayout( mainLayout, e=1, ac=( self.inplaceBN, "top", 10, self.inplaceTF ) ) | |
| mc.formLayout( mainLayout, e=1, af=( self.inplaceBN, "left", 15 ) ) | |
| mc.formLayout( mainLayout, e=1, af=( self.inplaceBN, "right", 15 ) ) | |
| mc.showWindow(mainWin) | |
| mc.window( winName, e=1, wh=( 150, 90 ) ) | |
| def insetText( self, name, part): | |
| if name: | |
| mc.textField( self.inplaceTF, e=1, tx=name ) | |
| else: | |
| name = mc.textField( self.inplaceTF, q=1, tx=1 ) | |
| mc.optionVar( sv=( 'inmeshplace', name ) ) | |
| def startContext( self, mode=0 ): | |
| self.ctx = 'mContext' | |
| if mode == 1: | |
| self.obj = mc.textField( self.inplaceTF, q=1, tx=1 ) | |
| if mc.draggerContext(self.ctx, exists=1): | |
| mc.deleteUI(self.ctx) | |
| mc.draggerContext(self.ctx, releaseCommand=self.onRelease, name=self.ctx, cursor='crossHair') | |
| mc.setToolTo(self.ctx) | |
| self.pId = None | |
| self.allMeshTransform = mc.ls( sl=1, v=1 ) | |
| if not self.allMeshTransform: | |
| self.allMesh = mc.ls( type='mesh', v=1 ) | |
| elif self.allMeshTransform: | |
| vertextCheck = mc.filterExpand( self.allMeshTransform[0], sm=31 ) | |
| edgeCheck = mc.filterExpand( self.allMeshTransform[0], sm=32 ) | |
| faceCheck = mc.filterExpand( self.allMeshTransform[0], sm=34 ) | |
| if vertextCheck or edgeCheck or faceCheck: | |
| self.allMesh = [ mc.listRelatives( x, p=1, typ='mesh' )[0] for x in self.allMeshTransform if mc.listRelatives( x, p=1, typ='mesh' ) ] | |
| borderComp = mc.polyListComponentConversion( self.allMeshTransform, tf=1, border=1 ) | |
| allComp = mc.polyListComponentConversion( self.allMeshTransform, tf=1 ) | |
| if self.allMeshTransform: | |
| if vertextCheck: | |
| self.pId = [ int( x[x.find("[") + 1:x.find("]")] ) for x in mc.ls( allComp, fl=1 ) if x not in mc.ls( borderComp, fl=1 ) ] | |
| else: | |
| self.pId = [ int( x[x.find("[") + 1:x.find("]")] ) for x in mc.ls( allComp, fl=1 ) ] | |
| else: | |
| return | |
| else: | |
| self.allMesh = [ mc.listRelatives( x, s=1, typ='mesh' )[0] for x in self.allMeshTransform if mc.listRelatives( x, s=1, typ='mesh' ) ] | |
| def onRelease( self ): | |
| allVectors = {} | |
| pos = om2.MPoint() | |
| dir = om2.MVector() | |
| vp = mc.draggerContext( self.ctx, q=1, dp=1 ) | |
| omui2.M3dView().active3dView().viewToWorld(int(vp[0]), int(vp[1]), pos, dir) | |
| for mesh in self.allMesh: | |
| selectionList = om2.MSelectionList() | |
| selectionList.add(mesh) | |
| dagPath = selectionList.getDagPath(0) | |
| fnMesh = om2.MFnMesh(dagPath) | |
| if self.pId: | |
| intersection = fnMesh.allIntersections(om2.MFloatPoint(pos), om2.MFloatVector(dir), om2.MSpace.kWorld, 99999, 0, faceIds=self.pId ) | |
| else: | |
| intersection = fnMesh.allIntersections(om2.MFloatPoint(pos), om2.MFloatVector(dir), om2.MSpace.kWorld, 99999, 0 ) | |
| for i in intersection[0]: | |
| allVectors[ ( om2.MVector( pos ) - om2.MVector( i ) ).length() ] = om2.MVector( i ) | |
| if allVectors: | |
| mc.select( cl=1 ) | |
| maxLength = max( allVectors, key=float ) | |
| minLength = min( allVectors, key=float ) | |
| fVec = allVectors[ maxLength ] | |
| sVec = allVectors[ minLength ] | |
| point = [ (x + y) / 2 for x, y in zip( fVec, sVec ) ] | |
| if self.obj == 'group': | |
| newObj = eval( 'mc.' + self.obj + '(em=1)' ) | |
| mc.setAttr( newObj + '.displayHandle', 1 ) | |
| else: | |
| newObj = eval( 'mc.' + self.obj + '()' ) | |
| mc.xform( newObj, ws=1, t=point ) | |
| if self.allMeshTransform: | |
| mc.select( cl=1 ) | |
| mc.select( self.allMeshTransform, r=1 ) | |
| else: | |
| mc.select( cl=1 ) | |
| def start(): | |
| InMeshPlace().UI() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment