-
-
Save hb3p8/52ac227f77e8accf96cf to your computer and use it in GitHub Desktop.
| #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; | |
| } |
| #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 |
Здравствуйте, Данила! Ещё раз прошу вас добавить пример использования этого хэндлера ImGUI для OpenSceneGraph.
Здравствуйте Raizel. вы уже знаете как это использовать?
Та что братан. У тебя получилось? Я в си++ и OSG только начинаю (учусь)... Короче, я тут пару часов поигрался и вот что у меня получилось... Это работает с половины, IMGUI не принимает вступ од пользователя. Я почитаю как надо работать с OSG и попытаюсь всю отладить. Покамис хоть текст показывает :) Вот тебе ссылка на gist
Нет, не получилось использовать. Надо будет переписать пример. Всё-таки, IMGUI - отличная вещь!
Что касается OSG, его стоит изучать. Гибкость этого движка впечатляет. Ogre3D по сравнению с ним - полная фигня.
Один большой недостаток OSG - он абсолютно не подходит для игр. Очень много нужно допиливать.
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.)
Please, example, how to use it?