431 lines
15 KiB
Python
431 lines
15 KiB
Python
##--------------------------------------------------------------------------
|
|
try:
|
|
from PySide6 import QtWidgets, QtCore, QtGui
|
|
from PySide6.QtWidgets import *
|
|
from PySide6.QtGui import *
|
|
from PySide6.QtCore import *
|
|
from shiboken6 import wrapInstance
|
|
|
|
except ImportError:
|
|
from PySide2 import QtWidgets, QtCore, QtGui
|
|
from shiboken2 import wrapInstance
|
|
from PySide2.QtGui import QIcon
|
|
from PySide2.QtWidgets import QWidget
|
|
import shiboken2
|
|
|
|
|
|
from maya import cmds as mc
|
|
import maya.mel as mel
|
|
import json
|
|
import os
|
|
import maya.cmds as cmds
|
|
from functools import partial
|
|
|
|
import importlib
|
|
from .. import ModIt_Global
|
|
|
|
importlib.reload(ModIt_Global)
|
|
|
|
from .. import ModIt_CSS
|
|
importlib.reload(ModIt_CSS)
|
|
|
|
|
|
##______________________GLOBAL VAR
|
|
##PATH_SET
|
|
IconPath = ModIt_Global.IconsPathThemeClassic
|
|
PreferencePath = ModIt_Global.PreferencePath
|
|
ToolsPath = ModIt_Global.ToolPath
|
|
|
|
# ******************************************
|
|
# BUTTONS PARAMS
|
|
# ******************************************
|
|
iconFixeSize = 32
|
|
iconButtonSize = 30
|
|
separatorWidth = ModIt_Global.separatorWidth
|
|
|
|
##JSON PREF DATA
|
|
PRIM_MODE =(json.load(open(PreferencePath + 'Setting_Primitives_Placement.json',"r"))['PRIM_MODE'])
|
|
PRIM_SIZE =(json.load(open(PreferencePath + 'Setting_Primitives_Size.json',"r"))['PRIM_SIZE'])
|
|
|
|
|
|
|
|
class MyCustomBtn_Widget_forIcon(QtWidgets.QPushButton):
|
|
def __init__(self, iconPath):
|
|
super().__init__()
|
|
#FOR ICON HOVER EFFECT
|
|
pix_normal = QtGui.QPixmap(iconPath)
|
|
pix_over = pix_normal.copy()
|
|
painter = QtGui.QPainter(pix_over)
|
|
painter.fillRect(pix_over.rect(), QtGui.QColor(250, 250, 250, 40))
|
|
painter.setCompositionMode(QtGui.QPainter.CompositionMode_Plus)
|
|
painter.end()
|
|
self._icon_normal = QIcon(pix_normal)
|
|
self._icon_over = QIcon(pix_over)
|
|
self.setIcon(self._icon_normal)
|
|
#FOR CONTEXT MENU
|
|
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
|
|
|
def enterEvent(self, event): #ICON
|
|
self.setIcon(self._icon_over)
|
|
return super(MyCustomBtn_Widget, self).enterEvent(event)
|
|
def leaveEvent(self, event): #ICON
|
|
self.setIcon(self._icon_normal)
|
|
return super(MyCustomBtn_Widget, self).leaveEvent(event)
|
|
|
|
def mousePressEvent(self, event): #CONTEXT MENUE
|
|
super().mousePressEvent(event)
|
|
if event.button() == QtCore.Qt.RightButton:
|
|
# emit the signal, we can grab the pos directly from the event, no need to get cursor position anymore
|
|
self.customContextMenuRequested.emit(event.pos())
|
|
# make a call to mouseRelease event to restore button back to its original state
|
|
self.mouseReleaseEvent(event)
|
|
class MyCustomBtn_Widget(QtWidgets.QPushButton):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
|
def mousePressEvent(self, event):
|
|
super().mousePressEvent(event)
|
|
if event.button() == QtCore.Qt.RightButton:
|
|
# emit the signal, we can grab the pos directly from the event, no need to get cursor position anymore
|
|
self.customContextMenuRequested.emit(event.pos())
|
|
# make a call to mouseRelease event to restore button back to its original state
|
|
self.mouseReleaseEvent(event)
|
|
|
|
|
|
class SELECTIONS_LAYOUT(QtWidgets.QWidget):
|
|
def __init__(self, parent=None):
|
|
super().__init__(parent=parent)
|
|
|
|
SECTION_SELECTIONS_LAYOUT = QtWidgets.QHBoxLayout() # MAIN
|
|
SECTION_SELECTIONS_LAYOUT.setContentsMargins(0,0,0,0)
|
|
SECTION_SELECTIONS_LAYOUT.setSpacing(0)
|
|
self.setLayout(SECTION_SELECTIONS_LAYOUT)
|
|
|
|
##---------------------------------------------------- ALIGN PIVOT
|
|
self.AlignPivotFace_btn = MyCustomBtn_Widget()
|
|
self.AlignPivotFace_btn.setFixedSize(iconFixeSize, iconFixeSize)
|
|
self.AlignPivotFace_btn.setIconSize(QtCore.QSize(iconButtonSize, iconButtonSize))
|
|
self.AlignPivotFace_btn.setIcon(QtGui.QIcon(IconPath + "AlignFace.png"))
|
|
self.AlignPivotFace_btn.setToolTip(" Align and Bake Object Pivot based on Face Normals ")
|
|
self.AlignPivotFace_btn.clicked.connect(self.alignPivotFace)
|
|
|
|
|
|
|
|
##---------------------------------------------------- CONTINUS EDGE
|
|
self.ContinusEdge_btn = MyCustomBtn_Widget()
|
|
self.ContinusEdge_btn.setFixedSize(iconFixeSize, iconFixeSize)
|
|
self.ContinusEdge_btn.setIconSize(QtCore.QSize(iconButtonSize, iconButtonSize))
|
|
self.ContinusEdge_btn.setIcon(QtGui.QIcon(IconPath + "ContinusEdge.png"))
|
|
self.ContinusEdge_btn.setToolTip(" Select All Perimeter Contiguous Edge Until +45° angle ")
|
|
self.ContinusEdge_btn.clicked.connect(self.continusEdges)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##---------------------------------------------------- SELECT INNER
|
|
self.SelIn_btn = QtWidgets.QPushButton()
|
|
self.SelIn_btn.setFixedSize(iconFixeSize, iconFixeSize)
|
|
self.SelIn_btn.setIconSize(QtCore.QSize(iconButtonSize, iconButtonSize))
|
|
self.SelIn_btn.setIcon(QtGui.QIcon(IconPath + "SelIco1b.png"))
|
|
self.SelIn_btn.setToolTip(" Select Inner Faces ")
|
|
self.SelIn_btn.clicked.connect(self.selInner)
|
|
|
|
|
|
##---------------------------------------------------- SELECT INNER + SELECTION
|
|
self.SelInAndSel_btn = QtWidgets.QPushButton()
|
|
self.SelInAndSel_btn.setFixedSize(iconFixeSize, iconFixeSize)
|
|
self.SelInAndSel_btn.setIconSize(QtCore.QSize(iconButtonSize, iconButtonSize))
|
|
self.SelInAndSel_btn.setIcon(QtGui.QIcon(IconPath + "SelIco1.png"))
|
|
self.SelInAndSel_btn.setToolTip(" Select Inner Faces and Keep Selection ")
|
|
self.SelInAndSel_btn.clicked.connect(self.selInnerPlus)
|
|
|
|
|
|
##---------------------------------------------------- NX Edge
|
|
self.EdgeNx_btn = MyCustomBtn_Widget()
|
|
self.EdgeNx_btn.setFixedSize(iconFixeSize, iconFixeSize)
|
|
self.EdgeNx_btn.setIconSize(QtCore.QSize(iconButtonSize, iconButtonSize))
|
|
self.EdgeNx_btn.setIcon(QtGui.QIcon(IconPath + "SelIco3.png"))
|
|
self.EdgeNx_btn.setToolTip(" Select Every X Edges ")
|
|
self.EdgeNx_btn.clicked.connect(partial(self.selEdgeNX, "edgeLoop", 2))
|
|
|
|
# C O N N E C T P O P U P M E N U T O O U R B U T T O N
|
|
self.EdgeNx_btn.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
|
self.EdgeNx_btn.customContextMenuRequested.connect(self.showPopupNedge)
|
|
# CUBE M E N U I T E M S
|
|
self.popupMenuNedge = QtWidgets.QMenu()
|
|
Loop_2 = self.popupMenuNedge.addAction(" > Loop : Select 1 Edge each 2 Edges")
|
|
Loop_3 = self.popupMenuNedge.addAction(" > Loop : Select 1 Edge each 3 Edges")
|
|
Loop_4 = self.popupMenuNedge.addAction(" > Loop : Select 1 Edge each 4 Edges")
|
|
Loop_2.triggered.connect(partial(self.selEdgeNX, "edgeLoop", 2))
|
|
Loop_3.triggered.connect(partial(self.selEdgeNX, "edgeLoop", 3))
|
|
Loop_4.triggered.connect(partial(self.selEdgeNX, "edgeLoop", 4))
|
|
Ring_2 = self.popupMenuNedge.addAction(" > Ring : Select 1 Edge each 2 Edges")
|
|
Ring_3 = self.popupMenuNedge.addAction(" > Ring : Select 1 Edge each 3 Edges")
|
|
Ring_4 = self.popupMenuNedge.addAction(" > Ring : Select 1 Edge each 4 Edges")
|
|
Ring_2.triggered.connect(partial(self.selEdgeNX, "edgeRing", 2))
|
|
Ring_3.triggered.connect(partial(self.selEdgeNX, "edgeRing", 3))
|
|
Ring_4.triggered.connect(partial(self.selEdgeNX, "edgeRing", 4))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##---------------------------------------------------- CHECK FACES
|
|
self.CheckFace_btn = MyCustomBtn_Widget()
|
|
self.CheckFace_btn.setFixedSize(iconFixeSize, iconFixeSize)
|
|
self.CheckFace_btn.setIconSize(QtCore.QSize(iconButtonSize, iconButtonSize))
|
|
self.CheckFace_btn.setIcon(QtGui.QIcon(IconPath + "SelIco2.png"))
|
|
self.CheckFace_btn.setToolTip(" Select Object Faces By Type ")
|
|
self.CheckFace_btn.clicked.connect(self.checkNGon)
|
|
|
|
# C O N N E C T P O P U P M E N U T O O U R B U T T O N
|
|
self.CheckFace_btn.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
|
self.CheckFace_btn.customContextMenuRequested.connect(self.showPopupCheck)
|
|
# CUBE M E N U I T E M S
|
|
self.popupMenuCube = QtWidgets.QMenu()
|
|
Ngons = self.popupMenuCube.addAction(" Select all NGons faces on the selected mesh")
|
|
Quad = self.popupMenuCube.addAction(" Select all Quadrangles faces on the selected mesh")
|
|
Tri = self.popupMenuCube.addAction(" Select all Triangles faces on the selected mesh")
|
|
Concave = self.popupMenuCube.addAction(" Select all Concaves faces on the selected mesh")
|
|
Ngons.triggered.connect(self.checkNGon)
|
|
Quad.triggered.connect(self.checkQuad)
|
|
Tri.triggered.connect(self.checkTri)
|
|
Concave.triggered.connect(self.checkNConcave)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##---------------------------------------------------- Add to Layout
|
|
SECTION_SELECTIONS_LAYOUT.addWidget(self.AlignPivotFace_btn)
|
|
SECTION_SELECTIONS_LAYOUT.addWidget(self.ContinusEdge_btn)
|
|
SECTION_SELECTIONS_LAYOUT.addWidget(self.SelIn_btn)
|
|
SECTION_SELECTIONS_LAYOUT.addWidget(self.SelInAndSel_btn)
|
|
SECTION_SELECTIONS_LAYOUT.addWidget(self.EdgeNx_btn)
|
|
SECTION_SELECTIONS_LAYOUT.addWidget(self.CheckFace_btn)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------
|
|
##---------------------------------------------------- D E F I N I T I O N
|
|
#------------------------------------------------
|
|
def BAM(self):
|
|
print("BAMMM")
|
|
|
|
|
|
def showPopupNedge(self, position):
|
|
self.popupMenuNedge.exec_(self.EdgeNx_btn.mapToGlobal(position))
|
|
self.EdgeNx_btn.update()
|
|
|
|
def showPopupCheck(self, position):
|
|
self.popupMenuCube.exec_(self.CheckFace_btn.mapToGlobal(position))
|
|
self.CheckFace_btn.update()
|
|
|
|
|
|
|
|
def Clean(self):
|
|
mc.sets(n="selInnerPlusSet1")
|
|
mc.sets(add="selInnerPlusSet1")
|
|
mc.SelectFacetMask()
|
|
mc.polyUVSet(d=True, uvSet="ModIt_UvLayout")
|
|
mc.select(clear=True)
|
|
mc.select("selInnerPlusSet1")
|
|
mc.delete("selInnerPlusSet1")
|
|
|
|
def CleanPluss(self):
|
|
mc.sets(n="selInnerPlusSet1")
|
|
mc.sets(add="selInnerPlusSet1")
|
|
mc.SelectFacetMask()
|
|
mc.polyUVSet(d=True, uvSet="ModIt_UvLayout")
|
|
mc.select(clear=True)
|
|
mc.select("selInnerPlusSet1")
|
|
mc.delete("selInnerPlusSet1")
|
|
mc.GrowPolygonSelectionRegion()
|
|
|
|
def selInner(self):
|
|
#Verif Selection is Face
|
|
checkSelectedComponent = mc.filterExpand(sm=34)
|
|
if checkSelectedComponent == None:
|
|
ModIt_Global.WarningWindow(" You should select Faces.", 300)
|
|
return
|
|
|
|
mc.undoInfo(openChunk=True, infinity=True)
|
|
selFace= mc.ls(sl=True)
|
|
selObj = cmds.ls(sl=1, fl=1, o=1)
|
|
mc.polyProjection (selObj, ch=1, type= "Planar", ibd = False, cm= True, uvSetName = "ModIt_UvLayout", kir = True, md= "c")
|
|
mc.polyUVSet(cuv= True, uvSet = "ModIt_UvLayout")
|
|
|
|
selEdgePeri = mc.ConvertSelectionToEdgePerimeter()
|
|
mc.polyMapCut()
|
|
|
|
mc.SelectMeshUVShell()
|
|
|
|
mc.scriptJob( runOnce=True, e = ["SelectionChanged", self.Clean])
|
|
mc.undoInfo(closeChunk=True)
|
|
|
|
|
|
def selInnerPlus(self):
|
|
#Verif Selection is Face
|
|
checkSelectedComponent = mc.filterExpand(sm=34)
|
|
if checkSelectedComponent == None:
|
|
ModIt_Global.WarningWindow(" You should select Faces.", 300)
|
|
return
|
|
|
|
mc.undoInfo(openChunk=True, infinity=True)
|
|
selFace=mc.ls(sl=True)
|
|
selObj = cmds.ls(sl=1, fl=1, o=1)
|
|
|
|
mc.polyProjection (selObj, ch=1, type= "Planar", ibd = False, cm= True, uvSetName = "ModIt_UvLayout", kir = True, md= "c")
|
|
mc.polyUVSet(cuv= True, uvSet = "ModIt_UvLayout")
|
|
|
|
selEdgePeri = mc.ConvertSelectionToEdgePerimeter()
|
|
mc.polyMapCut()
|
|
|
|
mc.SelectMeshUVShell()
|
|
|
|
mc.scriptJob( runOnce=True, e = ["SelectionChanged", self.CleanPluss])
|
|
mc.undoInfo(closeChunk=True)
|
|
|
|
|
|
def selEdgeNX(self, type, nbr):
|
|
mel.eval('polySelectEdgesEveryN "%s" %s;' % (type, nbr))
|
|
|
|
def checkNGon(self):
|
|
mc.selectMode(q=True, co=True)
|
|
mc.polySelectConstraint(m=3 ,t = 0x0008, sz=3)
|
|
mc.polySelectConstraint(dis=True)
|
|
|
|
def checkTri(self):
|
|
mc.selectMode(q=True, co=True)
|
|
mc.polySelectConstraint(m=3 ,t = 0x0008, sz=1)
|
|
mc.polySelectConstraint(dis=True)
|
|
|
|
def checkQuad(self):
|
|
mc.selectMode(q=True, co=True)
|
|
mc.polySelectConstraint(m=3 ,t = 0x0008, sz=2)
|
|
mc.polySelectConstraint(dis=True)
|
|
|
|
|
|
def checkNConcave(self):
|
|
mc.selectMode(q=True, co=True)
|
|
mc.polySelectConstraint(m=3 ,t = 0x0008, c=1)
|
|
mc.polySelectConstraint(dis=True)
|
|
|
|
|
|
def alignPivotFace(self):
|
|
#Verif Selection is Face
|
|
checkSelectedComponent = mc.filterExpand(sm=34)
|
|
if checkSelectedComponent == None:
|
|
ModIt_Global.WarningWindow(" Works on Face mode only.", 300)
|
|
return
|
|
|
|
else:
|
|
mc.undoInfo(openChunk=True, infinity=True)
|
|
mc.setToolTo('Move')
|
|
getPivotPos = mel.eval("float $getPivotPos[] = `manipMoveContext -q -p Move`;")
|
|
mel.eval("ConvertSelectionToVertices;")
|
|
vtxSel = mc.ls(fl=1, sl=1)
|
|
selectedObjectStore = mc.ls(o=1, sl=1)
|
|
objectSelectionStore = mc.listRelatives(selectedObjectStore[0], p=1)
|
|
if len(vtxSel) < 3:
|
|
mc.warning("ModIt : Please select at least 3 Vertices, 2 Edges or 1 Face")
|
|
|
|
plane = mc.polyPlane(cuv=2, sy=1, sx=1, h=1, n='rotationPlane', ch=1, w=1, ax=(0, 1, 0))
|
|
mc.select((plane[0] + ".vtx[0:2]"), vtxSel[0], vtxSel[1], vtxSel[2])
|
|
mel.eval("snap3PointsTo3Points(0)")
|
|
mc.parent(objectSelectionStore, plane[0])
|
|
mc.makeIdentity(objectSelectionStore, apply=True, s=0, r=1, t=0, n=0)
|
|
mc.xform(ws=1, piv=(getPivotPos[0], getPivotPos[1], getPivotPos[2]))
|
|
mc.parent(objectSelectionStore, world=1)
|
|
mc.delete(plane)
|
|
mc.undoInfo(closeChunk=True)
|
|
|
|
|
|
|
|
def continusEdges(self):
|
|
#Verif Selection is Edge
|
|
checkSelectedComponent = mc.filterExpand(sm=32)
|
|
if checkSelectedComponent == None:
|
|
ModIt_Global.WarningWindow(" You should select a border edge.", 300)
|
|
return
|
|
|
|
else:
|
|
mc.undoInfo(openChunk=True, infinity=True)
|
|
# 1 - Continus Edge
|
|
mc.SelectContiguousEdges()
|
|
|
|
# 2 - Store Continus Set
|
|
mc.sets(n="ModIt_SelContinus_tempSet")
|
|
|
|
# Need to get select objectq
|
|
mc.SelectVertexMask()
|
|
mc.SelectToggleMode()
|
|
|
|
objSel = mc.ls(sl=True)
|
|
|
|
# GET ALL FACE
|
|
list = mc.ls(sl=True)
|
|
for item in list:
|
|
fCount = mc.polyEvaluate(v=True)
|
|
mc.select(cl=True)
|
|
mc.select(item + '.f[0:' + str(fCount) + ']', add=True)
|
|
|
|
# CONVERT IN EDGE
|
|
mc.ConvertSelectionToContainedEdges()
|
|
mc.sets(n="ModIt_IntEdges_tempSet")
|
|
|
|
mc.select(mc.sets('ModIt_IntEdges_tempSet', sub="ModIt_SelContinus_tempSet"))
|
|
|
|
mc.sets(n="ModIt_GoodSel")
|
|
mc.select(d=True)
|
|
|
|
obSelName = str(objSel[0])
|
|
mel.eval('doMenuComponentSelectionExt(" ' + obSelName + '", "edge", 0);')
|
|
mc.select("ModIt_GoodSel")
|
|
|
|
mc.delete("ModIt_IntEdges_tempSet")
|
|
mc.delete("ModIt_SelContinus_tempSet")
|
|
mc.delete("ModIt_GoodSel")
|