summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--editor/imgui.cpp8
-rw-r--r--editor/inspect-types.cpp2
-rw-r--r--editor/scenery-editor.cpp23
-rw-r--r--editor/update.cpp7
-rw-r--r--src/character.cpp6
-rw-r--r--src/character.hpp2
-rw-r--r--src/chunk.cpp7
-rw-r--r--src/chunk.hpp5
-rw-r--r--src/entity.cpp57
-rw-r--r--src/entity.hpp15
-rw-r--r--src/scenery.cpp11
-rw-r--r--src/scenery.hpp6
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: