Springhead Users Manual

12.6 アプリケーションクラス

Springheadを利用するアプリケーションの作成を容易にするために,アプリケーションクラスFWAppが用意されています. 2.5FWAppを使って簡単なアプリケーションを 作成する方法について説明しましたのでそちらも合わせて参考にしてください.

冒頭で説明した通り,Springheadのほとんどのオブジェクトは,親オブジェクトのCreate系関数を使って作成しますが, FWAppは例外的に,C++のクラス継承を用いてユーザのアプリケーションクラスを定義する方法をとります. この方が 仮想関数によって動作のカスタマイズがフレキシブルに行えるからです.

以下ではFWAppの機能やユーザが実装すべき仮想関数について順に見ていきます.

初期化

FWAppの初期化処理は仮想関数Initで行います.

FWApp

virtual void Init(int argc, char* argv[])

以下にInit関数のデフォルトの実装を示します.

void FWApp::Init(int argc, char* argv[]){
     // create SDK
     CreateSdk();
     // create a single scene
     GetSdk()->CreateScene();
     // initialize window manager
     GRInit(argc, argv);
     // create main window
     CreateWin();
     // create timer
     CreateTimer();
}

はじめに

     CreateSdk();

でSDKを作成します. つぎに

     GRInit(argc, argv);

でウィンドウマネジャが作成されます. デフォルトではGLUTを用いるウィンドウマネジャが作成されます. さらに

     GetSdk()->CreateScene();

FWSceneを1つ作成します. つづいて

     CreateWin();

でメインウィンドウを作成します. 最後に

     CreateTimer();

でタイマを作成します.

この基本処理に追加してなんらかの処理を行う場合は

virtual void Init(int argc = 0, char* argv[] = 0){
        // select GLUI window manager
        SetGRAdaptee(TypeGLUI);


        // call base Init
        FWApp::Init(argc, argv);


        // do extra initialization here



}

のように,FWApp:Initを実行してから追加の処理を行うのが良いでしょう. 一方,以下に挙げるようなカスタマイズが必要な場合はInit関数の処理全体を派生クラスに記述する必要があります.

この場合は,上に載せたInitのデフォルト処理をもとに必要な部分に修正を加えるのが良いでしょう.

プログラムの全体の構造は通常以下のようになります.

MyApp app;


int main(int argc, char* argv[]){
     app.Init(argc, argv);
     app.StartMainLoop();
     return 0;
}

ここでMyAppはユーザが定義したFWAppの派生クラスです(もちろん他の名前でも構いません) . MyAppのインスタンスをグローバル変数として定義し, main関数でInitStartMainLoopを順次実行します. StartMainLoop関数はアプリケーションのメインループを開始します.

タイマ

タイマの作成にはCreateTimer関数を使います. 通常,CreateTimerInitの中で呼びます.

FWApp

UTTimerIf* CreateTimer(UTTimerIf::Mode mode)

引数modeに指定できる値はUTTimerSetModeと同じです. 5.4節を参照してください. 戻り値としてUTTimerのインタフェースが返されます. 周期などの 設定はこのインタフェースを介して行います.

シミュレーション用と描画用に2つのタイマを作成する例を以下に示します.

UTTimerIf *timerSim, *timerDraw;
timerSim = CreateTimer(MULTIMEDIA);
timerSim->SetInterval(10);
timerDraw = CreateTimer(FRAMEWORK);
timerDraw->SetInterval(50);

この例ではシミュレーション用には周期を\( 10 \)[ms]のマルチメディアタイマを使い, 描画用には周期\( 50 \)[ms]のフレームワークタイマ(GLUTタイマ)を使っています.

タイマを始動すると,周期ごとに以下の仮想関数が呼ばれます.

FWApp

virtual void TimerFunc(int id)

タイマの判別は引数\( id \)で行います.

. この振る舞いをカスタマ

TimerFuncのデフォルトの振る舞いでは, カレントウィンドウのシーンのStepを呼び,つぎにPostRedisplayで再描画要求を発行します (その結果,直後にDisplay関数が呼び出されます) イズしたい場合はTimerFunc関数をオーバライドします.

void TimerFunc(int id){
     // proceed simulation of scene attached to current window
     if(id == timerSim->GetID()){
          GetCurrentWin()->GetScene()->Step();
     }
     // generate redisplay request
     else if(id == timerDraw->GetID()){
          PostRedisplay();
     }
}

この例ではシミュレーションと描画に異なる2つのタイマを使用しています.

描画

描画処理は次の仮想関数で行います.

FWApp

virtual void Display()

Displayは描画要求が発行されたときに呼び出されます. 描画要求はPostRedisplay関数で行います.

FWApp

virtual void PostRedisplay()

Display関数のデフォルトの振る舞いではカレントウィンドウのDisplay関数が呼ばれます.

キーボード・マウスイベント

FWAppは各ウィンドウに関連付けられた仮想キーボード・マウスデバイスDVKeyMouseにコールバック登録されています. したがって以下の仮想関数をオーバライドすることでキーボード・マウスイベントを処理できます.

FWApp

virtual bool OnMouse(int button, int state, int x, int y)

virtual bool OnDoubleClick(int button, int x, int y)

virtual bool OnMouseMove(int state, int x, int y, int zdelta)

virtual bool OnKey(int state, int key, int x, int y)

各イベントハンドラの詳細については10.5節を参照して下さい.