今回は3dsmaxとPythonで簡単なGUIを作ってみようと思います。
プログラムを実行すると、ウインドウが作成され、ボタンをクリックすると、ティーポットがランダムな位置と角度に発生します。
例によって参考にしたサンプルはこちらです。
import MaxPlus as mp import math import random # GUIを使うためのPySideのライブラリを読む from PySide import QtGui from PySide import QtCore # ウインドウを消さない方法 class _GCProtector(object): widgets = [] # ティーポットをランダムに移動と回転して作成 def make_teapot(): obj = mp.Factory.CreateGeomObject(mp.ClassIds.Teapot) node = mp.Factory.CreateNode(obj) obj.ParameterBlock.Radius.Value = 5.0 x1 = random.uniform(1,100) y1 = random.uniform(1,100) Rz = random.uniform(0,360) node.Position = mp.Point3(x1, y1,0 ) qtr = mp.AngAxis(0,0,1,math.radians(Rz)) node.Rotation =mp.Quat(qtr) # 時間を0に設定して、画面を再描画(しないと出ない) time = mp.Core.GetCurrentTime() mp.ViewportManager.RedrawViews(time) return # メインの関数 def GUI_test(): # ウィンドウのオブジェクト作成 w = QtGui.QWidget() # ウィンドウのサイズ w.resize(300, 100) # ウィンドウのタイトル w.setWindowTitle('MaxPlus_GUI') # ウィンドウを前面に出す w.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) # 水平方向にボタンなどUIを並べる main_layout = QtGui.QVBoxLayout() # ラベル表示 label = QtGui.QLabel("Click button to create a Object") main_layout.addWidget(label) # ボタン表示 teapot_btn = QtGui.QPushButton("Teapot") main_layout.addWidget(teapot_btn) w.setLayout(main_layout) # ボタンを押したら動く関数 teapot_btn.clicked.connect(make_teapot) # ウィンドウの表示 _GCProtector.widgets.append(w) w.show() # 3daMaxをリセットしてメインを起動 mp.FileManager.Reset(True) GUI_test()
長い!とか思われるかと思いますが、連載をご覧の方は過去と同じ個所が結構あります。
1~3行、10~20行は前回の連載のランダムにティーポットの位置と回転を作る関数ですので、省略します。
22、23行が新しい機能で、Pythonスクリプトで3dsmaxを操作した場合、画面を更新しないのです。なので、シーンエクスプローラーにはあるのに表示されない、という問題を解決します。
time = MaxPlus.Core.GetCurrentTime() mp.ViewportManager.RedrawViews(time) 時間をカレントタイムを変数に入れて、RedrawViews(変数)とすればOKです。
今回の新しい機能は「PySide」というのを用います。
実はMayaや他の3DCGツールもこれを使っていて、PyhtonでGUIを作るには便利な機能です。
5、6行がこの命令を使うためのライブラリを読み込んでます。
from PySide import QtGui
from PySide import QtCore
28~37行目がコメント通りにウインドウの作成やう浮きさタイトルを決めます。
レイアウトはこちらなどをご参考ください。
ちなみにリンク先は3dsMaxもMayaも関係ありません。PySideはPythonだけでも使うので多くのサンプルや文献があるのです。だからPyhtonで3DCGツールを作るメリットがあるのです。
重要なのでは35行目で、これが無いとウインドウが3dmaxを含め後ろに隠れてしまいます。
w.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
38~46行目でウインドウ内に文字とボタンを作っています。
label = QtGui.QLabel("Click button to create a Object")
main_layout.addWidget(label)
これで文字表示。
teapot_btn = QtGui.QPushButton("Teapot")
main_layout.addWidget(teapot_btn)
これでボタン表示。
w.setLayout(main_layout)
これでそれらをレイアウト。
teapot_btn.clicked.connect(make_teapot)
ボタンを押したら、make_teapot関数を動作させます。
そして、49、50行でウインドウを表示させます。 _GCProtector.widgets.append(w)
w.show()
これで完成なのですが、1つ問題が出ます。このままだとウインドウが表示されてもすぐ消えてしまうのです。そこで、8,9行目を最初に入れておきます。
class _GCProtector(object):
widgets = []
これはどうやら3dsmaxのメモリ管理の問題で使わないウインドウを見つけると無駄だと考えて消してしまうらしいのです。それを止めるのが「CGプロテクター」だそうです。
53行で3dsMaxをリセットして、54行でメインのGUI_test()関数を実行します。普段は35行目は削除しておかないと、スクリプト実行で作成しているシーンが消えてしまいますから注意です。
mp.FileManager.Reset(True)
GUI_test()
今回はここまでです。