Created
January 29, 2016 08:33
-
-
Save hb3p8/52ac227f77e8accf96cf to your computer and use it in GitHub Desktop.
ImGui OSG wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ImGuiHandler.hpp> | |
#include <imgui/imgui.h> | |
#include <iostream> | |
using namespace sf; | |
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) | |
// If text or lines are blurry when integrating ImGui in your engine: | |
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) | |
void ImGui_RenderDrawLists (ImDrawData* draw_data) | |
{ | |
// We are using the OpenGL fixed pipeline to make the example code simpler to read! | |
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. | |
GLint last_texture; | |
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); | |
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); | |
glEnable(GL_BLEND); | |
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
glDisable(GL_CULL_FACE); | |
glDisable(GL_DEPTH_TEST); | |
glEnable(GL_SCISSOR_TEST); | |
glDisable (GL_LIGHTING); | |
glEnableClientState(GL_VERTEX_ARRAY); | |
glEnableClientState(GL_TEXTURE_COORD_ARRAY); | |
glEnableClientState(GL_COLOR_ARRAY); | |
glEnable(GL_TEXTURE_2D); | |
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context | |
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays) | |
ImGuiIO& io = ImGui::GetIO(); | |
float fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y; | |
draw_data->ScaleClipRects(io.DisplayFramebufferScale); | |
// Setup orthographic projection matrix | |
glMatrixMode(GL_PROJECTION); | |
glPushMatrix(); | |
glLoadIdentity(); | |
glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f); | |
glMatrixMode(GL_MODELVIEW); | |
glPushMatrix(); | |
glLoadIdentity(); | |
// Render command lists | |
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) | |
for (int n = 0; n < draw_data->CmdListsCount; n++) | |
{ | |
const ImDrawList* cmd_list = draw_data->CmdLists[n]; | |
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->VtxBuffer.front(); | |
const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); | |
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, pos))); | |
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, uv))); | |
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, col))); | |
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) | |
{ | |
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; | |
if (pcmd->UserCallback) | |
{ | |
pcmd->UserCallback(cmd_list, pcmd); | |
} | |
else | |
{ | |
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); | |
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); | |
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer); | |
} | |
idx_buffer += pcmd->ElemCount; | |
} | |
} | |
#undef OFFSETOF | |
// Restore modified state | |
// glDisableClientState(GL_COLOR_ARRAY); | |
// glDisableClientState(GL_TEXTURE_COORD_ARRAY); | |
// glDisableClientState(GL_VERTEX_ARRAY); | |
glBindTexture(GL_TEXTURE_2D, last_texture); | |
glMatrixMode(GL_MODELVIEW); | |
glPopMatrix(); | |
glMatrixMode(GL_PROJECTION); | |
glPopMatrix(); | |
glPopAttrib(); | |
} | |
struct ImGuiNewFrameCallback : public osg::Camera::DrawCallback { | |
ImGuiNewFrameCallback (ImGuiHandler& theHandler) | |
: m_handler (theHandler) | |
{} | |
virtual void operator () (osg::RenderInfo& theRenderInfo) const { | |
m_handler.newFrame (theRenderInfo); | |
} | |
private: | |
ImGuiHandler& m_handler; | |
}; | |
struct ImGuiDrawCallback : public osg::Camera::DrawCallback { | |
ImGuiDrawCallback (ImGuiHandler& theHandler) | |
: m_handler (theHandler) | |
{} | |
virtual void operator () (osg::RenderInfo& theRenderInfo) const { | |
m_handler.render (theRenderInfo); | |
} | |
private: | |
ImGuiHandler& m_handler; | |
}; | |
ImGuiHandler::ImGuiHandler (GuiCallback *theGuicallback) | |
: m_callback (theGuicallback) { | |
g_Time = 0.0f; | |
for (int i = 0; i < 3; ++i) | |
g_MousePressed[i] = false; | |
g_MouseWheel = 0.0f; | |
g_FontTexture = 0; | |
} | |
void ImGuiHandler::init() { | |
ImGuiIO& io = ImGui::GetIO(); | |
// Build texture atlas | |
unsigned char* pixels; | |
int width, height; | |
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); | |
// Create OpenGL texture | |
GLint last_texture; | |
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); | |
glGenTextures(1, &g_FontTexture); | |
glBindTexture(GL_TEXTURE_2D, g_FontTexture); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); | |
// Store our identifier | |
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; | |
// Cleanup (don't clear the input data if you want to append new fonts later) | |
io.Fonts->ClearInputData(); | |
io.Fonts->ClearTexData(); | |
glBindTexture(GL_TEXTURE_2D, last_texture); | |
io.RenderDrawListsFn = ImGui_RenderDrawLists; | |
} | |
void ImGuiHandler::setCameraCallbacks (osg::Camera *theCamera) { | |
ImGuiDrawCallback* aPostDrawCallback = new ImGuiDrawCallback (*this); | |
theCamera->setPostDrawCallback (aPostDrawCallback); | |
ImGuiNewFrameCallback* aPreDrawCallback = new ImGuiNewFrameCallback (*this); | |
theCamera->setPreDrawCallback (aPreDrawCallback); | |
} | |
void ImGuiHandler::newFrame (osg::RenderInfo& theRenderInfo) { | |
if (!g_FontTexture) { | |
init(); | |
} | |
ImGuiIO& io = ImGui::GetIO(); | |
osg::Viewport* aViewport = theRenderInfo.getCurrentCamera()->getViewport(); | |
io.DisplaySize = ImVec2(aViewport->width(), aViewport->height()); | |
double aCurrentTime = theRenderInfo.getView()->getFrameStamp()->getSimulationTime(); | |
io.DeltaTime = g_Time > 0.0 ? (float)(aCurrentTime - g_Time) : (float)(1.0f/60.0f); | |
g_Time = aCurrentTime; | |
for (int i = 0; i < 3; i++) | |
{ | |
io.MouseDown[i] = g_MousePressed[i]; | |
// g_MousePressed[i] = false; | |
} | |
io.MouseWheel = g_MouseWheel; | |
g_MouseWheel = 0.0f; | |
ImGui::NewFrame(); | |
} | |
void ImGuiHandler::render (osg::RenderInfo& /*theRenderInfo*/) { | |
if (m_callback) { | |
(*m_callback)(); | |
} | |
ImGui::Render(); | |
} | |
bool ImGuiHandler::handle (const osgGA::GUIEventAdapter &theEventAdapter, | |
osgGA::GUIActionAdapter &theActionAdapter, | |
osg::Object *theObject, | |
osg::NodeVisitor *theNodeVisitor) { | |
bool wantCapureMouse = ImGui::GetIO().WantCaptureMouse; | |
bool wantCapureKeyboard = ImGui::GetIO().WantCaptureKeyboard; | |
switch (theEventAdapter.getEventType()) { | |
case osgGA::GUIEventAdapter::KEYDOWN: { | |
ImGuiIO& io = ImGui::GetIO(); | |
int c = theEventAdapter.getKey(); | |
if (c > 0 && c < 0x10000) { | |
io.AddInputCharacter((unsigned short)c); | |
} | |
std::cout << c << std::endl << std::flush; | |
return wantCapureKeyboard; | |
} | |
case(osgGA::GUIEventAdapter::PUSH): | |
{ | |
ImGuiIO& io = ImGui::GetIO(); | |
io.MousePos = ImVec2 (theEventAdapter.getX(), io.DisplaySize.y - theEventAdapter.getY()); | |
g_MousePressed[0] = true; | |
return wantCapureMouse; | |
} | |
case(osgGA::GUIEventAdapter::DRAG): | |
case(osgGA::GUIEventAdapter::MOVE): | |
{ | |
ImGuiIO& io = ImGui::GetIO(); | |
io.MousePos = ImVec2 (theEventAdapter.getX(), io.DisplaySize.y - theEventAdapter.getY()); | |
return wantCapureMouse; | |
} | |
case(osgGA::GUIEventAdapter::RELEASE): | |
{ | |
g_MousePressed[0] = false; | |
return wantCapureMouse; | |
} | |
case(osgGA::GUIEventAdapter::SCROLL): | |
{ | |
g_MouseWheel = theEventAdapter.getScrollingDeltaY(); | |
return wantCapureMouse; | |
} | |
default: | |
{ | |
return false; | |
} | |
} | |
return false; | |
} | |
bool ImGui::SliderReal (const char *label, double *v, float v_min, float v_max, const char *display_format, float power) | |
{ | |
float aValue = *v; | |
if (ImGui::SliderFloat (label, &aValue, v_min, v_max, display_format, power)) { | |
*v = aValue; | |
return true; | |
} | |
return false; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef UTILS_IMGUI_HANDLER_HEADER | |
#define UTILS_IMGUI_HANDLER_HEADER | |
#ifdef _WIN32 | |
#define NOMINMAX | |
#include <windows.h> | |
#endif | |
#include <osgViewer/ViewerEventHandlers> | |
#include <osg/Camera> | |
namespace sf { | |
struct GuiCallback | |
{ | |
virtual void operator () () {} | |
}; | |
class ImGuiHandler : public osgGA::GUIEventHandler { | |
public: | |
ImGuiHandler (GuiCallback* theGuicallback); | |
void init(); | |
void newFrame (osg::RenderInfo& theRenderInfo); | |
void render (osg::RenderInfo& theRenderInfo); | |
void setCameraCallbacks (osg::Camera* theCamera); | |
virtual bool handle(const osgGA::GUIEventAdapter& theEventAdapter, | |
osgGA::GUIActionAdapter& theActionAdapter, | |
osg::Object* theObject, | |
osg::NodeVisitor* theNodeVisitor); | |
private: | |
GuiCallback* m_callback; | |
double g_Time; | |
bool g_MousePressed[3]; | |
float g_MouseWheel; | |
GLuint g_FontTexture; | |
}; | |
} // namespace sf | |
namespace ImGui { | |
bool SliderReal (const char* label, double* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); | |
} | |
#endif // UTILS_IMGUI_HANDLER_HEADER |
Please use updated gist from fulezi https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c
@Megaton Thank you! What is the license for this code? (I'll ask fulezi the same.)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Нет, не получилось использовать. Надо будет переписать пример. Всё-таки, IMGUI - отличная вещь!
Что касается OSG, его стоит изучать. Гибкость этого движка впечатляет. Ogre3D по сравнению с ним - полная фигня.
Один большой недостаток OSG - он абсолютно не подходит для игр. Очень много нужно допиливать.