There are a couple of caveats, as you'll see in my example code below.
1) Irrlicht can be updated along with the GUI element it's in, but this has to be triggered with GWidget::queue_draw(), and I have not yet worked on how to do this in a separate thread, which everyone tells me will require GTK's Dispatcher. However, it's no problem for user-event-driven applications.
2) The red and blue bits are swapped in GDK, so before I copy the bits from Irrlicht to the Gdk::Pixbuf for rendering, I had to swap the red and blue.
3) It only works with the software renderers. GTK doesn't use OpenGL and won't make a window for it. QT can, but I wasn't interested in doing that now.
I had to modify Irrlicht a tiny bit and create a new Device, which turned out to be really easy - a testimony to how great Irrlicht is for modifying.
It uses a semi-clone of the IImagePresenter interface, which is meant to be hidden because not all of the video drivers use it, so I made a clone.
I tried using render targets, but I still needed a device to set and control the video surface size, and render targets are 1) not as fast for copying and 2) are hacky (we cheat because we know the texture of the software renderers is CImage).
Without further ado...
Diffs!
Makefile
Code: Select all
67a68
> CUSTOMPRESDEVICE = CIrrDeviceCustomPresenter.o
74c75
< $(BZIP2OBJ) $(EXTRAOBJ)
---
> $(BZIP2OBJ) $(CUSTOMPRESDEVICE) $(EXTRAOBJ)
Code: Select all
40a41,44
> #ifdef _IRR_COMPILE_WITH_CUSTOM_PRESENTER_DEVICE_
> #include "CIrrDeviceCustomPresenter.h"
> #endif
>
95a100,104
> #endif
>
> #ifdef _IRR_COMPILE_WITH_CUSTOM_PRESENTER_DEVICE_
> if (params.DeviceType == EIDT_CUSTOM_PRESENTER)
> dev = new CIrrDeviceCustomPresenter(params);
Code: Select all
209a210,215
> //! Define _IRR_COMPILE_WITH_CUSTOM_PRESENTER_DEVICE_ to compile the Irrlicht Engine with the custom presenter device.
> #define _IRR_COMPILE_WITH_CUSTOM_PRESENTER_DEVICE_
> #ifdef NO_IRR_COMPILE_WITH_CUSTOM_PRESENTER_DEVICE_
> #undef _IRR_COMPILE_WITH_CUSTOM_PRESENTER_DEVICE_
> #endif
>
Code: Select all
17a18
> #include "SImagePresenter.h"
191a193,197
>
> //! Set the Image Presenter
> /** Only available on the CustomPresenter device.
> \return true if successful. */
> virtual bool setImagePresenter( video::SImagePresenter* presenter, s32 surfaceId=0 ) { return false; }
Code: Select all
177a178
> #include "SImagePresenter.h"
Code: Select all
47a48,51
>
> //! A device for rendering to a user-defined image
> /** Meant for rendering to images of 3rd party GUI frameworks. */
> EIDT_CUSTOM_PRESENTER,
In Irrlicht/include:
SImagePresenter.h
Code: Select all
// (C) 2023 Nicolaus Anderson, Nikolaus Gebhardt
// See irrlicht.h for license
#ifndef IRR_SIMAGE_PRESENTER_H_INCLUDED
#define IRR_SIMAGE_PRESENTER_H_INCLUDED
#include "IReferenceCounted.h"
#include "dimension2d.h"
#include "rect.h"
#include "IImage.h"
namespace irr
{
namespace video
{
class SImagePresenter : public IReferenceCounted
{
public:
virtual ~SImagePresenter() {}
//! Render the graphics
/** \param surface - The image from the backbuffer of the video driver that
you get to render or copy to wherever you want.
\param surfaceId - Use this via Custom Presenter to track where you want the
image to be rendered/copied-to.
\param src - The rectangular area of the surface that is meant to be drawn/copied. */
virtual bool present(video::IImage* surface, s32 surfaceId, core::rect<s32>* src=0 ) = 0;
//! Return the surface
virtual core::dimension2du getSurfaceSize() = 0;
};
} // end namespace video
} // end namespace irr
#endif // IRR_SIMAGE_PRESENTER_H_INCLUDED
CIrrDeviceCustomPresenter.h
Code: Select all
// (C) 2023 Nicolaus Anderson, Nikolaus Gebhardt
// See irrlicht.h for license
#ifndef IRR_CUSTOM_PRESENTER_H_INCLUDED
#define IRR_CUSTOM_PRESENTER_H_INCLUDED
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_CUSTOM_PRESENTER_DEVICE_
#include <position2d.h>
#include <dimension2d.h>
#include <SImagePresenter.h>
#include "IImagePresenter.h"
#include "CIrrDeviceStub.h"
namespace irr
{
class CIrrDeviceCustomPresenter : public CIrrDeviceStub, public video::IImagePresenter
{
public:
//! Constructor
CIrrDeviceCustomPresenter(const SIrrlichtCreationParameters& param);
//! Destructor
virtual ~CIrrDeviceCustomPresenter();
//! Run the device
/** This both increments the clock and allows for resizing the window. */
virtual bool run() IRR_OVERRIDE;
//! Does nothing for this device.
/** These methods are only here to fulfill the interface requirements. */
virtual void yield() IRR_OVERRIDE {}
virtual void sleep(u32 timeMs, bool pauseTimer) IRR_OVERRIDE {}
virtual void setWindowCaption(const wchar_t* text) IRR_OVERRIDE {}
virtual void closeDevice() IRR_OVERRIDE {}
//! Checks if the window is active
/** \return Actually returns whether there is an SImagePresenter for the
surface/backbuffer to be presented to. */
virtual bool isWindowActive() const IRR_OVERRIDE;
//! Checks if the Irrlicht window has the input focus
/** \return Always false. This device does not support input. */
virtual bool isWindowFocused() const IRR_OVERRIDE { return false; }
//! Checks if the Irrlicht window is minimized
/** \return Always false. This device has no window. */
virtual bool isWindowMinimized() const IRR_OVERRIDE { return false; }
//! Checks if the Irrlicht window is running in fullscreen mode
/** \return Always false. This device has no window. */
virtual bool isFullscreen() const IRR_OVERRIDE { return false; }
//! Meant to set if the window should be resizable in windowed mode.
/** This does nothing as the render surface size is set by the SImagePresenter. */
virtual void setResizable(bool resize) IRR_OVERRIDE {}
//! Set the surface size for rendering
virtual void setWindowSize(const irr::core::dimension2d<u32>& size) IRR_OVERRIDE;
//! Does nothing for this device.
/** These methods are only here to fulfill the interface requirements. */
virtual void minimizeWindow() IRR_OVERRIDE {}
virtual void maximizeWindow() IRR_OVERRIDE {}
virtual void restoreWindow() IRR_OVERRIDE {}
virtual core::position2di getWindowPosition() IRR_OVERRIDE { return core::position2di(0); }
//! Sets the class that receives the backbuffer image created by the video driver
virtual bool setImagePresenter( video::SImagePresenter* presenter, s32 surfaceId ) IRR_OVERRIDE;
//! Used internally
virtual bool present(video::IImage* surface, void* windowId=0, core::rect<s32>* src=0 ) IRR_OVERRIDE;
//! Indicates the type of this device
virtual E_DEVICE_TYPE getType() const IRR_OVERRIDE
{
return EIDT_CUSTOM_PRESENTER;
}
protected:
void createDriver();
void createScene();
void updateSurfaceSize();
private:
video::SImagePresenter* Presenter;
s32 SurfaceId;
core::dimension2du SurfaceSize;
};
} // end namespace irr
#endif // _IRR_COMPILE_WITH_CUSTOM_PRESENTER_DEVICE_
#endif // IRR_CUSTOM_PRESENTER_H_INCLUDED
Code: Select all
// (C) 2023 Nicolaus Anderson, Nikolaus Gebhardt
// See irrlicht.h for license
#include "CIrrDeviceCustomPresenter.h"
#ifdef _IRR_COMPILE_WITH_CUSTOM_PRESENTER_DEVICE_
#include <SIrrCreationParameters.h>
#include "os.h"
#include "CSceneManager.h"
namespace irr
{
CIrrDeviceCustomPresenter::CIrrDeviceCustomPresenter(const SIrrlichtCreationParameters& param)
: CIrrDeviceStub(param)
, Presenter(0)
, SurfaceId(0)
, SurfaceSize(param.WindowSize)
{
createDriver();
createScene();
}
CIrrDeviceCustomPresenter::~CIrrDeviceCustomPresenter()
{
if (Presenter)
{
Presenter->drop();
Presenter = 0;
}
}
bool CIrrDeviceCustomPresenter::run()
{
os::Timer::tick();
updateSurfaceSize();
return true;
}
bool CIrrDeviceCustomPresenter::isWindowActive() const
{
return Presenter != 0;
}
void CIrrDeviceCustomPresenter::setWindowSize(const irr::core::dimension2d<u32>& size)
{
// Cannot change the surface size because that's determined by the presenter,
// but we can update it.
updateSurfaceSize();
}
bool CIrrDeviceCustomPresenter::setImagePresenter( video::SImagePresenter* presenter, s32 surfaceId )
{
if ( Presenter )
{
Presenter->drop();
Presenter = 0;
}
if ( presenter )
{
Presenter = presenter;
Presenter->grab();
}
SurfaceId = surfaceId;
return true;
}
bool CIrrDeviceCustomPresenter::present(video::IImage* surface, void* windowId, core::rect<s32>* src )
{
// TODO: Future consideration is to allow windowId to have some meaning.
// According to CSoftwareDriver2 line 986, what is stored is:
// WindowId = videoData.D3D9.HWnd;
// and it is this value that is passed to the present() method.
if (Presenter)
{
return Presenter->present(surface, SurfaceId, src);
}
return false;
}
void CIrrDeviceCustomPresenter::createDriver()
{
switch(CreationParams.DriverType)
{
#ifdef _IRR_COMPILE_WITH_X11_
case video::EDT_SOFTWARE:
#ifdef _IRR_COMPILE_WITH_SOFTWARE_
VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this);
#else
os::Printer::log("No Software driver support compiled in.", ELL_ERROR);
#endif
break;
case video::EDT_BURNINGSVIDEO:
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this);
#else
os::Printer::log("Burning's video driver was not compiled in.", ELL_ERROR);
#endif
break;
case video::EDT_OPENGL:
os::Printer::log("OpenGL is not supported by this device.", ELL_ERROR);
break;
case video::DEPRECATED_EDT_DIRECT3D8_NO_LONGER_EXISTS:
case video::EDT_DIRECT3D9:
os::Printer::log("This driver is not supported by this device.",
ELL_ERROR);
break;
case video::EDT_NULL:
VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize);
break;
default:
os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR);
break;
#else
case video::EDT_NULL:
VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize);
break;
default:
os::Printer::log("Operating with no video driver.", ELL_INFORMATION);
break;
#endif
}
}
void CIrrDeviceCustomPresenter::createScene()
{
// create Scene manager
SceneManager = scene::createSceneManager(VideoDriver, FileSystem, CursorControl, GUIEnvironment);
setEventReceiver(UserReceiver);
}
void CIrrDeviceCustomPresenter::updateSurfaceSize()
{
if ( !Presenter )
return;
core::dimension2du newSurfaceSize = Presenter->getSurfaceSize();
if ( SurfaceSize != newSurfaceSize )
{
SurfaceSize = newSurfaceSize;
if (VideoDriver)
VideoDriver->OnResize(SurfaceSize);
}
}
} // end namespace irr
#endif // _IRR_COMPILE_WITH_CUSTOM_PRESENTER_DEVICE_
Example code!
For this example, you will need to include all of the includes and libraries for GTK. I have an Eclipse project file out of which you can see and copy all of the listOptionValue entries for all the includes and libraries:
Eclipse project .cproject file:
Code: Select all
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.config.gnu.exe.debug.1634220638">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.debug.1634220638" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.1634220638" name="Debug" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="cdt.managedbuild.config.gnu.exe.debug">
<folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1634220638." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.464294452" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.715602610" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/>
<builder buildPath="${workspace_loc:/IrrGTKCustomPresenterTest}/Debug" id="cdt.managedbuild.target.gnu.builder.exe.debug.714763245" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.764510329" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.1156544493" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug">
<option id="gnu.cpp.compiler.exe.debug.option.optimization.level.1029276948" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
<option defaultValue="gnu.cpp.compiler.debugging.level.max" id="gnu.cpp.compiler.exe.debug.option.debugging.level.360095178" name="Debug Level" superClass="gnu.cpp.compiler.exe.debug.option.debugging.level" useByScannerDiscovery="false" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.144829812" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="/usr/local/include/irrlicht"/>
<listOptionValue builtIn="false" value="/usr/include/gtkmm-3.0"/>
<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/gtkmm-3.0/include"/>
<listOptionValue builtIn="false" value="/usr/include/atkmm-1.6"/>
<listOptionValue builtIn="false" value="/usr/include/gtk-3.0/unix-print"/>
<listOptionValue builtIn="false" value="/usr/include/gdkmm-3.0"/>
<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/gdkmm-3.0/include"/>
<listOptionValue builtIn="false" value="/usr/include/giomm-2.4"/>
<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/giomm-2.4/include"/>
<listOptionValue builtIn="false" value="/usr/include/pangomm-1.4"/>
<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/pangomm-1.4/include"/>
<listOptionValue builtIn="false" value="/usr/include/glibmm-2.4"/>
<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/glibmm-2.4/include"/>
<listOptionValue builtIn="false" value="/usr/include/gtk-3.0"/>
<listOptionValue builtIn="false" value="/usr/include/at-spi2-atk/2.0"/>
<listOptionValue builtIn="false" value="/usr/include/at-spi-2.0"/>
<listOptionValue builtIn="false" value="/usr/include/dbus-1.0"/>
<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/dbus-1.0/include"/>
<listOptionValue builtIn="false" value="/usr/include/gtk-3.0"/>
<listOptionValue builtIn="false" value="/usr/include/gio-unix-2.0"/>
<listOptionValue builtIn="false" value="/usr/include/cairo"/>
<listOptionValue builtIn="false" value="/usr/include/pango-1.0"/>
<listOptionValue builtIn="false" value="/usr/include/fribidi"/>
<listOptionValue builtIn="false" value="/usr/include/harfbuzz"/>
<listOptionValue builtIn="false" value="/usr/include/atk-1.0"/>
<listOptionValue builtIn="false" value="/usr/include/cairo"/>
<listOptionValue builtIn="false" value="/usr/include/cairomm-1.0"/>
<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/cairomm-1.0/include"/>
<listOptionValue builtIn="false" value="/usr/include/cairo"/>
<listOptionValue builtIn="false" value="/usr/include/pixman-1"/>
<listOptionValue builtIn="false" value="/usr/include/uuid"/>
<listOptionValue builtIn="false" value="/usr/include/freetype2"/>
<listOptionValue builtIn="false" value="/usr/include/libpng16"/>
<listOptionValue builtIn="false" value="/usr/include/sigc++-2.0"/>
<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/sigc++-2.0/include"/>
<listOptionValue builtIn="false" value="/usr/include/gdk-pixbuf-2.0"/>
<listOptionValue builtIn="false" value="/usr/include/libmount"/>
<listOptionValue builtIn="false" value="/usr/include/blkid"/>
<listOptionValue builtIn="false" value="/usr/include/glib-2.0"/>
<listOptionValue builtIn="false" value="/usr/lib/x86_64-linux-gnu/glib-2.0/include"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="gnu.cpp.compiler.option.include.files.71342643" name="Include files (-include)" superClass="gnu.cpp.compiler.option.include.files" useByScannerDiscovery="false" valueType="includeFiles"/>
<option id="gnu.cpp.compiler.option.dialect.std.466233890" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.c++17" valueType="enumerated"/>
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.6199757" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.744156975" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug">
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.exe.debug.option.optimization.level.185481247" name="Optimization Level" superClass="gnu.c.compiler.exe.debug.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
<option defaultValue="gnu.c.debugging.level.max" id="gnu.c.compiler.exe.debug.option.debugging.level.639517101" name="Debug Level" superClass="gnu.c.compiler.exe.debug.option.debugging.level" useByScannerDiscovery="false" valueType="enumerated"/>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1586742396" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.1051401144" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.465688178" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug">
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.866297673" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs">
<listOptionValue builtIn="false" value="Irrlicht"/>
<listOptionValue builtIn="false" value="GL"/>
<listOptionValue builtIn="false" value="gtkmm-3.0"/>
<listOptionValue builtIn="false" value="atkmm-1.6"/>
<listOptionValue builtIn="false" value="gdkmm-3.0"/>
<listOptionValue builtIn="false" value="giomm-2.4"/>
<listOptionValue builtIn="false" value="pangomm-1.4"/>
<listOptionValue builtIn="false" value="glibmm-2.4"/>
<listOptionValue builtIn="false" value="gtk-3"/>
<listOptionValue builtIn="false" value="gdk-3"/>
<listOptionValue builtIn="false" value="pangocairo-1.0"/>
<listOptionValue builtIn="false" value="pango-1.0"/>
<listOptionValue builtIn="false" value="harfbuzz"/>
<listOptionValue builtIn="false" value="atk-1.0"/>
<listOptionValue builtIn="false" value="cairo-gobject"/>
<listOptionValue builtIn="false" value="gio-2.0"/>
<listOptionValue builtIn="false" value="cairomm-1.0"/>
<listOptionValue builtIn="false" value="cairo"/>
<listOptionValue builtIn="false" value="sigc-2.0"/>
<listOptionValue builtIn="false" value="gdk_pixbuf-2.0"/>
<listOptionValue builtIn="false" value="gobject-2.0"/>
<listOptionValue builtIn="false" value="glib-2.0"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1614118428" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.exe.debug.523688494" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.473846942" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="src" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="IrrGTKCustomPresenterTest.cdt.managedbuild.target.gnu.exe.2067463168" name="Executable" projectType="cdt.managedbuild.target.gnu.exe"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.1634220638;cdt.managedbuild.config.gnu.exe.debug.1634220638.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.1156544493;cdt.managedbuild.tool.gnu.cpp.compiler.input.6199757">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.823068514;cdt.managedbuild.config.gnu.exe.release.823068514.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.1718865303;cdt.managedbuild.tool.gnu.c.compiler.input.1419537182">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.823068514;cdt.managedbuild.config.gnu.exe.release.823068514.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.988431735;cdt.managedbuild.tool.gnu.cpp.compiler.input.660843686">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.1634220638;cdt.managedbuild.config.gnu.exe.debug.1634220638.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.744156975;cdt.managedbuild.tool.gnu.c.compiler.input.1586742396">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/IrrGTKCustomPresenterTest"/>
</configuration>
<configuration configurationName="Release">
<resource resourceType="PROJECT" workspacePath="/IrrGTKCustomPresenterTest"/>
</configuration>
</storageModule>
</cproject>
Code: Select all
/*
* main.cpp
*
* Created on: Jan 21, 2023
* Author: Nicolaus Anderson
*/
#include <iostream>
#include <gtkmm.h>
#include <irrlicht.h>
/*
gint32 IrrSColorToGdkColor(irr::video::SColor c)
{
return c.getAlpha() << 24 | c.getBlue() << 16 | c.getGreen() << 8 | c.getRed();
}
*/
irr::video::SColor flipRedAndBlue(irr::video::SColor c)
{
return irr::video::SColor(
c.getAlpha(), c.getBlue(), c.getGreen(), c.getRed()
);
}
class IrrPanel : public Gtk::DrawingArea, public irr::video::SImagePresenter
{
public:
IrrPanel(guint32 width, guint32 height, guint8 antiAlias = 0, irr::video::SColor bufferColor=irr::video::SColor(0))
: my_irrParams()
, my_irrDevice(0)
, my_bufferColor(bufferColor)
, my_videoBuffer(0)
, my_videoSrcRect()
, my_pixbuf()
{
my_irrParams.DeviceType = irr::EIDT_CUSTOM_PRESENTER;
my_irrParams.DriverType = irr::video::EDT_BURNINGSVIDEO;
my_irrParams.AntiAlias = antiAlias;
my_irrParams.Bits = 32;
my_irrParams.WithAlphaChannel = true;
my_irrParams.WindowSize.set(width, height);
my_irrDevice = irr::createDeviceEx(my_irrParams);
my_irrDevice->setImagePresenter(this);
set_size_request(width, height);
}
irr::scene::ISceneManager* getSceneManager()
{
if (my_irrDevice)
return my_irrDevice->getSceneManager();
return 0;
}
virtual bool present(irr::video::IImage* surface, irr::s32 surfaceId, irr::core::rect<irr::s32>* src )
{
my_videoBuffer = surface;
if ( src )
my_videoSrcRect = *src;
if (my_videoBuffer)
{
const irr::core::dimension2du surfaceSize = my_videoBuffer->getDimension();
// Swap red and blue because GDK has them flipped
for ( irr::u32 w = 0; w < surfaceSize.Width; ++w)
{
for ( irr::u32 h = 0; h < surfaceSize.Height; ++h)
{
my_videoBuffer->setPixel(w, h, flipRedAndBlue(my_videoBuffer->getPixel(w, h)), false);
}
}
}
return true;
}
//! Return the surface
virtual irr::core::dimension2du getSurfaceSize()
{
return my_irrParams.WindowSize;
}
protected:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override
{
if (!my_irrDevice)
return false;
my_irrDevice->run();
my_irrDevice->getVideoDriver()->beginScene(true, true, my_bufferColor);
my_irrDevice->getSceneManager()->drawAll();
my_irrDevice->getVideoDriver()->endScene();
// endScene calls present, which sets the video buffer and source rect
if ( my_videoBuffer )
{
const irr::core::dimension2du surfaceSize = my_videoBuffer->getDimension();
// Currently, create_from_data only supports colors of 8 bits per sample.
// Unfortunately, red and blue bits are swapped compared to Irrlicht,
// so we do that in present()
my_pixbuf = my_pixbuf->create_from_data(
(const guint8*) my_videoBuffer->getData(), Gdk::COLORSPACE_RGB, true, 8,
surfaceSize.Width, surfaceSize.Height, my_videoBuffer->getPitch());
}
const int location_x = 0;
const int location_y = 0;
Gdk::Cairo::set_source_pixbuf(cr, my_pixbuf, location_x, location_y);
cr->paint();
return true;
}
protected:
irr::SIrrlichtCreationParameters my_irrParams;
irr::IrrlichtDevice* my_irrDevice;
irr::video::SColor my_bufferColor;
irr::video::IImage* my_videoBuffer;
irr::core::recti my_videoSrcRect;
Glib::RefPtr<Gdk::Pixbuf> my_pixbuf;
};
class MainWindow : public Gtk::Window {
public:
MainWindow()
: my_width(800)
, my_height(200)
, my_vbox(false,0) // No equal space allotment and no spacing between elements
, my_irrPanel(my_width, 500, 0, irr::video::SColor(0xff0000ff))
, my_button_addCube("Add Cube")
{
set_default_size(my_width, my_height);
add(my_vbox);
//my_vbox.pack_start(my_irrPanel);
my_vbox.pack_end(my_irrPanel);
my_vbox.pack_end(my_button_addCube, Gtk::PACK_SHRINK);
my_button_addCube.signal_clicked().connect(sigc::mem_fun(this, &MainWindow::addCubeToScene)); // @suppress("Invalid arguments")
show_all_children();
// TODO: Add camera and cube to scene
if ( my_irrPanel.getSceneManager() )
{
my_irrPanel.getSceneManager()->addCameraSceneNode(
0, irr::core::vector3df(0,2,-2), irr::core::vector3df(0), 0, true);
my_irrPanel.getSceneManager()->addLightSceneNode(
0, irr::core::vector3df(0,5,0), irr::video::SColor(0xffffffff), 7, 1);
//my_irrPanel.getSceneManager()->addCubeSceneNode(
// 1, 0, 1, irr::core::vector3df(0), irr::core::vector3df(0), irr::core::vector3df(1),
// irr::scene::ECMT_1BUF_12VTX_NA);
}
}
void addCubeToScene()
{
if ( my_irrPanel.getSceneManager() )
{
irr::scene::ISceneNode* cubeNode = my_irrPanel.getSceneManager()->addCubeSceneNode(
1, 0, 2, irr::core::vector3df(0), irr::core::vector3df(0,20,0), irr::core::vector3df(1),
irr::scene::ECMT_1BUF_12VTX_NA);
irr::video::SMaterial& mat = cubeNode->getMaterial(0);
mat.AmbientColor = irr::video::SColor(0xffff0000);
mat.DiffuseColor = irr::video::SColor(0xffff0000);
mat.GouraudShading = true;
mat.Lighting = true;
mat.ColorMaterial = irr::video::ECM_NONE; // irr::video::ECM_DIFFUSE_AND_AMBIENT;
mat.MaterialType = irr::video::EMT_SOLID;
}
my_irrPanel.queue_draw();
}
protected:
const int my_width;
const int my_height;
Gtk::VBox my_vbox;
IrrPanel my_irrPanel;
Gtk::Button my_button_addCube;
};
int main(int argc, char* argv[])
{
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.irr_fb_test"); // @Suppress("Invalid arguments")
MainWindow mainWindow;
return app->run(mainWindow);
}