[3dsMax]カレントレイヤーの中身を全部削除するスクリプトを作る際に出た問題について


カレントレイヤーの中身を全部削除するスクリプト

カレントレイヤーの中身を全部取得して、
それをforループで1つずつ削除するだけだと思っていたら罠があった。

●最初に作ったスクリプト

hako = layerManager.current
	--↑現在のレイヤーを取得し、変数hakoに入れる。

hako.nodes &nakami
	--↑現在のレイヤー内にある全てのオブジェクトを、変数nakamiに入れる。

for i in nakami do delete i
	--↑forループで変数nakamiに入っているものを削除する。
この作りだとカメラやライト等がレイヤー内にあるとエラーを出しまった。

”既に削除されたオブジェクトを削除しようとしている”という感じのエラー。

●エラーの原因を推測

原因はターゲットオブジェクトがセットになっているオブジェクト。
ターゲットとセットになっているオブジェクトは、片方を削除すると、もう片方も一緒に削除される。

例えば、ターゲットカメラのカメラ本体を削除すると、ターゲットも一緒に削除される。逆も同じ。
これはスクリプトで削除を行っても変わらない。

forループが取得した全オブジェクトを順番に削除していくなかで、
セットになったオブジェクトの片方が削除されたとき、もう片方も自動的に削除される。
forループはそれを感知できず、削除されたもう片方に対して削除を行うが、
もう片方はもう存在していないのでエラーが出てしまう。

こんな感じのはず。

●対策

処理を変える。
forループの代わりに、whileループを使う。
whileループは条件が一致している時だけ処理を繰り返す。

”レイヤー内のオブジェクトを1つ削除する→レイヤー内のオブジェクトを全部取得する”
↑これをレイヤーが空になるまで繰り返す。

--↓カレントレイヤー内のオブジェクト一覧を取得する関数を用意
fn syutoku &reiya =(
	ire = layerManager.current
	ire.nodes & nakami
	nakami
)

--↓オブジェクト一覧からオブジェクトを一つ削除する関数を用意
fn sakujo =(
	hako = syutoku &reiya

	if hako.count != 0 do(
	delete hako[1]
		)
)

--↓カレントレイヤー内のオブジェクトの総数を変数kazuに入れる。
kazu = (syutoku &reiya).count

--↓オブジェクトの総数が0より大きい場合に処理を繰り返す。
while kazu>0 do(
	sakujo() --←上の方で用意した関数sakujoを呼び出す。
	kazu = (syutoku &reiya).count --←オブジェクトの総数を変数kazuにいれる。
)

これで ”削除されたオブジェクトを削除しようとする事” は無くなり、
セットで消えるオブジェクトがあってもエラーは出なくなった。

———————————————–

【追記】

isDeleted関数を使えば、オブジェクトが削除されているかを判別できる。
これを使えば、forループでも問題ない。

hako = layermanager.current
hako.nodes & nakami


for i in nakami do(
	if (isDeleted i)==false do(
		delete i
	)
)

●参考文献

3ds Max 2017 ヘルプ ノードの共通プロパティ、演算子、メソッド
ノード ユーティリティ

広告

コメントを残す

メールアドレスが公開されることはありません。

スパム対策用の計算式と画像認証です。↓の欄を入力しないとコメントが出来ません。 *

*