From e77a7caf7467dd9f547732b50cb875f068886a6d Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 20 Dec 2018 20:31:14 +0100 Subject: [PATCH] rwgame: add imgui demo window --- rwgame/CMakeLists.txt | 15 ++++ rwgame/GameBase.cpp | 2 +- rwgame/GameWindow.hpp | 7 +- rwgame/RWGame.cpp | 12 ++- rwgame/RWGame.hpp | 3 + rwgame/RWImGui.cpp | 177 ++++++++++++++++++++++++++++++++++++++++++ rwgame/RWImGui.hpp | 21 +++++ 7 files changed, 233 insertions(+), 4 deletions(-) create mode 100644 rwgame/RWImGui.cpp create mode 100644 rwgame/RWImGui.hpp diff --git a/rwgame/CMakeLists.txt b/rwgame/CMakeLists.txt index 2d555a8b..3996ef0a 100644 --- a/rwgame/CMakeLists.txt +++ b/rwgame/CMakeLists.txt @@ -15,6 +15,9 @@ add_library(librwgame STATIC GameWindow.hpp GameWindow.cpp + RWImGui.cpp + RWImGui.hpp + HUDDrawer.hpp HUDDrawer.cpp MenuSystem.hpp @@ -68,6 +71,18 @@ target_link_libraries(librwgame SDL2::SDL2 ) +if(ENABLE_IMGUI) + target_compile_definitions(librwgame + PUBLIC + RW_IMGUI + ) + + target_link_libraries(librwgame + PUBLIC + imgui::sdl_gl3 + ) +endif() + add_executable(rwgame main.cpp ) diff --git a/rwgame/GameBase.cpp b/rwgame/GameBase.cpp index c827d32d..1d73f661 100644 --- a/rwgame/GameBase.cpp +++ b/rwgame/GameBase.cpp @@ -20,7 +20,7 @@ GameBase::GameBase(Logger &inlog, const std::optional &args) : bool fullscreen = config.fullscreen(); size_t w = config.width(), h = config.height(); - if (SDL_Init(SDL_INIT_VIDEO) < 0) + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) throw std::runtime_error("Failed to initialize SDL2!"); window.create(kWindowTitle + " [" + kBuildStr + "]", w, h, fullscreen); diff --git a/rwgame/GameWindow.hpp b/rwgame/GameWindow.hpp index 7d69d852..800a7ff0 100644 --- a/rwgame/GameWindow.hpp +++ b/rwgame/GameWindow.hpp @@ -5,8 +5,9 @@ #include #include - #include +#include +#include class GameWindow { SDL_Window* window = nullptr; @@ -30,6 +31,10 @@ public: bool isOpen() const { return !!window; } + + std::tuple getSDLContext() { + return std::make_tuple(window, glcontext); + } }; #endif diff --git a/rwgame/RWGame.cpp b/rwgame/RWGame.cpp index bbfed79f..7af0232a 100644 --- a/rwgame/RWGame.cpp +++ b/rwgame/RWGame.cpp @@ -2,6 +2,7 @@ #include +#include "RWImGui.hpp" #include "GameInput.hpp" #include "State.hpp" #include "StateManager.hpp" @@ -28,7 +29,6 @@ #include #include #include -#include #ifdef _MSC_VER #pragma warning(disable : 4305 5033) @@ -54,7 +54,8 @@ constexpr float kMaxPhysicsSubSteps = 2; RWGame::RWGame(Logger& log, const std::optional &args) : GameBase(log, args) , data(&log, config.gamedataPath()) - , renderer(&log, &data) { + , renderer(&log, &data) + , imgui(*this) { RW_PROFILE_THREAD("Main"); RW_TIMELINE_ENTER("Startup", MP_YELLOW); @@ -76,6 +77,8 @@ RWGame::RWGame(Logger& log, const std::optional &args) config.gamedataPath()); } + imgui.init(); + data.load(); for (const auto& [specialModel, fileName, name] : kSpecialModels) { @@ -480,6 +483,9 @@ bool RWGame::updateInput() { RW_PROFILE_SCOPE(__func__); SDL_Event event; while (SDL_PollEvent(&event)) { + if (imgui.process_event(event)) { + continue; + } switch (event.type) { case SDL_QUIT: return false; @@ -669,6 +675,8 @@ void RWGame::render(float alpha, float time) { RW_PROFILE_SCOPE("state"); stateManager.draw(renderer); } + + imgui.tick(); } void RWGame::renderDebugView(float time, ViewCamera &viewCam) { diff --git a/rwgame/RWGame.hpp b/rwgame/RWGame.hpp index 965a02ff..d8910f50 100644 --- a/rwgame/RWGame.hpp +++ b/rwgame/RWGame.hpp @@ -3,6 +3,8 @@ #include "GameBase.hpp" #include "HUDDrawer.hpp" +#include "RWConfig.hpp" +#include "RWImGui.hpp" #include "StateManager.hpp" #include "game.hpp" @@ -22,6 +24,7 @@ class RWGame final : public GameBase { GameData data; GameRenderer renderer; + RWImGui imgui; DebugDraw debug; GameState state; HUDDrawer hudDrawer{}; diff --git a/rwgame/RWImGui.cpp b/rwgame/RWImGui.cpp new file mode 100644 index 00000000..a9ac63d0 --- /dev/null +++ b/rwgame/RWImGui.cpp @@ -0,0 +1,177 @@ +#include "RWImGui.hpp" + +#ifdef RW_IMGUI + +#include "RWGame.hpp" + +#include +#include +#include + +#include + +RWImGui::RWImGui(RWGame &game) + : _game(game) { +} + +RWImGui::~RWImGui() { + destroy(); +} + +void RWImGui::init() { + IMGUI_CHECKVERSION(); + _context = ImGui::CreateContext(); + + auto [window, context] = _game.getWindow().getSDLContext(); + + ImGui_ImplSDL2_InitForOpenGL(window, context); + ImGui_ImplOpenGL3_Init("#version 150"); +} + +void RWImGui::destroy() { + if (!_context) { + return; + } + ImGui::SetCurrentContext(_context); + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplSDL2_Shutdown(); + ImGui::DestroyContext(); + _context = nullptr; +} + +bool RWImGui::process_event(SDL_Event &event) { + if (!_context) { + return false; + } + ImGui::SetCurrentContext(_context); + ImGui_ImplSDL2_ProcessEvent(&event); + auto& io = ImGui::GetIO(); + return io.WantCaptureMouse || io.WantCaptureKeyboard; +} + +void RWImGui::tick() { + if (!_context) { + return; + } + ImGui::SetCurrentContext(_context); + auto& io = ImGui::GetIO(); + + SDL_Window *window; + std::tie(window, std::ignore) = _game.getWindow().getSDLContext(); + + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplSDL2_NewFrame(window); + ImGui::NewFrame(); + + static float f = 0.0f; + + ImGui::Begin("Hello, world!"); + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", static_cast(1000.0f / io.Framerate), static_cast(io.Framerate)); ImGui::End(); + + static bool show_demo_window = true; + if (show_demo_window) { + ImGui::ShowDemoWindow(&show_demo_window); + } + + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); +} + +static ImGuiIO *g_io; + +static SDL_Window *g_sdl_window; +static SDL_GLContext g_sdl_gl_context; + + +void imgui_init(SDL_Window *sdl_window, SDL_GLContext sdl_gl_context) { + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + g_io = &ImGui::GetIO(); + + g_sdl_window = sdl_window; + g_sdl_gl_context = sdl_gl_context; + + ImGui_ImplSDL2_InitForOpenGL(sdl_window, sdl_gl_context); + ImGui_ImplOpenGL3_Init("#version 150"); + +// ImGui::StyleColorsDark(); +// ImGui::StyleColorsClassic(); + ImGui::StyleColorsLight(); + + + // Build atlas + unsigned char* tex_pixels = NULL; + int tex_w, tex_h; + g_io->Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_w, &tex_h); +} + +void imgui_process_event(SDL_Event *event, bool *mouse, bool *keyboard) { + ImGui_ImplSDL2_ProcessEvent(event); + *mouse = g_io->WantCaptureMouse; + *keyboard = g_io->WantCaptureKeyboard; +} + +static bool show_demo_window = true; + +void imgui_tick() { + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplSDL2_NewFrame(g_sdl_window); + ImGui::NewFrame(); + +// g_io->DisplaySize = ImVec2(1920, 1080); +// g_io->DeltaTime = 1.0f / 60.0f; + + static float f = 0.0f; + + ImGui::Begin("Hello, world!"); + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", static_cast(1000.0f / g_io->Framerate), static_cast(g_io->Framerate)); + ImGui::End(); + + if (show_demo_window) { + ImGui::ShowDemoWindow(&show_demo_window); + } + +// ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + ImGui::Render(); +// SDL_GL_MakeCurrent(g_sdl_window, g_sdl_gl_context); +// glViewport(0, 0, static_cast(g_io->DisplaySize.x), static_cast(g_io->DisplaySize.y)); +// glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); +// glClear(GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); +// SDL_GL_SwapWindow(g_sdl_window); +} + +void imgui_destroy() { + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplSDL2_Shutdown(); + ImGui::DestroyContext(); + g_io = nullptr; + g_sdl_gl_context = nullptr; + g_sdl_window = nullptr; +} + +#else + +RWImGui::RWImGui(RWGame &game) + : _game(game) { +} + +RWImGui::~RWImGui() { + destroy(); +} + +RWImGui::init(SDL_Window *window, SDL_GLContext context) { +} + +RWImGui::destroy() { +} + +RWImGui::process_event(SDL_Event &event) { +} + +#endif diff --git a/rwgame/RWImGui.hpp b/rwgame/RWImGui.hpp new file mode 100644 index 00000000..cb87d08b --- /dev/null +++ b/rwgame/RWImGui.hpp @@ -0,0 +1,21 @@ +#ifndef RWGAME_RWIMGUI_HPP +#define RWGAME_RWIMGUI_HPP + +#include + +class RWGame; +struct ImGuiContext; + +class RWImGui { + RWGame &_game; + ImGuiContext *_context = nullptr; +public: + RWImGui(RWGame &game); + ~RWImGui(); + void init(); + void destroy(); + bool process_event(SDL_Event &event); + void tick(); +}; + +#endif // RWGAME_RWIMGUI_HPP