diff options
-rw-r--r-- | editor/app.hpp | 5 | ||||
-rw-r--r-- | editor/draw.cpp | 2 | ||||
-rw-r--r-- | editor/editor.cpp | 70 | ||||
-rw-r--r-- | editor/editor.hpp | 2 | ||||
-rw-r--r-- | editor/events.cpp | 1 | ||||
-rw-r--r-- | editor/imgui-raii.cpp | 93 | ||||
-rw-r--r-- | editor/imgui-raii.hpp | 108 | ||||
-rw-r--r-- | editor/imgui-scenery.cpp | 12 | ||||
-rw-r--r-- | editor/imgui-tiles.cpp | 80 | ||||
-rw-r--r-- | editor/imgui.cpp | 158 | ||||
-rw-r--r-- | editor/keys.hpp | 2 | ||||
-rw-r--r-- | editor/update.cpp | 2 | ||||
-rw-r--r-- | loader/atlas.cpp | 2 | ||||
-rw-r--r-- | serialize/scenery.cpp | 3 |
14 files changed, 311 insertions, 229 deletions
diff --git a/editor/app.hpp b/editor/app.hpp index 381b4c83..c81f5f22 100644 --- a/editor/app.hpp +++ b/editor/app.hpp @@ -92,8 +92,9 @@ private: void do_quicksave(); void do_quickload(); - void draw_editor_pane(tile_editor& type, float main_menu_height); - void draw_editor_pane_atlas(tile_editor& ed, StringView name, const std::shared_ptr<tile_atlas>& atlas); + void draw_editor_pane(float main_menu_height); + void draw_editor_tile_pane_atlas(tile_editor& ed, StringView name, const std::shared_ptr<tile_atlas>& atlas); + void draw_editor_scenery_pane(scenery_editor& ed); void draw_cursor(); void init_imgui(Vector2i size); void draw_ui(); diff --git a/editor/draw.cpp b/editor/draw.cpp index 93631820..75444379 100644 --- a/editor/draw.cpp +++ b/editor/draw.cpp @@ -35,7 +35,7 @@ void app::draw_cursor() void app::draw() { - if (_editor.current_tile_editor()) + if (_editor.current_tile_editor() || _editor.current_scenery_editor()) draw_cursor(); draw_ui(); render_menu(); diff --git a/editor/editor.cpp b/editor/editor.cpp index 1ac4a887..3400f5af 100644 --- a/editor/editor.cpp +++ b/editor/editor.cpp @@ -11,11 +11,6 @@ namespace floormat { -tile_editor* editor::current_tile_editor() noexcept -{ - return const_cast<tile_editor*>(static_cast<const editor&>(*this).current_tile_editor()); -} - void editor::on_release() { _last_pos = NullOpt; @@ -50,32 +45,37 @@ global_coords editor::apply_snap(global_coords pos, global_coords last, snap_mod void editor::on_mouse_move(world& world, global_coords& pos, int mods) { - if (auto* mode = current_tile_editor(); mode && _last_pos && _last_pos->btn != button::none) + if (auto* mode = current_tile_editor()) { - auto& last = *_last_pos; - const Vector2i offset = pos - last.coord; - const snap_mode snap = get_snap_value(last.snap, mods); - const global_coords draw_coord = apply_snap(last.draw_coord + offset, last.draw_coord, snap); - if (draw_coord != last.draw_coord) + if (_last_pos && _last_pos->btn != button::none) { - const auto draw_offset = draw_coord - last.draw_coord; - if (!!draw_offset[0] ^ !!draw_offset[1] && std::abs(draw_offset.sum()) > 1) + auto& last = *_last_pos; + const Vector2i offset = pos - last.coord; + const snap_mode snap = get_snap_value(last.snap, mods); + const global_coords draw_coord = apply_snap(last.draw_coord + offset, last.draw_coord, snap); + if (draw_coord != last.draw_coord) { - const auto [minx, maxx] = std::minmax(draw_coord.x, last.draw_coord.x); - const auto [miny, maxy] = std::minmax(draw_coord.y, last.draw_coord.y); - if (draw_offset[0]) - for (std::uint32_t i = minx; i <= maxx; i++) - on_click_(world, { i, draw_coord.y }, last.btn); + const auto draw_offset = draw_coord - last.draw_coord; + if (!!draw_offset[0] ^ !!draw_offset[1] && std::abs(draw_offset.sum()) > 1) + { + const auto [minx, maxx] = std::minmax(draw_coord.x, last.draw_coord.x); + const auto [miny, maxy] = std::minmax(draw_coord.y, last.draw_coord.y); + if (draw_offset[0]) + for (std::uint32_t i = minx; i <= maxx; i++) + on_click_(world, { i, draw_coord.y }, last.btn); + else + for (std::uint32_t j = miny; j <= maxy; j++) + on_click_(world, { draw_coord.x, j }, last.btn); + } else - for (std::uint32_t j = miny; j <= maxy; j++) - on_click_(world, { draw_coord.x, j }, last.btn); + on_click_(world, draw_coord, last.btn); + _last_pos = { InPlaceInit, pos, draw_coord, snap, last.btn }; } - else - on_click_(world, draw_coord, last.btn); - _last_pos = { InPlaceInit, pos, draw_coord, snap, last.btn }; + pos = draw_coord; } - pos = draw_coord; } + else + on_release(); } void editor::on_click_(world& world, global_coords pos, button b) @@ -102,9 +102,7 @@ void editor::on_click(world& world, global_coords pos, int mods, button b) } } -editor::editor() -{ -} +editor::editor() = default; void editor::set_mode(editor_mode mode) { @@ -125,4 +123,22 @@ const tile_editor* editor::current_tile_editor() const noexcept } } +const scenery_editor* editor::current_scenery_editor() const noexcept +{ + if (_mode == editor_mode::scenery) + return &_scenery; + else + return nullptr; +} + +tile_editor* editor::current_tile_editor() noexcept +{ + return const_cast<tile_editor*>(static_cast<const editor&>(*this).current_tile_editor()); +} + +scenery_editor* editor::current_scenery_editor() noexcept +{ + return const_cast<scenery_editor*>(static_cast<const editor&>(*this).current_scenery_editor()); +} + } // namespace floormat diff --git a/editor/editor.hpp b/editor/editor.hpp index e0c4f848..1bbc3a89 100644 --- a/editor/editor.hpp +++ b/editor/editor.hpp @@ -27,6 +27,8 @@ struct editor final tile_editor* current_tile_editor() noexcept; const tile_editor* current_tile_editor() const noexcept; + scenery_editor* current_scenery_editor() noexcept; + const scenery_editor* current_scenery_editor() const noexcept; enum class button : unsigned char { none, place, remove, }; diff --git a/editor/events.cpp b/editor/events.cpp index fc55cca2..83abc96d 100644 --- a/editor/events.cpp +++ b/editor/events.cpp @@ -125,6 +125,7 @@ auto app::resolve_keybinding(int k_, int mods_) const -> std::tuple<key, int> case SDLK_1: return { key_mode_none, mods }; case SDLK_2: return { key_mode_floor, mods }; case SDLK_3: return { key_mode_walls, mods }; + case SDLK_4: return { key_mode_scenery, mods }; case SDLK_F5: return { key_quicksave, mods }; case SDLK_F9: return { key_quickload, mods }; case SDLK_q | CTRL: return { key_quit, mods }; diff --git a/editor/imgui-raii.cpp b/editor/imgui-raii.cpp new file mode 100644 index 00000000..7c885114 --- /dev/null +++ b/editor/imgui-raii.cpp @@ -0,0 +1,93 @@ +#include "imgui-raii.hpp" +#include <Corrade/Containers/StringView.h> +#include <Magnum/Magnum.h> +#include <Magnum/Math/Color.h> + +namespace floormat::imgui { + +font_saver::~font_saver() +{ + auto& ctx = *ImGui::GetCurrentContext(); + ctx.FontSize = font_size; + ctx.FontBaseSize = font_base_size; +} + +font_saver::font_saver(ImGuiContext& ctx, float size) : + font_size{ctx.FontSize}, font_base_size{ctx.FontBaseSize} +{ + ctx.FontSize = size; + ctx.FontBaseSize = size; +} + +font_saver::font_saver(float size) : font_saver{*ImGui::GetCurrentContext(), size} {} +style_saver::style_saver() : style{ImGui::GetStyle()} {} +style_saver::~style_saver() { ImGui::GetStyle() = style; } + +void text(const char* str, std::size_t len, ImGuiTextFlags_ flags) { ImGui::TextEx(str, str + len, flags); } + +raii_wrapper::raii_wrapper(raii_wrapper::F fn) : dtor{fn} {} +raii_wrapper::~raii_wrapper() { if (dtor) dtor(); } +raii_wrapper::raii_wrapper(raii_wrapper&& other) noexcept : dtor{other.dtor} { other.dtor = nullptr; } +raii_wrapper::operator bool() const noexcept { return dtor != nullptr; } + +raii_wrapper push_style_color(ImGuiCol_ var, const Color4& value) +{ + ImGui::PushStyleColor(var, {value[0], value[1], value[2], value[3]}); + return {[]{ ImGui::PopStyleColor(); }}; +} + +raii_wrapper push_style_var(ImGuiStyleVar_ var, float value) +{ + ImGui::PushStyleVar(var, value); + return {[]{ ImGui::PopStyleVar(); }}; +} + +raii_wrapper push_style_var(ImGuiStyleVar_ var, Vector2 value) +{ + ImGui::PushStyleVar(var, {value[0], value[1]}); + return {[]{ ImGui::PopStyleVar(); }}; +} + +raii_wrapper tree_node(Containers::StringView name, ImGuiTreeNodeFlags_ flags) +{ + if (ImGui::TreeNodeEx(name.data(), flags)) + return {&ImGui::TreePop}; + else + return {}; +} + +raii_wrapper begin_list_box(Containers::StringView name, ImVec2 size) +{ + if (ImGui::BeginListBox(name.data(), size)) + return {&ImGui::EndListBox}; + else + return {}; +} + +raii_wrapper begin_menu(Containers::StringView name, bool enabled) +{ + if (ImGui::BeginMenu(name.data(), enabled)) + return {&ImGui::EndMenu}; + else + return {}; +} + +raii_wrapper begin_main_menu() +{ + if (ImGui::BeginMainMenuBar()) + return {&ImGui::EndMainMenuBar}; + else + return {}; +} + +raii_wrapper begin_window(Containers::StringView name, ImGuiWindowFlags_ flags) +{ + if (name.isEmpty()) + name = "floormat editor"; + if (ImGui::Begin(name.data(), nullptr, flags)) + return {&ImGui::End}; + else + return {}; +} + +} // namespace floormat::imgui diff --git a/editor/imgui-raii.hpp b/editor/imgui-raii.hpp index a3059d1b..ebb99886 100644 --- a/editor/imgui-raii.hpp +++ b/editor/imgui-raii.hpp @@ -1,7 +1,7 @@ #pragma once - +#include "compat/prelude.hpp" #include <Corrade/Containers/StringView.h> -#include <Magnum/Math/Color.h> +#include <Magnum/Magnum.h> #include <imgui.h> #include <imgui_internal.h> @@ -10,100 +10,46 @@ namespace floormat::imgui { struct raii_wrapper final { using F = void(*)(void); - raii_wrapper(F fn) : dtor{fn} {} + raii_wrapper(F fn); raii_wrapper() = default; - ~raii_wrapper() { if (dtor) dtor(); } + ~raii_wrapper(); 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; } + raii_wrapper(raii_wrapper&& other) noexcept; + operator bool() const noexcept; +private: F dtor = nullptr; }; -[[nodiscard]] [[maybe_unused]] 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]] [[maybe_unused]] static inline raii_wrapper begin_main_menu() -{ - if (ImGui::BeginMainMenuBar()) - return {&ImGui::EndMainMenuBar}; - else - return {}; -} -[[nodiscard]] [[maybe_unused]] static inline raii_wrapper begin_menu(Containers::StringView name, bool enabled = true) -{ - if (ImGui::BeginMenu(name.data(), enabled)) - return {&ImGui::EndMenu}; - else - return {}; -} - -[[nodiscard]] [[maybe_unused]] static inline raii_wrapper begin_list_box(Containers::StringView name, ImVec2 size = {}) -{ - if (ImGui::BeginListBox(name.data(), size)) - return {&ImGui::EndListBox}; - else - return {}; -} - -[[nodiscard]] [[maybe_unused]] 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]] [[maybe_unused]] static inline raii_wrapper push_style_var(ImGuiStyleVar_ var, Vector2 value) -{ - ImGui::PushStyleVar(var, {value[0], value[1]}); - return {[]{ ImGui::PopStyleVar(); }}; -} - -[[nodiscard]] [[maybe_unused]] static inline raii_wrapper push_style_var(ImGuiStyleVar_ var, float value) -{ - ImGui::PushStyleVar(var, value); - return {[]{ ImGui::PopStyleVar(); }}; -} - -[[nodiscard]] [[maybe_unused]] 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(); }}; -} - -[[maybe_unused]] static inline void text(const char* str, std::size_t len, ImGuiTextFlags_ flags = ImGuiTextFlags_NoWidthForLargeClippedText) -{ - ImGui::TextEx(str, str + len, flags); -} +[[nodiscard]] raii_wrapper begin_window(StringView name = {}, ImGuiWindowFlags_ flags = ImGuiWindowFlags_None); +[[nodiscard]] raii_wrapper begin_main_menu(); +[[nodiscard]] raii_wrapper begin_menu(StringView name, bool enabled = true); +[[nodiscard]] raii_wrapper begin_list_box(StringView name, ImVec2 size = {}); +[[nodiscard]] raii_wrapper tree_node(StringView name, ImGuiTreeNodeFlags_ flags = ImGuiTreeNodeFlags_None); +[[nodiscard]] raii_wrapper push_style_var(ImGuiStyleVar_ var, Vector2 value); +[[nodiscard]] raii_wrapper push_style_var(ImGuiStyleVar_ var, float value); +[[nodiscard]] raii_wrapper push_style_color(ImGuiCol_ var, const Color4& value); +void text(const char* str, std::size_t len, ImGuiTextFlags_ flags = ImGuiTextFlags_NoWidthForLargeClippedText); template<std::size_t N> -[[maybe_unused]] static inline void text(const char (&buf)[N], ImGuiTextFlags_ flags = ImGuiTextFlags_NoWidthForLargeClippedText) +void text(const char (&buf)[N], ImGuiTextFlags_ flags = ImGuiTextFlags_NoWidthForLargeClippedText) { - static_assert(N > 0); ImGui::TextEx(buf, buf + N - 1, flags); } struct style_saver final { - style_saver() : style{ImGui::GetStyle()} {} - ~style_saver() { ImGui::GetStyle() = style; } + style_saver(); + ~style_saver(); private: ImGuiStyle style; }; struct font_saver final { - font_saver(float size) : font_saver{*ImGui::GetCurrentContext(), size} {} + font_saver(float size); ~font_saver(); private: font_saver(ImGuiContext& ctx, float size); @@ -111,18 +57,4 @@ private: float font_size, font_base_size; }; -font_saver::~font_saver() -{ - auto& ctx = *ImGui::GetCurrentContext(); - ctx.FontSize = font_size; - ctx.FontBaseSize = font_base_size; -} - -font_saver::font_saver(ImGuiContext& ctx, float size) : - font_size{ctx.FontSize}, font_base_size{ctx.FontBaseSize} -{ - ctx.FontSize = size; - ctx.FontBaseSize = size; -} - } // namespace floormat::imgui diff --git a/editor/imgui-scenery.cpp b/editor/imgui-scenery.cpp new file mode 100644 index 00000000..f98edf8f --- /dev/null +++ b/editor/imgui-scenery.cpp @@ -0,0 +1,12 @@ +#include "app.hpp" +#include "scenery-editor.hpp" +#include "imgui-raii.hpp" + +namespace floormat { + +void app::draw_editor_scenery_pane(scenery_editor& ed) +{ + +} + +} // namespace floormat diff --git a/editor/imgui-tiles.cpp b/editor/imgui-tiles.cpp new file mode 100644 index 00000000..312c6d12 --- /dev/null +++ b/editor/imgui-tiles.cpp @@ -0,0 +1,80 @@ +#include "app.hpp" +#include "src/tile-atlas.hpp" +#include "floormat/main.hpp" +#include "imgui-raii.hpp" +#include "compat/format.hpp" +#include <Magnum/Math/Color.h> + +namespace floormat { + +using namespace floormat::imgui; + +void app::draw_editor_tile_pane_atlas(tile_editor& ed, StringView name, const std::shared_ptr<tile_atlas>& atlas) +{ + const auto dpi = M->dpi_scale(); + constexpr Color4 color_perm_selected{1, 1, 1, .7f}, + color_selected{1, 0.843f, 0, .8f}, + color_hover{0, .8f, 1, .7f}; + const float window_width = ImGui::GetWindowWidth() - 32 * dpi; + char buf[128]; + const auto& style = ImGui::GetStyle(); + const auto N = atlas->num_tiles(); + + const auto click_event = [&] { + if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) + ed.select_tile_permutation(atlas); + else if (ImGui::IsItemClicked(ImGuiMouseButton_Middle)) + ed.clear_selection(); + }; + const auto do_caption = [&] { + click_event(); + if (ed.is_atlas_selected(atlas)) + { + ImGui::SameLine(); + text(" (selected)"); + } + const auto len = snformat(buf, "{:d}"_cf, N); + ImGui::SameLine(window_width - ImGui::CalcTextSize(buf).x - style.FramePadding.x - 4*dpi); + text(buf, len); + }; + if (const auto flags = ImGuiTreeNodeFlags_(ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Framed); + auto b = tree_node(name.data(), flags)) + { + do_caption(); + [[maybe_unused]] const raii_wrapper vars[] = { + push_style_var(ImGuiStyleVar_FramePadding, {2*dpi, 2*dpi}), + push_style_color(ImGuiCol_ButtonHovered, color_hover), + }; + const bool perm_selected = ed.is_permutation_selected(atlas); + constexpr std::size_t per_row = 8; + for (std::size_t i = 0; i < N; i++) + { + const bool selected = ed.is_tile_selected(atlas, i); + if (i > 0 && i % per_row == 0) + ImGui::NewLine(); + + [[maybe_unused]] const raii_wrapper vars[] = { + selected ? push_style_color(ImGuiCol_Button, color_selected) : raii_wrapper{}, + selected ? push_style_color(ImGuiCol_ButtonHovered, color_selected) : raii_wrapper{}, + perm_selected ? push_style_color(ImGuiCol_Button, color_perm_selected) : raii_wrapper{}, + perm_selected ? push_style_color(ImGuiCol_ButtonHovered, color_perm_selected) : raii_wrapper{}, + }; + + 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, size_2.y * dpi), + { uv[3][0], uv[3][1] }, { uv[0][0], uv[0][1] }); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) + ed.select_tile(atlas, i); + else + click_event(); + ImGui::SameLine(); + } + ImGui::NewLine(); + } + else + do_caption(); +} + +} // namespace floormat diff --git a/editor/imgui.cpp b/editor/imgui.cpp index 53d39de8..e5d9bd5a 100644 --- a/editor/imgui.cpp +++ b/editor/imgui.cpp @@ -1,10 +1,8 @@ #include "app.hpp" #include "floormat/main.hpp" -#include "src/tile-atlas.hpp" #include "compat/format.hpp" - -#include <Magnum/GL/Renderer.h> #include "imgui-raii.hpp" +#include <Magnum/Math/Color.h> namespace floormat { @@ -49,10 +47,11 @@ float app::draw_main_menu() if (auto b = begin_menu("Mode")) { const bool can_rotate = _editor.current_tile_editor() ? _editor.current_tile_editor()->can_rotate() : false; - bool b_none = false, b_floor = false, b_walls = false, b_rotate = false; - ImGui::MenuItem("Select", "1", &b_none); - ImGui::MenuItem("Floor", "2", &b_floor); - ImGui::MenuItem("Walls", "3", &b_walls); + bool b_none = false, b_floor = false, b_walls = false, b_rotate = false, b_scenery = false; + ImGui::MenuItem("Select", "1", &b_none); + ImGui::MenuItem("Floor", "2", &b_floor); + ImGui::MenuItem("Walls", "3", &b_walls); + ImGui::MenuItem("Scenery", "4", &b_scenery); ImGui::Separator(); ImGui::MenuItem("Rotate", "R", &b_rotate, can_rotate); if (b_none) @@ -61,6 +60,8 @@ float app::draw_main_menu() do_key(key_mode_floor); else if (b_walls) do_key(key_mode_walls); + else if (b_scenery) + do_key(key_mode_scenery); if (b_rotate) do_key(key_rotate_tile); } @@ -84,84 +85,52 @@ void app::draw_ui() _imgui.newFrame(); const float main_menu_height = draw_main_menu(); - if (auto* ed = _editor.current_tile_editor(); ed != nullptr) - draw_editor_pane(*ed, main_menu_height); + if (_editor.mode() != editor_mode::none) + draw_editor_pane(main_menu_height); [[maybe_unused]] auto font = font_saver{ctx.FontSize*dpi}; draw_fps(); draw_tile_under_cursor(); ImGui::EndFrame(); } -void app::draw_editor_pane_atlas(tile_editor& ed, StringView name, const std::shared_ptr<tile_atlas>& atlas) +void app::draw_fps() { const auto dpi = M->dpi_scale(); - constexpr Color4 color_perm_selected{1, 1, 1, .7f}, - color_selected{1, 0.843f, 0, .8f}, - color_hover{0, .8f, 1, .7f}; - const float window_width = ImGui::GetWindowWidth() - 32 * dpi; - char buf[128]; - const auto& style = ImGui::GetStyle(); - const auto N = atlas->num_tiles(); + const auto frame_time = M->smoothed_dt(); + char buf[16]; + const double hz = frame_time > 1e-6f ? (int)std::round(10./(double)frame_time + .05) * .1 : 9999; + snformat(buf, "{:.1f} FPS"_cf, hz); + const ImVec2 size = ImGui::CalcTextSize(buf); + ImDrawList& draw = *ImGui::GetForegroundDrawList(); + draw.AddText(nullptr, ImGui::GetCurrentContext()->FontSize, + {M->window_size()[0] - size.x - 3.5f*dpi, 3*dpi}, ImGui::ColorConvertFloat4ToU32({0, 1, 0, 1}), buf); +} - const auto click_event = [&] { - if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) - ed.select_tile_permutation(atlas); - else if (ImGui::IsItemClicked(ImGuiMouseButton_Middle)) - ed.clear_selection(); - }; - const auto do_caption = [&] { - click_event(); - if (ed.is_atlas_selected(atlas)) - { - ImGui::SameLine(); - text(" (selected)"); - } - const auto len = snformat(buf, "{:d}"_cf, N); - ImGui::SameLine(window_width - ImGui::CalcTextSize(buf).x - style.FramePadding.x - 4*dpi); - text(buf, len); - }; - if (const auto flags = ImGuiTreeNodeFlags_(ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Framed); - auto b = tree_node(name.data(), flags)) - { - do_caption(); - [[maybe_unused]] const raii_wrapper vars[] = { - push_style_var(ImGuiStyleVar_FramePadding, {2*dpi, 2*dpi}), - push_style_color(ImGuiCol_ButtonHovered, color_hover), - }; - const bool perm_selected = ed.is_permutation_selected(atlas); - constexpr std::size_t per_row = 8; - for (std::size_t i = 0; i < N; i++) - { - const bool selected = ed.is_tile_selected(atlas, i); - if (i > 0 && i % per_row == 0) - ImGui::NewLine(); - - [[maybe_unused]] const raii_wrapper vars[] = { - selected ? push_style_color(ImGuiCol_Button, color_selected) : raii_wrapper{}, - selected ? push_style_color(ImGuiCol_ButtonHovered, color_selected) : raii_wrapper{}, - perm_selected ? push_style_color(ImGuiCol_Button, color_perm_selected) : raii_wrapper{}, - perm_selected ? push_style_color(ImGuiCol_ButtonHovered, color_perm_selected) : raii_wrapper{}, - }; - - 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, size_2.y * dpi), - { uv[3][0], uv[3][1] }, { uv[0][0], uv[0][1] }); - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) - ed.select_tile(atlas, i); - else - click_event(); - ImGui::SameLine(); - } - ImGui::NewLine(); - } - else - do_caption(); +void app::draw_tile_under_cursor() +{ + if (!cursor.tile) + return; + + const auto dpi = M->dpi_scale(); + char buf[64]; + const auto coord = *cursor.tile; + const auto chunk = coord.chunk(); + const auto local = coord.local(); + snformat(buf, "{}:{} - {}:{}"_cf, chunk.x, chunk.y, local.x, local.y); + const auto size = ImGui::CalcTextSize(buf); + const auto window_size = M->window_size(); + + ImDrawList& draw = *ImGui::GetForegroundDrawList(); + draw.AddText(nullptr, ImGui::GetCurrentContext()->FontSize, + {window_size[0]*.5f - size.x/2, 3*dpi}, (unsigned)-1, buf); } -void app::draw_editor_pane(tile_editor& ed, float main_menu_height) +void app::draw_editor_pane(float main_menu_height) { + auto* ed = _editor.current_tile_editor(); + auto* sc = _editor.current_scenery_editor(); + fm_assert(!ed || !sc); + const auto window_size = M->window_size(); const auto dpi = M->dpi_scale(); @@ -188,43 +157,16 @@ void app::draw_editor_pane(tile_editor& ed, float main_menu_height) auto b = begin_window({}, flags)) { ImGui::SetWindowFontScale(dpi); - if (auto b = begin_list_box("##atlases", {-FLT_MIN, -1})) - for (const auto& [k, v] : ed) - draw_editor_pane_atlas(ed, k, v); + if (auto b = begin_list_box("##atlases", {-FLT_MIN, -1})) + { + if (ed) + for (const auto& [k, v] : *ed) + draw_editor_tile_pane_atlas(*ed, k, v); + else if (sc) + draw_editor_scenery_pane(*sc); + } } } } -void app::draw_fps() -{ - const auto dpi = M->dpi_scale(); - const auto frame_time = M->smoothed_dt(); - char buf[16]; - const double hz = frame_time > 1e-6f ? (int)std::round(10./(double)frame_time + .05) * .1 : 9999; - snformat(buf, "{:.1f} FPS"_cf, hz); - const ImVec2 size = ImGui::CalcTextSize(buf); - ImDrawList& draw = *ImGui::GetForegroundDrawList(); - draw.AddText(nullptr, ImGui::GetCurrentContext()->FontSize, - {M->window_size()[0] - size.x - 3.5f*dpi, 3*dpi}, ImGui::ColorConvertFloat4ToU32({0, 1, 0, 1}), buf); -} - -void app::draw_tile_under_cursor() -{ - if (!cursor.tile) - return; - - const auto dpi = M->dpi_scale(); - char buf[64]; - const auto coord = *cursor.tile; - const auto chunk = coord.chunk(); - const auto local = coord.local(); - snformat(buf, "{}:{} - {}:{}"_cf, chunk.x, chunk.y, local.x, local.y); - const auto size = ImGui::CalcTextSize(buf); - const auto window_size = M->window_size(); - - ImDrawList& draw = *ImGui::GetForegroundDrawList(); - draw.AddText(nullptr, ImGui::GetCurrentContext()->FontSize, - {window_size[0]*.5f - size.x/2, 3*dpi}, (unsigned)-1, buf); -} - } // namespace floormat diff --git a/editor/keys.hpp b/editor/keys.hpp index 12b96f27..b74d5557 100644 --- a/editor/keys.hpp +++ b/editor/keys.hpp @@ -15,7 +15,7 @@ enum key : unsigned { key_noop, key_camera_up, key_camera_left, key_camera_right, key_camera_down, key_camera_reset, key_rotate_tile, - key_mode_none, key_mode_floor, key_mode_walls, + key_mode_none, key_mode_floor, key_mode_walls, key_mode_scenery, key_quit, key_quicksave, key_quickload, key_COUNT, key_MIN = key_noop, key_NO_REPEAT = key_rotate_tile, key_GLOBAL = key_quit, diff --git a/editor/update.cpp b/editor/update.cpp index f2ac1bc6..eba39798 100644 --- a/editor/update.cpp +++ b/editor/update.cpp @@ -90,6 +90,8 @@ void app::do_key(key k, int mods) return _editor.set_mode(editor_mode::floor); case key_mode_walls: return _editor.set_mode(editor_mode::walls); + case key_mode_scenery: + return _editor.set_mode(editor_mode::scenery); case key_quicksave: return do_quicksave(); case key_quickload: diff --git a/loader/atlas.cpp b/loader/atlas.cpp index 1e498e1a..f68ca820 100644 --- a/loader/atlas.cpp +++ b/loader/atlas.cpp @@ -63,7 +63,7 @@ std::shared_ptr<anim_atlas> loader_impl::anim_atlas(StringView name) fm_assert(anim_info.nframes == 1 || anim_info.fps > 0); const auto size = tex.pixels().size(); const auto width = size[1], height = size[0]; - fm_assert(Vector2uz{anim_info.pixel_size} == Vector2uz(width, height)); + fm_assert(Vector2uz{anim_info.pixel_size} == Vector2uz{width, height}); auto atlas = std::make_shared<struct anim_atlas>(path, tex, std::move(anim_info)); return anim_atlas_map[atlas->name()] = atlas; diff --git a/serialize/scenery.cpp b/serialize/scenery.cpp index 984b11bc..64fc7d7b 100644 --- a/serialize/scenery.cpp +++ b/serialize/scenery.cpp @@ -6,6 +6,7 @@ #include "serialize/json-helper.hpp" #include <array> #include <Corrade/Containers/StringStlView.h> +#include <Corrade/Utility/Path.h> #include <nlohmann/json.hpp> namespace { @@ -105,7 +106,7 @@ void adl_serializer<scenery_proto>::from_json(const json& j, scenery_proto& val) StringView atlas_name = j["atlas-name"]; fm_assert(!atlas_name.isEmpty()); - auto atlas = loader.anim_atlas(atlas_name); + auto atlas = loader.anim_atlas(Path::join("scenery", atlas_name)); auto& f = val.frame; f = {}; |