Node.js+Photoshop: Generatorの設計と使い方

先月、Photoshop 14.1の新機能として「Generator」が発表されました。色々使ってみると結構面白い技術なので、Generatorの設計、そして使い方を詳しく紹介したいと思います。

まずはいくつかの定義について:

  • GeneratorとはPhotoshop CC(14.1+)に組み込まれるNode.jsサーバを指す
  • Generator プラグイン:Generator に接続するNode.js アプリケーション
  • Generator Core:Node.jsサーバとプラグインの間のコミュニケーションなどを管理するNode.jsライブラリ。ソースはPhotoshopチームのgithubにあり。
  • Image Asset Generator:少し話題を集めた、自動的に画像アセットを書き出してくれるプラグイン。記事によってこのプラグインのことを「Generator」と呼ぶのでNodeサーバの話と混乱しやすい。この記事の題材ではないが、最後に少し言及している。
    ということで、Generatorを使うと言うのはCoreに接続するプラグインを作る話なので、その設計と作り方を見てみよう。

Generatorの設計

画像の通り、Generator Coreはフォトショに組み込まれていて、別途Node.jsアプリケーションとして起動することもできる。組み込みのCoreがPhotoshopの中の決まったフォルダにあるプラグインのみに対応する。なので通常では、プラグインを開発している間はGenerator Coreを別途起動し、動作確認後、プラグインが完成したら、プラグインのソースをPhotoshopのプラグインフォルダーに移動する。

必要なパーツのインストール

  1. Node.jsをインストールしよう。
  2. Generator Coreのソースを取得。gitを使いたくない場合はそのページで「Download zip」をクリック。
  3. ターミナル(Mac)またはコマンドプロンプト(Win)を使って、Generator Coreのソースフォルダーに移動し、「npm install」を入力。

そうするとnpm(Nodeパッケージモジュール)が必要なライブラリを拾ってくれる。ちなみにnpmが動かない場合は、Node.jsのインストールに何かの問題があったと思われる。

Photoshop側の設定

別途起動するGenerator Coreからのコネクションを受けるように設定。そのためには、Photoshop → 環境設定 → プラグインの設定画面で、Generatorリモート接続を有効にする。そしてパスワードを、デフォルトとして、「password」にする。

パスワードの値はGenerator Coreのソースのapp.jsで変更できるが、初めはデフォルトの「password」のままにしておく。

プラグイン開発

次はプラグイン作り。他のNode.jsのアプリケーションと同様に、少なくとも2つのファイルが必要:コンフィグのpackage.jsonmain.jsのソース。Generator Coreのソースの /test/plugins/ の中にテスト用のプラグインが3つありますので、プラグインの設計としては参考例になります。

必要最低限のプラグインはこんな感じ:

package.json
{   
"name": "Andy Test",
"main": "main.js",
"generator-core-version": ">=1.0.0"
}

main.js
(function () {
var _generator;
function init(generator) {
_generator = generator;
console.log("Hello world");
}
exports.init = init;
}());

初期で渡される generator オブジェクトは後で必要になるのでlocal varとして取っておく。上記のような2つのファイルをフォルダーに入れたら、プラグインとして起動するコンソールコマンドはこれ:

> node [generator-coreへのパス]/app -f [プラグインフォルダのパス]

つまり、「node app」でGenerator Coreのapp.jsをNodeアプリとして起動し、「-f path」でプラグインのフォルダを指定。ダウンロードしたgenerator-coreフォルダから実行すると、下記の通り。

> node app -f test/plugins/my-test-plugin

ちなみに test/plugins のフォルダを指定して、3つのテスト用のプラグインを実行しますとエラーが出ます。その理由は、一つのプラグインはバージョン指定が違った場合にちゃんとエラーが出るかをテストするものだからです。

Photoshop側のAPIを呼ぶには

Photoshopは昔からExtendScriptという拡張機能に対応しています。と言っても、Photoshop内にJavascriptのVMが組み込まれてるだけなので、そのAPIさえわかれば、Photoshopの各機能をJavascriptで使える。

ただ大事なのは、ExtendScriptとGeneratorにはそれぞれ別のJavascriptのVMがあり、GeneratorプラグインからPhotoshop側のAPIを呼ぶために、ExtendScriptのVMにスクリプトをストリングとして渡す流れになるということ。Generator Coreがそのために evaluateJSXString というAPIを実装する。(ExtendScript用のスクリプトを純JSと区別するために、昔からJSXと呼ばれている。) evaluateJSXString にJSのストリングを渡すと、Photoshop側で実装される。例えばPS側の環境設定で単位をピクセルに設定するには:

var str = 'app.preferences.rulerUnits = Units.PIXELS;'; 
_generator.evaluateJSXString(str);

上記の通り、PS側のAPIを呼ぶためにGenerator Coreに渡されたgeneratorオブジェクトを使う。他にもPS側のイベント登録、各種のデータ取得などに使われる。

さらなる詳細

  • 実践的なプラグインの各機能(PSからのイベント登録、メニューの追加など)の事例として、同僚のTom Krchagenerator-getting-startedのソースを参照してください。
  • ExtendScript(PS側で使えるAPI)のリファレンスはこちら
  • CoreのgeneratorオブジェクトのAPIリファレンスが現時点では見つからないので、generator.jsのソースを直接見るのが一番早いかと。

Image Asset Generatorについて

Photoshop CCがGeneratorと共に、画像アセット生成のためのGenerator プラグインに対応。レイヤー名に「.png」などをつけると自動的に画像を生成してくれるやつのこと。非常に便利なプラグインで少し話題を集めたが、多くの記事がこのプラグインのことを「Generator」と呼ぶので混乱しやすい。このプラグインはPhotoshopのフォルダー内に置いてあるので、組み込みのGenerator Coreにて実行される。

このAsset Generatorプラグインのコード側のできが非常に良いので、プラグイン開発の上級な参考事例として、ソースの参照をお勧めする。