diff options
-rw-r--r-- | editor/imgui.cpp | 8 | ||||
-rw-r--r-- | editor/inspect-types.cpp | 2 | ||||
-rw-r--r-- | editor/scenery-editor.cpp | 23 | ||||
-rw-r--r-- | editor/update.cpp | 7 | ||||
-rw-r--r-- | src/character.cpp | 6 | ||||
-rw-r--r-- | src/character.hpp | 2 | ||||
-rw-r--r-- | src/chunk.cpp | 7 | ||||
-rw-r--r-- | src/chunk.hpp | 5 | ||||
-rw-r--r-- | src/entity.cpp | 57 | ||||
-rw-r--r-- | src/entity.hpp | 15 | ||||
-rw-r--r-- | src/scenery.cpp | 11 | ||||
-rw-r--r-- | src/scenery.hpp | 6 |
12 files changed, 83 insertions, 66 deletions
diff --git a/editor/imgui.cpp b/editor/imgui.cpp index 05396414..652b33a5 100644 --- a/editor/imgui.cpp +++ b/editor/imgui.cpp @@ -153,12 +153,12 @@ void app::do_popup_menu() if (auto b1 = begin_popup(SCENERY_POPUP_NAME)) { - auto iter = sc->iter(); - if (ImGui::MenuItem("Activate", nullptr, false, sc->can_activate(iter))) - sc->activate(iter); + const auto i = sc->index(); + if (ImGui::MenuItem("Activate", nullptr, false, sc->can_activate(i))) + sc->activate(i); if (auto next_rot = sc->atlas->next_rotation_from(sc->r); ImGui::MenuItem("Rotate", nullptr, false, next_rot != sc->r)) - sc->rotate(iter, next_rot); + sc->rotate(i, next_rot); ImGui::Separator(); diff --git a/editor/inspect-types.cpp b/editor/inspect-types.cpp index ead95c08..75450085 100644 --- a/editor/inspect-types.cpp +++ b/editor/inspect-types.cpp @@ -32,7 +32,7 @@ struct entity_accessors<scenery> { }, entity::type<rotation>::field{"rotation"_s, [](const scenery& x) { return x.r; }, - [](scenery& x, rotation r) { x.rotate(x.iter(), r); }, + [](scenery& x, rotation r) { x.rotate(x.index(), r); }, }, entity::type<std::uint16_t>::field{"frame"_s, [](const scenery& x) { return x.frame; }, diff --git a/editor/scenery-editor.cpp b/editor/scenery-editor.cpp index 73705056..1165219d 100644 --- a/editor/scenery-editor.cpp +++ b/editor/scenery-editor.cpp @@ -79,8 +79,27 @@ bool scenery_editor::is_anything_selected() const void scenery_editor::place_tile(world& w, global_coords pos, const scenery_& s) { auto [c, t] = w[pos]; - // todo check collision at pos - auto sc = w.make_entity<scenery>(pos, s.proto); + if (!s) + { + // don't regen colliders + const auto px = Vector2(pos.local()) * TILE_SIZE2; + const auto es = c.entities(); + for (auto i = es.size()-1; i != (std::size_t)-1; i--) + { + const auto& e = *es[i]; + if (e.type != entity_type::scenery) + continue; + auto center = Vector2(e.coord.local())*TILE_SIZE2 + Vector2(e.offset) + Vector2(e.bbox_offset), + min = center - Vector2(e.bbox_size/2), max = min + Vector2(e.bbox_size); + if (px >= min && px <= max) + c.remove_entity(i); + } + } + else + { + // todo check collision at pos + w.make_entity<scenery>(pos, s.proto); + } c.mark_scenery_modified(); } diff --git a/editor/update.cpp b/editor/update.cpp index 6107cfa6..470e8b9f 100644 --- a/editor/update.cpp +++ b/editor/update.cpp @@ -69,7 +69,7 @@ void app::do_mouse_up_down(std::uint8_t button, bool is_down, int mods) if (button == mouse_button_left) { if (auto* cl = find_clickable_scenery(*cursor.pixel)) - return (void)cl->e->activate(cl->e->iter()); + return (void)cl->e->activate(cl->e->index()); } // TODO it should open on mouseup if still on the same item as on mousedown else if (button == mouse_button_right) @@ -110,7 +110,7 @@ void app::do_rotate(bool backward) auto r = backward ? e.atlas->prev_rotation_from(e.r) : e.atlas->next_rotation_from(e.r); if (r != e.r) { - e.rotate(e.iter(), r); + e.rotate(e.index(), r); e.chunk().mark_scenery_modified(); } } @@ -190,9 +190,8 @@ void app::update_world(float dt) const auto size = es.size(); for (auto i = size-1; i != (std::size_t)-1; i--) { - auto iter = es.cbegin() + std::ptrdiff_t(i); auto& e = *es[i]; - c.with_scenery_update(e, [&] { return e.update(iter, dt); }); + c.with_scenery_update(e, [&] { return e.update(i, dt); }); } } } diff --git a/src/character.cpp b/src/character.cpp index 7094b54d..e99ce183 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -83,7 +83,7 @@ void character::set_keys(bool L, bool R, bool U, bool D) b_D = D; } -bool character::update(It it, float dt) +bool character::update(std::size_t i, float dt) { auto [lr, ud, rot] = arrows_to_dir(b_L, b_R, b_U, b_D); @@ -102,7 +102,7 @@ bool character::update(It it, float dt) r = rot; c->ensure_passability(); - for (int i = 0; i < nframes; i++) + for (int k = 0; k < nframes; k++) { constexpr auto frac = Vector2(32767); constexpr auto inv_frac = Vector2(1.f/32767); @@ -110,7 +110,7 @@ bool character::update(It it, float dt) offset_frac = Vector2s(Vector2(std::fmod(offset_[0], 1.f), std::fmod(offset_[1], 1.f)) * frac); auto off_i = Vector2i(offset_); if (can_move_to(off_i)) - entity::move(it, off_i); + i = move(i, off_i); ++frame %= atlas->info().nframes; } //Debug{} << "pos" << Vector2i(pos.local()); diff --git a/src/character.hpp b/src/character.hpp index 4c02a764..b5bba8fb 100644 --- a/src/character.hpp +++ b/src/character.hpp @@ -13,7 +13,7 @@ struct character final : entity { ~character() override; void set_keys(bool L, bool R, bool U, bool D); - bool update(It it, float dt) override; + bool update(std::size_t i, float dt) override; private: int allocate_frame_time(float dt); diff --git a/src/chunk.cpp b/src/chunk.cpp index f4ba079d..351848d0 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -137,15 +137,16 @@ void chunk::add_entity(const std::shared_ptr<entity>& e) _entities.insert(it, e); } -void chunk::remove_entity(entity_const_iterator it) +void chunk::remove_entity(std::size_t i) { - const auto& e = *it; + fm_debug_assert(i < _entities.size()); + const auto& e = _entities[i]; if (!e->is_dynamic()) mark_scenery_modified(false); if (bbox bb; _bbox_for_scenery(*e, bb)) _remove_bbox(bb); - _entities.erase(it); + _entities.erase(_entities.cbegin() + std::ptrdiff_t(i)); } const std::vector<std::shared_ptr<entity>>& chunk::entities() const diff --git a/src/chunk.hpp b/src/chunk.hpp index 497c0181..5b0e6d74 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -108,15 +108,12 @@ struct chunk final requires requires(F fun) { fun(); } void with_scenery_update(entity& e, F&& fun); - using entity_vector = std::vector<std::shared_ptr<entity>>; - using entity_const_iterator = typename entity_vector::const_iterator; - [[nodiscard]] bool can_place_entity(const entity_proto& proto, local_coords pos); void add_entity(const std::shared_ptr<entity>& e); void add_entity_unsorted(const std::shared_ptr<entity>& e); void sort_entities(); - void remove_entity(entity_const_iterator it); + void remove_entity(std::size_t i); const std::vector<std::shared_ptr<entity>>& entities() const; private: diff --git a/src/entity.cpp b/src/entity.cpp index 1599debd..586f9ecc 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -33,14 +33,10 @@ entity::~entity() noexcept fm_debug_assert(id); if (c->_teardown || c->_world->_teardown) [[unlikely]] return; - auto& w = *c->_world; if (chunk::bbox bb; c->_bbox_for_scenery(*this, bb)) c->_remove_bbox(bb); - auto& es = c->_entities; - auto it = std::find_if(es.cbegin(), es.cend(), [id = id](const auto& x) { return x->id == id; }); - fm_debug_assert(it != es.cend()); - es.erase(it); - w.do_kill_entity(id); + c->_world->do_kill_entity(id); + const_cast<std::uint64_t&>(id) = 0; } Vector2b entity::ordinal_offset_for_type(entity_type type, Vector2b offset) @@ -87,7 +83,7 @@ struct chunk& entity::chunk() const return *c; } -auto entity::iter() const -> It +std::size_t entity::index() const { auto& c = chunk(); auto& es = c._entities; @@ -95,7 +91,7 @@ auto entity::iter() const -> It fm_assert(it != es.cend()); it = std::find_if(it, es.cend(), [id = id](const auto& x) { return x->id == id; }); fm_assert(it != es.cend()); - return it; + return (std::size_t)std::distance(es.cbegin(), it); } bool entity::operator==(const entity_proto& o) const @@ -106,7 +102,7 @@ bool entity::operator==(const entity_proto& o) const bbox_size == o.bbox_size && delta == o.delta; } -void entity::rotate(It, rotation new_r) +void entity::rotate(std::size_t, rotation new_r) { auto& w = *c->_world; w[coord.chunk()].with_scenery_update(*this, [&]() { @@ -159,44 +155,45 @@ bool entity::can_move_to(Vector2i delta) return ret; } -void entity::move(It it, Vector2i delta) +std::size_t entity::move(std::size_t i, Vector2i delta) { - auto e_ = *it; + auto& es = c->_entities; + fm_debug_assert(i < es.size()); + auto e_ = es[i]; const auto& e = *e_; - auto& c = *e.c; - auto& w = *c._world; + auto& w = *c->_world; const auto coord = e.coord; const auto offset = e.offset; - auto& es = c._entities; const auto [coord_, offset_] = normalize_coords(coord, offset, delta); if (coord_ == coord && offset_ == offset) - return; + return i; if (!e.is_dynamic()) - c.mark_scenery_modified(false); + c->mark_scenery_modified(false); chunk::bbox bb0, bb1; - bool b0 = c._bbox_for_scenery(e, bb0), - b1 = c._bbox_for_scenery(e, coord_.local(), offset_, bb1); + bool b0 = c->_bbox_for_scenery(e, bb0), + b1 = c->_bbox_for_scenery(e, coord_.local(), offset_, bb1); const auto ord = e.ordinal(coord_.local(), offset_, e.type); if (coord_.chunk() == coord.chunk()) { - c._replace_bbox(bb0, bb1, b0, b1); + c->_replace_bbox(bb0, bb1, b0, b1); auto it_ = std::lower_bound(es.cbegin(), es.cend(), e_, [=](const auto& a, const auto&) { return a->ordinal() < ord; }); e_->coord = coord_; e_->offset = offset_; - auto pos0 = std::distance(es.cbegin(), it), pos1 = std::distance(es.cbegin(), it_); - if (pos1 > pos0) + auto pos1 = std::distance(es.cbegin(), it_); + if ((std::size_t)pos1 > i) pos1--; //for (auto i = 0_uz; const auto& x : es) fm_debug("%zu %s %f", i++, x->atlas->name().data(), x->ordinal()); - if (pos1 != pos0) + if ((std::size_t)pos1 != i) { //fm_debug("insert (%hd;%hd|%hhd;%hhd) %td -> %zu | %f", coord_.chunk().x, coord_.chunk().y, coord_.local().x, coord_.local().y, pos1, es.size(), e.ordinal()); - es.erase(it); + es.erase(es.cbegin() + (std::ptrdiff_t)i); es.insert(es.cbegin() + pos1, std::move(e_)); } + return std::size_t(pos1); } else { @@ -205,13 +202,15 @@ void entity::move(It it, Vector2i delta) if (!e.is_dynamic()) c2.mark_scenery_modified(false); c2._add_bbox(bb1); - c.remove_entity(it); + c->remove_entity(i); auto& es = c2._entities; - auto it_ = std::lower_bound(es.cbegin(), es.cend(), e_, [=](const auto& a, const auto&) { return a->ordinal() < ord; }); + auto it = std::lower_bound(es.cbegin(), es.cend(), e_, [=](const auto& a, const auto&) { return a->ordinal() < ord; }); + auto ret = (std::size_t)std::distance(es.cbegin(), it); e_->coord = coord_; e_->offset = offset_; - e_->c = &c2; - es.insert(it_, std::move(e_)); + const_cast<struct chunk*&>(e_->c) = &c2; + es.insert(it, std::move(e_)); + return ret; } } @@ -230,8 +229,8 @@ entity::operator entity_proto() const return x; } -bool entity::can_activate(It) const { return false; } -bool entity::activate(It) { return false; } +bool entity::can_activate(std::size_t) const { return false; } +bool entity::activate(std::size_t) { return false; } bool entity::is_dynamic() const { diff --git a/src/entity.hpp b/src/entity.hpp index 8d2c66a1..9c6dc2d1 100644 --- a/src/entity.hpp +++ b/src/entity.hpp @@ -36,10 +36,9 @@ struct entity_proto struct entity { fm_DECLARE_DELETED_COPY_ASSIGNMENT(entity); - using It = typename std::vector<std::shared_ptr<entity>>::const_iterator; const std::uint64_t id = 0; - struct chunk* c; + struct chunk* const c; std::shared_ptr<anim_atlas> atlas; global_coords coord; Vector2b offset, bbox_offset; @@ -55,19 +54,19 @@ struct entity float ordinal() const; static float ordinal(local_coords xy, Vector2b offset, entity_type type); struct chunk& chunk() const; - It iter() const; + std::size_t index() const; virtual bool operator==(const entity_proto& e0) const; operator entity_proto() const; - virtual bool can_activate(It it) const; - virtual bool activate(It it); - virtual bool update(It it, float dt) = 0; - virtual void rotate(It it, rotation r); + virtual bool can_activate(std::size_t i) const; + virtual bool activate(std::size_t i); + virtual bool update(std::size_t i, float dt) = 0; + virtual void rotate(std::size_t i, rotation r); static Pair<global_coords, Vector2b> normalize_coords(global_coords coord, Vector2b cur_offset, Vector2i delta); [[nodiscard]] virtual bool can_move_to(Vector2i delta); - static void move(It it, Vector2i delta); + std::size_t move(std::size_t i, Vector2i delta); void update_bbox(Vector2b bbox_offset, Vector2ub bbox_size); // todo bool is_dynamic() const; diff --git a/src/scenery.cpp b/src/scenery.cpp index a7c21ae2..5fe6d573 100644 --- a/src/scenery.cpp +++ b/src/scenery.cpp @@ -7,19 +7,22 @@ namespace floormat { -scenery_proto::scenery_proto() = default; +scenery_proto::scenery_proto() +{ + type = entity_type::scenery; +} scenery_proto& scenery_proto::operator=(const scenery_proto&) = default; scenery_proto::scenery_proto(const scenery_proto&) = default; scenery_proto::~scenery_proto() noexcept = default; scenery_proto::operator bool() const { return atlas != nullptr; } -bool scenery::can_activate(It) const +bool scenery::can_activate(std::size_t) const { return atlas && interactive; } -bool scenery::update(It, float dt) +bool scenery::update(std::size_t, float dt) { auto& s = *this; if (!s.active) @@ -60,7 +63,7 @@ bool scenery::update(It, float dt) } } -bool scenery::activate(It) +bool scenery::activate(std::size_t) { auto& s = *this; if (s.active) diff --git a/src/scenery.hpp b/src/scenery.hpp index 8f0d5d27..2939fe7d 100644 --- a/src/scenery.hpp +++ b/src/scenery.hpp @@ -40,9 +40,9 @@ struct scenery final : entity std::uint8_t closing : 1 = false; std::uint8_t interactive : 1 = false; - bool can_activate(It it) const override; - bool activate(It it) override; - bool update(It it, float dt) override; + bool can_activate(std::size_t i) const override; + bool activate(std::size_t i) override; + bool update(std::size_t i, float dt) override; bool operator==(const entity_proto& p) const override; private: |