summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-11-06 18:14:02 +0100
committerStanislaw Halik <sthalik@misaki.pl>2022-11-06 18:14:02 +0100
commitedc3ad8c86cb1a042134f82c738029004b116d86 (patch)
tree1535f1450a859a4489f0e62dcc36e56015abe78c
parentacf6f498818572528003ffc62f02fdcd4bf71a9a (diff)
editor stuff
-rw-r--r--editor/draw.cpp2
-rw-r--r--editor/editor-enums.hpp19
-rw-r--r--editor/editor.cpp282
-rw-r--r--editor/editor.hpp84
-rw-r--r--editor/imgui.cpp6
-rw-r--r--editor/tile-editor.cpp232
-rw-r--r--editor/tile-editor.hpp57
-rw-r--r--editor/update.cpp3
8 files changed, 371 insertions, 314 deletions
diff --git a/editor/draw.cpp b/editor/draw.cpp
index ee11edd3..ad634815 100644
--- a/editor/draw.cpp
+++ b/editor/draw.cpp
@@ -23,7 +23,7 @@ void app::draw_cursor()
mesh.draw(shader, {center, size, LINE_WIDTH});
};
- if (const auto* ed = _editor.current(); ed && ed->mode() == editor_mode::walls)
+ if (const auto* ed = _editor.current_tile_editor(); ed && ed->mode() == editor_mode::walls)
switch (ed->rotation())
{
case editor_wall_rotation::N: draw(_wireframe_wall_n, TILE_SIZE); break;
diff --git a/editor/editor-enums.hpp b/editor/editor-enums.hpp
new file mode 100644
index 00000000..604956cb
--- /dev/null
+++ b/editor/editor-enums.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+namespace floormat {
+
+enum class editor_mode : unsigned char {
+ none, floor, walls, scenery,
+};
+
+enum class editor_wall_rotation : std::uint8_t {
+ N, W,
+};
+
+enum class editor_snap_mode : std::uint8_t {
+ none = 0,
+ horizontal = 1 << 0,
+ vertical = 1 << 1,
+};
+
+} // namespace floormat
diff --git a/editor/editor.cpp b/editor/editor.cpp
index 499dd441..99948aca 100644
--- a/editor/editor.cpp
+++ b/editor/editor.cpp
@@ -1,11 +1,6 @@
#include "editor.hpp"
-#include "serialize/json-helper.hpp"
-#include "serialize/tile-atlas.hpp"
#include "src/loader.hpp"
-#include "random.hpp"
-#include "compat/assert.hpp"
-#include "compat/unreachable.hpp"
-#include "src/tile-defs.hpp"
+#include "tile-atlas.hpp"
#include "src/world.hpp"
#include "keys.hpp"
@@ -17,249 +12,9 @@
namespace floormat {
-tile_editor::tile_editor(editor_mode mode, StringView name) : _name{ name}, _mode{ mode}
+tile_editor* editor::current_tile_editor() noexcept
{
- load_atlases();
-}
-
-void tile_editor::load_atlases()
-{
- static const std::filesystem::path image_path{IMAGE_PATH, std::filesystem::path::generic_format};
- using atlas_array = std::vector<std::shared_ptr<tile_atlas>>;
- const String filename = _name + ".json";
- const auto filename_view = std::string_view{filename.cbegin(), filename.cend()};
- for (auto& atlas : json_helper::from_json<atlas_array>(image_path/filename_view))
- {
- StringView name = atlas->name();
- if (auto x = name.findLast('.'); x)
- name = name.prefix(x.data());
- auto& [_, vec] = _permutation;
- vec.reserve((std::size_t)atlas->num_tiles());
- _atlases[name] = std::move(atlas);
- }
-}
-
-std::shared_ptr<tile_atlas> tile_editor::maybe_atlas(StringView str)
-{
- auto it = std::find_if(_atlases.begin(), _atlases.end(), [&](const auto& tuple) -> bool {
- const auto& [x, _] = tuple;
- return StringView{x} == str;
- });
- if (it == _atlases.end())
- return nullptr;
- else
- return it->second;
-}
-
-std::shared_ptr<tile_atlas> tile_editor::atlas(StringView str)
-{
- if (auto ptr = maybe_atlas(str); ptr)
- return ptr;
- else
- fm_abort("no such atlas: %s", str.cbegin());
-}
-
-void tile_editor::clear_selection()
-{
- _selected_tile = {};
- _permutation = {};
- _selection_mode = sel_none;
-}
-
-void tile_editor::select_tile(const std::shared_ptr<tile_atlas>& atlas, std::size_t variant)
-{
- fm_assert(atlas);
- clear_selection();
- _selection_mode = sel_tile;
- _selected_tile = { atlas, variant_t(variant % atlas->num_tiles()) };
-}
-
-void tile_editor::select_tile_permutation(const std::shared_ptr<tile_atlas>& atlas)
-{
- fm_assert(atlas);
- clear_selection();
- _selection_mode = sel_perm;
- _permutation = { atlas, {} };
-}
-
-bool tile_editor::is_tile_selected(const std::shared_ptr<const tile_atlas>& atlas, std::size_t variant) const
-{
- return atlas && _selection_mode == sel_tile && _selected_tile &&
- atlas == _selected_tile.atlas && variant == _selected_tile.variant;
-}
-
-bool tile_editor::is_permutation_selected(const std::shared_ptr<const tile_atlas>& atlas) const
-{
- const auto& [perm, _] = _permutation;
- return atlas && _selection_mode == sel_perm && perm == atlas;
-}
-
-bool tile_editor::is_atlas_selected(const std::shared_ptr<const tile_atlas>& atlas) const
-{
- switch (_selection_mode)
- {
- default:
- case sel_none:
- return false;
- case sel_perm:
- return is_permutation_selected(atlas);
- case sel_tile:
- return atlas && _selected_tile && atlas == _selected_tile.atlas;
- }
-}
-
-template<std::random_access_iterator T>
-void fisher_yates(T begin, T end)
-{
- const auto N = std::distance(begin, end);
- for (auto i = N-1; i >= 1; i--)
- {
- const auto j = random(i+1);
- using std::swap;
- swap(begin[i], begin[j]);
- }
-}
-
-tile_image_proto tile_editor::get_selected_perm()
-{
- auto& [atlas, vec] = _permutation;
- const auto N = (variant_t)atlas->num_tiles();
- if (N == 0)
- return {};
- if (vec.empty())
- {
- for (variant_t i = 0; i < N; i++)
- vec.push_back(i);
- fisher_yates(vec.begin(), vec.end());
- }
- const auto idx = vec.back();
- vec.pop_back();
- return {atlas, idx};
-}
-
-tile_image_proto tile_editor::get_selected()
-{
- switch (_selection_mode)
- {
- case sel_none:
- return {};
- case sel_tile:
- return _selected_tile;
- case sel_perm:
- return get_selected_perm();
- default:
- fm_warn_once("invalid editor mode '%u'", (unsigned)_selection_mode);
- break;
- }
-}
-
-void tile_editor::place_tile(world& world, global_coords pos, const tile_image_proto& img)
-{
- auto [c, t] = world[pos];
- switch (_mode)
- {
- case editor_mode::none:
- break;
- case editor_mode::floor:
- t.ground() = img;
- break;
- case editor_mode::walls:
- switch (_rotation)
- {
- case editor_wall_rotation::N:
- t.wall_north() = img;
- break;
- case editor_wall_rotation::W:
- t.wall_west() = img;
- break;
- }
- break;
- }
-}
-
-void tile_editor::toggle_rotation()
-{
- if (_rotation == editor::rotation_W)
- _rotation = editor::rotation_N;
- else
- _rotation = editor::rotation_W;
-}
-
-void tile_editor::set_rotation(editor_wall_rotation r)
-{
- switch (r)
- {
- default:
- fm_warn_once("invalid rotation '0x%hhx", r);
- return;
- case editor::rotation_W:
- case editor::rotation_N:
- _rotation = r;
- break;
- }
-}
-
-auto tile_editor::check_snap(int mods) const -> snap_mode
-{
- const bool ctrl = mods & kmod_ctrl, shift = mods & kmod_shift;
-
- if (!(ctrl | shift))
- return snap_mode::none;
-
- switch (_mode)
- {
- default:
- case editor_mode::none:
- return snap_mode::none;
- case editor_mode::walls:
- switch (_rotation)
- {
- case editor_wall_rotation::N:
- return snap_mode::horizontal;
- case editor_wall_rotation::W:
- return snap_mode::vertical;
- default: return snap_mode::none;
- }
- case editor_mode::floor:
- if (shift)
- return snap_mode::horizontal;
- if (ctrl)
- return snap_mode::vertical;
- return snap_mode::none;
- }
-}
-
-bool tile_editor::can_rotate() const
-{
- return _mode == editor_mode::walls;
-}
-
-editor::editor()
-{
-}
-
-void editor::set_mode(editor_mode mode)
-{
- _mode = mode;
- on_release();
-}
-
-const tile_editor* editor::current() const noexcept
-{
- switch (_mode)
- {
- case editor_mode::floor:
- return &_floor;
- case editor_mode::walls:
- return &_wall; // todo
- default:
- return nullptr;
- }
-}
-
-tile_editor* editor::current() noexcept
-{
- return const_cast<tile_editor*>(static_cast<const editor&>(*this).current());
+ return const_cast<tile_editor*>(static_cast<const editor&>(*this).current_tile_editor());
}
void editor::on_release()
@@ -270,7 +25,7 @@ void editor::on_release()
auto editor::get_snap_value(snap_mode snap, int mods) const -> snap_mode
{
- if (const auto* mode = current(); mode != nullptr)
+ if (const auto* mode = current_tile_editor(); mode != nullptr)
return mode->check_snap(mods);
else if (snap != snap_mode::none)
return snap;
@@ -296,7 +51,7 @@ 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(); mode && _last_pos && _last_pos->btn != button::none)
+ if (auto* mode = current_tile_editor(); mode && _last_pos && _last_pos->btn != button::none)
{
auto& last = *_last_pos;
const Vector2i offset = pos - last.coord;
@@ -326,7 +81,7 @@ void editor::on_mouse_move(world& world, global_coords& pos, int mods)
void editor::on_click_(world& world, global_coords pos, button b)
{
- if (auto* mode = current(); mode != nullptr)
+ if (auto* mode = current_tile_editor(); mode != nullptr)
if (auto opt = mode->get_selected(); opt)
{
switch (b)
@@ -341,11 +96,34 @@ void editor::on_click_(world& world, global_coords pos, button b)
void editor::on_click(world& world, global_coords pos, int mods, button b)
{
- if (auto* mode = current(); mode != nullptr)
+ if (auto* mode = current_tile_editor(); mode != nullptr)
{
_last_pos = { pos, pos, mode->check_snap(mods), b };
on_click_(world, pos, b);
}
}
+editor::editor()
+{
+}
+
+void editor::set_mode(editor_mode mode)
+{
+ _mode = mode;
+ on_release();
+}
+
+const tile_editor* editor::current_tile_editor() const noexcept
+{
+ switch (_mode)
+ {
+ case editor_mode::floor:
+ return &_floor;
+ case editor_mode::walls:
+ return &_wall; // todo
+ default:
+ return nullptr;
+ }
+}
+
} // namespace floormat
diff --git a/editor/editor.hpp b/editor/editor.hpp
index 09277590..94cb7709 100644
--- a/editor/editor.hpp
+++ b/editor/editor.hpp
@@ -1,77 +1,45 @@
#pragma once
#include "compat/defs.hpp"
-#include "tile-atlas.hpp"
+#include "compat/integer-types.hpp"
#include "global-coords.hpp"
-#include "tile.hpp"
+#include "tile-image.hpp"
+#include "scenery.hpp"
+#include "editor-enums.hpp"
+#include "tile-editor.hpp"
-#include <cstdint>
-#include <tuple>
#include <optional>
-#include <vector>
#include <map>
#include <memory>
-#include <Corrade/Containers/String.h>
+#include <Corrade/Containers/StringView.h>
namespace floormat {
-enum class editor_mode : unsigned char {
- none, floor, walls,
-};
-
-enum class editor_wall_rotation : std::uint8_t {
- N, W,
-};
-
struct world;
+struct anim_atlas;
+struct tile_atlas;
-struct tile_editor final
+struct scenery_editor final
{
-private:
- enum selection_mode : std::uint8_t {
- sel_none, sel_tile, sel_perm,
+ struct pair final {
+ std::shared_ptr<anim_atlas> atlas;
+ scenery s;
};
- String _name;
- std::map<std::string, std::shared_ptr<tile_atlas>> _atlases;
- tile_image_proto _selected_tile;
- std::tuple<std::shared_ptr<tile_atlas>, std::vector<decltype(tile_image_proto::variant)>> _permutation;
- selection_mode _selection_mode = sel_none;
- editor_mode _mode;
- editor_wall_rotation _rotation = editor_wall_rotation::N;
+ scenery_editor() noexcept;
- void load_atlases();
- tile_image_proto get_selected_perm();
+ void set_rotation(rotation r);
+ void rotation() const;
+ void next_rotation();
+ void prev_rotation();
-public:
- enum class snap_mode : std::uint8_t {
- none = 0,
- horizontal = 1 << 0,
- vertical = 1 << 1,
- };
+ void select_tile(const std::shared_ptr<anim_atlas>& atlas, enum rotation r, std::uint16_t frame);
+ void clear_selection();
- tile_editor(editor_mode mode, StringView name);
- std::shared_ptr<tile_atlas> maybe_atlas(StringView str);
- std::shared_ptr<tile_atlas> atlas(StringView str);
- auto cbegin() const noexcept { return _atlases.cbegin(); }
- auto cend() const noexcept { return _atlases.cend(); }
- auto begin() const noexcept { return _atlases.cbegin(); }
- auto end() const noexcept { return _atlases.cend(); }
- StringView name() const noexcept { return _name; }
- editor_mode mode() const noexcept { return _mode; }
- editor_wall_rotation rotation() const noexcept { return _rotation; }
+private:
+ void load_atlases();
- void clear_selection();
- void select_tile(const std::shared_ptr<tile_atlas>& atlas, std::size_t variant);
- void select_tile_permutation(const std::shared_ptr<tile_atlas>& atlas);
- bool is_tile_selected(const std::shared_ptr<const tile_atlas>& atlas, std::size_t variant) const;
- bool is_permutation_selected(const std::shared_ptr<const tile_atlas>& atlas) const;
- bool is_atlas_selected(const std::shared_ptr<const tile_atlas>& atlas) const;
- tile_image_proto get_selected();
- void place_tile(world& world, global_coords pos, const tile_image_proto& img);
- void toggle_rotation();
- void set_rotation(editor_wall_rotation r);
- snap_mode check_snap(int mods) const;
- bool can_rotate() const;
+ std::map<StringView, std::shared_ptr<anim_atlas>> _atlases;
+ pair _selected_frame;
};
struct editor final
@@ -81,8 +49,8 @@ struct editor final
[[nodiscard]] editor_mode mode() const noexcept { return _mode; }
void set_mode(editor_mode mode);
- tile_editor* current() noexcept;
- const tile_editor* current() const noexcept;
+ tile_editor* current_tile_editor() noexcept;
+ const tile_editor* current_tile_editor() const noexcept;
enum class button : std::uint8_t { none, place, remove, };
@@ -98,7 +66,7 @@ struct editor final
static constexpr inline auto rotation_N = editor_wall_rotation::N;
static constexpr inline auto rotation_W = editor_wall_rotation::W;
- using snap_mode = tile_editor::snap_mode;
+ using snap_mode = editor_snap_mode;
private:
snap_mode get_snap_value(snap_mode snap, int mods) const;
diff --git a/editor/imgui.cpp b/editor/imgui.cpp
index ae974b06..5df5df64 100644
--- a/editor/imgui.cpp
+++ b/editor/imgui.cpp
@@ -1,5 +1,7 @@
#include "app.hpp"
#include "floormat/main.hpp"
+#include "src/tile-atlas.hpp"
+
#include <Magnum/GL/Renderer.h>
#include "imgui-raii.hpp"
@@ -52,7 +54,7 @@ float app::draw_main_menu()
}
if (auto b = begin_menu("Mode"))
{
- const bool can_rotate = _editor.current() ? _editor.current()->can_rotate() : false;
+ 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);
@@ -81,7 +83,7 @@ void app::draw_ui()
ImGui::StyleColorsDark(&ImGui::GetStyle());
const float main_menu_height = draw_main_menu();
- if (auto* ed = _editor.current(); ed != nullptr)
+ if (auto* ed = _editor.current_tile_editor(); ed != nullptr)
draw_editor_pane(*ed, main_menu_height);
draw_fps();
draw_cursor();
diff --git a/editor/tile-editor.cpp b/editor/tile-editor.cpp
new file mode 100644
index 00000000..03a1ee47
--- /dev/null
+++ b/editor/tile-editor.cpp
@@ -0,0 +1,232 @@
+#include "tile-editor.hpp"
+#include "tile-atlas.hpp"
+#include "world.hpp"
+#include "keys.hpp"
+#include "loader.hpp"
+#include "random.hpp"
+#include "serialize/json-helper.hpp"
+#include "serialize/tile-atlas.hpp"
+
+namespace floormat {
+
+tile_editor::tile_editor(editor_mode mode, StringView name) : _name{ name}, _mode{ mode}
+{
+ load_atlases();
+}
+
+void tile_editor::load_atlases()
+{
+ static const std::filesystem::path image_path{FM_IMAGE_PATH, std::filesystem::path::generic_format};
+ using atlas_array = std::vector<std::shared_ptr<tile_atlas>>;
+ const String filename = _name + ".json";
+ const auto filename_view = std::string_view{filename.cbegin(), filename.cend()};
+ for (auto& atlas : json_helper::from_json<atlas_array>(image_path/filename_view))
+ {
+ StringView name = atlas->name();
+ if (auto x = name.findLast('.'); x)
+ name = name.prefix(x.data());
+ auto& [_, vec] = _permutation;
+ vec.reserve((std::size_t)atlas->num_tiles());
+ _atlases[name] = std::move(atlas);
+ }
+}
+
+std::shared_ptr<tile_atlas> tile_editor::maybe_atlas(StringView str)
+{
+ auto it = std::find_if(_atlases.begin(), _atlases.end(), [&](const auto& tuple) -> bool {
+ const auto& [x, _] = tuple;
+ return StringView{x} == str;
+ });
+ if (it == _atlases.end())
+ return nullptr;
+ else
+ return it->second;
+}
+
+std::shared_ptr<tile_atlas> tile_editor::atlas(StringView str)
+{
+ if (auto ptr = maybe_atlas(str); ptr)
+ return ptr;
+ else
+ fm_abort("no such atlas: %s", str.cbegin());
+}
+
+void tile_editor::clear_selection()
+{
+ _selected_tile = {};
+ _permutation = {};
+ _selection_mode = sel_none;
+}
+
+void tile_editor::select_tile(const std::shared_ptr<tile_atlas>& atlas, std::size_t variant)
+{
+ fm_assert(atlas);
+ clear_selection();
+ _selection_mode = sel_tile;
+ _selected_tile = { atlas, variant_t(variant % atlas->num_tiles()) };
+}
+
+void tile_editor::select_tile_permutation(const std::shared_ptr<tile_atlas>& atlas)
+{
+ fm_assert(atlas);
+ clear_selection();
+ _selection_mode = sel_perm;
+ _permutation = { atlas, {} };
+}
+
+bool tile_editor::is_tile_selected(const std::shared_ptr<const tile_atlas>& atlas, std::size_t variant) const
+{
+ return atlas && _selection_mode == sel_tile && _selected_tile &&
+ atlas == _selected_tile.atlas && variant == _selected_tile.variant;
+}
+
+bool tile_editor::is_permutation_selected(const std::shared_ptr<const tile_atlas>& atlas) const
+{
+ const auto& [perm, _] = _permutation;
+ return atlas && _selection_mode == sel_perm && perm == atlas;
+}
+
+bool tile_editor::is_atlas_selected(const std::shared_ptr<const tile_atlas>& atlas) const
+{
+ switch (_selection_mode)
+ {
+ default:
+ case sel_none:
+ return false;
+ case sel_perm:
+ return is_permutation_selected(atlas);
+ case sel_tile:
+ return atlas && _selected_tile && atlas == _selected_tile.atlas;
+ }
+}
+
+template<std::random_access_iterator T>
+void fisher_yates(T begin, T end)
+{
+ const auto N = std::distance(begin, end);
+ for (auto i = N-1; i >= 1; i--)
+ {
+ const auto j = random(i+1);
+ using std::swap;
+ swap(begin[i], begin[j]);
+ }
+}
+
+tile_image_proto tile_editor::get_selected_perm()
+{
+ auto& [atlas, vec] = _permutation;
+ const auto N = (variant_t)atlas->num_tiles();
+ if (N == 0)
+ return {};
+ if (vec.empty())
+ {
+ for (variant_t i = 0; i < N; i++)
+ vec.push_back(i);
+ fisher_yates(vec.begin(), vec.end());
+ }
+ const auto idx = vec.back();
+ vec.pop_back();
+ return {atlas, idx};
+}
+
+tile_image_proto tile_editor::get_selected()
+{
+ switch (_selection_mode)
+ {
+ case sel_none:
+ return {};
+ case sel_tile:
+ return _selected_tile;
+ case sel_perm:
+ return get_selected_perm();
+ default:
+ fm_warn_once("invalid editor mode '%u'", (unsigned)_selection_mode);
+ break;
+ }
+}
+
+void tile_editor::place_tile(world& world, global_coords pos, const tile_image_proto& img)
+{
+ auto [c, t] = world[pos];
+ switch (_mode)
+ {
+ case editor_mode::none:
+ break;
+ case editor_mode::floor:
+ t.ground() = img;
+ break;
+ case editor_mode::walls:
+ switch (_rotation)
+ {
+ case editor_wall_rotation::N:
+ t.wall_north() = img;
+ break;
+ case editor_wall_rotation::W:
+ t.wall_west() = img;
+ break;
+ }
+ break;
+ default:
+ fm_warn_once("wrong editor mode '%d' for place_tile()", (int)_mode);
+ break;
+ }
+}
+
+void tile_editor::toggle_rotation()
+{
+ if (_rotation == editor_wall_rotation::W)
+ _rotation = editor_wall_rotation::N;
+ else
+ _rotation = editor_wall_rotation::W;
+}
+
+void tile_editor::set_rotation(editor_wall_rotation r)
+{
+ switch (r)
+ {
+ default:
+ fm_warn_once("invalid rotation '0x%hhx", r);
+ return;
+ case editor_wall_rotation::W:
+ case editor_wall_rotation::N:
+ _rotation = r;
+ break;
+ }
+}
+
+auto tile_editor::check_snap(int mods) const -> editor_snap_mode
+{
+ const bool ctrl = mods & kmod_ctrl, shift = mods & kmod_shift;
+
+ if (!(ctrl | shift))
+ return editor_snap_mode::none;
+
+ switch (_mode)
+ {
+ default:
+ case editor_mode::none:
+ return editor_snap_mode::none;
+ case editor_mode::walls:
+ switch (_rotation)
+ {
+ case editor_wall_rotation::N:
+ return editor_snap_mode::horizontal;
+ case editor_wall_rotation::W:
+ return editor_snap_mode::vertical;
+ default: return editor_snap_mode::none;
+ }
+ case editor_mode::floor:
+ if (shift)
+ return editor_snap_mode::horizontal;
+ if (ctrl)
+ return editor_snap_mode::vertical;
+ return editor_snap_mode::none;
+ }
+}
+
+bool tile_editor::can_rotate() const
+{
+ return _mode == editor_mode::walls;
+}
+
+} // namespace floormat
diff --git a/editor/tile-editor.hpp b/editor/tile-editor.hpp
new file mode 100644
index 00000000..4089ca62
--- /dev/null
+++ b/editor/tile-editor.hpp
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "editor-enums.hpp"
+#include "tile-image.hpp"
+#include "global-coords.hpp"
+#include <tuple>
+#include <memory>
+
+namespace floormat {
+
+struct world;
+
+struct tile_editor final
+{
+private:
+ enum selection_mode : std::uint8_t {
+ sel_none, sel_tile, sel_perm,
+ };
+
+ String _name;
+ std::map<std::string, std::shared_ptr<tile_atlas>> _atlases;
+ tile_image_proto _selected_tile;
+ std::tuple<std::shared_ptr<tile_atlas>, std::vector<decltype(tile_image_proto::variant)>> _permutation;
+ selection_mode _selection_mode = sel_none;
+ editor_mode _mode;
+ editor_wall_rotation _rotation = editor_wall_rotation::N;
+
+ void load_atlases();
+ tile_image_proto get_selected_perm();
+
+public:
+ tile_editor(editor_mode mode, StringView name);
+ std::shared_ptr<tile_atlas> maybe_atlas(StringView str);
+ std::shared_ptr<tile_atlas> atlas(StringView str);
+ auto cbegin() const noexcept { return _atlases.cbegin(); }
+ auto cend() const noexcept { return _atlases.cend(); }
+ auto begin() const noexcept { return _atlases.cbegin(); }
+ auto end() const noexcept { return _atlases.cend(); }
+ StringView name() const noexcept { return _name; }
+ editor_mode mode() const noexcept { return _mode; }
+ editor_wall_rotation rotation() const noexcept { return _rotation; }
+
+ void clear_selection();
+ void select_tile(const std::shared_ptr<tile_atlas>& atlas, std::size_t variant);
+ void select_tile_permutation(const std::shared_ptr<tile_atlas>& atlas);
+ bool is_tile_selected(const std::shared_ptr<const tile_atlas>& atlas, std::size_t variant) const;
+ bool is_permutation_selected(const std::shared_ptr<const tile_atlas>& atlas) const;
+ bool is_atlas_selected(const std::shared_ptr<const tile_atlas>& atlas) const;
+ tile_image_proto get_selected();
+ void place_tile(world& world, global_coords pos, const tile_image_proto& img);
+ void toggle_rotation();
+ void set_rotation(editor_wall_rotation r);
+ editor_snap_mode check_snap(int mods) const;
+ bool can_rotate() const;
+};
+
+} // namespace floormat
diff --git a/editor/update.cpp b/editor/update.cpp
index adca9492..569d81dc 100644
--- a/editor/update.cpp
+++ b/editor/update.cpp
@@ -1,5 +1,6 @@
#include "app.hpp"
#include "src/chunk.hpp"
+#include "src/tile-atlas.hpp"
#include "floormat/events.hpp"
#include "floormat/main.hpp"
@@ -69,7 +70,7 @@ void app::do_key(key k, int mods)
fm_warn("unhandled key: '%zu'", std::size_t(k));
return;
case key_rotate_tile:
- if (auto* ed = _editor.current(); ed)
+ if (auto* ed = _editor.current_tile_editor(); ed)
ed->toggle_rotation();
return;
case key_mode_none: