階層・グループ
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 &配列の参照渡し。
関連
- まとめる対象を選ぶ: 「選択・取得」章
- レイヤの表示と個別ノードの表示: 「表示・名前・色・ユーザ定義」章
コメント