diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-01-11 13:54:53 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-01-11 14:11:47 +0100 |
commit | 7867213a01fcabb1f05b1836c2ca59dc3bb2132f (patch) | |
tree | 44af754bed0278c8bf3435df6278bd291c3043e5 /editor/ground-editor.cpp | |
parent | 74cf06b6b217eff32a547cf73f051f27e6b80919 (diff) |
rename tile_atlas -> ground_atlas
Diffstat (limited to 'editor/ground-editor.cpp')
-rw-r--r-- | editor/ground-editor.cpp | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/editor/ground-editor.cpp b/editor/ground-editor.cpp new file mode 100644 index 00000000..0f67853e --- /dev/null +++ b/editor/ground-editor.cpp @@ -0,0 +1,166 @@ +#include "ground-editor.hpp" +#include "src/ground-atlas.hpp" +#include "src/world.hpp" +#include "src/random.hpp" +#include "keys.hpp" +#include "loader/loader.hpp" +#include "compat/exception.hpp" +#include <Corrade/Containers/PairStl.h> +#include <Corrade/Utility/Path.h> + +namespace floormat { + +ground_editor::ground_editor() +{ + load_atlases(); +} + +void ground_editor::load_atlases() +{ + for (const auto& atlas : loader.ground_atlases("floor.json"_s)) + { + auto& [_, vec] = _permutation; + vec.reserve(atlas->num_tiles()); + _atlases[atlas->name()] = atlas; + } +} + +std::shared_ptr<ground_atlas> ground_editor::maybe_atlas(StringView str) +{ + if (auto it = _atlases.find(str); it != _atlases.end()) + return it->second; + else + return nullptr; +} + +std::shared_ptr<ground_atlas> ground_editor::atlas(StringView str) +{ + if (auto ptr = maybe_atlas(str)) + return ptr; + else + fm_throw("no such atlas: {}"_cf, str); +} + +StringView ground_editor::name() const noexcept { return "floor"_s; } + +void ground_editor::clear_selection() +{ + _selected_tile = {}; + _permutation = {}; + _selection_mode = sel_none; +} + +void ground_editor::select_tile(const std::shared_ptr<ground_atlas>& atlas, size_t variant) +{ + fm_assert(atlas); + clear_selection(); + _selection_mode = sel_tile; + _selected_tile = { atlas, variant_t(variant % atlas->num_tiles()) }; +} + +void ground_editor::select_tile_permutation(const std::shared_ptr<ground_atlas>& atlas) +{ + fm_assert(atlas); + clear_selection(); + _selection_mode = sel_perm; + _permutation = { atlas, {} }; +} + +bool ground_editor::is_tile_selected(const std::shared_ptr<const ground_atlas>& atlas, size_t variant) const +{ + return atlas && _selection_mode == sel_tile && _selected_tile && + atlas == _selected_tile.atlas && variant == _selected_tile.variant; +} + +bool ground_editor::is_permutation_selected(const std::shared_ptr<const ground_atlas>& atlas) const +{ + const auto& [perm, _] = _permutation; + return atlas && _selection_mode == sel_perm && perm == atlas; +} + +bool ground_editor::is_atlas_selected(const std::shared_ptr<const ground_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; + } +} + +bool ground_editor::is_anything_selected() const +{ + return _selection_mode != sel_none; +} + +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 ground_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 ground_editor::get_selected() +{ + switch (_selection_mode) + { + default: + fm_warn_once("invalid editor mode '%u'", (unsigned)_selection_mode); + [[fallthrough]]; + case sel_none: + return {}; + case sel_tile: + return _selected_tile; + case sel_perm: + return get_selected_perm(); + } +} + +void ground_editor::place_tile(world& world, global_coords pos, const tile_image_proto& img) +{ + auto [c, t] = world[pos]; + c.mark_ground_modified(); + t.ground() = img; +} + +auto ground_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; + + if (shift) + return editor_snap_mode::horizontal; + if (ctrl) + return editor_snap_mode::vertical; + return editor_snap_mode::none; +} + +} // namespace floormat |