MetaBox/Scripts/Animation/springmagic/ui.py
2025-01-14 03:08:08 +08:00

476 lines
18 KiB
Python

import os
import time
import inspect
import webbrowser
import urllib.request 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))