FlashのJavascript拡張機能 JSFL(その1)

あれこれ考えていたときに、Flashは確かJavascriptでいろいろ操作できるはず、ということを思い出しました。
何年か前にちょっとやったことがあったのですが、すっかり忘れてしまったので一からやり直してみます。

サンプルから始めよう

ヘルプによると、JSFL実装のサンプルが公開されているらしいので、Adobeのサイト内からダウンロードします。
Samples.zip (ZIP, 8.96 MB) をダウンロードします。これを展開したファイルの中の ExtendingFlash ディレクトリ以下にいろいろ情報がまとまっていますのでこれを見てみます。以下のように5つのファイルと一つのPDFが入っています。

  • dllComputeSum/
  • filtersGetSet/
  • PolyStar/
  • Shape/
  • TraceBitmap/
  • extending_readme.pdf

extending_readme.pdfに各ディレクトリの内容が(英語で)書かれているのでこの流れに沿って内容を見てみたいと思います。

その1となる今回のエントリではShapeの中身を見てみますが、これの流れを追うことで、基本的なJSFLの使い方を把握することができます。

Shape command

まず、Shapeディレクトリですが、ここには Shape.jsfl というファイルが一つあるだけです。これを Configuration/Commands フォルダにコピーします。
このフォルダの場所は、「Flash CS3 ドキュメンテーション>JSFL ファイルの保存」に詳しく書かれており、Windows環境の自分の場合なら、C:\Documents and Settings\<ユーザー>\Local Settings\Application Data\Adobe\Flash CS3\ja\Configuration\Commandsという場所になります。
この状態で、Flashの「コマンド」メニューを開くと「Shape」コマンドが追加されています。
矩形を描画し、選択して、このコマンドを実行してみます。すると「出力」パネルに次のように選択したシェイプの情報が出力されました。

selection length: 1
selected element[object Shape]
element type: shape
contour array length: 2

Next Contour, orientation:1, interior: false
vrt: 324.95, 203
vrt: 164, 203
vrt: 164, 129
vrt: 324.95, 129

Next Contour, orientation:-1, interior: true
vrt: 324.95, 129
vrt: 164, 129
vrt: 164, 203
vrt: 324.95, 203

このソースコードを少しずつ追っていきたいと思います。

var selArray = fl.getDocumentDOM().selection;
fl.trace( "selection length: " + selArray.length );

var elt = selArray[0];
fl.trace( "selected element" + elt );
fl.trace( "element type: " + elt.elementType );

flがFlashオブジェクトに相当し、getDocumentDOM()でドキュメントクラスを取得することが可能となります。selectionというのは現在選択中のElementオブジェクトが入った配列となるプロパティです。何も選択していないときには長さゼロの配列となるようです。
また、fl.trace という関数で出力パネルに文字列を出力させることが出来ることが分かります。
ここまでのコードを参考にして、選択しているオブジェクトの情報を出力してみたいと思います。

var selArray = fl.getDocumentDOM().selection;
fl.trace( "selection length: " + selArray.length );
for (i=0;  i<selArray.length;  i++){
  var elt = selArray[i];
  fl.trace( "selected element " + elt );
  fl.trace( " -> elementType: " + elt.elementType );
}

elementTypeは、シェイプであれば"shape"、ムービークリップインスタンスであれば"instance"、テキストであれば"text"が出力されました。ヘルプによれば、elementTypeはストリングを返し、必ず「"shape"、"text"、"instance"、または "shapeObj"」のどれかになるらしいです。

元のコードに戻って続きを見てみます。

var contourArray = elt.contours;
fl.trace("contour array length: " + contourArray.length);

var contourCount = 0;
for (i=0;  i<contourArray.length;  i++){
  var contour = contourArray[i];
  fl.trace(" ");
  fl.trace("Next Contour, orientation:" + contour.orientation + ", interior: " + contour.interior );
  contourCount++;

  // ..
}

この"contour"というのは「輪郭」という意味らしく、Flashでは「シェイプの境界にあるハーフエッジの閉じたパス」という意味を持っています。上記コードではそのパスの配列をcontoursというパラメータで取得しているのです。
contoursは二つのパラメータを持っていますがそれぞれの内容は次のような意味となります。

interior 輪郭内にエリアが含まれる場合 true
orientation 輪郭の方向が反時計回りである場合 -1、時計回りである場合 1、輪郭内にエリアが含まれない場合は 0

最後に、forループ内の残りのコードを見てみます。

for (i=0;  i<contourArray.length;  i++){
  // ..
  var he = contour.getHalfEdge();
  var iStart = he.id;
  var id = 0;
  while (id != iStart){
    // see if the edge is linear
    var edge = he.getEdge();
    var vrt = he.getVertex();

    var x = vrt.x;
    var y = vrt.y;
    fl.trace("vrt: " + x + ", " + y);

    he = he.getNext();
    id = he.id;
  }

ContourオブジェクトのgetHalfEdge()メソッドで、HalfEdgeオブジェクトという頂点データを持つオブジェクトを取得することができます。
HalfEdgeオブジェクトはリスト構造になっていて、一つのContourオブジェクトに含まれるHalfEdgeを次々とたどることが出来るようです。

HalfEdge, Edge

ということで、ここまででjsflの簡単な使い方と、データの調べ方が分かった。
しかし、最後のところでちょっと出てきたこのHalfEdge, Edgeというオブジェクトがポイントになりそうなので、最後にヘルプを見て勉強。

ということで、どうやら下図のような感じになるらしい。

ところが、Flash上でダイレクト選択ツールで選択したときに見えるポイントとは違う気がする。角がとがった単純な多角形なら見た目と同じ数のポイントが出力されるのだが、ベジェのコントロールポイントを曲げたり動かしたりするだけでjavascript経由で出力されるポイント数が変わってくる。
この辺りを本格的に触るときには注意しよう。