これまで何回かwxWidgetsをつかったり、OpenGLのアニメーションを作ったりしてきたが、今回はこれらをまとめ、サブウインドウからOpenGLを制御してみようと思う。
今までの関連記事は以下の通り
- wxWidgetsでWindowsを作ってみる
- wxWidgetsでOpenGLを使ってみる
- wxWidgetsでSubWindowsからMainWindowをコントロールする
- MenuとStatusBarを追加する - wxWidgets
- サブウインドウからメインウインドウをコントロールする(改) - wxWdgets
- wxWidgets+OpenGLアニメーション (やみくも編) - wxWidgets
- wxWidgets+OpenGLアニメーション (タイマー編) - wxWidgets
完成イメージは次のようになる。
コントロール側のウインドウから再生・停止と再生速度を制御できるようにする。基本的に過去に書いてきたことの組み合わせで実現できる。これまで作ってきたGLPanelやControlPanelに制御用の変数を追加し、これらのクラスとMainWindowにコントローラのwidgetからのイベントを処理するイベントハンドラを追加している。
- glpanel.hpp
#ifndef __GLPANEL_HPP__ #define __GLPANEL_HPP__ #include <wx/wx.h> #include <wx/glcanvas/h> #include "opengl.hpp" class GLPanel : public wxGLCanvas { private: bool isInitialized_; bool isPlayable_; int frameRate_; wxTimer* timer_; OpenGL gl_; public: GLPanel(wxWindow* parent, wxGLContext* sharedContext, wxWindowID id, int frameRate); ~GLPanel(); void setPlayable(bool isPlayable); void setFrameRate(int frameRate); void restartTimer(); void OnPaint(wxPaintEvent &event); void OnSize(wxSizeEvent &event); void OnEraseBackground(wxEraseEvent& event); void OnTimer(wxTimerEvent& event); }; #endif //__GLPANEL_HPP__
- glpanel.cpp
#include "glpanel.hpp" GLPanel::GLPanel(wxWindow* parent, wxGLContext* sharedContext, wxWindowID id, int frameRate) : wxGLCanvas(parent, sharedContext, id), isInitialized_(false), frameRate_(frameRate) { this->Connect(wxEVT_SIZE, wxSizeEventHandler(GLPanel::OnSize)); this->Connect(wxEVT_PAINT, wxPaintEventHandler(GLPanel::OnPaint)); this->Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(GLPanel::OnEraseBackground)); this->timer_ = new wxTimer(this); this->Connect(wxEVT_TIMER, wxTimerEventHandler(GLPanel::OnTimer)); this->timer_->Start(frameRate); } GLPanel::~GLPanel() { this->timer_->Stop(); } void GLPanel::setPlayable(bool isPlayable) { this->isPlayable_ = isPlayable; } void GLPanel::setFrameRate(int frameRate) { this->frameRate_ = frameRate; } void GLPanel::restartTimer() { this->timer_->Stop(); this->timer_->Start(this->frameRate_); } void GLPanel::OnPaint(wxPaintEvent &event) { wxPaintDC dc(this); if(!GetContext()){ return; } if(!isInitialized_){ SetCurrent(); gl_.init(); int w; int h; GetClientSize(&w, &h); gl_.setViewport(w, h); isInitialized_=true; } gl_.draw(); glFlush(); SwapBuffers(); } void GLPanel::OnSize(wxSizeEvent &event) { wxGLCanvas::OnSize(event); if(GetContext()) { SetCurrent(); gl_.setViewport(event.GetSize().GetWidth(), event.GetSize().GetHeight()); Refresh(); } } void GLPanel::OnEraseBackground(wxEraseEvent& event) { // Do nothing, to avoid flashing. } void GLPanel::OnTimer(wxTimerEvent& WXUNUSED(event)){ if(this->isPlayable_){ if(GetContext()){ this->SetCurrent(); this->Refresh(); } } }
たとえばGLPanelクラスではisPlayable_変数を追加し、OnTimerで再描画行う際のフラグとしている。また、各変数へアクセスするメンバ関数も用意した。
一方でControlPanelクラスでもイベントハンドラを用意しwidgetからのイベントを処理して、上位widgetに伝播させている。
- ControlPanel::OnPlay, ControlPanle::OnSlide
void ControlPanel::OnPlay(wxCommandEvent & event) { if(this->isPlay_){ event.SetString(wxT("STOP")); this->statusText_->SetLabel(wxT("Status : STOP")); this->button_->SetLabel(wxT("PLAY")); this->isPlay_ = false; }else{ event.SetString(wxT("PLAY")); this->statusText_->SetLabel(wxT("Status : PLAY")); this->button_->SetLabel(wxT("STOP")); this->isPlay_ = true; } event.SetInt(this->isPlay_); event.Skip(); } void ControlPanel::OnSlide(wxCommandEvent & event) { int fps = this->slider_->GetValue(); this->frameRate_ = 1000 / fps; this->sliderText_->SetLabel(wxString::Format(wxT("fps : %d (frame/sec)"), fps)); event.SetInt(this->frameRate_); event.Skip(); }
また、MainWindowクラスでも、それぞれのイベントを扱うイベントハンドラを作成した。
- MainWindow::OnPlay, MainWindow::OnSlide
void MainWindow::OnPlay(wxCommandEvent& event) { this->statusbar_->SetStatusText(event.GetString()); this->glpanel_->setPlayable(event.GetInt()); } void MainWindow::OnSlide(wxCommandEvent& event) { int frameRate = event.GetInt(); this->glpanel_->setFrameRate(frameRate); this->glpanel_->restartTimer(); }
それぞれGLPanelクラスのフレームレートやフラグなど制御用変数を変更している。
全体のソースはこちら→ WxGLAnimationをダウンロード
何を動かしてアニメーションとするかについてはOpenGL内で解決できそうに思うので、wxWidgets+OpenGLという点では、大方のことができるのではないだろうか。
コメント