summaryrefslogtreecommitdiffhomepage
path: root/main/app.hpp
blob: 8970aa15d2822d48cd8c7e09c1f6e1e49760842e (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
139
140
141
142
143
#pragma once
#include "tile-atlas.hpp"
#include "chunk.hpp"
#include "shaders/tile-shader.hpp"
#include "src/loader.hpp"
#include "draw/floor-mesh.hpp"
#include "draw/wall-mesh.hpp"
#include "draw/wireframe-mesh.hpp"
#include "draw/wireframe-quad.hpp"
#include "draw/wireframe-box.hpp"
#include "compat/enum-bitset.hpp"
#include "editor.hpp"
#include "world.hpp"
#include <Magnum/Timeline.h>
#include <Magnum/GL/DebugOutput.h>
#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/ImGuiIntegration/Context.h>
#include <memory>

#define FM_MSAA

#ifdef FM_MSAA
#include <Magnum/GL/Framebuffer.h>
#include <Magnum/GL/Renderbuffer.h>
#endif

namespace floormat {

struct app final : private Platform::Sdl2Application
{
    static int run_from_argv(int argc, char** argv);
    virtual ~app();

private:
    struct app_settings;

    [[maybe_unused]] [[noreturn]] static void usage(const Utility::Arguments& args);
    explicit app(const Arguments& arguments, app_settings opts);

    using dpi_policy = Platform::Implementation::Sdl2DpiScalingPolicy;
    using tile_atlas_ = std::shared_ptr<tile_atlas>;

    void update(double dt);

    void do_key(KeyEvent::Key k, KeyEvent::Modifiers m, bool pressed, bool repeated);
    void do_mouse_click(global_coords pos, int button);
    void do_mouse_release(int button);
    void do_mouse_move(global_coords pos);

    void do_camera(double dt);
    void reset_camera_offset();
    void recalc_cursor_tile();
    void recalc_viewport(Vector2i size);
    void init_imgui(Vector2i size);

    [[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 textInputEvent(TextInputEvent& event) override;
    [[maybe_unused]] void keyPressEvent(KeyEvent& event) override;
    [[maybe_unused]] void keyReleaseEvent(KeyEvent& event) override;
    [[maybe_unused]] void anyEvent(SDL_Event& event) override;

    void event_focus_out();
    void event_focus_in();
    void event_mouse_enter();
    void event_mouse_leave();

    std::array<std::int16_t, 4> get_draw_bounds() const noexcept;
    void drawEvent() override;
    void draw_msaa();
    void draw_world();
    void draw_cursor_tile();
    void draw_wireframe_quad(global_coords pt);
    void draw_wireframe_box(local_coords pt);

    void draw_ui();
    float draw_main_menu();
    void draw_editor_pane(tile_type& type, float main_menu_height);
    void draw_fps();
    void draw_cursor_coord();
    void render_menu();

    void debug_callback(GL::DebugOutput::Source src, GL::DebugOutput::Type type, UnsignedInt id,
                        GL::DebugOutput::Severity severity, const std::string& str) const;
    static void _debug_callback(GL::DebugOutput::Source src, GL::DebugOutput::Type type, UnsignedInt id,
                                GL::DebugOutput::Severity severity, const std::string& str, const void* self);
    void* register_debug_callback();

    global_coords pixel_to_tile(Vector2d position) const;

    enum class key : int {
        camera_up, camera_left, camera_right, camera_down, camera_reset,
        rotate_tile, quicksave, quickload,
        quit,
        MAX = quit, COUNT
    };
    void make_test_chunk(chunk& c);

    [[maybe_unused]] void* _dummy = register_debug_callback();

#ifdef FM_MSAA
    GL::Framebuffer _msaa_framebuffer{{{}, windowSize()}};
    GL::Renderbuffer _msaa_renderbuffer{};
#endif

    tile_shader _shader;
    tile_atlas_ floor1 = loader.tile_atlas("floor-tiles", {44, 4});
    tile_atlas_ floor2 = loader.tile_atlas("metal1", {2, 2});
    tile_atlas_ wall1  = loader.tile_atlas("wood2", {1, 1});
    tile_atlas_ wall2  = loader.tile_atlas("wood1", {1, 1});

    floor_mesh _floor_mesh;
    wall_mesh _wall_mesh;
    wireframe_mesh<wireframe::quad> _wireframe_quad;
    wireframe_mesh<wireframe::box> _wireframe_box;

    ImGuiIntegration::Context _imgui{NoCreate};

    world _world;
    enum_bitset<key> keys;
    Magnum::Timeline timeline;
    editor _editor;
    std::optional<Vector2i> _cursor_pixel;
    std::optional<global_coords> _cursor_tile;
    float _frame_time = 0;
    bool _cursor_in_imgui = false;

    struct app_settings {
        bool vsync = true;
    };

    app_settings _settings;

    static constexpr std::int16_t BASE_X = 0, BASE_Y = 0;
#ifdef FM_MSAA
    static constexpr int msaa_samples = 16;
#endif
};

} // namespace floormat