summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--editor/app.hpp5
-rw-r--r--editor/draw.cpp2
-rw-r--r--editor/editor.cpp70
-rw-r--r--editor/editor.hpp2
-rw-r--r--editor/events.cpp1
-rw-r--r--editor/imgui-raii.cpp93
-rw-r--r--editor/imgui-raii.hpp108
-rw-r--r--editor/imgui-scenery.cpp12
-rw-r--r--editor/imgui-tiles.cpp80
-rw-r--r--editor/imgui.cpp158
-rw-r--r--editor/keys.hpp2
-rw-r--r--editor/update.cpp2
-rw-r--r--loader/atlas.cpp2
-rw-r--r--serialize/scenery.cpp3
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 = {};