I'm trying to use QT with Irrlicht and it worked well, but I still having problems to make it work when the screen has a resize event, the screen bugs and show a strange image. I'm not sure if it's a MAC only bug because everything went well sometime ago when I tried on Ubuntu.
I'm sure that it's a stupidy problem, but I'm not finding
QIrrlichWidget.h
Code: Select all
#ifndef QIRRLICHTWIDGET_H
#define QIRRLICHTWIDGET_H
#include <QDebug>
#include <QWidget>
#include <QShowEvent>
#include <QPaintEngine>
#include <QResizeEvent>
#include <QPaintEvent>
#include <QMouseEvent>
#include <irrlicht.h>
#if linux
#include <X11/Xlib.h>
#include <QtGui/QX11Info>
#endif
/*!
* \brief QIrrlichtWidget: Irrlicht Engine Widget
*
* This class can be used to display a Irrlicht 3D Engine powered scene in your Qt
* application.
*/
class QIrrlichtWidget : public QWidget
{
Q_OBJECT
private:
irr::IrrlichtDevice *m_IrrDevice;
irr::video::E_DRIVER_TYPE m_DriverType;
irr::video::SColor m_ClearColor;
int internalTimer;
#if linux
// X11 specific code to disable autorepeat
void setAutoRepeatKeys( bool mode );
#endif
protected:
virtual QPaintEngine * paintEngine() const;
virtual void resizeEvent( QResizeEvent *event );
virtual void paintEvent( QPaintEvent *event );
virtual void timerEvent(QTimerEvent* event);
virtual void mousePressEvent( QMouseEvent *event );
virtual void mouseReleaseEvent( QMouseEvent *event );
virtual void mouseMoveEvent( QMouseEvent *event );
virtual void keyPressEvent( QKeyEvent *event );
virtual void keyReleaseEvent( QKeyEvent *event );
#if linux
virtual void focusInEvent( QFocusEvent *event );
virtual void focusOutEvent( QFocusEvent *event );
#endif
public:
void updateScreen();
void startScreenLoop();
void stopScreenLoop();
/*! \brief Constructor for the Widget. At least you have to specify the parent. Per default OpenGL is used
for the rendering
*/
QIrrlichtWidget( QWidget *parent, irr::video::E_DRIVER_TYPE driverType = irr::video::EDT_OPENGL );
virtual ~QIrrlichtWidget();
/*! \brief Retrieve the Irrlicht Device
\returns The Irrlicht Device used in this Widget
*/
irr::IrrlichtDevice * getIrrlichtDevice();
irr::video::IVideoDriver * getIrrlichtVideo();
/*! \brief Retrieve the Scene Manager
\returns The Scene Manager used in this Widget
*/
irr::scene::ISceneManager * getSceneManager();
/*! \brief Sets the Color used to clear the screen (Background color). Default is a dark gray (0.2 0.2 0.2)
\param color Color (RGB)
*/
void setClearColor( const irr::video::SColorf &color );
/*! \brief Set the aspect ratio of the active camera. Per default this is set to window width / window height every time the widget is resized
\param aspect Aspect Ratio to set
*/
void setAspectRatio( irr::f32 aspect = -1.0f );
/*! \brief Initializes the Irrlicht subsystem. You have to call this after the widget has been created
*/
void initialize();
public slots:
// Function called in response to updateIrrlichtQuery. Renders the scene in the widget
void updateIrrlicht(irr::IrrlichtDevice* device);
signals:
// Signal that its time to update the frame
void updateIrrlichtQuery(irr::IrrlichtDevice* device);
/*! \brief Is emitted whenever the user presses a mouse button */
void mousePress( QMouseEvent *event );
/*! \brief Is emitted whenever the user releases a mouse button */
void mouseRelease( QMouseEvent *event );
/*! \brief Is emitted whenever the user moves the mouse. Mouse Tracking is active per default, call setMouseTracking(bool) to disable this */
void mouseMove( QMouseEvent *event );
/*! \brief Is emitted whenever the user pressed a Key */
void keyPress( QKeyEvent *event );
/*! \brief Is emitted whenever the user releases a Key */
void keyRelease( QKeyEvent *event );
};
#endif // QIRRLICHTWIDGET_H
Code: Select all
#include "QIrrlichtWidget.h"
// ####################################################################
// PRIVATE MEMBERS
// ####################################################################
#if linux
void QIrrlichtWidget::setAutoRepeatKeys( bool mode )
{
qDebug() << "QIrrlichtWidget::setAutoRepeatKeys";
XKeyboardControl control;
control.auto_repeat_mode = ( mode ? 1 : 0 ); // Set mode to 1 for autorepeat, 0 to disable
control.key = -1; // We want to change the behaviour for all keys
XChangeKeyboardControl( QX11Info::display(), KBAutoRepeatMode, &control );
}
#endif
// ####################################################################
// PROTECTED MEMBERS
// ####################################################################
QPaintEngine * QIrrlichtWidget::paintEngine() const
{
qDebug() << "QIrrlichtWidget::paintEngine";
return 0;
}
void QIrrlichtWidget::updateScreen()
{
this->paintEvent( 0 );
}
void QIrrlichtWidget::resizeEvent( QResizeEvent *event )
{
qDebug() << "QIrrlichtWidget::resizeEvent";
if( m_IrrDevice == 0 )
return;
int newWidth = event->size().width();
int newHeight = event->size().height();
m_IrrDevice->getVideoDriver()->OnResize( irr::core::dimension2d<irr::u32>( newWidth, newHeight ));
setAspectRatio();
QWidget::resizeEvent(event);
}
void QIrrlichtWidget::paintEvent( QPaintEvent *event )
{
qDebug() << "QIrrlichtWidget::paintEvent";
emit updateIrrlichtQuery(m_IrrDevice);
}
void QIrrlichtWidget::mousePressEvent( QMouseEvent *event )
{
emit( mousePress( event ));
}
void QIrrlichtWidget::mouseReleaseEvent( QMouseEvent *event )
{
emit( mouseRelease( event ));
}
void QIrrlichtWidget::mouseMoveEvent( QMouseEvent *event )
{
emit( mouseMove( event ));
}
void QIrrlichtWidget::keyPressEvent( QKeyEvent * event )
{
emit( keyPress( event ));
}
void QIrrlichtWidget::keyReleaseEvent( QKeyEvent *event )
{
emit( keyRelease( event ));
}
#if linux
void QIrrlichtWidget::focusInEvent( QFocusEvent *event )
{
setAutoRepeatKeys( false );
}
void QIrrlichtWidget::focusOutEvent( QFocusEvent *event )
{
setAutoRepeatKeys( true );
}
#endif
// ####################################################################
// PUBLIC MEMBERS
// ####################################################################
QIrrlichtWidget::QIrrlichtWidget( QWidget *parent, irr::video::E_DRIVER_TYPE driverType ) : QWidget( parent )
{
qDebug() << "QIrrlichtWidget::ctor()";
setAttribute( Qt::WA_PaintOnScreen, true );
setAttribute( Qt::WA_OpaquePaintEvent, true );
setMouseTracking( true );
setFocusPolicy( Qt::ClickFocus );
setFocus( Qt::OtherFocusReason );
m_IrrDevice = 0;
m_DriverType = driverType;
setClearColor( irr::video::SColorf( 0.2f, 0.2f, 0.2f ));
}
QIrrlichtWidget::~QIrrlichtWidget()
{
qDebug() << "QIrrlichtWidget::dtor()";
if( m_IrrDevice != 0 )
m_IrrDevice->drop();
}
irr::IrrlichtDevice * QIrrlichtWidget::getIrrlichtDevice()
{
qDebug() << "QIrrlichtWidget::getIrrlichtDevice()";
if( m_IrrDevice != 0 )
return m_IrrDevice;
throw( "Irrlicht device has not been initialized");
}
irr::video::IVideoDriver * QIrrlichtWidget::getIrrlichtVideo()
{
qDebug() << "QIrrlichtWidget::getIrrlichtDevice()";
if( m_IrrDevice != 0 )
return m_IrrDevice->getVideoDriver();
throw( "Irrlicht device has not been initialized");
}
irr::scene::ISceneManager * QIrrlichtWidget::getSceneManager()
{
qDebug() << "QIrrlichtWidget::getSceneManager";
if( m_IrrDevice != 0 )
return m_IrrDevice->getSceneManager();
throw( "Irrlicht device has not been initialized" );
}
void QIrrlichtWidget::setClearColor( const irr::video::SColorf &color )
{
m_ClearColor = color.toSColor();
}
void QIrrlichtWidget::setAspectRatio( irr::f32 aspect )
{
qDebug() << "QIrrlichtWidget::setAspectRatio";
if( m_IrrDevice == 0 )
return;
irr::f32 newAspectRatio;
if( aspect < 0 ) // Automatic
{
irr::core::dimension2d<irr::u32> screenSize = m_IrrDevice->getVideoDriver()->getScreenSize();
newAspectRatio = ( irr::f32 ) screenSize.Width / ( irr::f32 ) screenSize.Height;
}
else
newAspectRatio = aspect;
// Set Aspect for active Camera
irr::scene::ISceneManager *mgr = getSceneManager();
mgr->getActiveCamera()->setAspectRatio( newAspectRatio );
}
void QIrrlichtWidget::initialize()
{
qDebug() << "QIrrlichtWidget::init";
if( m_IrrDevice != 0 )
return;
// Create the Irrlicht device if this is the first time we are being shown
irr::SIrrlichtCreationParameters createParams;
createParams.DriverType = m_DriverType;
createParams.WindowSize = irr::core::dimension2d<irr::u32>( size().width(), size().height() );
createParams.EventReceiver = 0;
createParams.Stencilbuffer = true;
createParams.IgnoreInput = true;
// Window ID for creating the native rendering context
createParams.WindowId = ( void * ) winId();
qDebug() << " render size = " << createParams.WindowSize.Width << " x " << createParams.WindowSize.Height;
qDebug() << " native window ID = " << createParams.WindowId;
if(( m_IrrDevice = irr::createDeviceEx( createParams )) == 0 )
throw( "failed to create Irrlicht device" );
connect(this, SIGNAL(updateIrrlichtQuery(irr::IrrlichtDevice*)), this, SLOT(updateIrrlicht(irr::IrrlichtDevice*)));
startScreenLoop();
}
void QIrrlichtWidget::timerEvent(QTimerEvent* event)
{
emit updateIrrlichtQuery(m_IrrDevice);
}
void QIrrlichtWidget::updateIrrlicht( irr::IrrlichtDevice* device )
{
if( device == 0 )
return;
// Draw everything (Scene and GUI)
device->getVideoDriver()->beginScene( true, true, m_ClearColor );
device->getTimer()->tick();
device->getSceneManager()->drawAll();
device->getSceneManager()->getGUIEnvironment()->drawAll();
device->getVideoDriver()->endScene();
}
void QIrrlichtWidget::startScreenLoop()
{
if(internalTimer != 0)
qDebug() << "Timer already started";
// Start a timer. A timer with setting 0 will update as often as possible.
internalTimer = startTimer(0);
}
void QIrrlichtWidget::stopScreenLoop()
{
if(internalTimer == 0)
qDebug() << "Timer already stoped";
killTimer( internalTimer );
internalTimer = 0;
}
Code: Select all
irrWidget = new QIrrlichtWidget(ui->centralWidget);
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setHorizontalStretch(1);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(irrWidget->sizePolicy().hasHeightForWidth());
irrWidget->setSizePolicy(sizePolicy);
ui->splitter_2->addWidget(irrWidget);
show();
irrWidget->initialize();
this->setupScene( irrWidget->getIrrlichtDevice() );

Thanks everyone