/*
    exportLayersAsFile.jsx
    
    レイヤ状態を個別のファイルとして保存する。
    オプションでグループフォルダの作成を行う
    
手順としては、
	MAPビルドを行う
	ネームスペースをコレクションで作成する
	システムフォルダ以下のグループデータを順次表示するXPSを生成する。
	ビルドする
	フレームをレイヤに統合する
	レイヤを1点づつファイルにとって保存する。
	オリジナルドキュメントを保存せずに閉じる
というのが望ましいアプローチだけど、今回はやらない
コーディングに時間がかかる上に　動作速度が遅いのも保障付
マップビルドの省略プロセスでそのまま書き出しをかける。
-----------
レイヤ名からファイル名を作成するときにファイルシステムで禁止されている文字をトラップする
アニメビルド以外の最終操作は、ファイルの複製をとって書き出しを行う仕様に変更
20111203

オプションとして出力前にコマンド実行を可能にする。
スムージング等に必要なコマンドをoptCodeに置く（アクション実行　又はフィルタ実行コードなど）
不要な場合は　false を置いといてください
コードは保存の直前に実行されます。
20120416

CS6でアニメーションが初期化されていない状態が発生したのでその対応（エラー停止の回避）コードを算定的に追加
20120617
*/
var optCode=false;
/*
var optCode="";
// ======================================================= OLM Smoother
optCode+="var idFltr = charIDToTypeID( \"Fltr\" );";
optCode+="var desc4 = new ActionDescriptor();";
optCode+="var idUsng = charIDToTypeID( \"Usng\" );";
optCode+="desc4.putString( idUsng, \"OLM Smoother...\" );";
optCode+="executeAction( idFltr, desc4 );";

// ========================================アクション実行
var aSetName="animationTools";
var actionName="Smoother";

optCode+="var idPly = charIDToTypeID( \"Ply \" );";
optCode+="    var descAct = new ActionDescriptor();";
optCode+="    var idnull = charIDToTypeID( \"null\" );";
optCode+="        var refAct = new ActionReference();";
optCode+="        var idActn = charIDToTypeID( \"Actn\" );";
optCode+="        refAct.putName( idActn, actionName );";
optCode+="       var idASet = charIDToTypeID( \"ASet\" );";
optCode+="        refAct.putName( idASet, aSetName );";
optCode+="    descAct.putReference( idnull, refAct );";
optCode+="executeAction( idPly, descAct, DialogModes.NO );";
*/
// enable double clicking from the Macintosh Finder or the Windows Explorer
#target photoshop
// in case we double clicked the file
	app.bringToFront();
//Photoshop用ライブラリ読み込み

if($.fileName){
//	CS3以降は　$.fileNameオブジェクトがあるのでロケーションフリーにできる
	var nasLibFolderPath = new File($.fileName).parent.parent.path +"/lib/";
}else{
//	$.fileName オブジェクトがない場合はインストールパスをきめうちする
	var nasLibFolderPath = Folder.userData.fullName + "/"+ localize("$$$/nas/lib=nas/lib/");
}
var includeLibs=[nasLibFolderPath+"config.js"];//読み込みライブラリを格納する配列

if(! app.nas){
//iclude nasライブラリに必要な基礎オブジェクトを作成する
	var nas = new Object();
		nas.Version=new Object();
		nas.isAdobe=true;
		nas.axe=new Object();
		nas.baseLocation=new Folder(Folder.userData.fullName+ "/nas");
//	ライブラリのロード　CS2-5用
//==================== ライブラリを登録して事前に読み込む
/*
	includeLibs配列に登録されたファイルを順次読み込む。
	登録はパスで行う。(Fileオブジェクトではない)
	$.evalFile メソッドが存在する場合はそれを使用するがCS2以前の環境ではglobal の eval関数で読み込む

＝＝＝　ライブラリリスト（以下は読み込み順位に一定の依存性があるので注意）
　config.js"		一般設定ファイル（デフォルト値書込）このルーチン外では参照不能
  nas_common.js		AE・HTML共用一般アニメライブラリ
  nas_GUIlib.js		Adobe環境共用GUIライブラリ
  nas_psAxeLib.js	PS用環境ライブラリ
  nas_prefarenceLib.js	Adobe環境共用データ保存ライブラリ

  nasXpsStore.js	PSほかAdobe汎用XpsStoreライブラリ(AE用は特殊)
  xpsio.js		汎用Xpsライブラリ
  mapio.js		汎用Mapライブラリ
  lib_STS.js		Adobe環境共用STSライブラリ
  dataio.js		Xpsオブジェクト入出力ライブラリ（コンバータ部）
  fakeAE.js		中間環境ライブラリ
  io.js			りまぴん入出力ライブラリ
  psAnimationFrameClass.js	PS用フレームアニメーション操作ライブラリ
  xpsQueue.js		PS用Xps-FrameAnimation連携ライブラリ
*/
includeLibs=[
	nasLibFolderPath+"config.js",
	nasLibFolderPath+"nas_common.js",
	nasLibFolderPath+"nas_GUIlib.js",
	nasLibFolderPath+"nas_psAxeLib.js",
	nasLibFolderPath+"nas_prefarenceLib.js"
];
//=====================================　Application Objectに参照をつける
	app.nas=nas;
	bootFlag=true;
}else{
	//alert("object nas exists")
	nas=app.nas;
	bootFlag=false;
};

/*	ライブラリ読み込み
ここで必要なライブラリをリストに加えてから読み込みを行う
*/
includeLibs.push(nasLibFolderPath+"fakeAE.js");
includeLibs.push(nasLibFolderPath+"nas.XpsStore.js");
includeLibs.push(nasLibFolderPath+"xpsio.js");
includeLibs.push(nasLibFolderPath+"mapio.js");
includeLibs.push(nasLibFolderPath+"lib_STS.js");
includeLibs.push(nasLibFolderPath+"dataio.js");
includeLibs.push(nasLibFolderPath+"io.js");
includeLibs.push(nasLibFolderPath+"psAnimationFrameClass.js");
includeLibs.push(nasLibFolderPath+"xpsQueue.js");
	if(false){
	}
for(prop in includeLibs){
	var myScriptFileName=includeLibs[prop];
	if($.evalFile){
	//$.evalFile ファンクションがあれば実行する
		$.evalFile(myScriptFileName);
	}else{
	//$.evalFile が存在しないバージョンではevalにファイルを渡す
		var scriptFile = new File(myScriptFileName);
		if(scriptFile.exists){
			scriptFile.open();
			var myContent=scriptFile.read()
			scriptFile.close();
			eval(myContent);
		}
	}
}
//=====================================保存してあるカスタマイズ情報を取得
if(bootFlag){nas.readPrefarence();nas.workTitles.select();}
//=====================================
//+++++++++++++++++++++++++++++++++ここまで共用
var noSave=false;
//-----------------------操作開始時に未保存の場合警告
if((app.documents.length)&&(! app.activeDocument.saved)){
    noSave=true;
    noSave=confirm("ドキュメントは保存されていません。保存しますか？");
//一度も保存されていないファイルに名前をつけて保存するルーチンが必要
//または明示的に保存されたファイルのみを扱うようにトラップする
    if(noSave){app.activeDocument.save();noSave=false;}
}
//-----------------------保存しなくても操作は続行
if((! noSave)&&(app.documents.length)&&(app.activeDocument.layers.length)){
var exportFiles=new Object;
 exportFiles.targetDoc=app.activeDocument;
try{
 exportFiles.currentTargetFolder=app.activeDocument.fullName.parent;
    }catch(eRR){
 exportFiles.currentTargetFolder=Folder.current;
    }
//操作用の一時ドキュメントを作っておく
 exportFiles.tempDoc=app.activeDocument.duplicate("__exportTempDoc__");//ここでアクティブドキュメントが切り替わる
 if(nas.axeAFC.checkAnimationMode()!="frameAnimation"){
	executeAction( stringIDToTypeID( "makeFrameAnimation" ), undefined, DialogModes.NO );
 };
 exportFiles.mkFolder=true;
 exportFiles.withRegister=true;
 exportFiles.byAFC=false;
 exportFiles.opForms=[".png",".psd",".tiff",".tga",".jpg"];
 exportFiles.opForm=0;
 exportFiles.guideLayers=[];
 exportFiles.guideLayersA=[];
 exportFiles.outputList=[];
 exportFiles.outputListA=[];
 exportFiles.outputListView=[];

exportFiles.isMenber=function(myObject){
    //引数判定してメンバ条件を判定
	if(( myObject.typename=="ArtLayer")&&
	    ((myObject.kind==LayerKind.NORMAL)||(myObject.kind==LayerKind.SMARTOBJECT))
    ){return true};
    return false;
}
exportFiles.refresh=function(){
//リセット時の再取得も含むので配列を初期化
	 this.guideLayers.length=0;this.outputList.length=0;
 for (var ix=0;ix<this.tempDoc.layers.length;ix++){
	if(this.tempDoc.layers[ix].name.match(/(frames?|peg|memo|system)/i)){
	 this.guideLayers.push(this.tempDoc.layers[ix]);
	 this.guideLayersA.push(this.targetDoc.layers[ix]);
	 continue;
	};//フレームレイヤ・レイヤセットをスキップ
//================ArtLayer　でノーマルとスマートオブジェクトを選択
	if(this.isMenber(this.tempDoc.layers[ix])){this.outputList.push(this.tempDoc.layers[ix]);this.outputListA.push(this.targetDoc.layers[ix]);continue;}
//=================レイヤセットでかつ、配下にレイヤを含んでいる場合（１段のみ掘下げ レイヤセットもメンバーにする）
	if((true)&&(this.tempDoc.layers[ix] instanceof LayerSet)&&(this.tempDoc.layers[ix].layers.length)){
		for (var lx=0;lx<this.tempDoc.layers[ix].layers.length;lx++){
            this.outputList.push(this.tempDoc.layers[ix].layers[lx]);
            this.outputListA.push(this.targetDoc.layers[ix].layers[lx]);
            continue;
		}
	}
 };//メンバ収集終了
//リストに登録
//	this.w.fileList.items
}
exportFiles.viewUpdate=function(){
    this.outputListView.length=0;
    if(this.byAFC){
        var myFrameCount=nas.axeAFC.countFrames();
        for(var fct=0;fct<myFrameCount;fct++){
//=============プレフィクスは、ターゲットから取得する
            this.outputListView.push(this.targetDoc.name.replace(/\.[^.]*$/,"")+nas.Zf(fct+1,3));
        }
    }else{
      for(fl in this.outputList){
	    if((! this.mkFolder)||(this.outputList[fl].parent instanceof Document)){
		this.outputListView.push(this.outputList[fl].name.replace(/[\\\/\:\?\*\"\>\<\|]/g,"_"));
	    }else{
		this.outputListView.push(("[ "+this.outputList[fl].parent.name +" ] "+this.outputList[fl].name).replace(/[\\\/\:\?\*\"\>\<\|]/g,"_"));
	    }
      }
    }
}
//インデックスで与えられたレイヤを残して他を非表示にする。
//オプションでフレームを非表示
//アニメフレームビルドとセット対象が異なるので対応
 exportFiles.set=function(index){
	 for(var ix=0;ix<this.guideLayers.length;ix++){
	  this.guideLayers[ix].visible=(this.withRegister==false)?false:true;
	} 
	for(var ix=0;ix<this.outputList.length;ix++){
	 this.outputList[ix].visible=(index==ix)?true:false;
	}
 }
//アニメフレームビルド用のターゲット操作
 exportFiles.setA=function(index){
	 for(var ix=0;ix<this.guideLayers.length;ix++){
	  this.guideLayersA[ix].visible=(this.withRegister==false)?false:true;
	} 
	for(var ix=0;ix<this.outputList.length;ix++){
	 this.outputListA[ix].visible=(index==ix)?true:false;
	}
 }

	exportFiles.refresh();
	exportFiles.viewUpdate();

exportFiles.export=function(){
//
//
        var mySaveDocument=null;
        var myTargetFolder=this.currentTargetFolder;
        var mySaveOptions=null;
        switch(this.opForms[this.opForm]){
            case ".tiff":;
                mySaveOptions=new TiffSaveOptions;
            break;
            case ".tga":;
                mySaveOptions=new TargaSaveOptions;
                //mySaveOptions.
            break;
            case ".png":;
                mySaveOptions=new PNGSaveOptions;
		if(! isNaN(mySaveOptions.compression)){mySaveOptions.compression=1;}
            break;
            case ".jpg":;
                mySaveOptions=new JPEGSaveOptions;
            break;
            default:
                mySaveOptions=new PhotoshopSaveOptions;
        }
//=================================== 実際の操作 ======================================//
    var myTempDoc=this.tempDoc;//対象ドキュメントをターゲット本体に設定
	app.activeDocument=myTempDoc;
         if(this.byAFC){
//     var myFrameCount=nas.axeAFC.countFrames();
     var myFrameCount=this.outputList.length;
     for(var fidx=0;fidx<myFrameCount;fidx++){
       //アニメフレームを出力 現在のファイル名から拡張子をのぞいたものをプレフィックスにして指定フォルダ直下に保存
                 nas.axeAFC.selectFrame(fidx+1);//表示セット
                 var storeName=this.targetDoc.name.replace(/\.[^.]*$/,"")+nas.Zf(fidx+1,3)+this.opForms[this.opForm]
                 mySaveDocument=myTempDoc.duplicate (storeName, true)
         if(mySaveDocument){
             app.activeDocument=mySaveDocument;nas.axeAFC.initFrames();//アニメフレームを初期化
             mySaveDocument.layers[0].visible=true;//表示が消えるので復帰しておく             
             var mySaveFile=new File(myTargetFolder.fullName+"/"+mySaveDocument.name)
         //可能なら保存する
         try{
             mySaveDocument.saveAs(mySaveFile,mySaveOptions,true);
             }catch(eRR){alert(eRR)}
             mySaveDocument.close(SaveOptions.DONOTSAVECHANGES);//閉じる
             app.activeDocument =myTempDoc;
       }
   }
         }else{
    for(var fidx=0;fidx<this.outputList.length;fidx++){
       //レイヤをたどって指定に従ってガイドレイヤのあるなしを選択して出力
                if(this.mkFolder)
                {
                   var folderName=this.outputList[fidx].parent.name.replace(/[\\\/\:\?\*\"\>\<\|]/g,"_");
                   myTargetFolder=new Folder(this.currentTargetFolder.fullName+"/"+folderName);
                };
                if(! myTargetFolder.exists){myTargetFolder.create();}
                 this.set(fidx);//表示セット
                   var fileName=this.outputList[fidx].name.replace(/[\\\/\:\?\*\"\>\<\|]/g,"_");
                mySaveDocument=myTempDoc.duplicate (fileName+this.opForms[this.opForm], true);
         if(mySaveDocument){
/*
	単独ファイルとして保存するためにレイヤ統合を行う。
元のドキュメントにアニメフレームがあった場合（かなりの確率で有る）
psdドキュメントに存在しないレイヤを指すフレームやアニメサムネールのキャッシュがつくので何かと不都合である。
アニメフレームを削除するために初期化を行う。
単純な初期化では第一フレームの表状態が再生されるため、当該レイヤが非表示のまま保存される場合があるので再表示を行う。
*/
             app.activeDocument=mySaveDocument;nas.axeAFC.initFrames();//アニメフレームを初期化
             mySaveDocument.layers[0].visible=true;//表示が消えるので復帰しておく
	if(optCode){eval(optCode);};
             var mySaveFile=new File(myTargetFolder.fullName+"/"+mySaveDocument.name);
         //可能なら保存する
         try{
             mySaveDocument.saveAs(mySaveFile,mySaveOptions,true);
             }catch(eRR){alert(eRR)}
             mySaveDocument.close(SaveOptions.DONOTSAVECHANGES);//閉じる
             app.activeDocument =myTempDoc;
         }
    }
         }
//             myTempDoc.close(SaveOptions.DONOTSAVECHANGES);//一時ファイルなので保存せずに閉じる
/*
    テンポラリのとり方は一考
    編集後のデータ構造を移植可能なら実装することにして宿題 2011/09/28
    */
}
//==============================================UI
exportFiles.w=nas.GUI.newWindow("dialog","レイヤをファイルとして保存",6,12);

exportFiles.w.msgBox=nas.GUI.addStaticText(exportFiles.w,"レイヤをファイルとして保存します。保存先を指定してください。",0,0,6,1);


exportFiles.w.folderTargetName=nas.GUI.addEditText(exportFiles.w,exportFiles.currentTargetFolder.fsName,0,1,5,1);
exportFiles.w.chgFolder=nas.GUI.addButton(exportFiles.w,"変更",5,1,1,1);

exportFiles.w.fileList=nas.GUI.addListBoxO(exportFiles.w,exportFiles.outputListView,null,0,2,4,7,{multiselect:true});
//チェックコントロール
exportFiles.w.mkSF=nas.GUI.addCheckBox(exportFiles.w,"サブフォルダを作る",0,9,4,1);
	exportFiles.w.mkSF.value=exportFiles.mkFolder;
exportFiles.w.regOpt=nas.GUI.addCheckBox(exportFiles.w,"タップとフレームを表示する",0,10,4,1);
	exportFiles.w.regOpt.value=exportFiles.withRegister;
exportFiles.w.afcOpt=nas.GUI.addCheckBox(exportFiles.w,"アニメフレームを出力する",0,11,4,1);
	exportFiles.w.afcOpt.value=exportFiles.byAFC;
//ボタンコントロール
exportFiles.w.ffLb=nas.GUI.addStaticText(exportFiles.w,"file format:",4,2,2,1);
exportFiles.w.ffBt=nas.GUI.addDropDownList(exportFiles.w,exportFiles.opForms,exportFiles.opForm,4,3,2,1);
//exportFiles.w.FlBt=nas.GUI.addButton(exportFiles.w,"addFile",4,3,2,1);
exportFiles.w.rmBt=nas.GUI.addButton(exportFiles.w,"remove",4,4,2,1);
exportFiles.w.rstBt=nas.GUI.addButton(exportFiles.w,"reset",4,5,2,1);


exportFiles.w.bdBt=nas.GUI.addButton(exportFiles.w,"makeAnimation",4,9,2,1);
exportFiles.w.okBt=nas.GUI.addButton(exportFiles.w,"OK",4,10,2,1);
exportFiles.w.cnBt=nas.GUI.addButton(exportFiles.w,"cancel",4,11,2,1);
//==================================コントロールメソッド
//保存フォルダ変更
exportFiles.w.chgFolder.onClick=function(){
    var newFolder=exportFiles.currentTargetFolder.selectDlg("select Save folder");
    if(newFolder){
        exportFiles.currentTargetFolder=newFolder;
        this.parent.folderTargetName.text=exportFiles.currentTargetFolder.fsName;
    }
}
//リスト編集（削除）
exportFiles.w.rmBt.onClick=function(){
    //選択されたIDのレイヤを削除してアップデート
    if(this.parent.fileList.selection){
var removeItemList=new Array();
for(ecItem in this.parent.fileList.selection){removeItemList.push(this.parent.fileList.selection[ecItem].index);}
removeItemList.sort(function(a,b){return(b-a);});
    for(var itmId=0;itmId<removeItemList.length;itmId++){
        exportFiles.outputList.splice(removeItemList[itmId],1);
    }
	exportFiles.viewUpdate();
    this.parent.fileList.update();
    }
 }
//フォーマット選択
exportFiles.w.ffBt.onChange=function(){
    exportFiles.opForm=this.selection.index;
}
//リストをリセット
exportFiles.w.rstBt.onClick=function(){
	exportFiles.refresh();
	exportFiles.viewUpdate();
    this.parent.fileList.update();
}
//パラメータ変更
exportFiles.w.fileList.update=function(){
    this.removeAll();
    for(var lid=0;lid<exportFiles.outputListView.length;lid++){
        this.add("item",exportFiles.outputListView[lid]);
          //("text",exportFiles.outputView[lid]);
    }
}
exportFiles.w.mkSF.onClick=function(){
    exportFiles.mkFolder=this.value;
      exportFiles.viewUpdate();
      this.parent.fileList.update();//クリアして
      
}
//タップ出力オプション
exportFiles.w.regOpt.onClick=function(){
    exportFiles.withRegister=this.value;
}
//アニメフレーム出力オプション
exportFiles.w.afcOpt.onClick=function(){
      exportFiles.byAFC=this.value;
      if(this.value){
        this.parent.mkSF.enabled=false;
        this.parent.regOpt.enabled=false;
        this.parent.bdBt.enabled=false;
      }else{
        this.parent.mkSF.enabled=true;
        this.parent.regOpt.enabled=true;
        this.parent.bdBt.enabled=true;
      }
      exportFiles.viewUpdate();
      this.parent.fileList.update();//クリアして
}
//アニメフレームをビルドする
exportFiles.w.bdBt.onClick=function(){
　app.activeDocument=exportFiles.targetDoc;
 var UndoString="レイヤからアニメフレーム";
 var myExecute="nas.axeAFC.initFrames();for(var fix=0;fix<this.parent.fileList.items.length;fix++){if(fix>0){nas.axeAFC.dupulicateFrame();}exportFiles.setA(fix);};nas.axeAFC.reverseAnimationFrames();";

 if(app.activeDocument.suspendHistory){
     app.activeDocument.suspendHistory(UndoString,myExecute);
 }else{
     evel(myExecute);
 }

    exportFiles.tempDoc.close(SaveOptions.DONOTSAVECHANGES);
    this.parent.close();
}

exportFiles.w.okBt.onClick=function(){
 var UndoString="output";
 if(app.activeDocument.suspendHistory){
     app.activeDocument.suspendHistory(UndoString, "exportFiles.export();");
          // =================== UNDOバッファを使用して復帰
var id8 = charIDToTypeID( "slct" );
    var desc5 = new ActionDescriptor();
    var id9 = charIDToTypeID( "null" );
        var ref2 = new ActionReference();
        var id10 = charIDToTypeID( "HstS" );
        var id11 = charIDToTypeID( "Ordn" );
        var id12 = charIDToTypeID( "Prvs" );
        ref2.putEnumerated( id10, id11, id12 );
    desc5.putReference( id9, ref2 );
executeAction( id8, desc5, DialogModes.NO );
 }else{
     evel("exportFiles.export();");
 }

    exportFiles.tempDoc.close(SaveOptions.DONOTSAVECHANGES);
    this.parent.close();
}
//キャンセルして終了
exportFiles.w.cnBt.onClick=function(){
	exportFiles.tempDoc.close(SaveOptions.DONOTSAVECHANGES);
	this.parent.close();
}
//

exportFiles.w.show();

}
