Fl_Gl_Windowでのキーボード・マウス入力

Fl_Gl_Windowの派生クラスによるOpenGL描画にキーボード・マウスイベントを処理する関数を追加する.

クラスの宣言

rxFlGLWindowクラスを以下のように変更する.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
class rxFlGLWindow : public Fl_Gl_Window
{
        enum DrawObject
    {
        RX_IDD_VERTEX = 0,            RX_IDD_EDGE,                RX_IDD_FACE,            };
 
    int m_iDraw;                rxTrackball m_tbView;     
public:
        rxFlGLWindow(int x_, int y_, int w_, int h_, const char* l) 
        : Fl_Gl_Window(x_, y_, w_, h_, l)
    {
        m_iDraw = RX_IDD_FACE;
        resizable(this);            end();
    }
 
        virtual ~rxFlGLWindow()
    {
    }
 
public:
    void InitGL(void);
    void Resize(int w, int h);
    void Display(void);
    void Mouse(int button, int state, int x, int y);
    void Motion(int x, int y);
    void PassiveMotion(int x, int y);
    void Keyboard(int key, int x, int y);
 
private:
    void draw(void)
    void resize(int x_, int y_, int w_, int h_);
    int  handle(int ev);
};

キーボード・マウスなどによるイベントを受け取るために,handle関数をオーバーライドしている. そして,GLUTからの移植性を考えて,Mouse,Motion,PassiveMotion,Keyboard関数を追加している. また,マウスにドラッグによる視点の変更を行うためのトラックボールクラス,

rxTrackball m_tbView;

キーボードによる描画の変更のためのフラグ

	enum DrawObject
	{
		RX_IDD_VERTEX = 0,	//!< 頂点描画
		RX_IDD_EDGE,		//!< エッジ描画
		RX_IDD_FACE,		//!< 面描画
	};
	int m_iDraw;			//!< 描画フラグ

をメンバ変数として追加した.

イベントハンドラ

handle関数では様々なFLTKイベントが発生したときに呼ばれる. イベントの種類は引数evで受け取ることができる. 各イベントの詳細は次節以降参照.

OpenGLのためのイベントハンドラの例を以下に示す.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
int rxFlGLWindow::handle(int ev)
{
    switch(ev){
    case FL_PUSH:                Mouse(Fl::event_button(), 1, Fl::event_x(), Fl::event_y());
        break;
    case FL_RELEASE:            Mouse(Fl::event_button(), 0, Fl::event_x(), Fl::event_y());
        break;
    case FL_DRAG:                Motion(Fl::event_x(), Fl::event_y());
        break;
    case FL_MOVE:                PassiveMotion(Fl::event_x(), Fl::event_y());
        break;
 
    case FL_KEYDOWN:            Keyboard(Fl::event_key(), Fl::event_x(), Fl::event_y());
        break;
    case FL_KEYUP:            case FL_SHORTCUT:            break;
 
    case FL_FOCUS:            case FL_UNFOCUS:
        break;
 
    default:
        return Fl_Window::handle(ev);
    }
    return 1;
}

FLTKは直近のイベントに関する情報を変数に記憶しておく.これらの変数の値を参照するのが, Fl::event_x(), Fl::event_y(), Fl::event_button()Fl::event_key()などである. これらFl::event_*()関数を使って,様々な値を実際に処理を行う関数に渡している. 各イベントの詳細は以下参照.

マウスイベント

イベントIDイベント発行タイミング関連する関数
FL_PUSHマウスボタンが押されたときFl::event_x()
Fl::event_y()
Fl::event_button()
FL_RELEASEマウスボタンが離されたとき同上
FL_DRAGマウスドラッグ(ボタンを押したまま移動)したときFl::event_x()
Fl::event_y()
Fl::event_state()
FL_MOVEマウスボタンを押さずにマウスを移動したとき同上
FL_MOUSEWHEELマウスホイールを回したときFl::event_dx()
Fl::event_dy()

rxFlGLWindowクラスにおいて,これらのイベントを処理する関数の例を以下に示す.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
void Mouse(int button, int state, int x, int y)
{
    make_current();
    int keymod = (Fl::event_state(FL_SHIFT) ? 2 : (Fl::event_state(FL_CTRL) ? 3 : 1));
    if(button == FL_LEFT_MOUSE){
        if(state){
            m_tbView.Start(x, y, keymod);
        }
        else{
            m_tbView.Stop(x, y);
        }
    }
    else if(button == FL_MIDDLE_MOUSE){
    }
    else if(button == FL_RIGHT_MOUSE){
    }
    redraw();
}
 
void Motion(int x, int y)
{
    make_current();
    m_tbView.Motion(x, y);
    redraw();
}
 
void PassiveMotion(int x, int y)
{
}

マウスボタンの状態はFL_*_MOUSEという名前で定義されている. m_tbView.Start()はトラックボールでの回転・平行移動・ズームをスタートする. 第三引数の値が1で回転,2で平行移動(視線に垂直な方向に平行移動),3でズーム(視線方向に平行移動)である. ドラッグ中に呼ばれるMotion関数内で,m_tbView.Motion()により視点回転・移動処理を行い, マウスボタンが放されたら m_tbView.Stop()で処理を終了している.

キーボードイベント

イベントIDイベント発行タイミング関連する関数
FL_KEYDOWNキーボードダウン.ウィジットにフォーカスがあるときに使われる.Fl::event_key()(ASCIIコード)
Fl::event_text()(文字列 - char*)
Fl::event_length()(文字列の長さ)
FL_KEYBOARDFL_KEYDOWNと同じ同上
FL_KEYUPキーボードアップ.ウィジットにフォーカスがあるときに使われる.同上
FL_SHORTCUTグローバルショートカット.どのウィジットにもフォーカスがなかったときに発行される.同上

rxFlGLWindowクラスにおいて,これらのイベントを処理する関数の例を以下に示す.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
void Keyboard(int key, int x, int y)
{
        cout << "Keyboard" << endl;
    make_current();
    switch(key){
    case FL_Left:
        m_iDraw = (m_iDraw == RX_IDD_VERTEX ? RX_IDD_FACE : m_iDraw-1);
        break;
    case FL_Right:
        m_iDraw = (m_iDraw == RX_IDD_FACE ? RX_IDD_VERTEX : m_iDraw+1);
        break;
 
    case 'v':
        m_iDraw = RX_IDD_VERTEX;
        break;
    case 'e':
        m_iDraw = RX_IDD_EDGE;
        break;
    case 'f':
        m_iDraw = RX_IDD_FACE;
        break;
    }
    redraw();
}

Keyboard関数では頂点,エッジ,面描画を切り替える. 矢印左右でこれらの描画を順次切り替え, キー"V","E","F"で直接それぞれの描画を設定する.

ウィンドウフォーカスイベント

イベントIDイベント発行タイミング関連する関数
FL_ENTERマウスポインタがウィジット上に来たとき-
FL_LEAVEマウスポインタがウィジット上から外れたとき-
FL_FOCUSウィジットにキーボードフォーカスが来たとき-
FL_UNFOCUSウィジットからキーボードフォーカスが外れたとき-

ウィジットイベント

イベントIDイベント発行タイミング関連する関数
FL_ACTIVATEウィジットがアクティブになった(activate()が呼ばれた)とき-
FL_DEACTIVATEウィジットがアクティブでなくなった(deactivate()が呼ばれた)とき-
FL_SHOWshow()が呼ばれてウィンドウが可視化されたとき-
FL_HIDEhide()が呼ばれてウィンドウが不可視化されたとき-

クリップボードイベント

イベントIDイベント発行タイミング関連する関数
FL_PASTEFl::event_text()(文字列 - char*)
Fl::event_length()(文字列の長さ)
FL_SELECTIONCLEAR

D&Dイベント

FLTKはファイルやテキストのD&Dに対応している. テキストはUFT8エンコードで送られ,ファイルはフルパスのリストとして送られる. これらは上記FL_PASTEイベント後, Fl::event_text()(文字列 - char*),Fl::event_length()(文字列の長さ) を参照することでその情報が得られる.

イベントIDイベント発行タイミング関連する関数
FL_DND_ENTERドラッグしたマウスポインタがウィジット上に来たとき-
FL_DND_DRAGドラッグ中に呼ばれる-
FL_DND_LEAVEドラッグしたマウスポインタがウィジット上から外れたとき-
FL_DND_RELEASEマウスボタンをリリースして,ファイルやテキストをドロップしたとき.この後すぐにFL_PASTEが呼ばれる-

ソースコード

上記例のソースコードは以下(Viual Studio 2010用プロジェクトファイル含む).

実行結果は以下.

fltk_opengl_window3.jpg

添付ファイル: filefltk_opengl_window3.jpg 1632件 [詳細] filefltk_simple_opengl2.zip 1400件 [詳細]

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2022-11-30 (水) 13:48:07