summaryrefslogtreecommitdiffhomepage
path: root/editor/events.cpp
blob: 74ee92ec3f960b5833790e2805f67defa66f19c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "app.hpp"

#include "floormat/main.hpp"
#include "floormat/events.hpp"
#include "src/world.hpp"

#include <utility>

#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/ImGuiIntegration/Context.hpp>

namespace floormat {

void app::on_focus_in() noexcept {}
void app::on_mouse_enter() noexcept {}
void app::on_any_event(const floormat::any_event& event) noexcept {}

#define accessor(type, name) \
    type m_##name = {}; auto name() const noexcept { return m_##name; }

void app::on_mouse_move(const mouse_move_event& event) noexcept
{
    struct {
        accessor(Vector2i, position)
    } e = {event.position};

    cursor.in_imgui = _imgui.handleMouseMoveEvent(e);

    if (!cursor.in_imgui)
        cursor.pixel = event.position;
    else
        cursor.pixel = std::nullopt;
    recalc_cursor_tile();

    if (cursor.tile)
        _editor.on_mouse_move(M->world(), *cursor.tile);
}

void app::on_mouse_up_down(const mouse_button_event& event, bool is_down) noexcept
{
    enum class Button : std::underlying_type_t<mouse_button> {
        Left = mouse_button_left,
        Right = mouse_button_right,
        Middle = mouse_button_middle,
    };
    struct ev {
        using Button = Button;
        accessor(Vector2i, position)
        accessor(Button, button)
    } e = {event.position, Button(event.button)};

    if (cursor.in_imgui = is_down
                          ? _imgui.handleMousePressEvent(e)
                          : _imgui.handleMouseReleaseEvent(e);
        !cursor.in_imgui)
    {
        cursor.pixel = event.position;
        recalc_cursor_tile();
        if (cursor.tile)
        {
            if (event.button == mouse_button_left && is_down)
                _editor.on_click(M->world(), *cursor.tile);
            else
                _editor.on_release();
        }
    }
}

void app::on_mouse_scroll(const mouse_scroll_event& event) noexcept
{
    struct {
        accessor(Vector2, offset)
        accessor(Vector2i, position)
    } e = {event.offset, event.position};
    _imgui.handleMouseScrollEvent(e);
}

void app::on_key_up_down(const floormat::key_event& event, bool is_down) noexcept
{
    using KeyEvent = Platform::Sdl2Application::KeyEvent;
    struct Ev final {
        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)};

    if (!(is_down ? _imgui.handleKeyPressEvent(e) : _imgui.handleKeyReleaseEvent(e)))
    {
        // todo put it into a separate function
        const key x = fm_begin(switch (event.key) {
                               default:            return key::COUNT;
                               case SDLK_w:        return key::camera_up;
                               case SDLK_a:        return key::camera_left;
                               case SDLK_s:        return key::camera_down;
                               case SDLK_d:        return key::camera_right;
                               case SDLK_HOME:     return key::camera_reset;
                               case SDLK_r:        return key::rotate_tile;
                               case SDLK_F5:       return key::quicksave;
                               case SDLK_F9:       return key::quickload;
                               case SDLK_ESCAPE:   return key::quit;
        });
        if (x != key::COUNT)
            keys[x] = is_down;
    }
    else
        keys = {};
}

void app::on_text_input_event(const floormat::text_input_event& event) noexcept
{
    struct {
        accessor(Containers::StringView, text)
    } e = {event.text};
    if (_imgui.handleTextInputEvent(e))
        keys = {};
}

void app::on_viewport_event(const Math::Vector2<int>& size) noexcept
{
    init_imgui(size);
}

void app::on_focus_out() noexcept
{
    cursor.pixel = std::nullopt;
    recalc_cursor_tile();
    keys = {};
}

void app::on_mouse_leave() noexcept
{
    cursor.pixel = std::nullopt;
    recalc_cursor_tile();
}

} // namespace floormat