プロフィール

Author:はるかわ しおん
なにか、新しいものを。
そして、楽しいものを。

FC2カウンター


上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
  • Illustrator のファイル二つのサブレイヤーをすべて自動合成するスクリプト

イラレ (Illustrator CS3) でレイヤー合成をしなければならなくなり (イラレ知らないのに)、急遽イラレの JavaScript を書きました。
急遽といっても、ほとんど情報がなく、Adobe ExtendScript Toolkit 2 の Adobe Illustrator CS3 Type Library をにらめっこしつつ、推測とトライ&エラーで10時間ほどかかって書き上がりました。

いくつかレイヤーを扱うスクリプトを書いている方々のソースを見てみたのですが、多少参考にはなったものの、ソースがとにかく読みづらい! ただでさえ Type Library の使い方がよくわからないのに、しかも実装されているロジックの意図がわからない (コメントなしなので) ので、非常に困ります。
参考にしたスクリプト作者様を悪く言う意図はないのですが、参考にはなったものの、かなりはまってしまったわけでもありまして。微妙な気分です。

思うに、イラレを使う方々 (デザイナー) は、私のような人々 (システムエンジニア) と違うんですよね。
ソースの可読性を考慮しているか否かが違うのもそうなのですが、なによりスクリプトの仕様がかなり違う。
Web で公開されているイラレのスクリプトをいくつか試しましたが、たとえば

・スクリプトの動作を決めるためのテキストをレイヤーとして表示させ、そこでテキストを編集させる
  →操作対象ファイルに関係ない情報ができてしまうことになるので、私なら INI ファイルとか使う

・あらかじめ対象オブジェクトが選択されている状態 or 対象ファイルが開いている状態でスクリプトを実行させる
  →もちろん小さい機能のスクリプトならその方が便利だと思うが、そういうスクリプトが多いというのは、SE とデザイナーの定型作業等々に対する意識の違いなのかなーと思う

・・・まぁいいや。書くのがめんどくさくなってきました。


本題です。
誰かの役に立つかもしれないので、上げておきます。
.jsx はここのブログにアップできないので、.js です。
検索に引っかかるように、ソースもばーっと載せておきます。

コメント等ありましたら、ぜひ。
ただ、当方イラレはまず使わないので、ソースの改良等はしないと思います。
このスクリプトで当方のやりたいことは実現できていますが、エラー処理などは一切省いてあります。何か不具合があっても無保証ですので、そのあたりはご了解ください。


SubLayerComposite.jsx


/*
二つの .ai の各サブレイヤーを合成する。
ただし、エラー処理とかはぜんぜんしてない。

a.ai (合成される側)
Layer-1 // ルートレイヤー (勝手に作った用語)
SubLayer-1a // サブレイヤー
SubLayer-1b
Layer-2
SubLayer-2a

b.ai (パーツ側)
Layer-A
SubLayer-Aa
SubLayer-Ab
Layer-B
SubLayer-Ba

↓実行後

a.ai
Layer-2 SubLayer-2a : Layer-B SubLayer-Ba
Layer-2 SubLayer-2a : Layer-A SubLayer-Ab
Layer-2 SubLayer-2a : Layer-A SubLayer-Aa
Layer-1 SubLayer-1b : Layer-B SubLayer-Ba
Layer-1 SubLayer-1b : Layer-A SubLayer-Ab
Layer-1 SubLayer-1b : Layer-A SubLayer-Aa
Layer-1 SubLayer-1a : Layer-B SubLayer-Ba
Layer-1 SubLayer-1a : Layer-A SubLayer-Ab
Layer-1 SubLayer-1a : Layer-A SubLayer-Aa
Layer-1
SubLayer-1a
SubLayer-1b
Layer-2
SubLayer-2a

*/


// 対象ファイルの指定
var docBase = docOpenDialog("各レイヤーごとに合成される側のIllustratorファイルを指定してください");
var docParts = docOpenDialog("パーツ側のIllustratorファイルを指定してください");

alert("合成処理を開始します。");


// 新規追加したレイヤー (レイヤー合成処理を行ったレイヤー) の数
var layerCount = 0;


// 合成される側のルートレイヤーの数だけループ
for (var i=0; i<docBase.layers.length; i++) {
/* alert("i= " + i + ", docBase.layers.length= " + docBase.layers.length + ", layerCount= " + layerCount); // デバッグ用 */

// 合成される側のルートレイヤーを順番に取得していく
var baseRootLayer = docBase.layers[i];


// 合成される側のルートレイヤーのサブレイヤーの数だけループ
for (var j=0; j<baseRootLayer.layers.length; j++) {
/* alert("j= " + j + ", baseRootLayer.layers.length= " + baseRootLayer.layers.length); // デバッグ用 */

// 合成される側のサブレイヤーを順番に取得していく
var baseSubLayer = baseRootLayer.layers[j];


// パーツ側のルートレイヤーの数だけループ
for (var k=0; k<docParts.layers.length; k++) {
/* alert("k= " + k + ", docParts.layers.length= " + docParts.layers.length); // デバッグ用 */

// パーツ側のルートレイヤーを順番に取得していく
var partsRootLayer = docParts.layers[k];


// パーツ側のルートレイヤーのサブレイヤーの数だけループ
for (var l=0; l<partsRootLayer.layers.length; l++) {
/* alert("l= " + l + ", partsRootLayer.layers.length= " + partsRootLayer.layers.length); // デバッグ用 */

// パーツ側のサブレイヤーを順番に取得していく
var partsSubLayer = partsRootLayer.layers[l];


// 合成される側に新規レイヤーを作成
newLayer = docBase.layers.add(); // レイヤーは、一番上にできる
layerCount++; // 一番上位のループに影響があるので、増えたレイヤー数を数えておく


// 合成される側のサブレイヤーをコピー (≒サブレイヤー配下の PageItem をすべて複製)
for (var m=0; m<baseSubLayer.pageItems.length; m++) {
/* alert("m= " + m + ", baseSubLayer.pageItems.length=" + baseSubLayer.pageItems.length); // デバッグ用 */
tmpPageItem = baseSubLayer.pageItems[m].duplicate(); // PageItem#duplicate()
tmpPageItem.moveToEnd(newLayer); // 複製した PageItem を新規レイヤーの末尾に移動
}


// パーツ側のサブレイヤーをコピー (≒サブレイヤー配下の PageItem をすべて複製)
for (var n=0; n<partsSubLayer.pageItems.length; n++) {
/* alert("n= " + n + ", partsSubLayer.pageItems.length= " + partsSubLayer.pageItems.length); // デバッグ用 */
tmpPageItem = partsSubLayer.pageItems[n].duplicate(); // PageItem#duplicate()
tmpPageItem.moveToEnd(newLayer); // 複製した PageItem を新規レイヤーの末尾に移動
}


// 新規レイヤー (レイヤー合成処理を行ったレイヤー) の名前を変更
newLayer.name = baseRootLayer.name + " " + baseSubLayer.name + " : " + partsRootLayer.name + " " + partsSubLayer.name;


}

}

}

i = i + layerCount; // レイヤーが次々に増えていくため、docBase.layers.length の値は次々に変わっていく (つまり、i は 追加済みレイヤー数+1 だけ増やさなければならない)

}


docBase.activate();

alert("合成処理が完了しました。間違いがないか確認してください。");


// ダイアログを表示し、指定ファイルをオープンし、Document を返却する。
function docOpenDialog(msg) {

filename = File.openDialog(msg);

if (filename) {
fileObj = new File(filename);
return app.open(fileObj);
}

}




コメント

> ・あらかじめ対象オブジェクトが選択されている状態 or 対象ファイルが開いている状態でスクリプトを実行させる

イラストレータのメニュー([ファイル]-[スクリプト])から実行させるためですね。
これはデザイナーだから、というんじゃなくて、操作の一部を自動化する目的です。
ファイルを一から作成する、もしくはテンプレートを利用して作成するといった自動化の場合はこんな事はしません。(もっともそれ以前に、そのような場合はJavaScriptは使わずVBScriptもしくはVB、VC等を使うんでしょうが)。

コメントの投稿

   管理者にだけ表示を許可する
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。