« 2012年3月 | トップページ | 2012年5月 »

2012年4月

2012年4月27日 (金)

選択中のキーフレームを現在フレームにポン。

たった今書きました。




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

//    現在フレームをゲット
var oPC = Dictionary.GetObject( "PlayControl" );
CurrentFrame = oPC.Current.value;

//    現在選ばれているFカーブを、Fカーブコレクションとしてゲット
var oFcurves = Application.FcurveSelection;

//    ゲットしたカーブをループ
for ( var i=0; i<oFcurves.count; i++ )
{
    var oFcurve = oFcurves(i);

 //    選択中のキーフレームを、キーフレームコレクションとしてゲット
    var oSelectedKeys = oFcurve.SelectedKeys;

 //    ゲットしたキーフレームをループ
    for ( var j=0; j<oSelectedKeys.count; j++ )
    {
       
//    現在フレームをセット
        var oKey = oSelectedKeys(j);
        oKey.Time = CurrentFrame;
    }
}


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



Fカーブエディタ上でキーフレームを選択し、このスクリプトを実行すると、そのキーフレームが現在フレーム上に移動します。 そんだけ。 以上です。



モーション作業やってると、けっこうこの操作は多いのです。

で、Fカーブエディタの設定で、キーフレームはフレーム上ににスナップするようにしてあるので、マウスでやってるときなんかはあまり問題ないんです。ドラッグして現在フレームに持って来るだけだから。

でもペンタブでやっているとドラッグが正確にできなくて困ることが多いです。特に、キーの値を変えないまま現在フレームまでドラッグするとなると右クリックすることになるので、ペンタブの右ドラッグはかなりやりにくい。 なのでスクリプトを書いてみました。 どの程度便利になるかは未知数でこれから数日の作業でわかるでしょう。 ひとまずブログに載せておきます。




以下若干スクリプティングな話ですが、



現在選択中のFカーブは、 Application.FcurveSelectionプロパティ で取得できます。戻り値はFカーブコレクションです。Fカーブオブジェクト単体じゃないのです。 なのでループして、ひとつずつFカーブオブジェクト単体として取り出し、何かを実行します。


この場合は SelectedKeysプロパティを使って選択中のキーフレームを取得しています。 戻り値はキーフレームコレクションです。 キーフレームオブジェクト単体じゃないです。 なのでまたループして、ひとつずつキーフレームオブジェクト単体として取り出し、何かを実行します。


この場合、キーフレームオブジェクトに効く Timeプロパティを使って、そのキーの時間軸(フレーム)を指定しています。このスクリプトの場合は現在フレームを指定しています。 もう目的のキーフレームにオブジェクト単体としてたどりついているので、何をやろうと自由です。 キーフレームオブジェクトに有効なメソッドとプロパティが、全て使えるということです。

という単純な構造のスクリプトですね。






Fカーブがらみのスクリプトって、実はなんとなく楽しい気がすることが多い。
なんでだろう?
Fカーブオブジェクトにはメソッドやプロパティがいっぱい用意されているから、
色々できそうだというトキメキがあるのかあ。
わかんないけど。





.

| | コメント (0) | トラックバック (0)

2012年4月24日 (火)

マークされたパラメータの取得2。

前回の記事の続きです。

前に書いた時のコメント欄でもらったアドバイスのうち、ガルさんが教えてくれたやつをまだ試していなかったので、やってみました。





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

var oMarkedParams = GetTheFuckMarkedParamsC( Selection )
if ( oMarkedParams )
{
    Logmessage( "マークされたパラメータ : " + oMarkedParams.count );
    for ( var i=0; i<oMarkedParams.count; i++ )
    {
        Logmessage( "  (" + (i+1) + ") " + oMarkedParams(i) );
    }
}
else
{
    Logmessage( "fuck you." );
}



function GetTheFuckMarkedParamsC( oObjects )
{
   
//    オブジェクト自身と、(カスタム)プロパティ上のパラメータを全部引っかき集める
    var oAllParams = XSIFactory.CreateObject( "XSI.Collection" );
    oAllParams.Unique = true;
    for( var i=0; i<oObjects.count; i++ )
    {
        var oObj =  oObjects(i);
        oAllParams.AddItems( oObj.Parameters );
        var oProps = oObj.Properties;
        for ( var j=0; j<oProps.count; j++ )
        {
            oAllParams.AddItems( oProps(j).Parameters );
        }
    }
   
    var oMarkedParams = XSIFactory.CreateObject( "XSI.Collection" );
    oMarkedParams.Unique = true;


 //    引っかき集めた全パラメータをループ
 //    Marked が true なら、マークされてるパラメータ
    for( var i=0; i<oAllParams.count; i++ )
    {
        var oParam = oAllParams(i);
        if ( oParam.Marked )
        {
            oMarkedParams.Add( oParam );
        }
    }
   
    if ( oMarkedParams.count != 0 )
    {
        return oMarkedParams;
    }
    else
    {
        return null;
    }
}

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


ううむ。 良いじゃないか。


実行スピードは測ってないけど、しくみで言うと、そのオブジェクトが持つ全パラメータをループしているので、しかもカスタムプロパティのパラメータまでループしているので、遅いはずだと思うんですよね。 でも今回の場合は、そのツールの内容上、そんなに速くなくてもいい処理ですこれは。 ドラッグしながら微調整、みたいなインタラクティブ性が重要な場合は速度のチューニングに気を遣うべきだと思うんですが、俺が書こうとしているツールではマークしたパラメータの取得ごときにそこまでのインタラクティブ性は求めない。全然求めない。一瞬待つくらいとか、なんなら1秒や2秒待ったって、困らない。


ということで、速度を求めないなら、コードの素直さとか、脆弱性が無い(どんな場合でも効く)ことの方がよっぽど重要な気がします。  まだ色んな場合で試していないので断言はできませんが、このガル方式は Parameter オブジェクトにインプリメントされている Marked プロパティを見ているだけなので、あまりコケようがないと思うんですよね。 つまり、Marked プロパティが効かないパラメータなんて、無いんじゃないかと。 ならば、どんな場合でも効くんじゃないかと。  もっとも素直であり、改造や移植もしやすく、良いのではないかと。



ってことでこれで行こうかなあ。
落とし穴あるかなあ。



xxx.Parameters とやると、カスタムプロパティ上にあるパラメータまでは引っかかりませんから、上記のコードではまずカスタムプロパティも含めた全パラメータを自前で引っかき集め、結果として引っかき集められたパラメータたちをもう一度ループして Marked をチェックしています。

ここが、自前ではなく既存の機能として引っかき集められると楽なんですけどねえ。 例えば、xxxx.Parameters プロパティではなく、xxxx.Parameters( true ) みたいにメソッドにしてしまって、 true ならカスタムパラメータも含める、false なら含めない、みたいな実装の仕方をしてくれると助かるんですよね。



っていうか、前から言ってますが、そのものズバリ、 X3DObject.MarkedParameters( true ) などというのが一番いいですね。 戻り値は ParameterCollection です。 true にするとカスタムプロパティ上のパラメータを含めます。 false だと含めません。 という感じで、SDKレベルで対応して欲しい。 嘔吐デスク様。




そのうちリクエスト送っておこう。




引き続き、ベターな方法があれば、どうか教えて下さい皆様。









.

| | コメント (0) | トラックバック (0)

2012年4月23日 (月)

マークされたパラメータの取得。

現在マークされているパラメータをパラメータオブジェクトのコレクションとして取得するのが、意外と厄介に思えるのですよ。


問題点は、以前、この記事で詳しく書きました。

コメント欄で、複数のお方と、濃い会話をしています。勉強になりました。





その記事で勉強したことを元に、パラメータオブジェクトを取得するファンクションを2つ載せてみます。

でも、この2つは、どんな場合でも上手く行くのか、まだわかりません。








一つ目は上の記事のガッデムPlotというツールの中から切り出したものです。


JScript
------------------------------------------------------------
var oMarkedParams = GetTheFuckMarkedParams( Selection )
if ( oMarkedParams )
{
    Logmessage( "マークされたパラメータ : " + oMarkedParams.count );
    for ( var i=0; i<oMarkedParams.count; i++ )
    {
        Logmessage( "  (" + (i+1) + ") " + oMarkedParams(i) );
    }
}
else
{
    Logmessage( "fuck you." );
}

function GetTheFuckMarkedParams( oObjects )
{
    MarkingList = GetMarking( );
    if ( MarkingList != null )
    {
        var oMarkedParams = XSIFactory.CreateObject( "XSI.Collection" );
        oMarkedParams.unique = true;
        var aMarkedParams = new VBArray( MarkingList ).toArray( );
        for ( var i=0; i<aMarkedParams.length; i++ )
        {
            for ( var j=0; j<oObjects.count; j++ )
            {
                var oParam = Dictionary.GetObject( oObjects(j) + "." + aMarkedParams[i], false );
                if ( oParam )
                {
                   
//    XYZ 同時にマークされてるためにマーキングリストが scl/euler/pos とかで終わってる場合は
                    //    NestedObjects で XYZ 個別パラメータを取得
                    //    Expression や Op の場合も NestedObjects に引っかかるのでトラップ

                     var oNestedParams = oParam.NestedObjects;
                     if ( oNestedParams.count != 0 )
                     {      
                        for ( var k=0; k<oNestedParams.count; k++ )
                        {
                             if ( oNestedParams(k).IsClassOf( siExpressionID ) )
                            {
                                 oMarkedParams.Add( oParam );   
//    NestedObjects が Expression だった場合
                            }
                            else if ( oNestedParams(k).IsClassOf( siOperatorID ) || oNestedParams(k).IsClassOf( siCustomOperatorID ))
                            {
                                 oMarkedParams.Add( oParam );   
//    NestedObjects が Op  だった場合
                            }
                            else
                            {
                                oMarkedParams.Add( oNestedParams(k) );   
//    上記以外は、個別 XYZ。 たぶん。 自信ない。
                            }
                        }
                    }
                    else
                    {
                        oMarkedParams.Add( oParam );   
//    posx とかなら、NestedObjects は無い
                    }
                }
            }
        }
        if ( oMarkedParams.count != 0 )
        {
            return oMarkedParams;
        }
        else
        {
            return null;
        }
    }
    else
    {
        return null;
    }
}


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


全然エレガントではなく、ちょっと黒魔術っぽいですが、まあ、仕事はできてます。







もうひとつは、コメント欄で教えてもらったものですね。


JScript
------------------------------------------------------------
var oMarkedParams = GetTheFuckMarkedParams( Selection )
if ( oMarkedParams )
{
    Logmessage( "マークされたパラメータ : " + oMarkedParams.count );
    for ( var i=0; i<oMarkedParams.count; i++ )
    {
        Logmessage( "  (" + (i+1) + ") " + oMarkedParams(i) );
    }
}
else
{
    Logmessage( "fuck you." );
}


function GetTheFuckMarkedParams( oObjects )
{
    var oCol = XSIFactory.CreateObject( "XSI.Collection" );
    oCol.items = oObjects;

    var aMarkings = GetMarking().toArray();
    var oCol2 = oCol.FindObjectsByMarkingAndCapabilities( aMarkings.join(), 0 );
    var oMarkedParams = XSIFactory.CreateObject( "XSI.Collection" );
    for ( var i=0; i<oCol2.count; i++ )
    {

        //    Expression が入っていた場合、Parameter オブジェクト以外に、
        //    CompoundParameter というタイプのものもコレクションに入ってしまうため、
        //    Parameter オブジェクトのみを選別するループが必要と思われる
       
        //    デバッグ用
        //Logmessage( oCol2(i).fullname + " = type :" + oCol2(i).type );

       
        if ( oCol2(i).type == "Parameter" )
        {
            oMarkedParams.Add( oCol2(i) );
        }
    }
   
    if ( oMarkedParams.count != 0 )
    {
        return oMarkedParams;
    }
    else
    {
        return null;
    }
}

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



FindObjectsByMarkingAndCapabilities を使っていますが、戻り値が Parameter だけなら楽なんだけど、 Compound Parameter とかいうタイプのオブジェクトが混じることがあるんですよね。 パラメータに Expression が入っていると、こいつが混じる気がします。なので選り分けが必要になります。

その選り分けに、上のコードでは type"Parameter" かどうかで判別していますが、これを ClassID で選り分けようと IsClassOf( siParameterID ) を使うと、この Compound Parameter も siParameterID にヒットしてしまうようで、選り分けにならないんですよ。 なので type を使うことにしています。





ガッデムPlot の時は、このツールの中核である PlotAndApplyAction コマンドがパラメータコレクションを引数として要求してくるので、上のようなファンクションを書いたのでした。 そして今書いている途中の StoreAction コマンドを使ったツールも同様です。 StoreAction コマンドが中核になるわけですが、引数でパラメータコレクションを渡さねばなりません。

もちろんストアすべきパラメータが最初から決まっていれば楽ちんですが、「ユーザが現在マークしているパラメータ」となると、イッキに難易度が上がる気がします。 ひとまず上のどちらかの方法でインプリメントしてみます。





もっといい方法ないでしょうかねえ。
っていうか、SDK 側でそのものズバリの機能を用意して欲しいです。
嘔吐デスク様。




.

| | コメント (0) | トラックバック (0)

2012年4月17日 (火)

貴方のセンターを私に下さい。

5年か6年前に書いて、それなりに使っているツールなんですがね。

1年くらい前に JScript で書き直したり。最近ちょっと手を入れたり。





まあ、大したアレではないのですが・・・。

他人からセンターをもらうツールです。
つまり、オブジェクトのセンターを、他のオブジェクトのセンターに合わせるツールです。
Transform > Match All Transforms のセンター版とでも言うか。


実際、こんなツールを使わずに標準機能だけでやろうと思えば、Center モードにして Match All Transforms を実行すればいいはずなんですが、複数オブジェクトを選んでこれをやると結果が不正確なことありませんかね? 結果としてセットされた新しいセンター位置が、ピックしたオブジェクトのセンターからズレてしまうことがあるように見えるのです。 誰か確認できたら教えて下さい。

それに、そもそも、Center モードに切り替えたり戻したりというのが面倒なので、まあ、このツールを使った方が楽かなあと思っています。



貴方のセンターを私に下さい。
http://homepage3.nifty.com/jjj/XSIFiles/Plugin/JJJ_XSI_Plugins.html

Anatano3



俺は意外とよく使ってますね。





スクリプティング的には、特筆すべきこと無し。 グローバル変数?とやらを使って、そのセッション内は設定を覚えているようにしてあることぐらいか。 まあ、これもどうというアレでもないですね。





ではごきげんよう。






.

| | コメント (0) | トラックバック (0)

2012年4月12日 (木)

飛び飛び連番調教その弐。

昨日書いたやつの、ちょっと改良したバージョンです。
ええと、AEで、歯欠け飛び飛びの連番としてインポートされているフッテージを、イッキにアルファベット順にする(つまりちゃんと連続したシークエンスになる)スクリプトです。





JavaScript
------------------------------------------------------------

//    フレームレート入力時のデフォルト値
DefFrameRate = 12;

var aTargetItemsSelected = new Array();
var aTargetItemsAll = new Array();
var oProjectItems = app.project.items;
//プロジェクト内の全アイテム
for ( var i=1; i<=oProjectItems.length; i++ )
{
    var oItem = oProjectItems[i];
   
   
//    フッテージアイテムであり、静止画でないなら、aTargetItemsAllに拉致
    if ( oItem instanceof FootageItem && oItem.mainSource.isStill == false )
    {
        aTargetItemsAll.push( oItem );
       
       
//    選択もされてたら、さらに aTargetItemsSelected にも拉致
        if ( oItem.selected )
        {
            aTargetItemsSelected.push( oItem );
        }
    }
}


//    選択されてるものがゼロなら、aTargetItemsAllが 対象
//    選択されたら、aTargetItemsSelected が対象
//    いずれも aTargetItems に集約

if ( aTargetItemsSelected.length == 0 )
{
    var aTargetItems = aTargetItemsAll;
}
else
{
    var aTargetItems = aTargetItemsSelected;
}


//    集約されたアイテムを処理
if ( aTargetItems.length != 0 )
//ゼロじゃなければ処理
{
    NewFrameRate = prompt( "フレームレート入力汁", DefFrameRate );
    if ( NewFrameRate )
    {
        NewFrameRate = parseFloat( NewFrameRate );
       
        ResultCount = 0;
        for ( var i=0; i<aTargetItems.length; i++ )
        {
            FuckinReplace( aTargetItems[i], NewFrameRate );
            ResultCount ++;
        }
        alert( "処理したフッテージの数は " + ResultCount + " だそうです。" + "\r\n" + "フレームレートは " + NewFrameRate + " にしたそうです。" );
    }
    else
    {
        alert( "ゴルァ" );
    }
}
else
    //    ゼロなら脅す
{
    alert( "処理対象アイテムが無いのでセーブせずに今すぐマシンをシャットダウンします。慌てて下さい。" );
}


//    差し替え & フレームレート設定
function FuckinReplace( oFootage, NewFrameRate )
{
    var oFile = new File ( oFootage.file );   
//    FootageItem.file = ファイルパスだそうですがほんとですか。
    oFootage.replaceWithSequence( oFile, true ); 
//    第2引数 = アルファベット順  というのは真実ですか。
   
   
//    フレームレートに文字とか変なもの入力していたら NaN になっているので、その場合は元のフレームレートを変更しない
    if ( !isNaN( NewFrameRate ) )
    {
       
//    FootageItem のフレームレートをいじる時は mainSource オブジェクトの conformFrameRate をいじれって死んだばあちゃんが言ってた。
        oFootage.mainSource.conformFrameRate = NewFrameRate;
    }
}

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

ダウンロード ToviToviRengbangChowkyow2.jsx (2.6K)




・フッテージを選んでいた場合、そのフッテージのみが処理対象になるようにした

・何も選んでなければ、プロジェクト内の全フッテージが処理対象になるようにした
(いずれも、連番フッテージのみ)

・フレームレートを入力するようにした



とかなんとか。

昨日のバージョンより確実に使いやすい。
2コマ打ちの素材と1コマ打ちの素材が混ざったプロジェクトで、昨日のだと、1コマ打ちの素材まで2コマなフレームレート( 12fpsとか )に変えられてしまっていましたので。

最初にフレームレートの入力を促されますが、ここで数値ではなく文字列など変なものを入力すると、フレームレートは元のまま変更されません。

数値しか受け付けない入力ダイアログとかって、できるのかな。 XSI なら、例えば整数型で作ったパラメータは小数点も入力できなくなっているし、もちろん文字列も入力できないじゃないですか。それと同じこと、AE のスクリプティングでもできるのかなーと。 知っているお方はなにとぞ教えて下さい。






ふう。
少しずつ書いている。
少しずつ前進してますが。
なんだかな。

AE で取得した配列って、1スタートなんですねえ。
なんでやねん。

でも自分で配列作ったら、当然 0スタートなんですよね。
ええい面倒だ。
これに気付かず、俺などは、なぜ動かないどこも間違ってねえぞゴルァとジタバタするわけですよ。


うーむ、やはり AE のSDK はアレだと思うんですよ。
SDKマニュアルもなんか古いのしかないし、
記述も非常にわかりにくい。
必要なオブジェクト、プロパティ、メソッドもあまり用意されてないように見える。




XSI様を見習え。



いや見習うな。












.

| | コメント (2) | トラックバック (0)

2012年4月11日 (水)

飛び飛び連番調教。

いきなり AfterEffects ネタなんですがね。



XSI で言う Step 2 とかの連番、つまり 1, 3, 5, 7・・・・という番号が飛び飛びになっている連番ファイルって、AE にインポートしにくいですよね。 ドラッグ&ドロップだと連番が歯欠けだぜゴルァと怒られるし、インポートのダイアログからも 「アルファベット順にする」 とかチェック入れてやらないとつながった連番として認識してもらえない。 そもそも、インポートのダイアログ使っちゃうとたくさんのフォルダを訪問しなくてはいけない。ドラッグ&ドロップのようにイッキにインポートできなくてめんどくさいですよね。



Aealert

ほんと、殺意を覚えます。


インポートでエラーが出てもダイアログを出さずに無視する、というようなオプションが無いというのが許せません。 これに限らず、AE ってのは、人間様が常にそこにいて、マウス操作とかOK押すという行為をするということを前提に作られているんですよね。バッチ処理があまり考えられてないというか。 昔はステキなソフトウェアだと思っていたんですが、使えば使うほど、ディスりたくなります。まるで XSI 様のようです。 ま、XSI 様のことは昔からディスっていましたけどね。それこそ、SI|3D の時代から。






ともかくですね、飛び飛び連番は面倒なのです。

でも、番号が飛び飛びになっていない、詰めた連番素材にはしたくないわけです。 第1の理由は、XSI と AE でタイムラインを一致させたいからです。 管理上の問題です。

また、連番の一部をレンダし直す時に、レンダし直すフレームのファイルだけを削除して、あとは勝手に XSI に存在しないフレームを探させてレンダしたりするので、やはり、XSI シーンのタイムラインと一致しているのが一番ラクです。


なので AE のインポート側でどうにか便利にならんものかと思ったんですよね。 おそらくアニメの撮影屋さんなんかは、こういう便利なスクリプトを大量に持っていたりするんでしょうけどね。




ま、ともかく、最低限のものを自作しました。

AE のスクリプティングはまだよくわかりません。
かなりアヤシイですが、ひとまず、俺が使う狭い範囲の中では、思った通りに動いてくれているように見えます。


実行すると、現在開いているプロジェクトのうち、連番素材を全部、アルファベット順の連番として差し替えます。 静止画はスキップされます。されるはず。されてくれ。

つまり、インポートをラクにするのではなく歯欠けの飛び飛び連番としてインポートされている悪い子のフッテージをアルファベット順に調教するというものです。 

なので、ドラッグ&ドロップでインポートした時にいちいち出るファッキンなアラートから逃れられるスクリプトではありません。  ドラッグ&ドロップしたのなら、次々に出るアラートをOK押して行かなければいけないのは、同じです。 このスクリプトはインポートの手順とは全く関係ないです。あくまでもインポート後の処理をするスクリプトです。  まあ、まずは最低限からです。 いずれ改良するでしょう。 



JavaScript
----------------------------------------------------------------------

// フレームレートは手で書き換えるのです
NewFrameRate = 12;
FootageCount = 0;

//    プロジェクト内の全アイテムをループしてるとかなんとか。
var oProjectItems = app.project.items;
for ( var i=1; i<=oProjectItems.length; i++ )
{
   
//    それが FootageItem とかいう野郎だったら拉致する。
    if ( oProjectItems[i] instanceof FootageItem )
    {
        var oFootage = oProjectItems[i];
      
//    静止画かどうかの判別は mainSourceオブジェクトの isStill で可能だと電波が言っているのですが、合ってますかこれ。
        if ( oFootage.mainSource.isStill == false )
        {
            FuckinReplace( oFootage, NewFrameRate );
            FootageCount ++;
        }
    }
}
alert( "処理したフッテージの数は " + FootageCount + " だそうです。" );

//    差し替え & フレームレート設定
function FuckinReplace( oFootage, NewFrameRate )
{
    var oFile = new File ( oFootage.file );   
//    FootageItem.file = ファイルパスだそうですがほんとですか。
    oFootage.replaceWithSequence( oFile, true ); 
//    第2引数 = アルファベット順  というのは真実ですか。

 //    FootageItem のフレームレートをいじる時は, frameRate じゃダメで、
    //    mainSource オブジェクトの conformFrameRate をいじれって死んだばあちゃんが言ってた。

    oFootage.mainSource.conformFrameRate = NewFrameRate;
}


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

ダウンロード ToviToviRengbangChowkyow.jsx (1.4K)




全部の連番が対象になってしまいますので注意です。
 
もともと歯欠けではなかった連番さえも、一緒くたに、分け隔てなく、平等に、アルファベット順の連番として置き換えられます。 俺としては特に不都合無いのでひとまずこうしています。



アルファベット順の連番にすると、AE 内での連番の表示の仕方が変わりますね。

アルファベット順ではない連番は、
Renban1
こういう表記ですが、


アルファベット順にすると、
Renban2
こうなりますね。


まあ、スッキリして見やすい気もするし、でもソース名から連番のスタートエンドが分からなくなるのは嫌かも知れないですね。 しばらくこれで様子を見て、問題あらば改良しましょう。



飛び飛び連番のフレームレートは、コンポのフレームレートと一致しない場合が多いのではないかと思います。 コンポは 24fps で、連番は Step 2 なので 12fps としてインポートしたいとか、そういう場合が多いですね。 なのでアルファベット順として読み込み直したフッテージには、新たにフレームレートを指定してやってます。 ひとまず、スクリプトの冒頭に 12 という数字を書いちゃってます。 変更したいときはここを書き換えるしかありません。 XSI の PPG のようなものを表示させてその都度フレームレートを入力するような仕様にしてもいいと思うんですが、俺の AE スクリプティング能力はまだそこまで行っていません。 いずれ。






スクリプトファイルは

C:\Program Files (x86)\Adobe\Adobe After Effects CS4\Support Files\Scripts

とかに入れておくと、ファイルメニュー > スクリプト に現れるので、いつでも実行できますね。 でも、ここに現れる名前って、変えられないのかな。 ファイル名と同一になってしまうのは、不便ですね。

もちろんここに入れなくても、ファイルメニュー > スクリプト > スクリプトを実行 からその都度ファイルを選んでもいいんですけどね。




Windwos7 64bit 上で、AECS4 で動作確認しました。
CS5 でも動くのかな。 後で試そう。




そのうち、選んでいるものだけを処理対象にするとか、改良すると思います。 まず最初は最低限から。

ドラッグ&ドロップを検知して、そのときにこのスクリプトを走らせるとか、できないのかな。 うーむ、できなさそうだよな。 AE 様だからな・・・。





それにしても AE のスクリプティングは、すげえやりにくいなあ。

XSI 様の方が遥かに良く見える。

おかしいなあ。






.

| | コメント (0) | トラックバック (0)

2012年4月10日 (火)

XSIApplication.Interactive。

XSI は、GUI で起動する場合と、コマンドラインで起動する場合がありますよね。



GUI ってのは普通に XSI で作業する時のアレで、コマンドラインは主にレンダする時のアレですね。


ま、コマンドラインはレンダのためだけにあるわけではなく、スクリプトを使って普通にシーンの変更・保存もできるので、GUI を使わずに脳内だけでスクリプトによる XSI 作業をするという変態の人もいるかも知れません。テキストエディタでスクリプト書きながら、Fカーブも見ずに 「あー このモーション、難しいなあ」 とか言っている変態ですね。 まあ、大昔はCGってもんはそれに近かったのかな。  

一方、ライトの設定やレンダの設定なんかを複数のシーンで次々に変えていくとかであれば、変態でもなんでもなく、実用的なコマンドラインの使い道だと思います。 レンダするシーンが30個あって、サンプリングの Min を全部のシーンで -1 から 0 に変えていくだとか、そういう場面は割とあるわけですが、たった1箇所数値を打ち直すために全部のシーンを開いてられないじゃないですか。 そういう時に1つのシーンでだけ GUI 作業をし、履歴のスクリプトをコピーしておいて、残りのシーンはコマンドラインでそのスクリプトを食わせてバッチ処理、という感じですね。



ま、ともかくですね、コマンドラインは日常的に使います。 俺の場合は、上記のようなシーンのパラメータをバッチ処理でいじるという使い方をすることもあるというだけで、ほとんどはレンダですけどね。 




で、GUI の XSI とコマンドラインの XSI をスクリプトで判別したいときがあったので、サポートさんに聞いてみたら、 XSIApplicationオブジェクトの Interactive プロパティを調べればいいと教えてもらったので、それを記録しておこうと思っただけです。 そんだけ。



どういう時に判別したいかと言いますとですね、俺の場合、前にも書きましたが Softimage のちに~さんが書いた New Scene Options というプラグインを使っていまして、これは XSI を起動したり新規シーンした時などに自動的にスクリプトを実行できるというプラグインなんですね。 XSI の初期状態を、自分が作業しやすい、気に入った状態にしたいので、これを使っています。

このプラグインは当然、カスタムイベントという機能を使って出来ているわけですね。 XSI で何かが起きると、その変化をトリガとしてスクリプトを走らせるというものがカスタムイベントなので、このプラグインの場合は XSI が起動したとか新規シーンを実行したという変化を検知してスクリプトを実行させてるわけです。



問題なのは、XSI 様にとっては GUI な XSI もコマンドラインな XSI も同じなわけでして、つまり、レンダのためにコマンドラインから XSI を実行した場合でも、同じようにプラグインがそのアクションを検知して、スクリプトを実行してしまうわけです。 スクリプトの中身によっては、これが困るんです。 例えばフローティングの RenderTree ウインドウを開く、というような GUI なことをするスクリプトがコマンドラインから実行されると、高確率で XSI様がクラッシュなさいます。


XSI の起動と同時に(つまりレンダが始まる前に)プラグインによりスクリプトが実行され、そこに GUI なことをするコードが書かれているので XSI 様がクラッシュ。  つまりレンダされません。 レンダの前に XSI様がお逝きになるのです。 これが非常に困る。



起動された時に自動的に実行されるスクリプトは、XSI の作業がしやすいように、インターフェースのウインドウ状態や、各種 Visibility(例えばカメラの視野角コーンを表示オンオフとか、センターの表示オンオフとか)をいじるというものなので、コマンドラインで起動するときにはまず関係のないものばかりです。 だから、コマンドラインから起動された場合だけ、このスクリプトを実行されないようにしたかったのです。

New Scene Options というプラグイン側では、その機能は持っていません。 なので、実行されるスクリプト側でそれをやればいいと思ったんですよ。 スクリプトの中に、「今起動されてるこの XSI って、GUI ですか? それともコマンドラインですか?  GUI の時だけこれを実行して下さいね」 と書けばいいと思ったのです。 でもそんな方法は知らない。だからサポートさんに質問してみたら、一瞬で答えが返ってきました。 おじさま、ステキです。



で、教えてもらったのが、XSIApplicationInteractive というプロパティがあって、インタラクティブつまり GUI な状態かどうかを true か false で返すとのことでした。


マニュアル:
http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/index.html?url=si_om/XSIApplication.Interactive.html,topicNumber=si_om_XSIApplication_Interactive_html


http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/index.html?url=files/dev_batch-1.htm,topicNumber=d28e69308


日本語マニュアルって、リンクどこなんだろ。
WEB なヘルプになったのに、日本語と英語をパッと切り替えるボタンとかないんですか。例えば Wikipedia なんかは、現在の項目の各国語のページにすぐ飛べるじゃないですか。使いやすくして下さいよ嘔吐デスク様。年貢納めてるんだからさ。




JScript だと、

if ( Application.Interactive )
{
    ほにゃららん
}


って書くだけですね。ほにゃららんの所に実行したいコードを書きます。 Intereactive が true の時しか実行されません。 コマンドラインでは、スクリプトファイル自体は NewScenesOptionsプラグインによって普通に実行されるわけですが、 Interactive で false が返って来るために、肝心の部分はめでたくスルーされるということです。


ってことで、俺の場合は実行されるコード全てをほにゃららんにブチ込みました。
コマンドライン起動に無害なコードなら、別にほにゃららんの外にあってもいいと思います。






以上。
おじさま。ステキです。






.

| | コメント (0) | トラックバック (0)

2012年4月 9日 (月)

バージョン違いで同時起動。

昔の話ですが、例えば XSI 6 のライセンスがあれば、5 とか以前のバージョンも、いくつでも同時に起動できたんですよね。



でも今は、2012 のライセンスを持っていて、2012 が起動している状態で、2011 をさらに起動しようとすると、インタラクティブライセンスが無いだとか言われて、起動できません。

2012 を全部終了させれば、2011 は起動できるようになります。 しかし、今度は 2011 がひとつでも起動していると、2012 や 2010 は起動できません。





昔は違ったのになあ、と思ってサポートさんに聞いてみたら、 嘔吐デスク様がそういうライセンスポリシーに変更してしまったのでどうにもなりません  という答えが返ってきました。


こんなリンクも教えてもらいました。 公式にはこのように書かれています。
http://tech.autodesk.jp/faq/faq/adsk_result_dd.asp?QA_ID=5669

おお、FAQ なんだ。 やっぱりよくある疑問なんですね。
とっくに定説だったのですか。知りませんでした。


正確には、バージョンが違うと同時に起動できないのではなくバージョンごとにライセンスを1つずつ食ってしまうということなんですね。 俺などはライセンスをひとつしか持っていないので、2012 で1つ食ったら、もうライセンス残ってないから起動できなかったということなんですね。


ちなみにこれって、ネットワークライセンスの場合ですか? スタンドアロンも同じなのかな。






ま、ともかく、そういう仕組みなんだとハッキリわかったので、良かったっす。
こちらの環境のせいではない。
仕方ない。






元に戻せや嘔吐デスク(゚Д゚)ゴルァ!!

なんでこうしたの。
どういう意味があるの。
複数マシンでいくつでも起動できたら困るだろうけど、
同じマシンなら、別にいいじゃねえか。
1台のマシンは同時に人間ひとりしか使わねえよ。

Maya様や Max様も同じなんですか?





それともアレか、例えばバックグラウンドで新しいバージョンを使ってコマンドラインのレンダをしながら、古いバージョンの GUI を起動して作業もするという 「同時使用」 をさせないようにしている、とかですかね?

ケチくさいこと言わないで下さいよ嘔吐デスクさん。
嘔吐CAD とかで儲かってんでしょ。
せめて1つずつだけでもいいから、バージョン違いを同時起動させて下さい。


新バージョンの挙動を確かめたりする時に、本当に必要なんですよ。このプロジェクト、新バージョンに移行しても大丈夫かな? のテストに思いっきり影響するんですよ。いちいち終了させてまた起動するって、やってられないの。 たのみますよ。



もう。












.

| | コメント (0) | トラックバック (0)

2012年4月 6日 (金)

このPassでもそのパッていしおん。

Pass分け分けPartition分け分けなわけですよ。



他の Pass 以下にあるパーティションをカレントPass(現在 Pass) に複製するスクリプトです。


もうちょっと細かく言うと、カレントPass ではなく他の Pass 以下に存在する Partition を、カレントPass 以下で再構築し、Partition に属するオブジェクトも同じ状態し、マテリアルやオーバーライドやビジビリティなどもろもろ設定も複製するという、スクリプトです。





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

// ConoPassDemoSonoPatTayShion ver 0.0025

//    現在 Pass を取得
var oActPass = ActiveProject.ActiveScene.ActivePass;

//    選択しているもののうち、パーティションだけを引っかき集める(現在Pass以下のパーティションは無視)
var oParts = FilterPartition( oActPass, Selection );


//    新規に作られた/発見されパーティションの入れ物
var oNewParts = XSIFactory.CreateObject( "XSI.Collection" );

//    選択していたパーティションをループし、現在 Pass 以下に同名同種のパーティションがあるかどうか探し、
//    あればそのままメンバぶっ込むし、なければ新規に作ってぶっ込む

for ( var i=0; i<oParts.count; i++ )
{
    var oSrcPart = oParts(i);   
//    元のパーティション
    SrcPartType = oSrcPart.PartitionType;   
//    元のパーティションの種類
   

    //    現在 Pass 以下で、同名のパーティションを探す (Filter メソッドで、名前でより分け、見つかった最初のものを返す)
    var oSamePartitionInThisFuckinPass = oActPass.Partitions.Filter( "", "", oSrcPart.name )(0);
    if ( oSamePartitionInThisFuckinPass )
    {
        DestPartType = oSamePartitionInThisFuckinPass.PartitionType;
        if ( SrcPartType == DestPartType )
        {

            //    名前も同じ、種類も同じパーティションが見つかった → 新規で作らず利用
            var oDestPart = oSamePartitionInThisFuckinPass;
            logmessage( "行き先パッていしおん (既にありますた) --> " + oDestPart + " -- Type : " + oDestPart.PartitionType );
        }
        else
        {

            //    同じ名前のパーティションが見つかったけど、種類(オブジェクト or ライト)が違った場合は、それと分かるように名前を付けて新規作成
            var oDestPart = oActPass.CreatePartition( oSrcPart.name + "_PartitionType" + SrcPartType, SrcPartType );
            logmessage( "行き先パッていしおん (無かったからつくりますた) --> " + oDestPart + " -- Type : " + SrcPartType );
        }
    }
    else
    {
       
//    同じ名前のパーティションが見つからなかった場合は、新規作成
        var oDestPart = oActPass.CreatePartition( oSrcPart.name, SrcPartType );
        logmessage( "行き先パッていしおん (無かったからつくりますた) --> " + oDestPart + " -- Type : " + SrcPartType );
    }

    //    行き先パーティションに、元パーティションのメンバ追加 (戻り値は、メンバ追加に問題があれば false になるらしい)
    NothingFuckinWrong = oDestPart.AddMember( oSrcPart.Members );
   

    //    Object Model でコケた時の保険
    if ( NothingFuckinWrong != true )
    {
        MoveToPartition( oDestPart, oSrcPart.Members );
        Logmessage( oDestPart + " : メンバ追加がなにやらヤヴァいらしいのでコマンドでやりますた。", siWarning );
    }
    else
    {
        Logmessage( oDestPart + " : メンバ追加しますた。" + oDestPart.Members.GetAsText() );
    }
    oNewParts.Add( oDestPart );
   
   

    //    元パーティションのもろもろを行き先パーティションにコピー
    oDestPart.viewvis.value = oSrcPart.viewvis.value;
    oDestPart.rendvis.value = oSrcPart.rendvis.value;
    oDestPart.selectability.value = oSrcPart.selectability.value;
    oDestPart.viewplaybackvis.value = oSrcPart.viewplaybackvis.value;
    oDestPart.ghosting.value = oSrcPart.ghosting.value;   
   

    //    元パーティションにマテリアルがあれば、新パーティションにも適用
    var oPartitionMat = oSrcPart.LocalProperties.Filter( siMaterialType )(0);
    if ( oPartitionMat )
    {
        oDestPart.SetMaterial( oPartitionMat );
        Logmessage( oDestPart.name + " : マテリアルアサインしますた --> " + oDestPart.Material );
    }
   

    //    元パーティションにオーバーライドがあれば、新パーティションにも複製
    var oOverrides = oSrcPart.LocalProperties.Filter( siOverrideType );
    for ( var j=0; j<oOverrides.count; j++ )
    {
 
//    パーティションの Visibility が No Effect 以外になってる場合、プロパティではないオーバーライドが存在するらしいので除外
        if ( !oOverrides(j).name.match( "VisibilityOverride" ) )
        {
            CopyPaste( oOverrides(j), null, oDestPart, 2 );
        }
    }
    var oNewOverrides = oDestPart.Properties.Filter( siOverrideType );
    for ( var j=0; j<oNewOverrides.count; j++ )
    {

 //    パーティションの Visibility が No Effect 以外になってる場合、プロパティではないオーバーライドが存在するらしいので除外
       if ( !oNewOverrides(j).name.match( "VisibilityOverride" ) )
        {
            oNewOverrides(j).name = oOverrides(j).name + "_dup1";
            Logmessage( oDestPart.name + " : Override 複製しますた --> " + oNewOverrides(j).name );
        }
    }

}

//    行き先になった全てのパーティションを選択しておしまい
if ( oNewParts.count != 0 )
{
    SelectObj( oNewParts );
}
else
{
    Logmessage( "No fuckin' valid partitions selected. Fuck you.", siError );
}



//    Partition だけ返すファンクション(現在Passのは除外)

function FilterPartition( oActivePass, oObjects )
{
    var oParts = XSIFactory.CreateObject( "XSI.Collection" )
    for ( var j=0; j<oObjects.count; j++ )
    {
        if ( oObjects(j).IsClassOf( siPartitionID ) )
        {
            if (  oObjects(j).Parent.fullname != oActivePass.fullname )
            {
                oParts.Add( oObjects(j) );
            }
        }
    }
    return oParts;
}

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

※追記
早速修正しますた。赤い字のコメント部分

これでたぶんエラー出ない・・・と思う



今週使いまくってます。 まずまず使えるではないか。
まあ、自分で要るもの書いてんだから当たり前ですがね。





例えばですが、

Cono1

hogehoge という Pass で色んなパーティションがあり、色んなオブジェクトが入っています。 オブジェクトもライトも。 で、パーティションにはマテリアルやオーバーライドも付いています。



これを、HAGE という Pass 以下でも再現したい場合に使うスクリプトです。

完全に同じパーティション構成の Pass が欲しいのなら Pass を複製すればいいだけですが、なんらかの事情でもう Pass は作ってしまっていて、他の目的のパーティションも混在するのでそれを作り直すのは面倒だったりなど、新規に Pass を作るのではなく既存の Pass を活かしたまま、特定のパーティションだけこっちの Pass でも再現したい、という場合に使います。  俺はしょっちゅうありますこういう場面。






使い方は、まずはこれからパーティションを作りたい Pass をカレントPass にします。 そして、Explorer から、複製の元になるパーティションをいくつでも選びます。

Cono2

↑まだパーティションを作っていない HAGE Pass を現在 Pass にしました。 

そして、複製の元になるパーティション、つまりカレントPass ではない他の Pass (この場合は hogehoge Pass)に所属するパーティションを、複数選んでいます。



この状態でスクリプトを実行すると、

Cono3

カレントPass である HAGE Pass 以下で、hogehoge Pass 以下にあったパーティション(選んでいたもの)を再現します。 というスクリプトです。


パーティションの名前は同じ。
所属するオブジェクトも同じ。
パーティションの各種 Visibility も同じ。
マテリアルがあればアサイン。
オーバーライドも複製(名前は同名が存在できないので _dup1 とか付けてます)。
ええと、他に再現すべき属性はありますかね・・・?

以上。













スクリプティング的に特筆するとすれば、


    var oSamePartitionInThisFuckinPass = oActPass.Partitions.Filter( "", "", oSrcPart.name )(0);


同名のパーティションを探すのに、PartitionCollection.Filter を使ってます。 ループするより Filter の方が短く書けて便利、なのかな。どうだろ。 実行速度はどうなんだろ。

Filter メソッドの戻り値も Collection なので、(0) を付けて最初の一人を指定してやらないと Partition Object にたどり着けません。 ここは常に (0) でいいと思います。なぜならば、パーティションは同名のものが存在できないからです。 なので名前でフィルタして見つかった「最初のひとり」と指定すれば、安全にその名前のパーティションを取得できると思います。








マテリアルを探すときは、LocalProperties です。


    var oPartitionMat = oSrcPart.LocalProperties.Filter( siMaterialType )(0);


カレントPass にあるパーティションのマテリアルは Partition.Material で取得できます。なければ null が入ります。 しかし今回は、カレントPass ではなく他の Pass にあるパーティションに割り当てられているマテリアルを取得したいのです。 カレントPass以外にあるパーティションに対して .Material とやってもダメです。 .Material は、現在の状態しか気にしてくれません。

.Material ってのは、カレントPassだろうが Group で上書きされてようがなんだろうが、結果として現在どのマテリアルになってんのか、を返すと考えればいいんじゃないでしょうかね。 どうでしょうかね。 間違ってたら教えて下さい。

やりたいのは、あっちの Pass でどうなっているのかを調べてこっちでも再現するということなわけですから、.Material を使って「現在状態」を調べても意味はないということですね。 なので、LocalProperties を使います。 LocalProperties は、マテリアルに限らず、そいつに与えられた色んなプロパティが取得されます。 なので当然、戻り値は Collection です。 今回はその中からマテリアルだけを取得したいので、また Filter メソッドを使います。しかし今度は上の例とは違って、名前ではなく、タイプでフィルタしています。siMaterialType ですね。

そしてここでも (0) を使って 「見つかった最初のマテリアル」 を取得しています。 パーティションに対して複数のマテリアルは与えられません。 つまり、パーティションの LocalProperties からマテリアルだけをフィルタできたら、そのマテリアルが唯一のマテリアルであるはずです。 だから (0) を使って大丈夫です。 たぶん。




その後の Override でも、全く同じことをしてますね。


   var oOverrides = oSrcPart.LocalProperties.Filter( siOverrideType );


LocalProperties から、siOverrideType でフィルタしています。 マテリアルと違ってオーバーライドの方はいくつでも与えられますから、(0) などとは書かずに取得しています。従って oOverrides には Collection が格納されます。 よって、次のループでひとりずつ呼び出して処理をしています。 ただし、今回の場合はコピペコマンドですから、もしかしてループの必要がなかったかも知れません。つまり Collection(複数)に対して丸ごと効いたかも知れませんという意味です。実験してないです。今気付きました。




オーバーライドの複製は CopyPaste コマンドを使っているんですが、他に方法を知りません。知っていたら教えて下さい。

CopyPaste コマンドには戻り値が無いもんですから、結果としてペーストされたブツへのリファレンス、つまりこの場合はペーストされたオーバーライドを取得する手がかりが、何もありません。 となると、ペーストされたオーバーライドをリネームしようとすると困るわけです。

今回の場合はたまたまですが、ペースト先は 「新規に作られたパーティション」 である場合が多いので、もう、行き先のパーティションに存在するオーバーライドをたった今ペーストされたばかりのオーバーライドであるとみなし、若い順にリネームしています。 新規で作られたパーティションである限りは、この方法でオーバーライドの名前はちゃんと複製元と一致すると思います(_dupとかは付きますが)。  

しかし、同名のパーティションがカレントPass以下に存在した場合は新たに作らずにそのパーティションを使う流れになっているため、たまたまそのパーティションが元々オーバーライドを持っていたりすると、コピー元とコピー先でオーバーライドの数が違ってくることになり、にも関わらず数値で若い順からリネームしているので、複製元と複製先でオーバーライドの名前が一致しなくなるでしょう。 でもまあ、知りません。 オーバーライドの名前を調べて一致したら複製しないだとか上書きするだとかも考えられますが、面倒なのでそこまでしません。








とかなんとか。






仕事をサボって書くブログは、なんて楽しいんでしょう。




ウソです。

ちゃんと裏ではレンダ回してます。
このスクリプトでパーティション分けたシーンをレンダしてます。




でも、もう僕は疲れたよパトラッシュ。






.

| | コメント (0) | トラックバック (0)

2012年4月 5日 (木)

var oFuck = Dictionary.GetObject( "preferences.rendering.region_display_mode" );oFuck.value = oFuck.value === 1 ? 2 : 1;。

またもやコードはタイトルに。
JScript です。



レンダリジョンの表示を、RGB と Alpha でトグルする高級スクリプトです。


Rgb_a_toggle
この左右の状態を行き来するというだけです。


リジョンの左上の三角クリック > Display > RGB Only とかやってらんないじゃないですか。 めんどくさいんですよ。


だからショートカットにでも割り当ててやりたかったんですよ。
ボタン化するときにでもコマンドとして登録してやって、ショートカットから起動できるようにすればいいですかね。





このスクリプトも過去に何度も書いては紛失し、そのたびに書き直すという実に無駄なことを繰り返してきたので、とうとうブログに書いておきます。失くしたらここに来ます。


昔作ったリージョンさんというプラグインの中にもこの機能はありますが、まあ、単体でサッとできた方が圧倒的に便利ですね。








var oFuck = Dictionary.GetObject( "preferences.rendering.region_display_mode" );oFuck.value = oFuck.value === 1 ? 2 : 1;



このコードですが、Preference の中のリジョンの表示の設定をいじっていることになりますね。 ビューごとではないので、複数のリジョンがあったら全部に影響があります。


値が 0 と 1 のトグルだったら、ToggleValue コマンドとかでやってやるのがラクなんでしょうけど、俺は RGB と A でトグルしたく、これが 1 と 2 のトグルなんですよ。 1 だったら 2 にしなさい、そうでなければ 1 にしなさい、というコードにする必要がある。 なので、過去にブールのトグルの記事を書いた時に頂いたコメントからパクりました。


A = A === X ? Y : X


という書き方をすると、「A の値が X だったら Y を新たに A に入れろよ。 そうじゃなきゃ X を入れろよ」 という意味になるようです。どうやら。 三項演算子っていうんですか。さっぱりわかりませんが、上記の挙動でたぶん合っていると思います。今後のスクリプト書きでガンガン活用したいと思います。 教えてくれた anamorph さんに感謝します。






あ、いや、違った。

俺はスクリプトとか無い国へ移住します。





.

| | コメント (4) | トラックバック (0)

2012年4月 4日 (水)

とっかえパッていしおん。

よくあるじゃないですか。
2つのPartition の間で、中身のオブジェクトをごっそり入れ替えたいこと。
パーティションマテリアルやらオーバーライドやらがたくさん付いている時とか、かな。
よくありますよね。




ないですか。




そうですか。




俺はあるんだよ (# ゚Д゚) ムッカー



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

//    とっかえパッていしおん

//    パーティション2つだけ選んで、かつタイプが一致してないとディスられる
if ( Selection.count == 2 )
{
    if ( Selection(0).type == "Partition" && Selection(1).type == "Partition" )
    {
        if (  Selection(0).PartitionType ==  Selection(1).PartitionType )
        {
            SwapMembers( Selection(0), Selection(1) );
            Logmessage( Selection(0).name + " <--> " + Selection(1).name + " : Members swapped. Fuck you anyway." );
        }
        else
        {
            Logmessage( "Partition type mismatch. Fuck you.", siError );
        }
    }
    else
    {
        Logmessage( "I said select 2 partitions. Fuck you.", siError );
    }
}
else
{
    Logmessage( "Select 2 partitions. Fuck you.", siError );
}

//    メンバ入れ替えファンクション
function SwapMembers( P1, P2 )
{
    var oMembers1 = XSIFactory.CreateObject( "XSI.Collection" );
    var oMembers2 = XSIFactory.CreateObject( "XSI.Collection" );
    oMembers1.Items = P1.Members;
    oMembers2.Items = P2.Members;
    NothingFuckinWrong1 = P1.AddMember( oMembers2 );
    NothingFuckinWrong2 = P2.AddMember( oMembers1 );
   
//    OM でコケる時があるので MoveToPartitionコマンドの保険を付けることもあるが今回は面独裁ので省略
}




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


パーティションを2つ選んで実行します。
すると、中身を入れ替えます。
Aに入ってたブツはBに入り、Bに入っていたブツはAに入るということです。



Pass をまたいだ2つのパーティションで実行してもたぶん効くはずだと思いますが実験してません。っていうか混乱するだけなのでやめた方がいいでしょう。 Pass をまたぐと警告を出すだとかそういう風に改造するかも知れません。



Partition.AddMember がコケる時があるんですよね。なぜだかはわからない。 そんなときは、Partition.AddMember の戻り値は上手くメンバが追加できたときは true でそうでないときは false のようですので、これを使って false の時だけ MoveToPartition コマンドを使うという書き方をしたこともあります。 まだよくわかっていない。 今回は省略してます。





それなりに便利じゃないか。
さっさと書けばよかったな。








.

| | コメント (0) | トラックバック (0)

2012年4月 3日 (火)

ヌルとかの方向でポン。

忘れないうちにメモりますよ。


ICE で、Direction 系ですね、何かの 「方向」 を指定するときに、Vector の x, y, z の数値じゃさっぱりわからんじゃないですか。  0, 1, 0 って言ったら Y の真上方向、とかってすぐわかりますけど、「右上69度の方向」 とかやろうと思ったら、 x, y, z のベクタで言えますか? あなた言えますか? 言えるあなたはCG屋に向いていません。




なのでシーンの中のオブジェクトの rot を利用したいじゃないですか。 ヌルとかが向いている方向が、そのまま ICE で使うベクタになっていて欲しいじゃないですか。


これ、基本的過ぎて、ICE のチュートリアルビデオ集みたいなの見てると、最初の方でよく出てきますよね。 俺も過去に何度もやっているんですよ。 でもそのたびにチュートリアルビデオひっくり返したり、人に聞いたりして。 いつまで経っても覚えない。

記憶しようとしているからダメなんですよね。 日本のうんこたれ英語教育と同じで、英単語を暗記しても英会話はできない。 それと同じで、ノードのつなぎ方を丸暗記しても ICE たんとの会話はできないわけです。 英語も ICE語も同じ。 ICE の考え方が体に滲みこんでいれば、特定のノードのつなぎ方を覚えていなくても、ああーこうやりゃいいはずだなー ってわかるはずですよね。英語と全く同じです。日本語で考えず、英単語の引き出しを探しもせず、英語の流れの中で、英語の頭で考えれば、それらしき表現が出てくるもんです。



でも今回は、丸暗記のためにメモしますよ。 
ええ。

だってもう、何回もやってるんだもん。 そのたびに、あれえどうだったっけーって大騒ぎするの、もう嫌だもん。 周辺の皆様、ご迷惑をおかけしました。



今回は m4g さんに教えてもらいましたが、ちょっと ICE 知っている人なら、こんなんすぐできますわね。 俺はまだできねえよ。 くそう。

ICE があのトーラスと共に衝撃のデビューを飾ったのが、2008年ですか。 もう4年前ですか。俺も一応、その年から ICE はいじり始めてますから、今度の秋が来れば4年も経ったことになるわけです。 最初に ICE 使った仕事は、たしかあの作品。 5年生の学校での日常を描いたあの作品。 教室で、スローモーションで飛んでいく牛乳パック。 そこに刺さったストローからこぼれる牛乳のしずく。 を、ICE でやったんだと思う。 Blob でレンダしたような気がするな。 今ならポリゴナイザ使うのかなあ。

ともかくですね、そんなに長いこと ICE いじってても、いまだにこんなことすら、パパっとできないんですよ。ええ。  だって、ICE を思いっきり使う仕事が、継続してないんですよ。 何かの仕事でガッツリ ICE やって、わあ、理解深まったなあ(゚∀゚) なんて思ってても、次に本格的に ICE 使うのが半年後とかね。  これじゃあ、覚えられないです。 ・・・いや、きっと俺が、もっと何にでも ICE を使おうとすればいいのかな。何でもできそうだからな。 ううむ。




とかなんとか前置きは長いくせに、以降の肝心の部分は短いです。はい。

Rotatevector

ダウンロード NullRotationToDirection.zip (223.6K)

(XSI 2012)


矢印が2つありますが、これはアイコンを矢印に変えたヌルです。


オレンジの矢印が、エミッションの方向です。
緑の矢印が、Wind フォースの方向です。


エミッションの方は、Emit コンパウンドの中で Use Initial Direction Vector を選んで、ブツのノーマル方向に発射しないようにしています。


ヌルの kine.globa.ori を取得します。 グローバルの回転ですね。で、 Rotate Vector ってのがキモですね。 あるベクタを、この kine.global.ori の値だけ回転させて新しいベクタを得るって感じですか。

で、その「あるベクタ」 ってのが、上の例の場合、 0, 0, 1 になってますね。 これが、ヌルの方向と一致させるためのベクタですね。  この場合はヌルの Z の方向が、新しく得られるベクタになります。 もしここを 0, 1, 0 にした場合は、ヌルのY方向が新たに得られるベクタになります。

オレンジのヌルは他のヌルの子供なっていますが、global のローテーションを取得しているので、ローカルでどっち向いてるかは関係ありません。あくまでもグローバルの回転を読み取っています。アイコンの見た目の向いている方向と一致させたいわけだから、これが都合いいはず。 ローカルで考えると、矢印がローカルでどこかを向いていた場合、矢印が向いている方向とツリーの中の Vector が、見た目上合わなくなりますからね。




ってことで、ヌルのZ方向にパーティクルを発射し、もうひとつのヌルのZ方向に風が吹いて流されるという ICE ツリーができました。 方向のコントロールはツリーの中ではなく、ビュー上のオブジェクトの見た目でわかりやすく。 という趣旨でした。 以上。

m4g さんありがとう。いつまでもヘタレですいません。 きっと今後もこんな感じで変わりません俺は。すいません。










ふう。
これでもう忘れねえだろう。
書いた内容より、書くという行為によって、覚えるんだよね。
しかも、万が一忘れても、まあ忘れるだろうけど、
自分のブログに1回書いたぞ、というのさえ記憶しておけば、
すぐに情報にたどり着けます。



とか言って。
自分でブログに書いたぞという事実すら、簡単に忘れるんだよねえ。


あれえ? 
なんで俺、こんなことも知らねえんだ?
一回やってたんじゃなかったんか?


とかいうパニックをごくりと飲み干して Google 先生に聞いてみると、
検索結果トップは自分のブログ記事だったり。


なんだ、一回やってんじゃん俺 orz
すっかり忘れてたよ orz


どれどれ、と思って内容を読んでみると、
なんだか一回やった記憶もなくて、
ほぼ初めての情報に見えて、
わぁ 参考になりますた ありがとう潤樹さん (゚∀゚)

とか。






俺はもうダメだ

ポリゴンのない国へ行こう







.

| | コメント (2) | トラックバック (0)

2012年4月 2日 (月)

私は、重力の呪縛から解放され、塵のように宙を漂いたい。

Fly

だって腰が痛いんですもの。


座ってたら、腰が痛い。下半身の圧迫から来ると思われる各部のシビレもひどい。

立ってても、腰が痛い。 長時間立つと、やはり腰は痛むものです。 足も痛くなります。 っていうか立ちっぱなしは普通に疲れ過ぎます。 1日で合計12時間以上とか立っていると、だんだん集中力が落ちて、後半はもう、1クリックするごとに椅子に座ってしまいます





だから漂いたい。
重力から逃れたい。
神よ。
今週だけでもいいから。


.

| | コメント (0) | トラックバック (0)

友愛その10。 小数点以下。

以前の友愛シリーズが尻切れトンボなのは全く無視して唐突にまた友愛の話が出てきてもそれは仕方のないことです。



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

var oP = XSIFactory.CreateObject( "CustomProperty" );
oP.name = "ドルァ小数点";
oP.AddParameter2( "hage", siDouble, 3.1415926535 );


var oL, oItem
oL  = oP.PPGLayout;
oItem = oL.AddItem( "hage", "はげ1" );
oItem.SetAttribute( siUIDecimals, 1 );

oItem = oL.AddItem( "hage", "はげ3" );
oItem.SetAttribute( siUIDecimals, 3 );

oItem = oL.AddItem( "hage", "はげ10" );
oItem.SetAttribute( siUIDecimals, 10 );

InspectObj( oP );

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

Dec_2

パラメータは、1つしか作ってません。
Double型です。 なので保持している値は、小数点以下があります。
そのひとつのパラメータを、3回 PPG に表示させてます。
小数点以下の数値をどこまで表示させるか。

  PPGItem.SetAttribute( siUIDecimals, 桁 );

の呪文の話ですた。



以上。





.

| | コメント (0) | トラックバック (0)

2012年4月 1日 (日)

ToggleValue( "ViewCube.show", "preferences" );。

コードはタイトルに。 JScript です。

ビューキューブ君の表示をトグルする高級なスクリプトです。


いちいち Preference に潜っていくのがめんどくさくて、
さっきブチ切れて、
ついに意を決して開発したスクリプトです。

なぜインターフェースのオモテにそのスイッチがないんだ XSI 様。





それにしてもこのキューブ君、最初はすんげえ馬鹿にしてたんだけど、
いやあ、便利ですよねえ (゚∀゚)
ぐりぐり回したりとかには全然使わないんだけど、
上下ひっくり返したりとかね。
トップビューで、鼻先を上に向けたい時とかあるじゃないですか。


でも消えていて欲しいこともあるわけでね。
だから高級スクリプトを書いたのです。











ところで、こういうスクリプトを、インターフェースの空いているちょっとした隙間に埋め込みたいんだよな。そういうことができるといいのにな。


例えばインターフェース上の Scene Search の右横とか、いっぱいスペース空いていてもったいないですよね。  

Ui

ここ使いたい・・・・。





ちなみに左側のボタンの下の隙間は、ツールバーを置いて自作の小さいスクリプトのボタンにしています。 

Ui2

このキューブトグルのスクリプトも、とりあえずここら辺に置きました。 トレイスイッチャにして複数のツールバーをタブで切り替えて使うのが推奨であります。






.

| | コメント (0) | トラックバック (0)

« 2012年3月 | トップページ | 2012年5月 »