c_dfDIJoystick2
Linux版の実装は後で考えることにして、とりあえずHamigaki.Inputという名前でDirectInputのラッパーを追加しました。
今日の差分
まだ、ジョイスティックだけで、かつ未テストです。
さて、DirectXの基盤技術であるCOMではインタフェースやクラスの識別にGUIDというものを使います。
そして、MicrosoftのヘッダファイルではDEFINE_GUID()マクロで数多くのGUIDが定義されています。
このDEFINE_GUID()マクロは、INITGUIDが定義されていればグローバル変数としてGUIDを定義し、INITGUIDが定義されていなければGUIDの宣言だけ行われるようになっています。
これは、プロジェクト中の一つのソースファイルのみINITGUIDを定義してコンパイルすることを想定したものです。
1ファイルだけ別の設定でコンパイルするため、プリコンパイルヘッダとの相性が悪いんですが、ライブラリを作る場合にも問題になります。
ライブラリ内でINITGUIDを使うと、そのライブラリと関係のないコンポーネント用のGUIDが定義されませんし、利用者側でINITGUIDさせるのは不便です。
そんなわけでライブラリ内では、「ヘッダを参考にGUIDを独自に別名で定義する」のが最適だと思います。
で、ここからが本題です。
DirectInputではデバイスの状態を受け取るバッファを定義するのにDIDATAFORMAT構造体を用います。
そして、ジョイスティック用のバッファDIJOYSTATE2構造体に対しては、c_dfDIJoystick2というグローバル変数が用意されています。
しかし、c_dfDIJoystick2にはいくつかGUIDが含まれており、INITGUIDの問題を避けるとするとこの変数は使用できません。
仕方がないので、c_dfDIJoystick2の中身をダンプして、独自に定義することにしたのです。
ダンプ結果を見ると、
::DIOBJECTDATAFORMAT joystick_obj_formats[] = { /* 中略 */ { &rz_axis_guid, 20, format::axis, aspect::position }, { &slider_guid, 24, format::axis, aspect::position }, { &slider_guid, 28, format::axis, aspect::position }, { &pov_guid, 32, format::pov, 0 }, /* 中略 */ { &rz_axis_guid, 196, format::axis, aspect::velocity }, { &slider_guid, 24, format::axis, aspect::velocity }, { &slider_guid, 28, format::axis, aspect::velocity }, { &x_axis_guid, 208, format::axis, aspect::accel }, { &y_axis_guid, 212, format::axis, aspect::accel }, { &z_axis_guid, 216, format::axis, aspect::accel }, { &rx_axis_guid, 220, format::axis, aspect::accel }, { &ry_axis_guid, 224, format::axis, aspect::accel }, { &rz_axis_guid, 228, format::axis, aspect::accel }, { &slider_guid, 24, format::axis, aspect::accel }, { &slider_guid, 28, format::axis, aspect::accel }, { &x_axis_guid, 240, format::axis, aspect::force }, /* 中略 */
なぜかスライダーの部分だけオフセットが重複しています。
バグっぽいんですが、スライダーの付いたコントローラなんて持ってないので確認できません。
MSのことなので、このバグったオフセットの場合のみ特別な処理とかしてそうですけど。
なお、Hamigaki.Inputでは正しいオフセットを与えています。