モディファイヤ
3ds Max Python チートシート の章一覧
モディファイヤは クラスを呼んで作り、addModifier で載せる のが基本です。
スタック(o.modifiers)は Python から読むと 0 番が一番上 です。
追加する
b = rt.getNodeByName("Box001")
b.heightsegs = 10 # ベンドが滑らかに曲がるようセグメントを増やす
bend = rt.Bend(angle=45, direction=90) # MXS: bend angle:45 direction:90
rt.addModifier(b, bend) # MXS: addModifier b bend
rt.addModifier(b, rt.TurboSmooth(iterations=2)) # 作ってすぐ載せる
rt.addModifier(b, rt.Uvwmap(), before=2) # 上から 2 番目(Bend)の下に差し込む
- ⚠️
addModifierのbefore=Nは「上から数えて N 番目のモディファイヤの 下(評価の順では前)」に入ります。番号は MaxScript の番号なので 1 始まり です。 - インスタンスのノードに
addModifierすると、すべてのインスタンス に同じモディファイヤが載ります。 - 載せられないモディファイヤ(例: スプライン専用のもの)かどうかは
rt.validModifier(b, rt.Bend)で確かめられます。
スタックにアクセスする
b = rt.getNodeByName("Box001")
rt.addModifier(b, rt.Bend())
rt.addModifier(b, rt.Taper())
mods = list(b.modifiers) # list() にしておくと通常の Python のリストとして扱える(MXS: b.modifiers)
top = b.modifiers[0] # 一番上(MXS: b.modifiers[1])
names = [m.name for m in b.modifiers] # ['Taper', 'Bend']
bends = [m for m in b.modifiers if rt.classOf(m) == rt.Bend] # 種類で探す
by_name = [m for m in b.modifiers if m.name == "Bend"] # 名前で探す
base = b.baseObject # 一番下のオブジェクト(Box)
- MaxScript の
b.modifiers[#Bend]のような名前での指定は、Python では内包表記で探すのが分かりやすいです。 m.nameは UI のスタックに表示される名前です。ユーザが名前を変えていることもあるので、確実なのはclassOfでの判定です。
パラメータを変える
b = rt.getNodeByName("Box001")
bend = rt.Bend()
rt.addModifier(b, bend)
bend.angle = 90 # MXS: bend.angle = 90
bend.axis = 0 # 0=X / 1=Y / 2=Z(UI のラジオボタンの順。0 始まり。既定値は 2(Z))
bend.enabled = False # オン / オフ(電球アイコン)
bend.enabledInViews = False # ビューポートでだけオフ
bend.name = "Bend_Main" # スタックでの表示名
- どんなパラメータがあるかは
rt.getPropNames(bend)で一覧できます(→「モジュール管理・デバッグ」章)。 - ラジオボタンの選択は整数で持っていることが多く、MaxScript でも 0 始まり のものがあります。名前と型は
getPropNames/showPropertiesで調べられますが、値の意味(0=X など)はヘルプで確かめます。この値は MaxScript 側でも同じ整数で持っているので、配列の 0/1 始まりの変換とは別の話です。
ギズモを動かす
b = rt.getNodeByName("Box001")
uvw = rt.Uvwmap()
rt.addModifier(b, uvw)
rt.redrawViews() # ← これが無いと gizmo が取れないことがある
uvw.gizmo.position = rt.Point3(0, 0, 10) # MXS: uvw.gizmo.position = [0,0,10]
- pymxs はシーンの評価を MaxScript ほど自動で行わないため、追加直後に
gizmoを読むとAttributeErrorになることがあります。rt.redrawViews()を挟む と取れるようになります(公式ヘルプの回避策)。
削除する
b = rt.getNodeByName("Box001")
rt.addModifier(b, rt.Bend())
rt.addModifier(b, rt.Taper())
rt.addModifier(b, rt.Twist())
rt.deleteModifier(b, b.modifiers[0]) # モディファイヤを渡して削除(一番上の Twist)
rt.deleteModifier(b, 1) # 番号で削除(1 始まり。今の一番上の Taper)
for m in list(b.modifiers): # 特定の種類をすべて削除
if rt.classOf(m) == rt.Bend:
rt.deleteModifier(b, m)
- ⚠️
deleteModifierに 番号 を渡すときは 1 始まりです(b.modifiers[0]と1が同じもの)。 - 回しながら削除するときは、先に
list()でコピーしておきます。
集約する(スタックを確定させる)
b = rt.getNodeByName("Box001")
rt.addModifier(b, rt.Bend(angle=30))
rt.collapseStack(b) # MXS: collapseStack b -- 全部を集約
print(rt.classOf(b.baseObject)) # Editable_Mesh
s = rt.getNodeByName("Sphere001")
rt.addModifier(s, rt.Bend())
rt.addModifier(s, rt.Twist())
rt.maxOps.CollapseNodeTo(s, 2, True) # MXS: maxOps.CollapseNodeTo s 2 true -- 上から 2 番目(Bend)まで集約。Twist は残る
t = rt.getNodeByName("Teapot001")
rt.convertToPoly(t) # 編集可能ポリゴンにして集約(MXS: convertToPoly t)
collapseStackは結果に合った編集可能オブジェクト(多くは Editable_Mesh)になります。ポリゴンにしたいときはconvertToPolyを使います。- 集約はスタックの情報を失う操作です。元に戻せるようにしたいときは
with pymxs.undo(True):で囲むか、先にシーンを保存・複製しておきます。
モディファイヤパネルで操作する
b = rt.getNodeByName("Box001")
rt.select(b)
rt.setCommandPanelTaskMode(rt.Name("modify")) # MXS: max modify mode
rt.modPanel.addModToSelection(rt.Edit_Poly()) # 選択に追加して、パネルで選んだ状態にする
current = rt.modPanel.getCurrentObject() # パネルで選ばれているもの
rt.subObjectLevel = 1 # サブオブジェクトレベル(1 = 頂点)
modPanelは UI の [修正] パネルを操作する関数群です。[修正] パネルが開いていて、対象が選ばれている ことが前提です。- UI に依存するので、バッチ処理では
addModifierを使います。
1 つのモディファイヤを複数オブジェクトで共有する
shared = rt.Bend(angle=30)
for o in rt.geometry:
rt.addModifier(o, shared) # 同じインスタンスを載せる(インスタンスモディファイヤ)
shared.angle = 60 # 全員に反映される
- 別々にしたいときは、ループの中で毎回
rt.Bend()を作ります。
落とし穴まとめ
o.modifiers[0]が一番上。before=/deleteModifierの番号 /CollapseNodeToの番号は 1 始まり。- 追加直後の
gizmoはrt.redrawViews()を挟んでから触る。 - 同じモディファイヤを複数に
addModifierすると共有される。 modPanelは [修正] パネルと選択に依存する。
関連
- 集約したメッシュを編集する: 「メッシュ・ポリゴン」章
- パラメータ名を調べる: 「モジュール管理・デバッグ」章
コメント