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

選択・取得

  • 3dsMax
  • MaxScript
  • チートシート
MaxScript チートシート の章一覧

スクリプトの起点になる「対象を手に入れる」操作をまとめます。 選択を変える系(select)と、選択せずに集める系(for ... collect)を使い分けるのがコツです。

全部・現在の選択を取得する

objects          -- シーン内の全ノード(コレクション)
selection        -- 現在選択されているノード
$                -- 現在の選択の省略形(1 つならそのノード、複数なら選択のセット、未選択なら undefined)
selection.count  -- 選択数
objects.count    -- 全ノード数
  • objects / selection は 選択を変えずに中身を読む ための入口です。
  • ⚠️ スクリプトでは $ より selection を使います。未選択でも selection はエラーになりません($ は未選択だと undefined なので、$.count のような書き方はエラーになります)。
  • ⚠️ objects はジオメトリだけでなく、ライト・カメラ・ヘルパーなど 全ノード を含みます。種類で絞るには、次の「種類ごとのコレクション」か、後述の「種類(クラス)で絞り込む」を使います。

種類ごとのコレクション

objects と同じように、種類別にまとまった組み込みコレクション が、あらかじめ用意された システム変数(コレクション)として使えます。これを使えばクラス判定を書かずに目的の種類だけを取得できます。

geometry     -- 全ジオメトリ(Box / Sphere / Editable_Poly ...)
lights       -- 全ライト
cameras      -- 全カメラ
shapes       -- 全シェイプ(スプライン / テキスト ...)
helpers      -- 全ヘルパー(Dummy / Point ...)
spacewarps   -- 全スペースワープ
systems      -- 全システム(Bones / Biped ...)

lights.count                 -- ライトの数を数える
for c in cameras do print c.name  -- カメラ名を列挙
select geometry              -- ジオメトリだけを選択
コレクション 取得対象 近い絞り込み(ターゲットは除く)
objects 全ノード —
geometry ジオメトリ全般 superClassOf o == GeometryClass
lights ライト全般 superClassOf o == light ※ターゲット含む
cameras カメラ全般 superClassOf o == camera ※ターゲット含む
shapes シェイプ全般 superClassOf o == shape
helpers ヘルパー全般 superClassOf o == helper
spacewarps スペースワープ全般 superClassOf o == SpacewarpObject
systems システム全般 superClassOf o == System
  • いずれも objects と同じく 選択を変えずに読める コレクションで、.count や for ... do がそのまま使えます。
  • ⚠️ lights / cameras には ターゲット(注視点)オブジェクトも含まれます。ライト本体だけを処理したいときは where classOf o != Targetobject や superClassOf o == light で除外します。
  • ⚠️ さらに細かく「Box だけ」「Omni ライトだけ」が欲しいときは、これらに対して後述の where classOf o == ... を重ねます。例: for o in lights where classOf o == Omnilight collect o -- Omni ライトだけ

名前で1つ取得する

$Box001                          -- 名前で直接指定(存在しないとエラーではなく undefined 扱い)
getNodeByName "Box001"           -- 文字列(変数)から取得。無ければ undefined
getNodeByName "box001" ignoreCase:false  -- 大文字小文字を厳密に区別(既定 true = 区別しない)
getNodeByName "Box001" exact:true         -- 名前の比較方法をより厳密にする(既定 exact:false)
  • 名前が 変数や文字列 になっているときは getNodeByName を使います。$ の後ろには変数を書けません。
  • ⚠️ 大文字小文字を制御するのは ignoreCase:、比較の厳密さを制御するのは exact: です。混同しないよう注意します。
  • ⚠️ 同名ノードが複数あると、既定では最初に見つかった1つだけが返ります。すべて欲しいときは getNodeByName "Box001" all:true で配列が返ります。
  • ⚠️ 名前にスペースや . などが入るときは $'My Box' のようにシングルクォートで囲みます。

名前のパターンでまとめて取得する

$Box*            -- 「Box」で始まる全ノード(ワイルドカード)
$*_low           -- 「_low」で終わる全ノード
($Box* as array) -- 配列にして for で回しやすくする
  • *(任意の文字列)と ?(任意の1文字)が使えます。
  • 親子関係で指定することもできます: $Dummy001/*(直下の子)、$Dummy001...*(子孫すべて)。
  • 結果は配列ではないので、as array で配列化すると扱いやすくなります。

選択を操作する

select $Box001        -- 選択を置き換える
selectMore $Sphere001 -- 現在の選択に追加する
deselect $Box001      -- 選択から外す
select objects        -- 全選択
clearSelection()      -- 全解除
selectByName()        -- ダイアログで選んだノードを配列で返す(選択は変わらない。キャンセルで undefined)
関数 動作
select <obj> 選択を 置き換え
selectMore <obj> 選択に 追加
deselect <obj> 選択から 除外
clearSelection() すべて解除
  • select には単体ノードでも配列でも $Box* でも渡せます(例: select #($Box001, $Sphere001))。
  • selectByName() は「名前により選択」ダイアログを開いて選んだノードを 配列で返すだけ の関数で、それ自体はシーンの選択を変えません。選択したいときは select (selectByName()) のようにします。

種類(クラス)で絞り込む

-- Box だけを集める(選択は変えない)
for o in objects where classOf o == Box collect o

-- ジオメトリ全般を集める(球でも円柱でもメッシュでも)
for o in objects where superClassOf o == GeometryClass collect o

-- ライトだけを選択する
select (for o in objects where superClassOf o == light collect o)
判定 用途
classOf o == Box そのクラスちょうど(派生は含めない)
superClassOf o == GeometryClass ジオメトリ全般
isKindOf o GeometryClass 派生も含めて「〜の仲間か」
  • 代表的なスーパークラス: GeometryClass / shape / light / camera / helper。
  • ⚠️ ノードの classOf は モディファイヤ適用後(スタック最上部)のクラス を返します。元が Box でも、編集可能ポリゴンに変換したり編集系モディファイヤを載せたりすると Box では引っかかりません。元の種類を見たいときは classOf o.baseObject を使います。

条件で絞り込む(表示・色・レイヤなど)

-- 非表示・フリーズを除いた「いま触れる」ノード
for o in objects where (not o.isHidden) and (not o.isFrozen) collect o

-- ワイヤフレームカラーが赤のノード
for o in objects where o.wirecolor == red collect o

-- 特定レイヤに属するノード
lay = LayerManager.getLayerFromName "Layer01"
nodesOnLayer = #()
lay.nodes &nodesOnLayer   -- 参照渡しで配列に格納される
nodesOnLayer   -- 中身をリスナーで確認
  • where の後ろには任意の条件式を書けます。複数条件は and / or でつなぎます。
  • ⚠️ layer.nodes は 参照渡し(&)で受け取る点が独特です。戻り値(成功なら true)ではなく、引数に渡した配列にノードが入ります。

名前付き選択セット

selectionSets["ExportSet"] = selection   -- 現在の選択をセットとして保存
select selectionSets["ExportSet"]        -- セットを呼び出して選択
selectionSets.count                      -- セット数
deleteItem selectionSets "ExportSet"     -- セットを削除
  • UI の「名前付き選択セット」と同じものを読み書きできます。

ループ中に選択を変える / 削除するときの定石

-- ✕ ループ中に対象を消すと取りこぼす
-- for o in selection do delete o

-- ◯ いったん配列のコピーを取ってから回す
for o in (getCurrentSelection()) do delete o
-- または
for o in (selection as array) do delete o
  • getCurrentSelection() と selection as array は、どちらもその時点の選択を 配列 として返します。以後シーンが変わっても中身は変わりません。
  • ⚠️ selection や objects を 回しながら中身を増減 させると、取りこぼしやエラーの原因になります。削除・再選択を伴うループでは必ずコピーしてから回します。

落とし穴まとめ

  • $Name には変数を書けません。変数・文字列からは getNodeByName を使います。
  • objects は全ノードです。ジオメトリだけが欲しいなら superClassOf == GeometryClass で絞ります。
  • 編集系モディファイヤやコンバートでクラスが変わります(Box → Editable_Poly など)。元の種類は classOf o.baseObject で見ます。
  • 削除・再選択を伴うループは getCurrentSelection() でコピーしてから回します。

関連

← MaxScript チートシート へ