diff options
-rw-r--r-- | editor/inspect-types.cpp | 11 | ||||
-rw-r--r-- | src/chunk-collision.cpp | 37 | ||||
-rw-r--r-- | src/chunk.cpp | 3 | ||||
-rw-r--r-- | src/hole.cpp | 26 | ||||
-rw-r--r-- | src/hole.hpp | 4 | ||||
-rw-r--r-- | src/object.cpp | 11 | ||||
-rw-r--r-- | src/object.hpp | 1 | ||||
-rw-r--r-- | src/world.cpp | 6 | ||||
-rw-r--r-- | src/world.hpp | 2 |
9 files changed, 65 insertions, 36 deletions
diff --git a/editor/inspect-types.cpp b/editor/inspect-types.cpp index 65af0966..2a4fd05d 100644 --- a/editor/inspect-types.cpp +++ b/editor/inspect-types.cpp @@ -164,14 +164,17 @@ template<> struct entity_accessors<hole, inspect_intent_t> [](const hole& x) { return x.flags.is_wall ? st::enabled : st::readonly; }, constantly(constraints::range<uint8_t>{0, tile_size_z}), }, + E::type<bool>::field{ "enabled"_s, + [](const hole& x) { return x.flags.enabled; }, + [](hole& x, bool value) { x.set_enabled(x.flags.on_render, x.flags.on_physics, value); }, + }, E::type<bool>::field{"on-render"_s, [](const hole& x) { return x.flags.on_render; }, - [](hole& x, bool value) { x.set_enabled(value, x.flags.on_physics); }, + [](hole& x, bool value) { x.set_enabled(value, x.flags.on_physics, x.flags.enabled); }, }, - E::type<bool>::field{ - "on-physics"_s, + E::type<bool>::field{ "on-physics"_s, [](const hole& x) { return x.flags.on_physics; }, - [](hole& x, bool value) { x.set_enabled(x.flags.on_render, value); }, + [](hole& x, bool value) { x.set_enabled(x.flags.on_render, value, x.flags.enabled); }, }, }; return std::tuple_cat(tuple0, tuple); diff --git a/src/chunk-collision.cpp b/src/chunk-collision.cpp index faaea11b..18f6d2bb 100644 --- a/src/chunk-collision.cpp +++ b/src/chunk-collision.cpp @@ -34,7 +34,7 @@ constexpr object_id make_id(collision_type type, pass_mode p, object_id id) } template<bool IsNeighbor> -bool add_holes_from(chunk::RTree& rtree, chunk& c, Vector2b chunk_offset) +bool add_holes_from_chunk(chunk::RTree& rtree, chunk& c, Vector2b chunk_offset) { bool has_holes = false; constexpr auto chunk_size = iTILE_SIZE2 * TILE_MAX_DIM; @@ -43,9 +43,11 @@ bool add_holes_from(chunk::RTree& rtree, chunk& c, Vector2b chunk_offset) chunk_max = TILE_MAX_DIM * iTILE_SIZE2 - iTILE_SIZE2 / 2 + max_bbox_size; for (const std::shared_ptr<object>& eʹ : c.objects()) { - if (eʹ->type() != object_type::hole) [[likely]] - continue; const auto& e = static_cast<struct hole&>(*eʹ); + if (e.type() != object_type::hole) [[likely]] + continue; + if (!e.flags.enabled | !e.flags.on_physics) + continue; auto center = Vector2i(e.offset) + Vector2i(e.bbox_offset) + Vector2i(e.coord.local()) * TILE_SIZE2; if constexpr(IsNeighbor) { @@ -64,7 +66,7 @@ bool add_holes_from(chunk::RTree& rtree, chunk& c, Vector2b chunk_offset) #if 0 CORRADE_NEVER_INLINE -bool find_hole_in_rtree(CutResult<float>::rect& hole, chunk::RTree& rtree, Vector2 min, Vector2 max) +bool find_hole_in_bbox(CutResult<float>::rect& hole, chunk::RTree& rtree, Vector2 min, Vector2 max) { bool ret = true; rtree.Search(min.data(), max.data(), [&](uint64_t data, const chunk::RTree::Rect& r) { @@ -95,7 +97,7 @@ start: fm_assert(min != max); // todo! CutResult<float>::rect hole; - bool ret = find_hole_in_rtree(hole, rtree, min, max); + bool ret = find_hole_in_bbox(hole, rtree, min, max); if (ret) [[likely]] rtree.Insert(min.data(), max.data(), id); @@ -120,7 +122,7 @@ start: } } #else -void filter_through_holes(chunk::RTree& rtree, object_id id, Vector2 min, Vector2 max, unsigned = 0) +void filter_through_holes(chunk::RTree& rtree, object_id id, Vector2 min, Vector2 max, bool) { rtree.Insert(min.data(), max.data(), id); } @@ -137,14 +139,15 @@ void chunk::ensure_passability() noexcept _pass_modified = false; _rtree->RemoveAll(); + //Debug{} << ".. reset passability"; bool has_holes = false; { - has_holes |= add_holes_from<false>(*_rtree, *this, {}); + has_holes |= add_holes_from_chunk<false>(*_rtree, *this, {}); const auto nbs = _world->neighbors(_coord); for (auto i = 0u; i < 8; i++) if (nbs[i]) - has_holes |= add_holes_from<true>(*_rtree, *nbs[i], world::neighbor_offsets[i]); + has_holes |= add_holes_from_chunk<true>(*_rtree, *nbs[i], world::neighbor_offsets[i]); } for (auto i = 0uz; i < TILE_COUNT; i++) @@ -181,17 +184,20 @@ void chunk::ensure_passability() noexcept filter_through_holes(*_rtree, id, min, max, has_holes); } } - for (const std::shared_ptr<object>& sʹ : objects()) + for (const std::shared_ptr<object>& eʹ : objects()) { - bbox box; - if (sʹ->type() != object_type::hole && _bbox_for_scenery(*sʹ, box)) + if (eʹ->updates_passability()) + continue; + bbox bb; + if (_bbox_for_scenery(*eʹ, bb)) { - if (sʹ->is_dynamic()) - _add_bbox(box); + if (!eʹ->is_dynamic()) + filter_through_holes(*_rtree, std::bit_cast<object_id>(bb.data), Vector2(bb.start), Vector2(bb.end), has_holes); else - filter_through_holes(*_rtree, std::bit_cast<object_id>(box.data), Vector2(box.start), Vector2(box.end), has_holes); + _add_bbox(bb); } } + fm_assert(!_pass_modified); } bool chunk::_bbox_for_scenery(const object& s, local_coords local, Vector2b offset, @@ -212,12 +218,15 @@ void chunk::_remove_bbox(const bbox& x) { auto start = Vector2(x.start), end = Vector2(x.end); _rtree->Remove(start.data(), end.data(), std::bit_cast<object_id>(x.data)); + //Debug{} << "bbox <<" << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); } void chunk::_add_bbox(const bbox& x) { auto start = Vector2(x.start), end = Vector2(x.end); _rtree->Insert(start.data(), end.data(), std::bit_cast<object_id>(x.data)); + + //Debug{} << "bbox >>" << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); } void chunk::_replace_bbox(const bbox& x0, const bbox& x1, bool b0, bool b1) diff --git a/src/chunk.cpp b/src/chunk.cpp index 57a3e62a..a7848936 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -3,6 +3,7 @@ #include "world.hpp" #include "log.hpp" #include "RTree.h" +#include "compat/non-const.hpp" #include <algorithm> #include <cr/GrowableArray.h> #include <cr/Optional.h> @@ -33,7 +34,7 @@ bool chunk::empty(bool force) const noexcept ground_atlas* chunk::ground_atlas_at(size_t i) const noexcept { return _ground ? _ground->atlases[i].get() : nullptr; } tile_ref chunk::operator[](size_t idx) noexcept { return { *this, uint8_t(idx) }; } -tile_proto chunk::operator[](size_t idx) const noexcept { return tile_proto(tile_ref { *const_cast<chunk*>(this), uint8_t(idx) }); } +tile_proto chunk::operator[](size_t idx) const noexcept { return tile_proto(tile_ref { non_const(*this), uint8_t(idx) }); } tile_ref chunk::operator[](local_coords xy) noexcept { return operator[](xy.to_index()); } tile_proto chunk::operator[](local_coords xy) const noexcept { return operator[](xy.to_index()); } diff --git a/src/hole.cpp b/src/hole.cpp index d3058d1a..e9c6c14f 100644 --- a/src/hole.cpp +++ b/src/hole.cpp @@ -4,11 +4,19 @@ #include "loader/vobj-cell.hpp" #include "shaders/shader.hpp" #include "tile-constants.hpp" +#include "world.hpp" #include "compat/non-const.hpp" namespace floormat { namespace { +void mark_chunk_modifiedʹ(chunk& c) +{ + c.mark_passability_modified(); + //c.mark_ground_modified(); // todo! + //c.mark_walls_modified(); // todo! +} + } // namespace hole_proto::~hole_proto() noexcept = default; @@ -63,9 +71,10 @@ hole::operator hole_proto() const void hole::mark_chunk_modified() { - //c->mark_ground_modified(); // todo! - //c->mark_walls_modified(); // todo! - c->mark_passability_modified(); + for (auto* const cʹ : c->world().neighbors(c->coord())) + if (cʹ) + mark_chunk_modifiedʹ(*cʹ); + mark_chunk_modifiedʹ(*c); } float hole::depth_offset() const @@ -84,7 +93,7 @@ void hole::set_height(uint8_t heightʹ) { if (height != heightʹ) { - const_cast<uint8_t&>(height) = heightʹ; + non_const(height) = heightʹ; mark_chunk_modified(); } } @@ -93,25 +102,28 @@ void hole::set_z_offset(uint8_t z) { if (z_offset != z) { - const_cast<uint8_t&>(z_offset) = z; + non_const(z_offset) = z; mark_chunk_modified(); } } -void hole::set_enabled(bool on_render, bool on_physics) +void hole::set_enabled(bool on_render, bool on_physics, bool on_both) { non_const(flags).on_render = on_render; - if (flags.on_physics != on_physics) + if (flags.on_physics != on_physics || on_both != flags.enabled) { non_const(flags).on_physics = on_physics; mark_chunk_modified(); } + + non_const(flags).enabled = on_both; } object_type hole::type() const noexcept { return object_type::hole; } bool hole::is_virtual() const { return true; } bool hole::is_dynamic() const { return true; } +bool hole::updates_passability() const { return true; } } // namespace floormat diff --git a/src/hole.hpp b/src/hole.hpp index 5e993072..52895e0b 100644 --- a/src/hole.hpp +++ b/src/hole.hpp @@ -21,6 +21,7 @@ struct hole_proto final : object_proto bool on_render : 1 = true; bool on_physics : 1 = true; + bool enabled : 1 = true; bool is_wall : 1 = false; }; @@ -41,11 +42,12 @@ struct hole final : object object_type type() const noexcept override; void update(const std::shared_ptr<object>& ptr, size_t& i, const Ns& dt) override; bool is_dynamic() const override; + bool updates_passability() const override; bool is_virtual() const override; void set_height(uint8_t height); void set_z_offset(uint8_t z); - void set_enabled(bool on_render, bool on_physics); + void set_enabled(bool on_render, bool on_physics, bool on_both); explicit operator hole_proto() const; diff --git a/src/object.cpp b/src/object.cpp index a3df2ef9..89988747 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -9,6 +9,7 @@ #include "compat/debug.hpp" #include "compat/exception.hpp" #include "compat/limits.hpp" +#include "compat/non-const.hpp" #include "nanosecond.inl" #include <cmath> #include <algorithm> @@ -71,9 +72,11 @@ object::~object() noexcept fm_debug_assert(id); if (c->is_teardown()) [[unlikely]] return; +#if 0 if (chunk::bbox bb; c->_bbox_for_scenery(*this, bb)) c->_remove_bbox(bb); - c->_world->do_kill_object(id); +#endif + c->_world->erase_object(id); const_cast<object_id&>(id) = 0; } @@ -357,10 +360,8 @@ bool object::is_virtual() const { return false; } point object::position() const { return {coord, offset}; } object_type object::type_of() const noexcept { return type(); } -bool object::is_dynamic() const -{ - return atlas->info().fps > 0; -} +bool object::is_dynamic() const { return atlas->info().fps > 0; } +bool object::updates_passability() const { return false; } void object::init_script(const std::shared_ptr<object>&) {} void object::destroy_script_pre(const std::shared_ptr<object>&, script_destroy_reason) {} diff --git a/src/object.hpp b/src/object.hpp index 9ee9f1d1..8d71645b 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -88,6 +88,7 @@ struct object static point normalize_coords(const point& pt, Vector2i delta); virtual bool is_dynamic() const; + virtual bool updates_passability() const; bool can_rotate(rotation new_r); bool can_move_to(Vector2i delta); bool move_to(size_t& i, Vector2i delta, rotation new_r); diff --git a/src/world.cpp b/src/world.cpp index c0a6cc39..d9040967 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -81,8 +81,8 @@ world::~world() noexcept for (auto& [k, c] : _chunks) { c._teardown = true; - c.mark_scenery_modified(); - c.mark_passability_modified(); + //c.mark_scenery_modified(); // XXX why? what for? + //c.mark_passability_modified(); // XXX why? what for? _last_chunk = {}; arrayResize(c._objects, 0); } @@ -179,7 +179,7 @@ void world::do_make_object(const std::shared_ptr<object>& e, global_coords pos, e->c->add_object_unsorted(e); } -void world::do_kill_object(object_id id) +void world::erase_object(object_id id) { fm_debug_assert(id != 0); auto cnt = _objects->erase(id); diff --git a/src/world.hpp b/src/world.hpp index c8084614..420e8894 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -50,7 +50,7 @@ private: explicit world(size_t capacity); void do_make_object(const std::shared_ptr<object>& e, global_coords pos, bool sorted); // todo replace 2nd arg with chunk& - void do_kill_object(object_id id); + void erase_object(object_id id); std::shared_ptr<object> find_object_(object_id id); [[noreturn]] static void throw_on_wrong_object_type(object_id id, object_type actual, object_type expected); |