First off, we should have a minimal test case. When things really don’t work as expected, step 1 is to make the smallest possible code that reproduces the bug. This has gone back and forth enough that it’s worth taking that time.
(I don’t know what they’re actually called, so I’m calling the thing we drag the “indicator” and the line that we can drag the indicator along the “bar”)
And in my testing, it looks the signals aren’t getting triggered in the order I’m expecting when I click on the bar and the indicator pops over to the click position. In that case, the valueChanged is getting called before the undoOpen, and we’re getting changes happening outside the undo chunk. Best way I can think to do this is add a variable that keeps track of whether we’re supposed to be in a chunk, and add some protections for double-open or double-close.
# I'm using Qt.py
# If you're not, you'll have to change these Qt imports to something that works for you
from Qt.QtWidgets import QDialog, QVBoxLayout, QSlider, QApplication
from Qt.QtCore import Qt
from maya import cmds
class SliderTest(QDialog):
def __init__(self, parent=None):
super(SliderTest, self).__init__(parent)
self.resize(400, 37)
self.vLayout = QVBoxLayout(self)
self.hSlider = QSlider(self)
self.hSlider.setOrientation(Qt.Horizontal)
self.vLayout.addWidget(self.hSlider)
self.hSlider.sliderPressed.connect(lambda : self.undoOpen("SlideTest"))
self.hSlider.sliderReleased.connect(self.undoClose)
self.hSlider.valueChanged.connect(self.updateValue)
self._inChunk = False
# Create a new image plane just for testing
self.node = cmds.imagePlane(width=100, height=50)[-1]
def undoOpen(self, name):
if not self._inChunk: # make sure we don't double-open the chunk
self._inChunk = True
cmds.undoInfo(openChunk=True, chunkName=name)
def undoClose(self, name):
if self._inChunk: # make sure we don't double-close the chunk
self._inChunk = False
cmds.undoInfo(closeChunk=True)
def updateValue(self, val):
self.undoOpen("SlideTest")
width = cmds.getAttr("{0}.width".format(self.node))
height = cmds.getAttr("{0}.height".format(self.node))
ratio = float(height) / width
cmds.setAttr("{0}.maintainRatio".format(self.node), 0)
cmds.setAttr("{0}.width".format(self.node), val)
cmds.setAttr("{0}.height".format(self.node), val * ratio)
cmds.setAttr("{0}.maintainRatio".format(self.node), 1)
# Get the Maya Main Window quick-n-dirty
app = QApplication.instance()
mayaWin = [i for i in app.topLevelWidgets() if i.objectName() == "MayaWindow"][0]
# start the test UI
st = SliderTest(mayaWin)
st.show()