プロフィール

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

FC2カウンター


上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
  • Illustrator の ActionIsRunning がおかしい

Illustrator CS3 の VBSスクリプトからアクション (実行時間 5秒くらいのもの) を実行しています。
しかし、どうしても ActionIsRunning が正しく動作しているようには見えません。

リファレンスには

appRef.DoScript "Opacity 60 (selection)", "Default Actions"
WHILE(appRef.ActionIsRunning)
WScript.sleep 1000
WEND

などとしてループして待て的なことが書いてありますが、いやいや、アクション実行中なのに WEND の先に行ってます!!!

すでに徹夜で何時間もはまっており、条件文のミスといった基本的なことではないです。
仕方なく、Excel 2000 を入れて VBE からデバッグしながらやっています。






今回の対策ですが、非常に情けないことに

WScript.sleep 30000 'app.ActionIsRunning は当てにならないので、十分な時間を待っておく
While (app.ActionIsRunning)
WScript.sleep 1000
Wend

ということになりました。何度もループするところなので、ループ回数×30秒の待ち時間です。


他の対策も考えてはみたものの、アクションの実行終了がわかるような何か (レイヤー名を変えるとか) をアクションに組み込み、それを While で監視する――のは馬鹿らしくてやめました。


レイヤーのコピーは layers(0).Copy とかでできるわけもなく、layer の中身を一個ずつ見てやる必要がある。とか。レイヤーの選択は layers(1).Selected = true とかでできることもなく。とか。
不便ばっかり、リファレンスが役に立たないばっかりで、時間まで浪費してしまう。悪口はなんではありますが、ちょっとひどいですよこりゃ。
日本語版のリファレンスなんてぜいたくなことは言わないので、英語版のリファレンスをもっとわかりやすくし、そしてオブジェクトモデルももっと再考してほしいものです。切に願います。


# バグレポート上げればいいのかしらん?
スポンサーサイト
  • Illustrator のスクリプトからアクションを実行

Illustrator は、JavaScript からアクションを実行することができないようです。
仕方がないので VBScript からチャレンジ。っていうか私は VBScript の方が得意なので、前エントリのレイヤー合成も VBScript で書けば良かったか。

で、とりあえず『Illustrator CS3 Scripting Guide.pdf』を確認してサンプルのスクリプトを動かしてみようと思ったんですが・・・


Your first Illustrator script
The traditional first project in any programming language is to display the message "Hello World!"
1. Start any text editor (Notepad, for example).
2. Type the following code.
Rem Hello World
Set appRef = CreateObject("Illustrator.Application")
Rem Create a new document and assign it to a variable
Set documentRef = appRef.Documents.Add
Rem Create a new text frame item and assign it to a variable
Set sampleText = documentRef.TextFrames.Add
Rem Set the contents and position of the TextFrame
sampleText.Position = Array(200, 200)
sampleText.Contents = "Hello World!"

3. Save the file as text only in a folder of your choice. Give the file the file extension .vbs.
4. To test the script, do either of the following:
● Double-click the file.
● Start Illustrator and choose File > Scripts > Other Scripts, and then navigate to and run your script
file.


・・・すると、"Internal script execution error" というエラーダイアログ!?
まったくもって意味が分かりません。言われる通りにやったよママン。

上記で示されたサンプルは
C:\Program Files\Adobe\Adobe Illustrator CS3\プリセット\スクリプト\hoge.vbs
として保存して実行したのですが、なんだか嫌な予感がしたので C:\hoge.vbs にして実行。
・・・やっぱり同じでした。

おかしいなと思い、4. の「Start Illustrator and choose File > Scripts > Other Scripts, and then navigate to and run your script」ではなく、Illustrator をいったん落として「Double-click the file.」したところ、正しく動きました。
え、でも、Illustrator が起動している状態で使いたいんですけどっ!


他から持ってきたスクリプトを試したところ、どう見たって構文も合ってるし改行コードも問題なさそうなスクリプトなのに「ステートメントの末尾が不正です」エラーも出たし、さんざん悩まされました。
結論としては、『Visual Basic でエラーメッセージ「DLL 読み込み時のエラーです」が表示される(Illustrator CS3)』のせいでした。
これの対応をしたところ、.vbs がちゃんと動くようになりました。


と、本題の前に二時間ほど時間を消費してしまったが、いざアクションを呼ぶスクリプトの作成だ!
・・・あれ?

『Illustrator CS3 VBScript Reference.pdf』 の DoScript より。

Plays an action from the Actions
palette.
Note: Use DoScript only if you
intend to run your script
from an application
external to Illustrator,
such as the Windows
Script Host. Calling
DoScript when running
a script from Illustrator’s
File > Scripts menu may
yield unexpected results.


なんとまぁ、Illustrator 起動中に DoScript を使ってはいけないそうです。
ところで

DoScript
(Action as String,
From as String
[, dialogs as Boolean])

の From って何!?
説明が「Plays an action from the Actions palette.」だけじゃ何も分からん。

"Action" で文書を検索してゆくと、

Set appRef = CreateObject("Illustrator.Application")
appRef.DoScript "Opacity 60 (selection)", "Default Actions"
WHILE(appRef.ActionIsRunning)
WScript.sleep 1000
WEND
msgbox "Done"

というサンプルが。ああ、そういうことね。。。


というわけで、文書の記述を元にちょっと直したスクリプトがこちら。
直接 .vbs を実行すると、Hello World という JPG 画像を自動保存します。
下記を hello.vbs など、適当な名前で保存してください。

Rem Hello World
Set appRef = CreateObject("Illustrator.Application")
Rem Create a new document and assign it to a variable
Set documentRef = appRef.Documents.Add
Rem Create a new text frame item and assign it to a variable
Set sampleText = documentRef.TextFrames.Add
Rem Set the contents and position of the TextFrame
sampleText.Position = Array(200, 200)
sampleText.Contents = "Hello World!"

appRef.DoScript "Web用に保存(JPG 標準)", "初期設定アクション"
WHILE(appRef.ActionIsRunning)
WScript.sleep 1000
WEND
msgbox "Done"


たったこれだけのことをするために、なんでこんなに苦労しなきゃならんのですかね。ふう。
  • 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);
}

}

  • HP s3340jp/CT WindowsXP化

WindowsVista にいい加減嫌気がさし、純正では XP に対応していない s3340jp/CT に XP SP3 をクリーンインストールしました。

ドライバは当然提供されていないので、私が使ったドライバを参考までに載せておきます。

・サウンド
Realtek High Definition Audio

・システムデバイス
NVIDIA nForce PCI System Management

・参考情報
s3340jp スペック情報


めちゃくちゃ速くなりましたよ!
やっぱり OS は、こうでなくちゃいかん。

  • Vista でファイルが二重に存在し、悩まされる

だましだまし使ってはいたのですが。
いい加減、頭に来るのでユーザーアカウント制御をオフにしました。
そのあたりの検証レポートです。
ぐぐってみたんですが、コレに困ってるという人、いなそうなんですよね。みんな困らないのだろうか。


・ユーザーアカウント制御の問題点

いちいちうざったいというのはさておき、コレによる弊害があります。
通常ユーザモードと管理者モードでファイルが二重に存在することがあり、どっちが有効なのか分からなくなる (大半は管理者モード側なんですが) ことがあるのです。

例えば Apache をインストール済みであるとき、httpd.conf が二重に存在しており、片方 (通常ユーザモードの方) をさんざん修正しても Apache にまったく設定が反映されないということがよく起こるのです。
注意していればいいだろうと今まで耐えては来ましたが、ファイルを別の場所にコピーする場合に管理者モードのウィンドウから通常ユーザモードのウィンドウにドラッグできなかったりして、かなり不便です。

どういうことかというと、この画像の通りです。同じファイルなのに、タイムスタンプが違います。
VistaFile.png
・・・あ、あれぇ? オンラインソフトのとあるファイラーを使っている方は違うが、エクスプローラで見ると同じですね。。。
困っている人があまり見あたらないのはこういう事情なのか、と今納得した私。
試しに メモ帳 と 秀丸エディタ (v7.07) で開き分けてみると、メモ帳では 2008/11/16 19:17 のファイルが表示されるが、秀丸では 2008/11/06 0:19 のファイルと 2008/11/16 19:17 のファイルを開き分けることが出来ました。なるほど、どういうことかは分かった。



・ユーザーアカウント制御をオフにすると?

どういうことかは分かったものの、ファイラーを捨てることなんてできません。
というわけで、さっそくユーザーアカウント制御をオフにして再起動します。

VistaFile2.png

このように、2008/11/16 19:17 のファイルのみが表示されるようになり、2008/11/06 0:19 のファイルはなんと! どこかへ行ってしまいました。
たぶん UAC をもう一度オンにすれば復旧するのでは・・・とは思いますが、なんとも言えません。試す気にもならないので・・・。

また、ファイルがひとつになった結果、どちらのファイルが有効になるのかがいまいち分かりません。本来ならばそれも検証する必要があるのですが、どれもこれもバックアップは取ってあるので、これ以上の検証もチェックもせずにマシンを使い続けることにします。
これ以上 OS に振り回されるのもアホらしいので。


# 今まで調べもせずにだましだまし使っていたのも、とにかくめんどうくさいからだもの。


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