00001 #include "wx_ogre_render_window.h"
00002 #include "orthographic.h"
00003
00004 #include <OGRE/OgreRoot.h>
00005 #include <OGRE/OgreViewport.h>
00006 #include <OGRE/OgreCamera.h>
00007 #include <OGRE/OgreRenderWindow.h>
00008 #include <OGRE/OgreStringConverter.h>
00009
00010 #ifdef __WXGTK__
00011 #include <gdk/gdk.h>
00012 #include <gtk/gtk.h>
00013 #include <gdk/gdkx.h>
00014 #include <wx/gtk/win_gtk.h>
00015 #include <GL/glx.h>
00016 #endif
00017
00018 #include <ros/console.h>
00019 #include <ros/assert.h>
00020
00021 namespace ogre_tools
00022 {
00023
00024 IMPLEMENT_CLASS (wxOgreRenderWindow, wxControl)
00025
00026 BEGIN_EVENT_TABLE (wxOgreRenderWindow, wxControl)
00027 EVT_PAINT (wxOgreRenderWindow::onPaint)
00028 EVT_SIZE (wxOgreRenderWindow::onSize)
00029 EVT_MOUSE_EVENTS (wxOgreRenderWindow::onMouseEvents)
00030 EVT_MOVE(wxOgreRenderWindow::onMove)
00031 END_EVENT_TABLE ()
00032
00033
00034 unsigned int wxOgreRenderWindow::sm_NextRenderWindowId = 1;
00035
00036 wxOgreRenderWindow::wxOgreRenderWindow (Ogre::Root* ogre_root, wxWindow *parent, wxWindowID id,
00037 const wxPoint &pos, const wxSize &size, long style, const wxValidator &validator, bool create_render_window)
00038 : wxControl( parent, id, pos, size, style, validator )
00039 , render_window_( 0 )
00040 , ogre_root_( ogre_root )
00041 , ortho_scale_( 1.0f )
00042 , auto_render_(true)
00043 {
00044 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
00045
00046 if (create_render_window)
00047 {
00048 createRenderWindow();
00049 }
00050 }
00051
00052
00053 wxOgreRenderWindow::~wxOgreRenderWindow ()
00054 {
00055 if (render_window_)
00056 {
00057 render_window_->removeViewport( 0 );
00058 render_window_->destroy();
00059 ogre_root_->detachRenderTarget(render_window_);
00060 }
00061
00062 render_window_ = 0;
00063 }
00064
00065
00066 inline wxSize wxOgreRenderWindow::DoGetBestSize () const
00067 {
00068 return wxSize (320, 240);
00069 }
00070
00071 Ogre::RenderWindow* wxOgreRenderWindow::getRenderWindow () const
00072 {
00073 return render_window_;
00074 }
00075
00076
00077 Ogre::Viewport* wxOgreRenderWindow::getViewport () const
00078 {
00079 return viewport_;
00080 }
00081
00082 void wxOgreRenderWindow::setCamera( Ogre::Camera* camera )
00083 {
00084 viewport_->setCamera( camera );
00085
00086 setCameraAspectRatio();
00087
00088 Refresh();
00089 }
00090
00091 void wxOgreRenderWindow::setCameraAspectRatio()
00092 {
00093 Ogre::Camera* camera = viewport_->getCamera();
00094 if ( camera )
00095 {
00096 int width;
00097 int height;
00098 GetSize( &width, &height );
00099
00100 camera->setAspectRatio( Ogre::Real( width ) / Ogre::Real( height ) );
00101
00102 if ( camera->getProjectionType() == Ogre::PT_ORTHOGRAPHIC )
00103 {
00104 Ogre::Matrix4 proj;
00105 buildScaledOrthoMatrix( proj, -width / ortho_scale_ / 2, width / ortho_scale_ / 2, -height / ortho_scale_ / 2, height / ortho_scale_ / 2,
00106 camera->getNearClipDistance(), camera->getFarClipDistance() );
00107 camera->setCustomProjectionMatrix(true, proj);
00108 }
00109 }
00110 }
00111
00112 void wxOgreRenderWindow::setOrthoScale( float scale )
00113 {
00114 ortho_scale_ = scale;
00115
00116 setCameraAspectRatio();
00117 }
00118
00119 void wxOgreRenderWindow::setPreRenderCallback( boost::function<void ()> func )
00120 {
00121 pre_render_callback_ = func;
00122 }
00123
00124 void wxOgreRenderWindow::setPostRenderCallback( boost::function<void ()> func )
00125 {
00126 post_render_callback_ = func;
00127 }
00128
00129
00130 void wxOgreRenderWindow::onPaint (wxPaintEvent &evt)
00131 {
00132 evt.Skip();
00133
00134 if (auto_render_)
00135 {
00136 if ( pre_render_callback_ )
00137 {
00138 pre_render_callback_();
00139 }
00140
00141 if( ogre_root_->_fireFrameStarted() )
00142 {
00143 #if (OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 6)
00144 ogre_root_->_fireFrameRenderingQueued();
00145 #endif
00146
00147 render_window_->update();
00148
00149 ogre_root_->_fireFrameEnded();
00150 }
00151
00152 if ( post_render_callback_ )
00153 {
00154 post_render_callback_();
00155 }
00156 }
00157 }
00158
00159
00160 void wxOgreRenderWindow::onSize (wxSizeEvent &evt)
00161 {
00162 int width;
00163 int height;
00164 wxSize size = evt.GetSize ();
00165 width = size.GetWidth ();
00166 height = size.GetHeight ();
00167
00168 if (render_window_)
00169 {
00170 #if !defined(__WXMAC__)
00171 render_window_->resize (width, height);
00172 #endif
00173
00174 render_window_->windowMovedOrResized ();
00175
00176 setCameraAspectRatio();
00177
00178 if (auto_render_)
00179 {
00180 Refresh();
00181 }
00182 }
00183
00184 evt.Skip();
00185 }
00186
00187 void wxOgreRenderWindow::onMove(wxMoveEvent& evt)
00188 {
00189 evt.Skip();
00190
00191 if (render_window_)
00192 {
00193
00194 }
00195
00196 ROS_INFO("move");
00197 }
00198
00199
00200 void wxOgreRenderWindow::onMouseEvents (wxMouseEvent &evt)
00201 {
00202 evt.Skip();
00203 }
00204
00205 void wxOgreRenderWindow::createRenderWindow ()
00206 {
00207 Ogre::NameValuePairList params;
00208 #if defined(__WXMAC__)
00209 params["externalWindowHandle"] = getOgreHandle();
00210 #else
00211 params["parentWindowHandle"] = getOgreHandle();
00212 #endif
00213
00214
00215 int width;
00216 int height;
00217 GetSize (&width, &height);
00218
00219 #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
00220 ogre_root_->getRenderSystem()->setConfigOption("RTT Preferred Mode", "PBuffer");
00221 #endif
00222
00223
00224 render_window_ = ogre_root_->createRenderWindow (
00225 Ogre::String ("OgreRenderWindow") + Ogre::StringConverter::toString (sm_NextRenderWindowId++),
00226 width, height, false, ¶ms);
00227
00228 render_window_->setActive (true);
00229 render_window_->setVisible(true);
00230 render_window_->setAutoUpdated(true);
00231
00232 viewport_ = render_window_->addViewport( NULL );
00233 }
00234
00235 std::string wxOgreRenderWindow::getOgreHandle () const
00236 {
00237 std::string handle;
00238
00239 #ifdef __WXMSW__
00240
00241 handle = Ogre::StringConverter::toString((size_t)((HWND)GetHandle()));
00242 #elif defined(__WXGTK__)
00243
00244 std::stringstream str;
00245 GtkWidget* widget = m_wxwindow;
00246 gtk_widget_set_double_buffered (widget, FALSE);
00247 if (!GTK_WIDGET_REALIZED(widget))
00248 {
00249 gtk_widget_realize( widget );
00250 }
00251
00252
00253 GtkPizza* pizza = GTK_PIZZA(widget);
00254 GdkWindow* gdkWin = pizza->bin_window;
00255 Window wid = GDK_WINDOW_XWINDOW(gdkWin);
00256
00257 XSync(GDK_WINDOW_XDISPLAY(widget->window), False);
00258 XSync(GDK_WINDOW_XDISPLAY(pizza->bin_window), False);
00259
00260 str << wid;
00261 handle = str.str();
00262 #elif defined(__WXMAC__)
00263 handle = Ogre::StringConverter::toString((size_t)(GetHandle()));
00264 #else
00265
00266 #error("Not supported on this platform.")
00267 #endif
00268
00269 return handle;
00270 }
00271
00272 bool wxOgreRenderWindow::Reparent(wxWindowBase* new_parent)
00273 {
00274
00275
00276
00277
00278
00279
00280
00281
00282 #if defined(__WXGTK__)
00283 Window win;
00284 Display* disp;
00285
00286 if (render_window_)
00287 {
00288 render_window_->getCustomAttribute("WINDOW", &win);
00289 render_window_->getCustomAttribute("XDISPLAY", &disp);
00290
00291 wxWindow* top = wxTheApp->GetTopWindow();
00292 GtkPizza* pizza = GTK_PIZZA(top->m_wxwindow);
00293 Window parent = GDK_WINDOW_XWINDOW(pizza->bin_window);
00294
00295 XSync(disp, False);
00296 XReparentWindow(disp, win, parent, 0, 0);
00297 XSync(disp, False);
00298 }
00299 #endif
00300
00301 bool ret = wxControl::Reparent(new_parent);
00302
00303 #if defined(__WXGTK__)
00304 if (render_window_)
00305 {
00306 XSync(disp, False);
00307
00308 gtk_widget_set_double_buffered(m_wxwindow, FALSE);
00309 if (!GTK_WIDGET_REALIZED(m_wxwindow))
00310 {
00311 gtk_widget_realize(m_wxwindow);
00312 }
00313
00314 GtkPizza* pizza = GTK_PIZZA(m_wxwindow);
00315
00316 XSync(GDK_WINDOW_XDISPLAY(m_wxwindow->window), False);
00317 XSync(GDK_WINDOW_XDISPLAY(pizza->bin_window), False);
00318
00319 GdkWindow* gdkWin = pizza->bin_window;
00320 Window parent = GDK_WINDOW_XWINDOW(gdkWin);
00321 XReparentWindow(disp, win, parent, 0, 0);
00322
00323
00324
00325 XMapWindow(disp, win);
00326
00327 XSync(disp, False);
00328 }
00329 #endif
00330
00331 return ret;
00332 }
00333
00334 }