summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Jamroot.jam15
-rw-r--r--application/main.cpp40
-rw-r--r--gfx/gl/uiShader.cpp1
-rw-r--r--test/test-assetFactory.cpp4
-rw-r--r--test/test-glContainer.cpp4
-rw-r--r--test/test-instancing.cpp5
-rw-r--r--test/test-network.cpp4
-rw-r--r--test/test-render.cpp3
-rw-r--r--test/test-text.cpp4
-rw-r--r--test/testMainWindow.cpp2
-rw-r--r--test/testMainWindow.h12
-rw-r--r--thirdparty/Jamfile.jam15
m---------thirdparty/imgui0
-rw-r--r--ui/applicationBase.cpp23
-rw-r--r--ui/applicationBase.h4
-rw-r--r--ui/gameMainWindow.cpp10
-rw-r--r--ui/gameMainWindow.h9
-rw-r--r--ui/imgui_wrap.h6
-rw-r--r--ui/mainApplication.cpp43
-rw-r--r--ui/mainApplication.h18
-rw-r--r--ui/mainWindow.cpp27
-rw-r--r--ui/mainWindow.h16
-rw-r--r--ui/window.cpp64
-rw-r--r--ui/window.h29
-rw-r--r--ui/windowContent.cpp32
-rw-r--r--ui/windowContent.h26
27 files changed, 292 insertions, 127 deletions
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/Jamroot.jam b/Jamroot.jam
index 8ef10fe..b07dfdd 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 : : <link>shared ;
+pkg-config.import freetype2 : : <link>shared ;
+pkg-config.import glib-2.0 : : <link>shared ;
+pkg-config.import mxml : : <link>shared ;
+pkg-config.import assimp : : <link>shared ;
+lib pthread : : <link>shared ;
+lib OpenMeshCore : : <link>shared ;
variant coverage : debug ;
project i-like-trains : requirements
@@ -93,6 +93,7 @@ lib ilt :
<library>thirdparty/<variant>release
<implicit-dependency>thirdparty
<library>sdl2
+ <library>thirdparty//imguisdl2
<library>freetype2
<library>glib-2.0
<library>mxml
diff --git a/application/main.cpp b/application/main.cpp
index f0ba8bb..d58cf6d 100644
--- a/application/main.cpp
+++ b/application/main.cpp
@@ -1,6 +1,7 @@
+#include "ui/mainApplication.h"
+#include "ui/mainWindow.h"
#include <array>
#include <assetFactory/assetFactory.h>
-#include <chrono>
#include <collection.h>
#include <game/activities/go.h>
#include <game/activities/idle.h>
@@ -31,17 +32,14 @@
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<Window>;
-
int
run()
{
geoData = std::make_shared<GeoData>(GeoData::loadFromAsciiGrid("test/fixtures/height/SD19.asc"));
- Windows windows;
- windows.create<GameMainWindow>(DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ windows.create<MainWindow>(DISPLAY_WIDTH, DISPLAY_HEIGHT)->setContent<GameMainWindow>();
world.create<Terrain>(geoData);
world.create<Water>(geoData);
@@ -89,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<TickDuration>(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<MainApplication>()->run();
+ return std::make_shared<DummyMainApplication>()->run();
}
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 <gfx/gl/shaders/vs-uiShader.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
-#include <initializer_list>
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 <boost/test/data/test_case.hpp>
#include <boost/test/unit_test.hpp>
@@ -15,8 +14,7 @@ BOOST_TEST_DONT_PRINT_LOG_VALUE(glContainer<int>::const_iterator);
BOOST_TEST_DONT_PRINT_LOG_VALUE(glContainer<int>::reverse_iterator);
BOOST_TEST_DONT_PRINT_LOG_VALUE(glContainer<int>::const_reverse_iterator);
-BOOST_GLOBAL_FIXTURE(ApplicationBase);
-BOOST_GLOBAL_FIXTURE(TestMainWindow);
+BOOST_GLOBAL_FIXTURE(TestMainWindowAppBase);
BOOST_FIXTURE_TEST_SUITE(i, glContainer<int>)
diff --git a/test/test-instancing.cpp b/test/test-instancing.cpp
index 77467d8..40c2c4f 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 <boost/test/data/test_case.hpp>
#include <boost/test/unit_test.hpp>
#include <set>
#include <gfx/gl/instanceVertices.h>
-BOOST_GLOBAL_FIXTURE(ApplicationBase);
-BOOST_GLOBAL_FIXTURE(TestMainWindow);
+BOOST_GLOBAL_FIXTURE(TestMainWindowAppBase);
struct TestInstanceVertices : public InstanceVertices<int> {
void
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 <boost/test/unit_test.hpp>
#include "testMainWindow.h"
-#include "ui/applicationBase.h"
#include <array>
#include <collection.h>
#include <game/network/link.h>
@@ -20,8 +19,7 @@
#include <utility>
#include <vector>
-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 <array>
#include <gfx/models/texture.h>
@@ -16,8 +15,7 @@
#include <unicode.h>
#include <vector>
-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 <boost/test/test_tools.hpp>
#include <format>
-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/thirdparty/Jamfile.jam b/thirdparty/Jamfile.jam
index 8b76449..7a47589 100644
--- a/thirdparty/Jamfile.jam
+++ b/thirdparty/Jamfile.jam
@@ -12,3 +12,18 @@ lib stb : stb_image.c :
<warnings>off
<warnings-as-errors>off
;
+
+lib imguisdl2 :
+ [ glob imgui/imgui*.cpp : imgui/imgui_demo.cpp ]
+ imgui/backends/imgui_impl_sdl2.cpp
+ imgui/backends/imgui_impl_opengl3.cpp
+ :
+ <link>static
+ <include>imgui
+ <use>..//sdl2
+ <cflags>-fPIC
+ <warnings>off
+ <warnings-as-errors>off
+ : :
+ <include>imgui
+ ;
diff --git a/thirdparty/imgui b/thirdparty/imgui
new file mode 160000
+Subproject 2db79d0868f7b02d26f7557a72504a0b6f84493
diff --git a/ui/applicationBase.cpp b/ui/applicationBase.cpp
index 7764c58..961007b 100644
--- a/ui/applicationBase.cpp
+++ b/ui/applicationBase.cpp
@@ -1,9 +1,17 @@
#include "applicationBase.h"
+#include "imgui_wrap.h"
#include <SDL2/SDL.h>
#include <stdexcept>
ApplicationBase::ApplicationBase()
{
+ initSDL();
+ initImGUI();
+}
+
+void
+ApplicationBase::initSDL() const
+{
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) {
throw std::runtime_error(SDL_GetError());
}
@@ -27,7 +35,22 @@ 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
+ io.IniFilename = nullptr; // Disable saving settings automagically
+}
+
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..6168504 100644
--- a/ui/gameMainWindow.cpp
+++ b/ui/gameMainWindow.cpp
@@ -27,14 +27,15 @@ 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}
{
uiComponents.create<ManualCameraController>(glm::vec2 {310'727'624, 494'018'810});
auto gms = uiComponents.create<GameMainSelector>(&camera, ScreenAbsCoord {w, h});
uiComponents.create<GameMainToolbar>(gms.get());
}
+GameMainWindow::~GameMainWindow() { }
+
void
GameMainWindow::tick(TickDuration)
{
@@ -45,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 a4e822e..fcbd135 100644
--- a/ui/gameMainWindow.h
+++ b/ui/gameMainWindow.h
@@ -2,15 +2,18 @@
#include "chronology.h"
#include "gfx/gl/sceneRenderer.h"
-#include "window.h"
+#include "windowContent.h"
#include <cstddef>
-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;
+ NO_MOVE(GameMainWindow);
+ NO_COPY(GameMainWindow);
+ void tick(TickDuration) override;
void render() const override;
private:
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
diff --git a/ui/mainApplication.cpp b/ui/mainApplication.cpp
new file mode 100644
index 0000000..6cb1037
--- /dev/null
+++ b/ui/mainApplication.cpp
@@ -0,0 +1,43 @@
+#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()
+{
+ 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<TickDuration>(t_end - t_start);
+
+ if (gameState) {
+ gameState->world.apply(&WorldObject::tick, t_passed);
+ }
+ windows.apply(&Window::tick, t_passed);
+ windows.apply(&Window::refresh);
+ ImGui::UpdatePlatformWindows();
+ ImGui::RenderPlatformWindowsDefault();
+
+ t_start = t_end;
+ }
+}
+
+void
+MainApplication::processInputs()
+{
+ for (SDL_Event e; SDL_PollEvent(&e);) {
+ if (e.type == SDL_QUIT) {
+ isRunning = false;
+ return;
+ }
+ ImGui_ImplSDL2_ProcessEvent(&e);
+ if (!ImGui::GetIO().WantCaptureMouse) {
+ 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<Window>;
+ void mainLoop();
+
+protected:
+ Windows windows;
+
+private:
+ void processInputs();
+ bool isRunning {true};
+};
diff --git a/ui/mainWindow.cpp b/ui/mainWindow.cpp
new file mode 100644
index 0000000..38d6a6e
--- /dev/null
+++ b/ui/mainWindow.cpp
@@ -0,0 +1,27 @@
+#include "mainWindow.h"
+#include <format>
+#include <stdexcept>
+
+#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}
+{
+ if (const auto version = gladLoadGL(reinterpret_cast<GLADloadfunc>(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 <cstddef>
+
+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..732e9ef 100644
--- a/ui/window.cpp
+++ b/ui/window.cpp
@@ -1,28 +1,17 @@
#include "window.h"
-#include "uiComponent.h"
-#include <format>
#include <glad/gl.h>
#include <glm/glm.hpp>
-#include <stdexcept>
-
-Window::GLInitHelper::GLInitHelper()
-{
- [[maybe_unused]] static auto init = []() {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
- if (const auto version = gladLoadGL(reinterpret_cast<GLADloadfunc>(SDL_GL_GetProcAddress)); version < 30003) {
- throw std::runtime_error {std::format("Insufficient OpenGL version: {}", version)};
- }
- else {
- return version;
- }
- }();
-}
+#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<int>(width), static_cast<int>(height)},
m_window {title.c_str(), static_cast<int>(SDL_WINDOWPOS_CENTERED), static_cast<int>(SDL_WINDOWPOS_CENTERED), size.x,
size.y, flags},
- glContext {m_window}, uiShader {width, height}
+ glContext {m_window}
{
}
@@ -39,23 +28,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 +53,15 @@ Window::refresh() const
SDL_GL_MakeCurrent(m_window, glContext);
clear(0.0F, 0.0F, 0.0F, 1.0F);
- render();
+ ImGui_ImplOpenGL3_NewFrame();
+ ImGui_ImplSDL2_NewFrame();
+ ImGui::NewFrame();
+ if (content) {
+ content->render();
+ // Render UI stuff here
+ }
+ ImGui::Render();
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
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 <SDL2/SDL.h>
#include <cstddef>
-#include <special_members.h>
#include <string>
using SDL_WindowPtr = wrapped_ptrt<SDL_Window, SDL_CreateWindow, SDL_DestroyWindow>;
@@ -22,24 +21,26 @@ public:
NO_COPY(Window);
NO_MOVE(Window);
- virtual void tick(TickDuration elapsed) = 0;
+ template<typename C, typename... P>
+ void
+ setContent(P &&... p)
+ {
+ glm::ivec2 size {};
+ SDL_GetWindowSizeInPixels(m_window, &size.x, &size.y);
+ content = std::make_unique<C>(size.x, size.y, std::forward<P>(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<UIComponent> 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 <functional>
+
+class WindowContent : public StdTypeDefs<WindowContent> {
+public:
+ using Factory = std::function<Ptr(size_t width, size_t height)>;
+ 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<UIComponent> uiComponents;
+ UIShader uiShader;
+};