一度
mGear/Skinning/Export Skinで保存したものを読み込んでみた。
スキンバインドしたてのもの 脇の下がおかしいが読み込んでみると、、、
ちゃんと読み込めてる
ちゃんと使える模様
一度
mGear/Skinning/Export Skinで保存したものを読み込んでみた。
スキンバインドしたてのもの 脇の下がおかしいが読み込んでみると、、、
ちゃんと読み込めてる
ちゃんと使える模様
どうにかこうにか手動でGuidを昔のジョイントに合わせたものがこれ
指が間違ってた。
でこの動画の続きによると
型の始まりのGuidのCUBEをクリックして Dupl.Sym.を押すと左右が対象になるみたいだったけど
つかってない手でやった。
つぎにGuidのトップノードを選択して新シーンとして保存してる
Guidトップ選択して Build From Selection
走りだす。
リグが出力されたようだ このあと動画のようにコントロールリグのサイズを変更しなくてスキンバインドのテストしたほうがいいと思う。
リグデフォーマグループを選択する
上やじるしを押すとすべての読み取るのに必要なジョイントが選択されます。
つまりはこれがしたいみたい。
設定は
ジョイント階層
測地線ボクセル
クラシックリニア
インタラクティブ
距離
チェックあり
5
チェック
チェック
チェック
チェックなし
ではリグを動かしてみましょう!
動かしにくいので最後にリグコントローラーのサイズを変更しよう。
ここでジョイントの表示サイズがでかすぎたのか変更してる。
表示サイズを大きくすると、ジョイントやボーンが選択しやすくなります。 表示サイズを小さくすると、フレクサなど他のオブジェクトが選択しやすくなります。 ディスプレイ > アニメーション > ジョイント サイズ(Display > Animation > Joint Size)を選択します。
一番下の8角形が大きすぎたので
Control+右クリックで「CV」を選択して小さくスケールしてる。
スケールできないからスケールツールをダブルクリックで起動しなおすことで初期化してスケールしてる。
ここでは逆に大きくした。
手の幅ぐらいのサイズにした
コントローラーハンドルここではBOXが頭にめり込んでるので直している。
した
体も同じくボディに埋まっているコントロールハンドルをCVモードで拡大していく
こんな感じ
ちょっとさらに仕切り直し
Maya2016 +mGear2.6.1系 から
Maya2020 +mGear3.7.0_beta_01に乗り換えてみた。
1、モデルを用意した
2,mGear/Shifter/Guide Managerを起動
3,mGear/Shifter/Guid Template Samples/Biped Template を実行
黄色いguidが作成された。
4、guideのサイズをモデルに合わせる
合わせやすいようにシェーディング/ワイヤーフレームシェードにした
ここではもとにあったジョイントに全くびったり合わせるために
ジョイントを読み込みました。
位置合わせツールがあったら楽なのにと思いました。
いろいろやったが下のスクリプトなど作ったがJointの数とターゲットの数も違うし使えなかった仕事としてならたぶん無理やりできるんだろうなと思う。
import maya.cmds as cmds
selectedList=cmds.ls( selection=True )
print("selectedList="+str(selectedList))
jointOriginal=selectedList[0]
guidTarget=selectedList[1]
#world座標を取る いろいろ考えたけど親基準にローカル座標そろえるのやめた。なぜなら親もローカル座標そろえないと話は始まらないから。
#cmds.pointPosition( 'particle1.pt[1]', world=True )
#def getParentWorldPos()
j_parentlist=cmds.listRelatives(jointOriginal, parent=True )
g_parentlist=cmds.listRelatives(jointOriginal, parent=True )
#print("parentlist="+str(parentlist))
jointOriginalParent=j_parentlist[0]
guidTargetParent=g_parentlist[0]
print("jointOriginalParent="+str(jointOriginalParent))
print("guidTargetParent="+str(guidTargetParent))
jointOriginalParentWorldXYZ=cmds.xform(jointOriginalParent,worldSpace=True, q=True, translation=True )
guidTargetParentWorldXYZ=cmds.xform(guidTargetParent,worldSpace=True, q=True, translation=True )
jointOriginalParentWorldXYZrot=cmds.xform(jointOriginalParent,worldSpace=True, q=True, rotation=True )
guidTargetParentWorldXYZrot=cmds.xform(guidTargetParent,worldSpace=True, q=True, rotation=True )
print("jointOriginalParentWorldXYZ="+str(jointOriginalParentWorldXYZ))
print("guidTargetParentWorldXYZ="+str(guidTargetParentWorldXYZ))
w_xDiff=jointOriginalParentWorldXYZ[0]-guidTargetParentWorldXYZ[0]
w_yDiff=jointOriginalParentWorldXYZ[1]-guidTargetParentWorldXYZ[1]
w_zDiff=jointOriginalParentWorldXYZ[2]-guidTargetParentWorldXYZ[2]
w_xDiffR=jointOriginalParentWorldXYZrot[0]-guidTargetParentWorldXYZrot[0]
w_yDiffR=jointOriginalParentWorldXYZrot[1]-guidTargetParentWorldXYZrot[1]
w_zDiffR=jointOriginalParentWorldXYZrot[2]-guidTargetParentWorldXYZrot[2]
worldDiff=[w_xDiff,w_yDiff,w_zDiff]
worldDiffR=[w_xDiffR,w_yDiffR,w_zDiffR]
print("worldDiff="+str(worldDiff))
print("worldDiffR="+str(worldDiffR))
""""""
tx=cmds.getAttr(jointOriginal+".tx")
ty=cmds.getAttr(jointOriginal+".ty")
tz=cmds.getAttr(jointOriginal+".tz")
print(" tx= "+str(tx)+" ty= "+str(ty)+" tz= "+str(tz))
"""
cmds.setAttr(guidTarget+".tx",tx)
cmds.setAttr(guidTarget+".ty",ty)
cmds.setAttr(guidTarget+".tz",tz)
"""
guid_Scale=9.869
goTX=guid_Scale/tx+w_xDiff
goTY=guid_Scale/ty+w_yDiff
goTZ=guid_Scale/tz+w_zDiff
print(" goTX= "+str(goTX)+" goTY= "+str(goTY)+" goTZ= "+str(goTZ))
""""""
#ZをXに
""""""
cmds.setAttr(guidTarget+".tx",goTZ)
cmds.setAttr(guidTarget+".ty",goTY)
cmds.setAttr(guidTarget+".tz",goTX)
"""
cmds.setAttr(guidTarget+".rx",goTZ)
cmds.setAttr(guidTarget+".ry",goTX)
cmds.setAttr(guidTarget+".rz",goTY)
"""
地道にジョイントにguideを合わせるしかない。(今のところ)
単位が違くなってるのはさっきguide側にスケールかけたからだった。
これはjoint rHand
これはguide のarm_R0_wrist
もう少しで、いけそうなのになあ
Maya2016付近のmGearを入れたところから
https://github.com/mgear-dev/mgear/releases/tag/v2.6.1
このビデオにそってみる。
1、モデルを用意した
2,mGear/Shifter/Guide UIを起動
3,mGear/Shifter/Import Biped Guide を実行
黄色いGuidが作成された。Guideのサイズをモデルに合わせる
用意したモデルに
Shifter/Guide Template Samples /Biped Templateをやってみたらエラー
エラー: AttributeError: file C:\Users\whaison\Documents\maya\2016\ja_JP\scripts\mGear\mgear_3.7.0_beta_01\release\scripts\mgear\core\utils.py line 223: nt.NurbsCurve(u’global_C0_axisShape’) has no attribute or method named ‘lineWidth’ #
バージョン的にだめな予感がしてきたので過去のmGearを探すことにした。
こんどは
mGear/Shifter/Guid Mannager起動してみたら起動したエラー
File “C:/Users/whaison/Documents/maya/2016/ja_JP/scripts/mGear/mgear_3.7.0_beta_01/release/scripts/mgear/shifter_classic_components\ui_slider_01\settingsUI.py”, line 11, in
from PySide2 import QtCore, QtGui, QtWidgets
ImportError: No module named PySide2
Maya2016にはPyside2はありませんよねそりゃ
以下の3つのファイルのソースを変更する
C:\Users\whaison\Documents\maya\2016\ja_JP\scripts\mGear\mgear_3.7.0_beta_01\release\scripts\mgear\shifter_classic_components\ui_slider_01\settingsUI.py
C:\Users\whaison\Documents\maya\2016\ja_JP\scripts\mGear\mgear_3.7.0_beta_01\release\scripts\mgear\shifter_classic_components\ui_container_01\settingsUI.py
C:\Users\whaison\Documents\maya\2016\ja_JP\scripts\mGear\mgear_3.7.0_beta_01\release\scripts\mgear\shifter_classic_components\sdk_control_01\settingsUI.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'C:\Users\Justi\OneDrive\Documents\maya\mGear\scripts\mgear\shifter_classic_components\sdk_control_01\settingsUI.ui'
#
# Created: Sat Aug 24 10:20:58 2019
# by: pyside2-uic running on PySide2 2.0.0~alpha0
#
# WARNING! All changes made in this file will be lost!
#from PySide2 import QtCore, QtGui, QtWidgets
from PySide import QtCore, QtGui
エラーなく動いた。
今回の変更はただのUIのロード先の変更なのでたーぶーん全体的には動く予感
エラー: AttributeError: file C:\Users\whaison\Documents\maya\2016\ja_JP\scripts\mGear\mgear_3.7.0_beta_01\release\scripts\mgear\core\pyqt.py line 160: ‘module’ object has no attribute ‘workspaceControl’
についてだが
この160行目をコメントしたら動いた。
C:\Users\whaison\Documents\maya\2016\ja_JP\scripts\mGear\mgear_3.7.0_beta_01\release\scripts\mgear\core\pyqt.py
"""pyQt/pySide widgets and helper functions for mGear"""
#############################################
# GLOBAL
#############################################
import os
import traceback
import maya.OpenMayaUI as omui
import pymel.core as pm
from mgear.vendor.Qt import QtWidgets
from mgear.vendor.Qt import QtCompat
from mgear.vendor.Qt import QtGui
from mgear.vendor.Qt import QtSvg
UI_EXT = "ui"
_LOGICAL_DPI_KEY = "_LOGICAL_DPI"
#################
# Old qt importer
#################
def _qt_import(binding, shi=False, cui=False):
QtGui = None
QtCore = None
QtWidgets = None
wrapInstance = None
if binding == "PySide2":
from PySide2 import QtGui, QtCore, QtWidgets
import shiboken2 as shiboken
from shiboken2 import wrapInstance
from pyside2uic import compileUi
elif binding == "PySide":
from PySide import QtGui, QtCore
import PySide.QtGui as QtWidgets
import shiboken
from shiboken import wrapInstance
from pysideuic import compileUi
elif binding == "PyQt4":
from PyQt4 import QtGui
from PyQt4 import QtCore
import PyQt4.QtGui as QtWidgets
from sip import wrapinstance as wrapInstance
from PyQt4.uic import compileUi
print("Warning: 'shiboken' is not supported in 'PyQt4' Qt binding")
shiboken = None
else:
raise Exception("Unsupported python Qt binding '%s'" % binding)
rv = [QtGui, QtCore, QtWidgets, wrapInstance]
if shi:
rv.append(shiboken)
if cui:
rv.append(compileUi)
return rv
def qt_import(shi=False, cui=False):
"""
import pyside/pyQt
Returns:
multi: QtGui, QtCore, QtWidgets, wrapInstance
"""
lookup = ["PySide2", "PySide", "PyQt4"]
preferredBinding = os.environ.get("MGEAR_PYTHON_QT_BINDING", None)
if preferredBinding is not None and preferredBinding in lookup:
lookup.remove(preferredBinding)
lookup.insert(0, preferredBinding)
for binding in lookup:
try:
return _qt_import(binding, shi, cui)
except Exception:
pass
raise _qt_import("ThisBindingSurelyDoesNotExist", False, False)
compileUi = qt_import(shi=True, cui=True)[-1]
#############################################
# helper Maya pyQt functions
#############################################
def ui2py(filePath=None, *args):
"""Convert qtDesigner .ui files to .py"""
if not filePath:
startDir = pm.workspace(q=True, rootDirectory=True)
filePath = pm.fileDialog2(dialogStyle=2,
fileMode=1,
startingDirectory=startDir,
fileFilter='PyQt Designer (*%s)' % UI_EXT,
okc="Compile to .py")
if not filePath:
return False
filePath = filePath[0]
if not filePath:
return False
if not filePath.endswith(UI_EXT):
filePath += UI_EXT
compiledFilePath = filePath[:-2] + "py"
pyfile = open(compiledFilePath, 'w')
compileUi(filePath, pyfile, False, 4, False)
pyfile.close()
info = "PyQt Designer file compiled to .py in: "
pm.displayInfo(info + compiledFilePath)
def maya_main_window():
"""Get Maya's main window
Returns:
QMainWindow: main window.
"""
main_window_ptr = omui.MQtUtil.mainWindow()
return QtCompat.wrapInstance(long(main_window_ptr), QtWidgets.QWidget)
def showDialog(dialog, dInst=True, dockable=False, *args):
"""
Show the defined dialog window
Attributes:
dialog (QDialog): The window to show.
"""
if dInst:
try:
for c in maya_main_window().children():
if isinstance(c, dialog):
c.deleteLater()
except Exception:
pass
# Create minimal dialog object
# if versions.current() >= 20180000:
# windw = dialog(maya_main_window())
# else:
windw = dialog()
# ensure clean workspace name
if hasattr(windw, "toolName") and dockable:
control = windw.toolName + "WorkspaceControl"
#if pm.workspaceControl(control, q=True, exists=True):
# pm.workspaceControl(control, e=True, close=True)
# pm.deleteUI(control, control=True)
desktop = QtWidgets.QApplication.desktop()
screen = desktop.screen()
screen_center = screen.rect().center()
windw_center = windw.rect().center()
windw.move(screen_center - windw_center)
# Delete the UI if errors occur to avoid causing winEvent
# and event errors (in Maya 2014)
try:
if dockable:
windw.show(dockable=True)
else:
windw.show()
return windw
except Exception:
windw.deleteLater()
traceback.print_exc()
def deleteInstances(dialog, checkinstance):
"""Delete any instance of a given dialog
Delete any instance of a given dialog and if the dialog is
instance of checkinstance.
Attributes:
dialog (QDialog): The dialog to delete.
checkinstance (QDialog): The instance to check the type of dialog.
"""
mayaMainWindow = maya_main_window()
for obj in mayaMainWindow.children():
if isinstance(obj, checkinstance):
if obj.widget().objectName() == dialog.toolName:
print 'Deleting instance {0}'.format(obj)
mayaMainWindow.removeDockWidget(obj)
obj.setParent(None)
obj.deleteLater()
def fakeTranslate(*args):
"""Fake Translation
fake QApplication.translate. This function helps to bypass the
incompativility for the Unicode utf8 deprecated in pyside2
"""
return args[1]
def position_window(window):
""" set the position for the windonw
Function borrowed from Cesar Saez QuickLauncher
Args:
window (QtWidget): the window to position
"""
pos = QtGui.QCursor.pos()
window.move(pos.x(), pos.y())
def get_main_window(widget=None):
"""Get the active window
Function borrowed from Cesar Saez QuickLauncher
Args:
widget (QtWidget, optional): window
Returns:
QtWidget: parent of the window
"""
widget = widget or QtWidgets.QApplication.activeWindow()
if widget is None:
return
parent = widget.parent()
if parent is None:
return widget
return get_main_window(parent)
def get_instance(parent, gui_class):
"""Get instace of a window from a given parent
Function borrowed from Cesar Saez QuickLauncher
Args:
parent (QtWidget): parent
gui_class (QtWidget): instance class to check
"""
for children in parent.children():
if isinstance(children, gui_class):
return children
return None
def get_icon_path(icon_name=None):
""" Gets the directory path to the icon
"""
file_dir = os.path.dirname(__file__)
if "\\" in file_dir:
file_dir = file_dir.replace("\\", "/")
if icon_name:
return "{0}/icons/{1}".format(file_dir, icon_name)
else:
return "{}/icons".format(file_dir)
def get_icon(icon, size=24):
"""get svg icon from icon resources folder as a pixel map
"""
img = get_icon_path("{}.svg".format(icon))
svg_renderer = QtSvg.QSvgRenderer(img)
image = QtGui.QImage(size, size, QtGui.QImage.Format_ARGB32)
# Set the ARGB to 0 to prevent rendering artifacts
image.fill(0x00000000)
svg_renderer.render(QtGui.QPainter(image))
pixmap = QtGui.QPixmap.fromImage(image)
return pixmap
# dpi scale test -------------------------------------------------------------
def get_logicaldpi():
"""attempting to "cache" the query to the maya main window for speed
Returns:
int: dpi of the monitor
"""
if _LOGICAL_DPI_KEY not in os.environ.keys():
try:
logical_dpi = maya_main_window().logicalDpiX()
except Exception:
logical_dpi = 96
finally:
os.environ[_LOGICAL_DPI_KEY] = str(logical_dpi)
return int(os.environ.get(_LOGICAL_DPI_KEY)) or 96
def dpi_scale(value, default=96, min_=1, max_=2):
"""Scale the provided value by the scale that maya is using
which is derived from the 'average' dpi of 96 from windows, linux, osx.
Args:
value (int, float): value to scale
default (int, optional): assumed default from various platforms
min_ (int, optional): if you do not want the value under 96 dpi
max_ (int, optional): if you do not want a value higher than 200% scale
Returns:
# int, float: scaled value
"""
return value * max(min_, min(get_logicaldpi() / float(default), max_))
mGear/Shifter/Guid Mannager起動してみたら起動した。
mGear/Shifter/Guid Mannager起動してみたら起動できなかった。
エラー: AttributeError: file C:\Users\whaison\Documents\maya\2016\ja_JP\scripts\mGear\mgear_3.7.0_beta_01\release\scripts\mgear\core\pyqt.py line 160: ‘module’ object has no attribute ‘workspaceControl’
zipフォルダにはいってるdrag_n_drop_install.pyってなんやろね
たぶんインストールが的確じゃなかった。
drag_n_drop_install.pyの
__file__がみつかりませんは
エラー: line 1: NameError: file line 59: global name ‘file‘ is not defined
こうすりゃ動くはず
"""
Drag and drop this file into your viewport to run the mGear installer.
1. Default Install:
Will install in the users documents folder where Maya is installed, a
restart will not be required.
2. Custom Install:
Will install in the user specified directory, this method will write the
correct module path in the Maya.env file, but a restart will be required
in this case.
"""
import os
import sys
import shutil
try:
import pymel.core as pm
from pymel import mayautils
from maya.app.startup import basic
is_maya = True
except ImportError():
is_maya = False
# -- maya requires this in order to successfully execute
def onMayaDroppedPythonFile(*args, **kwargs):
"""
This function is only supported since Maya 2017 Update 3
"""
pass
def files_exist(file_list):
"""Get all file paths that exist.
Args:
file_list (list): List of paths to iterate through
Returns:
list: List of all paths found
"""
file_found = []
for item in file_list:
if os.path.exists(item):
found = item
file_found.append(found)
return file_found
def _dropped_install():
# -- current folder where the installer resides
#current_folder = os.path.dirname(__file__)
current_folder = os.path.dirname("C:/Users/whaison/Documents/maya/2016/ja_JP/scripts/mGear/mgear_3.7.0_beta_01/drag_n_drop_install.py")
# -- folder of all conents of mgear resides
mgear_folder = os.path.normpath(os.path.join(current_folder, "release"))
custom_path = False
# -- default modules folder to install to
install_path = os.path.normpath(os.path.join(
os.environ['MAYA_APP_DIR'], "modules"))
# -- mesage for the main installer dialog window
message = (
"mGear will be installed here:\n"
"{}\n"
"\n"
"Make sure to SAVE your scene before continuing.\n"
"\n"
"NOTE: Installing to a custom directory will require a restart.\n"
"\n"
"Would you like to continue?".format(install_path)
)
# -- installer dialog window
input = pm.confirmDialog(title="Installation Path",
message=message,
icon="question",
button=["OK", "Cancel", "No, Custom Path"],
cancelButton="Cancel",
dismissString="Cancel")
if input == "Cancel":
pm.displayError("mGear installation has been cancelled.")
return
elif input == "No, Custom Path":
install_path = None
# -- custom path will be set here
if install_path is None:
install_path = pm.fileDialog2(
fileMode=3,
okCaption="Install here",
caption="Please choose a folder to install mGear...")[0]
custom_path = True
# -- if install path is still None, exit
if not install_path:
return
# -- flush the undo que in case there is anything that might disrupt
# the install
pm.flushUndo()
# -- create a fresh scene incase there are any solvers still
# loaded in memory
pm.newFile(force=True)
# -- mgear install path
mgear_install_path = os.path.join(install_path, "mgear")
# -- make sure the the mgear folder does not exist
if os.path.exists(mgear_install_path):
shutil.rmtree(mgear_install_path)
# -- copy to a folder because tge copytree gives issues with
# existing folders
shutil.copytree(mgear_folder, mgear_install_path)
# -- look in install directory for files of same name
search_names = ["platforms", "mGear.mod", "scripts"]
# -- construct path names
full_path = [os.path.join(install_path, x) for x in search_names]
# -- files of the same name
found = files_exist(full_path)
if found:
# -- message if same files are found
message = ("mGear files already exist in the install location.\n"
"\n"
"Would you like to overrite them?")
# -- same files dialog window
input = pm.confirmDialog(title="Delete existing files",
message=message,
icon="warning",
button=["OK", "Cancel"],
cancelButton="Cancel",
dismissString="Cancel")
if input == "Cancel":
# -- delete the temp folder
shutil.rmtree(mgear_install_path)
pm.displayError("mGear installation has been cancelled.")
return
# -- iterate over folders and remove them
for item in os.listdir(mgear_install_path):
if os.path.exists(os.path.join(install_path, item)):
# -- unload plugins incase there is a faulty install
try:
pm.unloadPlugin("mgear_solvers.mll", force=True)
pm.unloadPlugin("weightDriver.mll", force=True)
except:
pass
# -- delete file and folders
if os.path.isfile(os.path.join(install_path, item)):
os.remove(os.path.join(install_path, item))
elif os.path.isdir(os.path.join(install_path, item)):
shutil.rmtree(os.path.join(install_path, item))
# -- move the folder to the install path
shutil.move(os.path.join(install_path, "mgear", item), install_path)
# -- delete the temp folder
shutil.rmtree(mgear_install_path)
# -- now let's get mgear up and running
# -- add to the system path
if not os.path.join(install_path, "scripts") in sys.path:
sys.path.append(os.path.join(install_path, "scripts"))
if custom_path:
# -- we look for the Maya.env file and write the path to it
env_file = os.path.normpath(os.path.join(
os.environ["MAYA_APP_DIR"], pm.about(version=True), "Maya.env"))
if os.path.exists(env_file):
f = open(env_file, "w")
f.write("MAYA_MODULE_PATH={0}".format(install_path))
f.close()
# -- custom install dialog message
message = ("A re-start of Maya will be required after this setup.")
# -- custom install dialog window
input = pm.confirmDialog(title="Custom Install Path Restart",
message=message,
icon="information",
button=["OK"])
# -- if not a custom install we can load in the module
else:
# -- allows for not having to restart maya
pm.loadModule(scan=True)
pm.loadModule(allModules=True)
# -- reload user setup files
basic.executeUserSetup()
# -- force load the plugins just incase it does not happen
try:
pm.loadPlugin("mgear_solvers.mll")
pm.loadPlugin("weightDriver.mll")
except:
pass
# -- installation message
message = ("Installation Complete!")
# -- installation dialog window
input = pm.confirmDialog(title="Installation",
message=message,
icon="information",
button=["OK"])
pm.displayInfo("Installation Complete")
if is_maya:
_dropped_install()
で動いた OK押した
インストール完了と出た。
ここからリリース版をダウンロードする。
最新版は
https://github.com/mgear-dev/mgear_dist/releases
Maya2016は
https://github.com/mgear-dev/mgear/releases/tag/v2.6.1
zip をいい感じのフォルダに解凍する
普通はここに入れるものだからここに入れる。
C:\Users\whaison\Documents\maya\マヤのバージョン\ja_JP\scripts
いれたらmGear.modのフォルダまでのパスをコピーしておく
たとえば
C:\Users\whaison\Documents\maya\2020\ja_JP\scripts\mGear\mgear_3.7.0_beta_01\release
とか
C:\Users\whaison\Documents\maya\2016\ja_JP\scripts\mGear\mgear_2.6.1
C:\Users\whaison\Documents\maya\マヤのバージョン\Maya.envを開いて
MAYA_MODULE_PATH=ここにペーストして保存する。
Mayaを起動すると、、