summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-10-28 03:07:00 +0100
committerStanislaw Halik <sthalik@misaki.pl>2024-10-28 08:48:29 +0100
commit5032581ffc1e29d6b139d66eaa7228c0113bed14 (patch)
tree0fa40a95cba1ceacddef4b032b40e4b605329166
parent221861499394aa8fa5c2682cafb3387ab9a3683f (diff)
wip to rebasewip22
-rw-r--r--compat/assert.hpp12
-rw-r--r--editor/app.hpp12
-rw-r--r--editor/events.cpp147
-rw-r--r--editor/imgui-editors.cpp4
-rw-r--r--editor/imgui.cpp2
-rw-r--r--floormat/app.hpp9
-rw-r--r--floormat/events.hpp11
-rw-r--r--main/events.cpp100
-rw-r--r--main/main-impl.hpp9
-rw-r--r--main/sdl-fwd.hpp11
-rw-r--r--main/sdl-fwd.inl15
11 files changed, 210 insertions, 122 deletions
diff --git a/compat/assert.hpp b/compat/assert.hpp
index 8c882b0e..3daf33ce 100644
--- a/compat/assert.hpp
+++ b/compat/assert.hpp
@@ -39,10 +39,20 @@ void fm_emit_debug_loc0(const char* file, int line, fm_FORMAT_ARG_MSVC const cha
#define fm_debug_loc(pfx, ...) (::floormat::fm_emit_debug_loc(pfx, __FILE__, __LINE__,__VA_ARGS__))
#define fm_debug_loc0(...) (::floormat::fm_emit_debug_loc0(__FILE__, __LINE__,__VA_ARGS__))
+#if defined FM_NO_DEBUG && !defined FM_NO_DEBUG2
+#define FM_NO_DEBUG2
+#endif
+
#ifndef FM_NO_DEBUG
#define fm_debug_assert(...) fm_assert(__VA_ARGS__)
#else
-#define fm_debug_assert(...) void()
+#define fm_debug_assert(...) (void())
+#endif
+
+#ifndef FM_NO_DEBUG2
+#define fm_debug2_assert(...) fm_assert(__VA_ARGS__)
+#else
+#define fm_debug2_assert(...) (void())
#endif
#define fm_warn_once(...) do { \
diff --git a/editor/app.hpp b/editor/app.hpp
index b04da7dc..1e990f6c 100644
--- a/editor/app.hpp
+++ b/editor/app.hpp
@@ -108,10 +108,14 @@ private:
void draw() override;
- void on_mouse_move(const mouse_move_event& event) noexcept override;
- void on_mouse_up_down(const mouse_button_event& event, bool is_down) noexcept override;
- void on_mouse_scroll(const mouse_scroll_event& event) noexcept override;
- void on_key_up_down(const key_event& event, bool is_down) noexcept override;
+ [[nodiscard]] bool do_imgui_key(const sdl2::EvKey& ev, bool is_down);
+ [[nodiscard]] bool do_imgui_click(const sdl2::EvClick& ev, bool is_down);
+ [[nodiscard]] bool do_tests_key(const key_event& ev, bool is_down);
+
+ void on_mouse_move(const mouse_move_event& event, const sdl2::EvMove& ev) noexcept override;
+ void on_mouse_up_down(const mouse_button_event& event, bool is_down, const sdl2::EvClick& ev) noexcept override;
+ void on_mouse_scroll(const mouse_scroll_event& event, const sdl2::EvScroll& ev) noexcept override;
+ void on_key_up_down(const key_event& event, bool is_down, const sdl2::EvKey& ev) noexcept override;
std::tuple<key, int> resolve_keybinding(int k, int mods);
void on_text_input_event(const text_input_event& event) noexcept override;
//bool on_text_editing_event(const text_editing_event& event) noexcept override;
diff --git a/editor/events.cpp b/editor/events.cpp
index 1a259d0e..b25cdb7e 100644
--- a/editor/events.cpp
+++ b/editor/events.cpp
@@ -2,6 +2,7 @@
#include "floormat/main.hpp"
#include "floormat/events.hpp"
+#include "main/sdl-fwd.inl"
#include "src/world.hpp"
#include "keys.hpp"
#include "editor.hpp"
@@ -12,19 +13,14 @@
namespace floormat {
-void app::on_focus_in() noexcept {}
-void app::on_mouse_enter() noexcept {}
-void app::on_any_event(const any_event&) noexcept {}
-
-#define accessor(type, name) \
- type m_##name = {}; auto name() const noexcept { return m_##name; }
+namespace {
-static constexpr int fixup_mods_(int mods, int value, int mask)
+constexpr int fixup_mods_(int mods, int value, int mask)
{
return !!(mods & mask) * value;
}
-static constexpr int fixup_mods(int mods)
+constexpr int fixup_mods(int mods)
{
int ret = 0;
ret |= fixup_mods_(mods, kmod_ctrl, KMOD_CTRL);
@@ -34,11 +30,49 @@ static constexpr int fixup_mods(int mods)
return ret;
}
+} // namespace
+
+
+using PointerButtons = Platform::Sdl2Application::Pointer;
+using PointerEvent = Platform::Sdl2Application::PointerEvent;
+using PointerMoveEvent = Platform::Sdl2Application::PointerMoveEvent;
+
+void app::on_focus_in() noexcept {}
+void app::on_mouse_enter() noexcept {}
+void app::on_any_event(const any_event&) noexcept {}
+
+#define accessor(type, name) \
+ type m_##name = {}; auto name() const noexcept { return m_##name; }
+
+bool app::do_imgui_key(const sdl2::EvKey& ev, bool is_down)
+{
+ if (is_down)
+ return _imgui->handleKeyPressEvent(ev.val);
+ else
+ return _imgui->handleKeyReleaseEvent(ev.val);
+}
+
+bool app::do_imgui_click(const sdl2::EvClick& ev, bool is_down)
+{
+ if (is_down)
+ return _imgui->handlePointerPressEvent(ev.val);
+ else
+ return _imgui->handlePointerReleaseEvent(ev.val);
+}
+
+bool app::do_tests_key(const key_event& ev, bool is_down)
+{
+ bool ret = _editor->mode() == editor_mode::tests;
+ if (ret)
+ return tests_handle_key(ev, is_down);
+ return ret;
+}
+
void app::clear_keys(key min_inclusive, key max_exclusive)
{
auto& keys = *keys_;
using key_type = std::decay_t<decltype(keys)>::value_type;
- for (key_type i = key_type(min_inclusive); i < key_type(max_exclusive); i++)
+ for (auto i = key_type(min_inclusive); i < key_type(max_exclusive); i++)
{
const auto idx = key(i);
keys[idx] = false;
@@ -52,58 +86,59 @@ void app::clear_keys()
key_modifiers = {};
}
-void app::on_mouse_move(const mouse_move_event& event) noexcept
+void app::on_mouse_move(const mouse_move_event& event, const sdl2::EvMove& ev) noexcept
{
- if (!(event.position >= Vector2i() && event.position < M->window_size()))
- return;
+ do
+ {
+ cursor.in_imgui = _imgui->handlePointerMoveEvent(ev.val);
+ if (cursor.in_imgui)
+ break;
+ if (_editor->mode() == editor_mode::tests)
+ {
+ (void)tests_handle_mouse_move(event);
+ break;
+ }
+ }
+ while (false);
- struct {
- accessor(Vector2i, position)
- } e = {event.position};
-
- if ((cursor.in_imgui = _imgui->handleMouseMoveEvent(e)))
- void();
- else if (_editor->mode() == editor_mode::tests && tests_handle_mouse_move(event))
- void();
- update_cursor_tile(event.position);
+ update_cursor_tile(Vector2i(event.position));
do_mouse_move(fixup_mods(event.mods));
}
-void app::on_mouse_up_down(const mouse_button_event& event, bool is_down) noexcept
+void app::on_mouse_up_down(const mouse_button_event& event, bool is_down, const sdl2::EvClick& ev) noexcept
{
- if (!(event.position >= Vector2i() && event.position < M->window_size()))
+ const auto p = Vector2i(event.position);
+
+ if (!(p >= Vector2i{} && p < M->window_size()))
return;
- struct ev {
- enum class Button : std::underlying_type_t<mouse_button> {
- Left = mouse_button_left,
- Right = mouse_button_right,
- Middle = mouse_button_middle,
- };
- accessor(Vector2i, position)
- accessor(Button, button)
- } e = {event.position, ev::Button(event.button)};
-
- if ((cursor.in_imgui = is_down ? _imgui->handleMousePressEvent(e) : _imgui->handleMouseReleaseEvent(e)))
- void();
- else if (_editor->mode() == editor_mode::tests && tests_handle_mouse_click(event, is_down))
- void();
- else
+ do
+ {
+ cursor.in_imgui = do_imgui_click(ev, is_down);
+ if (cursor.in_imgui)
+ break;
+ if (_editor->mode() == editor_mode::tests)
+ if (tests_handle_mouse_click(event, is_down))
+ break;
do_mouse_up_down(event.button, is_down, fixup_mods(event.mods));
+ }
+ while(false);
}
-void app::on_mouse_scroll(const mouse_scroll_event& event) noexcept
+void app::on_mouse_scroll(const mouse_scroll_event& event, const sdl2::EvScroll& ev) noexcept
{
- if (!(event.position >= Vector2i() && event.position < M->window_size()))
- return;
+ const auto p = Vector2i(event.position);
- struct {
- accessor(Vector2, offset)
- accessor(Vector2i, position)
- } e = {event.offset, event.position};
-
- if (!(cursor.in_imgui = _imgui->handleMouseScrollEvent(e)))
- do_mouse_scroll((int)e.offset()[1]);
+ do
+ {
+ if (p >= Vector2i() && p < M->window_size())
+ break;
+ cursor.in_imgui = _imgui->handleScrollEvent(ev.val);
+ if (cursor.in_imgui)
+ break;
+ do_mouse_scroll((int)ev.val.offset()[1]);
+ }
+ while (false);
}
auto app::resolve_keybinding(int k_, int mods_) -> std::tuple<key, int>
@@ -190,23 +225,13 @@ auto app::resolve_keybinding(int k_, int mods_) -> std::tuple<key, int>
void app::clear_non_global_keys() { clear_keys(key_MIN, key_GLOBAL); }
void app::clear_non_repeated_keys() { clear_keys(key_NO_REPEAT, key_COUNT); }
-void app::on_key_up_down(const key_event& event, bool is_down) noexcept
+void app::on_key_up_down(const key_event& event, bool is_down, const sdl2::EvKey& ev) noexcept
{
- using KeyEvent = Platform::Sdl2Application::KeyEvent;
- struct Ev
- {
- using Key = KeyEvent::Key;
- using Modifier = KeyEvent::Modifier;
- using Modifiers = KeyEvent::Modifiers;
- accessor(Key, key)
- accessor(Modifiers, modifiers)
- } e = {Ev::Key(event.key), Ev::Modifier(event.mods)};
-
auto [x, mods] = resolve_keybinding(event.key, event.mods);
static_assert(key_GLOBAL >= key_NO_REPEAT);
- if ((x == key_COUNT || x < key_GLOBAL) && (is_down ? _imgui->handleKeyPressEvent(e) : _imgui->handleKeyReleaseEvent(e)) ||
- (x == key_COUNT || x == key_escape) && _editor->mode() == editor_mode::tests && tests_handle_key(event, is_down))
+ if ((x == key_COUNT || x < key_GLOBAL) && do_imgui_key(ev, is_down) ||
+ (x == key_COUNT || x == key_escape) && do_tests_key(event, is_down))
clear_non_global_keys();
else if (x >= key_NO_REPEAT)
is_down && !event.is_repeated ? do_key(x, mods, event.key & ~SDLK_SCANCODE_MASK) : void();
diff --git a/editor/imgui-editors.cpp b/editor/imgui-editors.cpp
index 4e331bcf..1dfc18fc 100644
--- a/editor/imgui-editors.cpp
+++ b/editor/imgui-editors.cpp
@@ -114,7 +114,7 @@ void draw_editor_tile_pane_atlas(ground_editor& ed, StringView name, const bptr<
snformat(buf, "##item_{}"_cf, i);
const auto uv = atlas->texcoords_for_id(i);
constexpr ImVec2 size_2 = { TILE_SIZE[0]*.5f, TILE_SIZE[1]*.5f };
- ImGui::ImageButton(buf, (void*)&atlas->texture(), ImVec2(size_2.x * dpi[0], size_2.y * dpi[1]),
+ ImGui::ImageButton(buf, atlas->texture().id(), ImVec2(size_2.x * dpi[0], size_2.y * dpi[1]),
{ uv[3][0], uv[3][1] }, { uv[0][0], uv[0][1] });
if (ImGui::IsItemClicked(ImGuiMouseButton_Left))
ed.select_tile(atlas, i);
@@ -181,7 +181,7 @@ void impl_draw_editor_scenery_pane(T& ed, Vector2 dpi)
const ImVec2 uv0 {texcoords[3][0], texcoords[3][1]}, uv1 {texcoords[0][0], texcoords[0][1]};
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + std::max(0.f, .5f*(thumbnail_width - img_size.x)));
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + .5f*std::max(0.f, row_height - img_size.y));
- ImGui::Image((void*)&atlas.texture(), img_size, uv0, uv1);
+ ImGui::Image(atlas.texture().id(), img_size, uv0, uv1);
click_event();
}
if (ImGui::TableSetColumnIndex(1))
diff --git a/editor/imgui.cpp b/editor/imgui.cpp
index 0e5b56cc..81ecd59c 100644
--- a/editor/imgui.cpp
+++ b/editor/imgui.cpp
@@ -312,7 +312,7 @@ void app::draw_lightmap_test(float main_menu_height)
if (ImGui::Begin("Lightmap", &is_open, flags))
{
- ImGui::Image(&shader.accum_texture(), preview_size, {0, 0}, {1, 1});
+ ImGui::Image(shader.accum_texture().id(), preview_size, {0, 0}, {1, 1});
ImGui::End();
}
else
diff --git a/floormat/app.hpp b/floormat/app.hpp
index 02f7d24c..9d1ac7e3 100644
--- a/floormat/app.hpp
+++ b/floormat/app.hpp
@@ -1,4 +1,5 @@
#pragma once
+#include "main/sdl-fwd.hpp"
namespace Magnum::Math { template<typename T> class Vector2; template<class T> class Nanoseconds; }
@@ -35,10 +36,10 @@ struct floormat_app
virtual void draw() = 0;
virtual z_bounds get_z_bounds() = 0;
- virtual void on_mouse_move(const mouse_move_event& event) noexcept = 0;
- virtual void on_mouse_up_down(const mouse_button_event& event, bool is_down) noexcept = 0;
- virtual void on_mouse_scroll(const mouse_scroll_event& event) noexcept = 0;
- virtual void on_key_up_down(const key_event& event, bool is_down) noexcept = 0;
+ virtual void on_mouse_move(const mouse_move_event& event, const sdl2::EvMove& ev) noexcept = 0;
+ virtual void on_mouse_up_down(const mouse_button_event& event, bool is_down, const sdl2::EvClick& ev) noexcept = 0;
+ virtual void on_mouse_scroll(const mouse_scroll_event& event, const sdl2::EvScroll& ev) noexcept = 0;
+ virtual void on_key_up_down(const key_event& event, bool is_down, const sdl2::EvKey& ev) noexcept = 0;
virtual void on_text_input_event(const text_input_event& event) noexcept = 0;
//virtual bool on_text_editing_event(const text_editing_event& event) noexcept = 0;
virtual void on_viewport_event(const Magnum::Math::Vector2<int>& size) noexcept = 0;
diff --git a/floormat/events.hpp b/floormat/events.hpp
index 68c2bedd..af3e6248 100644
--- a/floormat/events.hpp
+++ b/floormat/events.hpp
@@ -14,22 +14,25 @@ enum mouse_button : unsigned char {
};
struct mouse_button_event final {
- Vector2i position;
+ Vector2 position;
int mods = 0;
mouse_button button = mouse_button_none;
uint8_t click_count = 0;
+ bool is_primary : 1 = false;
};
struct mouse_move_event final {
- Vector2i position;
- mouse_button buttons = mouse_button_none;
+ Vector2 position;
int mods = 0;
+ mouse_button buttons = mouse_button_none;
+ bool is_primary : 1 = false;
};
struct mouse_scroll_event final {
Magnum::Vector2 offset;
- Vector2i position;
+ Vector2 position;
int mods = 0;
+ bool is_primary : 1 = false;
};
struct text_input_event final {
diff --git a/main/events.cpp b/main/events.cpp
index 1f1c81a2..59dfe28e 100644
--- a/main/events.cpp
+++ b/main/events.cpp
@@ -1,84 +1,102 @@
#include "main-impl.hpp"
#include "floormat/app.hpp"
#include "floormat/events.hpp"
+#include "sdl-fwd.inl"
#include <cstring>
#include <SDL_events.h>
#include <SDL_keyboard.h>
namespace floormat {
-void main_impl::viewportEvent(Platform::Sdl2Application::ViewportEvent& event)
+namespace {
+
+using Buttons = Platform::Sdl2Application::Pointers;
+
+mouse_button pointer_to_button_mask(Buttons b) { return mouse_button((uint8_t)b); }
+
+any_event make_any_event(const SDL_Event& e)
+{
+ static_assert(sizeof(SDL_Event) <= sizeof(any_event::buf));
+ any_event ret;
+ std::memcpy(&ret.buf, &e, sizeof(SDL_Event));
+ return ret;
+}
+
+} // namespace
+
+void main_impl::viewportEvent(ViewportEvent& event)
{
_framebuffer_size = event.framebufferSize();
recalc_viewport(event.framebufferSize(), event.windowSize());
app.on_viewport_event(event.framebufferSize());
}
-void main_impl::mousePressEvent(Platform::Sdl2Application::MouseEvent& event)
+void main_impl::pointerPressEvent(PointerEvent& ev)
{
- app.on_mouse_up_down({event.position() * _virtual_scale,
- (SDL_Keymod)(uint16_t)event.modifiers(),
- mouse_button(SDL_BUTTON((uint8_t)event.button())),
- uint8_t(std::min(255, event.clickCount()))},
- true);
+ app.on_mouse_up_down({
+ ev.position() * _virtual_scale,
+ (SDL_Keymod)(uint16_t)ev.modifiers(),
+ pointer_to_button_mask(ev.pointer()),
+ uint8_t(std::min(255, ev.clickCount())),
+ }, true, {ev});
}
-void main_impl::mouseReleaseEvent(Platform::Sdl2Application::MouseEvent& event)
+void main_impl::pointerReleaseEvent(PointerEvent& ev)
{
- app.on_mouse_up_down({event.position() * _virtual_scale,
- (SDL_Keymod)(uint16_t)event.modifiers(),
- mouse_button(SDL_BUTTON((uint8_t)event.button())),
- uint8_t(std::min(255, event.clickCount()))},
- false);
+ app.on_mouse_up_down({
+ ev.position() * _virtual_scale,
+ (SDL_Keymod)(uint16_t)ev.modifiers(),
+ pointer_to_button_mask(ev.pointer()),
+ uint8_t(std::min(255, ev.clickCount())),
+ }, false, {ev});
}
-void main_impl::mouseMoveEvent(Platform::Sdl2Application::MouseMoveEvent& event)
+void main_impl::pointerMoveEvent(PointerMoveEvent& ev)
{
- app.on_mouse_move({event.position() * _virtual_scale,
- (mouse_button)(uint8_t)uint32_t{event.buttons()},
- (SDL_Keymod)(uint16_t)event.modifiers()});
+ app.on_mouse_move({
+ ev.position() * _virtual_scale,
+ (SDL_Keymod)(uint16_t)ev.modifiers(),
+ pointer_to_button_mask(ev.pointers()),
+ ev.isPrimary(),
+ }, {ev});
}
-void main_impl::mouseScrollEvent(Platform::Sdl2Application::MouseScrollEvent& event)
+void main_impl::scrollEvent(ScrollEvent& ev)
{
- app.on_mouse_scroll({event.offset(), event.position() * _virtual_scale,
- (SDL_Keymod)(uint16_t)event.modifiers()});
+ app.on_mouse_scroll({
+ ev.offset(), ev.position() * _virtual_scale,
+ (SDL_Keymod)(uint16_t)ev.modifiers(),
+ }, {ev});
}
-void main_impl::textInputEvent(Platform::Sdl2Application::TextInputEvent& event)
+void main_impl::textInputEvent(TextInputEvent& event)
{
app.on_text_input_event({event.text()});
}
#if 0
-void main_impl::textEditingEvent(Platform::Sdl2Application::TextEditingEvent& event)
+void main_impl::textEditingEvent(TextEditingEvent& event)
{
app.on_text_editing_event({event.text(), event.start(), event.length()})
}
#endif
-void main_impl::keyPressEvent(Platform::Sdl2Application::KeyEvent& event)
-{
- app.on_key_up_down({(SDL_Keycode)(uint32_t)event.key(),
- (SDL_Keymod)(uint16_t)event.modifiers(),
- event.isRepeated()},
- true);
-}
-
-void main_impl::keyReleaseEvent(Platform::Sdl2Application::KeyEvent& event)
+void main_impl::keyPressEvent(KeyEvent& event)
{
- app.on_key_up_down({(SDL_Keycode)(uint32_t)event.key(),
- (SDL_Keymod)(uint16_t)event.modifiers(),
- event.isRepeated()},
- false);
+ app.on_key_up_down({
+ (SDL_Keycode)(uint32_t)event.key(),
+ (SDL_Keymod)(uint16_t)event.modifiers(),
+ event.isRepeated()
+ }, true, {event});
}
-static any_event make_any_event(const SDL_Event& e)
+void main_impl::keyReleaseEvent(KeyEvent& event)
{
- static_assert(sizeof(SDL_Event) <= sizeof(any_event::buf));
- any_event ret;
- std::memcpy(&ret.buf, &e, sizeof(SDL_Event));
- return ret;
+ app.on_key_up_down({
+ (SDL_Keycode)(uint32_t)event.key(),
+ (SDL_Keymod)(uint16_t)event.modifiers(),
+ event.isRepeated()
+ }, false, {event});
}
void main_impl::anyEvent(SDL_Event& event)
@@ -108,7 +126,7 @@ void main_impl::anyEvent(SDL_Event& event)
int floormat_main::get_mods() noexcept
{
- return (int)SDL_GetModState();
+ return SDL_GetModState();
}
} // namespace floormat
diff --git a/main/main-impl.hpp b/main/main-impl.hpp
index 3fb8bac5..17aecc72 100644
--- a/main/main-impl.hpp
+++ b/main/main-impl.hpp
@@ -9,6 +9,7 @@
#include "shaders/texture-unit-cache.hpp"
#include "shaders/shader.hpp"
#include "shaders/lightmap.hpp"
+#include "main/sdl-fwd.hpp"
#include "main/clickable.hpp"
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/String.h>
@@ -76,10 +77,10 @@ struct main_impl final : private Platform::Sdl2Application, public floormat_main
const Platform::Sdl2Application& application() const noexcept override;
[[maybe_unused]] void viewportEvent(ViewportEvent& event) override;
- [[maybe_unused]] void mousePressEvent(MouseEvent& event) override;
- [[maybe_unused]] void mouseReleaseEvent(MouseEvent& event) override;
- [[maybe_unused]] void mouseMoveEvent(MouseMoveEvent& event) override;
- [[maybe_unused]] void mouseScrollEvent(MouseScrollEvent& event) override;
+ [[maybe_unused]] void pointerPressEvent(PointerEvent& ev) override;
+ [[maybe_unused]] void pointerReleaseEvent(PointerEvent& ev) override;
+ [[maybe_unused]] void pointerMoveEvent(PointerMoveEvent& ev) override;
+ [[maybe_unused]] void scrollEvent(ScrollEvent& ev) override;
[[maybe_unused]] void textInputEvent(TextInputEvent& event) override;
//[[maybe_unused]] void textEditingEvent(TextEditingEvent& event) override;
[[maybe_unused]] void keyPressEvent(KeyEvent& event) override;
diff --git a/main/sdl-fwd.hpp b/main/sdl-fwd.hpp
new file mode 100644
index 00000000..776ec0a8
--- /dev/null
+++ b/main/sdl-fwd.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+namespace floormat::sdl2 {
+
+struct EvButtons;
+struct EvClick;
+struct EvMove;
+struct EvScroll;
+struct EvKey;
+
+} // namespace floormat::sdl2
diff --git a/main/sdl-fwd.inl b/main/sdl-fwd.inl
new file mode 100644
index 00000000..25bc45ee
--- /dev/null
+++ b/main/sdl-fwd.inl
@@ -0,0 +1,15 @@
+#pragma once
+#include "sdl-fwd.hpp"
+#include <Magnum/Platform/Sdl2Application.h>
+
+namespace floormat::sdl2 {
+
+using App = Platform::Sdl2Application;
+
+struct EvButtons { App::Pointer& val; };
+struct EvClick { App::PointerEvent& val; };
+struct EvMove { App::PointerMoveEvent& val; };
+struct EvScroll { App::ScrollEvent& val; };
+struct EvKey { App::KeyEvent& val; };
+
+} // namespace floormat::sdl2