先日の GUID でストーク。 の記事でまたまた有り難い情報を頂きまして、さらに実験してみました。
以下をコピーしてスクリプトエディタに貼り付けるか、このファイルをダウンロードしてスクリプトエディタで開いて、実行。
//Yes_Stalker5_GoGo.js
// ****** カスタムプロパティ作成
var oCProp = XSIFactory.CreateObject('CustomProperty');
oCProp.name = 'ストーカー ~ あなたを絶対逃がさない ~';
// ******
カスタムプロパティにパラメータ作成
oCProp.AddParameter3('sGUID',siString,'');
//GUIDパラメータ作成
oCProp.AddParameter3('sCLSID',siString,'');
//CLSIDパラメータ作成
oCProp.AddParameter3('sName',siString,'','','',false,true); //元の名前パラメータ作成
// ****** カスタムプロパティのUI
作成
var oLayout = oCProp.PPGLayout;
oLayout.AddItem('sGUID','GUID');
//GUID パラメータを UI に追加
oLayout.AddItem('sCLSID','CLSID');
//CLSIDパラメータを UI に追加
var oItem = oLayout.AddButton('GetGUID','GUID と CLSID取得。'); //ID取得ボタン作成(ボタンにはパラメータは無い)
oItem.SetAttribute(siUICX,300);
//ボタンの横幅(ピクセル)
oLayout.AddItem('sName','(元の)名前');
//元の名前パラメータを
UI に追加
oLayout.AddSpacer(0,10);
//すき間空けただけ
oItem =
oLayout.AddButton('Stalk','ストーク。');
//ストークボタン作成(ボタンにはパラメータは無い)
oItem.SetAttribute(siUICX,300);
//ボタンの横幅(ピクセル)
// ****** ボタンに機能割り当て
oLayout.Logic = GetGUID_OnClicked.toString()+
Stalk_OnClicked.toString();
oLayout.Language = 'JScript';
// ******
ID取得ボタンをクリックした時に実行されるルーチン
function GetGUID_OnClicked()
{
if (Selection.count !=0)
{
// ****** 選択中のオブジェクト(最初の1個)から GUID と
CLSID をゲット
var oDataRep =
XSIUtils.DataRepository; //DataRepositoryオブジェクトを取得(IDにアクセスするため)
GUID =
oDataRep.GetIdentifier( Selection(0), siObjectGUID )
;
//GUID取得
CLSID =
oDataRep.GetIdentifier( Selection(0), siObjectCLSID);
//ClassID取得
// if ( Selection(0).type == "customparamset")
// 上のように type で
特定しようとすると、Self-installed
形式のプロパティが customparamset として
// 認識されない模様。
従って、下のように、classname
を使うと、全てのカスタムプロパティ
// (上記 type == "customparamset" でヒットするものも含む)がストーク↓できますた。
if (classname(Selection(0)) ==
'CustomProperty')
{
CLSID =
'{76332571-D242-11d0-B69C-00AA003B3EA6}';
}
// 一方、Custom Operator の方は・・・・
// classname で CustomOperator
とすると、Self-installed オペレータだけでなく、
// 普通のスクリプトオペレータもヒットする(当たり前か)。
// しかし、普通のスクリプトオペレータと Self-installing
カスタムオペレータ を
// ひとくくりに
{72936430-9B0C-4167-8CA7-C30FC2188BB9} としてしまうと、
// ストークした時に普通のスクリプトオペレータの方だけ引っかかってくれない。
// なので、
//
//
1:Self-installing カスタムオペレータの type は、常にオペレータの名前になっているっぽい
//
2:普通のスクリプトオペレータの type は、常に ScriptedOp ( = siScriptedOpType)
になっているっぽい
//
// この2点を利用して、
//
// Classname が
CustomOperator であり、
// かつ type が siScriptedOpType
ではない = それは Self-Installed カスタムオペレータである
// 従って CLSID に
{72936430-9B0C-4167-8CA7-C30FC2188BB9} を授けよう
//
// としたら↓上手く行っているように見えます。
if (classname(Selection(0)) ==
'CustomOperator' && Selection(0).type != siScriptedOpType)
{
CLSID =
'{72936430-9B0C-4167-8CA7-C30FC2188BB9}';
}
PPG.sGUID.value =
GUID;
//GUIDパラメータに、さっきゲットした
GUID の値をぶち込む
PPG.sCLSID.value =
CLSID;
//CLSIDパラメータに、
さっきゲットした ClassID の値をぶち込む
PPG.sName.value =
Selection(0).fullname; //名前パラメータに、現在の名前をぶち込む
}
else //何も選んでないくせに ID 取得ボタンを押すアフォな人に向けたメッセージ
{
var Msg =
XSIUIToolkit.MsgBox('つけまわす人を選んどけっての。(
゚Д゚)オラ!',siMsgOkOnly,'ストークする気あんのかゴルァ');
}
}
// ******
ストークボタンをクリックした時に実行されるルーチン
function Stalk_OnClicked()
{
if (PPG.sGUID.value != '' && PPG.sCLSID !=
'')
{
// FindObjects コマンドを使って、シーン中 Class ID
が一致するものだけを oFindColl に格納 (XSICollection)
var oFindColl = FindObjects( null,
PPG.sCLSID.value );
var oDataRep =
XSIUtils.DataRepository;
Flag = 0;
//発見フラグ初期化
for (var i=0;
i<oFindColl.count; i++)
{
//oFindColl の中身をループ。ひとつずつ GUID の値を変数
CurrItemGUID にぶち込む
CurrItemGUID = oDataRep.GetIdentifier( oFindColl(i), siObjectGUID ) ;
// すでに Class ID
が一致するものだけに絞り込まれている。後は GUID が一致すれば桶。
//
でもこれって、FindObjects コマンドが Class ID だけじゃなくて、
// 直接 GUID を受け付けてくれればもっと楽なんじゃなかろか?
if
(PPG.sGUID.value == CurrItemGUID)
{
Flag ++;
// 発見フラグ勃起 ピコーン
SelectObj(oFindColl(i));
// 選ぶ
InspectObj(oFindColl(i)); // 表示する
CenterSelection(null,true); // ビューの中央に持ってくる
FrameSelection(null,true); // しかも寄る
Msg = 'みーつーけーたーわーよー ヽ(°▽、°)ノエヘヘヘヘ';
// 名前が変わっていた場合
if (oFindColl(i).fullname != PPG.sName.value)
{
Msg += '\r\n\r\n' +
'名前を変えても無駄よう~ ヽ(°▽、°)ノ ケケケケケケ';
Msg += '\r\n\r\n' + '元の名前 = ' +
PPG.sName.value;
Msg +=
'\r\n' + '今の名前 = ' + oFindColl(i).fullname;
}
else
{
Msg += '\r\n\r\n' +
oFindColl(i).fullname;
}
var Msg = XSIUIToolkit.MsgBox(Msg,siMsgInformation ,'ストーク成功。');
break;
}
}
if (Flag == 0) //発見フラグが立たない=死亡。
{
var
Msg = XSIUIToolkit.MsgBox('・゚・(つД`)・゚・ どこへ行ったのっ
!!!',siMsgCritical,'あなたの大切な人は死にますた。');
}
}
else //ID を取得してないのにストーク。ボタンを押すアフォな人に向けたメッセージ
{
var Msg =
XSIUIToolkit.MsgBox('つけまわす人を決めとけっての。(#゚Д゚)ドルァ!!',siMsgExclamation,'ストーク
する気あんのかゴルァ');
}
}
InspectObj(oCProp,null,null,siLock);
|
前回のスクリプトでは ActiveSceneRoot.FindChildren としていましたが、前回も書いたとおり、このメソッドは
X3DObject に対するメソッドであり、返ってくる値も X3DObjectCollection
です。 つまり、ストーク対象が3Dオブジェクトに限られるわけで、3Dオブジェクトではない Group やら Pass やら
Visibility(プロパティ)やらなんやらは、せっかく固有の GUID
を持っているのにストークできないことになります。もしこういう人たちを好きになってしまったらどうすればいいのでしょう。 ストークできないなら死んだ
ほうがマシです。
というのが問題だったわけですが。
有り難き情報を元に、頂いたスクリプトを若干いじってこのようにしました。
要は、FincChildren メソッドの代わりに、FindObjects コマンドを使えばいい、ということですよね?
ね? ね? そういうことですよね? 勘違いしてませんよね?
FindObjects コマンドの説明は、以下(SDKマニュアルよりコピペ)。
----------------------------------------------------------------------------------------
説明
オブジェクトをタイプで検索します。
スクリプト構文
FindObjects (
[Path], [Type] )
パラメータ
|
パラメータ
|
型
|
説明
|
|
Path
|
String
|
オブジェクトのパス名(実装されていません)
|
|
Type
|
String
|
オブジェクトのクラスID。このGUIDは、各オブジェクトのタイプをユニーク
に識別します。たとえば、Phongシェーダの各インスタンスは同じクラスIDを持ちます。このIDはLambertシェーダのIDとは異なります。クラ
スIDは、SPDLファイルのReference行またはDataRepository.GetIdentifierか
ら特定できます。
|
戻り値
検出されたオブジェクトを持つXSICollectionオ
ブジェクトを戻します。
----------------------------------------------------------------------------------------
1つ目のパラメータが「実装されていません」ってのが謎というかアフォですが。
で、どうやらこのコマンドは、シーンの中から、指定した ClassID を持っている人を探してくれるらしい。 ならば、先にストークしたい人の
ClassID をゲットしておいて、実際にストークする段階でこの FindObjects コマンドを使ってその ClassID
を持つ人だけに絞り込み、その中から GUID
が一致する人を探せばいいということですよね? ね? ね? そういうことですよね? 勘違いしてませんよね?
FindChildren メソッドは X3DObject に限られるのに対し、FindObjects は ClassID
という、X3DObject 以外の人たちでも必ず持っている ID を元に検索をかけるので、あらゆるものが検索対象になり、結果も
X3DObjectCollection ではなく XSICollection
として返してくれる、とゆーことだと理解しました。 ね? ね? そういうことですよね? 勘違いしてませんよね?
でも、上記スクリプトのコメントの中にも書きましたが、もしこの FindObject コマンドが ClassID だけではなく GUID
を受け付けてくれれば、いちいち絞り込みすることなくいきなり FindObjects(null, GUID);
ってやれば一発で1つのものを特定できるような気がするんですが、どうですかね。 その場合、ヒットするものは唯一無二の物のはずなので、戻り値は
Collection じゃなくて SceneItem になるのかな? ま、現在このコマンドはそういう仕様になっていないのでダメなわけですが。
それと、これも上記スクリプトの中のコメントに詳細を書いていますが、Self-Installed 形式のプロパティだけは Type ==
"custompset" で識別できませんでした。 Self-Installed
形式ではなく、シーンの中で手動で作ったカスタムプロパティはこれで認識できましたけど。 なので Type をやめて Classname ==
"CustomProperty" を使ってみたら、Self-installed
もそうじゃないのもちゃんとストークできました。ううむ。これでいいんだろうか。
一方、カスタムオペレータの方は・・・。
SDK Explorer などで見てもわかりますが、Self-Installed 形式のカスタムオペレータも、Self-Installed
形式ではない通常のスクリプトオペレータも、 Classname は CustomOperator になっています(下の画像赤線)。
しかし、これを利用して Classname == "CustomOperator " とくくってしまうと、後で FindObjects
コマンドでストークした時に、通常のスクリプトオペレータの方だけが引っかかってくれません。つまり通常のスクリプトオペレータの ClassID
は{72936430-9B0C-4167-8CA7-C30FC2188BB9} ではない、ということになると思います。 ううむ。なんでですか。
そこで他に両者の違う点を探してみると、Classname は同じ CustomOperator でも Type
は違っていることに気づき(上の画像の黄色線)、カスタムオペレータを作る別のプラグイン(デュアルQとか)で試しても常にこの結果になるように見えたの
で、判別するときに Classname だけでなく Type
も併用することにしました。すると、ちゃんとストークできるようになりました。 ううむ。これでいいんだろうか。
と、なんだか暗中模索状態ですが、ともかく前回のように3Dオブジェクトに限定されるようなことはなくなったので、進歩したと思います。氏に感謝いたしま
す。
でも基本的にシロートが十分とは言えない質と量で実験した結果をもとに書いていますので、何かとんでもない落とし穴や勘違いがあるかもしれません。そうい
う場合は是非指摘して下さい。
|
コメント