2016年12月22日木曜日

ノードのアトリビュート名を調べる。

セッターやゲッター使うときにアトリビュートの名称を調べるのがなかなか大変。
使っていくうちに覚えたりはするのですが、しばらく経つと忘れたりするし、ロング名じゃなくてショート名が使いたかったりすることも有ります。

手っ取り早く調べるなら、スクリプトエディタの"Echo All Commands"にチェックを入れて、アトリビュートエディタを操作したログで確認するとか。
スライダー操作のものは分からなかったりしますけどね。

他にはシーンをASCIIで保存して、調べるとか。


どちらも面倒な事には違いがないので、調べるMELを組んでしまいます。


global proc tryGetAttrName(
    string $node,
    string $sea )
{
    string $attrs[] =`listAttr $node`;
    string $sAttrs[]=`listAttr -sn $node`;
    
    string $lowSea=tolower( $sea );
    string $lowAttr;
    print("\n--- "+$node+" ---------\n");
    int $i=0;
    for( $attr in $attrs )
    {
        $lowAttr=tolower( $attr );
        if( ""==$lowSea
         || `gmatch $lowAttr ("*"+$sea+"*")` )
        {
            print($attr+": "+$sAttrs[$i]+"\n");
            
        }
        
        $i++;
        
    }
    print("\n-----------------------\n");
    
}



ノード名とざっくりとしたアトリビュート名を渡せば、「ロング名」:「ショート名」がスクリプトエディタのログに表示されます。


たとえば

tryGetAttrName( "locator1","disp" );

とするとロングのアトリビュート名に"disp"が含まれるものが表示されます。


ほかには、

tryGetAttrName( "locator1","" );

みたいに調べたいアトリビュート名を""にすると全てのアトリビュート名が表示されます。

2016年12月18日日曜日

アウトライナーのノードに色を付ける

会社では最近までmaya2014を使用していたので気が付かなかったのですが、Attribute Editor の Display フレームに見慣れないアトリビュートが追加されていることに気が付きました。


Outliner Color で色を指定して、


Use Outliner Color のチェックを入れると・・・



Outliner 上のノードの色が変わります。
Shapeノードにも色が付けれるけれど、ふつう Outliner は Transformノードしか表示していないと思うので Shape の色を変えても、ほぼ意味なしですね。


Hidden In Outliner を使えばノード自体を消すこともできるみたいです。
Constrain とかを Outliner から消せるので便利かも。


Outliner の Display にも関連メニューが追加されていて、有効無効が切り替えられるようです。


ただ、この機能、アトリビュートエディタで編集すると maya の負荷によって色が変わったり変わらなかったりするみたいです。
設定しても、色が保存されなかったり。

なので、スクリプトで制御する方が安全。

設定するアトリビュートは、useOutlinerColor と outlinerColor ショートネームは uocol と oclr です。

global proc outlineColor()
{
    string $jnts[]=`ls -typ "joint"`;
    for( $jnt in $jnts )
    {
        setAttr ($jnt+".uocol") 1;
        setAttr ($jnt+".oclr") 0 1 1;
        
    }
    
    string $lcts[]=`ls -typ "locator"`;
    for( $lct in $lcts )
    {
        string $pLct[]=`listRelatives -p $lct`;
        setAttr ($pLct[0]+".uocol") 1;
        setAttr ($pLct[0]+".oclr") 1 1 0;
        
    }
    
}



transform ノードである joint は、リストして直接変えればよいですが、shape ノードである locator なんかは、親の transform を調べてソレを変更する必要があります。


2016年12月12日月曜日

Photoshopのjsxを更新するバッチ

Photoshopスクリプトを作成しているときバージョン管理を行いたい。
スクリプトを作る場合には当然欲しくなります。

でも Photoshopの Presets\Scripts を直接リポジトリに登録するとなると色々面倒。
とりあえず別のところをSVNへコミットしておいてバッチファイルでコピーするのが妥当かな?


まずは、コピーするとき.jsxファイルがバラバラになっていると Presets\Scripts のなかもグチャグチャになるので、スクリプトごとにフォルダへまとめてソレをコピーする感じにしようと思います。
このことを前提にバッチを組んでいるので要注意。

で、バッチファイル。
@title %~nx0
@prompt %~n0$G

:: コピーするフォルダ名
set SCRIPT=hoge

:: Adobe フォルダがあるか調べる
@set ADOBE_PATH=%ProgramFiles%\Adobe\
@if not exist "%ADOBE_PATH%" goto :errAdobe

:: Photoshop フォルダを探す
@set SRC_FOLDER=%~dp0%SCRIPT%
@for /f "delims=*" %%F in ('dir /b "%ADOBE_PATH%" ^| find "Photoshop"') do call :copyAction "%%F"
@goto :endProcess



::------------------------------------------------------------------------------
:copyAction
    @set DST_FOLDER=%ADOBE_PATH%%~1\Presets\scripts\%SCRIPT%\
    @if not exist "%DST_FOLDER%" md "%DST_FOLDER%"
    
    xcopy "%SRC_FOLDER%" "%DST_FOLDER%" /s /y
    @exit /b



:errAdobe
    @echo Adobe のフォルダが見つかりません
    @goto :endProcess



:endProcess
    @pause



単にコピーするだけでは芸がないので、どんなバージョンのPhotoshopにも対応してみました。
ポイントは3箇所。

13行目でdelimsを設定しないとスペースで分割されてしまうのでダミーの文字を指定して分割されないようにしています。
同じく13行目、セット内でdirをfindへパイプするために ^| とエスケープさせています。
20行目callで渡された値はスペースで分割されないようダブルクォーテーション付きで渡されているので%~を使ってダブルクォーテーションを省いています。

たぶんコレでいけるはず。

2016年12月7日水曜日

Photoshopのスクリプトからexeを実行したい

Photoshopの話しが続きますが・・・。

表題の通り、jsxからexeを実行したいのです。

ファイルオブジェクトにexecute()メソッドがあることはある。
ただし、引数を渡せないときた。
しかも、渡す引数は実行するたびに変わる可能性があるのです。


こんな時どうするか?
jsxからバッチファイルを作るしかないじゃないですか!


function createBatchFile( arg )
{
 const CR = String.fromCharCode(13);
 const BATCH_FILE = new File(Folder.temp+"/hogehoge.bat");
 
 var command;
 switch( arg )
 {
 case 0: command = "echo \"hoge\""; break;
 case 1: command = "echo \"hogehoge\""; break;
 }
 
 BATCH_FILE.open("w");
 // 書き込み開始
 BATCH_FILE.write("@echo off"+CR);
 BATCH_FILE.write(command+CR);
 BATCH_FILE.write("pause"+CR);
 // 書き込み終了
 BATCH_FILE.close();
 
 // バッチ実行
 BATCH_FILE.execute();
 
}

createBatchFile( 0 );
createBatchFile( 1 );


3行目のfromCharCode(13)っていうのは改行コード。
4行目のFolder.tempでPhotoshopが使用するテンポラリフォルダを取得できるので、そこへ間借りさせてもらい"hogehoge.bat"を指定しています。
7行目のswitchで記入する文字列を分岐。この部分で実際に実行するexeを指定するわけです。
13行目でファイルを開き15行目からバッチファイルに記述です。

最後、22行目でバッチの実行。

すると2回関数を呼んでいるので、DOS窓が2つ出てくるはず。


execute自体は実行終了を待ってくれないので連続実行は危険極まりない。

2016年12月5日月曜日

Photoshopで表示されているレイヤーセット名を取得する

テクスチャとか作っているとレイヤーセットが増えてきますよね~。
カラーバリエーションとか模様違いとか。

出力するときに「ファイル名+レイヤーセット名」みたいにすると便利そうです。
今画面に表示されているレイヤーセットの名称を調べようとした時、どうするのか?


単純にレイヤーセットをリスト化して、最初に出てきた可視レイヤーセット名を取得すれば良いような気がします。

getLayerSetName = function()
{
    var lsObj = activeDocument.layerSets;
    
    var result = "";
    for( i=0; i<lsObj.length; i++ ){
        if( lsObj[i].visible ) {
            result = lsObj[i].name;
            break;
            
        }
        
    }
    
    return result;
    
}


これだけだったら話は早いのですが、斜め上の行動をする人が居るのが世の常。


こんな感じでレイヤーモードと透明度で色味調整しているファイルがあるかもしれない!
ま、スクリプト側からは注意喚起することくらいできないんですけど・・・。
目的はレイヤーセット名の取得なので無視します。


ちなみに、レイヤーの取得方法は3種類。
activeDocument.artLayers レイヤーのみ
activeDocument.layerSets レイヤーセットのみ
activeDocument.layers    レイヤーとレイヤーセット

このうちactiveDocument.layersから各レイヤーのblendMode,fillOpacity,opacity,visibleなんかの状況から分岐処理させるとかかな。


レイヤーカンプ使った出力スクリプトが公式で有るからソレ使えよみたいな感じですが、
テクスチャ作成途中の段階でレイヤーカンプ作るとレイヤーカンプは壊れ易いので無理。

そもそも3Dデザイナーのフォトショッパーってレイヤーカンプの存在知らなかったりするし。

2016年12月2日金曜日

Photoshopにスクリプトを登録してみる覚書

Photoshop用の自作スクリプトをメインメニューのファイル(F) > スクリプト(R)
の欄に表示させるには、Photoshopのインストール先の Presets\Scripts へ.jsxファイル
をコピーします。

たとえば hogehoge.jsx というのを作成しコピーした場合

ファイル名で登録されました。

よくあるパターンとして、メインになる処理を hogeCore.jsx にまとめて、引数だけ変えた
呼び出し用スクリプト hogeA.jsx と hogeB.jsx を作って登録したいと思った時、普通に
Presets\Scripts へコピーすると・・・



3つとも表示されてしまいます。

hogeCore はメニューに出したくない場合はどうすればよいか?


Presets\Scripts の中を見てみると、~Scripts Only みたいなフォルダが見つかります。
試しに"hoge Scripts Only"とフォルダを作成し、そこへ hogeCore.jsx を移動します。
すると、



hogeCore.jsx がメニューに表示されなくなりました。



次に、呼び出しファイルから処理ファイルを呼び出すスクリプトの書き方。

function main()
{
    const SELF = File( $.fileName );
    
    $.evalFile( SELF.path+"/hoge Scripts Only/hogeCore.jsx" );
    
    var ret = hogeCore();
    alert ( ret );
    
}

main();


function hogeCore()
{
    alert ("hogehoge");
    return 0;
    
}



$.fileName で自分のファイル名をフルパスで取れます。
$.evalFile() は、指定されたファイルを読み込む処理。
ここで hogeA.jsxと同じ階層の hoge Scripts Only フォルダ内に在る(はずの)hogeCore.jsx
を読み込んでいます。

こうすることで hogeCore.jsx の hogeCore() が実行可能になります。


メニューから hogeA を実行すると、

まず hogeCore.jsx のアラートが表示され、


hogeCore の返り値がアラートされます。