Updated
This commit is contained in:
476
Scripts/Animation/springmagic/ui.py
Normal file
476
Scripts/Animation/springmagic/ui.py
Normal file
@ -0,0 +1,476 @@
|
||||
import os
|
||||
import time
|
||||
import inspect
|
||||
import webbrowser
|
||||
try:
|
||||
import urllib.request as urllib
|
||||
except:
|
||||
import urllib2 as urllib
|
||||
import random
|
||||
import datetime
|
||||
import maya.mel as mel
|
||||
import pymel.core as pm
|
||||
|
||||
import Animation.springmagic.core as core
|
||||
|
||||
from shutil import copyfile
|
||||
|
||||
kSpringMagicVersion = 30500
|
||||
|
||||
scriptName = inspect.getframeinfo(inspect.currentframe()).filename
|
||||
scriptPath = os.path.dirname(os.path.abspath(scriptName))
|
||||
|
||||
# Parameter Initialization
|
||||
ui_file = scriptPath + os.sep + 'springMagic.ui'
|
||||
|
||||
# Constants
|
||||
kPaypalLink = r'https://www.paypal.me/Yanbin'
|
||||
kLinkedinLink = r'https://ca.linkedin.com/in/baiyanbin'
|
||||
kVimeoLink = r''
|
||||
kBilibiliLink = r'https://animbai.com/zh/2017/10/14/skintools-tutorials/'
|
||||
kYoutubeLink = r'https://animbai.com/2017/10/14/skintools-tutorials/'
|
||||
|
||||
kUpdateLink = r'https://animbai.com/category/download/'
|
||||
kVersionCheckLink = r'http://animbai.com/skintoolsver/'
|
||||
kOldPersonalLink = r'http://www.scriptspot.com/3ds-max/scripts/spring-magic'
|
||||
|
||||
def widgetPath(windowName, widgetNames):
|
||||
"""
|
||||
@param windowName: Window instance name to search
|
||||
@param widgetNames: list of names to search for
|
||||
"""
|
||||
returnDict = {}
|
||||
mayaWidgetList = pm.lsUI(dumpWidgets=True)
|
||||
|
||||
for widget in widgetNames:
|
||||
for mayaWidget in mayaWidgetList:
|
||||
if windowName in mayaWidget:
|
||||
if mayaWidget.endswith(widget):
|
||||
returnDict[widget] = mayaWidget
|
||||
|
||||
return returnDict
|
||||
|
||||
class SpringMagicWidget():
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.init()
|
||||
|
||||
def init(self):
|
||||
try:
|
||||
pm.deleteUI(self.ui)
|
||||
except:
|
||||
pass
|
||||
|
||||
# title = pm.window(pm.loadUI(ui_file = ui_file))
|
||||
|
||||
self.ui = pm.loadUI(f=ui_file)
|
||||
|
||||
ui_widget_list = [
|
||||
'donatePayPal_button',
|
||||
'main_progressBar',
|
||||
'main_processLabel',
|
||||
'main_textEdit',
|
||||
'main_lang_id',
|
||||
'spring_language_list',
|
||||
'springSpring_lineEdit',
|
||||
'springSubs_lineEdit',
|
||||
'springXspring_lineEdit',
|
||||
'springTension_lineEdit',
|
||||
'springExtend_lineEdit',
|
||||
'springInertia_lineEdit',
|
||||
'springSubDiv_lineEdit',
|
||||
'springLoop_checkBox',
|
||||
'springPoseMatch_checkBox',
|
||||
'springClearSubFrame_checkBox',
|
||||
'springFrom_lineEdit',
|
||||
'springEnd_lineEdit',
|
||||
'springActive_radioButton',
|
||||
'springFrom_radioButton',
|
||||
# 'springUpAxis_comboBox',
|
||||
'springApply_Button',
|
||||
'springCapsule_checkBox',
|
||||
'springFastMove_checkBox',
|
||||
'springFloor_checkBox',
|
||||
'springFloor_lineEdit',
|
||||
'springBindPose_button',
|
||||
'springStraight_button',
|
||||
'springCopy_button',
|
||||
'springPaste_button',
|
||||
# 'donateBitcoin_lineEdit',
|
||||
'miscUpdate_pushButton',
|
||||
'springAddBody_Button',
|
||||
'springClearBody_Button',
|
||||
'springAddPlane_Button',
|
||||
'springAddWindCmd',
|
||||
'springBind_Button',
|
||||
'springBake_Button',
|
||||
'shelf_button',
|
||||
'link_pushButton',
|
||||
'vimeo_pushButton',
|
||||
'bilibili_pushButton',
|
||||
'language_button',
|
||||
'statusbar',
|
||||
'springWind_Button']
|
||||
|
||||
self.uiObjects = widgetPath(self.ui, ui_widget_list)
|
||||
|
||||
# Main UI
|
||||
self.main_progressBar = pm.progressBar(self.uiObjects['main_progressBar'], edit=True)
|
||||
self.main_processLabel = pm.text(self.uiObjects['main_processLabel'], edit=True)
|
||||
self.main_lineEdit = pm.ui.PyUI(self.uiObjects['main_textEdit'], edit=True)
|
||||
self.lang_id = pm.text(self.uiObjects['main_lang_id'], edit=True)
|
||||
|
||||
self.language_list = pm.textScrollList(self.uiObjects['spring_language_list'], edit=True, selectCommand=self.languageSelectedCmd, visible=False)
|
||||
|
||||
self.spring_lineEdit = pm.textField(self.uiObjects['springSpring_lineEdit'], edit=True, changeCommand=self.springRatioChangeCmd)
|
||||
self.subs_lineEdit = pm.textField(self.uiObjects['springSubs_lineEdit'], edit=True)
|
||||
self.Xspring_lineEdit = pm.textField(self.uiObjects['springXspring_lineEdit'], edit=True, changeCommand=self.twistChangeCmd)
|
||||
self.tension_lineEdit = pm.textField(self.uiObjects['springTension_lineEdit'], edit=True, changeCommand=self.tensionChangeCmd)
|
||||
self.extend_lineEdit = pm.textField(self.uiObjects['springExtend_lineEdit'], edit=True, changeCommand=self.extendChangeCmd)
|
||||
self.inertia_lineEdit = pm.textField(self.uiObjects['springInertia_lineEdit'], edit=True, changeCommand=self.inertiaChangeCmd)
|
||||
self.sub_division_lineEdit = pm.textField(self.uiObjects['springSubDiv_lineEdit'], edit=True, changeCommand=self.subDivChangeCmd)
|
||||
self.loop_checkBox = pm.checkBox(self.uiObjects['springLoop_checkBox'], edit=True)
|
||||
self.pose_match_checkBox = pm.checkBox(self.uiObjects['springPoseMatch_checkBox'], edit=True)
|
||||
self.clear_subframe_checkBox = pm.checkBox(self.uiObjects['springClearSubFrame_checkBox'], edit=True)
|
||||
self.from_lineEdit = pm.textField(self.uiObjects['springFrom_lineEdit'], edit=True)
|
||||
self.end_lineEdit = pm.textField(self.uiObjects['springEnd_lineEdit'], edit=True)
|
||||
self.active_radioButton = pm.radioButton(self.uiObjects['springActive_radioButton'], edit=True)
|
||||
self.from_radioButton = pm.radioButton(self.uiObjects['springFrom_radioButton'], edit=True)
|
||||
# self.upAxis_comboBox = pm.optionMenu(self.uiObjects['springUpAxis_comboBox'], edit=True)
|
||||
self.apply_button = pm.button(self.uiObjects['springApply_Button'], edit=True, command=self.applyCmd)
|
||||
self.add_body_button = pm.button(self.uiObjects['springAddBody_Button'], edit=True, command=self.addBodyCmd)
|
||||
self.clear_body_button = pm.button(self.uiObjects['springClearBody_Button'], edit=True, command=self.clearBodyCmd)
|
||||
self.add_plane_button = pm.button(self.uiObjects['springAddPlane_Button'], edit=True, command=self.createColPlaneCmd)
|
||||
self.wind_button = pm.button(self.uiObjects['springWind_Button'], edit=True, command=self.addWindCmd)
|
||||
self.bind_button = pm.button(self.uiObjects['springBind_Button'], edit=True, command=self.bindControlsCmd)
|
||||
self.bake_button = pm.button(self.uiObjects['springBake_Button'], edit=True, command=self.clearBindCmd)
|
||||
self.shelf_button = pm.button(self.uiObjects['shelf_button'], edit=True, command=self.goShelfCmd)
|
||||
self.link_button = pm.button(self.uiObjects['link_pushButton'], edit=True, command=self.linkinCmd)
|
||||
self.vimeo_button = pm.button(self.uiObjects['vimeo_pushButton'], edit=True, command=self.youtubeCmd)
|
||||
self.bilibili_button = pm.button(self.uiObjects['bilibili_pushButton'], edit=True, command=self.bilibiliCmd)
|
||||
self.language_button = pm.button(self.uiObjects['language_button'], edit=True, command=self.languageCmd)
|
||||
|
||||
self.collision_checkBox = pm.checkBox(self.uiObjects['springCapsule_checkBox'], edit=True)
|
||||
self.fast_move_checkBox = pm.checkBox(self.uiObjects['springFastMove_checkBox'], edit=True)
|
||||
self.floor_checkBox = pm.checkBox(self.uiObjects['springFloor_checkBox'], edit=True)
|
||||
self.floor_lineEdit = pm.textField(self.uiObjects['springFloor_lineEdit'], edit=True, changeCommand=self.twistChangeCmd)
|
||||
|
||||
self.bind_pose_button = pm.button(self.uiObjects['springBindPose_button'], edit=True, command=self.setCmd)
|
||||
self.straight_button = pm.button(self.uiObjects['springStraight_button'], edit=True, command=self.straightCmd)
|
||||
self.copy_button = pm.button(self.uiObjects['springCopy_button'], edit=True, command=self.copyCmd)
|
||||
self.paste_button = pm.button(self.uiObjects['springPaste_button'], edit=True, command=self.pasteCmd)
|
||||
|
||||
# self.statusbar = pm.button(self.uiObjects['statusbar'], edit=True, menuItemCommand=self.testCmd)
|
||||
|
||||
# donate UI
|
||||
# self.donate_bitcoin_lineEdit = pm.textField(self.uiObjects['donateBitcoin_lineEdit'], edit=True, text=kBitcoin)
|
||||
|
||||
self.misc_update_button = pm.button(self.uiObjects['miscUpdate_pushButton'], edit=True, command=self.updatePageCmd)
|
||||
|
||||
# SpringMagic_mainWindow11|centralwidget|miscUpdate_pushButton
|
||||
# SpringMagic_mainWindow11|centralwidget|miscUpdate_pushButton
|
||||
# 'miscUpdate_pushButton': ui.Button('SpringMagic_mainWindow11|centralwidget|miscUpdate_pushButton')
|
||||
# miscUpdate_button = pm.button( centralwidget + '|miscUpdate_pushButton', edit = True )
|
||||
|
||||
pm.button(self.uiObjects['donatePayPal_button'], edit=True, command=self.donatePayPalCmd)
|
||||
|
||||
self.spam_word = ['', '', '', '', '']
|
||||
|
||||
def show(self):
|
||||
|
||||
pm.showWindow(self.ui)
|
||||
|
||||
self.checkUpdate()
|
||||
|
||||
def progression_callback(self, progression):
|
||||
pm.progressBar(self.main_progressBar, edit=True, progress=progression)
|
||||
|
||||
#############################################
|
||||
# Buttons callbacks
|
||||
############################################
|
||||
|
||||
def showSpam(self, *args):
|
||||
sWord = self.spam_word[random.randint(0, 4)]
|
||||
# print as unicode
|
||||
pm.text(self.main_processLabel, edit=True, label=str(sWord))
|
||||
|
||||
def linkinCmd(self, *args):
|
||||
# open my linked in page :)
|
||||
url = kLinkedinLink
|
||||
|
||||
webbrowser.open(url, new=2)
|
||||
|
||||
def pasteCmd(self, *args):
|
||||
core.pasteBonePose()
|
||||
|
||||
def setCmd(self, *args):
|
||||
|
||||
picked_bones = pm.ls(sl=1, type='joint')
|
||||
|
||||
if picked_bones:
|
||||
self.apply_button.setEnable(False)
|
||||
|
||||
core.bindPose()
|
||||
|
||||
# Select only the joints
|
||||
pm.select(picked_bones)
|
||||
|
||||
self.apply_button.setEnable(True)
|
||||
|
||||
def straightCmd(self, *args):
|
||||
|
||||
picked_bones = pm.ls(sl=1, type='joint')
|
||||
|
||||
if picked_bones:
|
||||
self.apply_button.setEnable(False)
|
||||
|
||||
for bone in picked_bones:
|
||||
core.straightBonePose(bone)
|
||||
|
||||
# Select only the joints
|
||||
pm.select(picked_bones)
|
||||
|
||||
self.apply_button.setEnable(True)
|
||||
|
||||
def applyCmd(self, *args):
|
||||
picked_transforms = pm.ls(sl=1, type='transform')
|
||||
|
||||
if picked_transforms:
|
||||
self.apply_button.setEnable(False)
|
||||
|
||||
pm.text(self.main_processLabel, edit=True, label='Calculating Bone Spring... (Esc to cancel)')
|
||||
|
||||
springRatio = 1 - float(self.spring_lineEdit.getText())
|
||||
twistRatio = 1 - float(self.Xspring_lineEdit.getText())
|
||||
isLoop = bool(self.loop_checkBox.getValue())
|
||||
isPoseMatch = bool(self.pose_match_checkBox.getValue())
|
||||
isFastMove = self.fast_move_checkBox.getValue()
|
||||
isCollision = self.collision_checkBox.getValue()
|
||||
|
||||
subDiv = 1.0
|
||||
if isCollision:
|
||||
subDiv = float(self.sub_division_lineEdit.getText())
|
||||
|
||||
# get frame range
|
||||
if self.active_radioButton.getSelect():
|
||||
startFrame = int(pm.playbackOptions(q=1, minTime=1))
|
||||
endFrame = int(pm.playbackOptions(q=1, maxTime=1))
|
||||
else:
|
||||
startFrame = int(self.from_lineEdit.getText())
|
||||
endFrame = int(self.end_lineEdit.getText())
|
||||
|
||||
tension = float(self.tension_lineEdit.getText())
|
||||
inertia = float(self.inertia_lineEdit.getText())
|
||||
extend = float(self.extend_lineEdit.getText())
|
||||
|
||||
wipeSubFrame = self.clear_subframe_checkBox.getValue()
|
||||
|
||||
spring = core.Spring(springRatio, twistRatio, tension, extend, inertia)
|
||||
springMagic = core.SpringMagic(startFrame, endFrame, subDiv, isLoop, isPoseMatch, isCollision, isFastMove, wipeSubFrame)
|
||||
|
||||
startTime = datetime.datetime.now()
|
||||
|
||||
try:
|
||||
core.startCompute(spring, springMagic, self.progression_callback)
|
||||
|
||||
deltaTime = (datetime.datetime.now() - startTime)
|
||||
|
||||
pm.text(self.main_processLabel, edit=True, label="Spring Calculation Time: {0}s".format(deltaTime.seconds))
|
||||
|
||||
except ValueError as exception:
|
||||
pm.text(self.main_processLabel, edit=True, label='Process aborted')
|
||||
pm.warning(exception)
|
||||
|
||||
# Select only the joints
|
||||
pm.select(picked_transforms)
|
||||
|
||||
pm.progressBar(self.main_progressBar, edit=True, progress=0)
|
||||
|
||||
self.apply_button.setEnable(True)
|
||||
|
||||
def copyCmd(self, *args):
|
||||
core.copyBonePose()
|
||||
|
||||
def webCmd(self, *args):
|
||||
# open my linked in page :)
|
||||
webbrowser.open(kOldPersonalLink, new=2)
|
||||
|
||||
def twistChangeCmd(self, *args):
|
||||
self.limitTextEditValue(self.Xspring_lineEdit, defaultValue=0.7)
|
||||
|
||||
def extendChangeCmd(self, *args):
|
||||
self.limitTextEditValue(self.extend_lineEdit, defaultValue=0.0)
|
||||
|
||||
def inertiaChangeCmd(self, *args):
|
||||
self.limitTextEditValue(self.inertia_lineEdit, defaultValue=0.0)
|
||||
|
||||
def springRatioChangeCmd(self, *args):
|
||||
self.limitTextEditValue(self.spring_lineEdit, defaultValue=0.7)
|
||||
|
||||
def tensionChangeCmd(self, *args):
|
||||
self.limitTextEditValue(self.tension_lineEdit, defaultValue=0.5)
|
||||
|
||||
def subDivChangeCmd(self, *args):
|
||||
# self.limitTextEditValue(self.sub_division_lineEdit, defaultValue=1)
|
||||
pass
|
||||
|
||||
def addWindCmd(self, *args):
|
||||
core.addWindObj()
|
||||
|
||||
def addBodyCmd(self, *args):
|
||||
core.addCapsuleBody()
|
||||
|
||||
def createColPlaneCmd(self, *args):
|
||||
core.createCollisionPlane()
|
||||
|
||||
def removeBodyCmd(self, *args):
|
||||
core.removeBody(clear=False)
|
||||
|
||||
def clearBodyCmd(self, *args):
|
||||
core.removeBody(clear=True)
|
||||
|
||||
def bindControlsCmd(self, *args):
|
||||
core.bindControls()
|
||||
|
||||
def clearBindCmd(self, *args):
|
||||
|
||||
# get frame range
|
||||
if self.active_radioButton.getSelect():
|
||||
startFrame = int(pm.playbackOptions(q=1, minTime=1))
|
||||
endFrame = int(pm.playbackOptions(q=1, maxTime=1))
|
||||
else:
|
||||
startFrame = int(self.from_lineEdit.getText())
|
||||
endFrame = int(self.end_lineEdit.getText())
|
||||
|
||||
core.clearBind(startFrame, endFrame)
|
||||
|
||||
def goShelfCmd(self, *args):
|
||||
parentTab = mel.eval('''global string $gShelfTopLevel;string $shelves = `tabLayout -q -selectTab $gShelfTopLevel`;''')
|
||||
imageTitlePath = scriptPath + os.sep + "icons" + os.sep + "Title.png"
|
||||
# commandLine = "execfile(r'{0}\\springMagic.py')".format(self.scriptPath)
|
||||
commandLine = "try:\n\timport springmagic\n\tspringmagic.main()\nexcept:\n\texecfile(r'{0}\springMagic.py')".format(scriptPath)
|
||||
|
||||
pm.shelfButton(commandRepeatable=True, image1=imageTitlePath, label="Spring Magic", parent=parentTab, command=commandLine)
|
||||
|
||||
def languageCmd(self, *args):
|
||||
self.language_list.setVisible(not self.language_list.getVisible())
|
||||
|
||||
def languageSelectedCmd(self, *args):
|
||||
self.language_list.setVisible(False)
|
||||
self.applyLanguage(int(self.language_list.getSelectIndexedItem()[0]))
|
||||
|
||||
def bilibiliCmd(self, *args):
|
||||
try:
|
||||
webbrowser.open(kBilibiliLink, new=2)
|
||||
except:
|
||||
pass
|
||||
|
||||
def youtubeCmd(self, *args):
|
||||
try:
|
||||
webbrowser.open(kYoutubeLink, new=2)
|
||||
except:
|
||||
pass
|
||||
|
||||
def vimeoCmd(self, *args):
|
||||
# try:
|
||||
# webbrowser.open(kVimeoLink, new=2)
|
||||
# except:
|
||||
# pass
|
||||
pass
|
||||
|
||||
def donatePayPalCmd(self, *args):
|
||||
try:
|
||||
webbrowser.open(kPaypalLink, new=2)
|
||||
except:
|
||||
pass
|
||||
|
||||
def updatePageCmd(self, *args):
|
||||
try:
|
||||
webbrowser.open(kUpdateLink, new=2)
|
||||
except:
|
||||
pass
|
||||
|
||||
def applyLanguage(self, lanId):
|
||||
lanDict = {1: '_chn', 2: '_eng', 3: '_jpn'}
|
||||
|
||||
if lanId in lanDict.keys():
|
||||
# get new language ui file path
|
||||
new_ui_file = scriptPath + os.sep + os.path.basename(ui_file).split('.')[0] + lanDict[lanId] + '.' + os.path.basename(ui_file).split('.')[1]
|
||||
copyfile(new_ui_file, ui_file)
|
||||
|
||||
# Reload interface
|
||||
self.init()
|
||||
self.show()
|
||||
|
||||
def detectMayaLanguage(self):
|
||||
mayaLan = None
|
||||
try:
|
||||
mayaLan = os.environ['MAYA_UI_LANGUAGE']
|
||||
except:
|
||||
import locale
|
||||
mayaLan = locale.getdefaultlocale()[0]
|
||||
|
||||
lanDict = {'zh_CN': 1, 'en_US': 2, 'ja_JP': 3}
|
||||
self.applyLanguage(lanDict[mayaLan])
|
||||
|
||||
def printTextEdit(self, textEdit, inputString):
|
||||
ctime = time.ctime()
|
||||
ptime = ctime.split(' ')
|
||||
inputString = ptime[3] + ' - ' + inputString
|
||||
pm.scrollField(textEdit, edit=True, insertionPosition=0, insertText=inputString + '\n')
|
||||
|
||||
def checkUpdate(self):
|
||||
|
||||
self.misc_update_button.setVisible(0)
|
||||
|
||||
page_content = None
|
||||
|
||||
site = kVersionCheckLink
|
||||
hdr = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
|
||||
'Accept-Encoding': 'none',
|
||||
'Accept-Language': 'en-US,en;q=0.8',
|
||||
'Connection': 'keep-alive'}
|
||||
|
||||
req = urllib.Request(site, headers=hdr)
|
||||
|
||||
try:
|
||||
page = urllib.urlopen(req, timeout=5)
|
||||
page_content = page.read()
|
||||
except:
|
||||
print('checkUpdate failed')
|
||||
|
||||
if page_content:
|
||||
page_content = page_content.decode('utf-8')
|
||||
if len(page_content.split('|springMagic|')) > 1:
|
||||
new_kSpringMagicVersion = int(page_content.split('|springMagic|')[1])
|
||||
|
||||
if new_kSpringMagicVersion > kSpringMagicVersion:
|
||||
self.misc_update_button.setVisible(1)
|
||||
|
||||
self.spam_word = []
|
||||
|
||||
prefix = '|spam'
|
||||
suffix = '|'
|
||||
|
||||
if self.lang_id.getLabel() == 'chn':
|
||||
suffix = 'chn|'
|
||||
|
||||
self.spam_word = [page_content.split(prefix + str(i) + suffix)[1] for i in range(1, 6)]
|
||||
else:
|
||||
pm.text(self.main_processLabel, edit=True, label='Check update failed, try later.')
|
||||
|
||||
self.showSpam()
|
||||
|
||||
def limitTextEditValue(self, ui_object, minValue=0, maxValue=1, roundF=2, defaultValue=0):
|
||||
value = 0
|
||||
|
||||
try:
|
||||
value = float(ui_object.getText())
|
||||
value = round(value, roundF)
|
||||
value = max(min(maxValue, value), minValue)
|
||||
except:
|
||||
value = defaultValue
|
||||
|
||||
ui_object.setText(str(value))
|
Reference in New Issue
Block a user