オブジェクトのユニークIDを取得する

投稿者: | 2016/03/26

3dsMaxはオブジェクト名がシーン内で一意であることを保証していません。

その為、シーン内でオブジェクト名が重複する可能性が常にあり、名前によってオブジェクトを特定出来ないケースが度々発生します。スクリプト内でノードを保持出来るケースなら問題無いのですが、外部ツールと連携する時や.NETを使用する時などに問題になります。

そういう時には、オブジェクトを一意に特定出来るユニークIDを取得する必要があります。そこで今回は、MaxScriptでのオブジェクトIDの取得について、2種類の方法を紹介します。

inode.handleを使う方法

inode.handleは、全てのノードが持っているプロパティです。
例えばBoxやSphere、あるいはBoneやHelperなど、シーンに直接表示されるオブジェクトは、全てこの方法でIDを取得する事ができます。このIDは、シーン内で常にユニークである事を保証しており、シーンを保存して再起動した場合でも、IDが一巡するまでは必ず同一のノードを指します。

-- ノードからハンドルを取得
id = $box001.handle

-- ハンドルからノードを取得
theBox = maxOps.getNodeByHandle id

注意点として、ノードの種類によってはinodeとは別に固有のhandleプロパティを持っている事があります。その場合、明示的にinodeインタフェースを指定してやる必要があります。

-- これはIDではなくTeapotのhandleプロパティ。(取手のON/OFF)
$teapot001.handle
--> true

-- こうする事で確実にIDを取得
$teapot001.inode.handle
--> 1655

AnimHandleを使う方法

ノード以外のオブジェクト、例えばマテリアル、モディファイヤ、コントローラ等では、AnimHandleという仕組みを使う必要があります。AnimHandleは、文字通りAnimatableオブジェクトのハンドルを取得出来る仕組みで、シーン内のほぼ全てのオブジェクトIDを取得する事が出来ます。

-- box001のマテリアルからハンドルを取得
id = GetHandleByAnim $box001.material

-- ハンドルからマテリアルを取得
theMtl = GetAnimByHandle id

注意点として、このIDは同一のプロセス内でしか一意になりません。つまり、シーンをファイルに保存してMaxを再起動すると、そのIDは無効になってしまいます。

反面、同一プロセス内であれば、たとえ.NET APIであっても一意性は保証されます。
以下はMaxScriptマテリアルを、.NET APIマテリアルとして開き直すサンプルです。

-- AnimHandleを取得
mtlId = GetHandleByAnim $.material

-- DotNet APIでマテリアルを取得しなおす
iGlobal = (dotnetClass "Autodesk.Max.GlobalInterface").Instance
mtlIdPtr = dotNetObject "System.UIntPtr" mtlId
theMtl = iGlobal.Animatable.GetAnimByHandle mtlIdPtr

コメントを残す

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