| Home |
2008.11.19
Illustrator のファイル二つのサブレイヤーをすべて自動合成するスクリプト
イラレ (Illustrator CS3) でレイヤー合成をしなければならなくなり (イラレ知らないのに)、急遽イラレの JavaScript を書きました。
急遽といっても、ほとんど情報がなく、Adobe ExtendScript Toolkit 2 の Adobe Illustrator CS3 Type Library をにらめっこしつつ、推測とトライ&エラーで10時間ほどかかって書き上がりました。
いくつかレイヤーを扱うスクリプトを書いている方々のソースを見てみたのですが、多少参考にはなったものの、ソースがとにかく読みづらい! ただでさえ Type Library の使い方がよくわからないのに、しかも実装されているロジックの意図がわからない (コメントなしなので) ので、非常に困ります。
参考にしたスクリプト作者様を悪く言う意図はないのですが、参考にはなったものの、かなりはまってしまったわけでもありまして。微妙な気分です。
思うに、イラレを使う方々 (デザイナー) は、私のような人々 (システムエンジニア) と違うんですよね。
ソースの可読性を考慮しているか否かが違うのもそうなのですが、なによりスクリプトの仕様がかなり違う。
Web で公開されているイラレのスクリプトをいくつか試しましたが、たとえば
・スクリプトの動作を決めるためのテキストをレイヤーとして表示させ、そこでテキストを編集させる
→操作対象ファイルに関係ない情報ができてしまうことになるので、私なら INI ファイルとか使う
・あらかじめ対象オブジェクトが選択されている状態 or 対象ファイルが開いている状態でスクリプトを実行させる
→もちろん小さい機能のスクリプトならその方が便利だと思うが、そういうスクリプトが多いというのは、SE とデザイナーの定型作業等々に対する意識の違いなのかなーと思う
・・・まぁいいや。書くのがめんどくさくなってきました。
本題です。
誰かの役に立つかもしれないので、上げておきます。
.jsx はここのブログにアップできないので、.js です。
検索に引っかかるように、ソースもばーっと載せておきます。
コメント等ありましたら、ぜひ。
ただ、当方イラレはまず使わないので、ソースの改良等はしないと思います。
このスクリプトで当方のやりたいことは実現できていますが、エラー処理などは一切省いてあります。何か不具合があっても無保証ですので、そのあたりはご了解ください。
▼SubLayerComposite.jsx
急遽といっても、ほとんど情報がなく、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);
}
}
| Home |


