執筆者:菅原
インタラクティブコンテンツ制作会社を経てモノリスソフトへ入社。 以来、テクニカルアーティストとして主にMayaツール開発の業務を担当。 好きな食べものはごはん。
TECH BLOG
こんにちは。モノリスソフト テクニカルアーティストの菅原です。
今回はMayaのShelfに登録しておくと便利かもしれないスクリプトをまとめてみます。記事内のスクリプトはMayaのScriptEditorへのコピーアンドペーストで動作しますので気軽に使用してみてください。
内容としてはいくつかは簡単なものになっていると思いますので、自分が使用しやすいように書き換える・学習に利用する等に活用していただければと思います。
import os import maya.cmds as cmds def reopen_scene(): fp = cmds.file(q=True, sn=True) if os.path.exists(fp): cmds.file(fp, o=True, f=True) reopen_scene()
ツール開発時には頻繁に検証用のシーンを開き直すため、こういったよく使うものは簡単なものでもShelfに登録しておくと作業が楽になります。
import maya.cmds as cmds from PySide2 import QtGui def copy_scene_path(): fp = cmds.file(q=True, sn=True) if os.path.exists(fp): cb = QtGui.QClipboard() cb.setText(fp.replace('\\', '/')) copy_scene_path()
Windowsのショートカットとして、Shiftキーを押しながらエクスプローラでファイルを右クリックすると「パスのコピー」というメニューは表示されるのですが、それを使用すると区切りがバックスラッシュになってしまいます。
場合によってはそちらの方が都合が良かったりもするのですが、このように処理を自分で用意することで好きな形式でパスを取得することが可能になります。
import os import subprocess import maya.cmds as cmds def open_scene_dir(): p = os.path.dirname(cmds.file(q=True, sn=True)) if not os.path.exists(p): return subprocess.Popen(["explorer", p.replace('/', '\\')]) open_scene_dir()
シーンファイルと同じフォルダに出力したツールのlogファイルの確認や、シーンファイルの近くにあるTexture等にアクセスする際に使用するスクリプトです。
import os import maya.cmds as cmds import maya.mel as mel from maya.app.general import mayaMixin from PySide2 import QtWidgets, QtGui, QtCore def open_recent_dir(): recent_dlg = RecentDialog() def on_double_clicked(): recent_dlg.close() file_path, _ = QtWidgets.QFileDialog.getOpenFileName(None, 'Open Maya Scene', recent_dlg.list.currentItem().text(), 'Maya Ascii (*.ma);;Maya Binary (*.mb);;All (*.*)') if not os.path.exists(file_path): return save_result = 1 if cmds.file(q=True, modified=True): save_result = mel.eval('saveChanges ""') if save_result > 0: print('open : ' + file_path) cmds.file(file_path, open=True, force=True) file_type = (cmds.file(file_path, q=True, type=True) or ["type_not_found"])[0] mel.eval('addRecentFile("{0}", "{1}")'.format(file_path, file_type)) recent_dlg.list.doubleClicked.connect(on_double_clicked) recent_dlg.exec_() class RecentDialog(mayaMixin.MayaQWidgetBaseMixin, QtWidgets.QDialog): def __init__(self, parent=None): super(RecentDialog, self).__init__(parent) self.setWindowTitle('Recent Directory') self.setLayout(QtWidgets.QVBoxLayout()) self.setMinimumSize(QtCore.QSize(600, 300)) high_col = QtGui.QColor(68, 68, 68) def_col = QtGui.QColor(43, 43, 43) self.__list_widget = QtWidgets.QListWidget() self.__list_widget.addItems(sorted(list(set([os.path.dirname(fp) for fp in cmds.optionVar(q='RecentFilesList')])))) [self.__list_widget.item(i).setBackgroundColor(high_col if i % 2 == 1 else def_col) for i in range(self.__list_widget.count())] style = 'QListWidget{font-size: 10pt;}' style += 'QListWidget{background-color: rgb(68, 68, 68);}' if self.__list_widget.count() % 2 == 1 else '' self.__list_widget.setStyleSheet(style) self.layout().addWidget(self.__list_widget) @property def list(self): return self.__list_widget open_recent_dir()
プロジェクト設定をしていなかったときや、開いているシーンファイルと同フォルダにある検証用に少しだけ変更したシーンファイルを開きたい場合等に使用するツールです。
前述の現在開いているシーンファイルのフォルダを開くからフォルダパスをコピーして同じようなことは可能ですが、それすら面倒な人向けです。
import pymel.core as pm from maya.app.general import mayaMixin from PySide2 import QtWidgets, QtCore def list_sorted_attr(): text_items = [] for n in pm.ls(sl=True): text_items.append('NODE: {0}'.format(str(n))) names = [] values = [] types = [] for attr in sorted(n.listAttr()): if not attr.exists() or attr.isHidden(): continue if attr.type() == 'TdataCompound' or attr.isCompound(): continue print(attr) names.append('{0} ({1})'.format(attr.plugAttr(longName=True, fullPath=True), attr.plugAttr(longName=False, fullPath=False))) types.append(str(attr.type())) values.append(str(attr.get())) max_len = [0] * 3 max_len[0] = len(sorted(names, reverse=True, key=len)[0]) max_len[1] = len(sorted(types, reverse=True, key=len)[0]) max_len[2] = len(sorted(values, reverse=True, key=len)[0]) for i, item in enumerate(zip(names, values, types)): n, v, t = item text_items.append('{0}: type:{1}, value:{2}'.format(n.ljust(max_len[0]), t.ljust(max_len[1]), v)) text_items.append('---------') dlg = TextDialog() dlg.setMinimumSize(QtCore.QSize(700, 400)) dlg.log.setText('\n'.join(text_items or ['None'])) dlg.log.setFont('courier new') dlg.show() class TextDialog(mayaMixin.MayaQWidgetBaseMixin, QtWidgets.QDialog): def __init__(self, parent=None): super(TextDialog, self).__init__(parent) self.setWindowTitle(u'Output') self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.__log = QtWidgets.QTextEdit(self) self.__log.setLineWrapMode(QtWidgets.QTextEdit.NoWrap) self.__log.setReadOnly(True) layout = QtWidgets.QVBoxLayout(self) layout.addWidget(self.__log) self.setLayout(layout) @property def log(self): return self.__log list_sorted_attr()
選択したノードのアトリビュートをABC順でソートして名前と値を一覧表示するツールです。
import maya.cmds as cmds def create_shark(): nodes = cmds.file(r'C:/Program Files/Autodesk/Maya2019/Examples/Modeling/Sculpting_Base_Meshes/Animals/Shark.ma', i=True, type='mayaAscii', options='v=0;p=17;f=0', rnn=True) nodes = cmds.ls(nodes, l=True) shark_dags = cmds.ls(nodes, type=['transform', 'mesh'], l=True) if len(shark_dags) is not 2: cmds.delete(nodes) return cmds.sets(shark_dags, e=True, forceElement='initialShadingGroup') cmds.delete(list(set(nodes) - set(shark_dags))) create_shark()
検証用メッシュとしてInitialShadingGroupを適用した鮫を作成するスクリプトです。MayaのExamplesにある鮫のデータを読み込んでいます。
他のデータを使用したい場合は、ファイルパス部分をExamplesにある他のデータに変更して使用してください。
今回はShelfに登録しておくと便利かもしれないスクリプトをまとめてみました。
簡単なものがいくつかありますので、全くスクリプトを触らないという人にとって興味を持つきっかけになれば幸いです。
執筆者:菅原
インタラクティブコンテンツ制作会社を経てモノリスソフトへ入社。 以来、テクニカルアーティストとして主にMayaツール開発の業務を担当。 好きな食べものはごはん。