summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--editor/inspect-types.cpp11
-rw-r--r--src/chunk-collision.cpp37
-rw-r--r--src/chunk.cpp3
-rw-r--r--src/hole.cpp26
-rw-r--r--src/hole.hpp4
-rw-r--r--src/object.cpp11
-rw-r--r--src/object.hpp1
-rw-r--r--src/world.cpp6
-rw-r--r--src/world.hpp2
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);