PythonでFlash作成 その2 「swfmill simpleモード編」

[pukiwiki]
みなさまGWはいかがでしたでしょうか?
私はこんなことをして遊んでました(汗
—-
[[こちらの記事のつづきです:http://boxheadroom.com/2009/04/22/py_swfmill]]

[/pukiwiki]

[pukiwiki]
世の中にはLLからFlash(swf)を作成するための方法はいろいろあるのですけれども、今回は
-xmlを解釈してswfに変換してくれる[[swfmill:http://swfmill.org/]]というツールを使用。 
-xmlを作成するためのユーティリティ関数をPythonで作成

と、ワンクッションおくことで、あたかもPythonでFlashを作成しているかのような作業環境を目指します。
 つまりメインとしては”PythonでXMLを作成する”という話なのですけれども。

で、いきなり出来上がりのコード。
swfmillのsimpleモード用のラッパーです。
(swfmill.exeと同じフォルダで動かしてます)
[/pukiwiki]

import subprocess
import  xml.etree.ElementTree as etree
import types
class Tag(object):
    def __init__(self):
        self.builder=etree.TreeBuilder()
    def create(_self,tag,contents=[],attrs={}):
        
        class C(object):
            def __init__(self,contents=contents,attrs=attrs):
                self.attrs=attrs
                self.contents=contents
            def force(self):
                a={}
                for k in self.attrs:
                    t=type(self.attrs[k])
                    if  t in [ types.StringType,types.UnicodeType]:
                        a[k]=self.attrs[k]
                    else :
                        a[k]=str(self.attrs[k])
                    
                _self.builder.start(tag,attrs=a)
                for i in self.contents:
                    i.force()
                _self.builder.end(tag)

        C.__name__=tag
        
        return C
            
    def tostring(self):
        doctype="""<?xml version="1.0" encoding="utf-8" ?>\n"""
        ret=self.builder.close()
        return doctype+etree.tostring(ret)

def reset():
    global movie,background,clip,font,textfield,place,meta,frame,library
    tag=Tag()
    movie=tag.create("movie",attrs=dict(version="6",width=320 ,height=240,framerate=12))
    background=tag.create("background",attrs=dict( color="#ffffff"))
    clip=tag.create("clip",attrs={ "id":"foo","import":"library/foo.jpg",
                                   "class":"org.osflash.Foo"})
    font=tag.create("font",attrs={ "id":"vera",
                            "import":"library/vera.ttf","glyphs":"0123456789"})
    textfield=tag.create("textfield",attrs=dict( id="hellobox",
                width="200",height="50",size="10",font="vera",text="hello world!"))
    place=tag.create("place",attrs=dict(id="hellobox",name="output",depth="10"))
    meta=tag.create("meta",attrs=dict(title="my title",description="To be indexed"))
    frame,library=[tag.create(t) for t in "frame library".split()]

if __name__=="__main__":
    root=movie(attrs=dict(framerate="10",height="200",width="400" ),
        contents=[
            
            background(attrs=dict(color="#ffffff")),
            library([
                clip(attrs={"import":"foo.jpg","id":"foo"}),
                textfield(attrs=dict( id="hello",text="hello world!",
                    width="200",height="50",size="10")) 
            ]),
            frame(contents=[
                    place(attrs=dict(depth=10,id="foo")),
                    place(attrs=dict(depth=11,id="hello"))

            ]),

        ])
    root.force()
    txt=tag.tostring()
    #print txt
    fname="helloworld"
    if True :
        proc = subprocess.Popen(
                                #'swfmill.exe -v swf2xml niku.swf niku.xml',
                                'swfmill.exe -v simple stdin %s.swf'%fname,
                               shell=True,
                               stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE,
                               )
        stdout_value = proc.communicate(txt)[0]
        stdout_value
        print stdout_value
        proc = subprocess.Popen(
                                #'swfmill.exe -v swf2xml niku.swf niku.xml',
                                'swfmill.exe -v swf2xml %s %s'%(fname,fname),
                               shell=True,
                               stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE,
                               )
        stdout_value = proc.communicate()[0]
        print stdout_value
 

以前の記事では遅延評価をデコレータとジェネレータを使って書きましたが、今回は素直にクラスを使いました。

実際にswfファイルの中身(を指定するためのXML)を記述しているのは以下の部分。

root=movie(attrs=dict(framerate="10",height="200",width="400" ),
        contents=[
            
            background(attrs=dict(color="#ffffff")),
            library([
                clip(attrs={"import":"foo.jpg","id":"foo"}),
                textfield(attrs=dict( id="hello",text="hello world!",
                    width="200",height="50",size="10")) 
            ]),
            frame(contents=[
                    place(attrs=dict(depth=10,id="foo")),
                    place(attrs=dict(depth=11,id="hello"))

            ]),

        ])
root.force()
txt=tag.tostring() #XMLが返って来る

内部的に作成されるXMLはこちら。
(適宜改行、インデントは手作業で加えました)

<?xml version="1.0" encoding="utf-8" ?>
<movie framerate="10" height="200" width="400">
    <background color="#ffffff" />
    <library>
        <clip id="foo" import="foo.jpg" />
        <textfield height="50" id="hello" size="10" text="hello world!" width="200" />
    </library>
    <frame>
        <place depth="10" id="foo" />
        <place depth="11" id="hello" />
    </frame>
</movie>

[pukiwiki]
こんな短いXMLを作るために、なんでこんな面倒なことを、、、と思われるかもしれませんが(自分でも思いますが)、IDLE使って書くと、普通にXMLを書き下すよりも楽でした。
ただし”simpleモード”だけだと、あまり使い道が無いので、細かいことをしたければ”xml2swfモード”用のラッパーを書かないといけないかも。
ActionScriptなどをいじろうと思うと、MTASCなどの助けも必要になりますし。
というわけで、 それらはまたいずれ。。。

*関数のキーワード引数に予約語を使うとシンタックスエラーになる
というのを、今回はじめて気が付きました。

dict(import=”spam.jpg”)

などとするとエラーになります。

{“import”:”spam.jpg”}

と書くことで回避できますけれども。
*関連記事
-[[PythonからswfmillでFlashムービー(swfファイル)を作成してみる:http://boxheadroom.com/2009/04/22/py_swfmill]]
-[[exec,eval とクロージャではまる&遅延評価:http://boxheadroom.com/2009/04/25/py_eval_exec_closure]]
—-
ToDo: ActionScript 、xml2swfモード

[/pukiwiki]

コメントを残す

メールアドレスが公開されることはありません。