Inside Processing / Javaのソースコードから見るProcessing
これは、必要に応じて追記するメモ的なエントリです。自作のライブラリをProcessing内部の処理と競合しないよう結びつけるため調べている内容を書いていきます。
Processingが用いているJavaライブラリ
Processingは、Graphics2Dを多用してJava2Dに依存したコードを書いている割に、ウィンドウやパネルの管理には同世代の技術であるSwingではなく古いAWTを用いています。とくにSwingの新しい機能を使う必要がなかったからでしょうね。Swing重いし。
Processingの処理の流れ
main
processing.core.PAppletにmainメソッドがあります。この中でAWTのFrameを作り、PApplet型のappletをインスタンス化し、貼り付けてpack()しています。
init, start
その後applet.init()が呼ばれ、さらにapplet.start()が呼ばれます。ここで"Animation Thread"が作られ、Runnableをimplementしているappletが割り当てられて、以降はapplet.run()が呼ばれ続けます。
run
run()の中では、handleDraw()が呼ばれて画面の描画処理を要求したあと、適当な時間を計算してThread.sleep()します。これで、設定されたフレームレートを保って画面が更新され続ける仕組みです。
handleDraw
handleDraw()はrun()が何回呼ばれたか(frameCount == 0 か否か)を見ており、初回の呼び出しならsetup()を、それ以外ならdraw()を呼んでいます。この二つは、Processingユーザの皆さんにはお馴染みですね。
なお、PAppletのsetup()メソッドは空ですが、draw()メソッドにはfinished = trueと記述されており、Sketchでオーバーライドされないと(つまりSketchにdraw()メソッドがないと)プログラムが終了するようになっています。
また、PAppletにはbooleanのフィールドloopingとredrawがあり、それぞれループを回すか否かおよび再描画が必要かどうか示しています。
後追いの説明になりますが、(looping || redraw)がfalseのときはhandleDraw()は何もせずreturnするようになっています。Sketch起動時にはlooping == trueなのでsetup()は必ず実行されます。
redrawは、looping == falseのときでも再描画をかけたいときに使います。具体的には、redraw()が呼ばれるとredraw = trueが代入され、次にrun()が呼ばれたとき描画が実行される仕組みです。
Processingのイベントハンドリング
マウスイベント(mouse*)
全てのマウスイベントMouseEvent eはcheckMouseEvent(e)に渡されます。
loopingがfalseなら即時にhandleMouseEvent(e)が呼ばれてイベントが処理されます。
一方loopingがtrueなら、描画の合間にイベントが処理されるよう配列型のフィールドmouseEventQueueにキューイングされます。キューに入ったイベントは、前段で説明したhandleDrawの中で呼ばれるdequeueMouseEvents()で一気に吐き出され、handleMouseEvent(e)で処理されます。
handleMouseEvent(MouseEvent e)では、マウスの座標などの情報を持つフィールドが更新されたのち、イベントの種類に応じてmouseナントカ()が呼ばれます。