ごちゃペディア

はなまるデジタル創作紀行(DTM、TAS、いろいろな技術)

Lua for AviUtl で EmuLua の gui 関数を使う

Lua for AviUtl で使える EmuLua 互換の関数を用意する話です。後年追加された AviUtl 本体の Lua 機能とは異なりますが、応用はできるかもしれません。

DeSmuMEはLuaの描く画像を含めたAVI出力ができません。Luaの内容を含めたAVIを作成しようと思うと、Lua for AviUtlで動くようにスクリプトを修正して、AviUtlから描画することになります(少なくとも個人の知見に基づく限りは)。しかしながら、構造の違いを考えながらスクリプトを書き換える作業はめんどくさいものです。

そこでわたしは、エミュレータから「どのような描画関数を呼び出してオーバーレイ画像を描いたか」を記録し、AviUtlでそれを解釈させることで、比較的簡単にAVIに描画内容を移植することを試みました。

フィルタの解説

まずはエミュレータ側から描画スクリプトを出力します。スクリプトは各行にLuaのコードを記述したファイルで、各行の内容が各フレームで実行されるコードになっています。そして、aviemugui.lua内の定義により、コードにはEmuLuaのgui関数を使うことができます。手っ取り早くスクリプトのサンプルを示すとこんな感じです。

gui.pixel(50, 50) -- 1行目(フレーム#1): 点を描く
gui.pixel(50, 50) gui.box(20,20,80,80) -- 2行目(フレーム#2): 点と矩形を描く
gui.pixel(51, 51) -- 3行目(フレーム#3): 少し違う位置に点を描く
-- フレーム#4以降: 記述なし、ゆえに処理なし

エミュレータ側で動かすスクリプトgui.box(x1,y1,x2,y2) と書いてある箇所があれば、その隣に io.write(string.format("gui.box(%d,%d,%d,%d) ",x1,y1,x2,y2)) などと書けば、深く考えずとも簡単にこのようなログを取ることができます。

あとはaviemugui.lua内の記述を調整して、この形式のスクリプトを読み込ませるようにすれば、記述通りの内容が処理中の動画に描かれます。一部のgui関数はエミュレータ側とは多少異なる挙動を見せるかもしれませんが、さほど問題にはならないでしょう。工夫次第では、一部パラメータを後で調整できるような形のスクリプトを処理させることもできるでしょう。

あんまり親切でない記事ですが、これでなんとなく理解できる人以外にはそもそも需要がなさそうな気がします。

関係ないおまけメモ: ギャラリーオブラビリンスのマップオーバーレイ

arukAdoさんのマップオーバーレイがおもしろいっ。尋ねてみるとどうやら白い色を抜いているそうで、試しにAviSynthスクリプトの断片を書いてみたら以下のような感じになりました。実際にはもう少し記述を増やして大きさや位置、タイミングなどを記さなければいけないでしょうけど……とりあえず。

AviSource("maptest.avi").FlipVertical
t = Crop(0,0,256,192)
b = Crop(0,192,256,192)
map = t.Mask(t.ResetMask.ColorKeyMask($ffffff,88,88,88).ShowAlpha.Invert)

b
minimap = map.Crop(0,96,256,96)
ApplyRange(0, 400, "Overlay", minimap, 0, 0, minimap.ShowAlpha, 0.8, "add")