easy ImGui integration

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

easy ImGui integration

Post by Seven »

I have been tinkering with getting ImGui to work with the latest Irrlicht and wanted to put my results here so they aren't lost.
Note that I use only OpenGL and compile Irrlicht without the others. I assume something similar would work with other drivers but I havent tried.

IGE_CHECK() just logs an error and returns false if the action fails, IGE_TRACE() just logs the text, etc...

setting up ImGui is relatively easy:

to initialize ImGui :

Code: Select all

// internal initialization method
bool IGE_ImGui::initializeImGui()
{
	IGE_TRACE("IGE_ImGui::initializeImGui()");

	// Setup Dear ImGui context
	IMGUI_CHECKVERSION();
	IGE_CHECK(ImGui::CreateContext(),"ImGui::CreateContext() failed",IGE_FAILURE);
	ImGuiIO& io = ImGui::GetIO(); //(void)io;
	io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
	io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
	io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;

	// Setup Dear ImGui style
	ImGui::StyleColorsDark();

	//ImGui_ImplGlfw_InitForOpenGL(m_Application->getWindow()->getWindow(), true);
	ImGui_ImplWin32_Init(getApplication()->getContext()->m_Driver->getExposedVideoData().OpenGLWin32.HWnd);
	IGE_CHECK(ImGui_ImplOpenGL3_Init("#version 130"),"ImGui_ImplOpenGL3_Init failed",IGE_FAILURE);

	// everything went fine
	return IGE_SUCCESS;
}
and then each frame :

Code: Select all


m_Driver->beginFrame();

// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();

.. render all of the ImGui stuff

ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

m_Driver->endFrame();
passing the irrlicht events to the ImGui system is also fairly straight forward
in the eventreciever class during OnEvent(const SEvent& event) i call this

Code: Select all

void IGE_ImGui::ImGui_ImplIrrlicht_ProcessEvent(const irr::SEvent& event)
{
	ImGuiIO& io = ImGui::GetIO();

	switch (event.EventType)
	{
		case irr::EET_MOUSE_INPUT_EVENT:
		{
			const irr::SEvent::SMouseInput& mouseEvent = event.MouseInput;
			if (mouseEvent.Event == irr::EMIE_LMOUSE_PRESSED_DOWN) io.MouseDown[0] = true;
			else if (mouseEvent.Event == irr::EMIE_LMOUSE_LEFT_UP) io.MouseDown[0] = false;
			else if (mouseEvent.Event == irr::EMIE_RMOUSE_PRESSED_DOWN) io.MouseDown[1] = true;
			else if (mouseEvent.Event == irr::EMIE_RMOUSE_LEFT_UP) io.MouseDown[1] = false;
			io.MousePos = ImVec2(mouseEvent.X, mouseEvent.Y);
		} break;

		case irr::EET_KEY_INPUT_EVENT:
		{
			const irr::SEvent::SKeyInput& keyEvent = event.KeyInput;
			io.KeyMap[ImGuiKey_Space] = 0;
			io.KeysDown[keyEvent.Key] = keyEvent.PressedDown;
			io.KeyCtrl = io.KeysDown[irr::KEY_LCONTROL] || io.KeysDown[irr::KEY_RCONTROL];
			io.KeyShift = io.KeysDown[irr::KEY_LSHIFT] || io.KeysDown[irr::KEY_RSHIFT];
			io.KeyAlt = io.KeysDown[irr::KEY_MENU];
			io.KeySuper = io.KeysDown[irr::KEY_LWIN] || io.KeysDown[irr::KEY_RWIN];
			if (event.KeyInput.Char > 0 && event.KeyInput.Char < 0x10000) io.AddInputCharacter((unsigned short)event.KeyInput.Char);
		} break;
	}
}
anyhow, all of this works very well with ImGui rendered and buttons reacting correctly, color edits working, etc....

The only real issue is the texture system. I have hacked it with this :

///////////////////////////////////////////////////////////////////////////
* ITexture.h
add public uint32_t UserData variable to base class
* COpenGLCoreTexture.h
UserData = m_TextureName during OpenGl texture creation
///////////////////////////////////////////////////////////////////////////

example usage :

Code: Select all

uint32_t TextureID = m_Driver->getTexture("_assets/_Textures/dwarf.jpg")->UserData;
ImGui::ImageButton((void*)(intptr_t)TextureID, ImVec2(600,600));
which works perfectly, however, it is a pretty serious hack and I am interested if there is another method for this.
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Re: easy ImGui integration

Post by Seven »

just an image to show it all working

https://ibb.co/N9ZnVbf
CuteAlien
Admin
Posts: 9733
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: easy ImGui integration

Post by CuteAlien »

I suppose as long as you can control all Irrlicht textures which you need in ImGui you can use a wrapper function around driver->getTexture (and removeTexture as well I suppose) which internally has a global map with an uint32_t and a texture pointer.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Re: easy ImGui integration

Post by Seven »

I had thought about that, but since I still need access to the OpenGL texture creation to have access to the textureName (which is just a uint32_t) then the small changes to ITexture. h and COpenGLCoreTexture.h are not too terrible. I just hate hacking things is all :) I already modify the engine slightly for a few other things so no worries. Just wanted to make sure I wasnt missing something. I saw someone had an Irrlicht / ImGui integration that looked pretty extensive and was looking to do it more simply is all.
CuteAlien
Admin
Posts: 9733
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: easy ImGui integration

Post by CuteAlien »

Hm, I see. Actually even have this on my todo list, just pretty far down :-( Either make getOpenGLTextureName and getDX9Texture accessible via ITexture or add some IOpenGLTexture/IDirect3DTexture interfaces which have those functions or add an exposed interface for textures like IVideoDriver has with SExposedVideoData. Maybe I should throw a coin...
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Re: easy ImGui integration

Post by Seven »

that would be a good addition for folks wanting to use ImGui I think.

It makes rendering to texture for the editor very easy.

Code: Select all

void IGE_Editor::drawPanel_3D()
{
	// create an ImGui window (docked in this case)
	ImGui::Begin("3D");

	// if we have a valid rendertarget
	if (m_RenderTarget)
	{
		// check if the ImGui window size changed so we can rebuild the rendertarget if needed in preFrame(const double& elapsedtime)
		ImVec2 dims = ImGui::GetContentRegionAvail();
		if ((dims.x != m_Dims.x) || (dims.y != m_Dims.y)) { m_DimsChanged = true; m_Dims = dims; }

		// render the smgr to the rendertarget texture
		render();

		// display the rendertarget texture on the 3D pane
		uint32_t id = m_RenderTarget->getTexture()[0]->UserData;
		ImGui::Image((void*)(intptr_t)id, dims, ImVec2(0, 1), ImVec2(1, 0));
	}

	// end create an ImGui window
	ImGui::End();
}
Post Reply