Haxeからleap.jsを呼んでみる2


[前回](http://qiita.com/hatchinee/items/4936fbcf8966477974b2)で、イベントにコールバックを登録しておいて実行する方式の実装をしました。

今回は、Sampleにあった`loop`関数を使ったヤツの実装をしませう。
この記事のキモっぽいところは

- 関数へのexternはstaticでいいっぽい
- オーバーロードはマクロを使う
- 最終的に呼び出し上の見た目が同じになれば良い雰囲気を感じた（ダックタイピングめいたアトモスフィア）

です。

なお、サンプルのコードは長過ぎて、全部移すのはすごいだるいのでmain関数の中身は

```csharp:Main.hx

class Main {
    static function main() {
        var targ = document.getElementById("framedata");
        Leap.loop(['enableGestures' => true], function(frame){
            var frameString = 'Frame ID: ${frame.id} <br />
                    Timestamp: ${frame.timestamp} &micro;s<br />
                    Hands: ${frame.hands.length} <br />
                    Fingers: ${frame.fingers.length} <br />
                    Tools: ${frame.tools.length} <br />
                    Gestures: ${frame.gestures.length} <br />';
            targ.innerHTML = frameString;
        });
    }
}

```

だけとします。

-----
　　

### loop関数のextern

とりあえず、loop関数の定義をしてやる必要があります。
ですが、どうやらHaxeは関数だけをモジュールに配置したりは出来ないようです。
ちょっと迷ったのですが、とりあえずstaticメソッドとして定義して、メタデータで辻褄を合わせてみませう。

```csharp:leap/Leap.hx
package leap;

@:native("Leap")
extern class Leap {
    public static function loop(callback : leap.Frame -> Void): Void;
}
```

試してみたのですが、動くみたいです。
見た目上の呼び出しの階層が合っていれば問題はないようですね。
　　

### overload

ひとつ問題があります。loop関数は、何種類かの引数の取り方をするようです。
Haxeは、仕様上メソッドのオーバーロードを許していないので、overloadマクロで対応します。

なので、先ほどのLeap.hxの定義は

```csharp:leap/Leap.hx
package leap;

@:native("Leap")
extern class Leap {
    @:overload(function(opt: Map<String, Dynamic>, callback : leap.Frame -> Void) : Void {})
    public static function loop(callback : leap.Frame -> Void): Void;
}

```

となります。
公式に例が少なくて少し戸惑ったのですが、`@:overload`の中はcurly bracketまで記述する必要があるので注意してください。


-----
　

最後に、callbackの引数に使われているFrame.hxを定義してやりましょう。

```csharp:leap/Frame.hx
package leap;

import haxe.ds.Vector;

@:native("Leap.Frame")
extern class Frame {
    public function new();

    public var fingers(default, null) : Vector<leap.Pointable>;
    public var gestures(default, null) : Vector<leap.Gesture>;
    public var hands(default, null) : Vector<leap.Hand>;
    public var id(default, null) : String;
    public var timestamp(default, null) : Int;
    public var tools(default, null) : Vector<leap.Pointable>;
    public var pointables(default, null) : Vector<leap.Pointable>;
    public var valid(default, null) : Bool;

    public function dump() : String;
    public function finger(id : String) : leap.Pointable;
    public function hand(id : String) : leap.Hand;
    public function pointable(id : String) : leap.Pointable;
    public function tool(id : String) : leap.Pointable;
    public function rotationAngle(since_frame : leap.Frame, axis : leap.Vector) : Int;
    public function rotationAxis(since_frame : leap.Frame) : leap.Vector;
    public function rotationMatrix(since_frame : leap.Frame) : leap.Matrix;
    public function scaleFactor(since_frame : leap.Frame) : Int;
    public function translation(since_frame : leap.Frame) : String;
    public function toString() : String;
}

```

fingersなどのデータは配列ですが、能動的に変更するようなケースはなさそうなので読み取り専用のVector（固定長配列）型としておきましょう。

`leap.Pointable`などの型も、クラスの定義だけしておくか、めんどくさかったらとりあえずDynamic型にしておくといいかと思います。ここらへんの柔軟さは嬉しいですね。

----
　
最後に、データを表示するための要素を付与しておいたhtmlを用意して、ブラウザで開きましょう。

```html:main.html
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <script src="./static/js/leap.js"></script>
        <title>Leap Motion Haxe Sample</title>
    </head>

    <body>
        <h1>haxe</h1>
        <div id="framedata">
        </div>

        <!-- scripts -->
        <script src="./static/js/main.js"></script>
    </body>
</html>

```

なんか出ると思います。ペンとか持つとペンも認識してくれます。
やりましたね。

　

Haxeをやる前は、jsライブラリの呼び出しだとか、すごいハマりまくりそうなイメージを持っていたのですが、すごい簡単に出来てしまう感じなので良いですね。もっとも、もうちょい規模の大きいコードですとまた違った問題が出てくるかもしれませんが。