----
#contents
----

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

***クラスの宣言 [#o82273b4]
rxFlGLWindowクラスを以下のように変更する.
#code(C){{
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:http://www.fltk.org/doc-1.3/classFl__Window.html#a9c0eb1c55a1a62ef3d3d87676f936187]]関数をオーバーライドしている.
そして,GLUTからの移植性を考えて,Mouse,Motion,PassiveMotion,Keyboard関数を追加している.
また,マウスにドラッグによる視点の変更を行うためのトラックボールクラス,
キーボードによる描画の変更のためのフラグをメンバ変数として追加した.
 rxTrackball m_tbView;
キーボードによる描画の変更のためのフラグ
 	enum DrawObject
	{
		RX_IDD_VERTEX = 0,	//!< 頂点描画
		RX_IDD_EDGE,		//!< エッジ描画
		RX_IDD_FACE,		//!< 面描画
	};
	int m_iDraw;			//!< 描画フラグ
をメンバ変数として追加した.


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

OpenGLのためのイベントハンドラの例を以下に示す.
#code(C){{
//! イベントハンドラ
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:	// キーダウン(FL_KEYBOARDでもOK)
		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():http://www.fltk.org/doc-1.3/group__fl__events.html#ga91585fcbaa1e79f7452fd2d16a82136e]],
[[Fl::event_y():http://www.fltk.org/doc-1.3/group__fl__events.html#ga192a0c5a37f33b9d117a69f20977c2a1]],
[[Fl::event_button():http://www.fltk.org/doc-1.3/group__fl__events.html#ga7ae6d99ceb1a2afb8a1dc4455ac941cd]]や
[[Fl::event_key():http://www.fltk.org/doc-1.3/group__fl__events.html#ga1ac131e3cd5ca674cc022b1f77233449]]などである.
これら[[Fl::event_*():http://www.fltk.org/doc-1.3/events.html#events_event_xxx]]関数を使って,様々な値を実際に処理を行う関数に渡している.
各イベントの詳細は以下参照.


***マウスイベント [#r4c1f536]
|イベントID|イベント発行タイミング|関連する関数|h
|FL_PUSH| マウスボタンが押されたとき | [[Fl::event_x():http://www.fltk.org/doc-1.3/group__fl__events.html#ga91585fcbaa1e79f7452fd2d16a82136e]]&br;[[Fl::event_y():http://www.fltk.org/doc-1.3/group__fl__events.html#ga192a0c5a37f33b9d117a69f20977c2a1]]&br;[[Fl::event_button():http://www.fltk.org/doc-1.3/group__fl__events.html#ga7ae6d99ceb1a2afb8a1dc4455ac941cd]] |
|FL_RELEASE| マウスボタンが離されたとき | 同上 |
|FL_DRAG| マウスドラッグ(ボタンを押したまま移動)したとき | [[Fl::event_x():http://www.fltk.org/doc-1.3/group__fl__events.html#ga91585fcbaa1e79f7452fd2d16a82136e]]&br;[[Fl::event_y():http://www.fltk.org/doc-1.3/group__fl__events.html#ga192a0c5a37f33b9d117a69f20977c2a1]]&br;[[Fl::event_state():http://www.fltk.org/doc-1.3/group__fl__events.html#gafa17a5b4d8d9163631c88142e60447ed]] |
|FL_MOVE| マウスボタンを押さずにマウスを移動したとき | 同上 |
|FL_MOUSEWHEEL| マウスホイールを回したとき | [[Fl::event_dx():http://www.fltk.org/doc-1.3/group__fl__events.html#gadd50231ad95aaf23a23e9db42cccb42e]]&br;[[Fl::event_dy():http://www.fltk.org/doc-1.3/group__fl__events.html#ga4704bd4e93b6471321d6ac84b0df97e5]] |

rxFlGLWindowクラスにおいて,これらのイベントを処理する関数の例を以下に示す.
#code(C){{
//! マウスイベント処理関数
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)
{
}
}}
sss
マウスボタンの状態はFL_*_MOUSEという名前で定義されている.
m_tbView.Start()はトラックボールでの回転・平行移動・ズームをスタートする.
第三引数の値が1で回転,2で平行移動(視線に垂直な方向に平行移動),3でズーム(視線方向に平行移動)である.
ドラッグ中に呼ばれるMotion関数内で,m_tbView.Motion()により視点回転・移動処理を行い,
マウスボタンが放されたら m_tbView.Stop()で処理を終了している.


***キーボードイベント [#b8f1503c]
|イベントID|イベント発行タイミング|関連する関数|h
|FL_KEYDOWN| キーボードダウン.ウィジットにフォーカスがあるときに使われる. | [[Fl::event_key():http://www.fltk.org/doc-1.3/group__fl__events.html#ga1ac131e3cd5ca674cc022b1f77233449]](ASCIIコード)&br;[[Fl::event_text():http://www.fltk.org/doc-1.3/group__fl__events.html#ga6647c55948fe1d8be9367267529e9c54]](文字列 - char*)&br;[[Fl::event_length():http://www.fltk.org/doc-1.3/group__fl__events.html#ga38f2de89fbdf59ad2cd4dca93f472911]](文字列の長さ) |
|FL_KEYBOARD| FL_KEYDOWNと同じ | 同上 |
|FL_KEYUP| キーボードアップ.ウィジットにフォーカスがあるときに使われる. | 同上 |
|FL_SHORTCUT| グローバルショートカット.どのウィジットにもフォーカスがなかったときに発行される. | 同上 |


rxFlGLWindowクラスにおいて,これらのイベントを処理する関数の例を以下に示す.
#code(C){{
//! キーボードイベント処理関数
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"で直接それぞれの描画を設定する.


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


***ウィジットイベント [#v1502f56]
|イベントID|イベント発行タイミング|関連する関数|h
|FL_ACTIVATE| ウィジットがアクティブになった([[activate():http://www.fltk.org/doc-1.3/classFl__Widget.html#ae0ca5f7159aceba7d813c81167e684bb]]が呼ばれた)とき | - |
|FL_DEACTIVATE| ウィジットがアクティブでなくなった([[deactivate():http://www.fltk.org/doc-1.3/classFl__Widget.html#a2eb3d2eebe8ba623c4007d4f8e66a1ee]]が呼ばれた)とき | - |
|FL_SHOW| [[show():http://www.fltk.org/doc-1.3/classFl__Widget.html#ab572c6fbc922bf3268b72cf9e2939606]]が呼ばれてウィンドウが可視化されたとき | - |
|FL_HIDE| [[hide():http://www.fltk.org/doc-1.3/classFl__Widget.html#a1fe8405b86da29d147dc3b5841cf181c]]が呼ばれてウィンドウが不可視化されたとき | - |


***クリップボードイベント [#a775852c]
|イベントID|イベント発行タイミング|関連する関数|h
|FL_PASTE| | [[Fl::event_text():http://www.fltk.org/doc-1.3/group__fl__events.html#ga6647c55948fe1d8be9367267529e9c54]](文字列 - char*)&br;[[Fl::event_length():http://www.fltk.org/doc-1.3/group__fl__events.html#ga38f2de89fbdf59ad2cd4dca93f472911]](文字列の長さ) |
|FL_SELECTIONCLEAR|  |  |


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

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




***ソースコード [#qbaaa04e]
上記例のソースコードは以下(Viual Studio 2010用プロジェクトファイル含む).
#ref(fltk_simple_opengl2.zip)

実行結果は以下.
#ref(fltk_opengl_window3.jpg,,50%)

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS