MetaBox/Scripts/Modeling/Edit/gs_curvetools/ui.py

2925 lines
130 KiB
Python
Raw Normal View History

2025-01-14 02:59:09 +08:00
"""
License:
This collection of code named GS CurveTools is a property of George Sladkovsky (Yehor Sladkovskyi)
and can not be copied or distributed without his written permission.
GS CurveTools v1.3.1 Studio
Copyright 2023, George Sladkovsky (Yehor Sladkovskyi)
All Rights Reserved
Autodesk Maya is a property of Autodesk, Inc.
Social Media and Contact Links:
Discord Server: https://discord.gg/f4DH6HQ
Online Store: https://sladkovsky3d.artstation.com/store
Online Documentation: https://gs-curvetools.readthedocs.io/
Twitch Channel: https://www.twitch.tv/videonomad
YouTube Channel: https://www.youtube.com/c/GeorgeSladkovsky
ArtStation Portfolio: https://www.artstation.com/sladkovsky3d
Contact Email: george.sladkovsky@gmail.com
"""
import os
from functools import partial as pa
from imp import reload
import maya.cmds as mc
import maya.OpenMayaUI as omui
from PySide2 import QtCore, QtGui, QtWidgets
from shiboken2 import wrapInstance
from . import core, uv_editor
from .constants import *
from .utils import gs_math as mt
from .utils import style, tooltips, utils, wrap
from .utils.utils import deferred, noUndo, undo
from .utils.wrap import WIDGETS
reload(core)
reload(uv_editor)
reload(utils)
reload(wrap)
reload(style)
MESSAGE = utils.logger
LOGGER = utils.logger.logger
# Maya Main Window and Workspace
def mayaMainWindow():
""" Get Maya main window pointer"""
mayaWindow = wrapInstance(int(omui.MQtUtil.mainWindow()), QtWidgets.QMainWindow)
return mayaWindow
def mayaWorkspaceControl(name, label, retain=True, iw=164, ih=783, widthProperty='preferred'):
""" Create Maya Dockable Workspace """
try:
control = mc.workspaceControl(name, l=label, r=retain, li=True, vis=True, wp=widthProperty, iw=iw, ih=ih, mw=iw, mh=100)
except BaseException:
LOGGER.debug("Using legacy workspace control")
control = mc.workspaceControl(name, l=label, r=retain, li=True, vis=True, wp=widthProperty, iw=iw, ih=ih, mw=iw)
qtControl = omui.MQtUtil.findControl(control)
dock = wrapInstance(int(qtControl), QtWidgets.QWidget)
wrap.WIDGETS[name] = dock
return dock
def curveControlWorkspace():
if mc.workspaceControl(CURVE_CONTROL_NAME, q=1, ex=1):
if MAYA_VER >= 2018:
if not mc.workspaceControl(CURVE_CONTROL_NAME, q=1, vis=1):
mc.workspaceControl(CURVE_CONTROL_NAME, e=1, rs=1)
deferred(core.updateMainUI)()
else:
mc.workspaceControl(CURVE_CONTROL_NAME, e=1, vis=0)
else:
mc.workspaceControl(CURVE_CONTROL_NAME, e=1, fl=1)
mc.deleteUI(CURVE_CONTROL_NAME)
else:
CurveControlUI()
core.curveControlUI.updateUI()
from . import main
main.checkScriptJobs(CURVE_CONTROL_NAME)
class CurveControlUI(QtWidgets.QWidget):
def __init__(self):
parent = mayaWorkspaceControl(name=CURVE_CONTROL_NAME,
label=CURVE_CONTROL_LABEL,
retain=False, iw=350, ih=750, widthProperty="free")
# Dockable Workspace Connection
super(CurveControlUI, self).__init__(parent)
self.ui()
parent.layout().addWidget(self)
def ui(self):
# Layout
mainLayout = QtWidgets.QVBoxLayout(self)
mainLayout.setContentsMargins(*style.scale([2, 0, 2, 0]))
self.scrollWidget = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout(self.scrollWidget)
scrollArea = QtWidgets.QScrollArea()
scrollArea.setWidget(self.scrollWidget)
mainLayout.addWidget(scrollArea)
# Layout Settings
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(style.scale(2))
layout.setMargin(0)
layout.setAlignment(QtCore.Qt.AlignTop)
scrollArea.setFrameShape(QtWidgets.QFrame.NoFrame)
scrollArea.setWidgetResizable(True)
# Main Controls
layout.addWidget(wrap.separator())
# Layer Selector, Color Picker, Curve Name and Line Thickness
with wrap.Row(layout, 'gsCurveControlHeader') as row:
layerSelector = wrap.LayerSelector('gsLayerSelector', row.layout())
layerSelector.setFixedWidth(style.scale(40))
layerSelector.currentIndexChanged.connect(core.changeLayerViaOptionMenu)
layerColorPicker = wrap.ColorPicker('gsColorPicker', row.layout())
layerColorPicker.setContentsMargins(*style.scale([3, 3, 1, 3]))
layerColorPicker.setFixedWidth(style.scale(20))
layerColorPicker.connectCommand(core.toggleColor.changeLayerColor)
curveColorPicker = wrap.ColorPicker('gsCurveColorPicker', row.layout())
curveColorPicker.setContentsMargins(*style.scale([1, 3, 2, 3]))
curveColorPicker.setFixedWidth(style.scale(20))
curveColorPicker.connectCommand(core.toggleColor.changeCurveColor)
selectedObjectName = wrap.LineEdit('selectedObjectName', row.layout())
selectedObjectName.setPlaceholderText('Select Curve')
selectedObjectName.returnPressed.connect(undo(core.renameSelected))
lineThickness = wrap.FloatField('lineWidth', row.layout())
lineThickness.setFixedWidth(style.scale(35))
lineThickness.setRange(-1, 10)
lineThickness.setValue(-1)
lineThickness.setDragCommand(pa(core.sliders.curveControlSliderDrag, lineThickness))
lineThickness.setReleaseCommand(core.sliders.release)
layout.addWidget(wrap.separator())
# Select Curves Prompt
label = wrap.Label(layout, 'selectCurvesPrompt')
label.setLabel('Select Compatible Curves')
label.setFontSize(14)
label.setVisible(False)
# Axis Control
with wrap.Column(layout, 'axisFrame') as column:
label = wrap.Label(column.layout())
label.setLabel('Axis Control')
label.setFontSize(14)
with wrap.Row(column.layout()) as row:
WIDGETS['Axis'] = axisButtonGrp = QtWidgets.QButtonGroup()
axisAuto = wrap.Button(row.layout(), 'gsBindAxisAuto')
axisAuto.setLabel('Auto', lineHeight=100)
axisAuto.setCheckable(True)
axisAuto.setButtonStyle('small')
axisAuto.setChecked(True)
axisAuto.clicked.connect(pa(undo(core.applyAxis), 0))
axisX = wrap.Button(row.layout(), 'gsBindAxisX')
axisX.setLabel('X', lineHeight=100)
axisX.setCheckable(True)
axisX.setButtonStyle('small')
axisX.clicked.connect(pa(undo(core.applyAxis), 1))
axisY = wrap.Button(row.layout(), 'gsBindAxisY')
axisY.setLabel('Y', lineHeight=100)
axisY.setCheckable(True)
axisY.setButtonStyle('small')
axisY.clicked.connect(pa(undo(core.applyAxis), 2))
axisZ = wrap.Button(row.layout(), 'gsBindAxisZ')
axisZ.setLabel('Z', lineHeight=100)
axisZ.setCheckable(True)
axisZ.setButtonStyle('small')
axisZ.clicked.connect(pa(undo(core.applyAxis), 3))
axisButtonGrp.addButton(axisAuto, 0)
axisButtonGrp.addButton(axisX, 1)
axisButtonGrp.addButton(axisY, 2)
axisButtonGrp.addButton(axisZ, 3)
axisFlip = wrap.Button(row.layout(), 'AxisFlip')
axisFlip.setLabel('Flip', lineHeight=100)
axisFlip.setCheckable(True)
axisFlip.setButtonStyle('small')
axisFlip.clicked.connect(pa(undo(core.applyAxis), -1))
column.layout().addWidget(wrap.separator())
# Edit Original Objects
with wrap.Row(column.layout(), margins=style.scale([0, 0, 0, 0]), objName='originalCurvesRow') as originalCurvesRow:
selectOriginalCurves = wrap.Button(originalCurvesRow.layout(), 'selectOriginalCurves')
selectOriginalCurves.setLabel('Select Original Curves', lineHeight=100)
selectOriginalCurves.setButtonStyle('small-filled')
selectOriginalCurves.clicked.connect(undo(core.curveControlUI.selectOriginalObjects))
editOrigObj = wrap.Button(originalCurvesRow.layout(), 'editOrigObj')
editOrigObj.setLabel('Edit Original Objects', lineHeight=100)
editOrigObj.setCheckable(True)
editOrigObj.setButtonStyle('small')
editOrigObj.clicked.connect(undo(core.curveControlUI.editOriginalObjects))
column.layout().addWidget(wrap.separator())
# Length Divisions
with wrap.Row(layout, margins=style.scale([0, 0, 3, 0])) as lengthDivisionsRow:
lengthDivision = wrap.ControlSlider(objName='lengthDivisions', typ='int')
lengthDivision.setLabel('L-Div')
lengthDivision.setMinMax(2, 100)
lengthDivision.setFieldMinMax(2, 10000)
lengthDivision.setValue(2)
lengthDivision.setDragCommand(pa(core.sliders.curveControlSliderDrag, lengthDivision))
lengthDivision.setReleaseCommand(core.sliders.release)
dynamicDivisionsToggle = wrap.Button(objName='dynamicDivisions')
dynamicDivisionsToggle.setLabel('Auto')
dynamicDivisionsToggle.setFixedWidth(style.scale(35))
dynamicDivisionsToggle.setButtonStyle('small')
dynamicDivisionsToggle.setCheckable(True)
dynamicDivisionsToggle.clicked.connect(undo(core.toggleDynamicDivisions))
lengthDivisionsRow.layout().addWidget(lengthDivision, 4)
lengthDivisionsRow.layout().addWidget(dynamicDivisionsToggle, 1)
# Width Divisions
widthDivision = wrap.ControlSlider(layout, 'widthDivisions', 'int')
widthDivision.setLabel('W-Div')
widthDivision.setMinMax(2, 31)
widthDivision.setFieldMinMax(2, 10000)
widthDivision.setValue(2)
widthDivision.setDragCommand(pa(core.sliders.curveControlSliderDrag, widthDivision))
widthDivision.setReleaseCommand(core.sliders.release)
# Orientation
orientation = wrap.ControlSlider(layout, 'Orientation', 'float')
orientation.setLabel('Orien')
orientation.setMinMax(-180, 180)
orientation.setFieldMinMax(-36000, 36000)
orientation.setPrecision(1)
orientation.setStep(0.5)
orientation.setDragCommand(pa(core.sliders.curveControlSliderDrag, orientation))
orientation.setReleaseCommand(core.sliders.release)
# Twist
twist = wrap.ControlSlider(layout, 'Twist', 'float')
twist.setLabel('Twist')
twist.setMinMax(-180, 180)
twist.setFieldMinMax(-36000, 36000)
twist.setPrecision(1)
twist.setStep(0.5)
twist.setDragCommand(pa(core.sliders.curveControlSliderDrag, twist))
twist.setReleaseCommand(core.sliders.release)
# Twist
invTwist = wrap.ControlSlider(layout, 'invTwist', 'float')
invTwist.setLabel('Inv.Twist')
invTwist.setMinMax(-180, 180)
invTwist.setFieldMinMax(-36000, 36000)
invTwist.setPrecision(1)
invTwist.setStep(0.5)
invTwist.setDragCommand(pa(core.sliders.curveControlSliderDrag, invTwist))
invTwist.setReleaseCommand(core.sliders.release)
# Twist Curve Graph
with wrap.Frame(layout, 'twistCurveFrame', margins=[0, 1, 0, 2]) as twistCurveFrame:
twistCurveFrame.frameButton.setLabel('Twist Curve Graph')
twistGraph = wrap.FallOffCurve(twistCurveFrame.getFrameLayout(), 'twistCurve')
def twistGraphCommand(_): # BUG: When undoing multiple edits, last edit is not reverted
core.attributes.propagateGraphs(twistGraph)
core.attributes.storeGraphs(twistGraph)
twistGraph.changeCommand(twistGraphCommand)
with wrap.Row(twistCurveFrame.getFrameLayout(), margins=style.scale([5, 0, 5, 2])) as row:
row.setFixedHeight(style.BUTTON_HEIGHT)
magnitude = wrap.FloatField('Magnitude', row.layout())
magnitude.setFixedWidth(style.scale(45))
magnitude.setRange(-99, 99)
magnitude.setStep(0.01)
magnitude.setPrecision(2)
magnitude.setDragCommand(pa(core.sliders.curveControlSliderDrag, magnitude))
magnitude.setReleaseCommand(core.sliders.release)
resetButton = wrap.Button(row.layout(), 'gsTwistGraphResetButton')
resetButton.setLabel('Reset Curve')
def resetTwistCmd():
utils.resetSingleGraph('twist')
core.attributes.storeGraphs(twistGraph)
resetButton.clicked.connect(undo(resetTwistCmd))
popOutButton = wrap.Button(row.layout(), 'gsTwistGraphPopOut')
popOutButton.setFixedWidth(style.scale(56))
popOutButton.setLabel('^')
popOutButton.clicked.connect(self.twistGraphPopOut)
# Width
width = wrap.ControlSlider(layout, 'Width', 'float')
width.setLabel('Width')
width.setMinMax(0.001, 5)
width.setFieldMinMax(0.001, 1000)
width.setPrecision(3)
width.setStep(0.001)
width.setValue(1)
width.setDragCommand(pa(core.sliders.curveControlSliderDrag, width))
width.setReleaseCommand(core.sliders.release)
# Taper
taper = wrap.ControlSlider(layout, 'Taper', 'float')
taper.setLabel('Taper')
taper.setMinMax(0.001, 3)
taper.setFieldMinMax(0.001, 1000)
taper.setPrecision(3)
taper.setStep(0.001)
taper.setValue(1)
taper.setDragCommand(pa(core.sliders.curveControlSliderDrag, taper))
taper.setReleaseCommand(core.sliders.release)
# Width for Tubes
with wrap.Row(layout, objName='widthComboSlider', spacing=0) as row:
with wrap.Column(row.layout()) as column:
widthX = wrap.ControlSlider(column.layout(), "WidthX", 'float')
widthX.setLabel("WidthX")
widthX.setMinMax(0.001, 5)
widthX.setFieldMinMax(0.001, 1000)
widthX.setPrecision(3)
widthX.setStep(0.001)
widthX.setValue(1)
widthX.setDragCommand(pa(core.sliders.curveControlSliderDrag, widthX))
widthX.setReleaseCommand(core.sliders.release)
widthZ = wrap.ControlSlider(column.layout(), "WidthZ", 'float')
widthZ.setLabel("WidthZ")
widthZ.setMinMax(0.001, 5)
widthZ.setFieldMinMax(0.001, 1000)
widthZ.setPrecision(3)
widthZ.setStep(0.001)
widthZ.setValue(1)
widthZ.setDragCommand(pa(core.sliders.curveControlSliderDrag, widthZ))
widthZ.setReleaseCommand(core.sliders.release)
lockButton = wrap.IconCheckButton(row.layout(), 'widthLockSwitch')
lockButton.setIcons(utils.getFolder.icons() + 'sliderLock_en_reversed.png',
utils.getFolder.icons() + 'sliderLock_reversed.png')
lockButton.setIconWidthHeight(10, 30)
lockButton.setChecked(True)
# Width Curve Graph
with wrap.Frame(layout, 'widthCurveFrame', margins=[0, 1, 0, 2]) as widthCurveFrame:
widthCurveFrame.frameButton.setLabel('Width Curve Graph')
widthGraph = wrap.FallOffCurve(widthCurveFrame.getFrameLayout(), 'scaleCurve')
def widthGraphCommand(_): # BUG: When undoing multiple edits, last edit is not reverted
core.attributes.propagateGraphs(widthGraph)
core.attributes.storeGraphs(widthGraph)
widthGraph.changeCommand(widthGraphCommand)
with wrap.Row(widthCurveFrame.getFrameLayout(), margins=style.scale([5, 0, 5, 2])) as row:
row.setFixedHeight(style.BUTTON_HEIGHT)
resetButton = wrap.Button(row.layout(), 'gsWidthGraphResetButton')
resetButton.setLabel('Reset Curve')
def resetWidthCmd():
utils.resetSingleGraph('scale')
core.attributes.storeGraphs(widthGraph)
resetButton.clicked.connect(undo(resetWidthCmd))
popOutButton = wrap.Button(row.layout(), 'gsWidthGraphPopOut')
popOutButton.setFixedWidth(style.scale(56))
popOutButton.setLabel('^')
popOutButton.clicked.connect(self.widthGraphPopOut)
# Length Unlock Switch
lengthUnlock = wrap.Button(layout, 'LengthLock')
lengthUnlock.setLabel('Length Unlock', lineHeight=100)
lengthUnlock.setCheckable(True)
lengthUnlock.setButtonStyle('small')
lengthUnlock.setFixedWidth(style.scale(106))
lengthUnlock.clicked.connect(pa(core.curveControlCheckBoxes, 2))
# Length
length = wrap.ControlSlider(layout, 'Length', 'float')
length.setLabel('Length')
length.setMinMax(0.001, 3)
length.setFieldMinMax(-1000, 1000)
length.setPrecision(3)
length.setStep(0.001)
length.setValue(1)
length.setDragCommand(pa(core.sliders.curveControlSliderDrag, length))
length.setReleaseCommand(core.sliders.release)
# TODO: Offset card from curve attribute
# Offset
offset = wrap.ControlSlider(layout, 'Offset', 'float')
offset.setLabel('Offset')
offset.setMinMax(-1, 1)
offset.setFieldMinMax(-30, 30)
offset.setStep(0.001)
offset.setValue(1)
offset.setDragCommand(pa(core.sliders.curveControlSliderDrag, offset))
offset.setReleaseCommand(core.sliders.release)
# Profile
profile = wrap.ControlSlider(layout, 'Profile', 'float')
profile.setLabel('Profile')
profile.setMinMax(-2, 2)
profile.setFieldMinMax(-1000, 1000)
profile.setStep(0.001)
profile.setDragCommand(pa(core.sliders.curveControlSliderDrag, profile))
profile.setReleaseCommand(core.sliders.release)
# Profile Curve Graph
with wrap.Frame(layout, 'profileCurveGraph', margins=[0, 1, 0, 2]) as profileCurveFrame:
profileCurveFrame.frameButton.setLabel('Profile Curve Graph')
profileGraph = wrap.FallOffCurve(profileCurveFrame.getFrameLayout(), 'profileCurve', attr=False)
def changeCommand(value):
core.updateLattice(value)
core.equalizeProfileCurve()
core.attributes.storeGraphs(profileGraph)
profileGraph.changeCommand(changeCommand)
profileSmoothingSlider = wrap.ControlSlider(profileCurveFrame.getFrameLayout(), 'profileSmoothing', 'int')
profileSmoothingSlider.setLabel('Smoothing')
profileSmoothingSlider.setMinMax(2, 30)
profileSmoothingSlider.setValue(2)
profileSmoothingSlider.setDragCommand(pa(core.sliders.curveControlSliderDrag, profileSmoothingSlider))
profileSmoothingSlider.setReleaseCommand(core.sliders.release)
with wrap.Row(profileCurveFrame.getFrameLayout(), margins=style.scale([5, 0, 5, 2])) as row:
row.setFixedHeight(style.BUTTON_HEIGHT)
profileMagnitude = wrap.FloatField('profileMagnitude', row.layout())
profileMagnitude.setFixedWidth(style.scale(45))
profileMagnitude.setValue(1)
profileMagnitude.setRange(-2, 2)
profileMagnitude.setStep(0.01)
profileMagnitude.setPrecision(2)
profileMagnitude.setDragCommand(pa(core.sliders.curveControlSliderDrag, profileMagnitude))
profileMagnitude.setReleaseCommand(core.sliders.release)
with wrap.Column(row.layout(), spacing=0) as eqColumn:
eqColumn.setFixedHeight(style.scale(24))
with wrap.Row(eqColumn.layout(), spacing=0) as eqRow:
def toggleEq():
WIDGETS['equalizeCurveButton'].setDisabled(
WIDGETS['autoEqualizeSwitchOn'].isChecked()
)
autoEqualizeGroup = QtWidgets.QButtonGroup(eqRow.layout())
autoEqualizeGroup.buttonClicked.connect(toggleEq)
autoEqualizeGroup.buttonClicked.connect(undo(core.equalizeProfileCurve))
autoEqualize = wrap.Button(eqRow.layout(), 'autoEqualizeSwitchOn')
autoEqualize.setLabel('Auto', lineHeight=100)
autoEqualize.setLabelStyle('small')
autoEqualize.setButtonStyle('small-compound-top-left')
autoEqualize.setCheckable(True)
autoEqualize.setChecked(True)
autoEqualizeOff = wrap.Button(eqRow.layout(), 'autoEqualizeSwitchOff')
autoEqualizeOff.setLabel('Manual', lineHeight=100)
autoEqualizeOff.setLabelStyle('small')
autoEqualizeOff.setButtonStyle('small-compound-top-right')
autoEqualizeOff.setCheckable(True)
autoEqualizeGroup.addButton(autoEqualize)
autoEqualizeGroup.addButton(autoEqualizeOff)
equalizeProfileCurve = wrap.Button(eqColumn.layout(), 'equalizeCurveButton')
equalizeProfileCurve.setLabel('Equalize Curve', lineHeight=100)
equalizeProfileCurve.setLabelStyle('small')
equalizeProfileCurve.setButtonStyle('small-filled-compound-bottom')
equalizeProfileCurve.setDisabled(True)
equalizeProfileCurve.clicked.connect(pa(undo(core.equalizeProfileCurve), True))
resetButton = wrap.Button(row.layout(), 'gsResetProfileGraphButton')
resetButton.setLabel('Reset Curve')
def resetButtonClicked(*_):
core.resetProfileCurve()
core.attributes.storeGraphs(profileGraph)
resetButton.clicked.connect(undo(resetButtonClicked))
popOutButton = wrap.Button(row.layout(), 'gsProfileGraphPopOut')
popOutButton.setFixedWidth(style.scale(56))
popOutButton.setLabel('^')
popOutButton.clicked.connect(self.profileGraphPopOut)
# Normals
normals = wrap.ControlSlider(layout, 'surfaceNormals', 'float')
normals.setLabel('Normals')
normals.setMinMax(0, 180)
normals.setPrecision(1)
normals.setValue(180)
normals.setDragCommand(pa(core.sliders.curveControlSliderDrag, normals))
normals.setReleaseCommand(core.sliders.release)
# Reverse Normals Switch
reverseNormals = wrap.Button(layout, 'reverseNormals')
reverseNormals.setLabel('Reverse Normals', lineHeight=100)
reverseNormals.setCheckable(True)
reverseNormals.setButtonStyle('small')
reverseNormals.setFixedWidth(style.scale(106))
reverseNormals.clicked.connect(pa(core.curveControlCheckBoxes, 0))
with wrap.Frame(layout, 'otherFrame', label='Other', margins=[2, 2, 2, 2]) as refineFrame:
samplingAccuracy = wrap.ControlSlider(parent=refineFrame.getFrameLayout(), objName='samplingAccuracy', typ='float')
samplingAccuracy.setLabel('SamplAcc')
samplingAccuracy.setMinMax(0.001, 2)
samplingAccuracy.setStep(0.01)
samplingAccuracy.setValue(0.33)
samplingAccuracy.setDragCommand(pa(core.sliders.curveControlSliderDrag, samplingAccuracy))
samplingAccuracy.setReleaseCommand(core.sliders.release)
# Refine
with wrap.Row(refineFrame.getFrameLayout(), margins=style.scale([0, 0, 3, 0])) as curveRefineRow:
refine = wrap.ControlSlider(layout, 'curveRefine', 'int')
refine.setLabel('Refine')
refine.setMinMax(0, 100)
refine.setFieldMinMax(0, 10000)
refine.setValue(20)
refine.setDragCommand(pa(core.sliders.curveControlSliderDrag, refine))
refine.setReleaseCommand(core.sliders.release)
autoRefineToggle = wrap.Button(objName='autoRefine')
autoRefineToggle.setLabel('Auto')
autoRefineToggle.setFixedWidth(style.scale(35))
autoRefineToggle.setButtonStyle('small')
autoRefineToggle.setCheckable(True)
autoRefineToggle.clicked.connect(undo(core.toggleAutoRefine))
curveRefineRow.layout().addWidget(refine, 4)
curveRefineRow.layout().addWidget(autoRefineToggle, 1)
# Smooth
smooth = wrap.ControlSlider(refineFrame.getFrameLayout(), 'curveSmooth', 'float')
smooth.setLabel('Smooth')
smooth.setMinMax(0, 10)
smooth.setDragCommand(pa(core.sliders.curveControlSliderDrag, smooth))
smooth.setReleaseCommand(core.sliders.release)
with wrap.Frame(layout, 'orientToNormalsFrame', label='Orient to Normals',
margins=[2, 2, 2, 2]) as orientFrame:
orientFrame.setVisible(False)
def selectMesh():
sel = mc.filterExpand(mc.ls(sl=1, l=1), sm=12)
if not sel:
sel = mc.ls(hl=1, o=1, l=1)
if not sel:
MESSAGE.warningInView('Select compatible mesh.')
return
self.meshName.setText(sel[0])
with wrap.Row(orientFrame.getFrameLayout()) as row:
selectMeshBtn = wrap.Button(row.layout(), "gsOrientToNormalsSelectTarget")
selectMeshBtn.setFixedWidth(style.scale(100))
selectMeshBtn.setLabel('Select Target')
selectMeshBtn.clicked.connect(selectMesh)
self.meshName = wrap.LineEdit('gsOrientMeshName', row.layout())
self.meshName.setPlaceholderText('Select or Type Target Mesh')
self.meshName.setClearButtonEnabled(True)
orientFrame.getFrameLayout().addWidget(wrap.separator())
with wrap.Row(orientFrame.getFrameLayout()) as row:
iterationsSlider = wrap.ControlSlider(row.layout(), 'gsIterationsSlider', 'int')
iterationsSlider.setMinMax(1, 100)
iterationsSlider.setValue(10)
iterationsSlider.setLabel('Iterations')
autoRefreshButton = wrap.Button(row.layout(), 'orientRefreshViewport')
autoRefreshButton.setButtonStyle('small')
autoRefreshButton.setCheckable(True)
autoRefreshButton.setChecked(True)
autoRefreshButton.setWidthHeight(w=style.scale(50))
autoRefreshButton.setLabel('Refresh VP', lineHeight=100)
with wrap.Row(orientFrame.getFrameLayout()) as row:
minAngleSlider = wrap.ControlSlider(row.layout(), 'gsMinimumAngle', 'float')
minAngleSlider.setMinMax(0.1, 90)
minAngleSlider.setValue(1)
minAngleSlider.setLabel('Min Angle')
orientFrame.getFrameLayout().addWidget(wrap.separator())
with wrap.Row(orientFrame.getFrameLayout()) as row:
orient = wrap.Button(row.layout(), 'gsOrientToNormals')
orient.setLabel('Orient')
orient.clicked.connect(undo(core.orientToFaceNormals))
with wrap.Frame(layout, 'solidifyFrame', label='Solidify Controls', margins=[2, 2, 2, 2]) as solidifyFrame:
# Solidify Activate
solidify = wrap.Button(solidifyFrame.getFrameLayout(), 'solidify')
solidify.setLabel('Solidify', lineHeight=100)
solidify.setCheckable(True)
solidify.setButtonStyle('small')
solidify.setFixedWidth(style.scale(106))
solidify.clicked.connect(pa(core.curveControlCheckBoxes, 1))
# Thickness
thickness = wrap.ControlSlider(solidifyFrame.getFrameLayout(), 'solidifyThickness', 'float')
thickness.setLabel('Thickness')
thickness.setMinMax(0.001, 5)
thickness.setFieldMinMax(-100, 100)
thickness.setValue(0.25)
thickness.setStep(0.01)
thickness.setDragCommand(pa(core.sliders.curveControlSliderDrag, thickness))
thickness.setReleaseCommand(core.sliders.release)
# Divisions
divisions = wrap.ControlSlider(solidifyFrame.getFrameLayout(), 'solidifyDivisions', 'int')
divisions.setLabel('Divisions')
divisions.setMinMax(0, 10)
divisions.setFieldMinMax(0, 100)
divisions.setDragCommand(pa(core.sliders.curveControlSliderDrag, divisions))
divisions.setReleaseCommand(core.sliders.release)
# ScaleX
solidifyScaleX = wrap.ControlSlider(solidifyFrame.getFrameLayout(), 'solidifyScaleX', 'float')
solidifyScaleX.setLabel('ScaleX')
solidifyScaleX.setMinMax(-10, 10)
solidifyScaleX.setFieldMinMax(-100, 100)
solidifyScaleX.setDragCommand(pa(core.sliders.curveControlSliderDrag, solidifyScaleX))
solidifyScaleX.setReleaseCommand(core.sliders.release)
# ScaleY
solidifyScaleY = wrap.ControlSlider(solidifyFrame.getFrameLayout(), 'solidifyScaleY', 'float')
solidifyScaleY.setLabel('ScaleY')
solidifyScaleY.setMinMax(-10, 10)
solidifyScaleY.setFieldMinMax(-100, 100)
solidifyScaleY.setDragCommand(pa(core.sliders.curveControlSliderDrag, solidifyScaleY))
solidifyScaleY.setReleaseCommand(core.sliders.release)
# Offset
offset = wrap.ControlSlider(solidifyFrame.getFrameLayout(), 'solidifyOffset', 'float')
offset.setLabel('Offset')
offset.setMinMax(-10, 10)
offset.setFieldMinMax(-100, 100)
offset.setDragCommand(pa(core.sliders.curveControlSliderDrag, offset))
offset.setReleaseCommand(core.sliders.release)
# Normals
solidifyNormals = wrap.ControlSlider(solidifyFrame.getFrameLayout(), 'solidifyNormals', 'float')
solidifyNormals.setLabel('SNormals')
solidifyNormals.setMinMax(0, 180)
solidifyNormals.setPrecision(1)
solidifyNormals.setValue(180)
solidifyNormals.setDragCommand(pa(core.sliders.curveControlSliderDrag, solidifyNormals))
solidifyNormals.setReleaseCommand(core.sliders.release)
with wrap.Frame(layout, 'UVFrame', label='UV Controls', margins=[2, 2, 2, 2]) as UVFrame:
flipUV = wrap.Button(UVFrame.getFrameLayout(), 'flipUV')
flipUV.setLabel('H-Flip UV', lineHeight=100)
flipUV.setCheckable(True)
flipUV.setButtonStyle('small')
flipUV.setFixedWidth(style.scale(106))
flipUV.clicked.connect(pa(undo(core.curveControlCheckBoxes), 3))
# Move U
moveU = wrap.ControlSlider(UVFrame.getFrameLayout(), 'moveU', 'float')
moveU.setLabel('MoveU')
moveU.setMinMax(-0.5, 0.5)
moveU.setStep(0.001)
moveU.setFieldMinMax(-100, 100)
moveU.setDragCommand(pa(core.sliders.curveControlSliderDrag, moveU))
moveU.setReleaseCommand(core.sliders.release)
# Move V
moveV = wrap.ControlSlider(UVFrame.getFrameLayout(), 'moveV', 'float')
moveV.setLabel('MoveV')
moveV.setMinMax(-0.5, 0.5)
moveV.setStep(0.001)
moveV.setFieldMinMax(-100, 100)
moveV.setDragCommand(pa(core.sliders.curveControlSliderDrag, moveV))
moveV.setReleaseCommand(core.sliders.release)
# Scale U
scaleU = wrap.ControlSlider(UVFrame.getFrameLayout(), 'scaleU', 'float')
scaleU.setLabel('ScaleU')
scaleU.setMinMax(0.001, 1.999)
scaleU.setFieldMinMax(0, 100)
scaleU.setStep(0.001)
scaleU.setValue(1)
scaleU.setDragCommand(pa(core.sliders.curveControlSliderDrag, scaleU))
scaleU.setReleaseCommand(core.sliders.release)
# Scale V
scaleV = wrap.ControlSlider(UVFrame.getFrameLayout(), 'scaleV', 'float')
scaleV.setLabel('ScaleV')
scaleV.setMinMax(0.001, 1.999)
scaleV.setFieldMinMax(0, 100)
scaleV.setStep(0.001)
scaleV.setValue(1)
scaleV.setDragCommand(pa(core.sliders.curveControlSliderDrag, scaleV))
scaleV.setReleaseCommand(core.sliders.release)
# Rotate UV
rotateUV = wrap.ControlSlider(UVFrame.getFrameLayout(), 'rotateUV', 'float')
rotateUV.setLabel('RotUV')
rotateUV.setMinMax(-180, 180)
rotateUV.setFieldMinMax(-3600, 3600)
rotateUV.setPrecision(2)
rotateUV.setDragCommand(pa(core.sliders.curveControlSliderDrag, rotateUV))
rotateUV.setReleaseCommand(core.sliders.release)
# Rotate UV Root (Legacy)
rotateUVRoot = wrap.ControlSlider(UVFrame.getFrameLayout(), 'rotateRootUV', 'float')
rotateUVRoot.setLabel('RotRtUV')
rotateUVRoot.setMinMax(-180, 180)
rotateUVRoot.setFieldMinMax(-3600, 3600)
rotateUVRoot.setPrecision(2)
rotateUVRoot.setDragCommand(pa(core.sliders.curveControlSliderDrag, rotateUVRoot))
rotateUVRoot.setReleaseCommand(core.sliders.release)
rotateUVRoot.setVisible(False)
# Rotate Tip UV (Legacy)
rotateUVTip = wrap.ControlSlider(UVFrame.getFrameLayout(), 'rotateTipUV', 'float')
rotateUVTip.setLabel('RotTipUV')
rotateUVTip.setMinMax(-180, 180)
rotateUVTip.setFieldMinMax(-3600, 3600)
rotateUVTip.setPrecision(2)
rotateUVTip.setDragCommand(pa(core.sliders.curveControlSliderDrag, rotateUVTip))
rotateUVTip.setReleaseCommand(core.sliders.release)
rotateUVRoot.setVisible(False)
# UV Bug Message
if MAYA_VER in [2020, 2022] and not mc.optionVar(q='GSCT_UVBugMessageDismissed'):
with wrap.Row(UVFrame.getFrameLayout()) as row:
label = wrap.Label(row.layout())
label.setLabel('<p style="color:#FF542F">How To Fix Maya 2020-2022 UV Bug:</p>')
linkButton = wrap.Button(row.layout())
linkButton.setLabel('Open Fix')
linkButton.setButtonStyle('small-filled')
linkButton.clicked.connect(lambda: utils.openLink(
'https://gs-curvetools.readthedocs.io/en/latest/faq.html#maya-2020-2022-and-broken-uvs'))
dismissMessage = wrap.Button(row.layout())
dismissMessage.setLabel('Dismiss')
dismissMessage.setButtonStyle('small-filled')
dismissMessage.clicked.connect(lambda: row.setHidden(True))
dismissMessage.clicked.connect(lambda: mc.optionVar(iv=['GSCT_UVBugMessageDismissed', 1]))
# Advanced Visibility Frame
with wrap.Frame(layout, 'advancedVisibilityFrame', label='Advanced Visibility',
margins=style.scale([3, 2, 3, 2]), spacing=style.scale(3)) as visibilityFrame:
with wrap.Row(visibilityFrame.getFrameLayout()) as row:
geometryHighlight = wrap.Button(row.layout(), 'geometryHighlight')
geometryHighlight.setLabel('Geometry Highlight', lineHeight=100)
geometryHighlight.setCheckable(True)
geometryHighlight.setChecked(bool(mc.optionVar(q="GSCT_GeometryHighlightEnabled")))
geometryHighlight.setButtonStyle('small')
geometryHighlight.clicked.connect(noUndo(core.advancedVisibility.geometryHighlightCommand))
curveHighlight = wrap.Button(row.layout(), 'curveHighlight')
curveHighlight.setLabel('Curve Highlight', lineHeight=100)
curveHighlight.setCheckable(True)
curveHighlight.setButtonStyle('small')
curveHighlight.setChecked(False)
curveHighlight.clicked.connect(undo(core.advancedVisibility.toggleCurveHighlightFromUI))
visibilityFrame.getFrameLayout().addWidget(wrap.separator())
def sliderChangeCommand(*_):
core.advancedVisibility.applySettingsToNode()
core.advancedVisibility.saveSettingsFromUI()
with wrap.Column(visibilityFrame.getFrameLayout(), objName='gsCurveHighlightFrame', spacing=style.scale(4)) as column:
column.setEnabled(False) # Disable immediately. We are going to check its state later.
# CV Size
with wrap.Row(column.layout(), spacing=4) as row:
CVsizeLabel = wrap.Label()
CVsizeLabel.setLabel("CV Size:")
CVsizeLabel.setFixedWidth(style.scale(100))
CVsizeLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
pointSizeSlider = wrap.mayaSlider(
mc.floatSliderGrp(
'gsPointSizeSlider',
f=1, adj=2, w=1, cw=[1, 45], min=1, max=100, v=10,
dc=lambda _: noUndo(core.advancedVisibility.applySettingsToNode)(),
cc=noUndo(sliderChangeCommand),
)
)
WIDGETS['gsPointSizeSlider'] = pointSizeSlider
row.layout().addWidget(CVsizeLabel, 0)
row.layout().addWidget(pointSizeSlider, 1)
# Selected Color
with wrap.Row(column.layout(), spacing=style.scale(4)) as row:
selectedColorLabel = wrap.Label()
selectedColorLabel.setLabel("Selected Color:")
selectedColorLabel.setFixedWidth(style.scale(100))
selectedColorLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
selectedColorPicker = wrap.ColorPicker("gsSelectedCVColor")
selectedColorPicker.connectDragCommand(lambda *_: noUndo(core.advancedVisibility.applySettingsToNode)())
selectedColorPicker.connectCommand(noUndo(sliderChangeCommand))
selectedAlphaValue = wrap.FloatField("gsSelectedCVAlpha")
selectedAlphaValue.setFixedWidth(style.scale(45))
selectedAlphaValue.setValue(1.0)
selectedAlphaValue.setRange(0, 1)
selectedAlphaValue.setStep(0.01)
selectedAlphaValue.setPrecision(2)
selectedAlphaValue.setDragCommand(lambda *_: noUndo(core.advancedVisibility.applySettingsToNode)())
selectedAlphaValue.setReleaseCommand(noUndo(sliderChangeCommand))
row.layout().addWidget(selectedColorLabel, 0)
row.layout().addWidget(selectedColorPicker, 1)
row.layout().addWidget(selectedAlphaValue, 0)
# Deselected Color
with wrap.Row(column.layout(), spacing=style.scale(4)) as row:
deselectedColorLabel = wrap.Label()
deselectedColorLabel.setLabel("Deselected Color:")
deselectedColorLabel.setFixedWidth(style.scale(100))
deselectedColorLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
deselectedColorPicker = wrap.ColorPicker("gsDeselectedCVColor")
deselectedColorPicker.connectDragCommand(lambda *_: noUndo(core.advancedVisibility.applySettingsToNode)())
deselectedColorPicker.connectCommand(noUndo(sliderChangeCommand))
deselectedAlphaValue = wrap.FloatField("gsDeselectedCVAlpha")
deselectedAlphaValue.setFixedWidth(style.scale(45))
deselectedAlphaValue.setValue(1)
deselectedAlphaValue.setRange(0, 1)
deselectedAlphaValue.setStep(0.01)
deselectedAlphaValue.setPrecision(2)
deselectedAlphaValue.setDragCommand(lambda *_: noUndo(core.advancedVisibility.applySettingsToNode)())
deselectedAlphaValue.setReleaseCommand(noUndo(sliderChangeCommand))
row.layout().addWidget(deselectedColorLabel, 0)
row.layout().addWidget(deselectedColorPicker, 1)
row.layout().addWidget(deselectedAlphaValue, 1)
column.layout().addWidget(wrap.separator())
# Curve Visibility
curveVisibility = wrap.Button(column.layout(), 'curveVisibility')
curveVisibility.setLabel('Curve Visibility', lineHeight=100)
curveVisibility.setCheckable(True)
curveVisibility.setButtonStyle('small')
curveVisibility.setChecked(True)
curveVisibility.clicked.connect(noUndo(sliderChangeCommand))
with wrap.Row(column.layout(), spacing=4) as row:
curveWidthLabel = wrap.Label()
curveWidthLabel.setLabel("Curve Width:")
curveWidthLabel.setFixedWidth(style.scale(100))
curveWidthLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
curveWidthSlider = wrap.mayaSlider(
mc.floatSliderGrp(
'gsCurveWidthSlider',
f=1, adj=2, w=1, cw=[1, 45], min=1, max=100, v=4,
dc=lambda _: noUndo(core.advancedVisibility.applySettingsToNode)(),
cc=noUndo(sliderChangeCommand),
),
)
WIDGETS['gsCurveWidthSlider'] = curveWidthSlider
row.layout().addWidget(curveWidthLabel, 0)
row.layout().addWidget(curveWidthSlider, 1)
with wrap.Row(column.layout(), spacing=style.scale(4)) as row:
curveHighlightColorLabel = wrap.Label()
curveHighlightColorLabel.setLabel("Curve Color:")
curveHighlightColorLabel.setFixedWidth(style.scale(100))
curveHighlightColorLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
curveHighlightColor = wrap.ColorPicker("gsCurveHighlightColor")
curveHighlightColor.connectDragCommand(lambda *_: noUndo(core.advancedVisibility.applySettingsToNode)())
curveHighlightColor.connectCommand(noUndo(sliderChangeCommand))
curveHighlightAlpha = wrap.FloatField("gsCurveHighlightAlpha")
curveHighlightAlpha.setFixedWidth(style.scale(45))
curveHighlightAlpha.setValue(1.0)
curveHighlightAlpha.setRange(0, 1)
curveHighlightAlpha.setStep(0.01)
curveHighlightAlpha.setPrecision(2)
curveHighlightAlpha.setDragCommand(lambda *_: noUndo(core.advancedVisibility.applySettingsToNode)())
curveHighlightAlpha.setReleaseCommand(noUndo(sliderChangeCommand))
row.layout().addWidget(curveHighlightColorLabel, 0)
row.layout().addWidget(curveHighlightColor, 1)
row.layout().addWidget(curveHighlightAlpha, 1)
column.layout().addWidget(wrap.separator())
# Hull Visibility
hullVisibility = wrap.Button(column.layout(), 'hullVisibility')
hullVisibility.setLabel('Hull Visibility', lineHeight=100)
hullVisibility.setCheckable(True)
hullVisibility.setButtonStyle('small')
hullVisibility.clicked.connect(noUndo(sliderChangeCommand))
with wrap.Row(column.layout(), spacing=4) as row:
hullWidthLabel = wrap.Label()
hullWidthLabel.setLabel("Hull Width:")
hullWidthLabel.setFixedWidth(style.scale(100))
hullWidthLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
hullWidthSlider = wrap.mayaSlider(
mc.floatSliderGrp(
'gsHullWidthSlider',
f=1, adj=2, w=1, cw=[1, 45], min=1, max=100, v=3,
dc=lambda _: noUndo(core.advancedVisibility.applySettingsToNode)(),
cc=noUndo(sliderChangeCommand),
)
)
WIDGETS['gsHullWidthSlider'] = hullWidthSlider
row.layout().addWidget(hullWidthLabel, 0)
row.layout().addWidget(hullWidthSlider, 1)
with wrap.Row(column.layout(), spacing=style.scale(4)) as row:
hullColorLabel = wrap.Label()
hullColorLabel.setLabel("Hull Color:")
hullColorLabel.setFixedWidth(style.scale(100))
hullColorLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
hullColor = wrap.ColorPicker("gsHullHighlightColor")
hullColor.connectDragCommand(lambda *_: noUndo(core.advancedVisibility.applySettingsToNode)())
hullColor.connectCommand(noUndo(sliderChangeCommand))
hullAlpha = wrap.FloatField("gsHullHighlightAlpha")
hullAlpha.setFixedWidth(style.scale(45))
hullAlpha.setValue(1.0)
hullAlpha.setRange(0, 1)
hullAlpha.setStep(0.01)
hullAlpha.setPrecision(2)
hullAlpha.setDragCommand(lambda *_: noUndo(core.advancedVisibility.applySettingsToNode)())
hullAlpha.setReleaseCommand(noUndo(sliderChangeCommand))
row.layout().addWidget(hullColorLabel, 0)
row.layout().addWidget(hullColor, 1)
row.layout().addWidget(hullAlpha, 1)
column.layout().addWidget(wrap.separator())
with wrap.Frame(column.layout(), 'advancedVisibilityFrame', label='Other Options:',
margins=style.scale([3, 2, 3, 2]), spacing=style.scale(3)) as optionsFrame:
with wrap.Row(optionsFrame.getFrameLayout()) as row:
lazyUpdate = wrap.Button(row.layout(), 'lazyUpdate')
lazyUpdate.setLabel("Lazy Update", lineHeight=100)
lazyUpdate.setCheckable(True)
lazyUpdate.setButtonStyle('small')
lazyUpdate.clicked.connect(noUndo(sliderChangeCommand))
alwaysOnTop = wrap.Button(row.layout(), 'alwaysOnTop')
alwaysOnTop.setLabel("Always On Top", lineHeight=100)
alwaysOnTop.setCheckable(True)
alwaysOnTop.setButtonStyle('small')
alwaysOnTop.setChecked(True)
alwaysOnTop.clicked.connect(noUndo(sliderChangeCommand))
optionsFrame.getFrameLayout().addWidget(wrap.separator())
experimentalLabel = wrap.Label(optionsFrame.getFrameLayout())
experimentalLabel.setLabel("Distance Colors:")
with wrap.Row(optionsFrame.getFrameLayout()) as row:
curveDistanceColor = wrap.Button(row.layout(), 'curveDistanceColor')
curveDistanceColor.setLabel("Curve", lineHeight=100)
curveDistanceColor.setCheckable(True)
curveDistanceColor.setButtonStyle('small')
curveDistanceColor.setChecked(True)
curveDistanceColor.clicked.connect(noUndo(sliderChangeCommand))
cvDistanceColor = wrap.Button(row.layout(), 'cvDistanceColor')
cvDistanceColor.setLabel("CV", lineHeight=100)
cvDistanceColor.setCheckable(True)
cvDistanceColor.setButtonStyle('small')
cvDistanceColor.setChecked(True)
cvDistanceColor.clicked.connect(noUndo(sliderChangeCommand))
hullDistanceColor = wrap.Button(row.layout(), 'hullDistanceColor')
hullDistanceColor.setLabel("Hull", lineHeight=100)
hullDistanceColor.setCheckable(True)
hullDistanceColor.setButtonStyle('small')
hullDistanceColor.setChecked(True)
hullDistanceColor.clicked.connect(noUndo(sliderChangeCommand))
with wrap.Row(optionsFrame.getFrameLayout()) as row:
distanceColorMinLabel = wrap.Label()
distanceColorMinLabel.setLabel("Color Min:")
distanceColorMinLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
distanceColorMinInput = wrap.FloatField("gsDistanceColorMinValue")
distanceColorMinInput.setValue(0.25)
distanceColorMinInput.setRange(0.01, 1)
distanceColorMinInput.setStep(0.01)
distanceColorMinInput.setPrecision(2)
distanceColorMinInput.setDragCommand(lambda *_: noUndo(core.advancedVisibility.applySettingsToNode)())
distanceColorMinInput.setReleaseCommand(noUndo(sliderChangeCommand))
distanceColorMaxLabel = wrap.Label()
distanceColorMaxLabel.setLabel("Color Max:")
distanceColorMaxLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
distanceColorMaxInput = wrap.FloatField("gsDistanceColorMaxValue")
distanceColorMaxInput.setValue(1.0)
distanceColorMaxInput.setRange(0.01, 1)
distanceColorMaxInput.setStep(0.01)
distanceColorMaxInput.setPrecision(2)
distanceColorMaxInput.setDragCommand(lambda *_: noUndo(core.advancedVisibility.applySettingsToNode)())
distanceColorMaxInput.setReleaseCommand(noUndo(sliderChangeCommand))
row.layout().addWidget(distanceColorMinLabel, 1)
row.layout().addWidget(distanceColorMinInput, 1)
row.layout().addWidget(distanceColorMaxLabel, 1)
row.layout().addWidget(distanceColorMaxInput, 1)
optionsFrame.getFrameLayout().addWidget(wrap.separator())
experimentalLabel = wrap.Label(optionsFrame.getFrameLayout())
experimentalLabel.setLabel("Experimental (possibly slow):")
CVocclusion = wrap.Button(optionsFrame.getFrameLayout(), 'CVocclusion')
CVocclusion.setLabel("Enable CV Occlusion", lineHeight=100)
CVocclusion.setCheckable(True)
CVocclusion.setButtonStyle('small')
CVocclusion.clicked.connect(noUndo(sliderChangeCommand))
with wrap.Row(optionsFrame.getFrameLayout(), spacing=style.scale(4)) as row:
selectOccluderButton = wrap.Button(row.layout(), "gsSelectOccluderButton")
selectOccluderButton.setFixedWidth(style.scale(100))
selectOccluderButton.setLabel('Select Occluder')
selectOccluderButton.clicked.connect(noUndo(core.advancedVisibility.selectOccluderFromScene))
occluderMeshName = wrap.LineEdit('gsOccluderMeshName', row.layout())
occluderMeshName.setPlaceholderText('Select or Type Occluder Mesh Name')
occluderMeshName.setClearButtonEnabled(True)
occluderMeshName.editingFinished.connect(noUndo(sliderChangeCommand))
core.advancedVisibility.loadSettingsFromOptionVar()
tooltips.toggleCustomTooltipsCurveControl(core.getOption('enableTooltips'))
layout.addWidget(wrap.separator())
resetButton = wrap.Button(layout, 'resetControlSliders')
resetButton.setLabel('Reset Sliders Range')
resetButton.clicked.connect(core.resetControlSliders)
def twistGraphPopOut(self):
name = "GSCT_TwistGraphPopOut"
if mc.workspaceControl(name, q=1, ex=1):
mc.deleteUI(name)
popOut = CreatePopOut(name, "Twist Graph Large", 512, 400)
graph = wrap.FallOffCurve(popOut.widgetLayout, 'twistCurve_large')
def twistGraphCommand(_):
core.attributes.propagateGraphs(graph)
core.attributes.storeGraphs(graph)
graph.changeCommand(twistGraphCommand)
with wrap.Row(popOut.widgetLayout, margins=style.scale([5, 0, 5, 2])) as row:
row.setFixedHeight(style.BUTTON_HEIGHT)
magnitude = wrap.FloatField('Magnitude_large', row.layout(), attrName='Magnitude')
magnitude.setFixedWidth(style.scale(45))
magnitude.setRange(-99, 99)
magnitude.setStep(0.01)
magnitude.setPrecision(2)
magnitude.setDragCommand(pa(core.sliders.curveControlSliderDrag, magnitude))
magnitude.setReleaseCommand(core.sliders.release)
resetButton = wrap.Button(row.layout())
resetButton.setLabel('Reset Curve')
def resetTwist():
utils.resetSingleGraph('twist')
core.attributes.storeGraphs(graph)
resetButton.clicked.connect(undo(resetTwist))
core.curveControlUI.updateUI()
def widthGraphPopOut(self):
name = "GSCT_WidthGraphPopOut"
if mc.workspaceControl(name, q=1, ex=1):
mc.deleteUI(name)
popOut = CreatePopOut(name, "Width Graph Large", 512, 400)
graph = wrap.FallOffCurve(popOut.widgetLayout, 'scaleCurve_large')
def widthGraphCommand(_):
core.attributes.propagateGraphs(graph)
core.attributes.storeGraphs(graph)
graph.changeCommand(widthGraphCommand)
with wrap.Row(popOut.widgetLayout, margins=style.scale([5, 0, 5, 2])) as row:
row.setFixedHeight(style.BUTTON_HEIGHT)
resetButton = wrap.Button(row.layout())
resetButton.setLabel('Reset Curve')
def resetWidthCmd():
utils.resetSingleGraph('width')
core.attributes.storeGraphs(graph)
resetButton.clicked.connect(undo(resetWidthCmd))
core.curveControlUI.updateUI()
def profileGraphPopOut(self):
name = "GSCT_ProfileGraphPopOut"
if mc.workspaceControl(name, q=1, ex=1):
mc.deleteUI(name)
popOut = CreatePopOut(name, "Profile Graph Large", 512, 400)
graph = wrap.FallOffCurve(popOut.widgetLayout, 'profileCurve_large', attr=False)
def changeCommand(value):
core.updateLattice(value)
core.equalizeProfileCurve()
graph.changeCommand(changeCommand)
with wrap.Row(popOut.widgetLayout, margins=style.scale([5, 0, 5, 2])) as row:
row.setFixedHeight(style.BUTTON_HEIGHT)
resetButton = wrap.Button(row.layout())
resetButton.setLabel('Reset Curve')
resetButton.clicked.connect(undo(core.resetProfileCurve))
core.curveControlUI.updateUI()
# UV Editor Window
def uvEditorWorkspace():
global uveditor
if mc.workspaceControl(UV_EDITOR_NAME, q=1, ex=1):
if MAYA_VER >= 2018:
if not mc.workspaceControl(UV_EDITOR_NAME, q=1, vis=1):
mc.workspaceControl(UV_EDITOR_NAME, e=1, rs=1)
else:
mc.workspaceControl(UV_EDITOR_NAME, e=1, vis=0)
try:
uveditor.updateEditor() # pylint: disable=used-before-assignment
except Exception as e:
LOGGER.exception(e)
else:
mc.workspaceControl(UV_EDITOR_NAME, e=1, fl=1)
mc.deleteUI(UV_EDITOR_NAME)
else:
uveditor = UVEditor('uveditor')
uveditor.init()
uveditor.updateEditor()
from . import main
main.checkScriptJobs(UV_EDITOR_NAME)
class UVEditor(QtWidgets.QWidget):
def __init__(self, name):
super(UVEditor, self).__init__()
self.name = name
self.timer = utils.Timer()
self.mouseToggle = False
self.previousSelection = []
self.uvUpdateCheck = 0
self.isolateMode = False
self.currentSelection = []
def init(self):
if mc.workspaceControl(UV_EDITOR_NAME, q=1, ex=1):
mc.deleteUI(UV_EDITOR_NAME)
parent = mayaWorkspaceControl(name=UV_EDITOR_NAME,
label=UV_EDITOR_LABEL,
retain=False, iw=705, ih=575,
widthProperty="free")
self.setParent(parent)
parent.layout().addWidget(self)
self.window()
self.editor.signal_keyPress.connect(self.updateButtons)
self.editor.signal_mouseMove.connect(self._updateCurves)
self.editor.signal_mouseRelease.connect(self._stopCurvesUpdate)
self.editor.signal_uvDrawEnd.connect(self.manualCurveUpdate)
self.editor.signal_functionKeyPress.connect(undo(self.functionSwitch))
self.uvList.signal_keyPressed.connect(self.updateVisibility)
def window(self):
# Layout
mainLayout = QtWidgets.QVBoxLayout(self)
mainLayout.setContentsMargins(*style.scale([2, 2, 2, 2]))
self.scrollWidget = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout(self.scrollWidget)
scrollArea = QtWidgets.QScrollArea()
scrollArea.setWidget(self.scrollWidget)
mainLayout.addWidget(scrollArea)
# Layout Settings
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(style.scale(2))
layout.setMargin(0)
layout.setAlignment(QtCore.Qt.AlignTop)
scrollArea.setFrameShape(QtWidgets.QFrame.NoFrame)
scrollArea.setWidgetResizable(True)
# Editor Init
self.editor = uv_editor.Editor()
self.editor.init()
self.updateColors()
# Main Widgets
with wrap.Row(layout) as mainRow:
with wrap.Column(mainRow.layout()) as mainColumn:
mainColumn.layout().setAlignment(QtCore.Qt.AlignTop)
mainColumn.setFixedWidth(style.scale(130))
# Controller switches
mainColumn.layout().addWidget(wrap.separator())
controllerLabel = wrap.Label(mainColumn.layout())
controllerLabel.setLabel('Controller Mode')
self.controllerGroup = QtWidgets.QButtonGroup(mainColumn.layout())
self.controllerGroup.buttonReleased.connect(self.updateControllerMode)
with wrap.Row(mainColumn.layout()) as selectMove:
select = wrap.Button(selectMove.layout(), 'gsUVSelect')
select.setCheckable(True)
select.setChecked(True)
select.setLabel("Select (Q)")
move = wrap.Button(selectMove.layout(), 'gsUVMove')
move.setCheckable(True)
move.setLabel("Move (W)")
with wrap.Row(mainColumn.layout()) as rotateScale:
rotate = wrap.Button(rotateScale.layout(), 'gsUVRotate')
rotate.setCheckable(True)
rotate.setLabel("Rotate (E)")
scale = wrap.Button(rotateScale.layout(), 'gsUVScale')
scale.setCheckable(True)
scale.setLabel("Scale (R)")
with wrap.Row(mainColumn.layout()) as scaleRow:
self.directionSwitch = QtWidgets.QButtonGroup(scaleRow.layout())
self.directionSwitch.buttonReleased.connect(self.updateControllerMode)
horizontal = wrap.Button(scaleRow.layout(), 'gsUVHorizontalScale')
horizontal.setLabel('H')
horizontal.setButtonStyle('small')
horizontal.setCheckable(True)
horizontal.setChecked(True)
vertical = wrap.Button(scaleRow.layout(), 'gsUVVerticalScale')
vertical.setButtonStyle('small')
vertical.setCheckable(True)
vertical.setLabel('V')
self.directionSwitch.addButton(horizontal, 0)
self.directionSwitch.addButton(vertical, 1)
drawUV = wrap.Button(mainColumn.layout(), 'gsDrawUVs')
drawUV.setCheckable(True)
drawUV.setLabel('Draw (D)')
self.controllerGroup.addButton(select, 0)
self.controllerGroup.addButton(move, 1)
self.controllerGroup.addButton(rotate, 2)
self.controllerGroup.addButton(scale, 3)
self.controllerGroup.addButton(drawUV, 4)
mainColumn.layout().addWidget(wrap.separator())
# Utility Functions
utilityLabel = wrap.Label(mainColumn.layout())
utilityLabel.setLabel('Utility Functions')
with wrap.Row(mainColumn.layout()) as HVFlip:
hFlipUV = wrap.Button(HVFlip.layout(), 'gsHorizontalFlipUV')
hFlipUV.setLabel('H-Flip (H)')
hFlipUV.clicked.connect(undo(self.horizontalFlipUV))
vFlipUV = wrap.Button(HVFlip.layout(), 'gsVerticalFlipUV')
vFlipUV.setLabel('V-Flip (V)')
vFlipUV.clicked.connect(undo(self.verticalFlipUV))
resetUV = wrap.Button(mainColumn.layout(), 'gsResetUVs')
resetUV.setLabel('Reset UV (X)')
resetUV.clicked.connect(undo(self.resetUVs))
syncSelection = wrap.Button(mainColumn.layout(), 'gsSyncSelectionUVs')
syncSelection.setLabel('Sync Selection (S)')
syncSelection.clicked.connect(undo(self.syncSelection))
randomizeUVs = wrap.Button(mainColumn.layout(), 'gsRandomizeUVs')
randomizeUVs.setLabel('Randomize')
randomizeUVs.setIcon('mod-bottom')
randomizeUVs.clicked.connect(undo(self.randomizeUVs))
mainColumn.layout().addWidget(wrap.separator())
# UV List
uvListLabel = wrap.Label(mainColumn.layout())
uvListLabel.setLabel('UV List')
self.uvList = wrap.UVItemList(mainColumn.layout())
self.uvList.setLayout(mainColumn.layout())
self.uvList.signal_mouseReleased.connect(self.updateVisibility)
focusView = wrap.Button(mainColumn.layout(), 'gsFocusUVs')
focusView.setLabel('Focus View (F)')
focusView.clicked.connect(self.editor.focusView)
with wrap.Row(mainColumn.layout()) as hideIsolate:
isolateSelect = wrap.Button(hideIsolate.layout(), 'gsUVIsolateSelect')
isolateSelect.setLabel('Isolate (I)')
isolateSelect.clicked.connect(self.isolateSelect)
hide = wrap.Button(hideIsolate.layout(), 'gsUVHide')
hide.setLabel('Hide (O)')
hide.clicked.connect(self.hide)
showAllButton = wrap.Button(mainColumn.layout(), 'gsUVShowAll')
showAllButton.setLabel('Show All (A)')
showAllButton.clicked.connect(self.showAll)
mainColumn.layout().addWidget(wrap.separator())
with wrap.Frame(mainColumn.layout(), label="Options") as optionsFrame:
# Texture Controls
textureFunctionsLabel = wrap.Label(optionsFrame.getFrameLayout())
textureFunctionsLabel.setLabel('Texture Controls:')
transparency = wrap.Button(optionsFrame.getFrameLayout(), 'UVEditorTransparencyToggle')
transparency.setButtonStyle('small')
transparency.setCheckable(True)
transparency.setChecked(mc.optionVar(q='GSCT_UVEditorTransparencyToggle'))
transparency.setLabel("Transparency")
alphaOnly = wrap.Button(optionsFrame.getFrameLayout(), 'UVEditorAlphaOnlyToggle')
alphaOnly.setButtonStyle('small')
alphaOnly.setCheckable(True)
alphaOnly.setChecked(mc.optionVar(q='GSCT_UVEditorAlphaOnly'))
alphaOnly.setLabel("Alpha Only")
useTransforms = wrap.Button(optionsFrame.getFrameLayout(), 'UVEditorUseTransforms')
useTransforms.setButtonStyle('small')
useTransforms.setCheckable(True)
useTransforms.setChecked(True)
useTransforms.setLabel("Use Transforms")
useTransforms.clicked.connect(self.updateTexture)
def toggleAlphaCommand():
if transparency.isChecked():
self.editor.toggleAlpha(True)
else:
self.editor.toggleAlpha(False)
alphaOnly.setChecked(False)
self.updateTexture()
mc.optionVar(iv=['GSCT_UVEditorTransparencyToggle', transparency.isChecked()])
transparency.clicked.connect(toggleAlphaCommand)
def toggleAlphaOnlyCommand(): # BUG: Find out why switching textures does not update alpha
if alphaOnly.isChecked():
transparency.setChecked(True)
else:
transparency.setChecked(False)
toggleAlphaCommand()
mc.optionVar(iv=['GSCT_UVEditorAlphaOnly', alphaOnly.isChecked()])
alphaOnly.clicked.connect(toggleAlphaOnlyCommand)
optionsFrame.getFrameLayout().addWidget(wrap.separator())
# Editor Colors
textureFunctionsLabel = wrap.Label(optionsFrame.getFrameLayout())
textureFunctionsLabel.setLabel('Editor Colors:')
with wrap.Row(optionsFrame.getFrameLayout(), margins=style.scale([5, 0, 5, 5])) as colorRow:
backgroundColorPicker = wrap.ColorPicker('UVEditorBGColorPicker', colorRow.layout())
backgroundColorPicker.setRGBColors(
utils.colorFrom255to1(eval(mc.optionVar(q="GSCT_UVEditorBGColor")))
)
backgroundColorPicker.connectCommand(self.updateColors)
gridColorPicker = wrap.ColorPicker('UVEditorGridColorPicker', colorRow.layout())
gridColorPicker.setRGBColors(
utils.colorFrom255to1(eval(mc.optionVar(q="GSCT_UVEditorGridColor")))
)
gridColorPicker.connectCommand(self.updateColors)
frameColorPicker = wrap.ColorPicker('UVEditorFrameColorPicker', colorRow.layout())
frameColorPicker.setRGBColors(
utils.colorFrom255to1(eval(mc.optionVar(q="GSCT_UVEditorFrameColor")))
)
frameColorPicker.connectCommand(self.updateColors)
# UV Card Colors
cardColors = wrap.Label(optionsFrame.getFrameLayout())
cardColors.setLabel('UV Colors:')
with wrap.Row(optionsFrame.getFrameLayout(), margins=style.scale([5, 0, 5, 5])) as colorRow2:
selectedCardFrameColor = wrap.ColorPicker('UVEditorUVFrameSelectedColorPicker', colorRow2.layout())
selectedCardFrameColor.setRGBColors(
utils.colorFrom255to1(eval(mc.optionVar(q="GSCT_UVEditorUVFrameSelectedColor")))
)
selectedCardFrameColor.connectCommand(self.updateColors)
deselectedCardFrameColor = wrap.ColorPicker('UVEditorUVFrameDeselectedColorPicker', colorRow2.layout())
deselectedCardFrameColor.setRGBColors(
utils.colorFrom255to1(eval(mc.optionVar(q="GSCT_UVEditorUVFrameDeselectedColor")))
)
deselectedCardFrameColor.connectCommand(self.updateColors)
cardFillColor = wrap.ColorPicker('UVEditorUVCardFillColorPicker', colorRow2.layout())
cardFillColor.setRGBColors(
utils.colorFrom255to1(eval(mc.optionVar(q="GSCT_UVEditorUVCardFillColor")))
)
cardFillColor.connectCommand(self.updateColors)
mainColumn.layout().addWidget(wrap.separator())
mainRow.layout().addWidget(self.editor)
if MAYA_VER in [2020, 2022] and not mc.optionVar(q='GSCT_UVBugMessageDismissed'):
with wrap.Row(mainLayout) as row:
label = wrap.Label(row.layout())
label.setLabel('<p style="color:#FF542F">How To Fix Maya 2020-2022 UV Bug:</p>')
linkButton = wrap.Button(row.layout())
linkButton.setLabel('Open Fix')
linkButton.setButtonStyle('small-filled')
linkButton.clicked.connect(lambda: utils.openLink(
'https://gs-curvetools.readthedocs.io/en/latest/faq.html#maya-2020-2022-and-broken-uvs')
)
dismissMessage = wrap.Button(row.layout())
dismissMessage.setLabel('Dismiss Message')
dismissMessage.setButtonStyle('small-filled')
dismissMessage.clicked.connect(lambda: row.setHidden(True))
dismissMessage.clicked.connect(lambda: mc.optionVar(iv=['GSCT_UVBugMessageDismissed', 1]))
def updateColors(self, *_):
if self.editor:
core.saveOptions()
try:
self.editor.changeColor(
eval(mc.optionVar(q="GSCT_UVEditorBGColor")),
eval(mc.optionVar(q="GSCT_UVEditorGridColor")),
eval(mc.optionVar(q="GSCT_UVEditorFrameColor")),
eval(mc.optionVar(q="GSCT_UVEditorUVCardFillColor")),
eval(mc.optionVar(q="GSCT_UVEditorUVFrameSelectedColor")),
eval(mc.optionVar(q="GSCT_UVEditorUVFrameDeselectedColor"))
)
except Exception as e:
self.editor.changeColor()
LOGGER.exception(e)
self.editor.update()
@noUndo
def updateEditor(self):
uveditor.updateItemList()
uveditor.updateUVs()
uveditor.updateTexture()
def showAll(self):
self.uvList.expandAll()
self.uvList.selectAll()
self.updateVisibility()
self.isolateMode = False
@noUndo
def updateUVs(self, keepSelection=False):
sel = mc.filterExpand(mc.ls(sl=1, fl=1, l=1), sm=9)
oldUVs = self.editor.UVDict
self.editor.purgeUVs()
if not sel:
return
sel = self.checkForLegacyUVs(sel)
for item in sel:
if (mc.attributeQuery('Orientation', n=item, ex=1) and
mc.connectionInfo(item + '.Orientation', isSource=1)):
if (mc.attributeQuery('gsmessage', n=item, ex=1) and
mc.listConnections(item + '.gsmessage')):
curves = core.getAllConnectedCurves(item)
else:
curves = [item]
for curve in curves:
attrs = core.attributes.getUVs(curve)
cb = core.attributes.getCheckboxes(curve)
if attrs:
uv = self.editor.createUV(curve)
if 'flipUV' in cb:
uv.flip = not cb['flipUV']
uv.moveUV(
x=attrs['moveU'],
y=attrs['moveV'],
rot=attrs['rotateUV'] * -1,
sx=attrs['scaleU'],
sy=attrs['scaleV'],
)
if keepSelection:
newUVs = self.editor.UVDict
for uv in newUVs:
if uv in oldUVs:
newUVs[uv].setSelected(True)
def checkForLegacyUVs(self, curves):
legacyCurves = []
for curve in curves:
root = mc.attributeQuery('rotateRootUV', n=curve, ex=1)
tip = mc.attributeQuery('rotateTipUV', n=curve, ex=1)
if root or tip:
rootValue = mc.getAttr(curve + '.rotateRootUV')
tipValue = mc.getAttr(curve + '.rotateTipUV')
if rootValue or tipValue:
legacyCurves.append(curve)
if not legacyCurves:
return curves
else:
MESSAGE.warningInView('Non Zero Legacy UV Attributes Detected')
dialog = mc.confirmDialog(
title='Legacy UVs',
message='Non Zero Legacy UVs Detected.\nUV Editor is not compatible with them.\nZero them out to proceed?',
icon='warning',
button=['Yes', 'Cancel'],
cancelButton='Cancel',
dismissString='Cancel'
)
if dialog == 'Yes':
for curve in legacyCurves:
mc.setAttr(curve + '.rotateRootUV', 0)
mc.setAttr(curve + '.rotateTipUV', 0)
return curves
elif dialog == 'Cancel':
dialog = mc.confirmDialog(
title='Legacy UVs',
message='UV Editor is not compatible with the old UVs.\nSome of the cards are ignored.',
icon='information',
button='OK',
cancelButton='OK',
dismissString='OK'
)
return list(set(curves) - set(legacyCurves))
@noUndo
def updateTexture(self):
sel = core.selectPart(2, justReturn=True)
if not sel:
self.editor.removeTexture()
self.editor.diffusePath = ''
return
geo = mc.filterExpand(sel, sm=12)
if not geo:
return
dag = mc.ls(geo[-1], dag=1, s=1)
shader = mc.listConnections(dag, d=1, s=1, t='shadingEngine')
if not shader:
return
network = mc.hyperShade(lun=shader[0])
fileNode = None
alphaNode = None
if network:
for node in network:
if mc.nodeType(node) == 'file' and mc.connectionInfo(node + '.outColor', isSource=1):
fileNode = node
break
for node in network:
if mc.nodeType(node) == 'file' and mc.connectionInfo(node + '.outTransparency', isSource=1):
alphaNode = node
break
if not fileNode:
return
texturePath = mc.getAttr(fileNode + '.fileTextureName')
alphaPath = mc.getAttr(alphaNode + '.fileTextureName') if alphaNode else None
# Find place2dTexture node
place2dTexture = None
if mc.attributeQuery('coverage', n=fileNode, ex=1):
info = mc.connectionInfo(fileNode + '.coverage', sfd=1)
if info:
place2dTexture = info.split('.')
if place2dTexture:
place2dTexture = place2dTexture[0]
# Get coverage and transformFrame from place2dTexture
cov, trans = None, None
if place2dTexture and mc.objExists(place2dTexture) and WIDGETS['UVEditorUseTransforms'].isChecked():
if (mc.attributeQuery('coverage', ex=1, n=place2dTexture) and
mc.attributeQuery('translateFrame', ex=1, n=place2dTexture)):
try:
cov = mc.getAttr(place2dTexture + '.coverage')[0]
trans = mc.getAttr(place2dTexture + '.translateFrame')[0]
except Exception as e:
LOGGER.exception(e)
coverage = cov if cov else (1.0, 1.0)
translation = (trans[0], trans[1]) if trans and trans else (0, 0)
if not WIDGETS['UVEditorTransparencyToggle'].isChecked() and not WIDGETS['UVEditorAlphaOnlyToggle'].isChecked():
alphaPath = None
if texturePath:
_, ext = os.path.splitext(texturePath)
try: # Python 3
supportedFormats = list([str(x, encoding='ASCII').lower() for x in QtGui.QImageReader.supportedImageFormats()])
except BaseException: # Python 2 fallback
supportedFormats = list([str(x).decode('ASCII').lower() for x in QtGui.QImageReader.supportedImageFormats()])
if ext and (ext[1:].lower() not in supportedFormats):
MESSAGE.warning(
"{} format is not supported. Use JPG/JPEG, PNG, TIF/TIFF (LZW or No Compression), TGA (24bit, no RLE)".format(ext[1:].upper()))
return
err = self.editor.setTexture('%s' % texturePath, alphaPath, coverage, translation)
if err == 'SamePath':
return
elif err == 'NoTexture':
MESSAGE.warning("Texture file could not be loaded.")
return
elif err == 'ZeroTexture':
MESSAGE.warning("Invalid Path or Zero Texture")
return
def manualCurveUpdate(self):
try:
self._updateCurves()
except Exception as e:
LOGGER.exception(e)
finally:
self._stopCurvesUpdate()
def _updateCurves(self):
if self.uvUpdateCheck == 0:
mc.undoInfo(ock=1, cn='gsUVUpdate')
self.uvUpdateCheck = 1
sel = mc.filterExpand(mc.ls(sl=1), sm=9)
uvs = self.editor.getUVs()
self.currentSelection *= 0
if not sel:
return
for curve in sel:
if curve in uvs:
self.currentSelection.append(curve)
else:
if (mc.attributeQuery('gsmessage', n=curve, ex=1) and
mc.listConnections(curve + '.gsmessage')):
boundCurves = core.getAllConnectedCurves(curve)
if boundCurves:
self.currentSelection += boundCurves
if not self.timer.increment(1.0 / 60.0):
return
if not self.currentSelection:
return
uvs = self.editor.getUVs()
for curve in self.currentSelection:
if curve in uvs:
core.attributes.setAttr(curve, uvs[curve])
def _stopCurvesUpdate(self):
if self.uvUpdateCheck == 1:
mc.undoInfo(cck=1)
self.uvUpdateCheck = 0
self.currentSelection *= 0
core.curveControlUI.updateUI()
def updateButtons(self, controllerMode, scaleMode):
buttons = self.controllerGroup.buttons()
direction = self.directionSwitch.buttons()
if controllerMode == 'SELECT':
buttons[0].setChecked(True)
elif controllerMode == 'MOVE':
buttons[1].setChecked(True)
elif controllerMode == 'ROTATE':
buttons[2].setChecked(True)
elif controllerMode == 'SCALE':
buttons[3].setChecked(True)
if scaleMode == 'H':
direction[0].setChecked(True)
else:
direction[1].setChecked(True)
elif controllerMode == 'DRAW':
buttons[4].setChecked(True)
def updateControllerMode(self):
buttonID = self.controllerGroup.checkedId()
scaleID = self.directionSwitch.checkedId()
scale = 'H'
if buttonID == 0:
mode = 'SELECT'
elif buttonID == 1:
mode = 'MOVE'
elif buttonID == 2:
mode = 'ROTATE'
elif buttonID == 3:
mode = 'SCALE'
if scaleID == 0:
scale = 'H'
else:
scale = 'V'
else:
mode = 'DRAW'
self.editor.controllerModeChange(mode, scale)
def updateItemList(self):
sel = mc.filterExpand(mc.ls(sl=1), sm=9)
if not sel:
self.uvList.clearItemList()
return
finalDict = {}
for curve in sel:
if (mc.attributeQuery('Orientation', n=curve, ex=1) and
mc.connectionInfo(curve + '.Orientation', isSource=1)):
if (mc.attributeQuery('gsmessage', n=curve, ex=1) and
mc.listConnections(curve + '.gsmessage')):
boundCurves = core.getAllConnectedCurves(curve)
finalDict[curve] = boundCurves
else:
finalDict[curve] = []
self.uvList.updateItemList(finalDict)
def updateVisibility(self):
itemList = self.uvList.getSelection()
items = self.editor.getAllUVs()
for item in items:
if item.name in itemList:
item.setVisible(True)
else:
item.setVisible(False)
self.editor.update()
def hide(self):
"""Hides selected UV items"""
selUVs = self.editor.getAllUVs(selected=True)
selUVsList = [i.name for i in selUVs]
for uv in selUVs:
uv.setVisible(False)
itemList = self.uvList.getItemList()
selectList = []
for item in itemList:
if item.curveName in selUVsList:
selectList.append(item)
self.uvList.selectItems(selectList)
def isolateSelect(self):
allUVs = self.editor.getAllUVs()
selUVs = self.editor.getAllUVs(selected=True)
if not selUVs:
return
if self.isolateMode:
self.showAll()
self.isolateMode = False
return
self.isolateMode = True
selUVsList = [i.name for i in selUVs]
for uv in allUVs:
if uv.name not in selUVsList:
uv.setVisible(False)
itemList = self.uvList.getItemList()
deselectList = []
for item in itemList:
if item.curveName not in selUVsList:
deselectList.append(item)
self.uvList.selectItems(deselectList)
def horizontalFlipUV(self):
items = self.editor.getAllUVs(selected=True)
for item in items:
if item.name and mc.attributeQuery('flipUV', n=item.name, ex=1):
flip = mc.getAttr(item.name + '.flipUV')
mc.setAttr(item.name + '.flipUV', not flip)
item.flip = flip
item.update()
if items:
self.editor.update()
def verticalFlipUV(self):
self.editor.verticalFlipUV()
self.manualCurveUpdate()
def functionSwitch(self, key):
if key == 'H':
self.horizontalFlipUV()
elif key == 'V':
self.verticalFlipUV()
elif key == 'X':
self.resetUVs()
elif key == 'I':
self.isolateSelect()
elif key == 'O':
self.hide()
elif key == 'A':
self.showAll()
elif key == 'S':
self.syncSelection()
def resetUVs(self):
self.editor.resetUV()
self.manualCurveUpdate()
def randomizeUVs(self):
if utils.getMod() == 'Shift':
self.editor.randomizeUVs(True)
else:
self.editor.randomizeUVs(False)
self.manualCurveUpdate()
def syncSelection(self):
"""Selects curves in Maya Viewport based on UV Editor selection"""
sel = mc.filterExpand(mc.ls(sl=1), sm=9)
if not sel:
return
selUVs = [x.name for x in self.editor.getAllUVs(selected=True)]
newSel = [x for x in sel if x in selUVs]
if newSel:
mc.select(newSel, r=1)
@utils.deferredLp
def x():
uvs = self.editor.getAllUVs()
for uv in uvs:
uv.setSelected(True)
self.editor.scene().update()
x()
uveditor = UVEditor('uveditor')
# Colors Window
class CustomLayerColors:
def window(self, *_):
self.windowName = 'GSCT_CustomLayerColorsWindow'
if mc.workspaceControl(self.windowName, q=1, ex=1):
mc.deleteUI(self.windowName)
popOut = CreatePopOut(self.windowName, "Layers Customization", 280, 586)
layout = popOut.widgetLayout
layout.setAlignment(QtCore.Qt.AlignTop)
letters = [chr(l) for l in range(ord('A'), ord('A') + 10)]
wrap.Label(layout).setLabel("Color Controls:")
with wrap.Frame(layout, label='Gradient', margins=[2, 2, 2, 2]) as generateFrame:
self.gradientRowsNumber = wrap.ControlSlider(generateFrame.getFrameLayout())
self.gradientRowsNumber.setLabel('Rows')
self.gradientRowsNumber.setMinMax(1, 80)
self.gradientRowsNumber.setValue(20)
with wrap.Row(generateFrame.getFrameLayout()) as gradientColorsLayout:
self.minGradientSwatch = wrap.ColorPicker('gradientSwatchMin', gradientColorsLayout.layout())
self.minGradientSwatch.setHSVColors([0.1, 1, 1])
self.maxGradientSwatch = wrap.ColorPicker('gradientSwatchMax', gradientColorsLayout.layout())
self.maxGradientSwatch.setHSVColors([300, 1, 1])
generateGradient = wrap.Button(generateFrame.getFrameLayout(), 'gsGenerateLayerColorGradient')
generateGradient.setLabel('Generate Gradient')
generateGradient.clicked.connect(self.generateColorGradient)
with wrap.Frame(layout, label='Randomize', margins=[2, 2, 2, 2]) as randomizeFrame:
self.saturationMin = wrap.ControlSlider(randomizeFrame.getFrameLayout(), typ='float')
self.saturationMin.setMinMax(0, 1)
self.saturationMin.setValue(0.8)
self.saturationMin.setStep(0.01)
self.saturationMin.setLabel('SatMin')
self.saturationMax = wrap.ControlSlider(randomizeFrame.getFrameLayout(), typ='float')
self.saturationMax.setMinMax(0, 1)
self.saturationMax.setValue(1.0)
self.saturationMax.setStep(0.01)
self.saturationMax.setLabel('SatMax')
randomizeButton = wrap.Button(randomizeFrame.getFrameLayout(), 'gsRandomizeLayerColors')
randomizeButton.setLabel('Randomize All')
randomizeButton.clicked.connect(self.randomizeAllColors)
layout.addWidget(wrap.separator())
wrap.Label(layout).setLabel("Layers:")
def colorRow(parent, i):
with wrap.Row(parent) as singleColor:
singleColor.setFixedHeight(style.scale(16))
label = wrap.Label()
if 10 <= i < 20:
label.setLabel('%s (%s)' % (i, letters[i - 10]))
else:
label.setLabel(str(i))
label.setFixedWidth(style.scale(int(35)))
layerName = wrap.LineEdit('layerCustomName_%s' % i)
newFont = QtGui.QFont('Roboto')
newFont.setPointSizeF(style.scale(5))
layerName.setFixedHeight(style.scale(18))
layerName.setFrame(False)
layerName.setFont(newFont)
layerName.setAutoFormat(True)
layerName.setClearButtonEnabled(True)
swatch = wrap.ColorPicker('layerColorPicker_%s' % i)
randButton = wrap.Button()
randButton.setButtonStyle('small-filled')
randButton.setLabel('Rand', lineHeight=100)
randButton.setLabelStyle('small')
randButton.setWidthHeight(h=style.scale(10))
randButton.clicked.connect(pa(self.randomizeColor, swatch))
resetButton = wrap.Button()
resetButton.setButtonStyle('small-filled')
resetButton.setLabel('Reset', lineHeight=100)
resetButton.setLabelStyle('small')
resetButton.setWidthHeight(h=style.scale(10))
resetButton.clicked.connect(pa(self.resetColor, swatch))
resetButton.clicked.connect(pa(self.resetName, layerName))
singleColor.layout().addWidget(label)
singleColor.layout().addWidget(layerName, 3)
singleColor.layout().addWidget(swatch, 1)
singleColor.layout().addWidget(randButton, 1)
singleColor.layout().addWidget(resetButton, 1)
return singleColor
with wrap.Frame(layout, label='0-19') as frame1:
for i in range(20):
colorRow(frame1.getFrameLayout(), i)
frame1.setCollapsed(False)
with wrap.Frame(layout, label='20-39') as frame2:
for i in range(20, 40):
colorRow(frame2.getFrameLayout(), i)
frame2.setCollapsed(True)
with wrap.Frame(layout, label='40-79') as frame3:
for i in range(40, 80):
colorRow(frame3.getFrameLayout(), i)
frame3.setCollapsed(True)
layout.addWidget(wrap.separator())
wrap.Label(layout).setLabel("Commands:")
resetButton = wrap.Button(layout, 'gsResetAllLayerColors')
resetButton.setLabel('Reset All')
resetButton.clicked.connect(self.resetAll)
with wrap.Row(layout) as controlButtons:
getCurrent = wrap.Button(controlButtons.layout(), 'gsGetCurrentSceneLayers')
getCurrent.setLabel('Get From Scene')
getCurrent.clicked.connect(self.getFromLayers)
setAsCurrent = wrap.Button(controlButtons.layout(), 'gsSetAsCurrentSceneLayers')
setAsCurrent.setLabel('Set To Scene')
setAsCurrent.clicked.connect(self.setToLayers)
with wrap.Row(layout) as buttonsFrame:
loadSaved = wrap.Button(buttonsFrame.layout(), 'gsLoadGlobalLayerPreset')
loadSaved.setLabel('Load Preset')
loadSaved.clicked.connect(self.loadPreset)
saveButton = wrap.Button(buttonsFrame.layout(), 'gsSaveGlobalLayerPreset')
saveButton.setLabel('Save As Preset')
saveButton.clicked.connect(self.savePreset)
self.getFromLayers()
def randomizeColor(self, swatch):
satMin = self.saturationMin.getValue()
satMax = self.saturationMax.getValue()
swatch.setRGBColors(core.toggleColor.generateBrightColor(satMin, satMax))
def randomizeAllColors(self):
for i in range(80):
self.randomizeColor(WIDGETS['layerColorPicker_%s' % i])
def resetColor(self, swatch):
swatch.setRGBColors([0, 0, 0])
def resetName(self, field):
field.clear()
def resetAll(self):
for i in range(80):
WIDGETS['layerColorPicker_%s' % i].setRGBColors([0, 0, 0])
WIDGETS['layerCustomName_%s' % i].clear()
def generateColorGradient(self):
rows = self.gradientRowsNumber.getValue()
colorMin = self.minGradientSwatch.getHSVColors()
colorMax = self.maxGradientSwatch.getHSVColors()
for i in range(rows):
fraction = i / float(rows)
h = mt.lerp(fraction, colorMin[0], colorMax[0])
s = mt.lerp(fraction, colorMin[1], colorMax[1])
v = mt.lerp(fraction, colorMin[2], colorMax[2])
WIDGETS['layerColorPicker_%s' % i].setHSVColors([h, s, v])
def getFromLayers(self):
# Getting colors
colorDict = core.toggleColor.readColorDict()
for key in colorDict:
WIDGETS['layerColorPicker_%s' % key].setRGBColors(colorDict[key])
# Getting names
core.toggleColor.checkColorStorageNode()
nameDict = eval(mc.getAttr(core.toggleColor.STORAGE_NODE + '.layerName'))
for key in nameDict:
if nameDict[key]:
WIDGETS['layerCustomName_%s' % key].setText(nameDict[key])
def getCurrentSwatches(self):
colorDict = {}
for i in range(80):
colorDict[i] = WIDGETS['layerColorPicker_%s' % i].getRGBColors()
return colorDict
def getCurrentNames(self):
core.toggleColor.checkColorStorageNode()
nameDict = {}
for i in range(80):
nameDict[i] = WIDGETS['layerCustomName_%s' % i].text()
return nameDict
def setToLayers(self):
colorDict = self.getCurrentSwatches()
core.toggleColor.writeColorDict(colorDict)
if WIDGETS['colorMode'].isChecked():
core.toggleColor.updateColors()
if WIDGETS['syncCurveColor'].isChecked():
core.toggleColor.syncCurveColors()
core.updateMainUI()
# Setting names
nameDict = self.getCurrentNames()
core.toggleColor.checkColorStorageNode()
mc.setAttr(core.toggleColor.STORAGE_NODE + '.layerName', str(nameDict), typ='string')
def setCurrentSwathes(self, colorDict):
for key in colorDict:
WIDGETS['layerColorPicker_%s' % key].setRGBColors(colorDict[key])
def setCurrentNames(self, nameDict):
for key in nameDict:
WIDGETS['layerCustomName_%s' % key].setText(nameDict[key])
def savePreset(self):
mc.optionVar(sv=['gsCurveToolsCustomColors', str(self.getCurrentSwatches())])
mc.optionVar(sv=['gsCurveToolsCustomLayerNames', str(self.getCurrentNames())])
def loadPreset(self):
colorString = mc.optionVar(q='gsCurveToolsCustomColors')
colorDict = eval(colorString)
self.setCurrentSwathes(colorDict)
nameString = mc.optionVar(q='gsCurveToolsCustomLayerNames')
nameDict = eval(nameString)
self.setCurrentNames(nameDict)
customLayerColors = CustomLayerColors()
class CreatePopOut(QtWidgets.QWidget):
def __init__(self, name, label, width, height):
self.name = name
parent = mayaWorkspaceControl(name=name,
label=label,
retain=False, iw=width, ih=height, widthProperty="free")
super(CreatePopOut, self).__init__(parent)
self.ui()
parent.layout().addWidget(self)
def ui(self):
self.mainLayout = QtWidgets.QVBoxLayout(self)
self.mainLayout.setContentsMargins(*style.scale([5, 5, 5, 5]))
self.scrollWidget = QtWidgets.QWidget()
self.widgetLayout = QtWidgets.QVBoxLayout(self.scrollWidget)
scrollArea = QtWidgets.QScrollArea()
scrollArea.setWidget(self.scrollWidget)
self.mainLayout.addWidget(scrollArea)
# Layout Settings
self.widgetLayout.setContentsMargins(0, 0, 0, 0)
self.widgetLayout.setSpacing(style.scale(2))
self.widgetLayout.setMargin(0)
scrollArea.setFrameShape(QtWidgets.QFrame.NoFrame)
scrollArea.setWidgetResizable(True)
class About: # Creates "About" and "Contacts" windows
def social(self):
layout = mc.columnLayout()
mc.textFieldButtonGrp(
bl='>',
bc=pa(
utils.openLink,
'https://discord.gg/f4DH6HQ'),
l='Discord Server',
tx='https://discord.gg/f4DH6HQ')
mc.textFieldButtonGrp(bl='>', bc=pa(utils.openLink, 'https://sladkovsky3d.artstation.com/store'),
l='Online Store', tx='https://sladkovsky3d.artstation.com/store')
mc.textFieldButtonGrp(bl='>', bc=pa(utils.openLink, 'http://gs-curvetools.readthedocs.io/'),
l='Online Documentation', tx='http://gs-curvetools.readthedocs.io/')
mc.textFieldButtonGrp(bl='>', bc=pa(utils.openLink, 'https://www.twitch.tv/videonomad'),
l='Twitch Channel', tx='https://www.twitch.tv/videonomad')
mc.textFieldButtonGrp(bl='>', bc=pa(utils.openLink, 'https://www.youtube.com/GeorgeSladkovsky'),
l='YouTube Channel', tx='https://www.youtube.com/GeorgeSladkovsky')
mc.textFieldButtonGrp(bl='>', bc=pa(utils.openLink, 'https://www.artstation.com/sladkovsky3d'),
l='ArtStation Portfolio', tx='https://www.artstation.com/sladkovsky3d')
mc.textFieldButtonGrp(bl='>', bc=pa(utils.openLink, 'mailto:george.sladkovsky@gmail.com'),
l='Contact Email', tx='george.sladkovsky@gmail.com')
return layout
def socialWindow(self):
if (mc.window('gsSocialMedia', ex=1)):
mc.deleteUI('gsSocialMedia')
mc.window('gsSocialMedia', t='Useful Links:', tlb=1)
self.social()
mc.showWindow()
def aboutWindow(self):
if mc.window('gsAboutWindow', ex=1):
mc.deleteUI('gsAboutWindow')
mc.window('gsAboutWindow', t='About', tlb=1)
mc.rowColumnLayout(h=400, co=[1, 'left', 10], cal=([1, 'left'], [2, 'right']), nc=2, cw=[1, 200])
mc.text(al='left', l='Version: \n%s' % core.VERSION)
mc.iconTextButton(al='right', w=90, h=80, i=utils.getFolder.icons() + 'gsCurveToolsIcon_logo.png')
mc.setParent('..')
mc.columnLayout(w=460, h=400)
mc.text(w=400, ww=1, al='left',
l='License:\nThis collection of code named GS CurveTools is a property of George Sladkovsky\
(Yehor Sladkovskyi) and can not be copied or distributed without his written permission.\
\n\n%s\nGeorge Sladkovsky (Yehor Sladkovskyi)\nAll Rights Reserved\
\n\nAutodesk Maya is a property of Autodesk, Inc.\n' % core.VERSION)
mc.text(l='Social Media and Contact Links:\n')
self.social()
mc.showWindow('gsAboutWindow')
about = About()
class AttributesFilter:
def __init__(self):
self.uiName = "GSCT_AttributesFilterPopOut"
self.attrs = [
('Length Divisions', 'lengthDivisions'),
('Dynamic Divisions', 'dynamicDivisions'),
('Width Divisions', 'widthDivisions'),
('Orientation', 'Orientation'),
('Twist', 'Twist'),
('Inverted Twist', 'invTwist'),
('Width', 'Width'),
('WidthX', 'WidthX'),
('WidthZ', 'WidthZ'),
('Taper', 'Taper'),
('Length Lock', 'LengthLock'),
('Length', 'Length'),
('Offset', 'Offset'),
('Profile', 'Profile'),
('Refine', 'curveRefine'),
('Auto Refine', 'autoRefine'),
('Smooth', 'curveSmooth'),
('Normals', 'surfaceNormals'),
('Reverse Normals', 'reverseNormals'),
('Axis Flip', 'AxisFlip'),
('Line Width', 'lineWidth'),
('Sampling', 'samplingAccuracy'),
]
self.solidify = [
('Solidify', 'solidify'),
('Solidify Thickness', 'solidifyThickness'),
('Solidify Divisions', 'solidifyDivisions'),
('Solidify Scale X', 'solidifyScaleX'),
('Solidify Scale Y', 'solidifyScaleY'),
('Solidify Offset', 'solidifyOffset'),
('Solidify Normals', 'solidifyNormals'),
]
self.uvs = [
('Move U', 'moveU'),
('Move V', 'moveV'),
('Rotate UV', 'rotateUV'),
('Scale U', 'scaleU'),
('Scale V', 'scaleV'),
('Flip UV', 'flipUV'),
('Rotate Root UV', 'rotateRootUV'),
('Rotate Tip UV', 'rotateTipUV'),
]
self.graphs = [
('Twist Graph', 'twistCurve'),
('Scale Graph', 'scaleCurve'),
('Profile Graph', 'profileCurve'),
('Twist Magnitude', 'Magnitude'),
('Profile Smoothing', 'profileSmoothing'),
('Profile Magnitude', 'profileMagnitude'),
]
def openUI(self):
if mc.workspaceControl(self.uiName, q=1, ex=1):
if mc.workspaceControl(self.uiName, q=1, vis=1):
mc.deleteUI(self.uiName)
return
else:
mc.deleteUI(self.uiName)
popOut = CreatePopOut(self.uiName, "Attributes Filter", 260, 456.0)
layout = popOut.widgetLayout
layout.setAlignment(QtCore.Qt.AlignTop)
with wrap.Row(layout, margins=style.scale([6, 0, 6, 0]), spacing=style.scale(10)) as mainRow:
mainRow.layout().setAlignment(QtCore.Qt.AlignTop)
with wrap.Column(mainRow.layout()) as leftColumn:
with wrap.Frame(leftColumn.layout(), label='Attributes', margins=[2, 0, 2, 0]) as leftFrame:
leftFrame.setCollapsible(False)
leftFrame.getFrameLayout().setAlignment(QtCore.Qt.AlignTop)
for i in range(len(self.attrs)):
btn = wrap.Button(leftFrame.getFrameLayout(), 'gsFilter_%s' % self.attrs[i][1])
btn.setLabel(self.attrs[i][0])
btn.setButtonStyle('small')
btn.setCheckable(True)
btn.setChecked(False if self.attrs[i][0] == 'Orientation' else True)
with wrap.Column(mainRow.layout()) as rightColumn:
rightColumn.layout().setAlignment(QtCore.Qt.AlignTop)
with wrap.Frame(rightColumn.layout(), label='Solidify', margins=[2, 0, 2, 0]) as rightFrame1:
rightFrame1.setCollapsible(False)
rightFrame1.getFrameLayout().setAlignment(QtCore.Qt.AlignTop)
for i in range(len(self.solidify)):
btn = wrap.Button(rightFrame1.getFrameLayout(), 'gsFilter_%s' % self.solidify[i][1])
btn.setLabel(self.solidify[i][0])
btn.setButtonStyle('small')
btn.setCheckable(True)
btn.setChecked(True)
with wrap.Frame(rightColumn.layout(), label='Graphs', margins=[2, 0, 2, 0]) as rightFrame2:
rightFrame2.setCollapsible(False)
rightFrame2.getFrameLayout().setAlignment(QtCore.Qt.AlignTop)
for i in range(len(self.graphs)):
btn = wrap.Button(rightFrame2.getFrameLayout(), 'gsFilter_%s' % self.graphs[i][1])
btn.setLabel(list(self.graphs)[i][0])
btn.setButtonStyle('small')
btn.setCheckable(True)
btn.setChecked(True)
with wrap.Frame(rightColumn.layout(), label='UVs', margins=[2, 0, 2, 0]) as rightFrame3:
rightFrame3.setCollapsible(False)
rightFrame3.getFrameLayout().setAlignment(QtCore.Qt.AlignTop)
for i in range(len(self.uvs)):
btn = wrap.Button(rightFrame3.getFrameLayout(), 'gsFilter_%s' % self.uvs[i][1])
btn.setLabel(list(self.uvs)[i][0])
btn.setButtonStyle('small')
btn.setCheckable(True)
btn.setChecked(True)
layout.addWidget(wrap.separator())
with wrap.Row(layout) as confirmCancelLayout:
btn = wrap.Button(confirmCancelLayout.layout())
btn.setLabel('Save')
btn.clicked.connect(self.saveToOptionVar)
btn.clicked.connect(lambda: MESSAGE.printInView("Filters Saved"))
btn = wrap.Button(confirmCancelLayout.layout())
btn.setLabel('Close')
btn.clicked.connect(self.closeUI)
self.updateUI()
self.saveToOptionVar()
def closeUI(self):
if mc.workspaceControl(self.uiName, q=1, ex=1):
mc.deleteUI(self.uiName)
def updateUI(self):
if mc.workspaceControl(self.uiName, q=1, ex=1):
controlsDict = self.getFromOptionVar()
if controlsDict and isinstance(controlsDict, dict):
for key in controlsDict:
buttonName = 'gsFilter_%s' % key
WIDGETS[buttonName].setChecked(controlsDict[key])
def saveToOptionVar(self):
if mc.workspaceControl(self.uiName, q=1, ex=1):
allControls = self.attrs + self.graphs + self.uvs + self.solidify
controlsDict = {}
for control in allControls:
buttonName = 'gsFilter_%s' % control[1]
button = WIDGETS[buttonName] if buttonName in WIDGETS else None
if button:
controlsDict.update({control[1]: button.isChecked()})
mc.optionVar(sv=('GSCT_AttributesFilter', str(controlsDict)))
def getFromOptionVar(self):
if mc.optionVar(ex='GSCT_AttributesFilter'):
dictString = mc.optionVar(q='GSCT_AttributesFilter')
if dictString:
return dict(eval(dictString))
attributesFilter = AttributesFilter()
class CardToCurveWindow:
def __init__(self):
self.uiName = "GSCT_CardToCurvePopOut"
self.buttonsDict = {}
def openUI(self):
if mc.workspaceControl(self.uiName, q=1, ex=1):
if mc.workspaceControl(self.uiName, q=1, vis=1):
mc.deleteUI(self.uiName)
return
else:
mc.deleteUI(self.uiName)
self.buttonsDict = self.loadClickedButtons()
self.getBtn = lambda name: self.buttonsDict[name] if name in self.buttonsDict else True
popOut = CreatePopOut(self.uiName, "Card to Curve", 245, 271)
layout = popOut.widgetLayout
layout.setAlignment(QtCore.Qt.AlignTop)
self.mainButtonGroup = QtWidgets.QButtonGroup()
self.mainButtonGroup.setExclusive(False)
self.mainButtonGroup.buttonClicked.connect(self.saveButtonsState)
with wrap.Column(layout) as mainColumn:
mainColumn.layout().setAlignment(QtCore.Qt.AlignTop)
with wrap.Frame(mainColumn.layout(), label='Output Type:', objName='gsCardToCurve_outputTypeSwitch') as outputTypeFrame:
outputTypeFrame.setCollapsible(False)
outputTypeFrame.setCollapsed(False)
with wrap.Row(outputTypeFrame.getFrameLayout()) as outputTypeSwitch:
self.outputTypeGroup = QtWidgets.QButtonGroup()
WIDGETS['gsCardToCurve_cardTypeGroup'] = self.outputTypeGroup
generateCards = wrap.Button(outputTypeSwitch.layout(), 'gsCardToCurve_generateCards')
generateCards.setButtonStyle('small')
generateCards.setLabel('Cards')
generateCards.setCheckable(True)
generateCurves = wrap.Button(outputTypeSwitch.layout(), 'gsCardToCurve_generateCurves')
generateCurves.setButtonStyle('small')
generateCurves.setLabel('Curves Only')
generateCurves.setCheckable(True)
self.outputTypeGroup.addButton(generateCards, 0)
self.outputTypeGroup.addButton(generateCurves, 1)
generateCards.setChecked(not mc.optionVar(q='GSCT_CardToCurveOutputType'))
generateCurves.setChecked(mc.optionVar(q='GSCT_CardToCurveOutputType'))
self.outputTypeGroup.buttonClicked.connect(self.updateActiveButtons)
with wrap.Frame(mainColumn.layout(), label='Card Type:', objName="gsCardToCurve_cardType") as cardTypeFrame:
self.cardTypeFrame = cardTypeFrame
cardTypeFrame.setCollapsible(False)
cardTypeFrame.setCollapsed(False)
with wrap.Row(cardTypeFrame.getFrameLayout()) as outputTypeSwitch:
self.cardTypeGroup = QtWidgets.QButtonGroup()
WIDGETS['gsCardToCurve_cardTypeGroup'] = self.cardTypeGroup
self.warpCards = wrap.Button(outputTypeSwitch.layout(), 'gsCardToCurve_warp')
self.warpCards.setButtonStyle('small')
self.warpCards.setLabel('Warp')
self.warpCards.setCheckable(True)
extrudeCards = wrap.Button(outputTypeSwitch.layout(), 'gsCardToCurve_extrude')
extrudeCards.setButtonStyle('small')
extrudeCards.setLabel('Extrude')
extrudeCards.setCheckable(True)
self.cardTypeGroup.addButton(self.warpCards, 0)
self.cardTypeGroup.addButton(extrudeCards, 1)
self.warpCards.setChecked(not mc.optionVar(q='GSCT_CardToCurveCardType'))
extrudeCards.setChecked(mc.optionVar(q='GSCT_CardToCurveCardType'))
self.cardTypeGroup.buttonClicked.connect(self.updateActiveButtons)
with wrap.Frame(mainColumn.layout(), label='Match Attributes:', objName="gsCardToCurve_matchAttributes") as matchAttributeFrame:
self.matchAttributeFrame = matchAttributeFrame
matchAttributeFrame.setCollapsible(False)
matchAttributeFrame.setCollapsed(False)
with wrap.Row(matchAttributeFrame.getFrameLayout()) as row:
orientation = wrap.Button(row.layout(), 'gsCardToCurve_orientation')
orientation.setButtonStyle('small')
orientation.setLabel('Orientation')
orientation.setCheckable(True)
orientation.setChecked(self.getBtn('gsCardToCurve_orientation'))
width = wrap.Button(row.layout(), 'gsCardToCurve_width')
width.setButtonStyle('small')
width.setLabel('Width')
width.setCheckable(True)
width.setChecked(self.getBtn('gsCardToCurve_width'))
self.mainButtonGroup.addButton(orientation)
self.mainButtonGroup.addButton(width)
with wrap.Row(matchAttributeFrame.getFrameLayout()) as row:
taper = wrap.Button(row.layout(), 'gsCardToCurve_taper')
taper.setButtonStyle('small')
taper.setLabel('Taper')
taper.setCheckable(True)
taper.setChecked(self.getBtn('gsCardToCurve_taper'))
twist = wrap.Button(row.layout(), 'gsCardToCurve_twist')
twist.setButtonStyle('small')
twist.setLabel('Twist')
twist.setCheckable(True)
twist.setChecked(self.getBtn('gsCardToCurve_twist'))
self.mainButtonGroup.addButton(taper)
self.mainButtonGroup.addButton(twist)
with wrap.Row(matchAttributeFrame.getFrameLayout()) as row:
profile = wrap.Button(row.layout(), 'gsCardToCurve_profile')
profile.setButtonStyle('small')
profile.setLabel('Profile')
profile.setCheckable(True)
profile.setChecked(self.getBtn('gsCardToCurve_profile'))
material = wrap.Button(row.layout(), 'gsCardToCurve_material')
material.setButtonStyle('small')
material.setLabel('Material')
material.setCheckable(True)
material.setChecked(self.getBtn('gsCardToCurve_material'))
self.mainButtonGroup.addButton(profile)
self.mainButtonGroup.addButton(material)
UVs = wrap.Button(matchAttributeFrame.getFrameLayout(), 'gsCardToCurve_UVs')
UVs.setButtonStyle('small')
UVs.setLabel('UVs')
UVs.setCheckable(True)
UVs.setChecked(self.getBtn('gsCardToCurve_UVs'))
UVs.clicked.connect(self.updateActiveButtons)
self.mainButtonGroup.addButton(UVs)
with wrap.Frame(mainColumn.layout(), label='UV Match Options:', objName="gsCardToCurve_UVMatchOptions") as uvMatchOptionsFrame:
self.uvMatchOptionsFrame = uvMatchOptionsFrame
uvMatchOptionsFrame.setCollapsible(False)
uvMatchOptionsFrame.setCollapsed(False)
with wrap.Row(uvMatchOptionsFrame.getFrameLayout()) as row:
verticalFlip = wrap.Button(row.layout(), 'gsCardToCurve_verticalFlip')
verticalFlip.setButtonStyle('small')
verticalFlip.setLabel('Vertical Flip')
verticalFlip.setCheckable(True)
verticalFlip.setChecked(self.getBtn('gsCardToCurve_verticalFlip'))
horizontalFlip = wrap.Button(row.layout(), 'gsCardToCurve_horizontalFlip')
horizontalFlip.setButtonStyle('small')
horizontalFlip.setLabel('Horizontal Flip')
horizontalFlip.setCheckable(True)
horizontalFlip.setChecked(self.getBtn('gsCardToCurve_horizontalFlip'))
self.mainButtonGroup.addButton(verticalFlip)
self.mainButtonGroup.addButton(horizontalFlip)
with wrap.Frame(mainColumn.layout(), label='Other:') as otherOptionsFrame:
otherOptionsFrame.setCollapsible(False)
otherOptionsFrame.setCollapsed(False)
reverseCurve = wrap.Button(otherOptionsFrame.getFrameLayout(), 'gsCardToCurve_reverseCurve')
reverseCurve.setButtonStyle('small')
reverseCurve.setLabel('Reverse Curve')
reverseCurve.setCheckable(True)
reverseCurve.setChecked(self.getBtn('gsCardToCurve_reverseCurve'))
self.mainButtonGroup.addButton(reverseCurve)
mainColumn.layout().addWidget(wrap.separator())
with wrap.Row(mainColumn.layout(), margins=style.scale([0, 3, 0, 3])) as _:
pass
mainColumn.layout().addWidget(wrap.separator())
with wrap.Row(mainColumn.layout()) as row:
convertSelected = wrap.Button(row.layout(), objName="gsCardToCurve_convertSelected")
convertSelected.setLabel('Convert Selected')
convertSelected.clicked.connect(undo(core.cardToCurve))
cancel = wrap.Button(row.layout())
cancel.setLabel('Cancel')
cancel.clicked.connect(self.closeUI)
self.updateActiveButtons()
self.saveButtonsState()
def closeUI(self):
self.saveButtonsState()
if mc.workspaceControl(self.uiName, q=1, ex=1):
if mc.workspaceControl(self.uiName, q=1, vis=1):
mc.deleteUI(self.uiName)
else:
mc.deleteUI(self.uiName)
def updateActiveButtons(self):
if self.outputTypeGroup.checkedId() == 1:
self.matchAttributeFrame.setEnabled(False)
self.uvMatchOptionsFrame.setEnabled(False)
self.cardTypeFrame.setEnabled(False)
mc.optionVar(iv=['GSCT_CardToCurveOutputType', 1])
else:
mc.optionVar(iv=['GSCT_CardToCurveOutputType', 0])
mc.optionVar(iv=['GSCT_CardToCurveCardType', int(not self.warpCards.isChecked())])
self.matchAttributeFrame.setEnabled(True)
self.cardTypeFrame.setEnabled(True)
if WIDGETS['gsCardToCurve_UVs'].isChecked():
self.uvMatchOptionsFrame.setEnabled(True)
else:
self.uvMatchOptionsFrame.setEnabled(False)
def saveButtonsState(self):
buttons = self.mainButtonGroup.buttons()
buttonsDict = {}
for b in buttons:
buttonsDict.update({b.objName: b.isChecked()})
mc.optionVar(sv=['GSCT_CardToCurveOptions', str(buttonsDict)])
def loadClickedButtons(self):
return eval(mc.optionVar(q='GSCT_CardToCurveOptions'))
cardToCurveWindow = CardToCurveWindow()
def scaleFactorWindow():
windowName = SCALE_FACTOR_UI
if mc.workspaceControl(windowName, q=1, ex=1):
mc.deleteUI(windowName)
popOut = CreatePopOut(windowName, "Scale Factor", 300, 95)
layout = popOut.widgetLayout
scaleFactor = core.getScaleFactor()
m_slider = mc.floatSliderGrp('GSCT_scaleFactorSlider',
pre=3, ss=0.01, min=0.01, max=10, fmn=0.001, fmx=1000, f=1,
v=scaleFactor
)
wrap.MayaSlider(m_slider, layout=layout)
with wrap.Row(layout) as row:
saveButton = wrap.Button(row.layout())
saveButton.setLabel('Save')
saveButton.clicked.connect(pa(core.saveScaleFactor, windowName, False))
saveButton.clicked.connect(updateScaleFactorWindow)
saveAndCloseButton = wrap.Button(row.layout())
saveAndCloseButton.setLabel('Save & Close')
saveAndCloseButton.clicked.connect(pa(core.saveScaleFactor, windowName))
cancelButton = wrap.Button(row.layout())
cancelButton.setLabel('Cancel')
cancelButton.clicked.connect(lambda: mc.deleteUI(windowName))
layout.addWidget(wrap.separator())
with wrap.Row(layout) as row:
with wrap.Row(row.layout(), margins=style.scale([2, 0, 2, 0])) as globalRow:
label = wrap.Label(globalRow.layout())
label.setLabel("Global:")
globalValue = mc.optionVar(q=('GSCT_globalScaleFactor'))
field = wrap.LineEdit("scaleFactorGlobalValue", globalRow.layout())
field.setText(str(globalValue))
field.setEnabled(False)
with wrap.Row(row.layout(), margins=style.scale([2, 0, 2, 0])) as sceneRow:
label = wrap.Label(sceneRow.layout())
label.setLabel("Scene:")
if mc.objExists('gsScaleFactorStorageNode') and mc.attributeQuery('scaleFactor', n='gsScaleFactorStorageNode', ex=1):
sceneValue = mc.getAttr('gsScaleFactorStorageNode.scaleFactor')
else:
sceneValue = "####"
field = wrap.LineEdit("scaleFactorSceneValue", sceneRow.layout())
field.setText(str(sceneValue))
field.setEnabled(False)
with wrap.Row(row.layout(), margins=style.scale([2, 0, 2, 0])) as sceneRow:
label = wrap.Label(sceneRow.layout())
label.setLabel("Selected:")
if mc.objExists('gsScaleFactorStorageNode') and mc.attributeQuery('scaleFactor', n='gsScaleFactorStorageNode', ex=1):
sceneValue = mc.getAttr('gsScaleFactorStorageNode.scaleFactor')
else:
sceneValue = "####"
field = wrap.LineEdit("scaleFactorSelectedValue", sceneRow.layout())
field.setText(str(sceneValue))
field.setEnabled(False)
from . import main
main.checkScriptJobs(SCALE_FACTOR_UI)
def updateScaleFactorWindow():
WIDGETS["scaleFactorGlobalValue"].setText(str(mc.optionVar(q=('GSCT_globalScaleFactor'))))
if mc.objExists('gsScaleFactorStorageNode') and mc.attributeQuery('scaleFactor', n='gsScaleFactorStorageNode', ex=1):
sceneValue = mc.getAttr('gsScaleFactorStorageNode.scaleFactor')
else:
sceneValue = "####"
WIDGETS["scaleFactorSceneValue"].setText(str(sceneValue))
def scaleFactorConversionDialog():
MESSAGE.warningInView('Curves Without Scale Factor Detected')
dialog = mc.confirmDialog(
title='No Scale Factor',
message='Curves without scale factor detected\nThose Curves were created before v1.2.7 and might not convert correctly',
icon='warning',
button=['Skip Old Curves', 'Convert All', 'Cancel'],
cancelButton='Cancel',
dismissString='Cancel'
)
if dialog == 'Cancel':
return None
if dialog == 'Skip Old Curves':
return 'Skip'
if 'Convert All':
return 'All'
def curveThicknessWindow():
name = 'GSCT_CurveThicknessWindow'
if mc.workspaceControl(name, q=1, ex=1):
mc.deleteUI(name)
popOut = CreatePopOut(name, "Curve Thickness", 300, 65)
layout = popOut.widgetLayout
layout.setAlignment(QtCore.Qt.AlignTop)
m_slider = mc.floatSliderGrp('GSCT_curveThicknessSlider',
pre=3, ss=0.01, min=-1, max=10, fmn=0.001, fmx=1000, f=1,
v=mc.optionVar(q='GSCT_globalCurveThickness')
)
wrap.MayaSlider(m_slider, layout=layout)
with wrap.Row(layout, margins=style.scale([0, 5, 0, 0])) as row:
def save():
mc.optionVar(fv=('GSCT_globalCurveThickness', mc.floatSliderGrp('GSCT_curveThicknessSlider', q=1, v=1)))
mc.deleteUI(name)
def update():
mc.optionVar(fv=('GSCT_globalCurveThickness', mc.floatSliderGrp('GSCT_curveThicknessSlider', q=1, v=1)))
core.updateLayerThickness()
saveButton = wrap.Button(row.layout())
saveButton.setLabel('Save')
saveButton.clicked.connect(save)
updateCurves = wrap.Button(row.layout())
updateCurves.setLabel('Update Curves')
updateCurves.clicked.connect(update)
cancelButton = wrap.Button(row.layout())
cancelButton.setLabel('Cancel')
cancelButton.clicked.connect(lambda: mc.deleteUI(name))
def randomizeCurveWindow():
name = "GSCT_RandomizeCurvePopOut"
if mc.workspaceControl(name, q=1, ex=1):
if mc.workspaceControl(name, q=1, vis=1):
mc.deleteUI(name)
return
else:
mc.deleteUI(name)
popOut = CreatePopOut(name, "Randomize Curve", 270, 565)
layout = popOut.widgetLayout
layout.setAlignment(QtCore.Qt.AlignTop)
def release(slider, *_):
core.sliders.randSliderDrag(slider)
core.sliders.randSliderRelease(slider)
core.sliders.release()
# Control Points
with wrap.Frame(layout, label='Control Points') as frame:
frame.setCollapsible(False)
with wrap.Row(frame.getFrameLayout()) as row:
enable = wrap.Button(row.layout(), 'curveRandomizeSlider0')
enable.setLabel('Enabled', lineHeight=100)
enable.setButtonStyle('small')
enable.setCheckable(True)
slider = wrap.mayaSlider(mc.floatSliderGrp('gsCurveCVsRandMulti', l='Mult:',
min=1, max=50, pre=1, step=0.5, cw=[(1, 30), (2, 1)]))
row.layout().addWidget(slider)
with wrap.Row(frame.getFrameLayout()) as row:
lockFirst = wrap.Button(row.layout(), 'gsLockFirstCV')
lockFirst.setLabel('Lock First CV', lineHeight=100)
lockFirst.setButtonStyle('small')
lockFirst.setCheckable(True)
lockLast = wrap.Button(row.layout(), 'gsLockLastCV')
lockLast.setLabel('Lock Last CV', lineHeight=100)
lockLast.setButtonStyle('small')
lockLast.setCheckable(True)
with wrap.Row(frame.getFrameLayout()) as row:
axisX = wrap.Button(row.layout(), 'gsRandAxisX')
axisX.setLabel('X', lineHeight=100)
axisX.setButtonStyle('small')
axisX.setCheckable(True)
axisY = wrap.Button(row.layout(), 'gsRandAxisY')
axisY.setLabel('Y', lineHeight=100)
axisY.setButtonStyle('small')
axisY.setCheckable(True)
axisZ = wrap.Button(row.layout(), 'gsRandAxisZ')
axisZ.setLabel('Z', lineHeight=100)
axisZ.setButtonStyle('small')
axisZ.setCheckable(True)
wrap.MayaSlider(
mc.floatSliderGrp(
'gsCurveCVsRand', min=0, max=1, step=0.05,
dc=pa(core.sliders.randSliderDrag, 0),
cc=pa(release, 0),
),
layout=frame.getFrameLayout()
)
# Rotation
with wrap.Frame(layout, label='Rotation') as frame:
frame.setCollapsible(False)
with wrap.Row(frame.getFrameLayout()) as row:
enable = wrap.Button(row.layout(), 'curveRandomizeSlider1')
enable.setLabel('Enabled', lineHeight=100)
enable.setButtonStyle('small')
enable.setCheckable(True)
slider = wrap.mayaSlider(mc.floatSliderGrp('gsCurveRotationRandMulti', l='Mult:',
min=1, max=50, pre=1, step=0.5, cw=[(1, 30), (2, 1)]))
row.layout().addWidget(slider)
with wrap.Row(frame.getFrameLayout()) as row:
axisX = wrap.Button(row.layout(), 'gsRandRotateAxisX')
axisX.setLabel('X', lineHeight=100)
axisX.setButtonStyle('small')
axisX.setCheckable(True)
axisY = wrap.Button(row.layout(), 'gsRandRotateAxisY')
axisY.setLabel('Y', lineHeight=100)
axisY.setButtonStyle('small')
axisY.setCheckable(True)
axisZ = wrap.Button(row.layout(), 'gsRandRotateAxisZ')
axisZ.setLabel('Z', lineHeight=100)
axisZ.setButtonStyle('small')
axisZ.setCheckable(True)
wrap.MayaSlider(
mc.floatSliderGrp(
'gsCurveRotationRand', min=0, max=1, step=0.05,
dc=pa(core.sliders.randSliderDrag, 1),
cc=pa(release, 1),
),
layout=frame.getFrameLayout()
)
# Orientation
with wrap.Frame(layout, label='Orientation') as frame:
frame.setCollapsible(False)
with wrap.Row(frame.getFrameLayout()) as row:
enable = wrap.Button(row.layout(), 'curveRandomizeSlider2')
enable.setLabel('Enabled', lineHeight=100)
enable.setButtonStyle('small')
enable.setCheckable(True)
slider = wrap.mayaSlider(mc.floatSliderGrp('gsCurveOrientationRandMulti', l='Mult:',
min=1, max=50, pre=1, step=0.5, cw=[(1, 30), (2, 1)]))
row.layout().addWidget(slider)
wrap.MayaSlider(
mc.floatSliderGrp(
'gsCurveOrientationRand', min=0, max=1, step=0.05,
dc=pa(core.sliders.randSliderDrag, 2),
cc=pa(release, 2),
),
layout=frame.getFrameLayout()
)
# Twist
with wrap.Frame(layout, label='Twist') as frame:
frame.setCollapsible(False)
with wrap.Row(frame.getFrameLayout()) as row:
enable = wrap.Button(row.layout(), 'curveRandomizeSlider3')
enable.setLabel('Enabled', lineHeight=100)
enable.setButtonStyle('small')
enable.setCheckable(True)
slider = wrap.mayaSlider(mc.floatSliderGrp('gsCurveTwistRandMulti', l='Mult:',
min=1, max=50, pre=1, step=0.5, cw=[(1, 30), (2, 1)]))
row.layout().addWidget(slider)
wrap.MayaSlider(
mc.floatSliderGrp(
'gsCurveTwistRand', min=0, max=1, step=0.05,
dc=pa(core.sliders.randSliderDrag, 3),
cc=pa(release, 3),
),
layout=frame.getFrameLayout()
)
# Width
with wrap.Frame(layout, label='Width') as frame:
frame.setCollapsible(False)
with wrap.Row(frame.getFrameLayout()) as row:
enable = wrap.Button(row.layout(), 'curveRandomizeSlider4')
enable.setLabel('Enabled', lineHeight=100)
enable.setButtonStyle('small')
enable.setCheckable(True)
slider = wrap.mayaSlider(mc.floatSliderGrp('gsCurveWidthRandMulti', l='Mult:',
min=1, max=50, pre=1, step=0.5, cw=[(1, 30), (2, 1)]))
row.layout().addWidget(slider)
uniform = wrap.Button(frame.getFrameLayout(), 'gsWidthCheckBoxUniform')
uniform.setButtonStyle('small')
uniform.setLabel('Uniform', lineHeight=100)
uniform.setCheckable(True)
wrap.MayaSlider(
mc.floatSliderGrp(
'gsCurveWidthRand', min=0.001, max=1, step=0.05,
dc=pa(core.sliders.randSliderDrag, 4),
cc=pa(release, 4),
),
layout=frame.getFrameLayout()
)
# Taper
with wrap.Frame(layout, label='Taper') as frame:
frame.setCollapsible(False)
with wrap.Row(frame.getFrameLayout()) as row:
enable = wrap.Button(row.layout(), 'curveRandomizeSlider5')
enable.setLabel('Enabled', lineHeight=100)
enable.setButtonStyle('small')
enable.setCheckable(True)
slider = wrap.mayaSlider(mc.floatSliderGrp('gsCurveTaperRandMulti', l='Mult:',
min=1, max=50, pre=1, step=0.5, cw=[(1, 30), (2, 1)]))
row.layout().addWidget(slider)
wrap.MayaSlider(
mc.floatSliderGrp(
'gsCurveTaperRand', min=0, max=1, step=0.05,
dc=pa(core.sliders.randSliderDrag, 5),
cc=pa(release, 5),
),
layout=frame.getFrameLayout()
)
# Profile
with wrap.Frame(layout, label='Profile') as frame:
frame.setCollapsible(False)
with wrap.Row(frame.getFrameLayout()) as row:
enable = wrap.Button(row.layout(), 'curveRandomizeSlider6')
enable.setLabel('Enabled', lineHeight=100)
enable.setButtonStyle('small')
enable.setCheckable(True)
slider = wrap.mayaSlider(mc.floatSliderGrp('gsCurveProfileRandMulti', l='Mult:',
min=1, max=50, pre=1, step=0.5, cw=[(1, 30), (2, 1)]))
row.layout().addWidget(slider)
uniform = wrap.Button(frame.getFrameLayout(), 'gsProfileCheckBoxNegative')
uniform.setButtonStyle('small')
uniform.setLabel('Allow Negative Values', lineHeight=100)
uniform.setCheckable(True)
wrap.MayaSlider(
mc.floatSliderGrp(
'gsCurveProfileRand', min=0, max=1, step=0.05,
dc=pa(core.sliders.randSliderDrag, 6),
cc=pa(release, 6),
),
layout=frame.getFrameLayout()
)
# Selection
with wrap.Frame(layout, label='Selection') as frame:
frame.setCollapsible(False)
enable = wrap.Button(frame.getFrameLayout(), 'curveRandomizeSlider7')
enable.setLabel('Enabled', lineHeight=100)
enable.setButtonStyle('small')
enable.setCheckable(True)
wrap.MayaSlider(
mc.floatSliderGrp(
'gsCurveSelectRand', min=0, max=1, step=0.05,
dc=pa(core.sliders.randSliderDrag, 7),
cc=pa(release, 7),
),
layout=frame.getFrameLayout()
)
layout.addWidget(wrap.separator())
with wrap.Row(layout) as row:
def randomizeClick():
core.sliders.randSliderDrag(-1)
core.sliders.randSliderRelease(-1)
core.sliders.release()
randomize = wrap.Button(row.layout())
randomize.setLabel("Randomize")
randomize.clicked.connect(randomizeClick)
close = wrap.Button(row.layout())
close.setLabel("Close")
close.clicked.connect(lambda: mc.deleteUI(name))