文系デザイナーのためのmaya MEL/Python基礎の基礎 Step2-7

さて、前回はPythonでGUIを作成しましたが、今回はその続きです。

ちょっと脱線しますが、MayaでGUIをPythonで作るには「PySide」という方法もありますが、ちょっと文系では難しいので、まずは普通のPythonだけで行います。
実は新しいMayaのUIはPySideで作ってあるので、UIを細かく設定できるのです。ただし、Mayaのバージョンによって動かないこともあり、ちょっと困るので、ここの連載では後半にします。

では、前回のプログラムをちょっと改造した例です。

import pymel.core as pm
window=str(pm.window(widthHeight=(250, 100),title=”MyTools”))
pm.columnLayout(adjustableColumn=True)
pm.button(command=”pm.polyCube()”, label=”BOX”)
pm.button(command=”pm.polyCylinder()”, label=”CYLINDER”)
pm.button(command=”pm.polySphere()”, label=”BALL”)
pm.button(command=lambda *args: pm.mel.eval((“deleteUI -window ” + window)), label=”CLOSE”)
pm.setParent(‘..’)
pm.showWindow(window)

実行すると、以下のウインドウが出て、それぞれのボタンを押すとプリミティブが生成される、というものです。
前回と違うのは、ボタンが4つに増やしたのと、2行目の

widthHeight=(250, 100),title=”MyTools”)
ボタンが増えただけ、ウインドウの幅を大きくして、タイトルを付けました。これを改造してみましょう。

まず、pm.columnLayout(adjustableColumn=True)

pm.columnLayout()
にして再実行してみます。


adjustableColumn=Trueでウインドウの幅に合わせてボタンの幅がピッタリに
なる仕組みにしていたんですね。
このように、サンプルの命令を削除してみて、何をやっているのか?を調べることができます。
もし、動かなくなっても、元のプログラムが残っていれば問題ないので、
修正したプログラムは上書き保存しないことです。
(これはデザイナーでも一般的ですよね)

colummLayoutという命令のHELPをもう一度確認みましょう。

右上に「カテゴリ内:ウインドウ、レイアウト」というのがあります。


と、このようにGUIに関する命令がすべて出てきます。こんなにあるんですね!「M」のアイコンがあるのはMelでしか使えないので注意です。
では、よく使う命令を紹介します。
まずrowLayoutです。ここを見ると「水平一列に配置できる」とあります。
下のサンプルプログラムに
rowLayout -numberOfColumns 3;
という記載がありますね。これは「3つ横に並べる」という意味のようです。
Pyhtonに変換すると
pm.rowLayout(numberOfColumns=3)
です。そこで、以下のように書き換えます。

import pymel.core as pm
window=str(pm.window(widthHeight=(250, 100),title=”MyTools”))
pm.columnLayout()
pm.rowLayout(numberOfColumns=3)
pm.button(command=”pm.polyCube()”, label=”BOX”)
pm.button(command=”pm.polyCylinder()”, label=”CYLINDER”)
pm.button(command=”pm.polySphere()”, label=”BALL”)
pm.setParent(‘..’)
pm.button(command=lambda *args: pm.mel.eval((“deleteUI -window ” + window)), label=”CLOSE”)
pm.setParent(‘..’)
pm.showWindow(window)

その前のプログラムの書き換えた箇所だけ太字にしてあります。

実行すると

こんな感じです。ボタン3つ横に並べることに成功しました。
pm.setParent(‘..’)をいれることで、rowLayoutで横に並べる範囲を決めます。

「Close」ボタンはそれ以降になるのでcolumnLayoutの機能で縦に並びます。

それ以外にも、
pm.text(label=”表示したい文字”)
を使うと、ボタン以外のタイトルをつけることもできます。
でもプリミティブを出したりしてもあまり面白くないので、よく使うウインドウなどを登録しておくといいでしょう。これは最初のころやりましたがシェルフに登録してみて、コマンドをチェックするのです。
たとえば、アウトライナを出す命令を「Ctrl+Shift」で実行し、シェルフ登録したものを右クリックで「Edit」します。


ここでMelとPythonのどちら選んでも同じです。この「OutlinerWindow」という命令です。これは困ったことにMelしかない命令のようです。先ほどマニュアルにも「M」マークがありましたね。
この場合、Pythonで実行するには、
pm.mel.OutlinerWindow()
と書きます。mel.Mel命令()という形です。
Cubeを出す行を以下のように書きかえてみます。pm.button(command=”pm.mel.OutlinerWindow()”, label=”OutLiner”)

実行すると、

ちゃんと、ボタンをクリックすれば、アウトライナが表示されます。
このようにUIを組み立てて、自分の良く使うコマンドだけのウインドを作ってしまうと便利ですよ。

文系デザイナーのためのmaya MEL/Python基礎の基礎 Step2-6

Step2-4の最後に関数と「window」という命令のお話をしました。今回はそれを使ってみます。ユーザインタフェースを作成するのです。
早速Mayaを起動して、スクリプトエディタでWindowの意味を調べてみましょう。「Window」とキーで入力して右ドラッグからマニュアルを見ます。

やはり、これはウインドウを作成する命令のようです。「Mel例」というところをクリックしましょう。

これをPymelに変換します。

import pymel.core as pm
window=str(pm.window(widthHeight=(200, 55), iconName=”Short Name”, title=”Long Name”))
# Make a new window //
pm.columnLayout(adjustableColumn=True)
pm.button(label=”Do Nothing”)
pm.button(command=lambda *args: pm.mel.eval((“deleteUI -window ” + window)), label=”Close”)
pm.setParent(‘..’)
pm.showWindow(window)

実行すると、こんなウインドウが出ます。

ボタンをクリックはできますが、「Do Nothing」なので何も起こらないですね。「Close」でウインドウが閉じます。

さて、仕組みを見てみましょう。
window=str(pm.window(widthHeight=(200, 55), iconName=”Short Name”, title=”Long Name”))
いきなり長いですね。でも過去に
X=1
とかやりましたね。Windowという変数を作って、それに値を代入しているようです。
=str()は数値を文字に変換するPythonの命令です。以下など参考にしましょう。
https://www.pythonweb.jp/tutorial/string/index9.html

この行ではMayaのウインドウを生成(データみたいなもの)して、windowという名前の変数に入れているのです。ちょっと判り難いですが、ここでは「そういうもの」で構いません。これは別の機会に改めて説明します。

マニュアルには、pm.windowが「ウインドウを作成する」とあります。()の中はCubeとかでやりました「オプション」です。
widthHeightはウインドウの大きさ、title=はウインドウのタイトルで、iconName=はウインドウの左上のアイコンを決める、ようです。
こうやってマニュアルを見て流れを研究します。

でもマニュアル最初に「作成されたウィンドウは非表示のままになります。最も効率的なのは、ウィンドウの要素を追加してから showWindow コマンドを使用してウィンドウを可視化する」とあります。
一番最後の行でpm.showWindow(window)がありますから、これとセットで使うようです。
次のpm.columnLayout(adjustableColumn=True)はここのマニュアルにないので、再度調べます。

これは縦に並べる命令のようです。「子を」がpm.setParent(‘..’)です。
その下のpm.buttonはボタンを作成する命令で、上のcolumnLayoutがあるので、ボタンが縦に並ぶ、ということですね。(label=”Do Nothing”)はボタンの表示のようです。上のボタンは“Do Nothing”で何も起きないで、下は動作する、ということは、違いを見ると、
pm.button(command=lambda *args: ???)が怪しいですね。???はウインドウを閉じる機能と思われます。そう思ったら、すぐに実験です。
polyCylinder()で円柱が表示されるので、pm.button(command=”pm.polyCylinder()”, label=”Cylinder”)
ではないか?と考えます。“Do Nothing”の行と入れ替えて実行します。


ちゃんとボタンをクリックすると、円柱が出ました!正解だったようです。

このようにマニュアルを見ながらサンプルプログラムの意味を分析すると、学習効果が高いです。面倒とか思わずにすぐにチェックしましょう。
さて、でも円柱出すなら、普通にやったほうが早いですよね?しかし、command=”pm.polyCylinder()”みたいのコマンドは1つしかボタンに入れられません。そこで前回の「関数」が再登場なのです。
前回の
def TreeObject():
 pm.polyCylinder()
 pm.polySphere()
 pm.cmds.move(2, 0, 0)
 pm.polyCube()
 pm.cmds.move(-2, 0, 0)
を実行して関数を定義します。
ボタンを出す命令を以下に変更します。
pm.button(command=”TreeObject()”, label=”Tree”)

ボタンで関数を呼び出せば、長い処理をボタン1つで処理ができる訳です。

いかがですか?次回もUIをやって、オリジナルなMayaツールを作成します。

文系デザイナーのためのmaya MEL/Python基礎の基礎 Step2-5

今回は、前回出てきました関数=「def」を命令を理解しましょう。
関数は、

def 関数の名前(引数):
 [タブかスペースを空ける]命令1
 [タブかスペースを空ける]命令2
 [タブかスペースを空ける]命令3
  :
  :
次の命令 [タブかスペースなしで]

というルールです。例えば

import pymel.core as pm
polyCylinder()
pm.polySphere()
pm.cmds.move(2, 0, 0)
pm.polyCube()
pm.cmds.move(-2, 0, 0)

というプログラムを実行すると、以下の結果になります。

当たり前ですが、プログラムは実行した命令の数だけ自動でやってくれます。
それを毎度入力するのは大変です。では関数にします。
import pymel.core as pm
def TreeObject():
 pm.polyCylinder()
 pm.polySphere()
 pm.cmds.move(2, 0, 0)
 pm.polyCube()
 pm.cmds.move(-2, 0, 0)


これを実行しても何も起きません。そこで、
TreeObject()
を実行します。どうですか?ちゃんと同じことを1命令でできましたね?

では少し改造します。
import pymel.core as pm
def TreeObject(x):
 pm.polyCylinder()
 pm.polySphere()
 pm.cmds.move(x, 0, 0)
 pm.polyCube()
 pm.cmds.move(-x, 0, 0)

関数の実行の際に
TreeObject(3)
とします。

どうですか?X=3なので、キューブとボールが±3の位置になりました。「引数」は関数の中に数値などのデータを送り届ける役割をするのです。
ではさらに改造します。
import pymel.core as pm
def TreeObject(x,z):
 pm.polyCylinder()
pm.cmds.move(0, 0, z)
 pm.polySphere()
 pm.cmds.move(x, 0, z)
 pm.polyCube()
 pm.cmds.move(-x, 0, z)
その後、
import pymel.core as pm
for n in range(10):
 print n
 TreeObject(2,n)
を実行します。

こんな感じになりました。for命令は過去にやったと思いますが、
for n in range(10): で下にある行を10回繰り返す、という意味です。
そこにprint nでカウントしているnを表示して、TreeObject(2,n)で関数を呼び出しているのです。
pm.cmds.move(0, 0, z)で、nの値がzに入って移動しながらコピーする、という仕組みです。
でも何かおかしいですね?Zに移動しているのにY方向の上に積み重ねてしまっています。

Display→ObjectDisplay→Local rotationAxisを表示すると、各パーツは横置きなので、Zは上なのですね。
このように関数は長い命令を1つまとめて、プログラムを作りやすく、読みやすくすることができます。

今回はここまでです。