- v0 などの以前の API バージョンに基づいて構築されたアプリケーションに、アプリケーション全体を一度に移行することなく v4 の機能を追加する。
- アプリケーションの残りの部分で v4 を使用している場合でも、以前のバージョンの GameInput に対してビルドされた SDK、ミドルウェア、またはエンジン プラグインを呼び出す。
サポートされている API バージョン
GameInput ランタイムは、自身のメジャー バージョン以下のすべての API バージョンをサポートします。たとえば、GameInput 4.0 ランタイムがインストールされている場合、すべての GameInput オブジェクトは v0、v1、v2、v3、および v4 のインターフェイスを実装し、アプリケーションはそれらを任意に組み合わせて使用できます。
インストールされているランタイムより新しい API バージョンを要求すると、
QueryInterface と GameInputInitialize は E_NOINTERFACE で失敗します。アプリケーションが使用する最も高い API バージョンによって、アプリケーションに必要な最小ランタイム バージョンが決まります。
PC では、インストールされているランタイムは、GameInput 再配布可能パッケージ、またはゲームと共に配置するランタイムです。詳細については、GameInput NuGet パッケージ と GameInput のサイドロード を参照してください。XBOX では、ランタイムは GDK に含まれており、より新しいランタイムをゲームと共に配置することもできます。詳細については、XBOX 本体での GameInput を参照してください。
プロジェクトをセットアップする
新しい実装では、最新の Microsoft.GameInput NuGet パッケージのヘッダーとGameInput.lib を使用します。パッケージでは、<GameInput.h> が最新のヘッダーであり、以前の各ヘッダーは <v0/GameInput.h> や <v2/GameInput.h> などのバージョン付きフォルダーにあります。ライブラリは GameInputInitialize をエクスポートします。これは、要求された任意の API バージョンの GameInput を作成します。
GDK に含まれるものなど、以前のリリースのライブラリも引き続き動作します。詳細については、以前のライブラリを維持する を参照してください。
v0 ヘッダーをインクルードする
v1 以降、各 GameInput ヘッダーは、GameInput::v4 などのバージョン付き名前空間でその型を宣言します。一方、v0 ヘッダーはグローバル名前空間で型を宣言します。v0 ヘッダーを最新のヘッダーと一緒に使用するには、GameInputV0.h などの独自のヘッダーに次の定型コードを記述します。
- 最初に最新の
<GameInput.h>をインクルードします。これにより、最新の API が独自の名前空間で宣言され、v0 ヘッダーが依存する Windows ヘッダーと COM ヘッダーがインクルードされるため、v0 ヘッダーが名前空間内でそれらを再度インクルードすることはありません。 - 前方宣言により、v0 ヘッダー内の typedef は、最新のヘッダーで既に宣言されたインターフェイスを参照するのではなく、
GameInput::v0に新しいインターフェイスを宣言します。 - 名前空間内で
<v0/GameInput.h>をインクルードすると、GameInput::v0::IGameInputやGameInput::v0::GameInputKindGamepadのように、すべての v0 の型、列挙型、定数がGameInput::v0に移動します。
<GameInput.h> の代わりに GameInputV0.h をインクルードし、既存のコードで修飾されていない名前を引き続き使用できるように using namespace GameInput::v0; を追加します。GameInputV0.h をインクルードするソース ファイルでは、GameInput::v4::IGameInput などの完全な名前を使用して最新の API を使用することもできます。
例: v0 アプリケーションに v4 の機能を追加する
v4 の機能を使い始めるために v0 のコードを書き直す必要はありません。v0 のコードは独自のソース ファイルに保持し、新しい v4 のコードは別のソース ファイルに記述します。2 つの間で GameInput オブジェクトをIUnknown* として受け渡し、それぞれの側で必要なバージョンの QueryInterface を呼び出します。
既存の v0 コード
次の v0 コードは、GameInput を作成してゲームパッドを読み取ります。元の v0 コードと比較して、変更点は次の 3 つだけです。<GameInput.h>の代わりにGameInputV0.hをインクルードします。- 最新のライブラリは v0 の
GameInputCreate関数をエクスポートしないため、v0 の IID を指定してGameInputInitializeを呼び出すことで GameInput を作成します。 - A ボタンが押されたときに、新しい v4 コードを呼び出します。
新しい v4 コード
新しいソース ファイルは v4 ヘッダーをインクルードし、v0 コードから渡されたデバイスでQueryInterface を呼び出します。次に、v4 で新しく追加された IGameInputDevice::SetLightingColor と IGameInputDevice::ApplyLightingColors を使用して、コントローラーのセンター ライトの色を変更します。デバイスにセンター ライトがない場合、この呼び出しは無視されます。
QueryInterface が失敗した場合、インストールされているランタイムは v4 をサポートしていません。v0 のコードは引き続き動作し、アプリケーションは v4 の機能をスキップできます。
すべてのコードで v4 を使用するようになったら、GameInputV0.h と QueryInterface の呼び出しを削除できます。
以前のライブラリを維持する
GDK に含まれるものなど、以前のリリースのライブラリを引き続きリンクする場合、既存の v0 コードを変更する必要はまったくありません。そのリリースの v0 ヘッダーのインクルードとGameInputCreate の呼び出しをそのまま続けます。この呼び出しはインストールされているランタイムに転送されるため、ランタイムが 4.0 以降の場合、返されるオブジェクトは v4 インターフェイスも実装し、前に示した新しい v4 コードは変更なしで動作します。
以前のライブラリは GameInputInitialize をエクスポートしません。v4 インターフェイスは QueryInterface を呼び出すことによってのみ取得し、GameInputInitialize を呼び出す v4 の GameInputCreate は呼び出さないでください。
バージョン間の切り替えに関する規則
異なる API バージョンのインターフェイスは、IGameInput や IGameInputDevice などの同じ名前を持ちますが、メソッドが異なる別の型です。v0 インターフェイスへのポインターは、両方が同じオブジェクトを参照している場合でも、v4 インターフェイスへのポインターではありません。
キャストは
QueryInterface の呼び出しと同じではありません。別の API バージョンのインターフェイスを取得するには、常に QueryInterface を使用してください。バージョン間の変換に static_cast、reinterpret_cast、または C スタイルのキャストを使用しないでください。キャストはコンパイルされますが、変換されたポインターを介してメソッドを呼び出すと間違ったメソッドが呼び出される可能性があり、未定義の動作につながります。- v0 ヘッダーの後に別の GameInput ヘッダーをインクルードしないでください。 v0 ヘッダーは
GAMEINPUT_E_DEVICE_DISCONNECTEDなどのエラー コードをマクロとして定義しており、これらのマクロにより、その後にインクルードされる GameInput ヘッダーの宣言が壊れます。GameInputV0.hは、最初に最新のヘッダーをインクルードすることでこの規則に従っています。 - 返されるオブジェクトは、呼び出したバージョンを使用します。 たとえば、v4 の読み取りで
GetDeviceを呼び出すと v4 のデバイスが返され、v4 のIGameInputに登録されたデバイス コールバックは v4 のデバイスを受け取ります。これらのオブジェクトを別のバージョンを使用するコードに渡す前に、QueryInterfaceを呼び出してください。 QueryInterfaceを呼び出すたびに参照が追加されます。 他の COM インターフェイス ポインターと同様に、返されたポインターが不要になったら解放してください。- 結果を確認してください。 新しい API バージョンを要求した場合、失敗は、インストールされているランタイムがそのバージョンをサポートしていないことを意味します。
GameInputV0.hの v0 の型は、別個の C++ 型です。GameInput::v0::IGameInputと、<v0/GameInput.h>単体のグローバルなIGameInputは同じインターフェイスを表しますが、C++ ではこれらは異なる型として扱われます。既存のコードや別のライブラリがグローバルな v0 の型で関数を宣言している場合は、<v0/GameInput.h>のみをインクルードするソース ファイルからそれらの関数を呼び出してください。
以前の API バージョンを使用する SDK を呼び出す
一部の SDK、ミドルウェア、およびエンジン プラグインは、特定の GameInput API バージョンに対してビルドされており、そのバージョンの GameInput インターフェイスを想定しています。アプリケーションは、新しいバージョンを使用しながら、これらのコンポーネントを呼び出すことができます。QueryInterface を呼び出してコンポーネントが想定するバージョンを取得し、そのポインターを渡します。
この呼び出しは、コンポーネントが使用するものと同じ GameInput ヘッダーをインクルードするソース ファイルに記述します。次の例では、ThirdPartySdk.h が ThirdPartySdkInitialize(GameInput::v2::IGameInput*) を宣言しており、アプリケーションの残りの部分は GameInput オブジェクトを IUnknown* として渡します。
QueryInterface を呼び出して v4 インターフェイスを取得します。
すべてのバージョンが同じオブジェクトによって実装されているため、SDK とアプリケーションはデバイス、読み取り、および状態を共有します。SDK の API バージョンも、インストールされているランタイムのバージョン以下である必要があります。
関連項目
GameInput API のバージョン管理GameInput NuGet パッケージ
GameInput のサイドロード
GameInputInitialize
GameInput API リファレンス
