Problem with OnResize and QT

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
jcfalcone
Posts: 37
Joined: Wed Nov 28, 2007 10:04 pm

Problem with OnResize and QT

Post by jcfalcone »

Hello everyone

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
 
 
QIrrlichWidget.cpp

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;
}
 
And I call It in this way:

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() );
 
I'm using QT5 with Irrlicht 1.8 on MAC 10.8.3, follow the image:
Image

Thanks everyone
serengeor
Posts: 1712
Joined: Tue Jan 13, 2009 7:34 pm
Location: Lithuania

Re: Problem with OnResize and QT

Post by serengeor »

just a guess, maybe you have to set the viewport?
http://irrlicht.sourceforge.net/docu/cl ... e4baa78a08
Working on game: Marrbles (Currently stopped).
jcfalcone
Posts: 37
Joined: Wed Nov 28, 2007 10:04 pm

Re: Problem with OnResize and QT

Post by jcfalcone »

serengeor wrote:just a guess, maybe you have to set the viewport?
http://irrlicht.sourceforge.net/docu/cl ... e4baa78a08
I changed to it and nothing happened:

Code: Select all

 
void QIrrlichtWidget::resizeEvent( QResizeEvent *event )
{
    qDebug() << "QIrrlichtWidget::resizeEvent";
 
    if( m_IrrDevice == 0 )
        return;
 
    int newWidth = event->size().width();
    int newHeight = event->size().height();
 
    qDebug() << newWidth << newHeight;
 
     m_IrrDevice->getVideoDriver()->OnResize( irr::core::dimension2d<irr::u32>( newWidth, newHeight ));
 
     m_IrrDevice->getVideoDriver()->setViewPort(irr::core::rect<irr::s32>(0,0,newWidth,newHeight));
 
    setAspectRatio();
 
    QWidget::resizeEvent(event);
}
 
smso
Posts: 246
Joined: Fri Jun 04, 2010 3:28 pm
Location: Hong Kong

Re: Problem with OnResize and QT

Post by smso »

In the member function:

Code: Select all

void QIrrlichtWidget::resizeEvent(QResizeEvent *event)
Try adding:

Code: Select all

emit resized(event);

Code: Select all

void QIrrlichtWidget::resizeEvent(QResizeEvent *event)
{
    ...
    QWidget::resizeEvent(event);
    emit resized(event);
}
Regards,
smso
jcfalcone
Posts: 37
Joined: Wed Nov 28, 2007 10:04 pm

Re: Problem with OnResize and QT

Post by jcfalcone »

Are you sure about the signal?

QWidget just have a resize function, not a signal.

Code: Select all

 
error: use of undeclared identifier 'resized'; did you mean 'resize'?
    emit resized(event);
         ^~~~~~~
         resize
 
smso
Posts: 246
Joined: Fri Jun 04, 2010 3:28 pm
Location: Hong Kong

Re: Problem with OnResize and QT

Post by smso »

Sorry it's my fault:

You should also a line in the file: QIrrlichWidget.h

Code: Select all

class QIrrlichtWidget : public QWidget
{
    Q_OBJECT
    
    public:
        
    ....
        
    signals:
        void resized(QResizeEvent *event);
    ....
 
Reqards,
smso
jcfalcone
Posts: 37
Joined: Wed Nov 28, 2007 10:04 pm

Re: Problem with OnResize and QT

Post by jcfalcone »

Nothing happened.

I need to connect that signal to something?
smso
Posts: 246
Joined: Fri Jun 04, 2010 3:28 pm
Location: Hong Kong

Re: Problem with OnResize and QT

Post by smso »

This is the ctor of my QIrrlichtWidget:

Code: Select all

QIrrlichtWidget::QIrrlichtWidget(QWidget *parent)
:   QWidget(parent),
    device(0),
    smgr(0),
    driver(0),
    camera(0)
{
    setAttribute(Qt::WA_OpaquePaintEvent);
    setAttribute(Qt::WA_PaintOnScreen);
    setAttribute(Qt::WA_NoBackground);
    setAttribute(Qt::WA_NoSystemBackground);
    
    
    setFocusPolicy(Qt::ClickFocus);
    setFocus(Qt::OtherFocusReason);
    setAutoFillBackground(false);
    
    
    setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
    
    this->setMouseTracking(true);       
    
}
Maybe this helps.

Regards,
smso
Post Reply