Ming と Python で SWF を作ってみた

Mac でちょっとした SWF を作りたかったので Ming を使って作ってみました。
PHP, Perl, Ruby, Python, C, C++, Java から使えるみたいなんですが、なんとなく Python で。
っで、「python ming」とかでググっても MongoDB の O/R mapper がヒットするぐらいで、「python ming swf」でググってもまともな情報が出てこないんですよね。

そもそも、公式ページである http://www.libming.org/ にアクセスすると Wiki のデフォルトページが表示されるだけで、「もうメンテすらされてないのかな?」と思ってしまうぐらい情報がないです。
まぁ言語設定を英語にしてアクセスすればちゃんとしたページが表示されるんですが。1(それに気付けるかが問題!)

というわけで、Mac OS X に libming とその Python モジュールをインストールして、簡単な SWF を作成するまでの手順を備忘録的にまとめました。
環境は Mac OS X 10.6.8、Python 2.7.1(pythonbrew でインストールしたもの)です。

Ming のインストール

Releases からアーカイブをダウンロードできます。このページは言語設定が日本語でも大丈夫です。
以下、Python モジュールをインストールするまでの手順です。環境によっては sudo で実行しないと Permission denied になるコマンドもあると思います。

$ wget http://sourceforge.net/projects/ming/files/Releases/ming-0.4.5.tar.bz2/download
$ tar xvf ming-0.4.5.tar.bz2
$ cd ming-0.4.5/
$ ./configure --enable-python LDFLAGS="-L$(which python | sed 's|bin/python|lib|')"

(An omission)

Config summary: 
  C++ enabled
  Perl extension disabled
  PHP extension disabled
  Python extension enabled
  Tcl extension disabled
  ZLIB enabled (-lz)
  Freetype library enabled (/usr/X11/bin/freetype-config)
  GIF library disabled
  PNG library disabled
$ make
$ make install
$ cd py_ext/
$ python setup.py install

ちなみに GitHub の Tags などからアーカイブを取得する場合は autogen.sh を実行して configure などを作成する必要があります。

$ wget https://github.com/libming/libming/archive/ming-0_4_5.tar.gz -O libming-ming-0_4_5.tar.gz
$ tar xvf libming-ming-0_4_5.tar.gz 
$ cd libming-ming-0_4_5/
$ sed -i '' s/libtoolize/glibtoolize/g autogen.sh 
$ ./autogen.sh 
Running glibtoolize -f -c
glibtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, `config'.
glibtoolize: copying file `config/ltmain.sh'
glibtoolize: putting macros in `macros'.
glibtoolize: copying file `macros/libtool.m4'
glibtoolize: copying file `macros/ltoptions.m4'
glibtoolize: copying file `macros/ltsugar.m4'
glibtoolize: copying file `macros/ltversion.m4'
glibtoolize: copying file `macros/lt~obsolete.m4'
glibtoolize: Consider adding `AC_CONFIG_MACRO_DIR([m4])' to configure.in and
glibtoolize: rerunning glibtoolize, to keep the correct libtool macros in-tree.
Running aclocal -I macros
Running glibtoolize --automake
Running autoheader -f
Running automake
Running autoconf

  All autostuff worked fine. 

$ ./configure --enable-python LDFLAGS="-L$(which python | sed 's|bin/python|lib|')"

(An omission)

Config summary: 
  C++ enabled
  Perl extension disabled
  PHP extension disabled
  Python extension enabled
  Tcl extension disabled
  ZLIB enabled (-lz)
  Freetype library enabled (/usr/X11/bin/freetype-config)
  GIF library disabled
  PNG library disabled

あとは同じです。

サンプルコード

Ming に関してはしっかりしたドキュメントがあまりないように思います。Python に関しては py_ext/shape.py がサンプルとして用意されていますが・・・。
使い方を手っ取り早く知るには、既存の SWF を swftopythn で Python スクリプトに変換するのがオススメです。

例えば、swfmill を使えば次のような XML から Hello World を表示する SWF を生成できます。

<?xml version="1.0" encoding="utf-8" ?>
<movie width="320" height="320" framerate="12">
  <background color="#000000"/>
  <frame>
    <textfield id="label" width="320" height="320" size="32" text="Hello World" color="#ffffff"/>
    <place id="label" name="output" depth="1" x="80" y="120"/>
  </frame>
</movie>

生成された SWF を swftopython に渡すと(そのままでは動かないですが)サンプルコードの出来上がりです。

$ swfmill simple hello.xml hello.swf
$ swftopython hello.swf
#!/usr/bin/python
from ming import *

Ming_useSWFVersion(7);

m =  SWFMovie();

Ming_setScale(1.0);
m.setDimension(6400, 6400);

# SWF_SETBACKGROUNDCOLOR 
m.setBackground(0x00, 0x00, 0x00);

# SWF_DEFINEEDITTEXT 
character1 =  SWFTextField();
character1.setFlags(SWFTEXTFIELD_WORDWRAP | SWFTEXTFIELD_MULTILINE);
character1.setBounds(6400, 6400);
character1.setFont(f2);
character1.setHeight(640);
character1.setColor(0xff, 0xff, 0xff, 0xff);
character1.align(SWFTEXTFIELD_ALIGN_LEFT);
character1.setLeftMargin(0);
character1.setRightMargin(0);
character1.setIndentation(0);
character1.setLineSpacing(20);
character1.setName('');
character1.addString('Hello World');

# SWF_PLACEOBJECT2 
i1 = m.add(character1);
i1.setDepth(1);
# PlaceFlagHasMatrix 
i1.moveTo(1600, 2400);
# PlaceFlagHasRatio 
i1.setName('output');

# SWF_SHOWFRAME 
m.nextFrame(); # end of frame 1 

# SWF_END 

#print('Content-type: application/x-shockwave-flash\n\n');
m.output(9);

ちょっと使ってみる

四角形が左から右に移動するだけの単純な SWF を作成するスクリプトを書いてみました。

#!/usr/bin/env python
from ming import *

FPS = 10
FRAME_COUNT = 10
Ming_setScale(20.0)  # convert twip to px (72dpi)
Ming_useSWFVersion(4)

def create_rect(x, y, width, height, color = [0, 0, 0, 0]):
    rect = SWFShape()
    rect.setRightFill(rect.addFill(*color))
    rect.movePenTo(x, y)
    rect.drawLine(width, 0)
    rect.drawLine(0, height)
    rect.drawLine(-width, 0)
    rect.drawLine(0, -height)
    return rect


movie = SWFMovie()
movie.setDimension(100, 100)
movie.setFrames(FRAME_COUNT)
movie.setRate(FPS)
movie.setBackground(0, 0, 0)

item = movie.add(create_rect(0, 45, 10, 10, [0xff, 0, 0]))
for i in range(FRAME_COUNT):
    movie.nextFrame()
    item.move(10, 0)

movie.save(__file__.replace('.py', '.swf'))

Flash Professional は単純なサンプルを作るだけでも物凄く大変だった気がしますが、Ming だと直観的ですね!!

この書き方だと PlaceObject の変換行列を変えることで移動させていますが、ActionScript で移動させようと思うと次のような感じになるかと思います。

#!/usr/bin/env python
from ming import *

FPS = 10
FRAME_COUNT = 10
Ming_setScale(20.0)  # convert twip to px (72dpi)
Ming_useSWFVersion(4)

def create_rect(x, y, width, height, color = [0, 0, 0, 0]):
    rect = SWFShape()
    rect.setRightFill(rect.addFill(*color))
    rect.movePenTo(x, y)
    rect.drawLine(width, 0)
    rect.drawLine(0, height)
    rect.drawLine(-width, 0)
    rect.drawLine(0, -height)
    return rect


movie = SWFMovie()
movie.setDimension(100, 100)
movie.setFrames(FRAME_COUNT)
movie.setRate(FPS)
movie.setBackground(0, 0, 0)

mc = SWFMovieClip()
mc.add(create_rect(0, 45, 10, 10, [0xff, 0, 0]))
mc.nextFrame()

item = movie.add(mc)
item.setName('mc')
for i in range(FRAME_COUNT):
    movie.nextFrame()
    movie.add(SWFAction('mc._x = mc._x + 10;'))

movie.save(__file__.replace('.py', '.swf'))

Flash Professional がなくても Mac でこんなに簡単に SWF が作成できるなんて素晴らしいですね!!

参考

  1. Chrome だと about:settings の Languages で English を Japanese より上にすれば大丈夫です