Last active
December 13, 2018 06:50
-
-
Save Onefabis/880764ea5b1379a7c06f8193318c02e5 to your computer and use it in GitHub Desktop.
Custom slider for maya
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PySide import QtGui,QtCore | |
import maya.OpenMayaUI as mui | |
import shiboken | |
import sys | |
class AttrFieldGroup(QtGui.QWidget): | |
valueChanged = QtCore.Signal(float) | |
def __init__(self, parent=None): | |
super(AttrFieldGroup, self).__init__(parent) | |
# Set the range of the slider and inital value | |
self.minRange = -100 | |
self.maxRange = 100 | |
self.zero = 0 | |
# Create dummy button to prevent missimg press on the slider | |
self.dummyB = QtGui.QPushButton ( self ) | |
self.dummyB.setGeometry( QtCore.QRect( 15, 17, 160, 23 ) ) | |
# Create input field | |
self.input = QtGui.QLineEdit(self) | |
# Alignment of the text inside the input field | |
self.input.setAlignment(QtCore.Qt.AlignCenter) | |
# Validator to limit the input values to the numbers | |
self.inputValidator = QtGui.QDoubleValidator() | |
self.inputValidator.setDecimals(0) | |
self.input.setValidator(self.inputValidator) | |
self.input.editingFinished.connect(self.fieldEdited) | |
self.input.textChanged.connect(self.inputCheck) | |
# Create slider | |
self.slider = QtGui.QSlider(self) | |
self.slider.setOrientation(QtCore.Qt.Horizontal) | |
self.slider.setRange( self.minRange, self.maxRange ) | |
self.slider.setGeometry(15, 0,160,50) | |
self.slider.setSingleStep(1) | |
# Attach slider to the different behaviours (move, press, release the handle) | |
self.slider.sliderMoved.connect(self.sliderMoved) | |
self.slider.sliderPressed.connect(self.sliderPressed) | |
self.slider.sliderReleased.connect(self.sliderReleased) | |
# Set initial value of the slider to zero | |
self.setValue( self.zero, 'st' ) | |
# Create 'close button' with connected 'close' function | |
self.but = QtGui.QPushButton( 'x', self ) | |
self.but.pressed.connect( self.winClose ) | |
#self.label.setAlignment( QtCore.Qt.AlignCenter ) | |
self.but.setGeometry( 178, 18, 13, 15 ) | |
# Create combo box | |
self.comboBox = QtGui.QComboBox( self ) | |
self.comboBox.addItem( 'Item 1' ) | |
self.comboBox.addItem( 'Item 2' ) | |
self.comboBox.addItem( 'Item 3' ) | |
self.comboBox.addItem( 'Item 4' ) | |
self.comboBox.currentIndexChanged.connect(self.changeComboB) | |
if int(mc.about(v=1)[3]) <= 5: | |
self.comboBox.setStyleSheet( 'QComboBox{background-color: rgba(30,30,30,180);border-radius: 2px;border: 1px solid #767676; color:#c5c5c5 } QComboBox::drop-down{border: none} QComboBox::down-arrow{ image: url(:/arrowDown.png); padding: 1px 1px 0 0 }' ) | |
else: | |
self.comboBox.setStyleSheet( 'QComboBox{background-color: rgba(30,30,30,180);border-radius: 2px;border: 1px solid #767676; color:#c5c5c5 } QComboBox::drop-down{border: none} QComboBox::down-arrow{ image: url(:/popupMenuIcon.png)}' ) | |
self.comboBox.setGeometry( 15, 35, 64, 16 ) | |
# Create checkbox | |
self.chBox = QtGui.QCheckBox( '',self ) | |
#self.chBox.setGeometry( 15, 80, 20, 20 ) | |
self.chBox.move(92, 35) | |
# Change the style of the checkbox | |
if int(mc.about(v=1)[3]) <= 5: | |
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0; padding: 0 0 0 2px; image: url(:/checkboxOff.png)}' ) | |
else: | |
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0; padding: 0; image: url(:/checkboxOff.png)}' ) | |
self.chBox.setCheckState(QtCore.Qt.Unchecked) | |
self.chBox.stateChanged.connect( self.chBoxChange ) | |
self.chBoxChange() | |
# Drop shadow effect for any element (template) | |
#shad = QtGui.QGraphicsDropShadowEffect(self) | |
#shad.setBlurRadius( 4 ) | |
#shad.setColor( 'black' ) | |
#shad.setOffset( 0 ) | |
#self.label.setGraphicsEffect( shad ) | |
# Tweak elements style | |
self.slider.setStyleSheet('QSlider::groove:horizontal {height: 5px;padding: 0 4px;border: 1px solid #767676;border-radius: 2px;background: rgba(30,30,30,180);filter:alpha(opacity=50);} QSlider::handle:horizontal { height: 10px; width 5px; margin: -5px -5px;background-color: #e46b00;border-radius: 2px; border: 1px solid #a24c00 } QSlider::handle:horizontal:hover{background-color: #eb7b19;border: 1px solid #c25c02;} ') | |
self.input.setStyleSheet('QLineEdit{background: rgba(30,30,30,180);border-radius: 2px; border: 1px solid #767676;padding-bottom:1px}') | |
self.but.setStyleSheet('QPushButton{background-color:#575757; color:#c5c5c5; padding: 0 0 2px 1px; border-radius: 2px; border: 1px solid #3c3a37;} QPushButton:hover{background-color:#6e6e6e;} QPushButton:pressed{background-color:#363636}') | |
self.input.setGeometry(( 100*(self.zero-self.minRange))/(self.maxRange-self.minRange)*1.6-(((100*(self.zero-self.minRange))/(self.maxRange-self.minRange))/50.0-1)*5, 0,30,18) | |
self.dummyB.setStyleSheet( 'QPushButton{background-color: rgba(30,30,30,1);border: none;} ' ) | |
def switchWindow( self ): | |
LightTween().valPrint() | |
def switchSimple( self ): | |
LightTween().valPrint() | |
# Function called when combobox switched | |
def changeComboB( self ): | |
sItem = self.comboBox.currentIndex() | |
print sItem | |
def chBoxChange ( self ): | |
if self.chBox.isChecked(): | |
self.chBox.setText('Selected') | |
if int(mc.about(v=1)[3]) <= 5: | |
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0; padding: 0 0 0 2px; image: url(:/checkboxOn.png)}' ) | |
else: | |
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0; padding: 0; image: url(:/checkboxOn.png)}' ) | |
else: | |
self.chBox.setText('Unselected') | |
if int(mc.about(v=1)[3]) <= 5: | |
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0 0 0 2px; padding: 0; image: url(:/checkboxOff.png)}' ) | |
else: | |
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0; padding: 0; image: url(:/checkboxOff.png)}' ) | |
# 'Simple' function called from RMB menu | |
def value(self): | |
return float(self.input.text()) | |
# Function called to set the slider to initial value defined by self.zero variable | |
def setValue(self, v, stQ ): | |
self.input.setText("%0.0f" % float(v)) | |
if stQ == 'ed': | |
self.fieldEdited() | |
# Function called by moving the slider handle | |
def sliderMoved(self, val): | |
self.input.setText('%0.0f' % (val)) | |
self._emitValueChanged() | |
percentV = 100*(val-self.minRange)/(self.maxRange-self.minRange) | |
self.input.setGeometry( percentV*1.6-(percentV/50.0-1)*5, 0,30,18) | |
#print val/1.00 | |
# Function called when mouse cursor click on the slider but outside the handle | |
def sliderPressed(self): | |
val = self.slider.value() | |
self.input.setText('%0.0f' % (val)) | |
percentV = 100*(val-self.minRange)/(self.maxRange-self.minRange) | |
self.input.setGeometry( percentV*1.6-(percentV/50.0-1)*5, 0,30,18) | |
self._emitValueChanged() | |
# Function performed by release of the slider handle | |
def sliderReleased(self): | |
val = float(self.input.text()) | |
LightTween().valPrint( val ) | |
# Function to limit input text field number to the range limit of the slider | |
def inputCheck(self): | |
val = self.input.text() | |
if val and val != "-" and val[0] != 'e': | |
val = float( self.input.text() ) | |
maxNum = [ str( abs( self.minRange ) ), str( abs( self.maxRange ) ) ] | |
if val > self.maxRange or val < self.minRange: | |
if val < 0 and val != self.minRange: | |
newVal = str(val)[:len ( maxNum[0] )] | |
self.input.setText(newVal) | |
elif val > 0 and val != self.maxRange: | |
newVal = str(val)[:len ( maxNum[1] )-1] | |
self.input.setText(newVal) | |
# Function performed when 'Enter' key pressed with the input field in focus | |
def fieldEdited(self): | |
val = float(self.input.text()) | |
slval = float(self.slider.value()) | |
if slval != val: | |
LightTween().valPrint( val ) | |
self.slider.setValue(int(val) ) | |
percentV = 100*(val-self.minRange)/(self.maxRange-self.minRange) | |
self.input.setGeometry( percentV*1.6-(percentV/50.0-1)*5, 0,30,18) | |
def _emitValueChanged(self): | |
self.valueChanged.emit(float(self.input.text())) | |
# Function to close the window by 'close' button | |
def winClose(self): | |
if mc.window( 'LightTween', ex=1): | |
mc.deleteUI( 'LightTween', wnd=1 ) | |
class LightTween ( object ): | |
def __init__( self ): | |
pass | |
def LightTweenUI ( self ): | |
try: | |
if mc.window( 'LightTween', ex=1 ): | |
mc.deleteUI( 'LightTween', wnd=1 ) | |
except: pass | |
mayaWin = shiboken.wrapInstance( long( mui.MQtUtil.mainWindow() ), QtGui.QWidget ) | |
# Create the main window | |
windowName = 'LightTween' | |
self.win = QtGui.QMainWindow( mayaWin ) | |
# Create the name for the main window | |
self.win.setObjectName( windowName ) | |
# Create the main widget | |
self.widget = QtGui.QWidget() | |
# Make the window 'frameless', without title head | |
self.win.setWindowFlags( QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint ) | |
# Make the window 'transparent', allowing selection behind it | |
self.win.setAttribute( QtCore.Qt.WA_NoSystemBackground, 1 ) | |
self.win.setAttribute( QtCore.Qt.WA_TranslucentBackground, 1 ) | |
self.win.setAttribute( QtCore.Qt.WA_PaintOnScreen) | |
# Set main widget as central inside the window | |
self.win.setCentralWidget( self.widget ) | |
self.ctrl = AttrFieldGroup( self.widget ) | |
self.ctrl.setGeometry( 0, 0, 194, 50 ) | |
self.sign = AttrFieldGroup() | |
# 'Under the cursor' positioning functionality (uncomment it) | |
#pos = QtGui.QCursor.pos() | |
#mc.window( windowName, e=1, tlc=[pos.y()-25, pos.x()-95 ] ) | |
# Right mouse ( Popup ) menu atteched to the slider | |
name = mui.MQtUtil.fullName(long(shiboken.getCppPointer(self.win)[0])) | |
mc.popupMenu(p=name) | |
mc.menuItem('Dummy item 1') | |
mc.menuItem('Dummy item 2') | |
mc.menuItem('Dummy item 3') | |
self.win.show() | |
def valPrint( self, val ): | |
print val | |
# Launch the script | |
LightTween().LightTweenUI() |
Updated with the commens of the main functions of the script
Function 'inputCheck' will filter the input value and limit user to enter the value bigger than 'self.maxRange' and smaller than 'self.minRange' pre-defined in the script to prevent slider to perform unpredictable drawing and performing
Create popup menu in a simpler way, also added a function tha check for value printing from the input field or from the slider, but presepving duble printing of the result.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Added support for the RMB menu. addMenuActions creates that menu, items calls for dummy functions