Add ImGui

This commit is contained in:
Devang 2024-05-24 13:06:38 +05:30
parent e6b8753a8a
commit 368e08ed1f
17 changed files with 249 additions and 69 deletions

4
.gitignore vendored
View File

@ -362,4 +362,6 @@ MigrationBackup/
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
FodyWeavers.xsd
naming.txt

View File

@ -4,6 +4,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
add_subdirectory(vendor/spdlog)
add_subdirectory(vendor/glfw)
add_subdirectory(vendor/glad)
add_subdirectory(vendor/imgui)
set(SRC_FILES "source/core/log.cpp"
"source/core/application.cpp"
@ -11,6 +12,7 @@ set(SRC_FILES "source/core/log.cpp"
"source/opengl/dsgl_renderer.cpp"
"source/core/id.cpp"
"source/core/timer.cpp"
"source/core/ui_layer.cpp"
"source/core/layer.cpp")
set(HEADER_FILES "include/DS/application.hpp"
@ -21,11 +23,12 @@ set(HEADER_FILES "include/DS/application.hpp"
"include/DS/layer.hpp"
"include/DS/timer.hpp"
"include/DS/id.hpp"
"include/DS/ui_layer.hpp"
"include/DS.h" )
add_library (DS ${SRC_FILES} ${HEADER_FILES})
target_include_directories(DS PUBLIC ./include/DS ./include vendor/spdlog/include vendor/glfw/include vendor/glad/include vendor/glm)
target_link_libraries(DS spdlog glfw glad)
target_include_directories(DS PUBLIC ./include/DS ./include vendor/spdlog/include vendor/glfw/include vendor/glad/include vendor/glm vendor/imgui)
target_link_libraries(DS spdlog glfw glad imgui)
target_precompile_headers(DS PUBLIC <memory> <vector> <string> <unordered_map> <unordered_set> <string_view> <stdint.h>)

View File

@ -4,6 +4,11 @@
#include "common.hpp"
#include "window.hpp"
#include "layer.hpp"
#include "ui_layer.hpp"
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
namespace DS
{
@ -20,10 +25,12 @@ namespace DS
class Application
{
friend AppInstancer;
friend UILayer;
private:
AppInfo m_info;
std::vector<Layer *> m_layers;
std::unique_ptr<UILayer> m_uiLayer;
public:
std::shared_ptr<Window> m_window;
@ -36,18 +43,25 @@ namespace DS
void load_gl();
virtual void on_start();
// called after all layers are updated
virtual void on_update();
virtual void on_close();
virtual void on_ui();
public:
Application(AppInfo info = {800, 600, "DS ENGINE"});
~Application();
inline void imgui_demo()
{
m_uiLayer->m_showDemo = !m_uiLayer->m_showDemo;
}
template <typename T>
void push_layer()
{
m_layers.push_back(new T());
m_layers[m_layers.size() - 1]->on_attach();
m_layers[m_layers.size() - 1]->on_attach(this);
}
void pop_layer();

View File

@ -6,6 +6,8 @@
namespace DS
{
class Application;
class Layer
{
private:
@ -13,10 +15,10 @@ namespace DS
Layer();
~Layer() = default;
virtual void on_attach();
virtual void on_detach();
virtual void on_update();
virtual void on_ui();
virtual void on_attach(Application *app);
virtual void on_detach(Application *app);
virtual void on_update(Application *app);
virtual void on_ui(Application *app);
UUID id;
};

View File

@ -0,0 +1,26 @@
#ifndef DS_UI_LAYER_HPP
#define DS_UI_LAYER_HPP
#include "layer.hpp"
namespace DS
{
class UILayer : public Layer
{
public:
bool m_showDemo;
public:
UILayer();
~UILayer();
void on_attach(Application *app) override;
void on_detach(Application *app) override;
void on_update(Application *app) override;
void on_ui(Application *app) override;
void change_style();
};
} // namespace DS
#endif

View File

@ -3,7 +3,6 @@
#include "common.hpp"
namespace DS
{
class Application;
@ -11,7 +10,7 @@ namespace DS
class Window
{
private:
GLFWwindow* m_glfwWindow;
GLFWwindow *m_glfwWindow;
int m_width, m_height;
static bool s_glfwInitialized;
@ -24,10 +23,11 @@ namespace DS
Window();
~Window();
void create(int width, int height, const char* title, bool make_current=true);
void create(int width, int height, const char *title, bool make_current = true);
CGETTER(int, get_width, m_width);
CGETTER(int, get_height, m_height);
CGETTER(GLFWwindow *, get_win, m_glfwWindow);
bool should_close();
void swap_buffers();

View File

@ -34,6 +34,7 @@ namespace DS
m_window = std::make_shared<Window>();
gl_loaded = false;
m_info = info;
m_uiLayer = std::make_unique<UILayer>();
}
Application::~Application()
@ -41,9 +42,41 @@ namespace DS
Window::terminate_glfw();
}
void Application::on_start() {}
void Application::on_update() {}
void Application::on_close() {}
void Application::on_start()
{
glfwSetErrorCallback(glfw_error_callback);
m_window->create(m_info.width, m_info.height, m_info.title);
load_gl();
}
void Application::on_update()
{
glClearColor(0.3f, 0.2f, 0.3f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
for (Layer *layer : m_layers)
{
layer->on_update(this);
}
m_uiLayer->on_update(this);
Window::poll_events();
m_window->swap_buffers();
}
void Application::on_close()
{
}
void Application::on_ui()
{
for (Layer *layer : m_layers)
{
layer->on_ui(this);
}
m_uiLayer->on_ui(this);
}
void Application::load_gl()
{
@ -61,22 +94,18 @@ namespace DS
void Application::run()
{
glfwSetErrorCallback(glfw_error_callback);
m_window->create(m_info.width, m_info.height, m_info.title);
load_gl();
on_start();
m_uiLayer->on_attach(this);
while (!m_window->should_close())
{
Window::poll_events();
on_update();
}
for (Layer *layer : m_layers)
{
layer->on_update();
}
m_window->swap_buffers();
while (m_layers.size() != 0)
{
pop_layer();
m_uiLayer->on_detach(this);
}
on_close();
@ -87,7 +116,7 @@ namespace DS
void Application::pop_layer()
{
Layer *l = m_layers[m_layers.size() - 1];
l->on_detach();
l->on_detach(this);
delete l;
m_layers.pop_back();
}

View File

@ -7,11 +7,11 @@ namespace DS
DS_INFO("{}", id.to_uint64());
}
void Layer::on_attach() {}
void Layer::on_attach(Application *app) {}
void Layer::on_detach() {}
void Layer::on_detach(Application *app) {}
void Layer::on_update() {}
void Layer::on_update(Application *app) {}
void Layer::on_ui() {}
void Layer::on_ui(Application *app) {}
}

View File

@ -0,0 +1,88 @@
#include "ui_layer.hpp"
#include "application.hpp"
namespace DS
{
UILayer::UILayer() : m_showDemo(false)
{
}
UILayer::~UILayer()
{
}
void UILayer::change_style()
{
ImGuiIO &io = ImGui::GetIO();
ImGuiStyle &style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
style.Colors[ImGuiCol_TableHeaderBg] = ImVec4(0.2f, 0.2f, 0.4f, 1.0f);
style.Colors[ImGuiCol_FrameBg] = ImVec4(0.15f, 0.15f, 0.15f, 1.0f);
style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.2f, 0.2f, 0.2f, 1.0f);
style.Colors[ImGuiCol_Header] = ImVec4(0.3f, 0.3f, 0.3f, 1.0f);
style.Colors[ImGuiCol_Button] = ImVec4(0.3f, 0.3f, 0.3f, 1.0f);
style.Colors[ImGuiCol_Tab] = ImVec4(0.3f, 0.3f, 0.3f, 1.0f);
style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.3f, 0.3f, 0.3f, 1.0f);
}
// INIT IMGUI
void UILayer::on_attach(Application *app)
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO &io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
ImGui::StyleColorsDark();
change_style();
const char *glsl_version = "#version 330 core";
ImGui_ImplGlfw_InitForOpenGL(app->m_window->get_win(), true);
ImGui_ImplOpenGL3_Init(glsl_version);
}
void UILayer::on_detach(Application *app)
{
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
}
void UILayer::on_update(Application *app)
{
// IMGUI
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
app->on_ui();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
auto io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow *backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backup_current_context);
}
}
void UILayer::on_ui(Application *app)
{
if (m_showDemo)
ImGui::ShowDemoWindow(&m_showDemo);
}
} // namespace DS

View File

@ -1,3 +1,4 @@
project(imgui)
add_library(imgui imgui.cpp imgui_demo.cpp imgui_draw.cpp imgui_tables.cpp imgui_widgets.cpp backends/)
add_library(imgui imgui.cpp imgui_demo.cpp imgui_draw.cpp imgui_tables.cpp imgui_widgets.cpp imgui_impl_glfw.cpp imgui_impl_opengl3.cpp)
target_include_directories(imgui PRIVATE ../glfw/include)

View File

@ -29,43 +29,43 @@
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#endif
static void glfw_error_callback(int error, const char* description)
static void glfw_error_callback(int error, const char *description)
{
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
}
// Main code
int main(int, char**)
int main(int, char **)
{
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit())
return 1;
// Decide GL+GLSL versions
// Decide GL+GLSL versions
#if defined(IMGUI_IMPL_OPENGL_ES2)
// GL ES 2.0 + GLSL 100
const char* glsl_version = "#version 100";
const char *glsl_version = "#version 100";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#elif defined(__APPLE__)
// GL 3.2 + GLSL 150
const char* glsl_version = "#version 150";
const char *glsl_version = "#version 150";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
#else
// GL 3.0 + GLSL 130
const char* glsl_version = "#version 130";
const char *glsl_version = "#version 130";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
// glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
// glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
#endif
// Create window with graphics context
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL3 example", nullptr, nullptr);
GLFWwindow *window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL3 example", nullptr, nullptr);
if (window == nullptr)
return 1;
glfwMakeContextCurrent(window);
@ -74,20 +74,21 @@ int main(int, char**)
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true;
ImGuiIO &io = ImGui::GetIO();
(void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
// io.ConfigViewportsNoAutoMerge = true;
// io.ConfigViewportsNoTaskBarIcon = true;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// ImGui::StyleColorsLight();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
ImGuiStyle &style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
@ -110,13 +111,13 @@ int main(int, char**)
// - Read 'docs/FONTS.md' for more instructions and details.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != nullptr);
// io.Fonts->AddFontDefault();
// io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
// io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
// io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
// io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
// ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
// IM_ASSERT(font != nullptr);
// Our state
bool show_demo_window = true;
@ -154,16 +155,16 @@ int main(int, char**)
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float *)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
@ -175,7 +176,7 @@ int main(int, char**)
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
@ -196,7 +197,7 @@ int main(int, char**)
// For this specific demo app we could also call glfwMakeContextCurrent(window) directly)
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow* backup_current_context = glfwGetCurrentContext();
GLFWwindow *backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backup_current_context);

View File

@ -9,11 +9,25 @@ public:
{
}
public:
virtual void on_update() override
private:
virtual void on_update(DS::Application *app) override
{
glClearColor(0.3f, 0.2f, 0.3f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
}
virtual void on_ui(DS::Application *app) override
{
ImGui::Begin("DS Debug Window");
ImGui::Text("Hello, World!");
if (ImGui::Button("Show/Hide Demo", ImVec2(120, 30)))
{
app->imgui_demo();
}
ImGui::End();
}
virtual void on_detach(DS::Application *app) override
{
DS_INFO("Detached test layer");
}
};