mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 10:19:59 +01:00
More options in the toolbox. User settings for selection of blit render
mode.
This commit is contained in:
@@ -51,7 +51,7 @@ void FrameBuffer::init()
|
|||||||
glBindFramebuffer(GL_FRAMEBUFFER, framebufferid_);
|
glBindFramebuffer(GL_FRAMEBUFFER, framebufferid_);
|
||||||
|
|
||||||
// take settings into account: no multisampling for level 0
|
// take settings into account: no multisampling for level 0
|
||||||
use_multi_sampling_ &= Settings::application.multisampling_level > 0;
|
use_multi_sampling_ &= Settings::application.render_multisampling > 0;
|
||||||
|
|
||||||
if (use_multi_sampling_){
|
if (use_multi_sampling_){
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ void FrameBuffer::init()
|
|||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, intermediate_textureid_);
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, intermediate_textureid_);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Settings::application.multisampling_level,
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Settings::application.render_multisampling,
|
||||||
use_alpha_ ? GL_RGBA : GL_RGB, attrib_.viewport.x, attrib_.viewport.y, GL_TRUE);
|
use_alpha_ ? GL_RGBA : GL_RGB, attrib_.viewport.x, attrib_.viewport.y, GL_TRUE);
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ bool Rendering::init()
|
|||||||
//
|
//
|
||||||
// OpenGL Multisampling main window
|
// OpenGL Multisampling main window
|
||||||
//
|
//
|
||||||
glfwWindowHint(GLFW_SAMPLES, Settings::application.multisampling_level);
|
glfwWindowHint(GLFW_SAMPLES, Settings::application.render_multisampling);
|
||||||
main_.init(0);
|
main_.init(0);
|
||||||
// set application icon
|
// set application icon
|
||||||
main_.setIcon("images/vimix_256x256.png");
|
main_.setIcon("images/vimix_256x256.png");
|
||||||
@@ -209,23 +209,21 @@ void Rendering::pushBackDrawCallback(RenderingCallback function)
|
|||||||
|
|
||||||
void Rendering::draw()
|
void Rendering::draw()
|
||||||
{
|
{
|
||||||
// Poll and handle events (inputs, window resize, etc.)
|
|
||||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
|
||||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
|
||||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
|
||||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
|
||||||
glfwPollEvents();
|
|
||||||
|
|
||||||
|
// operate on main window context
|
||||||
main_.makeCurrent();
|
main_.makeCurrent();
|
||||||
|
|
||||||
|
// User Interface step 1
|
||||||
UserInterface::manager().NewFrame();
|
UserInterface::manager().NewFrame();
|
||||||
|
|
||||||
|
// Custom draw
|
||||||
std::list<Rendering::RenderingCallback>::iterator iter;
|
std::list<Rendering::RenderingCallback>::iterator iter;
|
||||||
for (iter=draw_callbacks_.begin(); iter != draw_callbacks_.end(); iter++)
|
for (iter=draw_callbacks_.begin(); iter != draw_callbacks_.end(); iter++)
|
||||||
{
|
{
|
||||||
(*iter)();
|
(*iter)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// User Interface step 2
|
||||||
UserInterface::manager().Render();
|
UserInterface::manager().Render();
|
||||||
|
|
||||||
// perform screenshot if requested
|
// perform screenshot if requested
|
||||||
@@ -238,11 +236,18 @@ void Rendering::draw()
|
|||||||
// swap GL buffers
|
// swap GL buffers
|
||||||
glfwSwapBuffers(main_.window());
|
glfwSwapBuffers(main_.window());
|
||||||
|
|
||||||
|
// draw output window (and swap buffer output)
|
||||||
|
output_.draw( Mixer::manager().session()->frame() );
|
||||||
|
|
||||||
|
// Poll and handle events (inputs, window resize, etc.)
|
||||||
|
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||||
|
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||||
|
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||||
|
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||||
|
glfwPollEvents();
|
||||||
|
|
||||||
// no g_main_loop_run(loop) : update global GMainContext
|
// no g_main_loop_run(loop) : update global GMainContext
|
||||||
g_main_context_iteration(NULL, FALSE);
|
g_main_context_iteration(NULL, FALSE);
|
||||||
|
|
||||||
// draw output window
|
|
||||||
output_.draw( Mixer::manager().session()->frame() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -523,11 +528,12 @@ bool RenderingWindow::init(int id, GLFWwindow *share)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// store global ref to pointers (used by callbacks)
|
|
||||||
GLFW_window_[window_] = this;
|
|
||||||
|
|
||||||
// set position
|
// set position
|
||||||
glfwSetWindowPos(window_, winset.x, winset.y);
|
glfwSetWindowPos(window_, winset.x, winset.y);
|
||||||
|
|
||||||
|
/// CALLBACKS
|
||||||
|
// store global ref to pointers (used by callbacks)
|
||||||
|
GLFW_window_[window_] = this;
|
||||||
// window position and resize callbacks
|
// window position and resize callbacks
|
||||||
glfwSetWindowSizeCallback( window_, WindowResizeCallback );
|
glfwSetWindowSizeCallback( window_, WindowResizeCallback );
|
||||||
// glfwSetFramebufferSizeCallback( window_, WindowResizeCallback );
|
// glfwSetFramebufferSizeCallback( window_, WindowResizeCallback );
|
||||||
@@ -536,11 +542,11 @@ bool RenderingWindow::init(int id, GLFWwindow *share)
|
|||||||
// take opengl context ownership
|
// take opengl context ownership
|
||||||
glfwMakeContextCurrent(window_);
|
glfwMakeContextCurrent(window_);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize OpenGL loader on first call
|
||||||
|
//
|
||||||
static bool glad_initialized = false;
|
static bool glad_initialized = false;
|
||||||
if ( !glad_initialized ) {
|
if ( !glad_initialized ) {
|
||||||
//
|
|
||||||
// Initialize OpenGL loader
|
|
||||||
//
|
|
||||||
bool err = gladLoadGLLoader((GLADloadproc) glfwGetProcAddress) == 0;
|
bool err = gladLoadGLLoader((GLADloadproc) glfwGetProcAddress) == 0;
|
||||||
if (err) {
|
if (err) {
|
||||||
Log::Error("Failed to initialize GLAD OpenGL loader.");
|
Log::Error("Failed to initialize GLAD OpenGL loader.");
|
||||||
@@ -566,7 +572,7 @@ bool RenderingWindow::init(int id, GLFWwindow *share)
|
|||||||
// no need for multisampling
|
// no need for multisampling
|
||||||
glDisable(GL_MULTISAMPLE);
|
glDisable(GL_MULTISAMPLE);
|
||||||
// clear to black
|
// clear to black
|
||||||
window_attributes_.clear_color = glm::vec4(0.f, 0.f, 0.f, 1.0);
|
window_attributes_.clear_color = glm::vec4(0.f, 0.f, 0.f, 1.f);
|
||||||
// give back context ownership
|
// give back context ownership
|
||||||
glfwMakeContextCurrent(master_);
|
glfwMakeContextCurrent(master_);
|
||||||
}
|
}
|
||||||
@@ -574,12 +580,12 @@ bool RenderingWindow::init(int id, GLFWwindow *share)
|
|||||||
// Enable vsync on main window
|
// Enable vsync on main window
|
||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
// enable Antialiasing multisampling
|
// enable Antialiasing multisampling
|
||||||
if (Settings::application.multisampling_level > 0) {
|
if (Settings::application.render_multisampling > 0) {
|
||||||
glEnable(GL_MULTISAMPLE);
|
glEnable(GL_MULTISAMPLE);
|
||||||
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
|
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
|
||||||
}
|
}
|
||||||
// clear to grey
|
// clear to grey
|
||||||
window_attributes_.clear_color = glm::vec4(COLOR_BGROUND, 1.0);
|
window_attributes_.clear_color = glm::vec4(COLOR_BGROUND, 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -635,7 +641,7 @@ void RenderingWindow::makeCurrent()
|
|||||||
|
|
||||||
void RenderingWindow::draw(FrameBuffer *fb)
|
void RenderingWindow::draw(FrameBuffer *fb)
|
||||||
{
|
{
|
||||||
if (!window_)
|
if (!window_ || !fb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// only draw if window is not iconified
|
// only draw if window is not iconified
|
||||||
@@ -651,84 +657,78 @@ void RenderingWindow::draw(FrameBuffer *fb)
|
|||||||
Rendering::manager().pushAttrib(window_attributes_);
|
Rendering::manager().pushAttrib(window_attributes_);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
// draw frame buffer provided
|
// blit framebuffer
|
||||||
if (fb) {
|
if (Settings::application.render_blit) {
|
||||||
|
static int attached_textureid_fbo_ = 0;
|
||||||
|
static uint local_fbo_ = 0;
|
||||||
|
if ( attached_textureid_fbo_ != fb->texture()) {
|
||||||
|
|
||||||
if (false) {
|
// create a new fbo in this opengl context
|
||||||
// VAO is not shared between multiple contexts of different windows
|
if (local_fbo_ != 0)
|
||||||
// so we have to create a new VAO for rendering the surface in this window
|
glDeleteFramebuffers(1, &local_fbo_);
|
||||||
static WindowSurface *surface = new WindowSurface;
|
glGenFramebuffers(1, &local_fbo_);
|
||||||
static glm::mat4 projection = glm::ortho(-1.f, 1.f, -1.f, 1.f, -1.f, 1.f);
|
glBindFramebuffer(GL_FRAMEBUFFER, local_fbo_);
|
||||||
|
|
||||||
// calculate scaling factor of frame buffer inside window
|
// attach the 2D texture to local FBO
|
||||||
float windowAspectRatio = aspectRatio();
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture(), 0);
|
||||||
float renderingAspectRatio = fb->aspectRatio();
|
attached_textureid_fbo_ = fb->texture();
|
||||||
glm::vec3 scale;
|
|
||||||
if (windowAspectRatio < renderingAspectRatio)
|
|
||||||
scale = glm::vec3(1.f, windowAspectRatio / renderingAspectRatio, 1.f);
|
|
||||||
else
|
|
||||||
scale = glm::vec3(renderingAspectRatio / windowAspectRatio, 1.f, 1.f);
|
|
||||||
|
|
||||||
// draw
|
Log::Info("Blit to output window enabled.");
|
||||||
ShadingProgram::enduse();
|
|
||||||
glBindTexture(GL_TEXTURE_2D, fb->texture());
|
|
||||||
// surface->shader()->color.a = 0.4f; // TODO alpha blending ?
|
|
||||||
surface->draw(glm::scale(glm::identity<glm::mat4>(), scale), projection);
|
|
||||||
|
|
||||||
// done drawing
|
|
||||||
ShadingProgram::enduse();
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
|
||||||
static int attached_textureid_fbo_ = 0;
|
|
||||||
static uint local_fbo_ = 0;
|
|
||||||
if ( attached_textureid_fbo_ != fb->texture()) {
|
|
||||||
|
|
||||||
// create a new fbo in this opengl context
|
|
||||||
if (local_fbo_ != 0)
|
|
||||||
glDeleteFramebuffers(1, &local_fbo_);
|
|
||||||
glGenFramebuffers(1, &local_fbo_);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, local_fbo_);
|
|
||||||
|
|
||||||
// attach the 2D texture to local FBO
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture(), 0);
|
|
||||||
attached_textureid_fbo_ = fb->texture();
|
|
||||||
|
|
||||||
Log::Info("Blit to output window enabled.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate scaling factor of frame buffer inside window
|
|
||||||
int rx, ry, rw, rh;
|
|
||||||
float renderingAspectRatio = fb->aspectRatio();
|
|
||||||
if (aspectRatio() < renderingAspectRatio) {
|
|
||||||
int nh = (int)( float(window_attributes_.viewport.x) / renderingAspectRatio);
|
|
||||||
rx = 0;
|
|
||||||
ry = (window_attributes_.viewport.y - nh) / 2;
|
|
||||||
rw = window_attributes_.viewport.x;
|
|
||||||
rh = (window_attributes_.viewport.y + nh) / 2;
|
|
||||||
} else {
|
|
||||||
int nw = (int)( float(window_attributes_.viewport.y) * renderingAspectRatio );
|
|
||||||
rx = (window_attributes_.viewport.x - nw) / 2;
|
|
||||||
ry = 0;
|
|
||||||
rw = (window_attributes_.viewport.x + nw) / 2;
|
|
||||||
rh = window_attributes_.viewport.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// select fbo texture read target
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, local_fbo_);
|
|
||||||
|
|
||||||
// select screen target
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
||||||
|
|
||||||
// glBlitFramebuffer(0, 0, fb->width(), fb->height(), 0, 0, window_attributes_.viewport.x, window_attributes_.viewport.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
|
||||||
glBlitFramebuffer(0, fb->height(), fb->width(), 0, rx, ry, rw, rh, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
||||||
|
|
||||||
|
// calculate scaling factor of frame buffer inside window
|
||||||
|
int rx, ry, rw, rh;
|
||||||
|
float renderingAspectRatio = fb->aspectRatio();
|
||||||
|
if (aspectRatio() < renderingAspectRatio) {
|
||||||
|
int nh = (int)( float(window_attributes_.viewport.x) / renderingAspectRatio);
|
||||||
|
rx = 0;
|
||||||
|
ry = (window_attributes_.viewport.y - nh) / 2;
|
||||||
|
rw = window_attributes_.viewport.x;
|
||||||
|
rh = (window_attributes_.viewport.y + nh) / 2;
|
||||||
|
} else {
|
||||||
|
int nw = (int)( float(window_attributes_.viewport.y) * renderingAspectRatio );
|
||||||
|
rx = (window_attributes_.viewport.x - nw) / 2;
|
||||||
|
ry = 0;
|
||||||
|
rw = (window_attributes_.viewport.x + nw) / 2;
|
||||||
|
rh = window_attributes_.viewport.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// select fbo texture read target
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, local_fbo_);
|
||||||
|
|
||||||
|
// select screen target
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
// glBlitFramebuffer(0, 0, fb->width(), fb->height(), 0, 0, window_attributes_.viewport.x, window_attributes_.viewport.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||||
|
glBlitFramebuffer(0, fb->height(), fb->width(), 0, rx, ry, rw, rh, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
// draw geometry
|
||||||
Log::Info("No Framebuffer Provided to draw Rendering Window");
|
else
|
||||||
|
{
|
||||||
|
// VAO is not shared between multiple contexts of different windows
|
||||||
|
// so we have to create a new VAO for rendering the surface in this window
|
||||||
|
static WindowSurface *surface = new WindowSurface;
|
||||||
|
static glm::mat4 projection = glm::ortho(-1.f, 1.f, -1.f, 1.f, -1.f, 1.f);
|
||||||
|
|
||||||
|
// calculate scaling factor of frame buffer inside window
|
||||||
|
float windowAspectRatio = aspectRatio();
|
||||||
|
float renderingAspectRatio = fb->aspectRatio();
|
||||||
|
glm::vec3 scale;
|
||||||
|
if (windowAspectRatio < renderingAspectRatio)
|
||||||
|
scale = glm::vec3(1.f, windowAspectRatio / renderingAspectRatio, 1.f);
|
||||||
|
else
|
||||||
|
scale = glm::vec3(renderingAspectRatio / windowAspectRatio, 1.f, 1.f);
|
||||||
|
|
||||||
|
// draw
|
||||||
|
ShadingProgram::enduse();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, fb->texture());
|
||||||
|
// surface->shader()->color.a = 0.4f; // TODO alpha blending ?
|
||||||
|
surface->draw(glm::scale(glm::identity<glm::mat4>(), scale), projection);
|
||||||
|
|
||||||
|
// done drawing
|
||||||
|
ShadingProgram::enduse();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore attribs
|
// restore attribs
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ void Settings::Save()
|
|||||||
applicationNode->SetAttribute("toolbox", application.toolbox);
|
applicationNode->SetAttribute("toolbox", application.toolbox);
|
||||||
applicationNode->SetAttribute("framebuffer_ar", application.framebuffer_ar);
|
applicationNode->SetAttribute("framebuffer_ar", application.framebuffer_ar);
|
||||||
applicationNode->SetAttribute("framebuffer_h", application.framebuffer_h);
|
applicationNode->SetAttribute("framebuffer_h", application.framebuffer_h);
|
||||||
applicationNode->SetAttribute("multisampling_level", application.multisampling_level);
|
applicationNode->SetAttribute("multisampling_level", application.render_multisampling);
|
||||||
|
applicationNode->SetAttribute("render_blit", application.render_blit);
|
||||||
pRoot->InsertEndChild(applicationNode);
|
pRoot->InsertEndChild(applicationNode);
|
||||||
|
|
||||||
// bloc views
|
// bloc views
|
||||||
@@ -169,7 +170,8 @@ void Settings::Load()
|
|||||||
pElement->QueryIntAttribute("stats_corner", &application.stats_corner);
|
pElement->QueryIntAttribute("stats_corner", &application.stats_corner);
|
||||||
pElement->QueryIntAttribute("framebuffer_ar", &application.framebuffer_ar);
|
pElement->QueryIntAttribute("framebuffer_ar", &application.framebuffer_ar);
|
||||||
pElement->QueryIntAttribute("framebuffer_h", &application.framebuffer_h);
|
pElement->QueryIntAttribute("framebuffer_h", &application.framebuffer_h);
|
||||||
pElement->QueryIntAttribute("multisampling_level", &application.multisampling_level);
|
pElement->QueryIntAttribute("multisampling_level", &application.render_multisampling);
|
||||||
|
pElement->QueryBoolAttribute("render_blit", &application.render_blit);
|
||||||
|
|
||||||
// bloc windows
|
// bloc windows
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -77,7 +77,8 @@ struct Application
|
|||||||
std::map<int, ViewConfig> views;
|
std::map<int, ViewConfig> views;
|
||||||
int framebuffer_ar;
|
int framebuffer_ar;
|
||||||
int framebuffer_h;
|
int framebuffer_h;
|
||||||
int multisampling_level;
|
int render_multisampling;
|
||||||
|
bool render_blit;
|
||||||
|
|
||||||
// multiple windows handling
|
// multiple windows handling
|
||||||
std::vector<WindowConfig> windows;
|
std::vector<WindowConfig> windows;
|
||||||
@@ -100,7 +101,8 @@ struct Application
|
|||||||
current_view = 1;
|
current_view = 1;
|
||||||
framebuffer_ar = 3;
|
framebuffer_ar = 3;
|
||||||
framebuffer_h = 1;
|
framebuffer_h = 1;
|
||||||
multisampling_level = 2; // todo GUI selection
|
render_multisampling = 2; // todo GUI selection
|
||||||
|
render_blit = false;
|
||||||
std::vector<int> second (4,100);
|
std::vector<int> second (4,100);
|
||||||
windows = std::vector<WindowConfig>(3);
|
windows = std::vector<WindowConfig>(3);
|
||||||
windows[0].name = APP_NAME APP_TITLE;
|
windows[0].name = APP_NAME APP_TITLE;
|
||||||
|
|||||||
@@ -678,14 +678,20 @@ void ToolBox::Render()
|
|||||||
// Menu Bar
|
// Menu Bar
|
||||||
if (ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
{
|
{
|
||||||
if (ImGui::BeginMenu("Tools"))
|
if (ImGui::BeginMenu("Render"))
|
||||||
{
|
{
|
||||||
if ( ImGui::MenuItem( ICON_FA_CAMERA_RETRO " Screenshot", NULL) )
|
if ( ImGui::MenuItem( ICON_FA_CAMERA_RETRO " Screenshot") )
|
||||||
UserInterface::manager().StartScreenshot();
|
UserInterface::manager().StartScreenshot();
|
||||||
|
|
||||||
ImGui::MenuItem("Dev", NULL, false, false);
|
ImGui::MenuItem("Blit", nullptr, &Settings::application.render_blit);
|
||||||
ImGui::MenuItem("Icons", NULL, &show_icons_window);
|
ImGui::MenuItem("Multisampling", nullptr, (Settings::application.render_multisampling > 0), false);
|
||||||
ImGui::MenuItem("Demo ImGui", NULL, &show_demo_window);
|
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
if (ImGui::BeginMenu("Dev"))
|
||||||
|
{
|
||||||
|
ImGui::MenuItem("Icons", nullptr, &show_icons_window);
|
||||||
|
ImGui::MenuItem("Demo ImGui", nullptr, &show_demo_window);
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user