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

投稿者: | 2016/03/26

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

その為、シーン内で同名のオブジェクトが複数存在する可能性が常にあり、オブジェクトをハンドル出来ないケースが度々発生します。
例えば外部ツールと連携する時、.NET側でデータを保持する時、などなど・・・。

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

inode.handleを使う方法

inode.handleは、全てのノードが持っているプロパティです。
例えばBoxやSphere、あるいはボーンやヘルパーなど、座標を持ったオブジェクトは全てこの方法でIDを取得する事ができます。

$box001.handle
--> 1647 (ユニークID)

ただし、このIDはシーン内ではユニークである事を保証していますが、他のシーンが絡むと必ずしもユニークにならない事があるので、注意が必要です。

また、ノードの種類によっては、inodeとは別にhandleプロパティを持っている事もあり、こちらも注意が必要です。

-- これはIDではなく、Teapotのhandleプロパティ
$teapot001.handle
--> true

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

AnimHandleを使う方法

ノード以外のオブジェクト、例えばマテリアル、モディファイヤ、コントローラ等をハンドルするにはAnimHandleという仕組みを使うことができます。

AnimHandleは、文字通りAnimatableオブジェクトのハンドル(ID)を取得出来る仕組みで、シーン内のほぼ全てのオブジェクトのIDを取得する事が出来ます。

例えばマテリアルからハンドルを取得するには以下のようにします。

GetHandleByAnim $box001.material
--> 6193P

逆に、ハンドルからオブジェクトを復元する時には以下のようにします。

GetAnimByHandle 6139P
--> 01 - Default:Standard

注意点として、このIDは同一のプロセス内でしか有効になりません。
例えばIDをファイルに保存するような使い方をすると、Maxを再起動後にそのIDは無効な値になってしまいます。

反面、同一プロセス内であれば、たとえ.NET APIであっても一意性は保証されます。

以下はMaxScriptマテリアルオブジェクトを、.NET APIマテリアルオブジェクトで開き直すサンプルです。

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

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

コメントを残す

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