2009年7月29日水曜日

Flash Lite 1.1 のルートムービークリップの変数を動的生成してみた

swfの動的生成はswfmillmingという方法があるけれど、ひな形となるswfの変数だけを動的に変えるだけでよい場合にはswfバイナリを直接変更するという方法もあるという例。

生成した変数はルートムービークリップの変数になるようだ。変数名と同じ変数名でダイナミックTextインスタンスをステージに配置すれば、動的設定した文字列を表示することもできる。

ちなみに、検証にはFlash Lite 1.1で作成したswfを使った。

swf.rb
#!/usr/bin/env ruby
# -*- encoding: utf-8 -*-

require 'stringio'

module SWF
def self.read(src)
header = src.read(9)
x = (header[8] >> 3) * 4 + 5
header_size = ((((8 - (x & 7)) & 7) + x) / 8) + 12 + 5
header << src.read(header_size - 9)
body = src.read
[header, body]
end

class Vars
HD = "\x3f\x03\x00\x00\x00\x00"
BE = "\x96"
ZE = "\x00"
ZB = ZE + BE
ED = "\x00\x1d"

def initialize
@vars = []
end

def add(key, value)
@vars << [key, value]
end

def to_bytes
bytes = StringIO.new
bytes << HD
@vars.each do |key, val|
bytes << BE << [key.size + 2].pack('v') << ZE << key
bytes << ZB << [val.size + 2].pack('v') << ZE << val << ED
end
bytes << ZE
bytes.seek 0
bytes = bytes.read
bytes[2, 4] = [bytes.size - 6].pack('V')
bytes
end

def apply(src_io, dst_io)
vars = to_bytes
header, body = SWF.read(src_io)
header[4, 4] = [header.size + body.size + vars.size].pack('V')
dst_io << header
dst_io << vars
dst_io << body
end
end
end

if __FILE__ == $0
require 'yaml'
require 'optparse'
dat, src, dst = nil
OptionParser.new do |opt|
opt.on('-v VARS.yaml'){|v| dat = v }
opt.on('-i INPUT.swf'){|v| src = v }
opt.on('-o OUTPUT.swf'){|v| dst = v }
opt.parse!(ARGV)
unless dat && src && dst
opt.parse!(["-help"])
end
end
vars = SWF::Vars.new
YAML.load_file(dat).each{|key, value| vars.add(key, value) }
File.open(src, 'rb') do |s|
File.open(dst, 'wb') do |d|
vars.apply(s, d)
end
end
end

0 件のコメント:

コメントを投稿