This commit is contained in:
2025-04-17 04:52:48 +08:00
commit 9985b73dc1
3708 changed files with 2387532 additions and 0 deletions

View 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))