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

階層・グループ

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

オブジェクトを構造化する操作です。親子リンク(親を動かすと子も一緒に動く)、グループ(複数のノードを 1 つの塊として扱う)、レイヤ(表示・フリーズなどをまとめて管理する単位)はそれぞれ別物です。

親子リンク

$Child.parent = $Parent      -- リンクする
$Parent.children             -- 直接の子(NodeChildrenArray。インデックスへの代入はできないが append / deleteItem は可)
$Child.parent                -- 親(無ければ undefined)
$Child.parent = undefined    -- リンクを外す
  • 親を動かすと子も追従します(transform が伝播)。
  • ⚠️ parent への代入は 現在の見た目の位置を維持 します(ワールド位置は変わらない)。
  • リンク後も $Child.pos はワールド座標のままです。親から見た位置が欲しいときは in coordsys parent $Child.pos と書きます。

階層をたどる

-- 直接の子だけ
for c in $Parent.children do print c.name

-- 子孫すべて(再帰)
fn getDescendants node =
(
    local result = #()
    for c in node.children do
    (
        append result c
        join result (getDescendants c)
    )
    result
)
getDescendants $Parent

-- トップレベルのノード(親を持たない)を集める
for o in objects where o.parent == undefined collect o

-- シーン全体の木の根
rootNode.children
  • children は 直接の子だけ です。孫まで欲しいときは上のように再帰します。
  • rootNode はシーンの見えない根です。rootNode.children はトップレベルのノードと同じ集合になります。

グループ

g = group selection name:"MyGroup"  -- 選択をグループ化(名前を省くと Group001 のような一意名が付く)
isValidNode g                       -- 失敗すると group は OK を返すので確認する
isGroupHead g                       -- グループの親ノードか
isGroupMember $Box001               -- グループの中身か
setGroupOpen g true                 -- グループを開く(中身を個別選択可能に)

attachNodesToGroup #($Teapot001) g  -- 既存グループに追加
detachNodesFromGroup #($Teapot001)  -- 外す(開いたグループのメンバーであること)

ungroup g                           -- 1階層だけ解除
-- explodeGroup g                   -- 入れ子のグループもまとめて全部解除(ungroup は 1 段だけ)
  • グループは、ビューポートに形を持たない見えないノード(グループヘッド)を親にして、メンバーをその子としてリンクした構造です。objects を回すとこのヘッドも含まれるので、isGroupHead で除外します。
  • UI でメンバーを個別に選ぶには setGroupOpen g true で開きます。スクリプトからメンバーを列挙するだけなら g.children で足ります(開かなくてよい)。

レイヤ

lm = LayerManager
lay = lm.getLayerFromName "Props"                         -- 取得
if lay == undefined do lay = lm.newLayerFromName "Props"  -- 無ければ作成
lay.addNode $Box001                                        -- ノードをレイヤへ移動

$Box001.layer        -- ノードが属するレイヤ
$Box001.layer.name   -- レイヤ名

レイヤの表示・状態を変える

lay.ishidden = true  -- 非表示(レイヤごと)
lay.isFrozen = true  -- フリーズ
lay.current  = true  -- 現在のレイヤにする(以後作るノードはここに入る。false は代入できない)

-- レイヤに属するノードを集める(参照渡し。詳細は「選択・取得」章参照)
nodes = #()
lay.nodes &nodes
nodes

lay.getNumNodes()    -- 数だけならこちらで足りる
  • ⚠️ lay.nodes &nodes は 参照渡し(&)で配列を受け取る独特な API です。戻り値ではなく引数が書き換わります(「選択・取得」章にも同じ話があります)。

レイヤを一覧する

for i = 0 to LayerManager.count - 1 collect (LayerManager.getLayer i).name  -- ⚠️ 0 始まり

lay2 = LayerManager.newLayerFromName "Temp"
lay2.setName "Temp2"                    -- 名前の変更(name プロパティは読み取り専用)
LayerManager.deleteLayerByName "Temp2"  -- 空(ノードが無い)で現在のレイヤでなければ削除できる

落とし穴まとめ

  • parent 代入はワールド位置を維持する(見た目は動かない)。
  • children は直接の子のみ。子孫は再帰で集める。
  • グループのメンバー列挙はヘッドの children。UI で個別選択するときや detachNodesFromGroup する前は setGroupOpen g true で開く。グループヘッドは objects に含まれるので isGroupHead で除外する。
  • レイヤの非表示は ishidden(on はレイヤの[有効]状態で、非表示とは別)。LayerManager.getLayer は 0 始まり。
  • レイヤのノード列挙は lay.nodes &配列 の参照渡し。

関連

← MaxScript チートシート へ