diff options
-rw-r--r-- | main/app.cpp | 49 | ||||
-rw-r--r-- | main/app.hpp | 33 | ||||
-rw-r--r-- | main/camera.cpp | 23 | ||||
-rw-r--r-- | main/editor.hpp | 8 | ||||
-rw-r--r-- | main/imgui-raii.hpp | 84 | ||||
-rw-r--r-- | main/main.cpp | 18 | ||||
-rw-r--r-- | main/menu.cpp | 85 | ||||
-rw-r--r-- | shaders/tile-shader.cpp | 2 | ||||
-rw-r--r-- | shaders/tile-shader.hpp | 8 |
9 files changed, 204 insertions, 106 deletions
diff --git a/main/app.cpp b/main/app.cpp index e2d51455..9537bf58 100644 --- a/main/app.cpp +++ b/main/app.cpp @@ -4,6 +4,8 @@ #include <Magnum/GL/DefaultFramebuffer.h> #include <Magnum/ImGuiIntegration/Context.h> #include <Magnum/ImGuiIntegration/Context.hpp> +#include <SDL_events.h> +#include <SDL_video.h> namespace floormat { @@ -48,12 +50,19 @@ void app::mouseReleaseEvent(Platform::Sdl2Application::MouseEvent& event) { if (_imgui.handleMouseReleaseEvent(event)) return event.setAccepted(); +#if 0 + using Button = Platform::Sdl2Application::MouseEvent::Button; + if (event.button() == Button::Left) + { + } +#endif } void app::mouseMoveEvent(Platform::Sdl2Application::MouseMoveEvent& event) { if (_imgui.handleMouseMoveEvent(event)) - return event.setAccepted(); + return _cursor_pos = {}, event.setAccepted(); + _cursor_pos = event.position(); } void app::mouseScrollEvent(Platform::Sdl2Application::MouseScrollEvent& event) @@ -68,9 +77,47 @@ void app::textInputEvent(Platform::Sdl2Application::TextInputEvent& event) return keys = {}, event.setAccepted(); } +void app::anyEvent(SDL_Event& event) +{ + if (event.type == SDL_WINDOWEVENT) + switch (event.window.event) + { + case SDL_WINDOWEVENT_FOCUS_LOST: + return event_leave(); + case SDL_WINDOWEVENT_FOCUS_GAINED: + return event_enter(); + case SDL_WINDOWEVENT_LEAVE: + return event_mouse_leave(); + case SDL_WINDOWEVENT_ENTER: + return event_mouse_enter(); + default: + printf(""); break; // put breakpoint here + } +} + +void app::event_leave() +{ + _cursor_pos = std::nullopt; +} + +void app::event_enter() +{ + +} + +void app::event_mouse_leave() +{ + _cursor_pos = std::nullopt; +} + +void app::event_mouse_enter() +{ +} + void app::update(float dt) { do_camera(dt); + do_menu(); if (keys[key::quit]) Platform::Sdl2Application::exit(0); } diff --git a/main/app.hpp b/main/app.hpp index 7f508de5..0242365c 100644 --- a/main/app.hpp +++ b/main/app.hpp @@ -29,6 +29,7 @@ struct app final : Platform::Application void update(float dt); void do_camera(float dt); void reset_camera_offset(); + void keyPressEvent(KeyEvent& event) override; void keyReleaseEvent(KeyEvent& event) override; void mousePressEvent(MouseEvent& event) override; @@ -36,13 +37,19 @@ struct app final : Platform::Application void mouseMoveEvent(MouseMoveEvent& event) override; void mouseScrollEvent(MouseScrollEvent& event) override; void textInputEvent(TextInputEvent& event) override; + void anyEvent(SDL_Event& event) override; + void event_leave(); + void event_enter(); + void event_mouse_enter(); + void event_mouse_leave(); + void do_key(KeyEvent::Key k, KeyEvent::Modifiers m, bool pressed, bool repeated); void draw_chunk(chunk& c); - void draw_wireframe_quad(); - void draw_wireframe_box(); + void draw_wireframe_quad(local_coords pt); + void draw_wireframe_box(local_coords pt); void update_window_scale(Vector2i window_size); void viewportEvent(ViewportEvent& event) override; - void draw_menu(); + void do_menu(); void draw_menu_(tile_type& type, float main_menu_height); void setup_menu(); void display_menu(); @@ -50,6 +57,14 @@ struct app final : Platform::Application GL::DebugOutput::Severity severity, const std::string& str) const; void* register_debug_callback(); + Vector2 pixel_to_tile(Vector2 position) const; + void draw_cursor_tile(); + + std::optional<Vector2i> _cursor_pos; + + static constexpr Vector2 project(Vector3 pt); + static constexpr Vector2 unproject(Vector2 px); + enum class key : int { camera_up, camera_left, camera_right, camera_down, camera_reset, quit, @@ -78,4 +93,16 @@ struct app final : Platform::Application editor_state _editor; }; +constexpr Vector2 app::project(const Vector3 pt) +{ + const float x = -pt[1], y = -pt[0], z = pt[2]; + return { x-y, (x+y+z*2)*.59f }; +} + +constexpr Vector2 app::unproject(const Vector2 px) +{ + const float X = px[0], Y = px[1]; + return { X/2 + 50.f * Y / 59, 50 * Y / 59 - X/2 }; +} + } // namespace floormat diff --git a/main/camera.cpp b/main/camera.cpp index 967e1496..2bbadd00 100644 --- a/main/camera.cpp +++ b/main/camera.cpp @@ -5,7 +5,7 @@ namespace floormat { void app::do_camera(float dt) { - constexpr float pixels_per_second = 512; + constexpr float pixels_per_second = 256; if (keys[key::camera_up]) camera_offset += Vector2(0, 1) * dt * pixels_per_second; else if (keys[key::camera_down]) @@ -23,7 +23,7 @@ void app::do_camera(float dt) void app::reset_camera_offset() { - camera_offset = _shader.project({TILE_MAX_DIM*TILE_SIZE[0]/2.f, TILE_MAX_DIM*TILE_SIZE[1]/2.f, 0}); + camera_offset = project({TILE_MAX_DIM*TILE_SIZE[0]/2.f, TILE_MAX_DIM*TILE_SIZE[1]/2.f, 0}); //camera_offset = {}; } @@ -32,4 +32,23 @@ void app::update_window_scale(Vector2i sz) _shader.set_scale(Vector2{sz}); } +Vector2 app::pixel_to_tile(Vector2 position) const +{ + const auto px = position - Vector2{windowSize()}*.5f - camera_offset; + return unproject(px) / Vector2{TILE_SIZE[0]*.5f, TILE_SIZE[1]*.5f} + Vector2{.5f, .5f}; +} + +void app::draw_cursor_tile() +{ + if (_cursor_pos) + { + const auto tile = pixel_to_tile(Vector2(*_cursor_pos)); + if (std::min(tile[0], tile[1]) >= 0 && std::max(tile[0], tile[1]) < (int)TILE_MAX_DIM) + { + const auto x = std::uint8_t(tile[0]), y = std::uint8_t(tile[1]); + draw_wireframe_quad({x, y}); + } + } +} + } // namespace floormat diff --git a/main/editor.hpp b/main/editor.hpp index 1f0a0f72..44149555 100644 --- a/main/editor.hpp +++ b/main/editor.hpp @@ -9,7 +9,7 @@ namespace floormat { enum class editor_mode : unsigned char { - select, floors, walls, + select, floor, walls, }; struct tile_type final @@ -60,8 +60,8 @@ struct editor_state final [[nodiscard]] editor_mode mode() const { return _mode; } void set_mode(editor_mode mode) { _mode = mode; } - tile_type& floors() { return _floors; } - const tile_type& floors() const { return _floors; } + tile_type& floor() { return _floor; } + const tile_type& floor() const { return _floor; } editor_state(); @@ -72,7 +72,7 @@ struct editor_state final editor_state& operator=(editor_state&&) noexcept = default; private: - tile_type _floors{editor_mode::floors, "floor"}; + tile_type _floor{editor_mode::floor, "floor"}; editor_mode _mode = {}; bool _dirty = false; }; diff --git a/main/imgui-raii.hpp b/main/imgui-raii.hpp new file mode 100644 index 00000000..931b5189 --- /dev/null +++ b/main/imgui-raii.hpp @@ -0,0 +1,84 @@ +#pragma once + +#include <Corrade/Containers/StringView.h> +#include <Magnum/Math/Color.h> +#include <ImGui.h> + +namespace floormat::imgui { + +struct raii_wrapper final +{ + using F = void(*)(void); + raii_wrapper(F fn) : dtor{fn} {} + raii_wrapper() = default; + ~raii_wrapper() { if (dtor) dtor(); } + raii_wrapper(const raii_wrapper&) = delete; + raii_wrapper& operator=(const raii_wrapper&) = delete; + raii_wrapper& operator=(raii_wrapper&&) = delete; + raii_wrapper(raii_wrapper&& other) noexcept : dtor{other.dtor} { other.dtor = nullptr; } + inline operator bool() const noexcept { return dtor != nullptr; } + + F dtor = nullptr; +}; + +[[nodiscard]] static inline raii_wrapper begin_window(Containers::StringView name = {}, + ImGuiWindowFlags_ flags = ImGuiWindowFlags_None) +{ + if (name.isEmpty()) + name = "floormat editor"; + if (ImGui::Begin(name.data(), nullptr, flags)) + return {&ImGui::End}; + else + return {}; +} + +[[nodiscard]] static inline raii_wrapper begin_main_menu() +{ + if (ImGui::BeginMainMenuBar()) + return {&ImGui::EndMainMenuBar}; + else + return {}; +} +[[nodiscard]] static inline raii_wrapper begin_menu(Containers::StringView name, bool enabled = true) +{ + if (ImGui::BeginMenu(name.data(), enabled)) + return {&ImGui::EndMenu}; + else + return {}; +} + +[[nodiscard]] static inline raii_wrapper begin_list_box(Containers::StringView name, ImVec2 size = {}) +{ + if (ImGui::BeginListBox(name.data(), size)) + return {&ImGui::EndListBox}; + else + return {}; +} + +[[nodiscard]] static inline raii_wrapper tree_node(Containers::StringView name, ImGuiTreeNodeFlags_ flags = ImGuiTreeNodeFlags_None) +{ + if (ImGui::TreeNodeEx(name.data(), flags)) + return {&ImGui::TreePop}; + else + return {}; +} + +[[nodiscard]] static inline raii_wrapper push_style_var(ImGuiStyleVar_ var, Vector2 value) +{ + ImGui::PushStyleVar(var, {value[0], value[1]}); + return {[]{ ImGui::PopStyleVar(); }}; +} + +[[nodiscard]] static inline raii_wrapper push_style_var(ImGuiStyleVar_ var, float value) +{ + ImGui::PushStyleVar(var, value); + return {[]{ ImGui::PopStyleVar(); }}; +} + +[[nodiscard]] static inline raii_wrapper push_style_color(ImGuiCol_ var, const Color4& value) +{ + ImGui::PushStyleColor(var, {value[0], value[1], value[2], value[3]}); + return {[]{ ImGui::PopStyleColor(); }}; +} + +} // namespace floormat::imgui diff --git a/main/main.cpp b/main/main.cpp index a5acb0ca..e371713b 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -40,10 +40,9 @@ void app::drawEvent() { update(dt); } + _shader.set_tint({1, 1, 1, 1}); draw_chunk(_chunk); - draw_wireframe_quad(); - draw_wireframe_box(); - draw_menu(); + draw_cursor_tile(); display_menu(); swapBuffers(); @@ -58,30 +57,25 @@ void app::draw_chunk(chunk& c) _wall_mesh.draw(_shader, c); } -void app::draw_wireframe_quad() +void app::draw_wireframe_quad(local_coords pt) { constexpr float LINE_WIDTH = 1; constexpr auto X = TILE_SIZE[0], Y = TILE_SIZE[1]; - constexpr float N = TILE_MAX_DIM/2.f; - const Vector3 center {X*N, Y*N, 0}; + const Vector3 center {X*pt.x, Y*pt.y, 0}; _shader.set_tint({1, 0, 0, 1}); _wireframe_quad.draw(_shader, {center, {TILE_SIZE[0], TILE_SIZE[1]}, LINE_WIDTH}); - _shader.set_tint({1, 1, 1, 1}); } -void app::draw_wireframe_box() +void app::draw_wireframe_box(local_coords pt) { constexpr float LINE_WIDTH = 1.5; constexpr auto X = TILE_SIZE[0], Y = TILE_SIZE[1]; - constexpr float N = TILE_MAX_DIM/2.f; constexpr Vector3 size{TILE_SIZE[0], TILE_SIZE[1], TILE_SIZE[2]*1.5f}; - const Vector3 center1{X*(N+3), Y*(N+2), 0}, - center2{X*(N-2), Y*(N-4), 0}; + const Vector3 center1{X*pt.x, Y*pt.y, 0}; _shader.set_tint({0, 1, 0, 1}); _wireframe_box.draw(_shader, {center1, size, LINE_WIDTH}); - _wireframe_box.draw(_shader, {center2, size, LINE_WIDTH}); } } // namespace floormat diff --git a/main/menu.cpp b/main/menu.cpp index e5f291af..2874ad96 100644 --- a/main/menu.cpp +++ b/main/menu.cpp @@ -1,78 +1,11 @@ #include "app.hpp" +#include "imgui-raii.hpp" #include <Magnum/GL/Renderer.h> #include <Magnum/ImGuiIntegration/Integration.h> -#include <Magnum/Math/Color.h> namespace floormat { -struct raii_wrapper final -{ - using F = void(*)(void); - raii_wrapper(F fn) : dtor{fn} {} - raii_wrapper() = default; - ~raii_wrapper() { if (dtor) dtor(); } - raii_wrapper(const raii_wrapper&) = delete; - raii_wrapper& operator=(const raii_wrapper&) = delete; - raii_wrapper& operator=(raii_wrapper&&) = delete; - raii_wrapper(raii_wrapper&& other) noexcept : dtor{other.dtor} { other.dtor = nullptr; } - inline operator bool() const noexcept { return dtor != nullptr; } - - F dtor = nullptr; -}; - -constexpr inline const auto* imgui_name = "floormat editor"; - -[[nodiscard]] static raii_wrapper begin_window(int flags = 0) { - if (ImGui::Begin(imgui_name, nullptr, flags)) - return {&ImGui::End}; - else - return {}; -} - -[[nodiscard]] static raii_wrapper begin_main_menu() { - if (ImGui::BeginMainMenuBar()) - return {&ImGui::EndMainMenuBar}; - else - return {}; -} -[[nodiscard]] static raii_wrapper begin_menu(Containers::StringView name, bool enabled = true) { - if (ImGui::BeginMenu(name.data(), enabled)) - return {&ImGui::EndMenu}; - else - return {}; -} - -[[nodiscard]] static raii_wrapper begin_list_box(Containers::StringView name, ImVec2 size = {}) { - if (ImGui::BeginListBox(name.data(), size)) - return {&ImGui::EndListBox}; - else - return {}; -} - -[[nodiscard]] static raii_wrapper tree_node(Containers::StringView name, ImGuiTreeNodeFlags_ flags = {}) { - if (ImGui::TreeNodeEx(name.data(), flags)) - return {&ImGui::TreePop}; - else - return {}; -} - -[[nodiscard]] static raii_wrapper push_style_var(ImGuiStyleVar_ var, Vector2 value) -{ - ImGui::PushStyleVar(var, {value[0], value[1]}); - return {[]{ ImGui::PopStyleVar(); }}; -} - -[[nodiscard]] static raii_wrapper push_style_var(ImGuiStyleVar_ var, float value) -{ - ImGui::PushStyleVar(var, value); - return {[]{ ImGui::PopStyleVar(); }}; -} - -[[nodiscard]] static raii_wrapper push_style_color(ImGuiCol_ var, const Color4& value) -{ - ImGui::PushStyleColor(var, {value[0], value[1], value[2], value[3]}); - return {[]{ ImGui::PopStyleColor(); }}; -} +using namespace floormat::imgui; void app::setup_menu() { @@ -90,7 +23,7 @@ void app::display_menu() GL::Renderer::enable(GL::Renderer::Feature::ScissorTest); } -void app::draw_menu() +void app::do_menu() { _imgui.newFrame(); float main_menu_height = 0; @@ -109,13 +42,13 @@ void app::draw_menu() if (auto b = begin_menu("Mode")) { ImGui::MenuItem("Select", "F1", _editor.mode() == editor_mode::select); - ImGui::MenuItem("Floors", "F2", _editor.mode() == editor_mode::floors); + ImGui::MenuItem("Floor", "F2", _editor.mode() == editor_mode::floor); ImGui::MenuItem("Walls", "F3", _editor.mode() == editor_mode::walls); } main_menu_height = ImGui::GetContentRegionMax().y; } - draw_menu_(_editor.floors(), main_menu_height); + draw_menu_(_editor.floor(), main_menu_height); } void app::draw_menu_(tile_type& type, float main_menu_height) @@ -138,7 +71,8 @@ void app::draw_menu_(tile_type& type, float main_menu_height) ImGui::SetNextWindowPos({0, main_menu_height+style.WindowPadding.y}); ImGui::SetNextFrameWantCaptureKeyboard(false); ImGui::SetNextWindowSize({450, windowSize()[1] - main_menu_height - style.WindowPadding.y}); - if (auto b = begin_window(ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings)) + if (const auto flags = ImGuiWindowFlags_(ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings); + auto b = begin_window({}, flags)) { const float window_width = ImGui::GetWindowWidth() - 32; @@ -163,7 +97,8 @@ void app::draw_menu_(tile_type& type, float main_menu_height) ImGui::Text("%s", buf); }; const std::size_t N = v->num_tiles().product(); - if (auto b = tree_node(k.data(), ImGuiTreeNodeFlags_(ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Framed))) + if (const auto flags = ImGuiTreeNodeFlags_(ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Framed); + auto b = tree_node(k.data(), flags)) { click_event(); add_tile_count(); @@ -175,7 +110,7 @@ void app::draw_menu_(tile_type& type, float main_menu_height) { if (i > 0 && i % per_row == 0) ImGui::NewLine(); - sprintf(buf, "##item_%zu", i); + snprintf(buf, sizeof(buf), "##item_%zu", i); const auto uv = v->texcoords_for_id(i); ImGui::ImageButton(buf, (void*)&v->texture(), {TILE_SIZE[0]/2, TILE_SIZE[1]/2}, { uv[3][0], uv[3][1] }, { uv[0][0], uv[0][1] }); diff --git a/shaders/tile-shader.cpp b/shaders/tile-shader.cpp index b0177997..20b2230f 100644 --- a/shaders/tile-shader.cpp +++ b/shaders/tile-shader.cpp @@ -41,7 +41,7 @@ tile_shader& tile_shader::set_camera_offset(Vector2 camera_offset) CORRADE_INTERNAL_ASSERT(std::fabs(camera_offset[0]) <= std::scalbn(1.f, std::numeric_limits<float>::digits)); CORRADE_INTERNAL_ASSERT(std::fabs(camera_offset[1]) <= std::scalbn(1.f, std::numeric_limits<float>::digits)); if (camera_offset != camera_offset_) - setUniform(OffsetUniform, camera_offset_ = camera_offset); + setUniform(OffsetUniform, 2*(camera_offset_ = camera_offset)); return *this; } diff --git a/shaders/tile-shader.hpp b/shaders/tile-shader.hpp index 0e1e4442..c53dfff5 100644 --- a/shaders/tile-shader.hpp +++ b/shaders/tile-shader.hpp @@ -20,8 +20,6 @@ struct tile_shader : GL::AbstractShaderProgram Vector4 tint() const { return tint_; } tile_shader& set_tint(const Vector4& tint); - static constexpr Vector2 project(Vector3 pt); - private: Vector2 scale_, camera_offset_; Vector4 tint_; @@ -29,10 +27,4 @@ private: enum { ScaleUniform = 0, OffsetUniform = 1, TintUniform = 2, }; }; -constexpr Vector2 tile_shader::project(const Vector3 pt) -{ - float x = -pt[1], y = -pt[0], z = pt[2]; - return { x-y, (x+y+z*2)*.75f }; -} - } // namespace floormat |