summaryrefslogtreecommitdiffhomepage
path: root/editor/app.hpp
blob: 1be252ba47e113051811be6becf52a8539df3d85 (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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#pragma once
#include "compat/defs.hpp"
#include "compat/enum-bitset-fwd.hpp"
#include "compat/safe-ptr.hpp"
#include "floormat/app.hpp"
#include "keys.hpp"
#include "src/global-coords.hpp"
#include "src/object-id.hpp"
#include "editor-enums.hpp"
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Pointer.h>
#include <Corrade/Containers/Optional.h>
#include <Magnum/Math/Vector2.h>

namespace Magnum::GL {
template<UnsignedInt dimensions> class Texture;
typedef Texture<2> Texture2D;
} // namespace Magnum::GL

namespace Magnum::ImGuiIntegration { class Context; }

namespace floormat::wireframe {
GL::Texture2D make_constant_texture();
struct meshes;
} // namespace floormat::wireframe

namespace floormat::tests { struct tests_data; }

namespace floormat {

struct fm_settings;
struct floormat_main;
class world;
class chunk;
class ground_atlas;
class anim_atlas;
struct object;
struct critter;
struct point;
class editor;
template<typename T> struct shared_ptr_wrapper;
struct tests_data_;

struct cursor_state final
{
    Optional<Vector2i> pixel;
    Optional<global_coords> tile;
    Optional<Vector2b> subpixel;
    bool in_imgui = false;

    Optional<struct point> point() const;
};

struct clickable;

enum class Cursor: uint32_t {
    Arrow, TextInput, Wait, Crosshair, WaitArrow,
    ResizeNWSE, ResizeNESW, ResizeWE, ResizeNS, ResizeAll,
    No, Hand, Hidden, HiddenLocked,
};

enum class popup_target_type : unsigned char {
    none, scenery,
};

struct popup_target final {
    object_id id; // todo switch to weak_ptr<object>
    popup_target_type target = popup_target_type::none;
    bool operator==(const popup_target&) const;
};

struct app final : floormat_app
{
    static int run_from_argv(int argc, const char* const* argv);
    static fm_settings parse_cmdline(int argc, const char* const* argv);
    ~app() override;
#ifdef _WIN32
    static void set_dpi_aware();
#endif
    object_id get_object_colliding_with_cursor();
    floormat_main& main();
    const struct cursor_state& cursor_state();
    clickable* find_clickable_scenery(const Optional<Vector2i>& pixel);
    Vector2 point_screen_pos(point pt);
    shared_ptr_wrapper<critter> ensure_player_character(world& w);

private:
    explicit app(fm_settings&& opts);

    fm_DECLARE_DELETED_COPY_ASSIGNMENT(app);
    fm_DECLARE_DEPRECATED_MOVE_ASSIGNMENT(app);

    int exec();

    void update(Ns dt) override;
    void update_world(Ns dt);
    void update_cursor_tile(const Optional<Vector2i>& pixel);
    z_bounds get_z_bounds() override;
    void set_cursor();
    void maybe_initialize_chunk(const chunk_coords_& pos, chunk& c) override;
    void maybe_initialize_chunk_(const chunk_coords_& pos, chunk& c);
    void update_character(Ns dt);
    void reset_world();
    void reset_world(class world&& w);

    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;
    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;
    void on_viewport_event(const Magnum::Math::Vector2<int>& size) noexcept override;
    void on_any_event(const any_event& event) noexcept override;
    void on_focus_in() noexcept override;
    void on_focus_out() noexcept override;
    void on_mouse_leave() noexcept override;
    void on_mouse_enter() noexcept override;

    void do_mouse_move(int modifiers);
    void do_mouse_up_down(uint8_t button, bool is_down, int modifiers);
    void do_mouse_scroll(int offset);

    void do_quicksave();
    void do_quickload();
    void do_new_file();
    void do_escape();

    void draw_collision_boxes();
    void draw_clickables();
    void draw_light_info();
    void draw_lightmap_test(float main_menu_height);
    void do_lightmap_test();

    void draw_editor_pane(float main_menu_height);
    void draw_inspector();
    static void entity_inspector_name(char* buf, size_t len, object_id id);
    static void entity_friendly_name(char* buf, size_t len, const object& obj);
    bool check_inspector_exists(const popup_target& p);
    void set_cursor_from_imgui();
    void draw_cursor();
    void init_imgui(Vector2i size);
    void draw_ui();
    float draw_main_menu();
    void draw_fps();
    void draw_tile_under_cursor();
    void draw_z_level();
    void do_popup_menu();
    void kill_popups(bool hard);
    void render_menu();

    using key_set = enum_bitset<key, key_COUNT>;
    void do_key(key k, int mods);
    void do_key(key k);
    void do_set_mode(editor_mode mode);
    void do_rotate(bool backward);
    void do_emit_timestamp();
    void apply_commands(const key_set& k);
    int get_key_modifiers();
    void clear_keys(key min_inclusive, key max_exclusive);
    void clear_keys();
    void clear_non_global_keys();
    void clear_non_repeated_keys();

    void do_camera(const Ns& dt, const key_set& cmds, int mods);
    void reset_camera_offset();

    [[nodiscard]] bool tests_handle_key(const key_event& e, bool is_down);
    [[nodiscard]] bool tests_handle_mouse_click(const mouse_button_event& e, bool is_down);
    [[nodiscard]] bool tests_handle_mouse_move(const mouse_move_event& e);
    void tests_pre_update(Ns dt);
    void tests_post_update(Ns dt);
    void draw_tests_pane(float width);
    void draw_tests_overlay();
    void tests_reset_mode();
    tests::tests_data& tests();

    void reserve_inspector_array();
    void add_inspector(popup_target p);
    void erase_inspector(size_t index, ptrdiff_t count = 1);
    void kill_inspectors();

    uint64_t _timestamp = 0;
    floormat_main* M;
    safe_ptr<ImGuiIntegration::Context> _imgui;
    safe_ptr<floormat::wireframe::meshes> _wireframe;
    safe_ptr<tests_data_> _tests;
    safe_ptr<editor> _editor;
    safe_ptr<key_set> keys_;
    struct key_modifiers_ { int data[key_COUNT]; } key_modifiers;
    Array<popup_target> inspectors;
    object_id _character_id = 0;
    struct cursor_state cursor;
    popup_target _popup_target;

    Optional<chunk_coords_> tested_light_chunk;

    int8_t _z_level = 0;

    bool _pending_popup         : 1 = false;
    bool _render_bboxes         : 1 = false;
    bool _render_clickables     : 1 = false;
    bool _render_vobjs          : 1 = true;
    bool _render_all_z_levels   : 1 = true;
};

} // namespace floormat