はじめに
対象読者
最初に、このページはFireworksの機能拡張を作りたい、ActionScript 3.0が書ける人向けの紹介になります。ActionScriptと組み合わせる上で壁になりそうなjsfオブジェクト、メソッドについてはしっかり解説する予定ですが、それ以外のものについてはリファレンスを参考にしてください。
参考ページ
本文の内容は次のウェブページとフォーラムを参考にしています。
- Extending Adobe Fireworks CS4(英語)
- Fireworks Guru Forum(英語) - exteinding Fireworks
- ActionScript 3.0でのFireworksイベントの処理
- Fireworks jsf 外部jsfファイルの読み込み
用語:jsf
Fireworksの拡張APIにアクセスするFireworks用Javascript、そのファイルの拡張子です。
fireworksのConfigurationフォルダの場所
jsfファイルをはじめとする、Fireworksの機能を拡張するファイルは基本的にユーザーのConfigurationフォルダに置いておきます。設置フォルダによって扱われ方が変わります。他のjsfファイルなどがどこに置かれていて、それがどのように働くかは開発前に知っておく必要があります。
OS・バージョンによって多少異なります。昨今のマルチユーザー環境の場合にCS4では次の場所にあるはずです。(参考:Adobe Fireworks CS4 ユーザガイド/ユーザ設定ファイルについて )
コマンドの格納場所
- Vista: ブートドライブ\Users\<ユーザー名>\AppData\Roaming\Adobe\Fireworks CS4\Commands\
- XP:ブートドライブ\Users¥ユーザー名\AppData\Local\Adobe\Fireworks CS4\Commands\
- OS X:/Users/<ユーザー名>/Library/Application Support/Adobe/Fireworks CS4/Commands/
パネルの格納場所
- Vista:ブートドライブ\Users\<ユーザー名>\AppData\Roaming\Adobe\Fireworks CS4\Command Panels\
- XP:ブートドライブ\Users¥ユーザー名\AppData\Local\Adobe\Fireworks CS4\Command Panels\
- OS X:/Users/<ユーザー名>/Library/Application Support/Adobe/Fireworks CS4/Command Panels/
もうひとつFireworksには設定ファイルを保存する場所があって、それはアプリケーションの実行ファイルと同じディレクトリにあります。こちらには、もともと用意されているFireworksのコマンドやパネルが格納されていて、機能拡張を作る上で参考にすることもできます。また、Extension Managerでインストールした場合、こちらに入ります。
コマンドフォルダではjsfの拡張子を持つファイルとswfファイルをメニュー「コマンド」に表示します。パネルフォルダでは、swfファイルをメニュー「ウィンドウ」に表示します。ファイル名がそのまま表示され、そのファイル名はOSが許す限り日本語をふくめたマルチバイト文字や空白も認められるので、jsfやswfのファイル名は機能を示すわかりやすいものをつけると便利です。
他の拡張子は無視されるので、呼び出しの都合上コマンドフォルダに置きたいけれど隠したい、クラスやメソッドをまとめたjsfファイルは拡張子を変えておきます。実際にコマンドがあるフォルダをみるとffsなる表示されないファイルが存在します。
コマンドとパネルの違い
swfはコマンドとしてもパネルとしても設置できるのですが、機能によって設置場所を選択できます。
コマンドは、メニューの「コマンド」から利用できます。選択されたら即時実行されるのが特徴で、GUIを表示(コマンド>クリエイティブ>矢印を追加など)する場合も、実行後必ず閉じるようにします。また、コマンドとして扱われるswfはモーダルダイアログとして起動されるので、表示中はほかの作業ができません。GUIを用意する場合は、実行を途中でキャンセルできるように、閉じるボタンやキャンセルボタンを配置しておいたほうがより親切なものになります。(Macではコマンドから呼び出すFlashパネルに閉じるボタンは表示されません。)
パネルは実行を伴わずに表示させることができ、パネルを表示しているときにもドキュメントを変更できます。ワークスペースとして位置やパネルが開いているかどうかをユーザーが登録できます。また、常駐させられるので、Fireworks上の捜査をキャッチして割り込むことができます。ドキュメントを開くとき、保存するとき、ツールを変更したときなど、ユーザの操作をトリガーとする機能を提供できます。
書き出しバージョン
swfを書き出すときに心配なのがFlash Playerのバージョンです。基本的にはFlash Player 9をターゲットにすれば動きますが、モーダルダイアログとして開いているパネルを閉じるためのMMEndCommandはActionScript3の場合Flash Player9では存在しないのでパブリッシュが成功しません。CommandのGUIとしてパネルを作る場合にはFlash Player10以上で作ることが必要です。
気になるFireworksの方の対応ですが、CS3、CS4ともにFlash Player10向けの書き出しで動きました。CS3のころのFlash Playerのバージョンは公式には9だった筈なのでWindows版の場合はActiveXで入れているFlashのバージョンに依存するような気がしますが試してないので不明です。
なお、Flash Player9にも逃げ道となるクラスがあります。クラスファイル自体はこれ。
デバッグ方法
jsfを使った方法
FireworksにはFlashPanelから実行されたjsfをすべてアラートで表示する設定があります。大変便利なのですが、何かを実行する度にアラートがでてしまうので、フォーカスのチェックが必要だったりすると邪魔になります。
jsfの表示開始
jsfの表示終了
デバッグプレイヤーのログを使う方法
FireworksのFlashパネルは再生場所がFireworks上であるだけで、大抵のswfむけデバッグツールは有効です。一番簡単なのは、通常のswfと同じように、FlashTracer(Firefoxプラグイン)やFlashDevelopのログ機能を使ってtrace結果を表示するようにします。実際、私が公開しているFireworksExecuteクラスとFireworksEventクラスではisDebugModeをtureにするとjsfを全部trace表示するように作ってあります。
ただ、flashlog.txt上のtrace結果を利用する際は他のswf/AIRアプリケーションからのtraceと混乱しないような環境で行う必要があります。また、Fireworksが元々持っているスタートアップ画面もswfなので通信場所などがすべてtraceされますのでその辺りはご注意下さい。

swfパネルからFireworksにコマンドを送る
MMExecute
swfからjsfを実行する一番簡単な方法は、adobe.utilパッケージのMMExecuteを使用します。例文ではimportしていますが、タイムライン上にスクリプトを書く場合adobe.utilパッケージは既にimport済み状態ですので、そのまま使えます。
String MMExecute(String);
引数にはjsfが評価可能な式が入ります。戻り値は引数の実行結果がString型で入ってきます。実際の例は次の通りです。
アクティブドキュメントの幅を500ピクセルに変更する
MMExecute('fw.getDocumentDOM().width=500');
アクティブドキュメントの幅を取得
MMExecute('fw.getDocumentDOM().width;');
入力欄を表示してその値を得る
var res:String = MMExecute('prompt("入力欄タイトル","説明");'); // output "null" か ユーザー入力文字列
if (res!="null") MMExecute('alert("あなたが入力したのは「' + res + '」です。");');//表示
カラーピッカーを表示して選択
var res:String = MMExecute('fw.popupColorPickerOverMouse("#00000000",true,false)');
MMExecute('alert("あなたが選んだのは' + res + '色です。");');
fw.runScriptの扱い方
下記の点ですが、2009年に実行されないとかいていたのですが、実行コードを書いておけば実行されることを確認しました。訂正いたします。
マニュアルにはexecuteとあるのですが、CS4でテストする限りそのままでは実行されません。fw.runScript('スクリプト');は、jsfファイルの読み込み(actionscriptでいう#includeに近いけれど一切実行はされず、ActionScriptのメソッド内で呼び出すとその場限り使用可能になります)と、swfのロード(コマンドに置けばモーダルダイアログとしてswf起動)のための命令です。
fw.runScriptで読み込んだファイル内にある関数やメソッドを実行するためには、次のようにします。fw.runScriptで読み込んだjsfの変数や関数は、一度読み込めば、読込元jsfかswfの中でどこからでも呼び出すことができます。
パネルを開いている間に、パネルを上書きしたりjsfを書き換えても自動では更新されないので、一度パネルを最小化するか閉じて、再度パネルを開きロードするようにします。MacのCS4はタブを切り替えるなどではパネルを閉じただけでは再ロードされないので、完全に閉じるかFireworks自体を再起動する必要があります。
存在しないファイルをfw.runScriptで呼び出した場合は、空のjsfファイルがユーザー設定フォルダのCommandsに生成されます。テスト中にサイズ0のjsfファイルが見つかったらスクリプト側に誤りがあると可能性が高いです。
jsf
fw.runScript("FILE_PATH/commandfile.jsf");
somemethod();
ActionScript 3.0
//即実行する場合
import adobe.utils.MMExecute;
MMExecute('fw.runScript("comandfile.jsf");');
//ロードしてから後で実行する場合
import adobe.utils.MMExecute;
MMExecute('fw.runScript("comandfile.jsf");');
MMExecute('somemethod();');
また、ちょっと読み込めるファイルの指定方法が、fw.runScriptを実行しているスクリプトファイルの置場によって異なるので、表にまとめました。
| fw.runScript()で読み込むファイル位置→ | コマンド | コマンドパネルなど |
|---|---|---|
| コマンドのフォルダにjsf | フルパス | フルパス |
| コマンドパネルのフォルダのswf | ファイル名(※) かフルパス |
フルパス |
fw.runScriptはもともとコマンドが配されるフォルダ内のjsfを読みに行くようなのですが、私の環境(ユーザー設定フォルダ内のConfigurationフォルダに設置した場合)ではロードできないファイルとして認識されて「スクリプトにロックがかかっています」というエラーが出ました。テスト中にユーザー設定フォルダ内のConfigurationフォルダに置くjsfファイルでは毎回フルパスで記述すると覚えておいたほうが安全かもしれません。
※ファイル名で呼び出せるのは、Fireworks本体のあるフォルダにあるConfiguration/Commands内にあるファイルです。ユーザー設定ファイル以下のCommandsに置いたものは存在するけれど、ファイル名ではアクセス出来ないファイルになっています。
Actionscriptから情報を取得する
文字列以外の引数を使いたい、戻り値を取得したい
MMExecuteでjsfに渡す引数は、単純なArray、Objectであれば簡単に引き渡せます。JSON形式に変換してやればかなり複雑なものまで渡せます。受け取りは、pngTextから取得するときと、pngTextとは関係のない変数を受け取るときで戻り値の形式が変わるのでその点に注意が必要です。
pngTextとは?
Fireworksはドキュメントに表示されないデータを置くことができ、ファイルと一緒に保存できるプロパティpngTextがあります。これは文字列からFwArray、FwDictionary(オブジェクト)形式のデータを入れることができてそれがpngTextです。マニュアルによれば初期状態で生成日とファイルを生成したアプリケーション名が入っています。pngTextは、png構造の”tEXt”チャンクの内容に相当するとあるので、Fireworks PNG形式の拡張仕様でもないようです。tEXtチャンクについて知る場合はPNG 仕様書:チャック仕様書 4.2.3.1. tEXt テキストデータ(「PNG (Portable Network Graphics) Specification, Version 1.2」の和訳の一部)などを参考に。
pngTextは複数のフィールドを持つことができるので、フィールドに値をセットして利用します。また、ドキュメントについている情報なので、次のようなことをすると挙動がおかしくなる可能性があります。
fw.getDocumentDOM().pngText.foo = fw.getDocumentDOM();
pntTextのフィールドに値をセットする
import com.adobe.serialization.json.JSON;
var foo:Object = {aaa:"bbb",ccc:[d,e,f]};
MMExecute('fw.getDocumentDOM().pngText.foo='+JSON.encode(foo)+';');
これくらいの構造なら、JSONのライブラリを使わないでも渡せます。
var foo:String = '{aaa:"bbb",ccc:[d,e,f]}';
MMExecute('fw.getDocumentDOM().pngText.foo='+foo+';');
pngTextのフィールドから受け取る
import com.adobe.serialization.json.JSON;
var res:String = MMExecute('fw.getDocumentDOM().pngText.foo;');
res = res.replace(/([{,\s]+)([a-zA-Z0-9_]+):/g,'$1"$2":');
var foo:Object = JSON.decode(res) as Object;
普通の変数を渡す場合
import com.adobe.serialization.json.JSON;
MMExecute('fw.runScript("boo.jsf");');
var foo:Object = {aaa:"bbb",ccc:[d,e,f]};
MMExecute('setValue('+JSON.encode(foo)+');');
--boo.jsfの記述
setValue(obj) {
alert(obj.toSource());
}
変数(関数などの戻り値をオブジェクトで受け取りたい場合も含む)を取得する場合
普通の変数は、(変数の中身)という形式できてしまうので、JSON.decodeに渡す前に最初と最後の”(”と”)”を取ってやる必要があります。
import com.adobe.serialization.json.JSON;
var res:String = MMExecute('function getVar(){var foo=[0,2,3,{aaa:"b"}];return foo;}getVar();');//returns -> '([0,2,3,{aaa:"b"}])'
res = res.slice(1,-1);// returns -> '[0,2,3,{aaa:"b"}]'
res = res.replace(/([{,\s]+)([a-zA-Z0-9_]+):/g,'$1"$2":');// returns -> '[0,2,3,{"aaa":"b"}]'
var foo:Object = JSON.decode(res) as Object;//{0:0,1:2,3:3,{aaa:"b"}} Arrayにしておけば[0,2,3,{aaa:"b"}]
よく使いそうな機能
テキストファイル保存
ActionScriptにはローカルディスクにファイルを保存する機能がないので、保存はjsfを書いて行います。Fireworksが扱える画像ファイルは、Fireworks Objectにたくさんのメソッドがありますし、説明通りつかえば動きますので今回は割愛します。
Coreオブジェクト:FileオブジェクトとFile Referenceオブジェクト
ファイルを読み書きするため専用のオブジェクトです。ファイルを開くのはFileオブジェクトですので、Fileオブジェクトでファイルポインタを取得してそこから1行ずつ読み込んだり、テキストデータを書き込んだりします。使い方はC言語やperl/phpなどの方式と大変似ています。
FileオブジェクトはすべてFile.プロパティ/メソッドという形で使います。また、ファイルリファレンスオブジェクトはFileReference.メソッドという形でなく、File.open()を使用することでFileReferenceオブジェクトのインスタンスを取得できるのでそれを使用します。メソッドはオンラインマニュアルのThe Fireworks Object Model / Core objects の、Files ObjectとFile Reference Objectに書いてあります。Files Objectはファイルとディレクトリ操作に大変使いやすいメソッドが揃っているので一読しておいたほうがよいと思います。
実装のためのコード
//Javascriptでかき出す全テキストファイル共通での文字エンコーディングの指定
Fw.textOutputEncoding = "utf-8";
/*おそらく選択できるのはutf-8とOSの標準文字エンコーディングです。*/
//ファイルを作成する
Files.createFile("yourfilepath",".txt"/*ファイル拡張子*/,"TEXT"/*クリエイター*/);
//読込専用でファイルを開く
Files.open("yourfilepath",false);
//書き込めるようにファイルを開く
var fr = Files.open("yourfilepath",true);
//書き込む
fr.write("contents...");//Fw.textOutputEncodinで指定した文字エンコーディングのファイルが出来る
fr.writeUTF8("contents...");//CS4から使えるUTF-8限定で保存
//ファイルリファレンスを閉じる
fr.close();
テキストファイル読込
設定ファイルを外部ファイルで持っている場合に使えます。jsfにはパネルの環境設定を書き出したり読み込むための命令がありますが、こちらは特定フォーマット向けなので、汎用には利用できません。
jsf
1行ずつ読み込む形式です。ファイルの終了を示すまでwhileなどで読み取ります。
ActionScript
URLLoaderを利用します。
fw.runScriptを活用する。
jsfファイルに変数=の形で定義しておくと、fw.runScript一発で読み込めるので用途によってはこちらがオススメです。
テキストのクリップボードコピー
jsfのコピーとペーストはオブジェクトのコピーとペーストになるなので、テキスト以外の情報もクリップボードにコピーしてしまいます。Flashパネルを作る場合には、単純なテキストのクリップボードコピーはActionScriptに任せてしまった方が後の配慮が少なくて楽です。
jsfのみでクリップボードコピーを実装している方が海外にはいらっしゃるのでそちらもどうぞ。
ActionScriptでの実装
必ず、flash.system.System.setClipboardで実装します。flash.desktop.Clipboardのほうが高性能ですが、こちらを使うとWindows版CS4のクラッシュの原因になります。
import flash.systemSystem;
function setStringToClip(message:String){
System.setClipboard(message);
}
Fireworksから送られるイベントを取得して処理を行う
FlashパネルはFireworksからイベントを受け取って処理することができます。ドキュメントを閉じたりすること自体に割り込んで処理を止める用途ではありません。
Windows版とMac版の違い
Flashパネルから使えるjsfは同一ですが、Fireworks自体の挙動が異なるので同じパネルでも動作が変わる場合があります。いくつかパネルを作成していて気になるのは次の点。
- Windows版ではパネルの開閉(もしタブになっていたらタブの切り替え)を行う度に、swfのロード/アンロードが行われる。(CS4 Windows版の整頓パネルが@タブを切り替える度に状態がリセットされるのはそのため。)
- Mac版では、KeyboardEvent.altKeyなどが無効になる。
この現象はどちらが仕様通りというのは言い切れないので双方でテストを行うか、その機能への対策
ActionScript3.0用クラス
せっかくActionScript 3.0でFireworksからのイベントが受け取れるということで、クラス化しました。また、このクラスの習作としてFireworksが送るイベントをアイドル状態をのぞいてリストにするFlash Panelを作りました。FireworksのイベントをFlashパネルで監視(Extension習作)をご覧ください。
メインの機能はExternalInterface.addCallback()での登録ですが、自動的にFireworksにswfがイベントを受け取ることを通知するためのメソッドを設定するので毎回IsFwCallbackInstalled部分を記述する必要がありません。
もう一つの機能は、イベント名を覚えたり毎度確認するのは大変なのでイベント名を定数で指定できます。かなり間違いが減らせると思います。
ActionScript3向けMMExecuteを置き換えるクラス
ActionScript 2 までであれば、Extending Fireworksで紹介されているfwapiというライブラリを使用できますが、ActionScript3.0ではそのままでは使えません。そこで、デバッグや値の取得を補助するクラスを作ってみました。現在はベータ版です。また、as3corelib必須です。Fireworksでpickした画像をそのままクリップボードへ(Flashパネル習作)
そのページでクラスの動作を確認するためにカラーピッカーを作成しましたのでそちらも合わせてご確認下さい。DebugModeをONのまま書き出しているのでjsfは全部flashlog.txtに入ってきます。FlashTracerなどでご覧ください。