リファレンス / 3ds Max / 3ds Max Python チートシート

モディファイヤ

  • 3dsMax
  • Python
  • pymxs
  • チートシート
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 は [修正] パネルと選択に依存する。

関連

← 3ds Max Python チートシート へ