819 lines
36 KiB
Python
819 lines
36 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import maya.cmds as cmds
|
|
import math
|
|
import re
|
|
import maya.mel as mel
|
|
import maya.OpenMaya as OpenMaya
|
|
|
|
def run():
|
|
cmd = 'source dagMenuProc;'
|
|
mel.eval(cmd)
|
|
global insetDataPP
|
|
global insetMesh
|
|
global insetFace
|
|
global insetDataEdgeLoopList
|
|
global insetMeshVolume
|
|
global insetInnerEdges
|
|
global updatedNewSelEdge
|
|
updatedNewSelEdge = []
|
|
insetInnerEdges = []
|
|
insetDataEdgeLoopList = []
|
|
insetDataPP = []
|
|
insetMesh = ''
|
|
insetFace = ''
|
|
insetMeshVolume = 0
|
|
if cmds.window('RoundInsetUI', exists = True):
|
|
cmds.deleteUI('RoundInsetUI')
|
|
RoundInsetUI = cmds.window('RoundInsetUI', title='Round Inset',w = 240, s = 1 ,mxb = False, mnb = False)
|
|
cmds.columnLayout(adj=1)
|
|
cmds.text(l='')
|
|
cmds.rowColumnLayout(nc=3, cw=[(1, 300), (2, 20),(3, 5),(4, 90),(5, 10)] )
|
|
cmds.columnLayout(adj=1)
|
|
cmds.rowColumnLayout(nc=2, cw=[(1, 270), (2, 20)] )
|
|
cmds.floatSliderGrp('rInsetV', en = 0, cw3=[60,40,0], label='Offset ', field=True,v=0.01, min= -1, max= 1, step=0.001)
|
|
cmds.button('rInsetVMax',l='+', c=lambda *args: slipderMax("rInsetV"), en = 1,bgc=[0.28,0.28,0.28])
|
|
cmds.floatSliderGrp('rBevelRound', en = 0, cw3=[60,40,0], label='Round ', field=True, v=0 , min=-1, max= 1 ,step=0.001)
|
|
cmds.button('rBevelRoundMax',l='+', c=lambda *args: slipderMax("rBevelRound"), en = 1,bgc=[0.28,0.28,0.28])
|
|
cmds.floatSliderGrp('rBevelAngle', en = 0, cw3=[60,40,0], cc=lambda *args: rBevelAngleUpdate(), dc=lambda *args: rBevelAngleUpdate(), label='Angle ', field=True, v=80, min=60, max= 90, fmn = 0, fmx = 180, step=0.1)
|
|
#cmds.button('rBevelLengthMax',l='+', c='slipderMax("rBevelLength")', en = 1,bgc=[0.28,0.28,0.28])
|
|
cmds.setParent( '..' )
|
|
cmds.setParent( '..' )
|
|
cmds.setParent( '..' )
|
|
cmds.text(l='')
|
|
cmds.rowColumnLayout(nc=6, cw=[(1, 10),(2, 60),(3, 60),(4, 60),(5, 60),(6, 60)] )
|
|
cmds.text(l='')
|
|
cmds.button('InsetButton', l='Inset', en=1, c=lambda *args: roundInsetRun(), bgc=[0.18,0.48,0.18])
|
|
cmds.button('reFineButton', l='Refine', en=0, c=lambda *args: reFineSwtich(), bgc=[0.18,0.18,0.18])
|
|
cmds.button('InnerCornerEvenButton',l='Even', en=0, c=lambda *args: evenInnerCorner(), bgc=[0.18,0.18,0.18])
|
|
cmds.button('InsetRemoveButton', l='Remove', en=0, c=lambda *args: roundInsetRemove(),bgc=[0.18,0.18,0.18])
|
|
cmds.button('InsetCleaneButton', l='Done', en=1, c=lambda *args: roundInsetClean(), bgc=[0.48,0.18,0.18])
|
|
cmds.setParent( '..' )
|
|
cmds.text(l='')
|
|
cmds.showWindow(RoundInsetUI)
|
|
|
|
|
|
def slipderMax(name):
|
|
sliderName = name
|
|
currentMaxV = cmds.floatSliderGrp(sliderName, q = 1, max=1)
|
|
currentMinV = cmds.floatSliderGrp(sliderName, q = 1, min=1)
|
|
cmds.floatSliderGrp(sliderName, e = 1, min = currentMinV*2, max= currentMaxV*2)
|
|
|
|
|
|
def roundInsetRemove():
|
|
global insetFace
|
|
global insetMesh
|
|
global insetDataEdgeLoopList
|
|
shape_node = cmds.listRelatives(insetMesh, shapes=True)
|
|
source_shape = shape_node[-1]
|
|
destination_shape = shape_node[0]
|
|
if insetFace:
|
|
history_nodes = cmds.listHistory(insetMesh)
|
|
delList = ["polyExtrudeFace1", "polyCrease1", "insetOffsetNod*"]
|
|
for d in delList:
|
|
if cmds.objExists(d):
|
|
cmds.delete(d)
|
|
cmds.select(insetFace)
|
|
cmds.floatSliderGrp('rInsetV', e=1, v=0.01, min=-1, max= 1,fmx = 10, step=0.001)
|
|
cmds.floatSliderGrp('rBevelAngle',e=1, en = 0)
|
|
cmds.floatSliderGrp('rBevelRound', e=1 ,en=0, v=0, min=-1, max= 1, step=0.001)
|
|
if cmds.objExists('insetDataEdgeLoopListKeep'):
|
|
cmds.delete('insetDataEdgeLoopListKeep')
|
|
if cmds.objExists('cornerDisp'):
|
|
cmds.setAttr('cornerDisp.creaseLevel', 0)
|
|
cmds.delete('cornerDisp')
|
|
if insetMesh:
|
|
cmds.select(insetMesh)
|
|
cmds.delete(all=1, e=1, ch=1)
|
|
cmd = 'doMenuComponentSelectionExt("' + insetMesh + '", "facet" , 0);'
|
|
mel.eval(cmd)
|
|
cmds.select(insetFace)
|
|
insetFace = ''
|
|
insetMesh = ''
|
|
insetDataEdgeLoopList = []
|
|
cmds.setToolTo('Move')
|
|
cmds.button('InsetButton', e=1, en=1, bgc=[0.18,0.48,0.18])
|
|
cmds.button('reFineButton',l='Refine', e=1, en=0, bgc=[0.18,0.18,0.18])
|
|
cmds.button('InnerCornerEvenButton', e=1, en=0, bgc=[0.18,0.18,0.18])
|
|
cmds.button('InsetRemoveButton', e=1, en=0, bgc=[0.18,0.18,0.18])
|
|
cmds.button('InsetCleaneButton', e=1, en=1, bgc=[0.48,0.18,0.18])
|
|
|
|
def roundInsetClean():
|
|
currentsel = cmds.ls(sl=1,fl=1)
|
|
if currentsel:
|
|
geoSel = currentsel[0].split('.')[0]
|
|
if geoSel:
|
|
cmds.delete(geoSel, ch=1)
|
|
global insetFace
|
|
global insetMesh
|
|
if cmds.objExists("insetOffsetNod*"):
|
|
listNode = cmds.ls("insetOffsetNod*")
|
|
for s in listNode:
|
|
getOldMesh = cmds.listConnections((s + '.outputGeometry'), scn=True )
|
|
try:
|
|
getOldShape = cmds.listConnections((getOldMesh[0] + '.outputGeometry'), scn=True )
|
|
cmds.delete(getOldShape, ch=1)
|
|
except:
|
|
cmds.delete(getOldMesh, ch=1)
|
|
|
|
cleanList = ('insetOffsetNod*','roundV','insetOffsetV','insetDataEdgeLoopListKeep','blendOffsetNode','tempLoopListKeep')
|
|
for c in cleanList:
|
|
if cmds.objExists(c):
|
|
cmds.delete(c)
|
|
|
|
cmds.floatSliderGrp('rInsetV', e=1, v=0.01, min=-1, max= 1,fmx = 10, step=0.001)
|
|
cmds.floatSliderGrp('rBevelAngle', e = 1, en = 0, cw3=[60,40,0], field=True, v=80, min=60, max= 90, fmn = 0, fmx = 180, step=0.1)
|
|
cmds.floatSliderGrp('rBevelRound', e=1 ,en=0, v=0, min=-1, max= 1, step=0.001)
|
|
if cmds.objExists('insetDataEdgeLoopListKeep'):
|
|
cmds.delete('insetDataEdgeLoopListKeep')
|
|
if cmds.objExists('cornerDisp'):
|
|
cmds.setAttr('cornerDisp.creaseLevel', 0)
|
|
cmds.delete('cornerDisp')
|
|
if insetFace:
|
|
cmds.select(insetFace)
|
|
cmd = 'doMenuComponentSelectionExt("' + insetMesh + '", "facet", 0);'
|
|
mel.eval(cmd)
|
|
cmds.select(insetFace)
|
|
insetFace = ''
|
|
insetMesh = ''
|
|
cmds.button('InsetButton', e=1, en=1, bgc=[0.18,0.48,0.18])
|
|
cmds.button('reFineButton', e=1, en=0, bgc=[0.18,0.18,0.18])
|
|
cmds.button('InnerCornerEvenButton',e=1, en=0, bgc=[0.18,0.18,0.18])
|
|
cmds.button('InsetRemoveButton', e=1, en=0, bgc=[0.18,0.18,0.18])
|
|
cmds.button('InsetCleaneButton', e=1, en=1, bgc=[0.48,0.18,0.18])
|
|
cmds.setToolTo('Move')
|
|
# clean storeBevel Attr
|
|
transformsNodeList = cmds.ls(dag =1,type='transform',l=1)
|
|
for l in transformsNodeList:
|
|
anyUserAttr = cmds.listAttr(l,userDefined=1)
|
|
if anyUserAttr:
|
|
for a in anyUserAttr:
|
|
if a == 'storeBevelV':
|
|
if cmds.attributeQuery(a, node = l, ex=True ):
|
|
cmds.setAttr((l + "." + a), l=0)
|
|
cmds.deleteAttr(l + "." + a)
|
|
|
|
def evenInnerCorner():
|
|
global recordInnerCornerList
|
|
cmds.select(recordInnerCornerList)
|
|
sortGrp = []
|
|
sortGrp = getEdgeRingGroup(recordInnerCornerList)
|
|
if len(sortGrp) > 0:
|
|
for g in sortGrp:
|
|
if cmds.objExists('tempEvenCurve'):
|
|
cmds.delete('tempEvenCurve')
|
|
listVtx = vtxLoopOrder(g)
|
|
cmds.select(g)
|
|
cmds.polyToCurve(form=2, degree=1, conformToSmoothMeshPreview=1)
|
|
cmds.rename('tempEvenCurve')
|
|
curveCVs =cmds.ls('tempEvenCurve.cv[*]',fl=1)
|
|
posCurve = cmds.xform(curveCVs[0], a=1,ws=1, q=1, t=1)
|
|
posEdge = cmds.xform(listVtx[0], a=1,ws=1, q=1, t=1)
|
|
if posCurve == posEdge:
|
|
pass
|
|
else:
|
|
listVtx = listVtx[::-1]
|
|
if len(curveCVs)>2:
|
|
cmds.rebuildCurve('tempEvenCurve',ch=1, rpo=1, rt=0, end=1, kr=0, kcp=0, kep=1, kt=0, s = 0 , d=1, tol=0)
|
|
if len(curveCVs)< 4:
|
|
cmds.delete( 'tempEvenCurve.cv[1]', 'tempEvenCurve.cv[3]')
|
|
curveCVs =cmds.ls('tempEvenCurve.cv[*]',fl=1)
|
|
posCurve = cmds.xform(curveCVs[0], a=1,ws=1, q=1, t=1)
|
|
posEdge = cmds.xform(listVtx[0], a=1,ws=1, q=1, t=1)
|
|
posEdge[0] = round(posEdge[0],3)
|
|
posEdge[1] = round(posEdge[1],3)
|
|
posEdge[2] = round(posEdge[2],3)
|
|
posCurve[0] = round(posCurve[0],3)
|
|
posCurve[1] = round(posCurve[1],3)
|
|
posCurve[2] = round(posCurve[2],3)
|
|
for i in range(len(curveCVs)):
|
|
pos = cmds.xform(curveCVs[i], a=1,ws=1, q=1, t=1)
|
|
cmds.xform(listVtx[i], a=1, ws=1, t = (pos[0],pos[1],pos[2]) )
|
|
cmds.delete('tempEvenCurve')
|
|
cmds.select('cornerDisp')
|
|
cmd = 'doMenuComponentSelectionExt("' + insetMesh + '", "edge", 0);'
|
|
mel.eval(cmd)
|
|
cmds.select(insetFace,add=1)
|
|
cmds.setToolTo('selectSuperContext')
|
|
|
|
|
|
|
|
|
|
def matchCorner(edgeLoop, getRoundV):
|
|
global insetFace
|
|
global insetInnerEdges
|
|
global insetDataEdgeLoopList
|
|
selLoopShort = edgeLoop
|
|
toCV = cmds.polyListComponentConversion(selLoopShort, tv=True)
|
|
toEdge =cmds.polyListComponentConversion(toCV, te=True)
|
|
toEdge = cmds.ls(toEdge,fl=1)
|
|
toFace = cmds.polyListComponentConversion(selLoopShort, tf=True)
|
|
toFace = cmds.ls(toFace,fl=1)
|
|
toFace = list(set(toFace)-set(insetFace))
|
|
toEdgeB = cmds.polyListComponentConversion(toFace, te=True)
|
|
toEdgeB = cmds.ls(toEdgeB,fl=1)
|
|
selLoopLong = list(set(toEdgeB)-set(toEdge))
|
|
totalLengthA = 0
|
|
for s in selLoopLong:
|
|
intSelCV = cmds.polyListComponentConversion(s, tv=True)
|
|
intSelCV = cmds.ls(intSelCV,fl=1)
|
|
distanceX = distanceBetween(intSelCV[0],intSelCV[1])
|
|
totalLengthA = totalLengthA + distanceX
|
|
totalLengthB = 0
|
|
for s in selLoopShort:
|
|
intSelCV = cmds.polyListComponentConversion(s, tv=True)
|
|
intSelCV = cmds.ls(intSelCV,fl=1)
|
|
distanceX = distanceBetween(intSelCV[0],intSelCV[1])
|
|
totalLengthB = totalLengthB + distanceX
|
|
scaleV = totalLengthA/totalLengthB*getRoundV
|
|
#cmds.select(toDO)
|
|
toDO = list(set(toEdge) - set(toEdgeB)-set(insetInnerEdges))
|
|
toDO = toDO + selLoopShort
|
|
toDO = list(set(toDO))
|
|
if len(insetDataEdgeLoopList) == len(toDO):
|
|
pass
|
|
else:
|
|
cmds.sets(selLoopLong,forceElement="cornerDisp")
|
|
pPoint,vList,cList = unBevelEdgeLoop(toDO)
|
|
for v in vList:
|
|
cmds.scale(scaleV,scaleV,scaleV, v, cs=1, r=1, p= (pPoint[0],pPoint[1],pPoint[2]))
|
|
|
|
def distanceBetween(p1,p2):
|
|
pA = cmds.pointPosition(p1, w =1)
|
|
pB = cmds.pointPosition(p2, w =1)
|
|
dist = math.sqrt( ((pA[0] - pB[0])**2) + ((pA[1] - pB[1])**2) + ((pA[2] - pB[2])**2) )
|
|
return dist
|
|
|
|
def getEdgeRingGroup(selEdges):
|
|
#selEdges = cmds.ls(sl=1,fl=1)
|
|
trans = selEdges[0].split(".")[0]
|
|
e2vInfos = cmds.polyInfo(selEdges, ev=True)
|
|
e2vDict = {}
|
|
fEdges = []
|
|
for info in e2vInfos:
|
|
evList = [ int(i) for i in re.findall('\\d+', info) ]
|
|
e2vDict.update(dict([(evList[0], evList[1:])]))
|
|
while True:
|
|
try:
|
|
startEdge, startVtxs = e2vDict.popitem()
|
|
except:
|
|
break
|
|
edgesGrp = [startEdge]
|
|
num = 0
|
|
for vtx in startVtxs:
|
|
curVtx = vtx
|
|
while True:
|
|
nextEdges = []
|
|
for k in e2vDict:
|
|
if curVtx in e2vDict[k]:
|
|
nextEdges.append(k)
|
|
if nextEdges:
|
|
if len(nextEdges) == 1:
|
|
if num == 0:
|
|
edgesGrp.append(nextEdges[0])
|
|
else:
|
|
edgesGrp.insert(0, nextEdges[0])
|
|
nextVtxs = e2vDict[nextEdges[0]]
|
|
curVtx = [ vtx for vtx in nextVtxs if vtx != curVtx ][0]
|
|
e2vDict.pop(nextEdges[0])
|
|
else:
|
|
break
|
|
else:
|
|
break
|
|
num += 1
|
|
fEdges.append(edgesGrp)
|
|
retEdges =[]
|
|
for f in fEdges:
|
|
collectList=[]
|
|
for x in f:
|
|
getCom= (trans +".e["+ str(x) +"]")
|
|
collectList.append(getCom)
|
|
retEdges.append(collectList)
|
|
return retEdges
|
|
|
|
|
|
def unBevelEdgeLoop(edgelist):
|
|
listVtx = vtxLoopOrder(edgelist)
|
|
checkA = angleBetweenThreeP(listVtx[1],listVtx[0],listVtx[-1])
|
|
angleA = math.degrees(checkA)
|
|
checkB = angleBetweenThreeP(listVtx[-2],listVtx[-1],listVtx[0])
|
|
angleB = math.degrees(checkB)
|
|
angleC = 180 - angleA -angleB
|
|
distanceC = distanceBetween(listVtx[0],listVtx[-1])
|
|
distanceA = distanceC / math.sin(math.radians(angleC)) * math.sin(math.radians(angleA))
|
|
distanceB = distanceC / math.sin(math.radians(angleC)) * math.sin(math.radians(angleB))
|
|
oldDistA = distanceBetween(listVtx[-2],listVtx[-1])
|
|
oldDistB = distanceBetween(listVtx[0],listVtx[1])
|
|
scalarB = distanceB / oldDistB
|
|
pA = cmds.pointPosition(listVtx[0], w =1)
|
|
pB = cmds.pointPosition(listVtx[1], w =1)
|
|
newP = [0,0,0]
|
|
newP[0] = ((pB[0]-pA[0])*scalarB) + pA[0]
|
|
newP[1] = ((pB[1]-pA[1])*scalarB) + pA[1]
|
|
newP[2] = ((pB[2]-pA[2])*scalarB) + pA[2]
|
|
listVtx = listVtx[1:-1]
|
|
storeDist = []
|
|
for l in listVtx:
|
|
sotreXYZ = [0,0,0]
|
|
p=cmds.xform(l,q=True,t=True,ws=True)
|
|
sotreXYZ[0] = (newP[0] -p[0])/100
|
|
sotreXYZ[1] = (newP[1] -p[1])/100
|
|
sotreXYZ[2] = (newP[2] -p[2])/100
|
|
storeDist.append(sotreXYZ)
|
|
return newP,listVtx,storeDist
|
|
|
|
def vtxLoopOrder(edgelist):
|
|
selEdges = edgelist
|
|
#selEdges = cmds.ls(sl=1, fl=1)
|
|
shapeNode = cmds.listRelatives(selEdges[0], fullPath=True, parent=True)
|
|
transformNode = cmds.listRelatives(shapeNode[0], fullPath=True, parent=True)
|
|
edgeNumberList = []
|
|
for a in selEdges:
|
|
checkNumber = a.split('.')[1].split('\n')[0].split(' ')
|
|
for c in checkNumber:
|
|
findNumber = ''.join([ n for n in c.split('|')[-1] if n.isdigit() ])
|
|
if findNumber:
|
|
edgeNumberList.append(findNumber)
|
|
getNumber = []
|
|
for s in selEdges:
|
|
evlist = cmds.polyInfo(s, ev=True)
|
|
checkNumber = evlist[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)
|
|
dup = set([ x for x in getNumber if getNumber.count(x) > 1 ])
|
|
getHeadTail = list(set(getNumber) - dup)
|
|
checkCircleState = 0
|
|
if not getHeadTail:
|
|
checkCircleState = 1
|
|
getHeadTail.append(getNumber[0])
|
|
vftOrder = []
|
|
vftOrder.append(getHeadTail[0])
|
|
count = 0
|
|
while len(dup) > 0 and count < 3000:
|
|
checkVtx = transformNode[0] + '.vtx[' + vftOrder[-1] + ']'
|
|
velist = cmds.polyInfo(checkVtx, ve=True)
|
|
getNumber = []
|
|
checkNumber = velist[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)
|
|
findNextEdge = []
|
|
for g in getNumber:
|
|
if g in edgeNumberList:
|
|
findNextEdge = g
|
|
edgeNumberList.remove(findNextEdge)
|
|
checkVtx = transformNode[0] + '.e[' + findNextEdge + ']'
|
|
findVtx = cmds.polyInfo(checkVtx, ev=True)
|
|
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)
|
|
gotNextVtx = []
|
|
for g in getNumber:
|
|
if g in dup:
|
|
gotNextVtx = g
|
|
dup.remove(gotNextVtx)
|
|
vftOrder.append(gotNextVtx)
|
|
count += 1
|
|
if checkCircleState == 0:
|
|
vftOrder.append(getHeadTail[1])
|
|
elif vftOrder[0] == vftOrder[1]:
|
|
vftOrder = vftOrder[1:]
|
|
elif vftOrder[0] == vftOrder[-1]:
|
|
vftOrder = vftOrder[0:-1]
|
|
finalList = []
|
|
for v in vftOrder:
|
|
finalList.append(transformNode[0] + '.vtx[' + v + ']')
|
|
return (finalList)
|
|
|
|
def angleBetweenThreeP(pA, pB, pC):
|
|
a = cmds.pointPosition(pA, w =1)
|
|
b = cmds.pointPosition(pB, w =1)
|
|
c = cmds.pointPosition(pC, w =1)
|
|
ba = [ aa-bb for aa,bb in zip(a,b) ]
|
|
bc = [ cc-bb for cc,bb in zip(c,b) ]
|
|
nba = math.sqrt ( sum ( (x**2.0 for x in ba) ) )
|
|
ba = [ x/nba for x in ba ]
|
|
nbc = math.sqrt ( sum ( (x**2.0 for x in bc) ) )
|
|
bc = [ x/nbc for x in bc ]
|
|
scalar = sum ( (aa*bb for aa,bb in zip(ba,bc)) )
|
|
angle = math.acos(scalar)
|
|
return angle
|
|
|
|
def getfaceArea(mesh,faceId):
|
|
if cmds.objectType(mesh) == 'transform':
|
|
mesh = cmds.listRelatives(mesh,s=True,ni=True,pa=True)[0]
|
|
selectionList = OpenMaya.MSelectionList()
|
|
OpenMaya.MGlobal.getSelectionListByName(mesh,selectionList)
|
|
mDagPath = OpenMaya.MDagPath()
|
|
selectionList.getDagPath(0,mDagPath)
|
|
meshFaceIt = OpenMaya.MItMeshPolygon(mDagPath)
|
|
if faceId != None:
|
|
meshFaceUtil = OpenMaya.MScriptUtil()
|
|
meshFacePtr = meshFaceUtil.asIntPtr()
|
|
meshFaceIt.setIndex(faceId,meshFacePtr)
|
|
faceArea = OpenMaya.MScriptUtil()
|
|
faceArea.createFromDouble(0.0)
|
|
faceAreaPtr = faceArea.asDoublePtr()
|
|
meshFaceIt.getArea(faceAreaPtr)
|
|
areaCheck = OpenMaya.MScriptUtil(faceAreaPtr).asDouble()
|
|
return areaCheck
|
|
|
|
def edgeLoopByAngle(selList):
|
|
global edgeLoopOverLengthLib
|
|
edgeLengthData = {}
|
|
listVtx = vtxLoopOrder(selList)
|
|
listVtx.append(listVtx[0])
|
|
listVtx.append(listVtx[1])
|
|
collectList = []
|
|
for r in range(len(listVtx)-2):
|
|
pA = cmds.pointPosition(listVtx[r], w=True)
|
|
pB = cmds.pointPosition(listVtx[r+1], w=True)
|
|
pC = cmds.pointPosition(listVtx[r+2], w=True)
|
|
direction_vectorA = [pA[i] - pB[i] for i in range(3)]
|
|
lengthA = sum(y ** 2 for y in direction_vectorA) ** 0.5
|
|
normalized_directionA = [y / lengthA for y in direction_vectorA]
|
|
direction_vectorB = [pB[i] - pC[i] for i in range(3)]
|
|
lengthB = sum(y ** 2 for y in direction_vectorB) ** 0.5
|
|
normalized_directionB = [y / lengthB for y in direction_vectorB]
|
|
dot_product = sum([normalized_directionA[z] * normalized_directionB[z] for z in range(3)])
|
|
#checkAngle = abs(abs(dot_product) - 1.0)
|
|
angle_degrees = math.degrees(math.acos(dot_product))
|
|
if angle_degrees > 10:
|
|
edgeFoundA = cmds.polyListComponentConversion(listVtx[r], listVtx[r+1],fv=True, te=True, internal=True)
|
|
distA = math.sqrt( ((pA[0] - pB[0])**2) + ((pA[1] - pB[1])**2) + ((pA[2] - pB[2])**2) )
|
|
edgeFoundB = cmds.polyListComponentConversion( listVtx[r+1],listVtx[r+2],fv=True, te=True, internal=True)
|
|
distB = math.sqrt( ((pB[0] - pC[0])**2) + ((pB[1] - pC[1])**2) + ((pB[2] - pC[2])**2) )
|
|
collectList = collectList + edgeFoundA + edgeFoundB
|
|
edgeLengthData[edgeFoundA[0]] = distA
|
|
edgeLengthData[edgeFoundB[0]] = distB
|
|
|
|
if collectList:
|
|
#avoid long edge
|
|
values = list(edgeLengthData.values())
|
|
# Calculate the threshold for the top 20% and bottom 20%
|
|
num_values = len(values)
|
|
top_threshold = sorted(values)[int(0.95 * num_values)]
|
|
bottom_threshold = sorted(values)[int(0.05 * num_values)]
|
|
# Filter out values outside the range
|
|
filtered_data = {key: value for key, value in edgeLengthData.items() if value >= bottom_threshold and value <= top_threshold}
|
|
filtered_values = list(filtered_data.values())
|
|
average_length = sum(filtered_values) / len(filtered_values)
|
|
edgeLoopOverLengthLib = 2 * average_length
|
|
overLength = [edge for edge, length in edgeLengthData.items() if length > edgeLoopOverLengthLib]
|
|
collectList = list(set(collectList) - set(overLength))
|
|
return collectList
|
|
|
|
def roundInsetRun():
|
|
currentsel = cmds.ls(sl=1,fl=1)
|
|
if currentsel:
|
|
geoSel = currentsel[0].split('.')[0]
|
|
if geoSel:
|
|
cmds.delete(geoSel, ch=1)
|
|
getRoundV = cmds.floatSliderGrp('rBevelRound', q=1, v=1)
|
|
if cmds.objExists("insetOffsetNod*"):
|
|
listNode = cmds.ls("insetOffsetNod*")
|
|
for s in listNode:
|
|
getOldMesh = cmds.listConnections((s + '.outputGeometry'), scn=True )
|
|
try:
|
|
getOldShape = cmds.listConnections((getOldMesh[0] + '.outputGeometry'), scn=True )
|
|
cmds.delete(getOldShape, ch=1)
|
|
except:
|
|
cmds.delete(getOldMesh, ch=1)
|
|
if cmds.objExists('insetOffsetNod*'):
|
|
cmds.delete('insetOffsetNod*')
|
|
if cmds.objExists('roundV'):
|
|
cmds.delete('roundV')
|
|
if cmds.objExists("insetOffsetV"):
|
|
cmds.delete('nsetOffsetV')
|
|
if cmds.objExists('insetDataEdgeLoopListKeep'):
|
|
cmds.delete('insetDataEdgeLoopListKeep')
|
|
if cmds.objExists('cornerDisp'):
|
|
cmds.setAttr("cornerDisp.creaseLevel", 0)
|
|
cmds.delete('cornerDisp*')
|
|
global insetDataPP
|
|
global insetMesh
|
|
global insetInnerEdges
|
|
global insetFace
|
|
global insetDataEdgeLoopList
|
|
global insetFaceArea
|
|
global newLoop
|
|
global recordInnerCornerList
|
|
global edgeLoopAngleLib
|
|
global edgeLoopOverLengthLib
|
|
global updatedNewSelEdge
|
|
edgeLoopOverLengthLib = []
|
|
recordInnerCornerList = []
|
|
newLoop = []
|
|
insetDataEdgeLoopList = []
|
|
insetDataPP = []
|
|
insetMesh = ''
|
|
insetFace = ''
|
|
insetInnerEdges = []
|
|
insetFaceArea = 0
|
|
selComponent = cmds.filterExpand(ex =1, sm =34)
|
|
if selComponent:
|
|
geo = cmds.ls(hl=1)
|
|
cmds.makeIdentity(geo[0], apply=1, t=0, r=0, s=1, n=0, pn=1)
|
|
insetMesh = geo[0]
|
|
faceID = selComponent[0].split('[')[-1].split(']')[0]
|
|
faceID = int(faceID)
|
|
insetFaceArea = getfaceArea(insetMesh,faceID)
|
|
edgeLoopCheck = cmds.polyListComponentConversion(selComponent, te=True)
|
|
edgeLoopCheck = cmds.ls(edgeLoopCheck,fl=1)
|
|
edgeLoopCheckInternal = cmds.polyListComponentConversion(selComponent, te=True,internal=1)
|
|
edgeLoopCheckInternal = cmds.ls(edgeLoopCheckInternal,fl=1)
|
|
tempCheck =[]
|
|
if edgeLoopCheckInternal:
|
|
tempCheck = list(set(edgeLoopCheck) -set(edgeLoopCheckInternal))
|
|
else:
|
|
tempCheck = edgeLoopCheck
|
|
insetDataEdgeLoopList = tempCheck
|
|
cmds.sets(insetDataEdgeLoopList, name= 'insetDataEdgeLoopListKeep', text='insetDataEdgeLoopListKeep')
|
|
cmds.setAttr('insetDataEdgeLoopListKeep.hiddenInOutliner', 1)
|
|
if not cmds.attributeQuery('storeBevelV', node = geo[0], ex=True ):
|
|
cmds.addAttr(geo[0], ln='storeBevelV')
|
|
cmds.setAttr((insetMesh + '.storeBevelV'), 0.01)
|
|
cmds.polyExtrudeFacet(selComponent,constructionHistory=1, keepFacesTogether=1 ,divisions=1, twist=0, taper=1, offset= 0.01, thickness=0, smoothingAngle=30)
|
|
insetFace = cmds.ls(sl=1,fl=1)
|
|
if 'Shape' in insetFace[0]:
|
|
insetFace = insetFace[1:]
|
|
newLoop = cmds.polyListComponentConversion(insetFace,te=True)
|
|
newLoop = cmds.ls(newLoop,fl=1)
|
|
newLoopInternal = cmds.polyListComponentConversion(insetFace, te=True,internal=1)
|
|
newLoopInternal = cmds.ls(newLoopInternal,fl=1)
|
|
newEdgeLoopCheck = []
|
|
if newLoopInternal:
|
|
newEdgeLoopCheck = list(set(newLoop) -set(newLoopInternal))
|
|
else:
|
|
newEdgeLoopCheck = newLoop
|
|
cmds.select(cl=1)
|
|
findCorner = []
|
|
newLoop = newEdgeLoopCheck
|
|
checkEdgeRingGrp = getEdgeRingGroup(newLoop)
|
|
cornerLoopCollect = []
|
|
for c in checkEdgeRingGrp:
|
|
getList = edgeLoopByAngle(c)
|
|
if getList:
|
|
cornerLoopCollect = cornerLoopCollect + getList
|
|
cornerLoop = cornerLoopCollect
|
|
recordInnerCornerList = cornerLoop
|
|
if cmds.objExists('tempLoopListKeep'):
|
|
updatedNewSelEdge = cmds.sets('tempLoopListKeep',q=1)
|
|
cmds.select(updatedNewSelEdge)
|
|
cmds.ConvertSelectionToFaces()
|
|
cmds.ConvertSelectionToEdgePerimeter()
|
|
tempCheckList = cmds.ls(sl=1,fl=1)
|
|
newCorner = list(set(newLoop)&set(tempCheckList))
|
|
cornerLoop = newCorner
|
|
cmds.delete('tempLoopListKeep')
|
|
insetInnerEdges = cmds.polyListComponentConversion(insetFace, te=True,internal=True)
|
|
insetInnerEdges = cmds.ls(insetInnerEdges,fl=1)
|
|
if cornerLoop:
|
|
cmds.createNode('creaseSet')
|
|
cmds.rename('cornerDisp')
|
|
cmds.setAttr("cornerDisp.creaseLevel", 1)
|
|
cmds.setAttr('cornerDisp.hiddenInOutliner', 1)
|
|
#cmds.select(cornerLoop)
|
|
cornerLoopVtx = cmds.polyListComponentConversion(cornerLoop,tv = True)
|
|
cornerLoopVtx = cmds.ls(cornerLoopVtx,fl=1)
|
|
sortGrp = []
|
|
sortGrp = getEdgeRingGroup(cornerLoop)
|
|
if len(sortGrp) > 0:# need a method to check loop number = protect corner number
|
|
################ BUG #######################
|
|
for g in sortGrp:
|
|
matchCorner(g, 1)
|
|
point_positions = {}
|
|
for n in cornerLoopVtx:
|
|
vertex_position = cmds.pointPosition(n, w=True)
|
|
point_positions[n] = vertex_position
|
|
|
|
for g in sortGrp:
|
|
matchCorner(g, 1.3)
|
|
newRoundMesh = cmds.duplicate(insetMesh, rr=1)
|
|
cmds.rename(newRoundMesh, 'roundV')
|
|
|
|
for point_name, new_position in point_positions.items():
|
|
cmds.xform(point_name, translation=new_position, worldSpace=True)
|
|
|
|
##################################################################
|
|
innerCVList = cmds.polyListComponentConversion(cornerLoop, tv=True)
|
|
innerCVList = cmds.ls(innerCVList,fl=1)
|
|
edgeBorderFaceA = cmds.polyListComponentConversion(newLoop,tf = True)
|
|
edgeBorderFaceA = cmds.ls(edgeBorderFaceA,fl=1)
|
|
insetDataEdgeLoopList = cmds.sets("insetDataEdgeLoopListKeep", q=True)
|
|
edgeBorderFaceB = cmds.polyListComponentConversion(insetDataEdgeLoopList,tf = True)
|
|
edgeBorderFaceB = cmds.ls(edgeBorderFaceB,fl=1)
|
|
setA = set(edgeBorderFaceA)
|
|
setB = set(edgeBorderFaceB)
|
|
edgeBorderFace = list(setA.intersection(setB))
|
|
findRingList =cmds.polyListComponentConversion(edgeBorderFace, te=True,internal=True)
|
|
loopRingList = cmds.ls(findRingList,fl=1)
|
|
insetDataPP = []
|
|
moveP = []
|
|
baseP = []
|
|
checkCV = cmds.polyListComponentConversion(loopRingList[0], tv=True)
|
|
checkCV = cmds.ls(checkCV,fl=1)
|
|
bevelDistance = distanceBetween(checkCV[0],checkCV[-1])
|
|
for r in loopRingList:
|
|
checkCV = cmds.polyListComponentConversion(r, tv=True)
|
|
checkCV = cmds.ls(checkCV,fl=1)
|
|
if checkCV[0] in innerCVList:
|
|
moveP = checkCV[0]
|
|
baseP = checkCV[1]
|
|
else:
|
|
moveP = checkCV[1]
|
|
baseP = checkCV[0]
|
|
basePPos = cmds.pointPosition(baseP, w =1)
|
|
movePPos = cmds.pointPosition(moveP, w =1)
|
|
dataCollect = [moveP,basePPos,movePPos]
|
|
insetDataPP.append(dataCollect)
|
|
newMesh = cmds.duplicate(insetMesh, rr=1)
|
|
cmds.rename(newMesh,'insetOffsetV')
|
|
refBevelV = math.sqrt(insetFaceArea) *4
|
|
for v in range(len(insetDataPP)):
|
|
currentPos = cmds.pointPosition(insetDataPP[v][0], w =1)
|
|
posX = ((currentPos[0] - insetDataPP[v][1][0])*(refBevelV))+ insetDataPP[v][1][0]
|
|
posY = ((currentPos[1] - insetDataPP[v][1][1])*(refBevelV))+ insetDataPP[v][1][1]
|
|
posZ = ((currentPos[2] - insetDataPP[v][1][2])*(refBevelV))+ insetDataPP[v][1][2]
|
|
cmds.move(posX, posY, posZ, insetDataPP[v][0].replace(insetMesh, 'insetOffsetV'), a =True, ws=True)
|
|
#cmds.delete(insetMesh, ch=1)
|
|
blendName = cmds.blendShape('insetOffsetV','roundV', insetMesh)
|
|
cmds.delete('insetOffsetV','roundV')
|
|
cmds.rename(blendName, 'insetOffsetNode')
|
|
cmds.setAttr("insetOffsetNode.envelope", 2)
|
|
if cmds.objExists('blendOffsetNode') == 0:
|
|
cmds.group(em= 1, n='blendOffsetNode')
|
|
cmds.addAttr('blendOffsetNode', longName='offset', attributeType='double', defaultValue=0)
|
|
cmds.setAttr('blendOffsetNode.offset', keyable=True)
|
|
cmds.setAttr('blendOffsetNode.hiddenInOutliner', 1)
|
|
cmds.connectControl( 'rInsetV', 'blendOffsetNode.offset' )
|
|
cmds.connectAttr('blendOffsetNode.offset', 'insetOffsetNode.insetOffsetV', force=True)
|
|
cmds.connectControl( 'rBevelRound', 'insetOffsetNode.roundV' )
|
|
cmds.floatSliderGrp('rBevelAngle',e=1, en=0)
|
|
cmds.floatSliderGrp('rBevelRound', e=1, en=1, v=0)
|
|
cmds.button('InsetButton',e=1, en = 0, bgc=[0.18,0.18,0.18])
|
|
cmds.button('reFineButton',e=1, en = 1,bgc=[0.28,0.18,0.38])
|
|
cmds.button('InsetRemoveButton',e=1, en = 1,bgc=[0.28,0.18,0.38])
|
|
cmds.button('InsetCleaneButton',e=1, en = 1)
|
|
cmds.button('InnerCornerEvenButton',e=1, en = 1,bgc=[0.28,0.18,0.38])
|
|
cmds.select(cl=1)
|
|
cmds.select('cornerDisp')
|
|
cmd = 'doMenuComponentSelectionExt("' + insetMesh + '", "edge", 0);'
|
|
mel.eval(cmd)
|
|
cmds.select(insetFace,add=1)
|
|
outliner_editor = 'outlinerPanel1'
|
|
cmds.outlinerEditor(outliner_editor,e=1,refresh=True)
|
|
|
|
def reFineSwtich():
|
|
cmds.floatSliderGrp('rBevelAngle',e=1, en = 1)
|
|
cmds.floatSliderGrp('rInsetV',e=1, en = 0)
|
|
cmds.button('InsetButton', e=1, en=0, bgc=[0.18,0.18,0.18])
|
|
cmds.button('reFineButton',l='update',e=1, en=1, bgc=[0.18,0.48,0.18], c=lambda *args: reFineMySelect())
|
|
cmds.button('InnerCornerEvenButton', e=1, en=0, bgc=[0.18,0.18,0.18])
|
|
cmds.button('InsetRemoveButton', e=1, en=0, bgc=[0.18,0.18,0.18])
|
|
cmds.button('InsetCleaneButton', e=1, en=1, bgc=[0.48,0.18,0.18])
|
|
reviewProtectCorner()
|
|
edgeLoopByAngleUpdate()
|
|
rBevelAngleUpdate()
|
|
cmds.select('cornerDisp')
|
|
cmds.setAttr('cornerDisp.creaseLevel', 1)
|
|
cmds.scriptJob (event = ["SelectionChanged", updateSelToCrease])
|
|
cmds.scriptJob(uiDeleted=["RoundInsetUI", RoundInsetScriptJobClean])
|
|
|
|
def edgeLoopByAngleUpdate():
|
|
global insetDataEdgeLoopList
|
|
global edgeLoopAngleLib
|
|
global edgeLoopOverLengthLib
|
|
insetDataEdgeLoopList = cmds.sets("insetDataEdgeLoopListKeep", q=True)
|
|
edgeLoopAngleLib = {}
|
|
sortGrp = getEdgeRingGroup(insetDataEdgeLoopList)
|
|
for s in sortGrp:
|
|
listVtx = vtxLoopOrder(s)
|
|
listVtx.append(listVtx[0])
|
|
listVtx.append(listVtx[1])
|
|
for r in range(len(listVtx)-2):
|
|
pA = cmds.pointPosition(listVtx[r], w=True)
|
|
pB = cmds.pointPosition(listVtx[r+1], w=True)
|
|
pC = cmds.pointPosition(listVtx[r+2], w=True)
|
|
edgeFoundA = cmds.polyListComponentConversion(listVtx[r], listVtx[r+1],fv=True, te=True, internal=True)
|
|
distA = math.sqrt( ((pA[0] - pB[0])**2) + ((pA[1] - pB[1])**2) + ((pA[2] - pB[2])**2) )
|
|
edgeFoundB = cmds.polyListComponentConversion( listVtx[r+1],listVtx[r+2],fv=True, te=True, internal=True)
|
|
distB = math.sqrt( ((pB[0] - pC[0])**2) + ((pB[1] - pC[1])**2) + ((pB[2] - pC[2])**2) )
|
|
direction_vectorA = [pA[i] - pB[i] for i in range(3)]
|
|
lengthA = sum(y ** 2 for y in direction_vectorA) ** 0.5
|
|
normalized_directionA = [y / lengthA for y in direction_vectorA]
|
|
direction_vectorB = [pB[i] - pC[i] for i in range(3)]
|
|
lengthB = sum(y ** 2 for y in direction_vectorB) ** 0.5
|
|
normalized_directionB = [y / lengthB for y in direction_vectorB]
|
|
dot_product = sum([normalized_directionA[z] * normalized_directionB[z] for z in range(3)])
|
|
angle_degrees = math.degrees(math.acos(dot_product))
|
|
rounded_angle = round(angle_degrees, 4) + ((r+1)*0.0001)
|
|
edgeFound = []
|
|
edgeFound = [edgeFoundA[0],edgeFoundB[0]]
|
|
if distA > edgeLoopOverLengthLib*2:
|
|
edgeFound.remove(edgeFoundA[0])
|
|
if distB > edgeLoopOverLengthLib*2:
|
|
edgeFound.remove(edgeFoundB[0])
|
|
if edgeFound:
|
|
edgeLoopAngleLib[edgeFound[0]] = rounded_angle
|
|
|
|
|
|
def reviewProtectCorner():
|
|
global insetFace
|
|
global insetMesh
|
|
shape_node = cmds.listRelatives(insetMesh, shapes=True)
|
|
source_shape = shape_node[-1]
|
|
destination_shape = shape_node[0]
|
|
if insetFace:
|
|
history_nodes = cmds.listHistory(insetMesh)
|
|
delList = ["polyExtrudeFace1", "polyCrease1", "insetOffsetNod*"]
|
|
for d in delList:
|
|
if cmds.objExists(d):
|
|
cmds.delete(d)
|
|
cmds.select(cl=1)
|
|
|
|
|
|
def rBevelAngleUpdate():
|
|
currentList = cmds.ls(sl=1,fl=1)
|
|
global edgeLoopAngleLib
|
|
checkListAA = []
|
|
newV = cmds.floatSliderGrp('rBevelAngle', q=1 ,v=1)
|
|
toCheck = 90 - newV
|
|
overLength = [edge for edge, value in edgeLoopAngleLib.items() if value > toCheck]
|
|
newList = list(set(overLength))
|
|
if currentList != newList:
|
|
cmds.select(newList,r=1)
|
|
cmds.sets(clear="cornerDisp")
|
|
cmds.sets(newList,forceElement="cornerDisp")
|
|
|
|
|
|
def updateSelToCrease():
|
|
updateList = cmds.ls(sl=1, fl=1)
|
|
cmds.sets(clear="cornerDisp")
|
|
cmds.sets(updateList,forceElement="cornerDisp")
|
|
|
|
def RoundInsetScriptJobClean():
|
|
foundError = 1
|
|
while foundError > 0:
|
|
jobs = cmds.scriptJob( listJobs=True )
|
|
foundError = 0
|
|
for j in jobs:
|
|
if "updateSelTo" in j:
|
|
jID = j.split(':')[0]
|
|
try:
|
|
cmds.scriptJob (kill = int(jID))
|
|
except:
|
|
foundError = 1
|
|
|
|
def reFineMySelect():
|
|
updatedNewSelEdge = cmds.filterExpand(ex =1, sm =32)
|
|
cmds.sets(updatedNewSelEdge, name= 'tempLoopListKeep', text='tempLoopListKeep')
|
|
cmds.setAttr('tempLoopListKeep.hiddenInOutliner', 0)
|
|
RoundInsetScriptJobClean()
|
|
global insetFace
|
|
global insetMesh
|
|
global insetDataEdgeLoopList
|
|
insetDataEdgeLoopList = []
|
|
getRoundV = cmds.floatSliderGrp('rBevelRound', q=1, v=1)
|
|
getInsetV = cmds.floatSliderGrp('rInsetV', q=1, v=1)
|
|
shape_node = cmds.listRelatives(insetMesh, shapes=True)
|
|
source_shape = shape_node[-1]
|
|
destination_shape = shape_node[0]
|
|
if insetFace:
|
|
history_nodes = cmds.listHistory(insetMesh)
|
|
delList = ["polyExtrudeFace1", "polyCrease1", "insetOffsetNod*"]
|
|
for d in delList:
|
|
if cmds.objExists(d):
|
|
cmds.delete(d)
|
|
cmds.select(insetFace)
|
|
if cmds.objExists('insetDataEdgeLoopListKeep'):
|
|
cmds.delete('insetDataEdgeLoopListKeep')
|
|
if cmds.objExists('cornerDisp'):
|
|
cmds.setAttr('cornerDisp.creaseLevel', 0)
|
|
cmds.delete('cornerDisp')
|
|
roundInsetRun()
|
|
cmds.setAttr('blendOffsetNode.offset', getInsetV)
|
|
#cmds.setAttr('insetOffsetNode.roundV', getRoundV)
|
|
#cmds.select('cornerDisp')
|
|
cmd = 'doMenuComponentSelectionExt("' + insetMesh + '", "edge", 0);'
|
|
mel.eval(cmd)
|
|
cmds.select(insetFace,add=1)
|
|
cmds.setToolTo('selectSuperContext')
|
|
cmds.button('InsetButton',e=1, en = 0, bgc=[0.18,0.18,0.18])
|
|
cmds.button('reFineButton',l='Refine',e=1, en = 1,c=lambda *args: reFineSwtich(),bgc=[0.28,0.18,0.38])
|
|
cmds.button('InsetRemoveButton',e=1, en = 1,bgc=[0.28,0.18,0.38])
|
|
cmds.button('InsetCleaneButton',e=1, en = 1)
|
|
cmds.button('InnerCornerEvenButton',e=1, en = 1,bgc=[0.28,0.18,0.38])
|
|
cmds.floatSliderGrp('rBevelAngle',e=1, en=0)
|
|
cmds.floatSliderGrp('rInsetV',e=1, en = 1)
|
|
|
|
if __name__ == "__main__":
|
|
run()
|