Irrlicht embedded in a wxWidgets control

A forum to store posts deemed exceptionally wise and useful
mandrav
Posts: 117
Joined: Sat Aug 27, 2005 8:29 pm
Contact:

Irrlicht embedded in a wxWidgets control

Post by mandrav »

Seeing that many people are asking how to embed Irrlicht in a wxWidgets control (especially for wxGTK), I decided to make such a control (which I had already written) available to the public.

Grab it here.
Make sure to read the README contained in the archive.
Also, the source file contains doxygen-compatible documentation comments so you can run it through doxygen and get a nice documentation about it :).

If a mod believes this post is in the wrong forum, feel free to move it.

Enjoy,
Yiannis.
Eternl Knight
Posts: 313
Joined: Tue Nov 01, 2005 5:01 am

Post by Eternl Knight »

This officially makes you my second favourite person today (fav is my wife who convinced my boys to buy me a Playstation 2 for Father's Day :) ).

This works for Linux & Windows or just Windows?

EDIT: It works for both, provided one is using wxGTK. This should make things a little easier to port :) Thanks

--EK
kornerr
Posts: 245
Joined: Thu Jul 06, 2006 9:57 am
Location: Russia, Siberia, Kemerovo
Contact:

Post by kornerr »

I get segfault:

Code: Select all

(test:3084): Gdk-WARNING **: gdkdrawable-x11.c:971 drawable is not a pixmap or window
Segmentation fault

Code: Select all

- - - -
Panel::Panel (wxFrame *parent, wxWindowID id, wxSize size):
    wxPanel (parent, id, wxDefaultPosition, size, wxTAB_TRAVERSAL) {
    SIrrlichtCreationParameters param;
    wxStaticText *pnl = new wxStaticText (this, -1, wxEmptyString);
    pnl->SetBackgroundStyle (wxBG_STYLE_CUSTOM);
    GtkWidget *handle = pnl->GetHandle ();
    if (!handle)
        cout << "no handle\n";
    //GtkWidget *handle = this->GetHandle ();
    XID handle_id = GDK_WINDOW_XWINDOW (handle->window);
    Display *display = GDK_WINDOW_XDISPLAY (handle->window);
    core::stringc win_desc = (int)display;
    win_desc += ':';
    win_desc += (int)handle_id;
    param.WindowId = (long)win_desc.c_str ();
    param.DriverType = EDT_OPENGL;
    param.WindowSize = core::dimension2d<s32> (400, 300);
    dev = createDeviceEx (param);
    smgr = dev->getSceneManager ();
    drv = dev->getVideoDriver ();
    smgr->addCameraSceneNodeFPS (0, 10, 10);
    ISceneNode *cube = smgr->addCubeSceneNode (1);
    cube->setMaterialFlag (EMF_LIGHTING, false);
    cube->setMaterialTexture (0, drv->getTexture ("media/rockwall.bmp"));
}
- - - -
And this:

Code: Select all

core::stringc dName = (long)mDisp;
doesn't work at all, becauss Irr can't create strings from longs.

What am I doing wrong?
Thanks.

PS: Can you provide a full workable demo?
Open Source all the way, baby ;)
OSRPG
mandrav
Posts: 117
Joined: Sat Aug 27, 2005 8:29 pm
Contact:

Post by mandrav »

I get segfault:
I don't :).
Seriously, this code has been tested on linux. As a matter of fact I had already pointed you to one of my posts where there's a screenshot of an editor using this under linux.

Anyone else who tried it and gets segfaults?
And this:

Code: Select all

core::stringc dName = (long)mDisp;
doesn't work at all, becauss Irr can't create strings from longs.
Do you really think so?
Here's one of the irr::core::string constructors:

Code: Select all

	//! Constructs a string from an int
	string(int number)
        {
        ...
        {
kornerr
Posts: 245
Joined: Thu Jul 06, 2006 9:57 am
Location: Russia, Siberia, Kemerovo
Contact:

Post by kornerr »

int != long int.
See:

Code: Select all

kornerr@kornerr:~/cpp/irr/wx$ make
g++ -o test editor.cpp `wx-config --cxxflags`  -I"/usr/X11/include" -I"/usr/local/include/irrlicht" -g -Wall -I"/usr/include/gtk-2.0" -I"/usr/include/glib-2.0" -I"/usr/lib/glib-2.0/include" -I"/usr/include/pango-1.0" -I"/usr/lib/gtk-2.0/include" -I"/usr/include/atk-1.0" `wx-config --libs` -L"/usr/X11/lib" -L"/usr/local/lib" -lIrrlicht -lGL -lGLU -lXxf86vm -lXext -lX11
editor.cpp: In constructor `Panel::Panel(wxFrame*, int, wxSize)':
editor.cpp:56: error: conversion from `long int' to `irr::core::string<c8,
   irr::core::irrAllocator<c8> >' is ambiguous
/usr/local/include/irrlicht/irrString.h:62: error: candidates are:
   irr::core::string<T, TAlloc>::string(int) [with T = c8, TAlloc =
   irr::core::irrAllocator<c8>]
/usr/local/include/irrlicht/irrString.h:53: error:
   irr::core::string<T, TAlloc>::string(double) [with T = c8, TAlloc =
   irr::core::irrAllocator<c8>]
make: *** [test] Error 1
Which distro do you use? (mine is Slackware10.2)
Thanks.
Open Source all the way, baby ;)
OSRPG
mandrav
Posts: 117
Joined: Sat Aug 27, 2005 8:29 pm
Contact:

Post by mandrav »

int != long int
I know it's not :? . Especially on my AMD64 where I created and used this component.

Anyway, maybe something has changed in Irrlicht? Let me check again because back when I created it I was using 0.14 and it compiled and worked fine.
kornerr
Posts: 245
Joined: Thu Jul 06, 2006 9:57 am
Location: Russia, Siberia, Kemerovo
Contact:

Post by kornerr »

Don't forget to tell me what distro you use.
Open Source all the way, baby ;)
OSRPG
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, I've added the double to string conversion. Now several types are not automatically recognized anymore. Cast numbers either to int or double.
mandrav
Posts: 117
Joined: Sat Aug 27, 2005 8:29 pm
Contact:

Post by mandrav »

hybrid wrote:Cast numbers either to int or double.
I see. The point is that int!=long in AMD64 systems so it's not going to cut it...
Is it possible to add the long conversion too?
jonasrf
Posts: 25
Joined: Fri Jan 13, 2006 6:18 am
Contact:

Post by jonasrf »

kornerr wrote: PS: Can you provide a full workable demo?
That would be great if you could. I must be a total idiot but I couldn't figure out what you ment in the readme file. Do I stick this in a panel, or were? If so could you tell me how to do that. I'm very new at wxwidgets, so I'm only familiar with wxframe.
kornerr
Posts: 245
Joined: Thu Jul 06, 2006 9:57 am
Location: Russia, Siberia, Kemerovo
Contact:

Post by kornerr »

I just added

Code: Select all

if (handle->window == 0)
        cout << "no window\n";
and indeed, there's simply no pointer.

And what's the use of this:

Code: Select all

wxStaticText* pnl = new wxStaticText(this, -1, wxEmptyString);
How is text supposed to be Irrlicht window?
I tried wxPanel, although handle->window is still null.
You definetely need to give us the full workable demo.
Open Source all the way, baby ;)
OSRPG
mandrav
Posts: 117
Joined: Sat Aug 27, 2005 8:29 pm
Contact:

Post by mandrav »

kornerr wrote:I just added

Code: Select all

if (handle->window == 0)
        cout << "no window\n";
and indeed, there's simply no pointer.

And what's the use of this:

Code: Select all

wxStaticText* pnl = new wxStaticText(this, -1, wxEmptyString);
How is text supposed to be Irrlicht window?
I tried wxPanel, although handle->window is still null.
You definetely need to give us the full workable demo.
I can understand the fact that you may lack some basic wx knowledege regarding cross-platform gotchas, but you didn't state your knowledge level so I have no clue.

Did you bother to read the accompanying README?
kornerr
Posts: 245
Joined: Thu Jul 06, 2006 9:57 am
Location: Russia, Siberia, Kemerovo
Contact:

Post by kornerr »

I did bother. Ok, let's see:

Code: Select all

Usage quick-mini-turorial:

int irrID = wxNewId();
wxIrrlicht* irrWin = new wxIrrlicht(this, irrID);
try
{
    irrWin->Init();
    irrWin->StartRendering();
}
catch (const char* c)
{
    wxMessageBox(_("Could not initialise wxIrrlicht: ") + wxString(c, wxConvUTF8),
                 _("Error"),
                 wxICON_ERROR);
}
Constructor only sets some variables necessary for rendering.
Then Init:

Code: Select all

void wxIrrlicht::Init(irr::SIrrlichtCreationParameters* init_params)
{
    SIrrlichtCreationParameters params;
    params.DriverType = EDT_OPENGL; // default to OpenGL driver if no init_params specified

    SIrrlichtCreationParameters* actual_params = init_params ? init_params : &params;
    dimension2d<s32> irrSize(GetClientSize().GetX(), GetClientSize().GetY());
    actual_params->WindowSize = irrSize;

    // initialize Irrlicht in this window
#ifdef LINUX
    wxStaticText* pnl = new wxStaticText(this, -1, wxEmptyString);
    pnl->SetBackgroundStyle(wxBG_STYLE_CUSTOM);

    GtkWidget* handle = pnl->GetHandle();
    if (!handle)
        return;
    XID xHandle = GDK_WINDOW_XWINDOW(handle->window);
    Display* mDisp = GDK_WINDOW_XDISPLAY(handle->window);
    core::stringc dName = (long)mDisp;
    dName += ':';
    dName += (int)xHandle;
    actual_params->WindowId = (long)dName.c_str();
#else
    actual_params->WindowId = (long)this->GetHandle();
#endif

    m_pDevice = createDeviceEx(*actual_params);

    // sanity check
    if (!m_pDevice)
        throw "Can't create Irrlicht device!";

    // setup the Irrlicht event receiver
    wxIrrlichtLogEventReceiver* recv = new wxIrrlichtLogEventReceiver(this);
    m_pDevice->setEventReceiver(recv);

    // keep pointers to graphics driver, scene manager and gui environment handy
        m_pDriver = m_pDevice->getVideoDriver();
        m_pSceneManager = m_pDevice->getSceneManager();
        m_pGuiEnvironment = m_pDevice->getGUIEnvironment();

    // create scene
    OnCreateScene();

    // initialise the driver with the window size
    m_pDriver->OnResize(irrSize);
}
It fails on XID xHandle = GDK_WINDOW_XWINDOW(handle->window);
because handle->window is null. That's what I'm talking about. Isn't it clear, or does it make me a wx noob telling this?
If it's not null for you, JUST show full workable application, is it so hard?
Open Source all the way, baby ;)
OSRPG
mandrav
Posts: 117
Joined: Sat Aug 27, 2005 8:29 pm
Contact:

Post by mandrav »

kornerr wrote:I did bother. Ok, let's see:
Is it by accident that you selectively copy parts of the README, or is it intentional?
Let me quote the part of the README that you didn't post (and seems you didn't even read):
wxIrrlicht README wrote: Note that under Linux, you must call wxIrrlicht::Init() after the parent window
has been activated the first time. Until then, the GTK window handles returned by wxWidgets are invalid.
In simple words, this means that you should either call Init() inside the parent window's activate event handler (just once, the first time), or that you should call it from wxApp::OnInit(), right after you create your main frame.
kornerr wrote:Isn't it clear, or does it make me a wx noob telling this?
If it's not null for you, JUST show full workable application, is it so hard?
It's not hard, but I don't have it available here. Add to that the fact that you clearly didn't read all the documentation.
If you ask me one question that is really not answered in the docs, I will gladly help you.
kornerr
Posts: 245
Joined: Thu Jul 06, 2006 9:57 am
Location: Russia, Siberia, Kemerovo
Contact:

Post by kornerr »

lol, i indeed didn't read that last part :)
so i have:

Code: Select all

bool App::OnInit () {
        frame = new Frame  ("wx + irr", wxDefaultPosition, wxSize (800, 600));
        frame->CenterOnScreen ();

        SIrrlichtCreationParameters param;
        wxStaticText *pnl = new wxStaticText (frame, -1, wxEmptyString);
        pnl->SetBackgroundStyle (wxBG_STYLE_CUSTOM);
        GtkWidget *handle = pnl->GetHandle ();
        //this->SetBackgroundStyle (wxBG_STYLE_CUSTOM);
        //GtkWidget *handle = 0;
        //handle = frame->GetHandle ();
        if (handle == 0)
                cout << "no handle\n";
        if (handle->window == 0)
                cout << "no window\n";
        XID handle_id = GDK_WINDOW_XWINDOW (handle->window);
        Display *display = GDK_WINDOW_XDISPLAY (handle->window);
        core::stringc win_desc = (int)display;
        win_desc += ':';
        win_desc += (int)handle_id;
        param.WindowId = (long)win_desc.c_str ();
        param.DriverType = EDT_OPENGL;
        param.WindowSize = core::dimension2d<s32> (400, 300);
        dev = createDeviceEx (param);
        smgr = dev->getSceneManager ();
        drv = dev->getVideoDriver ();
        smgr->addCameraSceneNodeFPS (0, 10, 10);
        ISceneNode *cube = smgr->addCubeSceneNode (1);
        cube->setMaterialFlag (EMF_LIGHTING, false);
        cube->setMaterialTexture (0, drv->getTexture ("media/rockwall.bmp"));
        return true;
}
no nulls now, but irr window is created separate again :(
what am i doing wrong now?
thanks.
Open Source all the way, baby ;)
OSRPG
Post Reply