« 取得 その1001。 全ICETree/RenderTreeビューの取得。 | トップページ | Seed を変えると発射。 »

2012年6月13日 (水)

友愛 その11。 プロパティを View で表示させる。

PPG をいかに小さくするかに命をかけることもあります。


ウインドウ開きっぱなしで作業するタイプのものは、大きいと邪魔ですからね。 XSI の UI が、もっとドック的に埋め込みカスタマイズの自由度が高ければいいんですけどねえ。  AfterEffects のあんな感じみたいに自由にならないかな。フローティングではなくどこかに埋め込みたいんだよな。 あるいは大きなフローティングウインドウの一部に、その時々によって任意に埋め込んだり切り離したりしたいんだよな。



まあ、できないことを嘆いても仕方ないので、フローティングウインドウを我慢して使うのですが、小さいほど嬉しい場合が多いです。 なので過去の友愛シリーズで色々書いたように、PPG 内の表示方法を工夫して、使いやすさと小ささを上手いバランスで共存させられる UI 作りに精を出します。


でも、PPG での表示調整は限界がありますし、そもそも PPG の中の見え方を調整できるというだけであり、PPGウインドウそのものを小さくすることはできません。 PPG を表示させるコマンドである InspectObj には、フローティングウインドウの大きさ調整機能が無いからです。↓

InspectObj (2012)
 http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/index.html?url=si_cmds/InspectObj.html,topicNumber=si_cmds_InspectObj_html




実は、モーダルPPG のみ、2012以降はサイズが変更できるようですね。今度試してみよう。↓

PPGLayout.SetViewSize (2012)
http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/index.html?url=si_om/PPGLayout.SetViewSize.html,topicNumber=si_om_PPGLayout_SetViewSize_html





そこで、InspectObj で PPG を表示させるのではなく、View を新規に作成してその中にプロパティを埋め込むという方法を採ります。 なぜならば、View オブジェクトにはウインドウの大きさを変える機能があるからです。


JScript
----------------------------------------------------------------------

var oP = XSIFactory.CreateObject( "CustomProperty" );
oP.name = "はげちょびん";
oP.AddParameter2( "bHage", siBool, true );

var oP = XSIFactory.CreateObject( "CustomProperty" );
oP.name = "はげちょびん";
oP.AddParameter2( "bHage", siBool, true );

var oL = oP.PPGLayout;
oL.AddItem( "bHage", "はげ" );

//InspectObj( oP );

var oActiveLayout = Application.Desktop.ActiveLayout;
var oNewView = oActiveLayout.CreateView( "Property Panel", "はげちょびん" );
//    この時点でまだ空っぽの View
oNewView.BeginEdit();   
//    この Begin と end が必要な理由が俺よくわかってない
    oNewView.Resize( 100, 55 );   
//    ウインドウの大きさ
    oNewView.Move( 300, 400 );   
//    ウインドウの画面上の出現位置
    oNewView.SetAttributeValue( "targetcontent", oP.fullname );
//    ここで初めて、View の中身が決定される
oNewView.EndEdit();

----------------------------------------------------------------------


View

画像の左側が InspectObj でやった場合のウインドウです。 右が、View を使って小さいウインドウにした場合です。 スクリプトの途中に  //InspectObj( oP ); という部分がありますが、ここを非コメント化して、逆にそれ以降の行を全部コメント化すると、InspectObj バージョンになります。

View を使った方が、あからさまに小さいです。当たり前です。小さくしたんですから。 InspectObj はこれができません。 これがやりたかったんです。





このスクリプトの場合、oP にプロパティが格納されているわけですが、そもそもプロパティとは、シーンの中に埋め込まない限り、いわば概念上の存在です。実体の無い仮想的な入れ物とでも言うか。 それを視覚化するために InspectObj コマンドや CreateView メソッドを使います。 今回のプロパティはシーンに埋め込まず、CreateObject を使って仮想的に作っているので、これらを使わないことには、スクリプトからの制御は出来ても、ユーザにそれを見せることができないわけです。

しかしそれをユーザに見せるためにいつものように InspectObj コマンドを使ってしまうと、表示サイズの制御ができないので、サイズ調整機能を持った View オブジェクトを作りましょうというのが、この記事の話です。



まず、Viewオブジェクトを作るための場所を指定します。


  var oActiveLayout = Application.Desktop.ActiveLayout;


現在アクティブになっている XSI の Layout を指定します。 この Layout オブジェクトに対して CreateView メソッドを使うと、新しい View が作られます。 こうです。


  //    この時点でまだ空っぽの View
  var oNewView = oActiveLayout.CreateView( "Property Panel", "はげちょびん" );


「はげちょびん」 ってのはただの名前なのでどうでもいいです。 大事なのは最初の引数です。 プロパティを表示させたい場合は最初の引数で "Property Panel" と指定してやります。 なぜかはわかりません。そういうもんです。 

ちなみにここで "Explorer" と指定すると、Explorer が新規で出現します。 "Render Tree" と指定すれば、Render Tree が新規で出現します。 キーボードショートカットの 78 などを押した場合と同じ挙動です。 今回の場合はプロパティを出現させたいので、"Proeprty Panel" にします。 これはそういうもんだと覚えてしまうしかないかな。


この時点ではまだ空っぽの View を作っただけです。 "Property Panel" だよと宣言したことによってプロパティが埋め込まれる準備はできたのですが、まだ肝心のプロパティそのものは埋め込んでいません。 でもこの時点で実行させても、既にCreateView メソッドを実行している以上、View は出現します。 空っぽだというだけです。


プロパティを埋め込むのと順番の前後はどうでもいいのですが、サイズと位置をここで決めています。


    oNewView.Resize( 100, 55 );    //    ウインドウの大きさ
    oNewView.Move( 300, 400 );    //    ウインドウの画面上の出現位置


さっき作られた空っぽの View オブジェクトは、oNewView に格納されてます。 oNewView に対して Resize や Move のメソッドで数値をくれてやれば、望みの大きさと位置になります。 今回の場合、主にこの Resizeメソッドを使いたいがために、InspectObjコマンドを避けてわざわざこんな面倒なことをしているわけです。


で、最後に(先にでもいいんですが)、


  //    ここで初めて、View の中身が決定される

  oNewView.SetAttributeValue( "targetcontent", oP.fullname );


ここで、やっとプロパティを View に埋め込みました。 第1引数の targetcontent ってのが、View の中身をセットするためのアトリビュートの名前です。 中身自体は、第2引数です。 今回、前半で CreateObject で仮想的に作ってあるプロパティ = oP を与えてあります。Fullname を渡すということになっています。

順番はどうでもいいと書きましたがもちろん、oNewView に新しい View オブジェクトを格納する前に targetcontent がどうしたとか言ってもダメです。 ちゃんと View オブジェクトをゲットした後であれば、中身をセットするのと、Resize や Move する順番は、テレコになっても構わないという意味です。



作り方は以上。








この方法を採ったときの問題点。

タイトルバーをダブルクリックで畳んでしまうと、再びダブルクリックで戻した時に、空っぽになってしまう。  

Viewempty

なぜ? これはかなり嫌ですね。 空っぽにしない方法があるでしょうか。 どなたかご存知でしたら教えて下さい。





プロパティのパラメータを Preset として保存/読み込みできない。 これは、InspectObj で PPG を表示させたときは右上に出てくる Load/Save Preset が View には無いからですね。 

Loadsavepreset

こればっかりは仕方ない。
どうしても View で Load/Save の機能を付けたかったら、スクリプティングで Preset の Load/Save は可能なので、自前でボタンでも付けて Load/Save させるしかないでしょう。 ただ、そんなことしてボタンに UI 面積を取られて大きくなっていくと、View を使って小さくしようとしたという当初の目的に反するかもしれません。 あるいは View で Load/Save ができる他の方法があればどうか教えて下さい。





以上。






ちなみにプロパティを表示させるために View を使う理由は必ずしも小さい UI が欲しいからというわけでもなく、Move メソッドを使って位置を指定できるのも大きなメリットだと思うんですよね。 特に、多くのプロパティをズラズラと並べて表示させながらいじりたい時などに使えると思います。


こういうのとか。↓

JScript
----------------------------------------------------------------------

var aString = Array( "は", "げ", "ち", "ょ", "び", "ん" );
XX = 100;
YY = 100;

for ( var j=0; j<10; j++ )
{
    for ( var i=0; i<6; i++ )
    {
        var oP = XSIFactory.CreateObject( "CustomProperty" );
        Num = i+1;
        oP.name = "はげちょびん " + Num;
        oP.AddParameter2( "sHage" + Num , siString, aString[i] );

        var oL = oP.PPGLayout;
        var oItem = oL.AddItem( "sHage" + Num, "はげちょびん文字" );
        oItem.SetAttribute( siUICX, 100 );
       
        var oNewView = oActiveLayout.CreateView( "Property Panel", aString[i] );
        oNewView.BeginEdit();
            oNewView.Resize( 250, 60 );
            oNewView.Move( XX, YY );
            oNewView.SetAttributeValue( "targetcontent", oP.fullname );
        oNewView.EndEdit();
       
        XX += 250;
    }
    XX = 100;
    YY += 80;
}


----------------------------------------------------------------------

楽しいことになるので、コピペして実行させてみて下さいよ。

けけけけけけけ。


その後は、インターフェース上のメインメニュー Window > Close All でお願いします。けけけ。


同じ操作をスクリプトで書くなら、

JScript
----------------------------------------------------------------------
var oViews =  Application.Desktop.ActiveLayout.Views;
for ( var i=0; i<oViews.count; i++ )
{
    oViews(i).State = siClosed;
}

----------------------------------------------------------------------

これでもいいですね。 実行させると、スクリプトエディタそのものも閉じられちゃうので一瞬焦りますが。

このように、View オブジェクトの State プロパティを使えば最小化とか元に戻すとかも出来ますね。 このやり方は空調屋のおじさまに聞きました。  詳しくはマニュアルの View オブジェクトページから State プロパティをたどってみて下さい。




あとは、Python なんかだと、マウスポインタの座標もゲットできるんじゃなかったでしたっけ? だとすると、マウスの下にプロパティを View で表示させるとか、できるんじゃないでしょうか。  JScript でもできるかなあ?  っていうか、マウスの座標の取得とかって、XSI の SDK側でその機能を持たせられないでしょうかね?  画面の解像度とかも。







マーティンも View でやっています。
http://myara.blog.fc2.com/blog-entry-124.html


あ、View云々とは関係ないですが、このハードエッジツール、死ぬほど便利です。  普通のやり方=右クリックして Mark Hard Edges なんて、もうやってられません。 非常にジェネリックで汎用性の高い、万人におすすめ出来るツールですこれは。








.

|

« 取得 その1001。 全ICETree/RenderTreeビューの取得。 | トップページ | Seed を変えると発射。 »

コメント

いつもありがたく拝見させていただいていますm(_ _)m

viewを畳んで戻すとviewの中身が空っぽになってしまう問題ですが、oPの部分を

var oP = ActiveSceneRoot.AddProperty ( "CustomProperty");

にすると解決します。
シーンルートにカスタムプロパティを作ってしましますが・・・(;;;´Д`)

もしくは、CustomPreference を作っておいて"targetcontent"のところで
それを参照すると、空っぽにならなくなるようです。
ちゃんとしたブツが存在しないとダメということでしょうか・・・?

あと、BeginEditとEndEditですが、無くてもちゃんと動くみたいですよー


私も以前に同じところでつまずいていたのでコメントさせていただきました。
以上になります。すでにご存じのことを書いていましたらゴメンナサイ!!

投稿: ザクスキ | 2012年6月16日 (土) 16時37分

リンクはありがとうございます!

viewが空っぽになってしまうのはバグだと思います。多分。

viewをダブルクリックで最小化にするだけでも、
XSIはviewが閉じられたと勘違いして仮想プロパティーを削除します。

自分のプラグイン(ハードエッジ)の場合は
SceneRoot に Property(Custom Parameter)を作って、
OnClosed を使って、Viewを閉じる場合、ルートにあるPropertyを削除する
という風に作ったんですけど、

viewを最小化にすると、OnClosedが実行されて、ルートのPropertyを削除しちゃう。
これは潤樹さんのこの記事を読んで気づいたんですけど。

今書いているプラグインのGUIにこれを防ぐため、OnClosedのイベントに直接削除ではなく、Ifを使っています。
onClosed{
if (!oView) DeleteObj(Property)
}

投稿: myara | 2012年6月22日 (金) 01時24分

ザクスキさん、なるほど、実体があればいいわけですね。
やってみました。仰る通りでした。ありがとうございます!

しかし実体は残したくないなあ。

その後サポートに問い合わせてみたら、これはバグではない、仕組み上しかたない、的な答えでした。





マーティン、そうか、シーンルートに実体置いといて、ウインドウ閉じたら消すってのは、いいね。俺もやってみよう。
今、マーティンのハードエッジ 1.3 を試してみたら、確かに、ウインドウ最小化した時も、ダブルクリックでたたんだ時も、プロパティ消えちゃうね。ってことは、1.3 ではまだ if (!oView) DeleteObj(Property) の対策をしてないってことなのかな。(後でソース読んでみよう。。。)

上のザクスキさんへのコメントにも書いたけど、エアコン屋さんのおじさんに聞いたら、この現象はバグじゃないんだってさ。マニュアルに明確に記述はないものの、View の記述がこれこれで、CreateObject の記述がこれこれなので、そこから判断するとこの挙動は仕方のないことだ、という内容の説明でした。うん、バグかどうかなんてどうでもいいし、仕方ないならそれでいいんだが、俺はダブルクリックでたたんでも中身が消えない方法を知りたいだけなのだ。実体を残すのが唯一の方法ということなのかな。 ともかくマーティンが教えてくれた if (!oView) DeleteObj(Property) あたりを試してみよう・・・・。 (今日のICE勉強会が終わってから)

投稿: 潤樹 | 2012年6月22日 (金) 10時19分

俺ハードエッジ1.3では _OnClosed { DeleteObj(prop) } しか使っていなかったから消えてしまいます。
今書いてるプラグインで if(!oView) を使ってみたら上手くいきました。

昨日xsibaseのバグ報告スレッドにこの問題を聞いてみたら、Blair氏は「これはXSIFactoryのバグで、既にログされている」と答えてくれました。直す気があるかどうかは知りませんけど、多分無いでしょうね。

ICE勉強会については後で聞かせて下さい!仕事で忙しくて申請し忘れましたorz

投稿: myara | 2012年6月22日 (金) 12時27分

おお、ログされているバグですか。そうですか。 こりゃ空調屋のおじさんに教えてあげようかな。
情報ありがとうね。いつもお世話になります。

投稿: 潤樹 | 2012年6月26日 (火) 12時31分

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: 友愛 その11。 プロパティを View で表示させる。:

« 取得 その1001。 全ICETree/RenderTreeビューの取得。 | トップページ | Seed を変えると発射。 »