add qtimgui renderer library

This commit is contained in:
Miodrag Milanovic 2018-10-21 09:29:06 +02:00
parent b948b76c8e
commit 40722c098d
13 changed files with 837 additions and 0 deletions

44
3rdparty/qtimgui/.gitignore vendored Normal file
View File

@ -0,0 +1,44 @@
# Created by https://www.gitignore.io/api/qt
### Qt ###
# C++ objects and libs
*.slo
*.lo
*.o
*.a
*.la
*.lai
*.so
*.dll
*.dylib
# Qt-es
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.qbs.user
*.qbs.user.*
*.moc
moc_*.cpp
qrc_*.cpp
ui_*.h
Makefile*
*build-*
# QtCreator
*.autosave
# QtCtreator Qml
*.qmlproject.user
*.qmlproject.user.*
# QtCtreator CMake
CMakeLists.txt.user*
# End of https://www.gitignore.io/api/qt

381
3rdparty/qtimgui/ImGuiRenderer.cpp vendored Normal file
View File

@ -0,0 +1,381 @@
#include "ImGuiRenderer.h"
#include <QDateTime>
#include <QGuiApplication>
#include <QMouseEvent>
#include <QClipboard>
#include <QCursor>
#include <QDebug>
namespace QtImGui {
namespace {
QHash<int, ImGuiKey> keyMap = {
{ Qt::Key_Tab, ImGuiKey_Tab },
{ Qt::Key_Left, ImGuiKey_LeftArrow },
{ Qt::Key_Right, ImGuiKey_RightArrow },
{ Qt::Key_Up, ImGuiKey_UpArrow },
{ Qt::Key_Down, ImGuiKey_DownArrow },
{ Qt::Key_PageUp, ImGuiKey_PageUp },
{ Qt::Key_PageDown, ImGuiKey_PageDown },
{ Qt::Key_Home, ImGuiKey_Home },
{ Qt::Key_End, ImGuiKey_End },
{ Qt::Key_Delete, ImGuiKey_Delete },
{ Qt::Key_Backspace, ImGuiKey_Backspace },
{ Qt::Key_Enter, ImGuiKey_Enter },
{ Qt::Key_Escape, ImGuiKey_Escape },
{ Qt::Key_A, ImGuiKey_A },
{ Qt::Key_C, ImGuiKey_C },
{ Qt::Key_V, ImGuiKey_V },
{ Qt::Key_X, ImGuiKey_X },
{ Qt::Key_Y, ImGuiKey_Y },
{ Qt::Key_Z, ImGuiKey_Z },
};
QByteArray g_currentClipboardText;
}
void ImGuiRenderer::initialize(WindowWrapper *window) {
m_window.reset(window);
initializeOpenGLFunctions();
ImGui::CreateContext();
ImGuiIO &io = ImGui::GetIO();
for (ImGuiKey key : keyMap.values()) {
io.KeyMap[key] = key;
}
io.RenderDrawListsFn = [](ImDrawData *drawData) {
instance()->renderDrawList(drawData);
};
io.SetClipboardTextFn = [](void *user_data, const char *text) {
Q_UNUSED(user_data);
QGuiApplication::clipboard()->setText(text);
};
io.GetClipboardTextFn = [](void *user_data) {
Q_UNUSED(user_data);
g_currentClipboardText = QGuiApplication::clipboard()->text().toUtf8();
return (const char *)g_currentClipboardText.data();
};
window->installEventFilter(this);
}
void ImGuiRenderer::renderDrawList(ImDrawData *draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
ImGuiIO& io = ImGui::GetIO();
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
if (fb_width == 0 || fb_height == 0)
return;
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// Backup GL state
GLint last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, &last_active_texture);
glActiveTexture(GL_TEXTURE0);
GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
GLint last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, &last_blend_src_rgb);
GLint last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, &last_blend_dst_rgb);
GLint last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, &last_blend_src_alpha);
GLint last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, &last_blend_dst_alpha);
GLint last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
GLint last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
// Setup viewport, orthographic projection matrix
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
const float ortho_projection[4][4] =
{
{ 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f },
{-1.0f, 1.0f, 0.0f, 1.0f },
};
glUseProgram(g_ShaderHandle);
glUniform1i(g_AttribLocationTex, 0);
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
glBindVertexArray(g_VaoHandle);
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawIdx* idx_buffer_offset = 0;
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
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, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
}
idx_buffer_offset += pcmd->ElemCount;
}
}
// Restore modified GL state
glUseProgram(last_program);
glBindTexture(GL_TEXTURE_2D, last_texture);
glActiveTexture(last_active_texture);
glBindVertexArray(last_vertex_array);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
}
bool ImGuiRenderer::createFontsTexture()
{
// Build texture atlas
ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
// Upload texture to graphics system
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_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// Store our identifier
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
// Restore state
glBindTexture(GL_TEXTURE_2D, last_texture);
return true;
}
bool ImGuiRenderer::createDeviceObjects()
{
// Backup GL state
GLint last_texture, last_array_buffer, last_vertex_array;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
const GLchar *vertex_shader =
"#version 330\n"
"uniform mat4 ProjMtx;\n"
"in vec2 Position;\n"
"in vec2 UV;\n"
"in vec4 Color;\n"
"out vec2 Frag_UV;\n"
"out vec4 Frag_Color;\n"
"void main()\n"
"{\n"
" Frag_UV = UV;\n"
" Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
"}\n";
const GLchar* fragment_shader =
"#version 330\n"
"uniform sampler2D Texture;\n"
"in vec2 Frag_UV;\n"
"in vec4 Frag_Color;\n"
"out vec4 Out_Color;\n"
"void main()\n"
"{\n"
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
"}\n";
g_ShaderHandle = glCreateProgram();
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(g_VertHandle, 1, &vertex_shader, 0);
glShaderSource(g_FragHandle, 1, &fragment_shader, 0);
glCompileShader(g_VertHandle);
glCompileShader(g_FragHandle);
glAttachShader(g_ShaderHandle, g_VertHandle);
glAttachShader(g_ShaderHandle, g_FragHandle);
glLinkProgram(g_ShaderHandle);
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
glGenBuffers(1, &g_VboHandle);
glGenBuffers(1, &g_ElementsHandle);
glGenVertexArrays(1, &g_VaoHandle);
glBindVertexArray(g_VaoHandle);
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
glEnableVertexAttribArray(g_AttribLocationPosition);
glEnableVertexAttribArray(g_AttribLocationUV);
glEnableVertexAttribArray(g_AttribLocationColor);
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos));
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv));
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
#undef OFFSETOF
createFontsTexture();
// Restore modified GL state
glBindTexture(GL_TEXTURE_2D, last_texture);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
glBindVertexArray(last_vertex_array);
return true;
}
void ImGuiRenderer::newFrame()
{
if (!g_FontTexture)
createDeviceObjects();
ImGuiIO& io = ImGui::GetIO();
// Setup display size (every frame to accommodate for window resizing)
io.DisplaySize = ImVec2(m_window->size().width(), m_window->size().height());
io.DisplayFramebufferScale = ImVec2(m_window->devicePixelRatio(), m_window->devicePixelRatio());
// Setup time step
double current_time = QDateTime::currentMSecsSinceEpoch() / double(1000);
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
g_Time = current_time;
// Setup inputs
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
if (m_window->isActive())
{
auto pos = m_window->mapFromGlobal(QCursor::pos());
io.MousePos = ImVec2(pos.x(), pos.y()); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.)
}
else
{
io.MousePos = ImVec2(-1,-1);
}
for (int i = 0; i < 3; i++)
{
io.MouseDown[i] = g_MousePressed[i];
}
io.MouseWheelH = g_MouseWheelH;
io.MouseWheel = g_MouseWheel;
g_MouseWheelH = 0;
g_MouseWheel = 0;
// Hide OS mouse cursor if ImGui is drawing it
// glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
// Start the frame
ImGui::NewFrame();
}
void ImGuiRenderer::onMousePressedChange(QMouseEvent *event)
{
g_MousePressed[0] = event->buttons() & Qt::LeftButton;
g_MousePressed[1] = event->buttons() & Qt::RightButton;
g_MousePressed[2] = event->buttons() & Qt::MiddleButton;
}
void ImGuiRenderer::onWheel(QWheelEvent *event)
{
// 5 lines per unit
g_MouseWheelH += event->pixelDelta().x() / (ImGui::GetTextLineHeight());
g_MouseWheel += event->pixelDelta().y() / (5.0 * ImGui::GetTextLineHeight());
}
void ImGuiRenderer::onKeyPressRelease(QKeyEvent *event)
{
ImGuiIO& io = ImGui::GetIO();
if (keyMap.contains(event->key())) {
io.KeysDown[keyMap[event->key()]] = event->type() == QEvent::KeyPress;
}
if (event->type() == QEvent::KeyPress) {
QString text = event->text();
if (text.size() == 1) {
io.AddInputCharacter(text.at(0).unicode());
}
}
#ifdef Q_OS_MAC
io.KeyCtrl = event->modifiers() & Qt::MetaModifier;
io.KeyShift = event->modifiers() & Qt::ShiftModifier;
io.KeyAlt = event->modifiers() & Qt::AltModifier;
io.KeySuper = event->modifiers() & Qt::ControlModifier; // Comamnd key
#else
io.KeyCtrl = event->modifiers() & Qt::ControlModifier;
io.KeyShift = event->modifiers() & Qt::ShiftModifier;
io.KeyAlt = event->modifiers() & Qt::AltModifier;
io.KeySuper = event->modifiers() & Qt::MetaModifier;
#endif
}
bool ImGuiRenderer::eventFilter(QObject *watched, QEvent *event)
{
switch (event->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
this->onMousePressedChange(static_cast<QMouseEvent *>(event));
break;
case QEvent::Wheel:
this->onWheel(static_cast<QWheelEvent *>(event));
break;
case QEvent::KeyPress:
case QEvent::KeyRelease:
this->onKeyPressRelease(static_cast<QKeyEvent *>(event));
break;
default:
break;
}
return QObject::eventFilter(watched, event);
}
ImGuiRenderer* ImGuiRenderer::instance() {
static ImGuiRenderer* instance = nullptr;
if (!instance) {
instance = new ImGuiRenderer();
}
return instance;
}
}

58
3rdparty/qtimgui/ImGuiRenderer.h vendored Normal file
View File

@ -0,0 +1,58 @@
#pragma once
#include <QOpenGLExtraFunctions>
#include <QObject>
#include <QPoint>
#include <imgui.h>
#include <memory>
class QMouseEvent;
class QWheelEvent;
class QKeyEvent;
namespace QtImGui {
class WindowWrapper {
public:
virtual ~WindowWrapper() {}
virtual void installEventFilter(QObject *object) = 0;
virtual QSize size() const = 0;
virtual qreal devicePixelRatio() const = 0;
virtual bool isActive() const = 0;
virtual QPoint mapFromGlobal(const QPoint &p) const = 0;
};
class ImGuiRenderer : public QObject, QOpenGLExtraFunctions {
Q_OBJECT
public:
void initialize(WindowWrapper *window);
void newFrame();
bool eventFilter(QObject *watched, QEvent *event);
static ImGuiRenderer *instance();
private:
ImGuiRenderer() {}
void onMousePressedChange(QMouseEvent *event);
void onWheel(QWheelEvent *event);
void onKeyPressRelease(QKeyEvent *event);
void renderDrawList(ImDrawData *draw_data);
bool createFontsTexture();
bool createDeviceObjects();
std::unique_ptr<WindowWrapper> m_window;
double g_Time = 0.0f;
bool g_MousePressed[3] = { false, false, false };
float g_MouseWheel;
float g_MouseWheelH;
GLuint g_FontTexture = 0;
int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0;
};
}

21
3rdparty/qtimgui/LICENSE vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Ryohei Ikegami
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

78
3rdparty/qtimgui/QtImGui.cpp vendored Normal file
View File

@ -0,0 +1,78 @@
#include "QtImGui.h"
#include "ImGuiRenderer.h"
#include <QWindow>
#ifdef QT_WIDGETS_LIB
#include <QWidget>
#endif
namespace QtImGui {
#ifdef QT_WIDGETS_LIB
namespace {
class QWidgetWindowWrapper : public WindowWrapper {
public:
QWidgetWindowWrapper(QWidget *w) : w(w) {}
void installEventFilter(QObject *object) override {
return w->installEventFilter(object);
}
QSize size() const override {
return w->size();
}
qreal devicePixelRatio() const override {
return w->devicePixelRatioF();
}
bool isActive() const override {
return w->isActiveWindow();
}
QPoint mapFromGlobal(const QPoint &p) const override {
return w->mapFromGlobal(p);
}
private:
QWidget *w;
};
}
void initialize(QWidget *window) {
ImGuiRenderer::instance()->initialize(new QWidgetWindowWrapper(window));
}
#endif
namespace {
class QWindowWindowWrapper : public WindowWrapper {
public:
QWindowWindowWrapper(QWindow *w) : w(w) {}
void installEventFilter(QObject *object) override {
return w->installEventFilter(object);
}
QSize size() const override {
return w->size();
}
qreal devicePixelRatio() const override {
return w->devicePixelRatio();
}
bool isActive() const override {
return w->isActive();
}
QPoint mapFromGlobal(const QPoint &p) const override {
return w->mapFromGlobal(p);
}
private:
QWindow *w;
};
}
void initialize(QWindow *window) {
ImGuiRenderer::instance()->initialize(new QWindowWindowWrapper(window));
}
void newFrame() {
ImGuiRenderer::instance()->newFrame();
}
}

15
3rdparty/qtimgui/QtImGui.h vendored Normal file
View File

@ -0,0 +1,15 @@
#pragma once
class QWidget;
class QWindow;
namespace QtImGui {
#ifdef QT_WIDGETS_LIB
void initialize(QWidget *window);
#endif
void initialize(QWindow *window);
void newFrame();
}

38
3rdparty/qtimgui/README.md vendored Normal file
View File

@ -0,0 +1,38 @@
# QtImGui
Qt (QOpenGLWidget / QOpenGLWindow) backend for [ImGui](https://github.com/ocornut/imgui)
It enables ImGui to run in QOpenGLWidget / QOpenGLWindow.
[![https://gyazo.com/eb68699c96b9147cca3d5ea9fadfc263](https://i.gyazo.com/eb68699c96b9147cca3d5ea9fadfc263.gif)](https://gyazo.com/eb68699c96b9147cca3d5ea9fadfc263)
## How to use
* Add QtImGui sources and headers to your project
* If you are using git submodule, run `git submodule update --init --recursive` to ensure that the inner submodule is initialized as well.
* Add `include(path/to/qtimgui.pri)` to youre `.pro` file
* Subclass `QOpenGLWindow` or `QOpenGLWidget` and:
```cpp
class DemoWindow : public QOpenGLWindow
{
protected:
void initializeGL() override
{
QtImGui::initialize(this);
}
void paintGL() override
{
// you can do custom GL rendering as well in paintGL
QtImGui::newFrame();
ImGui::Text("Hello");
// more widgets...
ImGui::Render();
}
};
```
See [QOpenGLWidget example](demo-widget/demo-widget.cpp) and [QOpenGLWindow example](/demo-window/demo-window.cpp) for details.

View File

@ -0,0 +1,85 @@
#include <QtImGui.h>
#include <imgui.h>
#include <QApplication>
#include <QTimer>
#include <QSurfaceFormat>
#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
class DemoWindow : public QOpenGLWidget, private QOpenGLExtraFunctions
{
protected:
void initializeGL() override
{
initializeOpenGLFunctions();
QtImGui::initialize(this);
}
void paintGL() override
{
QtImGui::newFrame();
// 1. Show a simple window
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
{
static float f = 0.0f;
ImGui::Text("Hello, world!");
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
ImGui::ColorEdit3("clear color", (float*)&clear_color);
if (ImGui::Button("Test Window")) show_test_window ^= 1;
if (ImGui::Button("Another Window")) show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
}
// 2. Show another simple window, this time using an explicit Begin/End pair
if (show_another_window)
{
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello");
ImGui::End();
}
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
if (show_test_window)
{
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
ImGui::ShowTestWindow();
}
// Do render before ImGui UI is rendered
glViewport(0, 0, width(), height());
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui::Render();
}
private:
bool show_test_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImColor(114, 144, 154);
};
int main(int argc, char *argv[])
{
// Use OpenGL 3 Core Profile
QSurfaceFormat glFormat;
glFormat.setVersion(3, 3);
glFormat.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(glFormat);
QApplication a(argc, argv);
// Show window
DemoWindow w;
w.setWindowTitle("QtImGui widget example");
w.resize(1280, 720);
w.show();
// Update at 60 fps
QTimer timer;
QObject::connect(&timer, SIGNAL(timeout()), &w, SLOT(update()));
timer.start(16);
return a.exec();
}

View File

@ -0,0 +1,8 @@
QT += core gui widgets
TARGET = demo-widget
TEMPLATE = app
include(../qtimgui.pri)
SOURCES += \
demo-widget.cpp

View File

@ -0,0 +1,85 @@
#include <QtImGui.h>
#include <imgui.h>
#include <QGuiApplication>
#include <QTimer>
#include <QSurfaceFormat>
#include <QOpenGLWindow>
#include <QOpenGLExtraFunctions>
class DemoWindow : public QOpenGLWindow, private QOpenGLExtraFunctions
{
protected:
void initializeGL() override
{
initializeOpenGLFunctions();
QtImGui::initialize(this);
}
void paintGL() override
{
QtImGui::newFrame();
// 1. Show a simple window
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
{
static float f = 0.0f;
ImGui::Text("Hello, world!");
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
ImGui::ColorEdit3("clear color", (float*)&clear_color);
if (ImGui::Button("Test Window")) show_test_window ^= 1;
if (ImGui::Button("Another Window")) show_another_window ^= 1;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
}
// 2. Show another simple window, this time using an explicit Begin/End pair
if (show_another_window)
{
ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello");
ImGui::End();
}
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
if (show_test_window)
{
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
ImGui::ShowTestWindow();
}
// Do render before ImGui UI is rendered
glViewport(0, 0, width(), height());
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui::Render();
}
private:
bool show_test_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImColor(114, 144, 154);
};
int main(int argc, char *argv[])
{
// Use OpenGL 3 Core Profile
QSurfaceFormat glFormat;
glFormat.setVersion(3, 3);
glFormat.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(glFormat);
QGuiApplication a(argc, argv);
// Show window
DemoWindow w;
w.setTitle("QtImGui window example");
w.resize(1280, 720);
w.show();
// Update at 60 fps
QTimer timer;
QObject::connect(&timer, SIGNAL(timeout()), &w, SLOT(update()));
timer.start(16);
return a.exec();
}

View File

@ -0,0 +1,8 @@
QT += core gui
TARGET = demo-window
TEMPLATE = app
include(../qtimgui.pri)
SOURCES += \
demo-window.cpp

13
3rdparty/qtimgui/qtimgui.pri vendored Normal file
View File

@ -0,0 +1,13 @@
SOURCES += \
$$PWD/imgui/imgui_draw.cpp \
$$PWD/imgui/imgui.cpp \
$$PWD/imgui/imgui_demo.cpp \
$$PWD/ImGuiRenderer.cpp \
$$PWD/QtImGui.cpp
INCLUDEPATH += $$PWD/imgui $$PWD
HEADERS += \
$$PWD/ImGuiRenderer.h \
$$PWD/QtImGui.h

3
3rdparty/qtimgui/qtimgui.pro vendored Normal file
View File

@ -0,0 +1,3 @@
TEMPLATE = subdirs
SUBDIRS += demo-widget demo-window