Processing3の仕組みを覗いてみる

# はじめに

この記事では、Processing3.3.5(7/2現在最新)の `settings()` や `setup()` 、 `draw()` がどうやって動いているのかの説明していきます。IDEに関する説明ではありません。
間違いやさらなる面白い情報があるという方は是非、コメントにてご指摘ください！

# どうやって解明するのか

[https://github.com/processing/processing](https://github.com/processing/processing)

> This is the official source code for the Processing Development Environment (PDE), the “core” and the libraries that are included with the download.

ということでProcessingの公式のソースコードを読んでいきます。

[core/src/processing](https://github.com/processing/processing/tree/master/core/src/processing)の中にProcessingがどうやって動いているのかが詳しく書かれています。

# `settings()` と `setup()` 、 `draw()` の定義

これら3つの関数は全て [PApplet.java](https://github.com/processing/processing/blob/master/core/src/processing/core/PApplet.java) の中で定義されています。１つずつ見ていきましょう。

## `settings()`

```java
  public void settings() {
    // is this necessary? (doesn't appear to be, so removing)
    //size(DEFAULT_WIDTH, DEFAULT_HEIGHT, JAVA2D);
  }
```

[code link](https://github.com/processing/processing/blob/master/core/src/processing/core/PApplet.java#L1037)

## `setup()`

```java
  public void setup() {
  }
```

[code link](https://github.com/processing/processing/blob/master/core/src/processing/core/PApplet.java#L1800)

## `draw()`

```java
  public void draw() {
    // if no draw method, then shut things down
    //System.out.println("no draw method, goodbye");
    finished = true;
  }
```

[code link](https://github.com/processing/processing/blob/master/core/src/processing/core/PApplet.java#L1832)

## ほとんど何も書いてない...

Processingでみなさんが書いているコードは実は `PApplet` を継承したclassです。以下のコードを実行すると、ちゃんと `true` が返ってきます。

```
println(this instanceof PApplet);
```

Processingでは `PApplet` の `settings()` や `setup()` 、 `draw()` をオーバーライドすることを前提として書かれています。コードの前に `@Override` と書いてもエラーは出ません。

# 各関数は何処で使われているの？

`settings()` は `handleSettings()` という関数で呼び出されています。
また `setup()` と `draw()` は `handleDraw()` という関数で呼び出されています。
両方とも、 `PApplet` の中に存在します。

## `handleSettings()`
この後 `PApplet` 内で、 `runSketch()` ⇒ `main()` という順番に呼び出されていきます。
余談ですが、この関数内では `insideSettings` というboolean型の変数が使われています。Processingの `smooth()` と `noSmooth()` は `insideSettings` という変数がtrueのときだけのみ動きます。trueの状態で処理を行えるのは `settings()` の中だけなので注意しましょう。実際に [困っている人](https://github.com/processing/processing/issues/5160) もいました。

[code link](https://github.com/processing/processing/blob/master/core/src/processing/core/PApplet.java#L948)

## `handleDraw()`

`frameCount == 0` のときは `setup()` 、それ以外のときは `draw()` が呼び出されるようになっています。これまた小ネタですが、 `frameCount` はpublicな変数なので、 自由に数値をいじれます。 `frameCount = -1` と `draw()` 内で行うと `setup()` が呼び出されます。使う機会はないでしょうが、Processingの脆弱性の一つでしょう。

[code link](https://github.com/processing/processing/blob/master/core/src/processing/core/PApplet.java#L2373)

# AnimationThread

`PSurfaceNone` というクラスの中に [AnimationThread](https://github.com/processing/processing/blob/master/core/src/processing/core/PSurfaceNone.java#L252) というThreadが定義されています。 `handleDraw()` はその中の `callDraw()` で呼ばれ、さらに `run()` の中でwhile文によって終了条件を満たすまでループされ続けます。

# まとめ

以上、いつも私達がProcessingで書いていた `settings()` や `setup()` 、 `draw()` がどのように動いているかの解説をさせていただきました。この記事を見て納得して頂けたら幸いです。

## 最後にまたまた小ネタ

`handleDraw()` はpublicなので、オーバーライドすることができます。以下のコードを他人のコードに入れるだけで `setup()` と `draw()` は呼び出されなくなります。

```java
void handleDraw() {
}
```

これもまたProcessingの脆弱性と言えるでしょう。大丈夫なのかProcessing...