From 88668a16780bfba0bdbfe179ba1fb0b416aa39f5 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Tue, 4 Jun 2024 23:31:49 +0100 Subject: Add imgui submodule, latest version, docking branch --- .gitmodules | 3 +++ thirdparty/imgui | 1 + 2 files changed, 4 insertions(+) create mode 160000 thirdparty/imgui diff --git a/.gitmodules b/.gitmodules index 6332369..63a1a38 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "thirdparty/ctre"] path = thirdparty/ctre url = https://github.com/hanickadot/compile-time-regular-expressions +[submodule "thirdparty/imgui"] + path = thirdparty/imgui + url = https://github.com/ocornut/imgui diff --git a/thirdparty/imgui b/thirdparty/imgui new file mode 160000 index 0000000..2db79d0 --- /dev/null +++ b/thirdparty/imgui @@ -0,0 +1 @@ +Subproject commit 2db79d0868f7b02d26f7557a72504a0b6f844937 -- cgit v1.2.3 From 61a6f00897637653597a29be7c4301d07f6c4ae9 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 5 Jun 2024 02:17:45 +0100 Subject: Build and link imgui with sdl2 and opengl2 backends --- Jamroot.jam | 1 + thirdparty/Jamfile.jam | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/Jamroot.jam b/Jamroot.jam index 967021d..94ab3b2 100644 --- a/Jamroot.jam +++ b/Jamroot.jam @@ -93,6 +93,7 @@ lib ilt : thirdparty//glad thirdparty//glad sdl2 + thirdparty//imguisdl2 freetype2 glib-2.0 mxml diff --git a/thirdparty/Jamfile.jam b/thirdparty/Jamfile.jam index bee3392..2a91a0b 100644 --- a/thirdparty/Jamfile.jam +++ b/thirdparty/Jamfile.jam @@ -5,3 +5,14 @@ lib glad : gl.xml : off off ; + +lib imguisdl2 : + [ glob imgui/imgui*.cpp : imgui/imgui_demo.cpp ] + imgui/backends/imgui_impl_sdl2.cpp + imgui/backends/imgui_impl_opengl3.cpp + : + imgui + ..//sdl2 + : : + imgui + ; -- cgit v1.2.3 From e4ed331cea817e55956200c9c116f8d11b54c86b Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 5 Jun 2024 02:21:00 +0100 Subject: Add imgui init and shutdown to appbase and gamemainwindow --- ui/applicationBase.cpp | 22 ++++++++++++++++++++++ ui/applicationBase.h | 4 ++++ ui/gameMainWindow.cpp | 15 +++++++++++++++ ui/gameMainWindow.h | 4 ++++ ui/imgui_wrap.h | 6 ++++++ 5 files changed, 51 insertions(+) create mode 100644 ui/imgui_wrap.h diff --git a/ui/applicationBase.cpp b/ui/applicationBase.cpp index 2be1f6c..3fa6e2b 100644 --- a/ui/applicationBase.cpp +++ b/ui/applicationBase.cpp @@ -1,8 +1,16 @@ #include "applicationBase.h" +#include "imgui_wrap.h" #include #include ApplicationBase::ApplicationBase() +{ + initSDL(); + initImGUI(); +} + +void +ApplicationBase::initSDL() const { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) { throw std::runtime_error(SDL_GetError()); @@ -24,7 +32,21 @@ ApplicationBase::ApplicationBase() setGlAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); } +void +ApplicationBase::initImGUI() const +{ + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO & io = ImGui::GetIO(); + 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 viewports +} + ApplicationBase::~ApplicationBase() { SDL_Quit(); + ImGui::DestroyContext(); } diff --git a/ui/applicationBase.h b/ui/applicationBase.h index 9d9b66b..082557d 100644 --- a/ui/applicationBase.h +++ b/ui/applicationBase.h @@ -9,4 +9,8 @@ public: NO_COPY(ApplicationBase); NO_MOVE(ApplicationBase); + +private: + void initSDL() const; + void initImGUI() const; }; diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp index ccbcdba..8e93694 100644 --- a/ui/gameMainWindow.cpp +++ b/ui/gameMainWindow.cpp @@ -16,6 +16,12 @@ #include #include +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#include "backends/imgui_impl_opengl3.h" +#include "backends/imgui_impl_sdl2.h" +#pragma GCC diagnostic pop + class GameMainToolbar : Mode, public Toolbar { public: explicit GameMainToolbar(GameMainSelector * gms_) : @@ -30,11 +36,20 @@ public: GameMainWindow::GameMainWindow(size_t w, size_t h) : Window {w, h, "I Like Trains", SDL_WINDOW_OPENGL}, SceneRenderer {Window::size, 0} { + ImGui_ImplSDL2_InitForOpenGL(m_window, glContext.get()); + ImGui_ImplOpenGL3_Init(); + uiComponents.create(glm::vec2 {310'727'624, 494'018'810}); auto gms = uiComponents.create(&camera, ScreenAbsCoord {w, h}); uiComponents.create(gms.get()); } +GameMainWindow::~GameMainWindow() +{ + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplSDL2_Shutdown(); +} + void GameMainWindow::tick(TickDuration) { diff --git a/ui/gameMainWindow.h b/ui/gameMainWindow.h index a4e822e..594843d 100644 --- a/ui/gameMainWindow.h +++ b/ui/gameMainWindow.h @@ -8,11 +8,15 @@ class GameMainWindow : public Window, SceneRenderer, public SceneProvider { public: GameMainWindow(size_t w, size_t h); + ~GameMainWindow() override; void tick(TickDuration) override; void render() const override; + NO_MOVE(GameMainWindow); + NO_COPY(GameMainWindow); + private: void content(const SceneShader &) const override; void environment(const SceneShader &, const SceneRenderer &) const override; diff --git a/ui/imgui_wrap.h b/ui/imgui_wrap.h new file mode 100644 index 0000000..1d619a4 --- /dev/null +++ b/ui/imgui_wrap.h @@ -0,0 +1,6 @@ +#pragma once + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#include "imgui.h" // IWYU pragma: export +#pragma GCC diagnostic pop -- cgit v1.2.3 From 02c3f1fd622bb5b4da1462c5bb507a4a541447d5 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 15 Jun 2024 15:28:53 +0100 Subject: First cut reshuffling app/window/gl/render bits --- application/main.cpp | 3 ++- gfx/gl/uiShader.cpp | 1 - test/test-assetFactory.cpp | 4 +--- test/test-glContainer.cpp | 4 +--- test/test-instancing.cpp | 5 +---- test/test-network.cpp | 4 +--- test/test-render.cpp | 3 +-- test/test-text.cpp | 4 +--- test/testMainWindow.cpp | 2 +- test/testMainWindow.h | 12 +++++------ ui/applicationBase.cpp | 1 + ui/gameMainWindow.cpp | 23 ++++++-------------- ui/gameMainWindow.h | 11 +++++----- ui/mainWindow.cpp | 28 ++++++++++++++++++++++++ ui/mainWindow.h | 16 ++++++++++++++ ui/window.cpp | 53 ++++++++++++---------------------------------- ui/window.h | 29 +++++++++++++------------ ui/windowContent.cpp | 32 ++++++++++++++++++++++++++++ ui/windowContent.h | 26 +++++++++++++++++++++++ 19 files changed, 157 insertions(+), 104 deletions(-) create mode 100644 ui/mainWindow.cpp create mode 100644 ui/mainWindow.h create mode 100644 ui/windowContent.cpp create mode 100644 ui/windowContent.h diff --git a/application/main.cpp b/application/main.cpp index f0ba8bb..04c88f3 100644 --- a/application/main.cpp +++ b/application/main.cpp @@ -1,3 +1,4 @@ +#include "ui/mainWindow.h" #include #include #include @@ -41,7 +42,7 @@ public: geoData = std::make_shared(GeoData::loadFromAsciiGrid("test/fixtures/height/SD19.asc")); Windows windows; - windows.create(DISPLAY_WIDTH, DISPLAY_HEIGHT); + windows.create(DISPLAY_WIDTH, DISPLAY_HEIGHT)->setContent(); world.create(geoData); world.create(geoData); diff --git a/gfx/gl/uiShader.cpp b/gfx/gl/uiShader.cpp index cf53e2c..bb9570e 100644 --- a/gfx/gl/uiShader.cpp +++ b/gfx/gl/uiShader.cpp @@ -7,7 +7,6 @@ #include #include #include -#include UIShader::IconProgram::IconProgram(const glm::mat4 & vp) : UIProgram {vp, uiShader_vs, uiShader_fs} { } diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index 73370c8..1c2c417 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -21,10 +21,8 @@ #include "lib/location.h" #include "lib/stream_support.h" #include "testMainWindow.h" -#include "ui/applicationBase.h" -BOOST_GLOBAL_FIXTURE(ApplicationBase); -BOOST_GLOBAL_FIXTURE(TestMainWindow); +BOOST_GLOBAL_FIXTURE(TestMainWindowAppBase); const std::filesystem::path TMP {"/tmp"}; diff --git a/test/test-glContainer.cpp b/test/test-glContainer.cpp index ec1c0d1..332d440 100644 --- a/test/test-glContainer.cpp +++ b/test/test-glContainer.cpp @@ -1,7 +1,6 @@ #define BOOST_TEST_MODULE glContainer #include "testMainWindow.h" -#include "ui/applicationBase.h" #include #include @@ -15,8 +14,7 @@ BOOST_TEST_DONT_PRINT_LOG_VALUE(glContainer::const_iterator); BOOST_TEST_DONT_PRINT_LOG_VALUE(glContainer::reverse_iterator); BOOST_TEST_DONT_PRINT_LOG_VALUE(glContainer::const_reverse_iterator); -BOOST_GLOBAL_FIXTURE(ApplicationBase); -BOOST_GLOBAL_FIXTURE(TestMainWindow); +BOOST_GLOBAL_FIXTURE(TestMainWindowAppBase); BOOST_FIXTURE_TEST_SUITE(i, glContainer) diff --git a/test/test-instancing.cpp b/test/test-instancing.cpp index c1860a4..3244bad 100644 --- a/test/test-instancing.cpp +++ b/test/test-instancing.cpp @@ -1,17 +1,14 @@ #define BOOST_TEST_MODULE instancing #include "stream_support.h" -#include "testHelpers.h" #include "testMainWindow.h" -#include "ui/applicationBase.h" #include #include #include #include -BOOST_GLOBAL_FIXTURE(ApplicationBase); -BOOST_GLOBAL_FIXTURE(TestMainWindow); +BOOST_GLOBAL_FIXTURE(TestMainWindowAppBase); BOOST_FIXTURE_TEST_SUITE(i, InstanceVertices) diff --git a/test/test-network.cpp b/test/test-network.cpp index 174e2a5..59eebae 100644 --- a/test/test-network.cpp +++ b/test/test-network.cpp @@ -5,7 +5,6 @@ #include #include "testMainWindow.h" -#include "ui/applicationBase.h" #include #include #include @@ -20,8 +19,7 @@ #include #include -BOOST_GLOBAL_FIXTURE(ApplicationBase); -BOOST_GLOBAL_FIXTURE(TestMainWindow); +BOOST_GLOBAL_FIXTURE(TestMainWindowAppBase); struct TestLinkS; diff --git a/test/test-render.cpp b/test/test-render.cpp index 79424f5..2c4efea 100644 --- a/test/test-render.cpp +++ b/test/test-render.cpp @@ -69,8 +69,7 @@ public: } }; -BOOST_GLOBAL_FIXTURE(ApplicationBase); -BOOST_GLOBAL_FIXTURE(TestMainWindow); +BOOST_GLOBAL_FIXTURE(TestMainWindowAppBase); BOOST_DATA_TEST_CASE(cam, boost::unit_test::data::xrange(500, 30000, 1300) * boost::unit_test::data::xrange(500, 10000, 300) diff --git a/test/test-text.cpp b/test/test-text.cpp index f185cf5..b0a9503 100644 --- a/test/test-text.cpp +++ b/test/test-text.cpp @@ -7,7 +7,6 @@ #include "testMainWindow.h" #include "testRenderOutput.h" -#include "ui/applicationBase.h" #include "ui/text.h" #include #include @@ -16,8 +15,7 @@ #include #include -BOOST_GLOBAL_FIXTURE(ApplicationBase); -BOOST_GLOBAL_FIXTURE(TestMainWindow); +BOOST_GLOBAL_FIXTURE(TestMainWindowAppBase); BOOST_AUTO_TEST_CASE(utf8_string_view_iter) { diff --git a/test/testMainWindow.cpp b/test/testMainWindow.cpp index d0b674c..4a76044 100644 --- a/test/testMainWindow.cpp +++ b/test/testMainWindow.cpp @@ -2,7 +2,7 @@ #include #include -TestMainWindow::TestMainWindow() : Window {1, 1, __FILE__, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN} +TestMainWindow::TestMainWindow() : MainWindow {1, 1, __FILE__, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN} { glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback( diff --git a/test/testMainWindow.h b/test/testMainWindow.h index 445491d..f54eb72 100644 --- a/test/testMainWindow.h +++ b/test/testMainWindow.h @@ -1,15 +1,13 @@ #pragma once -#include "ui/window.h" +#include "ui/applicationBase.h" +#include "ui/mainWindow.h" -class TestMainWindow : public Window { +class TestMainWindow : public MainWindow { // This exists only to hold an OpenGL context open for the duration of the tests, // in the same way a real main window would always exist. public: TestMainWindow(); - - void - tick(TickDuration) override - { - } }; + +class TestMainWindowAppBase : public ApplicationBase, public TestMainWindow { }; diff --git a/ui/applicationBase.cpp b/ui/applicationBase.cpp index 3fa6e2b..c3134b4 100644 --- a/ui/applicationBase.cpp +++ b/ui/applicationBase.cpp @@ -35,6 +35,7 @@ ApplicationBase::initSDL() const void ApplicationBase::initImGUI() const { + puts(__PRETTY_FUNCTION__); // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp index 8e93694..6168504 100644 --- a/ui/gameMainWindow.cpp +++ b/ui/gameMainWindow.cpp @@ -16,12 +16,6 @@ #include #include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#include "backends/imgui_impl_opengl3.h" -#include "backends/imgui_impl_sdl2.h" -#pragma GCC diagnostic pop - class GameMainToolbar : Mode, public Toolbar { public: explicit GameMainToolbar(GameMainSelector * gms_) : @@ -33,22 +27,14 @@ public: } }; -GameMainWindow::GameMainWindow(size_t w, size_t h) : - Window {w, h, "I Like Trains", SDL_WINDOW_OPENGL}, SceneRenderer {Window::size, 0} +GameMainWindow::GameMainWindow(size_t w, size_t h) : WindowContent {w, h}, SceneRenderer {{w, h}, 0} { - ImGui_ImplSDL2_InitForOpenGL(m_window, glContext.get()); - ImGui_ImplOpenGL3_Init(); - uiComponents.create(glm::vec2 {310'727'624, 494'018'810}); auto gms = uiComponents.create(&camera, ScreenAbsCoord {w, h}); uiComponents.create(gms.get()); } -GameMainWindow::~GameMainWindow() -{ - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplSDL2_Shutdown(); -} +GameMainWindow::~GameMainWindow() { } void GameMainWindow::tick(TickDuration) @@ -60,7 +46,10 @@ void GameMainWindow::render() const { SceneRenderer::render(*this); - Window::render(); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_DEPTH_TEST); + uiComponents.apply(&UIComponent::render, uiShader, UIComponent::Position {}); } void diff --git a/ui/gameMainWindow.h b/ui/gameMainWindow.h index 594843d..fcbd135 100644 --- a/ui/gameMainWindow.h +++ b/ui/gameMainWindow.h @@ -2,21 +2,20 @@ #include "chronology.h" #include "gfx/gl/sceneRenderer.h" -#include "window.h" +#include "windowContent.h" #include -class GameMainWindow : public Window, SceneRenderer, public SceneProvider { +class GameMainWindow : public WindowContent, SceneRenderer, public SceneProvider { public: GameMainWindow(size_t w, size_t h); ~GameMainWindow() override; - void tick(TickDuration) override; - - void render() const override; - NO_MOVE(GameMainWindow); NO_COPY(GameMainWindow); + void tick(TickDuration) override; + void render() const override; + private: void content(const SceneShader &) const override; void environment(const SceneShader &, const SceneRenderer &) const override; diff --git a/ui/mainWindow.cpp b/ui/mainWindow.cpp new file mode 100644 index 0000000..830dba5 --- /dev/null +++ b/ui/mainWindow.cpp @@ -0,0 +1,28 @@ +#include "mainWindow.h" +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#include "backends/imgui_impl_opengl3.h" +#include "backends/imgui_impl_sdl2.h" +#pragma GCC diagnostic pop + +MainWindow::MainWindow(size_t w, size_t h) : MainWindow {w, h, "I Like Trains", SDL_WINDOW_OPENGL} { } + +MainWindow::MainWindow(size_t w, size_t h, const std::string & title, Uint32 flags) : Window {w, h, title, flags} +{ + puts(__PRETTY_FUNCTION__); + if (const auto version = gladLoadGL(reinterpret_cast(SDL_GL_GetProcAddress)); version < 30003) { + throw std::runtime_error {std::format("Insufficient OpenGL version: {}", version)}; + } + + ImGui_ImplSDL2_InitForOpenGL(m_window, glContext.get()); + ImGui_ImplOpenGL3_Init(); +} + +MainWindow::~MainWindow() +{ + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplSDL2_Shutdown(); +} diff --git a/ui/mainWindow.h b/ui/mainWindow.h new file mode 100644 index 0000000..fe26c5c --- /dev/null +++ b/ui/mainWindow.h @@ -0,0 +1,16 @@ +#pragma once + +#include "window.h" +#include + +class MainWindow : public Window { +public: + MainWindow(size_t w, size_t h); + ~MainWindow() override; + + NO_MOVE(MainWindow); + NO_COPY(MainWindow); + +protected: + MainWindow(size_t width, size_t height, const std::string & title, Uint32 flags); +}; diff --git a/ui/window.cpp b/ui/window.cpp index dd488d7..8ceaf49 100644 --- a/ui/window.cpp +++ b/ui/window.cpp @@ -1,28 +1,12 @@ #include "window.h" -#include "uiComponent.h" -#include #include #include -#include - -Window::GLInitHelper::GLInitHelper() -{ - [[maybe_unused]] static auto init = []() { - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - if (const auto version = gladLoadGL(reinterpret_cast(SDL_GL_GetProcAddress)); version < 30003) { - throw std::runtime_error {std::format("Insufficient OpenGL version: {}", version)}; - } - else { - return version; - } - }(); -} Window::Window(size_t width, size_t height, const std::string & title, Uint32 flags) : size {static_cast(width), static_cast(height)}, m_window {title.c_str(), static_cast(SDL_WINDOWPOS_CENTERED), static_cast(SDL_WINDOWPOS_CENTERED), size.x, size.y, flags}, - glContext {m_window}, uiShader {width, height} + glContext {m_window} { } @@ -39,23 +23,21 @@ Window::swapBuffers() const SDL_GL_SwapWindow(m_window); } +void +Window::tick(TickDuration elapsed) +{ + if (content) { + content->tick(elapsed); + } +} + bool Window::handleInput(const SDL_Event & e) { if (SDL_GetWindowID(m_window) == e.window.windowID) { - SDL_Event eAdjusted {e}; - switch (e.type) { - // SDL and OpenGL have coordinates that are vertically opposed. - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - eAdjusted.button.y = size.y - e.button.y; - break; - case SDL_MOUSEMOTION: - eAdjusted.motion.y = size.y - e.motion.y; - break; + if (content) { + return content->handleInput(e); } - uiComponents.rapplyOne(&UIComponent::handleInput, eAdjusted, UIComponent::Position {{}, size}); - return true; } return false; } @@ -66,16 +48,9 @@ Window::refresh() const SDL_GL_MakeCurrent(m_window, glContext); clear(0.0F, 0.0F, 0.0F, 1.0F); - render(); + if (content) { + content->render(); + } swapBuffers(); } - -void -Window::render() const -{ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_DEPTH_TEST); - uiComponents.apply(&UIComponent::render, uiShader, UIComponent::Position {}); -} diff --git a/ui/window.h b/ui/window.h index 8f2b70b..62c34de 100644 --- a/ui/window.h +++ b/ui/window.h @@ -1,13 +1,12 @@ #pragma once #include "chronology.h" -#include "collection.h" -#include "gfx/gl/uiShader.h" +#include "config/types.h" #include "ptr.h" -#include "uiComponent.h" // IWYU pragma: keep +#include "special_members.h" +#include "windowContent.h" #include #include -#include #include using SDL_WindowPtr = wrapped_ptrt; @@ -22,24 +21,26 @@ public: NO_COPY(Window); NO_MOVE(Window); - virtual void tick(TickDuration elapsed) = 0; + template + void + setContent(P &&... p) + { + glm::ivec2 size {}; + SDL_GetWindowSizeInPixels(m_window, &size.x, &size.y); + content = std::make_unique(size.x, size.y, std::forward

(p)...); + } + + void tick(TickDuration elapsed); void refresh() const; bool handleInput(const SDL_Event & e); - void clear(float r, float g, float b, float a) const; void swapBuffers() const; protected: - virtual void render() const; - - struct GLInitHelper { - GLInitHelper(); - }; + void clear(float r, float g, float b, float a) const; const ScreenAbsCoord size; SDL_WindowPtr m_window; SDL_GLContextPtr glContext; - GLInitHelper glInithelper; - Collection uiComponents; - UIShader uiShader; + WindowContent::Ptr content; }; diff --git a/ui/windowContent.cpp b/ui/windowContent.cpp new file mode 100644 index 0000000..91732a7 --- /dev/null +++ b/ui/windowContent.cpp @@ -0,0 +1,32 @@ +#include "windowContent.h" +#include "SDL_events.h" + +WindowContent::WindowContent(size_t width, size_t height) : uiShader {width, height} { } + +void +WindowContent::tick(TickDuration) +{ +} + +bool +WindowContent::handleInput(const SDL_Event & e) +{ + SDL_Event eAdjusted {e}; + const auto size = [&e] { + glm::ivec2 size {}; + SDL_GetWindowSizeInPixels(SDL_GetWindowFromID(e.window.windowID), &size.x, &size.y); + return size; + }(); + switch (e.type) { + // SDL and OpenGL have coordinates that are vertically opposed. + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + eAdjusted.button.y = size.y - e.button.y; + break; + case SDL_MOUSEMOTION: + eAdjusted.motion.y = size.y - e.motion.y; + break; + } + uiComponents.rapplyOne(&UIComponent::handleInput, eAdjusted, UIComponent::Position {{}, size}); + return true; +} diff --git a/ui/windowContent.h b/ui/windowContent.h new file mode 100644 index 0000000..474445a --- /dev/null +++ b/ui/windowContent.h @@ -0,0 +1,26 @@ +#pragma once + +#include "chronology.h" +#include "collection.h" +#include "gfx/gl/uiShader.h" +#include "special_members.h" +#include "stdTypeDefs.h" +#include "uiComponent.h" // IWYU pragma: keep +#include + +class WindowContent : public StdTypeDefs { +public: + using Factory = std::function; + WindowContent(size_t width, size_t height); + virtual ~WindowContent() = default; + NO_MOVE(WindowContent); + NO_COPY(WindowContent); + + virtual void tick(TickDuration); + virtual void render() const = 0; + virtual bool handleInput(const SDL_Event & e); + +protected: + ::Collection uiComponents; + UIShader uiShader; +}; -- cgit v1.2.3 From 321103ea84cf61f58a26d59700284d84f11833f5 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 15 Jun 2024 17:35:13 +0100 Subject: Move main application loop into the library --- application/main.cpp | 37 ++++--------------------------------- ui/mainApplication.cpp | 34 ++++++++++++++++++++++++++++++++++ ui/mainApplication.h | 18 ++++++++++++++++++ 3 files changed, 56 insertions(+), 33 deletions(-) create mode 100644 ui/mainApplication.cpp create mode 100644 ui/mainApplication.h diff --git a/application/main.cpp b/application/main.cpp index 04c88f3..d58cf6d 100644 --- a/application/main.cpp +++ b/application/main.cpp @@ -1,7 +1,7 @@ +#include "ui/mainApplication.h" #include "ui/mainWindow.h" #include #include -#include #include #include #include @@ -32,16 +32,13 @@ static const int DISPLAY_WIDTH = 1280; static const int DISPLAY_HEIGHT = 1024; -class MainApplication : public GameState, public ApplicationBase { +class DummyMainApplication : public GameState, public MainApplication { public: - using Windows = Collection; - int run() { geoData = std::make_shared(GeoData::loadFromAsciiGrid("test/fixtures/height/SD19.asc")); - Windows windows; windows.create(DISPLAY_WIDTH, DISPLAY_HEIGHT)->setContent(); world.create(geoData); @@ -90,41 +87,15 @@ public: } } - auto t_start = std::chrono::high_resolution_clock::now(); - while (isRunning) { - processInputs(windows); - const auto t_end = std::chrono::high_resolution_clock::now(); - const auto t_passed = std::chrono::duration_cast(t_end - t_start); - - world.apply(&WorldObject::tick, t_passed); - windows.apply(&Window::tick, t_passed); - windows.apply(&Window::refresh); - - t_start = t_end; - } + mainLoop(); world.objects.clear(); return 0; } - -private: - void - processInputs(const Windows & windows) - { - for (SDL_Event e; SDL_PollEvent(&e);) { - if (e.type == SDL_QUIT) { - isRunning = false; - return; - } - windows.applyOne(&Window::handleInput, e); - } - } - - bool isRunning {true}; }; int main(int, char **) { - return std::make_shared()->run(); + return std::make_shared()->run(); } diff --git a/ui/mainApplication.cpp b/ui/mainApplication.cpp new file mode 100644 index 0000000..08f49a4 --- /dev/null +++ b/ui/mainApplication.cpp @@ -0,0 +1,34 @@ +#include "mainApplication.h" +#include "game/gamestate.h" +#include "game/worldobject.h" + +void +MainApplication::mainLoop() +{ + auto t_start = std::chrono::high_resolution_clock::now(); + while (isRunning) { + processInputs(); + const auto t_end = std::chrono::high_resolution_clock::now(); + const auto t_passed = std::chrono::duration_cast(t_end - t_start); + + if (gameState) { + gameState->world.apply(&WorldObject::tick, t_passed); + } + windows.apply(&Window::tick, t_passed); + windows.apply(&Window::refresh); + + t_start = t_end; + } +} + +void +MainApplication::processInputs() +{ + for (SDL_Event e; SDL_PollEvent(&e);) { + if (e.type == SDL_QUIT) { + isRunning = false; + return; + } + windows.applyOne(&Window::handleInput, e); + } +} diff --git a/ui/mainApplication.h b/ui/mainApplication.h new file mode 100644 index 0000000..a6cb126 --- /dev/null +++ b/ui/mainApplication.h @@ -0,0 +1,18 @@ +#pragma once + +#include "applicationBase.h" +#include "collection.h" +#include "window.h" + +class MainApplication : public ApplicationBase { +public: + using Windows = Collection; + void mainLoop(); + +protected: + Windows windows; + +private: + void processInputs(); + bool isRunning {true}; +}; -- cgit v1.2.3 From 38510fa00ff2b192d7c2f9c8311ad6939faa8256 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 16 Jun 2024 11:16:21 +0100 Subject: Remove initialisation order debug --- ui/applicationBase.cpp | 1 - ui/mainWindow.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/ui/applicationBase.cpp b/ui/applicationBase.cpp index c3134b4..3fa6e2b 100644 --- a/ui/applicationBase.cpp +++ b/ui/applicationBase.cpp @@ -35,7 +35,6 @@ ApplicationBase::initSDL() const void ApplicationBase::initImGUI() const { - puts(__PRETTY_FUNCTION__); // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); diff --git a/ui/mainWindow.cpp b/ui/mainWindow.cpp index 830dba5..38d6a6e 100644 --- a/ui/mainWindow.cpp +++ b/ui/mainWindow.cpp @@ -12,7 +12,6 @@ MainWindow::MainWindow(size_t w, size_t h) : MainWindow {w, h, "I Like Trains", MainWindow::MainWindow(size_t w, size_t h, const std::string & title, Uint32 flags) : Window {w, h, title, flags} { - puts(__PRETTY_FUNCTION__); if (const auto version = gladLoadGL(reinterpret_cast(SDL_GL_GetProcAddress)); version < 30003) { throw std::runtime_error {std::format("Insufficient OpenGL version: {}", version)}; } -- cgit v1.2.3 From 7f14bb09be25c3e02ab5d7c921916d739d08e6f9 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 16 Jun 2024 12:27:17 +0100 Subject: Disable saving settings automagically --- ui/applicationBase.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/applicationBase.cpp b/ui/applicationBase.cpp index 3fa6e2b..b945dca 100644 --- a/ui/applicationBase.cpp +++ b/ui/applicationBase.cpp @@ -43,6 +43,7 @@ ApplicationBase::initImGUI() const io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable docking io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable viewports + io.IniFilename = nullptr; // Disable saving settings automagically } ApplicationBase::~ApplicationBase() -- cgit v1.2.3 From 3d7a2f7cbc69bcfb5b04d343cb15c3027721b2e7 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 16 Jun 2024 12:28:42 +0100 Subject: Integrate ImGUI main calls --- ui/mainApplication.cpp | 7 +++++++ ui/window.cpp | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/ui/mainApplication.cpp b/ui/mainApplication.cpp index 08f49a4..d843ef1 100644 --- a/ui/mainApplication.cpp +++ b/ui/mainApplication.cpp @@ -1,6 +1,10 @@ #include "mainApplication.h" #include "game/gamestate.h" #include "game/worldobject.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#include "backends/imgui_impl_sdl2.h" +#pragma GCC diagnostic pop void MainApplication::mainLoop() @@ -16,6 +20,8 @@ MainApplication::mainLoop() } windows.apply(&Window::tick, t_passed); windows.apply(&Window::refresh); + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); t_start = t_end; } @@ -29,6 +35,7 @@ MainApplication::processInputs() isRunning = false; return; } + ImGui_ImplSDL2_ProcessEvent(&e); windows.applyOne(&Window::handleInput, e); } } diff --git a/ui/window.cpp b/ui/window.cpp index 8ceaf49..732e9ef 100644 --- a/ui/window.cpp +++ b/ui/window.cpp @@ -1,6 +1,11 @@ #include "window.h" #include #include +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#include "backends/imgui_impl_opengl3.h" +#include "backends/imgui_impl_sdl2.h" +#pragma GCC diagnostic pop Window::Window(size_t width, size_t height, const std::string & title, Uint32 flags) : size {static_cast(width), static_cast(height)}, @@ -48,9 +53,15 @@ Window::refresh() const SDL_GL_MakeCurrent(m_window, glContext); clear(0.0F, 0.0F, 0.0F, 1.0F); + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplSDL2_NewFrame(); + ImGui::NewFrame(); if (content) { content->render(); + // Render UI stuff here } + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); swapBuffers(); } -- cgit v1.2.3 From 65c9432714c166cd79bdc24c07b18d8b15670063 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 24 Jun 2024 23:37:07 +0100 Subject: Don't process input events which ImGui handled --- ui/mainApplication.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/mainApplication.cpp b/ui/mainApplication.cpp index d843ef1..6cb1037 100644 --- a/ui/mainApplication.cpp +++ b/ui/mainApplication.cpp @@ -36,6 +36,8 @@ MainApplication::processInputs() return; } ImGui_ImplSDL2_ProcessEvent(&e); - windows.applyOne(&Window::handleInput, e); + if (!ImGui::GetIO().WantCaptureMouse) { + windows.applyOne(&Window::handleInput, e); + } } } -- cgit v1.2.3 From 353116f55989c8b49e26265d1d7948f520259cec Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 24 Jun 2024 23:46:25 +0100 Subject: Use shared installed libraries explicitly --- Jamroot.jam | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Jamroot.jam b/Jamroot.jam index 94ab3b2..81a3831 100644 --- a/Jamroot.jam +++ b/Jamroot.jam @@ -6,13 +6,13 @@ import lex ; import sequence ; import glsl ; -pkg-config.import sdl2 ; -pkg-config.import freetype2 ; -pkg-config.import glib-2.0 ; -pkg-config.import mxml ; -pkg-config.import assimp ; -lib pthread ; -lib OpenMeshCore ; +pkg-config.import sdl2 : : shared ; +pkg-config.import freetype2 : : shared ; +pkg-config.import glib-2.0 : : shared ; +pkg-config.import mxml : : shared ; +pkg-config.import assimp : : shared ; +lib pthread : : shared ; +lib OpenMeshCore : : shared ; variant coverage : debug ; project i-like-trains : requirements -- cgit v1.2.3 From 6cd132b9740af30c41f478cf73d41b0a10399945 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 24 Jun 2024 23:49:43 +0100 Subject: Build ImGui as a static library --- thirdparty/Jamfile.jam | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/thirdparty/Jamfile.jam b/thirdparty/Jamfile.jam index 2a91a0b..06ab869 100644 --- a/thirdparty/Jamfile.jam +++ b/thirdparty/Jamfile.jam @@ -11,8 +11,12 @@ lib imguisdl2 : imgui/backends/imgui_impl_sdl2.cpp imgui/backends/imgui_impl_opengl3.cpp : + static imgui - ..//sdl2 + ..//sdl2 + -fPIC + off + off : : imgui ; -- cgit v1.2.3 From d90c4ba89a4ed63438ca1aa4f5911037472c717e Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Tue, 2 Jul 2024 19:33:59 +0100 Subject: Re-add testHelpers.h --- test/test-instancing.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test-instancing.cpp b/test/test-instancing.cpp index 40c2c4f..1dd4cea 100644 --- a/test/test-instancing.cpp +++ b/test/test-instancing.cpp @@ -1,6 +1,7 @@ #define BOOST_TEST_MODULE instancing -#include "stream_support.h" +#include "stream_support.h" // IWYU pragma: keep +#include "testHelpers.h" #include "testMainWindow.h" #include #include -- cgit v1.2.3 From 97fe4b6b2d6ada8066821594543bea38b564fb93 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 5 Jul 2024 02:06:55 +0100 Subject: Fix up perf tests in light of window management changes --- test/Jamfile.jam | 8 ++++---- test/perf-assetFactory.cpp | 6 ++---- test/perf-instancing.cpp | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/test/Jamfile.jam b/test/Jamfile.jam index 1266854..0b830a8 100644 --- a/test/Jamfile.jam +++ b/test/Jamfile.jam @@ -55,8 +55,8 @@ run test-enumDetails.cpp ; run test-render.cpp : -- : test-assetFactory : test ; run test-glContextBhvr.cpp ; run test-assetFactory.cpp : -- : [ sequence.insertion-sort [ glob-tree $(res) : *.* ] fixtures/rgb.txt test-instancing ] : test ; -run perf-assetFactory.cpp : <\ : test-assetFactory : benchmark test ; -run perf-geoData.cpp : : : test benchmark ; +run perf-assetFactory.cpp : \< : test-assetFactory : benchmark test ; +run perf-geoData.cpp : \< : test-geoData : test benchmark ; run perf-persistence.cpp : \< : test-persistence : benchmark test ; run test-worker.cpp ; run test-instancing.cpp : -- : test-glContainer : test ; @@ -67,7 +67,7 @@ compile test-static-enumDetails.cpp ; compile test-static-stream_support.cpp ; explicit perf-assetFactory ; explicit perf-persistence ; -explicit perf-terrain ; +explicit perf-geoData ; explicit perf-instancing ; -alias perf : perf-assetFactory perf-persistence perf-terrain ; +alias perf : perf-assetFactory perf-persistence perf-geoData perf-instancing ; explicit perf ; diff --git a/test/perf-assetFactory.cpp b/test/perf-assetFactory.cpp index 147e4ba..671713c 100644 --- a/test/perf-assetFactory.cpp +++ b/test/perf-assetFactory.cpp @@ -1,13 +1,11 @@ #include "assetFactory/assetFactory.h" -#include "assetFactory/factoryMesh.h" #include "testMainWindow.h" -#include "ui/applicationBase.h" #include static void brush47xml_load(benchmark::State & state) { - TestMainWindow window; + TestMainWindowAppBase window; for (auto _ : state) { benchmark::DoNotOptimize(AssetFactory::loadXML(RESDIR "/brush47.xml")); @@ -17,7 +15,7 @@ brush47xml_load(benchmark::State & state) static void foliagexml_load(benchmark::State & state) { - TestMainWindow window; + TestMainWindowAppBase window; for (auto _ : state) { benchmark::DoNotOptimize(AssetFactory::loadXML(RESDIR "/foliage.xml")); diff --git a/test/perf-instancing.cpp b/test/perf-instancing.cpp index 829ea50..3638111 100644 --- a/test/perf-instancing.cpp +++ b/test/perf-instancing.cpp @@ -26,7 +26,7 @@ struct data { static void partition(benchmark::State & state) { - TestMainWindow window; + TestMainWindowAppBase window; data d(static_cast(state.range())); GlobalPosition2D pos {}; for (auto _ : state) { -- cgit v1.2.3 From 8902c9b7d26184ae045afcccd66fa168fdff56aa Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 6 Jul 2024 13:33:30 +0100 Subject: Replace deprecated GL_QUADS usage in text rendering --- ui/text.cpp | 19 +++++++++++++------ ui/text.h | 7 ++++++- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/ui/text.cpp b/ui/text.cpp index 5675061..bdaaba5 100644 --- a/ui/text.cpp +++ b/ui/text.cpp @@ -27,13 +27,20 @@ Text::operator=(const std::string_view s) return init += q.second.size(); }); quads.resize(glyphCount); - GLint current = 0; + GLushort current = 0; auto model = models.begin(); auto quad = quads.begin(); for (const auto & [texture, fquads] : tquads) { - model->first = texture; - model->second = {fquads.size() * 4, current * 4}; - current += static_cast(fquads.size()); + model->textureId = texture; + model->range.resize(fquads.size() * 6); + for (auto out = model->range.begin(); const auto & q [[maybe_unused]] : fquads) { + static constexpr std::array quadIndices {0, 1, 2, 2, 3, 0}; + std::transform(quadIndices.begin(), quadIndices.end(), out, [current](auto x) { + return current + x; + }); + current += 4; + out += 6; + } model++; quad = std::transform(fquads.begin(), fquads.end(), quad, [this](const Font::Quad & q) { return q * [this](const glm::vec4 & corner) { @@ -52,8 +59,8 @@ Text::render(const UIShader & shader, const Position &) const glActiveTexture(GL_TEXTURE0); glBindVertexArray(vao); for (const auto & m : models) { - glBindTexture(GL_TEXTURE_2D, m.first); - glDrawArrays(GL_QUADS, m.second.second, m.second.first); + glBindTexture(GL_TEXTURE_2D, m.textureId); + glDrawElements(GL_TRIANGLES, static_cast(m.range.size()), GL_UNSIGNED_SHORT, m.range.data()); } glBindVertexArray(0); glBindTexture(GL_TEXTURE_2D, 0); diff --git a/ui/text.h b/ui/text.h index 31ed9a5..a367456 100644 --- a/ui/text.h +++ b/ui/text.h @@ -21,7 +21,12 @@ public: Text & operator=(const std::string_view s); private: - std::vector>> models; + struct TextData { + GLuint textureId; + std::vector range; + }; + + std::vector models; glContainer quads; glVertexArray vao; glm::vec3 colour; -- cgit v1.2.3