diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-07-16 12:27:46 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-07-16 12:27:46 +0200 |
commit | 47b9691f9bde62ea62f6601503997d93ed7ab64c (patch) | |
tree | f0e08b4f37ced066ac18defdf233eec0e91b6cc0 | |
parent | 6aabc74a535da1f2d5cf866346b31939d097cbac (diff) |
wa
87 files changed, 386 insertions, 348 deletions
diff --git a/bench/critter.cpp b/bench/critter.cpp index 9dd69f3a..418a4f9e 100644 --- a/bench/critter.cpp +++ b/bench/critter.cpp @@ -1,5 +1,4 @@ #include "compat/debug.hpp" -#include "compat/shared-ptr-wrapper.hpp" #include "compat/function2.hpp" #include "src/critter.hpp" #include "src/world.hpp" @@ -109,7 +108,7 @@ bool run(world& w, const function_view<Ns() const>& make_dt, mark_all_modified(w); object_id id = 0; - auto npc_ = w.ensure_player_character(id, make_proto((float)start.accel)).ptr; + auto npc_ = w.ensure_player_character(id, make_proto((float)start.accel)); auto& npc = *npc_; auto index = npc.index(); diff --git a/bench/loader.cpp b/bench/loader.cpp index 00008d00..0cd08699 100644 --- a/bench/loader.cpp +++ b/bench/loader.cpp @@ -3,6 +3,7 @@ #include "loader/wall-cell.hpp" #include "serialize/json-helper.hpp" #include "serialize/anim.hpp" +#include "compat/borrowed-ptr.inl" #include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/StringIterable.h> #include <benchmark/benchmark.h> diff --git a/compat/shared-ptr-wrapper.hpp b/compat/shared-ptr-wrapper.hpp deleted file mode 100644 index 8315d674..00000000 --- a/compat/shared-ptr-wrapper.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include <memory> - -namespace floormat { - -template<typename T> -struct shared_ptr_wrapper final -{ - std::shared_ptr<T> ptr; -}; - -} // namespace floormat diff --git a/editor/app.cpp b/editor/app.cpp index 36d4ad1b..b5d6b7a1 100644 --- a/editor/app.cpp +++ b/editor/app.cpp @@ -1,7 +1,7 @@ #include "app.hpp" #include "compat/assert.hpp" #include "compat/sysexits.hpp" -#include "compat/shared-ptr-wrapper.hpp" +#include "compat/borrowed-ptr.inl" #include "editor.hpp" #include "src/anim-atlas.hpp" #include "src/critter.hpp" @@ -27,10 +27,11 @@ Optional<struct point> cursor_state::point() const floormat_main& app::main() { return *M; } const cursor_state& app::cursor_state() { return cursor; } -shared_ptr_wrapper<critter> app::ensure_player_character(world& w) +bptr<critter> app::ensure_player_character(world& w) { return w.ensure_player_character(_character_id); } + void app::reset_world() { if (M) diff --git a/editor/app.hpp b/editor/app.hpp index aecd495b..b04da7dc 100644 --- a/editor/app.hpp +++ b/editor/app.hpp @@ -2,6 +2,7 @@ #include "compat/defs.hpp" #include "compat/enum-bitset-fwd.hpp" #include "compat/safe-ptr.hpp" +#include "compat/borrowed-ptr-fwd.hpp" #include "floormat/app.hpp" #include "keys.hpp" #include "src/global-coords.hpp" @@ -82,7 +83,7 @@ struct app final : floormat_app const struct cursor_state& cursor_state(); clickable* find_clickable_scenery(const Optional<Vector2i>& pixel); Vector2 point_screen_pos(point pt); - shared_ptr_wrapper<critter> ensure_player_character(world& w); + bptr<critter> ensure_player_character(world& w); private: explicit app(fm_settings&& opts); diff --git a/editor/camera.cpp b/editor/camera.cpp index 14618d5b..5fe28bc7 100644 --- a/editor/camera.cpp +++ b/editor/camera.cpp @@ -10,6 +10,7 @@ #include "src/camera-offset.hpp" #include "src/timer.hpp" #include "compat/enum-bitset.hpp" +#include "compat/borrowed-ptr.inl" #include <bit> #include <Magnum/Math/Functions.h> diff --git a/editor/draw.cpp b/editor/draw.cpp index f5a906d2..d781c5a9 100644 --- a/editor/draw.cpp +++ b/editor/draw.cpp @@ -1,4 +1,5 @@ #include "app.hpp" +#include "compat/borrowed-ptr.inl" #include "src/tile-constants.hpp" #include "floormat/main.hpp" #include "floormat/draw-bounds.hpp" diff --git a/editor/ground-editor.cpp b/editor/ground-editor.cpp index 49f636ce..f6b3c438 100644 --- a/editor/ground-editor.cpp +++ b/editor/ground-editor.cpp @@ -7,7 +7,6 @@ #include "keys.hpp" #include "loader/loader.hpp" #include "loader/ground-cell.hpp" -#include <memory> #include <Corrade/Containers/GrowableArray.h> #include <Corrade/Utility/Path.h> @@ -18,7 +17,7 @@ typename std::map<StringView, ground_cell>::const_iterator ground_editor::end() struct ground_editor::tuple { - std::shared_ptr<ground_atlas> atlas; + bptr<ground_atlas> atlas; Array<variant_t> variant; }; @@ -43,7 +42,7 @@ void ground_editor::load_atlases() fm_assert(!_atlases.empty()); } -std::shared_ptr<ground_atlas> ground_editor::maybe_atlas(StringView str) +bptr<ground_atlas> ground_editor::maybe_atlas(StringView str) { if (auto it = _atlases.find(str); it != _atlases.end()) return it->second.atlas; @@ -51,7 +50,7 @@ std::shared_ptr<ground_atlas> ground_editor::maybe_atlas(StringView str) return nullptr; } -std::shared_ptr<ground_atlas> ground_editor::atlas(StringView str) +bptr<ground_atlas> ground_editor::atlas(StringView str) { if (auto ptr = maybe_atlas(str)) return ptr; @@ -68,7 +67,7 @@ void ground_editor::clear_selection() _selection_mode = sel_none; } -void ground_editor::select_tile(const std::shared_ptr<ground_atlas>& atlas, size_t variant) +void ground_editor::select_tile(const bptr<ground_atlas>& atlas, size_t variant) { fm_assert(atlas); clear_selection(); @@ -76,7 +75,7 @@ void ground_editor::select_tile(const std::shared_ptr<ground_atlas>& atlas, size _selected_tile = { atlas, variant_t(variant % atlas->num_tiles()) }; } -void ground_editor::select_tile_permutation(const std::shared_ptr<ground_atlas>& atlas) +void ground_editor::select_tile_permutation(const bptr<ground_atlas>& atlas) { fm_assert(atlas); clear_selection(); @@ -84,19 +83,19 @@ void ground_editor::select_tile_permutation(const std::shared_ptr<ground_atlas>& *_permutation = { atlas, {} }; } -bool ground_editor::is_tile_selected(const std::shared_ptr<const ground_atlas>& atlas, size_t variant) const +bool ground_editor::is_tile_selected(const bptr<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 +bool ground_editor::is_permutation_selected(const bptr<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 +bool ground_editor::is_atlas_selected(const bptr<const ground_atlas>& atlas) const { switch (_selection_mode) { diff --git a/editor/ground-editor.hpp b/editor/ground-editor.hpp index 9745d14b..b27065f0 100644 --- a/editor/ground-editor.hpp +++ b/editor/ground-editor.hpp @@ -28,18 +28,18 @@ class ground_editor final public: ground_editor(); ~ground_editor() noexcept; - std::shared_ptr<ground_atlas> maybe_atlas(StringView str); - std::shared_ptr<ground_atlas> atlas(StringView str); + bptr<ground_atlas> maybe_atlas(StringView str); + bptr<ground_atlas> atlas(StringView str); typename std::map<StringView, ground_cell>::const_iterator begin() const noexcept; typename std::map<StringView, ground_cell>::const_iterator end() const noexcept; StringView name() const noexcept; void clear_selection(); - void select_tile(const std::shared_ptr<ground_atlas>& atlas, size_t variant); - void select_tile_permutation(const std::shared_ptr<ground_atlas>& atlas); - bool is_tile_selected(const std::shared_ptr<const ground_atlas>& atlas, size_t variant) const; - bool is_permutation_selected(const std::shared_ptr<const ground_atlas>& atlas) const; - bool is_atlas_selected(const std::shared_ptr<const ground_atlas>& atlas) const; + void select_tile(const bptr<ground_atlas>& atlas, size_t variant); + void select_tile_permutation(const bptr<ground_atlas>& atlas); + bool is_tile_selected(const bptr<const ground_atlas>& atlas, size_t variant) const; + bool is_permutation_selected(const bptr<const ground_atlas>& atlas) const; + bool is_atlas_selected(const bptr<const ground_atlas>& atlas) const; bool is_anything_selected() const; tile_image_proto get_selected(); void place_tile(world& world, global_coords pos, const tile_image_proto& img); diff --git a/editor/imgui-editors.cpp b/editor/imgui-editors.cpp index b447984d..a36e7c00 100644 --- a/editor/imgui-editors.cpp +++ b/editor/imgui-editors.cpp @@ -2,6 +2,7 @@ #include "src/tile-constants.hpp" #include "compat/array-size.hpp" #include "compat/format.hpp" +#include "compat/borrowed-ptr.inl" #include "imgui-raii.hpp" #include "ground-editor.hpp" #include "wall-editor.hpp" @@ -44,9 +45,9 @@ StringView scenery_path(const wall_cell& wa) { return wa.atlas->name(); } StringView scenery_name(StringView, const scenery_& sc) { return sc.name; } StringView scenery_name(StringView, const vobj_& vobj) { return vobj.descr; } StringView scenery_name(StringView, const wall_cell& w) { return w.name; } -std::shared_ptr<anim_atlas> get_atlas(const scenery_& sc) { return sc.proto.atlas; } -std::shared_ptr<anim_atlas> get_atlas(const vobj_& vobj) { return vobj.factory->atlas(); } -std::shared_ptr<wall_atlas> get_atlas(const wall_cell& w) { return w.atlas; } +bptr<anim_atlas> get_atlas(const scenery_& sc) { return sc.proto.atlas; } +bptr<anim_atlas> get_atlas(const vobj_& vobj) { return vobj.factory->atlas(); } +bptr<wall_atlas> get_atlas(const wall_cell& w) { return w.atlas; } Vector2ui get_size(const auto&, anim_atlas& atlas) { return atlas.frame(atlas.first_rotation(), 0).size; } Vector2ui get_size(const auto&, wall_atlas& atlas) { auto sz = atlas.image_size(); return { std::max(1u, std::min(sz.y()*3/2, sz.x())), sz.y() }; } bool is_selected(const scenery_editor& ed, const scenery_& sc) { return ed.is_item_selected(sc); } @@ -58,7 +59,7 @@ void select_tile(wall_editor& wa, const wall_cell& sc) { wa.select_atlas(sc.atla auto get_texcoords(const auto&, anim_atlas& atlas) { return atlas.texcoords_for_frame(atlas.first_rotation(), 0, !atlas.group(atlas.first_rotation()).mirror_from.isEmpty()); } auto get_texcoords(const wall_cell& w, wall_atlas& atlas) { auto sz = get_size(w, atlas); return Quads::texcoords_at({}, sz, atlas.image_size()); } -void draw_editor_tile_pane_atlas(ground_editor& ed, StringView name, const std::shared_ptr<ground_atlas>& atlas, Vector2 dpi) +void draw_editor_tile_pane_atlas(ground_editor& ed, StringView name, const bptr<ground_atlas>& atlas, Vector2 dpi) { const auto b = push_id("tile-pane"); diff --git a/editor/imgui.cpp b/editor/imgui.cpp index 2923c3ea..5e5acf90 100644 --- a/editor/imgui.cpp +++ b/editor/imgui.cpp @@ -1,6 +1,7 @@ #include "app.hpp" #include "src/tile-constants.hpp" #include "compat/format.hpp" +#include "compat/borrowed-ptr.inl" #include "editor.hpp" #include "ground-editor.hpp" #include "wall-editor.hpp" diff --git a/editor/inspect-types.cpp b/editor/inspect-types.cpp index fba0fc7b..da5a8c9f 100644 --- a/editor/inspect-types.cpp +++ b/editor/inspect-types.cpp @@ -184,7 +184,7 @@ template<> struct entity_accessors<hole, inspect_intent_t> template<typename, typename = void> struct has_anim_atlas : std::false_type {}; template<typename T> -requires requires (const T& x) { { x.atlas } -> std::convertible_to<const std::shared_ptr<anim_atlas>&>; } +requires requires (const T& x) { { x.atlas } -> std::convertible_to<const bptr<anim_atlas>&>; } struct has_anim_atlas<T> : std::true_type { static const anim_atlas& get_atlas(const object& x) { return *x.atlas; } }; diff --git a/editor/scenery-editor.cpp b/editor/scenery-editor.cpp index 2c205e3e..0ba04028 100644 --- a/editor/scenery-editor.cpp +++ b/editor/scenery-editor.cpp @@ -6,6 +6,7 @@ #include "src/rotation.inl" #include "app.hpp" #include "src/scenery.hpp" +#include "compat/borrowed-ptr.inl" #include <Magnum/Math/Range.h> @@ -68,7 +69,7 @@ auto scenery_editor::get_selected() const -> const scenery_& return _selected; } -bool scenery_editor::is_atlas_selected(const std::shared_ptr<anim_atlas>& atlas) const +bool scenery_editor::is_atlas_selected(const bptr<anim_atlas>& atlas) const { return atlas == _selected.proto.atlas; } diff --git a/editor/scenery-editor.hpp b/editor/scenery-editor.hpp index 678b990f..6f15bf76 100644 --- a/editor/scenery-editor.hpp +++ b/editor/scenery-editor.hpp @@ -1,7 +1,6 @@ #pragma once #include "src/scenery-proto.hpp" #include <map> -#include <memory> #include <Corrade/Containers/String.h> namespace floormat { @@ -30,7 +29,7 @@ public: void select_tile(const scenery_& s); void clear_selection(); const scenery_& get_selected() const; - bool is_atlas_selected(const std::shared_ptr<anim_atlas>& atlas) const; + bool is_atlas_selected(const bptr<anim_atlas>& atlas) const; bool is_item_selected(const scenery_& s) const; bool is_anything_selected() const; static void place_tile(world& w, global_coords pos, const scenery_& s, app& a); diff --git a/editor/tests/hole-test.cpp b/editor/tests/hole-test.cpp index 7b6041b2..b419f7e8 100644 --- a/editor/tests/hole-test.cpp +++ b/editor/tests/hole-test.cpp @@ -1,5 +1,4 @@ #include "../tests-private.hpp" -#include "compat/shared-ptr-wrapper.hpp" #include "src/tile-constants.hpp" #include "src/chunk-region.hpp" #include "src/hole.hpp" diff --git a/editor/tests/path-test.cpp b/editor/tests/path-test.cpp index 63b59dd4..4b82af68 100644 --- a/editor/tests/path-test.cpp +++ b/editor/tests/path-test.cpp @@ -1,14 +1,15 @@ #include "../tests-private.hpp" #include "../app.hpp" #include "compat/array-size.hpp" -#include "compat/shared-ptr-wrapper.hpp" #include "compat/vector-wrapper.hpp" +#include "compat/borrowed-ptr.inl" #include "floormat/main.hpp" #include "src/search-astar.hpp" #include "src/search-result.hpp" #include "src/critter.hpp" #include "shaders/shader.hpp" #include "../imgui-raii.hpp" +#include <cstdio> #include <cr/Optional.h> #include <mg/Functions.h> #include <mg/Color.h> @@ -59,7 +60,7 @@ bool path_test::handle_mouse_click(app& a, const mouse_button_event& e, bool is_ case mouse_button_left: { auto& M = a.main(); auto& w = M.world(); - auto C = a.ensure_player_character(w).ptr; + auto C = a.ensure_player_character(w); if (auto pt = a.cursor_state().point()) { constexpr auto chunk_size = iTILE_SIZE2 * TILE_MAX_DIM; diff --git a/editor/tests/raycast-test.cpp b/editor/tests/raycast-test.cpp index 6596303f..07b44eaf 100644 --- a/editor/tests/raycast-test.cpp +++ b/editor/tests/raycast-test.cpp @@ -2,12 +2,12 @@ #include "editor/app.hpp" #include "floormat/main.hpp" #include "compat/array-size.hpp" -#include "compat/shared-ptr-wrapper.hpp" #include "../imgui-raii.hpp" #include "src/critter.hpp" #include "src/world.hpp" #include "src/raycast-diag.hpp" #include <cinttypes> +#include <cstdio> #include <array> #include <vector> #include <mg/Color.h> @@ -73,7 +73,7 @@ struct raycast_test final : base_test auto& w = M.world(); if (auto pt_ = a.cursor_state().point()) { - auto C = a.ensure_player_character(w).ptr; + auto C = a.ensure_player_character(w); auto pt0 = C->position(); pending = { .from = pt0, .to = *pt_, .self = C->id, .exists = true, }; return true; diff --git a/editor/tests/region-test.cpp b/editor/tests/region-test.cpp index 1206b1eb..0c51bf8a 100644 --- a/editor/tests/region-test.cpp +++ b/editor/tests/region-test.cpp @@ -1,5 +1,4 @@ #include "../tests-private.hpp" -#include "compat/shared-ptr-wrapper.hpp" #include "src/tile-constants.hpp" #include "src/chunk-region.hpp" #include "src/object.hpp" @@ -153,7 +152,7 @@ void region_test::do_region_extraction(app& a, chunk_coords_ coord) { auto& M = a.main(); auto& w = M.world(); - auto C = a.ensure_player_character(w).ptr; + auto C = a.ensure_player_character(w); if (auto* c = w.at(coord)) { auto C_coord = Vector2i{ Vector2i(C->coord.local()) * iTILE_SIZE2 + Vector2i(C->offset) }; diff --git a/editor/tests/walk-test.cpp b/editor/tests/walk-test.cpp index a317928f..f04fc869 100644 --- a/editor/tests/walk-test.cpp +++ b/editor/tests/walk-test.cpp @@ -1,5 +1,4 @@ #include "../tests-private.hpp" -#include "compat/shared-ptr-wrapper.hpp" #include "editor/app.hpp" #include "src/critter.hpp" #include "src/critter-script.hpp" @@ -8,6 +7,7 @@ #include "floormat/main.hpp" #include "../imgui-raii.hpp" #include "src/search-astar.hpp" +#include "compat/borrowed-ptr.inl" #include <mg/Functions.h> namespace floormat::tests { @@ -43,7 +43,7 @@ bool pf_test::handle_mouse_click(app& a, const mouse_button_event& e, bool is_do { if (auto ptʹ = a.cursor_state().point()) { - auto C = a.ensure_player_character(m.world()).ptr; + auto C = a.ensure_player_character(m.world()); fm_assert(C->is_dynamic()); constexpr auto chunk_size = iTILE_SIZE2 * TILE_MAX_DIM; @@ -63,7 +63,7 @@ bool pf_test::handle_mouse_click(app& a, const mouse_button_event& e, bool is_do } else if (e.button == mouse_button_right && is_down) { - auto C = a.ensure_player_character(m.world()).ptr; + auto C = a.ensure_player_character(m.world()); C->script.do_clear(C); } return false; diff --git a/editor/vobj-editor.cpp b/editor/vobj-editor.cpp index 9eb36e39..d4497fda 100644 --- a/editor/vobj-editor.cpp +++ b/editor/vobj-editor.cpp @@ -13,7 +13,7 @@ namespace floormat { StringView vobj_factory::name() const { return info().name; } StringView vobj_factory::descr() const { return info().descr; } -std::shared_ptr<anim_atlas> vobj_factory::atlas() const { return info().atlas; } +bptr<anim_atlas> vobj_factory::atlas() const { return info().atlas; } vobj_factory::vobj_factory() = default; vobj_factory::~vobj_factory() noexcept = default; @@ -81,7 +81,7 @@ struct light_factory final : vobj_factory { object_type type() const override; const vobj_cell& info() const override; - std::shared_ptr<object> make(world& w, object_id id, global_coords pos) const override; + bptr<object> make(world& w, object_id id, global_coords pos) const override; }; object_type light_factory::type() const { return object_type::light; } @@ -95,7 +95,7 @@ const vobj_cell& light_factory::info() const return ret; } -std::shared_ptr<object> light_factory::make(world& w, object_id id, global_coords pos) const +bptr<object> light_factory::make(world& w, object_id id, global_coords pos) const { auto ret = w.make_object<light>(id, pos, light_proto{}); return ret; @@ -105,7 +105,7 @@ struct hole_factory final : vobj_factory { object_type type() const override; const vobj_cell& info() const override; - std::shared_ptr<object> make(world& w, object_id id, global_coords pos) const override; + bptr<object> make(world& w, object_id id, global_coords pos) const override; }; object_type hole_factory::type() const { return object_type::hole; } @@ -119,7 +119,7 @@ const vobj_cell& hole_factory::info() const return ret; } -std::shared_ptr<object> hole_factory::make(world& w, object_id id, global_coords pos) const +bptr<object> hole_factory::make(world& w, object_id id, global_coords pos) const { auto ret = w.make_object<hole>(id, pos, hole_proto{}); return ret; diff --git a/editor/vobj-editor.hpp b/editor/vobj-editor.hpp index 0057504c..c614b4e7 100644 --- a/editor/vobj-editor.hpp +++ b/editor/vobj-editor.hpp @@ -1,6 +1,7 @@ #pragma once #include "src/object-type.hpp" #include "src/object-id.hpp" +#include "compat/borrowed-ptr-fwd.hpp" #include <memory> #include <map> #include <cr/String.h> @@ -20,11 +21,11 @@ struct vobj_factory virtual ~vobj_factory() noexcept; virtual const vobj_cell& info() const = 0; virtual object_type type() const = 0; - virtual std::shared_ptr<object> make(world& w, object_id id, global_coords pos) const = 0; + virtual bptr<object> make(world& w, object_id id, global_coords pos) const = 0; StringView name() const; StringView descr() const; - std::shared_ptr<anim_atlas> atlas() const; + bptr<anim_atlas> atlas() const; }; class vobj_editor final diff --git a/editor/wall-editor.cpp b/editor/wall-editor.cpp index 57cdb8ed..ee458547 100644 --- a/editor/wall-editor.cpp +++ b/editor/wall-editor.cpp @@ -71,13 +71,13 @@ StringView wall_editor::name() const { return "wall"_s; } enum rotation wall_editor::rotation() const { return _r; } void wall_editor::set_rotation(enum rotation r) { _r = r; } void wall_editor::toggle_rotation() { _r = next_rot(_r); } -std::shared_ptr<wall_atlas> wall_editor::get_selected() const { return _selected_atlas; } -void wall_editor::select_atlas(const std::shared_ptr<wall_atlas>& atlas) { _selected_atlas = atlas; } +bptr<wall_atlas> wall_editor::get_selected() const { return _selected_atlas; } +void wall_editor::select_atlas(const bptr<wall_atlas>& atlas) { _selected_atlas = atlas; } void wall_editor::clear_selection() { _selected_atlas = nullptr; } -bool wall_editor::is_atlas_selected(const std::shared_ptr<wall_atlas>& atlas) const { return _selected_atlas == atlas; } +bool wall_editor::is_atlas_selected(const bptr<wall_atlas>& atlas) const { return _selected_atlas == atlas; } bool wall_editor::is_anything_selected() const { return _selected_atlas != nullptr; } -void wall_editor::place_tile(world& w, global_coords coords, const std::shared_ptr<wall_atlas>& atlas) +void wall_editor::place_tile(world& w, global_coords coords, const bptr<wall_atlas>& atlas) { auto [c, t] = w[coords]; switch (_r) diff --git a/editor/wall-editor.hpp b/editor/wall-editor.hpp index 22f018d1..063729c7 100644 --- a/editor/wall-editor.hpp +++ b/editor/wall-editor.hpp @@ -3,7 +3,6 @@ #include "src/rotation.hpp" #include "src/global-coords.hpp" #include "loader/wall-cell.hpp" -#include <memory> #include <map> namespace floormat { @@ -14,7 +13,7 @@ class wall_atlas; class wall_editor { std::map<StringView, wall_cell> _atlases; - std::shared_ptr<wall_atlas> _selected_atlas; + bptr<wall_atlas> _selected_atlas; enum rotation _r = rotation::N; void load_atlases(); @@ -32,13 +31,13 @@ public: void set_rotation(enum rotation r); void toggle_rotation(); - std::shared_ptr<wall_atlas> get_selected() const; - void select_atlas(const std::shared_ptr<wall_atlas>& atlas); + bptr<wall_atlas> get_selected() const; + void select_atlas(const bptr<wall_atlas>& atlas); void clear_selection(); - bool is_atlas_selected(const std::shared_ptr<wall_atlas>& atlas) const; + bool is_atlas_selected(const bptr<wall_atlas>& atlas) const; bool is_anything_selected() const; - void place_tile(world& w, global_coords coords, const std::shared_ptr<wall_atlas>& atlas); + void place_tile(world& w, global_coords coords, const bptr<wall_atlas>& atlas); editor_snap_mode check_snap(int mods) const; }; diff --git a/loader/anim-atlas.cpp b/loader/anim-atlas.cpp index 76a656e4..cfbe7245 100644 --- a/loader/anim-atlas.cpp +++ b/loader/anim-atlas.cpp @@ -2,13 +2,13 @@ #include "atlas-loader.inl" #include "anim-cell.hpp" #include "anim-traits.hpp" -#include "compat/exception.hpp" +#include "compat/borrowed-ptr.inl" namespace floormat::loader_detail { template class atlas_loader<anim_atlas>; -std::shared_ptr<class anim_atlas> loader_impl::get_anim_atlas(StringView path) noexcept(false) +bptr<class anim_atlas> loader_impl::get_anim_atlas(StringView path) noexcept(false) { return _anim_loader->make_atlas(path, {}); } @@ -23,7 +23,7 @@ ArrayView<const anim_cell> loader_impl::anim_atlas_list() return _anim_loader->atlas_list(); } -std::shared_ptr<anim_atlas> loader_impl::anim_atlas(StringView name, StringView dir, loader_policy p) noexcept(false) +bptr<anim_atlas> loader_impl::anim_atlas(StringView name, StringView dir, loader_policy p) noexcept(false) { char buf[fm_FILENAME_MAX]; auto path = make_atlas_path(buf, dir, name); diff --git a/loader/anim-cell.hpp b/loader/anim-cell.hpp index 37bbb7d8..ce3f6d54 100644 --- a/loader/anim-cell.hpp +++ b/loader/anim-cell.hpp @@ -1,5 +1,5 @@ #pragma once -#include <memory> +#include "compat/borrowed-ptr.hpp" #include <Corrade/Containers/String.h> namespace floormat { @@ -8,7 +8,7 @@ class anim_atlas; struct anim_cell { - std::shared_ptr<anim_atlas> atlas; + bptr<anim_atlas> atlas; String name; }; diff --git a/loader/anim-traits.cpp b/loader/anim-traits.cpp index 524f4c24..09da71e8 100644 --- a/loader/anim-traits.cpp +++ b/loader/anim-traits.cpp @@ -7,6 +7,7 @@ #include "serialize/json-helper.hpp" #include "serialize/anim.hpp" #include "compat/exception.hpp" +#include "compat/borrowed-ptr.inl" #include <cr/StringView.h> #include <cr/GrowableArray.h> #include <cr/StridedArrayView.h> @@ -19,8 +20,8 @@ namespace floormat::loader_detail { using anim_traits = atlas_loader_traits<anim_atlas>; StringView anim_traits::loader_name() { return "anim_atlas"_s; } -auto anim_traits::atlas_of(const Cell& x) -> const std::shared_ptr<Atlas>& { return x.atlas; } -auto anim_traits::atlas_of(Cell& x) -> std::shared_ptr<Atlas>& { return x.atlas; } +auto anim_traits::atlas_of(const Cell& x) -> const bptr<Atlas>& { return x.atlas; } +auto anim_traits::atlas_of(Cell& x) -> bptr<Atlas>& { return x.atlas; } StringView anim_traits::name_of(const Cell& x) { return x.name; } String& anim_traits::name_of(Cell& x) { return x.name; } @@ -57,7 +58,7 @@ auto anim_traits::make_invalid_atlas(Storage& s) -> Cell .scale = anim_scale::fixed{size.x(), true}, .nframes = 1, }; - auto atlas = std::make_shared<class anim_atlas>(loader.INVALID, loader.make_error_texture(size), move(def)); + auto atlas = bptr<class anim_atlas>{InPlace, loader.INVALID, loader.make_error_texture(size), move(def)}; auto info = anim_cell { .atlas = atlas, .name = loader.INVALID, @@ -65,7 +66,7 @@ auto anim_traits::make_invalid_atlas(Storage& s) -> Cell return info; } -auto anim_traits::make_atlas(StringView name, const Cell&) -> std::shared_ptr<Atlas> +auto anim_traits::make_atlas(StringView name, const Cell&) -> bptr<Atlas> { char buf[fm_FILENAME_MAX]; auto json_path = loader.make_atlas_path(buf, {}, name, ".json"_s); @@ -96,7 +97,7 @@ auto anim_traits::make_atlas(StringView name, const Cell&) -> std::shared_ptr<At const auto width = size[1], height = size[0]; fm_soft_assert(anim_info.pixel_size[0] == width && anim_info.pixel_size[1] == height); - auto atlas = std::make_shared<class anim_atlas>(name, tex, move(anim_info)); + auto atlas = bptr<class anim_atlas>{InPlace, name, tex, move(anim_info)}; return atlas; } diff --git a/loader/anim-traits.hpp b/loader/anim-traits.hpp index 517a3097..85c71612 100644 --- a/loader/anim-traits.hpp +++ b/loader/anim-traits.hpp @@ -1,6 +1,6 @@ #pragma once #include "atlas-loader-fwd.hpp" -#include <memory> +#include "compat/borrowed-ptr.hpp" #include <cr/Optional.h> namespace floormat { struct anim_cell; class anim_atlas; } @@ -15,13 +15,13 @@ template<> struct atlas_loader_traits<anim_atlas> using Storage = atlas_storage<Atlas, Self>; static StringView loader_name(); - static const std::shared_ptr<Atlas>& atlas_of(const Cell& x); - static std::shared_ptr<Atlas>& atlas_of(Cell& x); + static const bptr<Atlas>& atlas_of(const Cell& x); + static bptr<Atlas>& atlas_of(Cell& x); static StringView name_of(const Cell& x); static String& name_of(Cell& x); static void atlas_list(Storage& st); static Cell make_invalid_atlas(Storage& st); - static std::shared_ptr<Atlas> make_atlas(StringView name, const Cell& c); + static bptr<Atlas> make_atlas(StringView name, const Cell& c); static Optional<Cell> make_cell(StringView name); }; diff --git a/loader/atlas-loader.hpp b/loader/atlas-loader.hpp index 226918f0..e56297c1 100644 --- a/loader/atlas-loader.hpp +++ b/loader/atlas-loader.hpp @@ -2,7 +2,6 @@ #include "compat/defs.hpp" #include "atlas-loader-fwd.hpp" #include "policy.hpp" -#include <memory> namespace floormat::loader_detail { diff --git a/loader/atlas-loader.inl b/loader/atlas-loader.inl index 8f1d1db6..6c5fedd4 100644 --- a/loader/atlas-loader.inl +++ b/loader/atlas-loader.inl @@ -5,7 +5,6 @@ #include "atlas-loader.hpp" #include "atlas-loader-storage.hpp" #include "loader/loader.hpp" -#include <memory> #include <cr/ArrayView.h> #include <cr/Optional.h> #include <cr/GrowableArray.h> diff --git a/loader/ground-atlas.cpp b/loader/ground-atlas.cpp index d46b0dfc..4b3495a0 100644 --- a/loader/ground-atlas.cpp +++ b/loader/ground-atlas.cpp @@ -2,14 +2,14 @@ #include "atlas-loader.inl" #include "ground-traits.hpp" #include "ground-cell.hpp" +#include "compat/borrowed-ptr.inl" #include <Magnum/Math/Vector2.h> namespace floormat::loader_detail { template class atlas_loader<ground_atlas>; -std::shared_ptr<ground_atlas> -loader_impl::get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexcept(false) +bptr<ground_atlas> loader_impl::get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexcept(false) { return _ground_loader->make_atlas(name, { .atlas = {}, .name = {}, .size = size, .pass = pass, @@ -31,8 +31,7 @@ const ground_cell& loader_impl::invalid_ground_atlas() return _ground_loader->get_invalid_atlas(); } -const std::shared_ptr<class ground_atlas>& -loader_impl::ground_atlas(StringView filename, loader_policy policy) noexcept(false) +const bptr<class ground_atlas>& loader_impl::ground_atlas(StringView filename, loader_policy policy) noexcept(false) { return _ground_loader->get_atlas(filename, policy); } diff --git a/loader/ground-cell.cpp b/loader/ground-cell.cpp index 21982bd0..33696cd6 100644 --- a/loader/ground-cell.cpp +++ b/loader/ground-cell.cpp @@ -4,6 +4,7 @@ //#include "serialize/corrade-string.hpp" #include "serialize/ground-atlas.hpp" #include "serialize/corrade-array.hpp" +#include "compat/borrowed-ptr.inl" #include <cr/Array.h> namespace floormat { diff --git a/loader/ground-cell.hpp b/loader/ground-cell.hpp index 9326cb9c..d96132a0 100644 --- a/loader/ground-cell.hpp +++ b/loader/ground-cell.hpp @@ -1,6 +1,6 @@ #pragma once #include "src/pass-mode.hpp" -#include <memory> +#include "compat/borrowed-ptr.hpp" #include <Corrade/Containers/String.h> #include <Magnum/Math/Vector2.h> @@ -10,7 +10,7 @@ class ground_atlas; struct ground_cell { - std::shared_ptr<ground_atlas> atlas; + bptr<ground_atlas> atlas; String name; Vector2ub size; pass_mode pass = pass_mode::pass; diff --git a/loader/ground-traits.cpp b/loader/ground-traits.cpp index fd3b2dc1..3061ef4c 100644 --- a/loader/ground-traits.cpp +++ b/loader/ground-traits.cpp @@ -5,6 +5,7 @@ #include "src/tile-defs.hpp" #include "src/ground-atlas.hpp" #include "compat/assert.hpp" +#include "compat/borrowed-ptr.inl" #include <cr/Optional.h> #include <Corrade/Containers/StringView.h> #include <Corrade/Containers/Pointer.h> @@ -15,8 +16,8 @@ namespace floormat::loader_detail { using ground_traits = atlas_loader_traits<ground_atlas>; StringView ground_traits::loader_name() { return "ground_atlas"_s; } -auto ground_traits::atlas_of(const Cell& x) -> const std::shared_ptr<Atlas>& { return x.atlas; } -auto ground_traits::atlas_of(Cell& x) -> std::shared_ptr<Atlas>& { return x.atlas; } +auto ground_traits::atlas_of(const Cell& x) -> const bptr<Atlas>& { return x.atlas; } +auto ground_traits::atlas_of(Cell& x) -> bptr<Atlas>& { return x.atlas; } StringView ground_traits::name_of(const Cell& x) { return x.name; } String& ground_traits::name_of(Cell& x) { return x.name; } @@ -30,17 +31,17 @@ void ground_traits::atlas_list(Storage& s) auto ground_traits::make_invalid_atlas(Storage& s) -> Cell { fm_debug_assert(!s.invalid_atlas); - auto atlas = std::make_shared<Atlas>( + auto atlas = bptr<Atlas>{InPlace, ground_def{loader.INVALID, Vector2ub{1,1}, pass_mode::pass}, - loader.make_error_texture(Vector2ui(tile_size_xy))); + loader.make_error_texture(Vector2ui(tile_size_xy))}; return ground_cell{ atlas, atlas->name(), atlas->num_tiles2(), atlas->pass_mode() }; } -auto ground_traits::make_atlas(StringView name, const Cell& c) -> std::shared_ptr<Atlas> +auto ground_traits::make_atlas(StringView name, const Cell& c) -> bptr<Atlas> { auto def = ground_def{name, c.size, c.pass}; auto tex = loader.texture(loader.GROUND_TILESET_PATH, name); - auto atlas = std::make_shared<Atlas>(def, tex); + auto atlas = bptr<Atlas>{InPlace, def, tex}; return atlas; } diff --git a/loader/ground-traits.hpp b/loader/ground-traits.hpp index f3fff4ee..c4d9b905 100644 --- a/loader/ground-traits.hpp +++ b/loader/ground-traits.hpp @@ -1,6 +1,6 @@ #pragma once #include "atlas-loader-fwd.hpp" -#include <memory> +#include "compat/borrowed-ptr.hpp" namespace floormat { struct ground_cell; class ground_atlas; } @@ -14,13 +14,13 @@ template<> struct atlas_loader_traits<ground_atlas> using Storage = atlas_storage<ground_atlas, Self>; static StringView loader_name(); - static const std::shared_ptr<Atlas>& atlas_of(const Cell& x); - static std::shared_ptr<Atlas>& atlas_of(Cell& x); + static const bptr<Atlas>& atlas_of(const Cell& x); + static bptr<Atlas>& atlas_of(Cell& x); static StringView name_of(const Cell& x); static String& name_of(Cell& x); static void atlas_list(Storage& s); static Cell make_invalid_atlas(Storage& st); - static std::shared_ptr<Atlas> make_atlas(StringView name, const Cell& c); + static bptr<Atlas> make_atlas(StringView name, const Cell& c); static Optional<Cell> make_cell(StringView name); }; diff --git a/loader/impl.cpp b/loader/impl.cpp index cc37e8c8..86bd76d5 100644 --- a/loader/impl.cpp +++ b/loader/impl.cpp @@ -1,5 +1,6 @@ #include "impl.hpp" #include "compat/assert.hpp" +#include "compat/borrowed-ptr.inl" #include "ground-traits.hpp" #include "ground-cell.hpp" #include "wall-traits.hpp" diff --git a/loader/impl.hpp b/loader/impl.hpp index b873ba82..9b3ab1c0 100644 --- a/loader/impl.hpp +++ b/loader/impl.hpp @@ -1,9 +1,9 @@ #pragma once -#include "compat/safe-ptr.hpp" #include "loader/loader.hpp" +#include "compat/safe-ptr.hpp" +#include "compat/borrowed-ptr-fwd.hpp" #include "atlas-loader-fwd.hpp" #include <tsl/robin_map.h> -#include <memory> #include <vector> #include <Corrade/Containers/Optional.h> #include <Corrade/Containers/StringView.h> @@ -45,26 +45,26 @@ struct loader_impl final : loader_ // >-----> ground >-----> [[nodiscard]] static atlas_loader<class ground_atlas>* make_ground_atlas_loader(); safe_ptr<atlas_loader<class ground_atlas>> _ground_loader{ make_ground_atlas_loader() }; - const std::shared_ptr<class ground_atlas>& ground_atlas(StringView filename, loader_policy policy) noexcept(false) override; + const bptr<class ground_atlas>& ground_atlas(StringView filename, loader_policy policy) noexcept(false) override; ArrayView<const ground_cell> ground_atlas_list() noexcept(false) override; const ground_cell& invalid_ground_atlas() override; - std::shared_ptr<class ground_atlas> get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexcept(false) override; + bptr<class ground_atlas> get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexcept(false) override; // >-----> walls >-----> [[nodiscard]] static atlas_loader<class wall_atlas>* make_wall_atlas_loader(); safe_ptr<atlas_loader<class wall_atlas>> _wall_loader{ make_wall_atlas_loader() }; - const std::shared_ptr<class wall_atlas>& wall_atlas(StringView name, loader_policy policy) override; + const bptr<class wall_atlas>& wall_atlas(StringView name, loader_policy policy) override; ArrayView<const wall_cell> wall_atlas_list() override; - std::shared_ptr<class wall_atlas> get_wall_atlas(StringView filename) noexcept(false) override; + bptr<class wall_atlas> get_wall_atlas(StringView filename) noexcept(false) override; const wall_cell& invalid_wall_atlas() override; // >-----> anim >-----> [[nodiscard]] static atlas_loader<class anim_atlas>* make_anim_atlas_loader(); safe_ptr<atlas_loader<class anim_atlas>> _anim_loader{ make_anim_atlas_loader() }; ArrayView<const anim_cell> anim_atlas_list() override; - std::shared_ptr<class anim_atlas> anim_atlas(StringView name, StringView dir, loader_policy policy) noexcept(false) override; + bptr<class anim_atlas> anim_atlas(StringView name, StringView dir, loader_policy policy) noexcept(false) override; const anim_cell& invalid_anim_atlas() override; - std::shared_ptr<class anim_atlas> get_anim_atlas(StringView path) noexcept(false) override; + bptr<class anim_atlas> get_anim_atlas(StringView path) noexcept(false) override; // >-----> scenery >-----> [[nodiscard]] static atlas_loader<struct scenery_proto>* make_scenery_atlas_loader(); @@ -77,7 +77,7 @@ struct loader_impl final : loader_ // >-----> vobjs >-----> tsl::robin_map<StringView, const struct vobj_cell*> vobj_atlas_map; std::vector<struct vobj_cell> vobjs; - std::shared_ptr<class anim_atlas> make_vobj_anim_atlas(StringView name, StringView image_filename); + bptr<class anim_atlas> make_vobj_anim_atlas(StringView name, StringView image_filename); const struct vobj_cell& vobj(StringView name) override; ArrayView<const struct vobj_cell> vobj_list() override; void get_vobj_list(); diff --git a/loader/loader.hpp b/loader/loader.hpp index cf2bbc8a..0ee08148 100644 --- a/loader/loader.hpp +++ b/loader/loader.hpp @@ -1,8 +1,8 @@ #pragma once #include "compat/defs.hpp" +#include "compat/borrowed-ptr-fwd.hpp" #include "src/pass-mode.hpp" #include "loader/policy.hpp" -#include <memory> #include <cr/StringView.h> //namespace Magnum { using Vector2ub = Math::Vector2<unsigned char>; } @@ -35,9 +35,9 @@ struct loader_ virtual Trade::ImageData2D make_error_texture(Vector2ui size, Vector4ub color) = 0; virtual Trade::ImageData2D texture(StringView prefix, StringView filename) noexcept(false) = 0; - virtual const std::shared_ptr<class ground_atlas>& ground_atlas(StringView filename, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0; - virtual const std::shared_ptr<class wall_atlas>& wall_atlas(StringView name, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0; - virtual std::shared_ptr<class anim_atlas> anim_atlas(StringView name, StringView dir, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0; + virtual const bptr<class ground_atlas>& ground_atlas(StringView filename, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0; + virtual const bptr<class wall_atlas>& wall_atlas(StringView name, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0; + virtual bptr<class anim_atlas> anim_atlas(StringView name, StringView dir, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0; virtual const struct scenery_proto& scenery(StringView name, loader_policy policy = loader_policy::DEFAULT) = 0; virtual ArrayView<const ground_cell> ground_atlas_list() noexcept(false) = 0; @@ -58,11 +58,11 @@ struct loader_ virtual const scenery_cell& invalid_scenery_atlas() = 0; /** \deprecated{internal use only}*/ [[nodiscard]] - virtual std::shared_ptr<class ground_atlas> get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexcept(false) = 0; + virtual bptr<class ground_atlas> get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexcept(false) = 0; /** \deprecated{internal use only}*/ [[nodiscard]] - virtual std::shared_ptr<class wall_atlas> get_wall_atlas(StringView name) noexcept(false) = 0; + virtual bptr<class wall_atlas> get_wall_atlas(StringView name) noexcept(false) = 0; /** \deprecated{internal use only}*/ [[nodiscard]] - virtual std::shared_ptr<class anim_atlas> get_anim_atlas(StringView path) noexcept(false) = 0; + virtual bptr<class anim_atlas> get_anim_atlas(StringView path) noexcept(false) = 0; /** \deprecated{internal use only}*/ [[nodiscard]] virtual struct scenery_proto get_scenery(StringView filename, const scenery_cell& c) noexcept(false) = 0; diff --git a/loader/scenery-traits.hpp b/loader/scenery-traits.hpp index 37aaa199..0d7387c7 100644 --- a/loader/scenery-traits.hpp +++ b/loader/scenery-traits.hpp @@ -1,6 +1,6 @@ #pragma once #include "atlas-loader-fwd.hpp" -#include <memory> +#include "compat/borrowed-ptr.hpp" namespace floormat { struct scenery_cell; struct scenery_proto; } diff --git a/loader/vobj-cell.hpp b/loader/vobj-cell.hpp index 1fa22ea2..c5882624 100644 --- a/loader/vobj-cell.hpp +++ b/loader/vobj-cell.hpp @@ -1,6 +1,6 @@ #pragma once #include <cr/String.h> -#include <memory> +#include "compat/borrowed-ptr.hpp" namespace floormat { @@ -9,7 +9,7 @@ class anim_atlas; struct vobj_cell final { String name, descr; - std::shared_ptr<class anim_atlas> atlas; + bptr<class anim_atlas> atlas; }; } // namespace floormat diff --git a/loader/vobj.cpp b/loader/vobj.cpp index f09c9581..789854a4 100644 --- a/loader/vobj.cpp +++ b/loader/vobj.cpp @@ -4,6 +4,7 @@ #include "src/anim-atlas.hpp" #include "src/anim.hpp" #include "compat/exception.hpp" +#include "compat/borrowed-ptr.inl" #include "loader/vobj-cell.hpp" #include <Corrade/Containers/ArrayViewStl.h> #include <Corrade/Containers/StridedArrayView.h> @@ -49,7 +50,7 @@ void adl_serializer<vobj>::from_json(const json& j, vobj& val) namespace floormat::loader_detail { -std::shared_ptr<class anim_atlas> loader_impl::make_vobj_anim_atlas(StringView name, StringView image_filename) +bptr<class anim_atlas> loader_impl::make_vobj_anim_atlas(StringView name, StringView image_filename) { auto tex = texture(VOBJ_PATH, image_filename); anim_def def; @@ -72,7 +73,7 @@ std::shared_ptr<class anim_atlas> loader_impl::make_vobj_anim_atlas(StringView n def.groups = Array<anim_group>{1}; def.groups[0] = move(group); } - auto atlas = std::make_shared<class anim_atlas>(name, tex, move(def)); + auto atlas = bptr<class anim_atlas>(InPlace, name, tex, move(def)); return atlas; } diff --git a/loader/wall-atlas.cpp b/loader/wall-atlas.cpp index 8b2acb09..dbf71c47 100644 --- a/loader/wall-atlas.cpp +++ b/loader/wall-atlas.cpp @@ -3,6 +3,7 @@ #include "loader/wall-cell.hpp" #include "loader/wall-traits.hpp" #include "loader/atlas-loader.inl" +#include "compat/borrowed-ptr.inl" #include <Corrade/Containers/Array.h> #include <Corrade/Containers/StringIterable.h> #include <Magnum/Trade/ImageData.h> @@ -12,8 +13,7 @@ namespace floormat::loader_detail { template class atlas_loader<class wall_atlas>; -std::shared_ptr<class wall_atlas> -loader_impl::get_wall_atlas(StringView name) noexcept(false) +bptr<class wall_atlas> loader_impl::get_wall_atlas(StringView name) noexcept(false) { return _wall_loader->make_atlas(name, {}); } @@ -33,7 +33,7 @@ const wall_cell& loader_impl::invalid_wall_atlas() return _wall_loader->get_invalid_atlas(); } -const std::shared_ptr<class wall_atlas>& +const bptr<class wall_atlas>& loader_impl::wall_atlas(StringView filename, loader_policy policy) noexcept(false) { return _wall_loader->get_atlas(filename, policy); diff --git a/loader/wall-cell.cpp b/loader/wall-cell.cpp index 8870b891..a385163b 100644 --- a/loader/wall-cell.cpp +++ b/loader/wall-cell.cpp @@ -1,5 +1,6 @@ #include "wall-cell.hpp" #include "compat/exception.hpp" +#include "compat/borrowed-ptr.inl" #include "serialize/json-helper.hpp" #include "serialize/corrade-string.hpp" #include "serialize/corrade-array.hpp" diff --git a/loader/wall-cell.hpp b/loader/wall-cell.hpp index 541a8339..690896c2 100644 --- a/loader/wall-cell.hpp +++ b/loader/wall-cell.hpp @@ -1,5 +1,5 @@ #pragma once -#include <memory> +#include "compat/borrowed-ptr.hpp" #include <Corrade/Containers/String.h> namespace floormat { @@ -8,7 +8,7 @@ class wall_atlas; struct wall_cell { - std::shared_ptr<wall_atlas> atlas; + bptr<wall_atlas> atlas; String name; static Array<wall_cell> load_atlases_from_json(); diff --git a/loader/wall-traits.cpp b/loader/wall-traits.cpp index 07ff7d9c..e5cd7f40 100644 --- a/loader/wall-traits.cpp +++ b/loader/wall-traits.cpp @@ -6,6 +6,7 @@ #include "src/wall-atlas.hpp" #include "compat/array-size.hpp" #include "compat/exception.hpp" +#include "compat/borrowed-ptr.inl" #include <cr/StringView.h> #include <cr/Optional.h> #include <mg/ImageData.h> @@ -15,8 +16,8 @@ namespace floormat::loader_detail { using wall_traits = atlas_loader_traits<wall_atlas>; StringView wall_traits::loader_name() { return "wall_atlas"_s; } -auto wall_traits::atlas_of(const Cell& x) -> const std::shared_ptr<Atlas>& { return x.atlas; } -auto wall_traits::atlas_of(Cell& x) -> std::shared_ptr<Atlas>& { return x.atlas; } +auto wall_traits::atlas_of(const Cell& x) -> const bptr<Atlas>& { return x.atlas; } +auto wall_traits::atlas_of(Cell& x) -> bptr<Atlas>& { return x.atlas; } StringView wall_traits::name_of(const Cell& x) { return x.name; } String& wall_traits::name_of(Cell& x) { return x.name; } @@ -33,7 +34,7 @@ auto wall_traits::make_invalid_atlas(Storage& s) -> Cell constexpr auto name = loader_::INVALID; constexpr auto frame_size = Vector2ui{tile_size_xy, tile_size_z}; - auto a = std::make_shared<class wall_atlas>( + auto a = bptr<class wall_atlas>(InPlace, wall_atlas_def { Wall::Info{.name = name, .depth = 8}, array<Wall::Frame>({{ {}, frame_size}, }), @@ -46,7 +47,7 @@ auto wall_traits::make_invalid_atlas(Storage& s) -> Cell return { .atlas = move(a), .name = name, }; } -auto wall_traits::make_atlas(StringView name, const Cell&) -> std::shared_ptr<Atlas> +auto wall_traits::make_atlas(StringView name, const Cell&) -> bptr<Atlas> { char file_buf[fm_FILENAME_MAX], json_buf[fm_FILENAME_MAX]; auto file = loader.make_atlas_path(file_buf, loader.WALL_TILESET_PATH, name); @@ -57,7 +58,7 @@ auto wall_traits::make_atlas(StringView name, const Cell&) -> std::shared_ptr<At fm_soft_assert(name == def.header.name); fm_soft_assert(!def.frames.isEmpty()); auto tex = loader.texture(""_s, file); - auto atlas = std::make_shared<class wall_atlas>(move(def), file, tex); + auto atlas = bptr<class wall_atlas>(InPlace, move(def), file, tex); return atlas; } diff --git a/loader/wall-traits.hpp b/loader/wall-traits.hpp index 9233cb97..587555ef 100644 --- a/loader/wall-traits.hpp +++ b/loader/wall-traits.hpp @@ -1,6 +1,6 @@ #pragma once #include "atlas-loader-fwd.hpp" -#include <memory> +#include "compat/borrowed-ptr.hpp" namespace floormat { struct wall_cell; class wall_atlas; } @@ -14,13 +14,13 @@ template<> struct atlas_loader_traits<wall_atlas> using Storage = atlas_storage<wall_atlas, Self>; static StringView loader_name(); - static const std::shared_ptr<Atlas>& atlas_of(const Cell& x); - static std::shared_ptr<Atlas>& atlas_of(Cell& x); + static const bptr<Atlas>& atlas_of(const Cell& x); + static bptr<Atlas>& atlas_of(Cell& x); static StringView name_of(const Cell& x); static String& name_of(Cell& x); static void atlas_list(Storage& st); static Cell make_invalid_atlas(Storage& st); - static std::shared_ptr<Atlas> make_atlas(StringView name, const Cell& c); + static bptr<Atlas> make_atlas(StringView name, const Cell& c); static Optional<Cell> make_cell(StringView name); }; diff --git a/serialize/ground-atlas.cpp b/serialize/ground-atlas.cpp index d563bb05..49bcf7b9 100644 --- a/serialize/ground-atlas.cpp +++ b/serialize/ground-atlas.cpp @@ -1,5 +1,6 @@ #include "ground-atlas.hpp" #include "compat/exception.hpp" +#include "compat/borrowed-ptr.inl" #include "src/ground-atlas.hpp" #include "src/ground-def.hpp" #include "loader/loader.hpp" @@ -49,15 +50,15 @@ void adl_serializer<ground_cell>::from_json(const json& j, ground_cell& val) } -void adl_serializer<std::shared_ptr<ground_atlas>>::to_json(json& j, const std::shared_ptr<const ground_atlas>& x) +void adl_serializer<bptr<ground_atlas>>::to_json(json& j, const bptr<const ground_atlas>& x) { j = std::tuple<StringView, Vector2ub, pass_mode>{x->name(), x->num_tiles2(), x->pass_mode()}; } -void adl_serializer<std::shared_ptr<ground_atlas>>::from_json(const json& j, std::shared_ptr<ground_atlas>& val) +void adl_serializer<bptr<ground_atlas>>::from_json(const json& j, bptr<ground_atlas>& val) { ground_def def = j; - val = std::make_shared<ground_atlas>(move(def), loader.texture(loader.GROUND_TILESET_PATH, def.name)); + val = bptr<ground_atlas>(InPlace, move(def), loader.texture(loader.GROUND_TILESET_PATH, def.name)); } } // namespace nlohmann diff --git a/serialize/ground-atlas.hpp b/serialize/ground-atlas.hpp index 20b50537..e74792a5 100644 --- a/serialize/ground-atlas.hpp +++ b/serialize/ground-atlas.hpp @@ -1,4 +1,5 @@ #pragma once +#include "compat/borrowed-ptr.hpp" #include <nlohmann/json_fwd.hpp> namespace floormat { @@ -18,9 +19,9 @@ struct adl_serializer<floormat::ground_def> final { }; template<> -struct adl_serializer<std::shared_ptr<floormat::ground_atlas>> final { - static void to_json(json& j, const std::shared_ptr<const floormat::ground_atlas>& x); - static void from_json(const json& j, std::shared_ptr<floormat::ground_atlas>& x); +struct adl_serializer<floormat::bptr<floormat::ground_atlas>> final { + static void to_json(json& j, const floormat::bptr<const floormat::ground_atlas>& x); + static void from_json(const json& j, floormat::bptr<floormat::ground_atlas>& x); }; template<> diff --git a/serialize/old-savegame.cpp b/serialize/old-savegame.cpp index 073756d2..8e4998b0 100644 --- a/serialize/old-savegame.cpp +++ b/serialize/old-savegame.cpp @@ -18,7 +18,6 @@ #include <cerrno> #include <cstring> #include <concepts> -#include <memory> #include <vector> @@ -80,7 +79,9 @@ constexpr inline uint8_t meta_short_scenery_bit = highbits<uint8_t, 1, 0>; } // namespace -template<typename T> concept object_subtype = std::is_base_of_v<object, T> || std::is_base_of_v<object_proto, T>; +template<typename T> concept object_subtype = requires { + requires std::is_base_of_v<object, T> || std::is_base_of_v<object_proto, T>; +}; enum : tilemeta { meta_ground = 1 << 2, diff --git a/serialize/savegame.cpp b/serialize/savegame.cpp index f7893094..d279bd9e 100644 --- a/serialize/savegame.cpp +++ b/serialize/savegame.cpp @@ -5,6 +5,7 @@ #include "compat/strerror.hpp" #include "compat/hash.hpp" #include "compat/exception.hpp" +#include "compat/borrowed-ptr.inl" #include "src/ground-atlas.hpp" #include "src/wall-atlas.hpp" @@ -23,7 +24,6 @@ #include <cstdio> #include <compare> #include <concepts> -#include <memory> #include <vector> #include <algorithm> #include <Corrade/Utility/Path.h> @@ -402,7 +402,7 @@ struct writer final : visitor_<writer, true, true> template<typename F> static void visit(const local_coords& pt, F&& f) { visit(pt.to_index(), f); } template<typename F> void visit(StringView name, F&& f) { visit(intern_string(name), f); } - template<typename F> void visit(qual<std::shared_ptr<anim_atlas>>& a, atlas_type type, F&& f) + template<typename F> void visit(qual<bptr<anim_atlas>>& a, atlas_type type, F&& f) { atlasid id = intern_atlas(a, type); visit(id, f); } template<typename F> void write_scenery_proto(const scenery& obj, F&& f) @@ -483,7 +483,7 @@ ok: void(); visit(intern_string(name), f); } - template<typename T> [[nodiscard]] atlasid intern_atlas(const std::shared_ptr<T>& atlas_, atlas_type type) + template<typename T> [[nodiscard]] atlasid intern_atlas(const bptr<T>& atlas_, atlas_type type) { const void* atlas = atlas_.get(); atlas_array.reserve(vector_initial_size); @@ -512,7 +512,7 @@ ok: void(); } } - template<typename T> atlasid maybe_intern_atlas(const std::shared_ptr<T>& atlas, atlas_type type) + template<typename T> atlasid maybe_intern_atlas(const bptr<T>& atlas, atlas_type type) { if (!atlas) return null<atlasid>; @@ -533,7 +533,7 @@ ok: void(); template<typename F> void serialize_objects_(chunk& c, F&& f) { uint32_t count = 0; - for (const std::shared_ptr<object>& obj : c.objects()) + for (const bptr<object>& obj : c.objects()) { if (obj->ephemeral) continue; @@ -541,7 +541,7 @@ ok: void(); } visit(count, f); - for (const std::shared_ptr<object>& obj : c.objects()) + for (const bptr<object>& obj : c.objects()) { fm_assert(obj != nullptr); if (obj->ephemeral) @@ -798,7 +798,7 @@ struct reader final : visitor_<reader<IsNewest>, false, IsNewest> template<typename F> static void visit(local_coords& pt, F&& f) { uint8_t i; f(i); pt = local_coords{i}; } - template<typename F> void visit(std::shared_ptr<anim_atlas>& a, atlas_type type, F&& f) + template<typename F> void visit(bptr<anim_atlas>& a, atlas_type type, F&& f) { atlasid id = (atlasid)-1; f(id); @@ -819,7 +819,7 @@ struct reader final : visitor_<reader<IsNewest>, false, IsNewest> } template<typename F> - void read_scenery(std::shared_ptr<scenery>& ret, const object_proto& pʹ, const object_header_s& h, F&& f) + void read_scenery(bptr<scenery>& ret, const object_proto& pʹ, const object_header_s& h, F&& f) { const auto coord = global_coords{h.ch->coord(), h.tile}; auto sc_type = scenery_type::none; @@ -852,7 +852,7 @@ ok: } template<typename Obj, typename Proto, typename Header> - std::shared_ptr<object> make_object(const object_header_s& h0, object_proto&& p0, Header&& h, auto&& f) + bptr<object> make_object(const object_header_s& h0, object_proto&& p0, Header&& h, auto&& f) { fm_soft_assert(h0.id != 0); @@ -867,7 +867,7 @@ ok: template<typename F> void read_object(chunk* ch, F&& f) { - std::shared_ptr<object> obj; + bptr<object> obj; object_id id = 0; auto type = object_type::none; local_coords tile; @@ -899,7 +899,7 @@ ok: obj = make_object<light, light_proto, std::nullptr_t>(s, move(p), {}, f); goto ok; case object_type::scenery: { - std::shared_ptr<scenery> objʹ; + bptr<scenery> objʹ; read_scenery(objʹ, move(p), s, f); obj = move(objʹ); goto ok; diff --git a/serialize/scenery.cpp b/serialize/scenery.cpp index edcd57c7..e278d408 100644 --- a/serialize/scenery.cpp +++ b/serialize/scenery.cpp @@ -1,6 +1,7 @@ #include "scenery.hpp" #include "compat/overloaded.hpp" #include "compat/exception.hpp" +#include "compat/borrowed-ptr.inl" #include "src/anim-atlas.hpp" #include "compat/assert.hpp" #include "loader/loader.hpp" diff --git a/serialize/tile.cpp b/serialize/tile.cpp index cd9064a8..1cbf8d1b 100644 --- a/serialize/tile.cpp +++ b/serialize/tile.cpp @@ -1,7 +1,8 @@ -#include "serialize/tile.hpp" +#include "tile.hpp" +#include "ground-atlas.hpp" +#include "compat/borrowed-ptr.inl" #include "src/tile.hpp" #include "src/global-coords.hpp" -#include "serialize/ground-atlas.hpp" #include "src/ground-atlas.hpp" #include <tuple> #include <nlohmann/json.hpp> @@ -10,8 +11,6 @@ namespace floormat { using nlohmann::json; -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(tile_image_proto, atlas, variant) - inline void to_json(json& j, const tile_image_ref& val) { j = tile_image_proto(val); } inline void from_json(const json& j, tile_image_ref& val) { val = tile_image_proto(j); } @@ -28,13 +27,27 @@ inline void from_json(const json& j, global_coords& coord) { std::tuple<chunk_co } // namespace floormat -using namespace floormat; - namespace nlohmann { +using namespace floormat; + void adl_serializer<tile_image_ref>::to_json(json& j, const tile_image_ref& val) { using nlohmann::to_json; if (val.atlas) to_json(j, val); else j = nullptr; } void adl_serializer<tile_image_ref>::from_json(const json& j, tile_image_ref& val) { using nlohmann::from_json; if (j.is_null()) val = {}; else from_json(j, val); } +void adl_serializer<tile_image_proto>::to_json(json& j, const floormat::tile_image_proto& val) +{ + using nlohmann::to_json; + j["atlas"] = val.atlas; + j["variant"] = val.variant; +} + +void adl_serializer<tile_image_proto>::from_json(const json& j, floormat::tile_image_proto& val) +{ + using nlohmann::from_json; + val.atlas = j["atlas"]; + val.variant = j["variant"]; +} + void adl_serializer<local_coords>::to_json(json& j, const local_coords& val) { using nlohmann::to_json; to_json(j, local_coords_{val.x, val.y}); } void adl_serializer<local_coords>::from_json(const json& j, local_coords& val) { using nlohmann::from_json; local_coords_ proxy{}; from_json(j, proxy); val = {proxy.x, proxy.y}; } diff --git a/serialize/tile.hpp b/serialize/tile.hpp index ded1a479..239fc41f 100644 --- a/serialize/tile.hpp +++ b/serialize/tile.hpp @@ -20,6 +20,12 @@ struct adl_serializer<floormat::tile_image_ref> { }; template<> +struct adl_serializer<floormat::tile_image_proto> { + static void to_json(json& j, const floormat::tile_image_proto& val); + static void from_json(const json& j, floormat::tile_image_proto& val); +}; + +template<> struct adl_serializer<floormat::local_coords> { static void to_json(json& j, const floormat::local_coords& val); static void from_json(const json& j, floormat::local_coords& val); diff --git a/serialize/wall-atlas.hpp b/serialize/wall-atlas.hpp index 5ce61c74..29539350 100644 --- a/serialize/wall-atlas.hpp +++ b/serialize/wall-atlas.hpp @@ -1,6 +1,5 @@ #pragma once #include "src/wall-atlas.hpp" -#include <memory> #include <Corrade/Containers/Array.h> #include <nlohmann/json_fwd.hpp> diff --git a/shaders/lightmap.cpp b/shaders/lightmap.cpp index 69702624..01a8beb7 100644 --- a/shaders/lightmap.cpp +++ b/shaders/lightmap.cpp @@ -1,5 +1,6 @@ #include "shaders/lightmap.hpp" #include "compat/assert.hpp" +#include "compat/borrowed-ptr.inl" #include "src/tile-defs.hpp" #include "src/chunk.hpp" #include "src/tile-bbox.hpp" diff --git a/src/anim-atlas.hpp b/src/anim-atlas.hpp index 2803566f..cf9937ba 100644 --- a/src/anim-atlas.hpp +++ b/src/anim-atlas.hpp @@ -3,6 +3,7 @@ #include "rotation.hpp" #include "anim.hpp" #include "src/quads.hpp" +#include "compat/borrowed-ptr.hpp" #include <array> #include <Corrade/Containers/BitArray.h> #include <Corrade/Containers/String.h> @@ -12,7 +13,7 @@ namespace floormat { -class anim_atlas final +class anim_atlas final : public bptr_base { using texcoords = Quads::texcoords; using quad = Quads::quad; @@ -31,7 +32,7 @@ class anim_atlas final public: anim_atlas() noexcept; anim_atlas(String name, const ImageView2D& tex, anim_def info); - ~anim_atlas() noexcept; + ~anim_atlas() noexcept override; anim_atlas(anim_atlas&&) noexcept; anim_atlas& operator=(anim_atlas&&) noexcept; diff --git a/src/chunk-collision.cpp b/src/chunk-collision.cpp index a393554e..ec6f4ff2 100644 --- a/src/chunk-collision.cpp +++ b/src/chunk-collision.cpp @@ -41,7 +41,7 @@ bool add_holes_from_chunk(chunk::RTree& rtree, chunk& c, Vector2b chunk_offset) constexpr auto max_bbox_size = Vector2i{0x100}; constexpr auto chunk_min = -iTILE_SIZE2/2 - max_bbox_size/2, chunk_max = TILE_MAX_DIM * iTILE_SIZE2 - iTILE_SIZE2 / 2 + max_bbox_size; - for (const std::shared_ptr<object>& eʹʹ : c.objects()) + for (const bptr<object>& eʹʹ : c.objects()) { auto& eʹ = *eʹʹ; if (eʹ.type() != object_type::hole) [[likely]] @@ -185,7 +185,7 @@ void chunk::ensure_passability() noexcept filter_through_holes(*_rtree, id, min, max, has_holes); } } - for (const std::shared_ptr<object>& eʹ : objects()) + for (const bptr<object>& eʹ : objects()) { if (eʹ->updates_passability()) continue; @@ -215,19 +215,19 @@ bool chunk::_bbox_for_scenery(const object& s, bbox& value) noexcept return _bbox_for_scenery(s, s.coord.local(), s.offset, s.bbox_offset, s.bbox_size, value); } -void chunk::_remove_bbox_static_(const std::shared_ptr<object>& e) +void chunk::_remove_bbox_static_(const bptr<object>& e) { mark_passability_modified(); e->maybe_mark_neighbor_chunks_modified(); } -void chunk::_add_bbox_static_(const std::shared_ptr<object>& e) +void chunk::_add_bbox_static_(const bptr<object>& e) { mark_passability_modified(); e->maybe_mark_neighbor_chunks_modified(); } -void chunk::_remove_bbox_(const std::shared_ptr<object>& e, const bbox& x, bool upd, bool is_dynamic) +void chunk::_remove_bbox_(const bptr<object>& e, const bbox& x, bool upd, bool is_dynamic) { if (!is_dynamic || upd) _remove_bbox_static(e, x); @@ -242,7 +242,7 @@ void chunk::_remove_bbox_dynamic(const bbox& x) //Debug{} << "bbox <<< dynamic" << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); } -void chunk::_remove_bbox_static(const std::shared_ptr<object>& e, [[maybe_unused]] const bbox& x) +void chunk::_remove_bbox_static(const bptr<object>& e, [[maybe_unused]] const bbox& x) { _remove_bbox_static_(e); //Debug{} << "bbox <<< static " << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); @@ -255,13 +255,13 @@ void chunk::_add_bbox_dynamic(const bbox& x) //Debug{} << "bbox >>> dynamic" << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); } -void chunk::_add_bbox_static(const std::shared_ptr<object>& e, [[maybe_unused]]const bbox& x) +void chunk::_add_bbox_static(const bptr<object>& e, [[maybe_unused]]const bbox& x) { _add_bbox_static_(e); //Debug{} << "bbox >>> static " << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); } -void chunk::_add_bbox_(const std::shared_ptr<object>& e, const bbox& x, bool upd, bool is_dynamic) +void chunk::_add_bbox_(const bptr<object>& e, const bbox& x, bool upd, bool is_dynamic) { if (!is_dynamic || upd) _add_bbox_static(e, x); @@ -270,7 +270,7 @@ void chunk::_add_bbox_(const std::shared_ptr<object>& e, const bbox& x, bool upd } template<bool Dynamic> -void chunk::_replace_bbox_impl(const std::shared_ptr<object>& e, const bbox& x0, const bbox& x1, bool b0, bool b1) +void chunk::_replace_bbox_impl(const bptr<object>& e, const bbox& x0, const bbox& x1, bool b0, bool b1) { if (_pass_modified) return; @@ -313,12 +313,12 @@ void chunk::_replace_bbox_dynamic(const bbox& x0, const bbox& x, bool b0, bool b _replace_bbox_impl<true>(nullptr, x0, x, b0, b); } -void chunk::_replace_bbox_static(const std::shared_ptr<object>& e, const bbox& x0, const bbox& x, bool b0, bool b) +void chunk::_replace_bbox_static(const bptr<object>& e, const bbox& x0, const bbox& x, bool b0, bool b) { _replace_bbox_impl<false>(e, x0, x, b0, b); } -void chunk::_replace_bbox_(const std::shared_ptr<object>& e, const bbox& x0, const bbox& x, bool b0, bool b, bool upd, bool is_dynamic) +void chunk::_replace_bbox_(const bptr<object>& e, const bbox& x0, const bbox& x, bool b0, bool b, bool upd, bool is_dynamic) { if (!is_dynamic || upd) _replace_bbox_static(e, x0, x, b0, b); diff --git a/src/chunk-render.cpp b/src/chunk-render.cpp index a2e1032a..421d98d2 100644 --- a/src/chunk-render.cpp +++ b/src/chunk-render.cpp @@ -3,6 +3,7 @@ #include "ground-atlas.hpp" #include "quads.hpp" #include "shaders/shader.hpp" +#include "compat/borrowed-ptr.inl" #include <algorithm> #include <Corrade/Containers/Array.h> #include <Corrade/Containers/ArrayViewStl.h> diff --git a/src/chunk-walls.cpp b/src/chunk-walls.cpp index fb4b6560..b3ed0d8c 100644 --- a/src/chunk-walls.cpp +++ b/src/chunk-walls.cpp @@ -3,6 +3,7 @@ #include "quads.hpp" #include "wall-atlas.hpp" #include "shaders/shader.hpp" +#include "compat/borrowed-ptr.inl" #include <Corrade/Containers/ArrayViewStl.h> #include <Corrade/Containers/Pair.h> #include <Corrade/Containers/Optional.h> diff --git a/src/chunk.cpp b/src/chunk.cpp index 2ecf668b..ac529090 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -4,6 +4,7 @@ #include "log.hpp" #include "RTree.h" #include "compat/non-const.hpp" +#include "ground-atlas.hpp" #include <algorithm> #include <cr/GrowableArray.h> #include <cr/Optional.h> @@ -136,7 +137,7 @@ void chunk::sort_objects() std::sort(_objects.begin(), _objects.end(), object_id_lessp); } -void chunk::add_object_pre(const std::shared_ptr<object>& e) +void chunk::add_object_pre(const bptr<object>& e) { fm_assert(!e->gone); fm_assert(&*e->c == this); @@ -152,7 +153,7 @@ void chunk::add_object_pre(const std::shared_ptr<object>& e) } } -void chunk::add_object_unsorted(const std::shared_ptr<object>& e) +void chunk::add_object_unsorted(const bptr<object>& e) { add_object_pre(e); _objects_sorted = false; @@ -160,7 +161,7 @@ void chunk::add_object_unsorted(const std::shared_ptr<object>& e) arrayAppend(_objects, e); } -size_t chunk::add_objectʹ(const std::shared_ptr<object>& e) +size_t chunk::add_objectʹ(const bptr<object>& e) { fm_assert(_objects_sorted); add_object_pre(e); @@ -172,7 +173,7 @@ size_t chunk::add_objectʹ(const std::shared_ptr<object>& e) return i; } -void chunk::add_object(const std::shared_ptr<object>& e) { (void)add_objectʹ(e); } +void chunk::add_object(const bptr<object>& e) { (void)add_objectʹ(e); } void chunk::on_teardown() // NOLINT(*-make-member-function-const) { @@ -186,26 +187,30 @@ void chunk::remove_object(size_t i) fm_assert(_objects_sorted); fm_debug_assert(i < _objects.size()); - const auto& eʹ = _objects[i]; - auto& e = *eʹ; - fm_assert(e.c == this); - fm_assert(!e.gone); - - const auto dyn = e.is_dynamic(), upd = e.updates_passability(); - if (!dyn) - mark_scenery_modified(); - - if (!_pass_modified) [[likely]] + auto eʹ = _objects[i]; { - if (!dyn || upd) - _remove_bbox_static_(eʹ); - else if (bbox bb; _bbox_for_scenery(e, bb)) - _remove_bbox_dynamic(bb); + auto& e = *eʹ; + fm_assert(e.c == this); + fm_assert(!e.gone); + + const auto dyn = e.is_dynamic(), upd = e.updates_passability(); + if (!dyn) + mark_scenery_modified(); + + if (!_pass_modified) [[likely]] + { + if (!dyn || upd) + _remove_bbox_static_(eʹ); + else if (bbox bb; _bbox_for_scenery(e, bb)) + _remove_bbox_dynamic(bb); + } + } arrayRemove(_objects, i); + //eʹ.destroy(); } -ArrayView<const std::shared_ptr<object>> chunk::objects() const +ArrayView<const bptr<object>> chunk::objects() const { fm_assert(_objects_sorted); return _objects; diff --git a/src/chunk.hpp b/src/chunk.hpp index e429f2de..cf41a970 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -102,7 +102,7 @@ public: void on_teardown(); bool is_teardown() const; - ArrayView<const std::shared_ptr<object>> objects() const; + ArrayView<const bptr<object>> objects() const; void remove_object(size_t i); void sort_objects(); @@ -117,21 +117,21 @@ public: private: struct ground_stuff { - std::array<std::shared_ptr<ground_atlas>, TILE_COUNT> atlases; + std::array<bptr<ground_atlas>, TILE_COUNT> atlases; std::array<uint8_t, TILE_COUNT> indexes = {}; std::array<variant_t, TILE_COUNT> variants = {}; }; struct wall_stuff { - std::array<std::shared_ptr<wall_atlas>, 2*TILE_COUNT> atlases; + std::array<bptr<wall_atlas>, 2*TILE_COUNT> atlases; std::array<variant_t, 2*TILE_COUNT> variants; std::array<uint_fast16_t, max_wall_quad_count> mesh_indexes; }; Pointer<ground_stuff> _ground; Pointer<wall_stuff> _walls; - Array<std::shared_ptr<object>> _objects; + Array<bptr<object>> _objects; class world* _world; GL::Mesh ground_mesh{NoCreate}, wall_mesh{NoCreate}, scenery_mesh{NoCreate}; Pointer<RTree> _rtree; @@ -147,10 +147,10 @@ private: void ensure_scenery_buffers(scenery_scratch_buffers bufs); - void add_object(const std::shared_ptr<object>& e); - void add_object_pre(const std::shared_ptr<object>& e); - [[nodiscard]] size_t add_objectʹ(const std::shared_ptr<object>& e); - void add_object_unsorted(const std::shared_ptr<object>& e); + void add_object(const bptr<object>& e); + void add_object_pre(const bptr<object>& e); + [[nodiscard]] size_t add_objectʹ(const bptr<object>& e); + void add_object_unsorted(const bptr<object>& e); struct bbox final { @@ -164,20 +164,20 @@ private: [[nodiscard]] static bool _bbox_for_scenery(const object& s, local_coords local, Vector2b offset, Vector2b bbox_offset, Vector2ub bbox_size, bbox& value) noexcept; - void _remove_bbox_(const std::shared_ptr<object>& e, const bbox& x, bool upd, bool is_dynamic); + void _remove_bbox_(const bptr<object>& e, const bbox& x, bool upd, bool is_dynamic); void _remove_bbox_dynamic(const bbox& x); - void _remove_bbox_static(const std::shared_ptr<object>& e, const bbox& x); - void _remove_bbox_static_(const std::shared_ptr<object>& e); + void _remove_bbox_static(const bptr<object>& e, const bbox& x); + void _remove_bbox_static_(const bptr<object>& e); - void _add_bbox_(const std::shared_ptr<object>& e, const bbox& x, bool upd, bool is_dynamic); + void _add_bbox_(const bptr<object>& e, const bbox& x, bool upd, bool is_dynamic); void _add_bbox_dynamic(const bbox& x); - void _add_bbox_static(const std::shared_ptr<object>& e, const bbox& x); - void _add_bbox_static_(const std::shared_ptr<object>& e); + void _add_bbox_static(const bptr<object>& e, const bbox& x); + void _add_bbox_static_(const bptr<object>& e); - template<bool Dynamic> void _replace_bbox_impl(const std::shared_ptr<object>& e, const bbox& x0, const bbox& x, bool b0, bool b); - void _replace_bbox_(const std::shared_ptr<object>& e, const bbox& x0, const bbox& x, bool b0, bool b, bool upd, bool is_dynamic); + template<bool Dynamic> void _replace_bbox_impl(const bptr<object>& e, const bbox& x0, const bbox& x, bool b0, bool b); + void _replace_bbox_(const bptr<object>& e, const bbox& x0, const bbox& x, bool b0, bool b, bool upd, bool is_dynamic); void _replace_bbox_dynamic(const bbox& x0, const bbox& x, bool b0, bool b); - void _replace_bbox_static(const std::shared_ptr<object>& e, const bbox& x0, const bbox& x, bool b0, bool b); + void _replace_bbox_static(const bptr<object>& e, const bbox& x0, const bbox& x, bool b0, bool b); GL::Mesh make_wall_mesh(); diff --git a/src/critter-script-empty.cpp b/src/critter-script-empty.cpp index 73a714ca..7c269aa4 100644 --- a/src/critter-script-empty.cpp +++ b/src/critter-script-empty.cpp @@ -10,9 +10,9 @@ struct empty_critter_script final : critter_script StringView name() const override; const void* id() const override; - void on_init(const std::shared_ptr<critter>& c) override; - void on_update(const std::shared_ptr<critter>& c, size_t& i, const Ns& dt) override; - void on_destroy(const std::shared_ptr<critter>& c, script_destroy_reason reason) override; + void on_init(const bptr<critter>& c) override; + void on_update(const bptr<critter>& c, size_t& i, const Ns& dt) override; + void on_destroy(const bptr<critter>& c, script_destroy_reason reason) override; void delete_self() noexcept override; }; @@ -28,9 +28,9 @@ const void* empty_critter_script::id() const return &script_name; } -void empty_critter_script::on_init(const std::shared_ptr<critter>&) {} -void empty_critter_script::on_update(const std::shared_ptr<critter>&, size_t&, const Ns&) {} -void empty_critter_script::on_destroy(const std::shared_ptr<critter>&, script_destroy_reason) {} +void empty_critter_script::on_init(const bptr<critter>&) {} +void empty_critter_script::on_update(const bptr<critter>&, size_t&, const Ns&) {} +void empty_critter_script::on_destroy(const bptr<critter>&, script_destroy_reason) {} void empty_critter_script::delete_self() noexcept { } constinit empty_critter_script empty_script_ = {}; diff --git a/src/critter-script-walk.cpp b/src/critter-script-walk.cpp index a10cf15d..2402fe74 100644 --- a/src/critter-script-walk.cpp +++ b/src/critter-script-walk.cpp @@ -23,16 +23,16 @@ struct walk_script final : critter_script StringView name() const override; const void* id() const override; - void on_init(const std::shared_ptr<critter>& c) override; - void on_update(const std::shared_ptr<critter>& c, size_t& i, const Ns& dt) override; - void on_destroy(const std::shared_ptr<critter>& c, script_destroy_reason reason) override; + void on_init(const bptr<critter>& c) override; + void on_update(const bptr<critter>& c, size_t& i, const Ns& dt) override; + void on_destroy(const bptr<critter>& c, script_destroy_reason reason) override; void delete_self() noexcept override; explicit walk_script(point dest); explicit walk_script(psr path); - bool walk_line(const std::shared_ptr<critter>& c, size_t& i, const Ns& dt); - bool walk_path(const std::shared_ptr<critter>& c, size_t& i, const Ns& dt); + bool walk_line(const bptr<critter>& c, size_t& i, const Ns& dt); + bool walk_path(const bptr<critter>& c, size_t& i, const Ns& dt); private: point dest; @@ -43,10 +43,10 @@ private: StringView walk_script::name() const { return "walk"_s; } const void* walk_script::id() const { return &script_name; } -void walk_script::on_destroy(const std::shared_ptr<critter>& c, script_destroy_reason) { c->clear_auto_movement(); } +void walk_script::on_destroy(const bptr<critter>& c, script_destroy_reason) { c->clear_auto_movement(); } void walk_script::delete_self() noexcept { delete this; } -void walk_script::on_init(const std::shared_ptr<critter>& c) +void walk_script::on_init(const bptr<critter>& c) { Debug{} << "| start walking from" << c->position() << "to" << dest; c->moves.AUTO = true; @@ -65,7 +65,7 @@ void walk_script::on_init(const std::shared_ptr<critter>& c) } } -void walk_script::on_update(const std::shared_ptr<critter>& c, size_t& i, const Ns& dt) +void walk_script::on_update(const bptr<critter>& c, size_t& i, const Ns& dt) { if (c->maybe_stop_auto_movement()) goto done; @@ -104,14 +104,14 @@ walk_script::walk_script(psr pathʹ) : fm_assert(!path.empty()); } -bool walk_script::walk_line(const std::shared_ptr<critter>& c, size_t& i, const Ns& dtʹ) +bool walk_script::walk_line(const bptr<critter>& c, size_t& i, const Ns& dtʹ) { auto dt = dtʹ; auto res = c->move_toward(i, dt, dest); return res.blocked || c->position() == dest; } -bool walk_script::walk_path(const std::shared_ptr<critter>& c, size_t& i, const Ns& dtʹ) +bool walk_script::walk_path(const bptr<critter>& c, size_t& i, const Ns& dtʹ) { auto dt = dtʹ; while (dt != Ns{}) diff --git a/src/critter-script.hpp b/src/critter-script.hpp index 2b81a939..9f81228b 100644 --- a/src/critter-script.hpp +++ b/src/critter-script.hpp @@ -1,6 +1,5 @@ #pragma once #include "script.hpp" -#include <memory> #include <cr/Pointer.h> namespace floormat { @@ -16,9 +15,9 @@ struct critter_script : base_script constexpr critter_script() noexcept = default; ~critter_script() noexcept override; - virtual void on_init(const std::shared_ptr<critter>& c) = 0; - virtual void on_update(const std::shared_ptr<critter>& c, size_t& i, const Ns& dt) = 0; - virtual void on_destroy(const std::shared_ptr<critter>& c, script_destroy_reason reason) = 0; + virtual void on_init(const bptr<critter>& c) = 0; + virtual void on_update(const bptr<critter>& c, size_t& i, const Ns& dt) = 0; + virtual void on_destroy(const bptr<critter>& c, script_destroy_reason reason) = 0; virtual void delete_self() = 0; object_type type() const override; diff --git a/src/critter.cpp b/src/critter.cpp index a05ea06f..b107394d 100644 --- a/src/critter.cpp +++ b/src/critter.cpp @@ -12,6 +12,7 @@ #include "compat/map.hpp" #include "compat/iota.hpp" #include "compat/exception.hpp" +#include "compat/borrowed-ptr.inl" #include <cmath> #include <utility> #include <array> @@ -393,12 +394,12 @@ Vector2 critter::ordinal_offset(Vector2b offset) const return Vector2(offset); } -void critter::update(const std::shared_ptr<object>& ptrʹ, size_t& i, const Ns& dt) +void critter::update(const bptr<object>& ptrʹ, size_t& i, const Ns& dt) { fm_debug_assert(&*ptrʹ == this); check_script_update_1(script.state()); - script->on_update(std::static_pointer_cast<critter>(ptrʹ), i, dt); + script->on_update(static_pointer_cast<critter>(ptrʹ), i, dt); #if 0 // for now, objects can't delete themselves if (check_script_update_2(script.state())) [[unlikely]] return; @@ -566,14 +567,14 @@ critter::~critter() noexcept { } -void critter::init_script(const std::shared_ptr<object>& ptrʹ) +void critter::init_script(const bptr<object>& ptrʹ) { - script.do_initialize(std::static_pointer_cast<critter>(ptrʹ)); + script.do_initialize(static_pointer_cast<critter>(ptrʹ)); } -void critter::destroy_script_pre(const std::shared_ptr<object>& ptrʹ, script_destroy_reason r) +void critter::destroy_script_pre(const bptr<object>& ptrʹ, script_destroy_reason r) { - script.do_destroy_pre(std::static_pointer_cast<critter>(ptrʹ), r); + script.do_destroy_pre(static_pointer_cast<critter>(ptrʹ), r); } void critter::destroy_script_post() diff --git a/src/critter.hpp b/src/critter.hpp index 38b5addf..e95bf065 100644 --- a/src/critter.hpp +++ b/src/critter.hpp @@ -32,7 +32,7 @@ struct critter final : object object_type type() const noexcept override; explicit operator critter_proto() const; - void update(const std::shared_ptr<object>& ptr, size_t& i, const Ns& dt) override; + void update(const bptr<object>& ptr, size_t& i, const Ns& dt) override; void update_movement(size_t& i, const Ns& dt, rotation r); struct move_result { bool blocked, moved; }; @@ -41,8 +41,8 @@ struct critter final : object Vector2 ordinal_offset(Vector2b offset) const override; float depth_offset() const override; - void init_script(const std::shared_ptr<object>& ptr) override; - void destroy_script_pre(const std::shared_ptr<object>& ptr, script_destroy_reason r) override; + void init_script(const bptr<object>& ptr) override; + void destroy_script_pre(const bptr<object>& ptr, script_destroy_reason r) override; void destroy_script_post() override; void clear_auto_movement(); diff --git a/src/ground-atlas.cpp b/src/ground-atlas.cpp index 726ec557..f78d53be 100644 --- a/src/ground-atlas.cpp +++ b/src/ground-atlas.cpp @@ -47,10 +47,10 @@ auto ground_atlas::make_texcoords(Vector2ui pixel_size, Vector2ub tile_count, si return texcoords_at(p0, sz, pixel_size); } -auto ground_atlas::make_texcoords_array(Vector2ui pixel_size, Vector2ub tile_count) -> std::unique_ptr<const texcoords[]> +auto ground_atlas::make_texcoords_array(Vector2ui pixel_size, Vector2ub tile_count) -> Array<texcoords> { const size_t N = Vector2ui{tile_count}.product(); - auto ptr = std::make_unique<std::array<Vector2, 4>[]>(N); + auto ptr = Array<texcoords>{NoInit, N}; for (auto i = 0uz; i < N; i++) ptr[i] = make_texcoords(pixel_size, tile_count, i); return ptr; diff --git a/src/ground-atlas.hpp b/src/ground-atlas.hpp index 3fc3a177..5ebdad1f 100644 --- a/src/ground-atlas.hpp +++ b/src/ground-atlas.hpp @@ -1,12 +1,14 @@ #pragma once +#include "compat/borrowed-ptr.hpp" #include "src/pass-mode.hpp" #include "src/quads.hpp" #include "src/ground-def.hpp" #include "loader/ground-cell.hpp" #include <array> -#include <memory> +#include <cr/Array.h> #include <Corrade/Containers/Optional.h> #include <Corrade/Containers/String.h> +#include <cr/Pointer.h> #include <Magnum/Magnum.h> #include <Magnum/Math/Vector2.h> #include <Magnum/GL/Texture.h> @@ -15,18 +17,18 @@ namespace floormat { class ground_atlas; -class ground_atlas final +class ground_atlas final : public bptr_base { using quad = Quads::quad; using texcoords = std::array<Vector2, 4>; - static std::unique_ptr<const texcoords[]> make_texcoords_array(Vector2ui pixel_size, Vector2ub tile_count); + static Array<texcoords> make_texcoords_array(Vector2ui pixel_size, Vector2ub tile_count); static texcoords make_texcoords(Vector2ui pixel_size, Vector2ub tile_count, size_t i); static String make_path(StringView name); ground_def _def; String _path; - std::unique_ptr<const texcoords[]> _texcoords; + Array<texcoords> _texcoords; GL::Texture2D _tex; Vector2ui _pixel_size; diff --git a/src/hole.cpp b/src/hole.cpp index 7a50566d..ad29c752 100644 --- a/src/hole.cpp +++ b/src/hole.cpp @@ -57,7 +57,7 @@ hole::~hole() noexcept return; } -void hole::update(const std::shared_ptr<object>&, size_t&, const Ns&) {} +void hole::update(const bptr<object>&, size_t&, const Ns&) {} hole::operator hole_proto() const { diff --git a/src/hole.hpp b/src/hole.hpp index 25db9886..35fd29d9 100644 --- a/src/hole.hpp +++ b/src/hole.hpp @@ -40,7 +40,7 @@ struct hole final : object Vector2 ordinal_offset(Vector2b offset) const override; float depth_offset() const override; object_type type() const noexcept override; - void update(const std::shared_ptr<object>& ptr, size_t& i, const Ns& dt) override; + void update(const bptr<object>& ptr, size_t& i, const Ns& dt) override; bool is_dynamic() const override; bool updates_passability() const override; bool is_virtual() const override; diff --git a/src/light.cpp b/src/light.cpp index 647368ec..2c5d1a4f 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -70,7 +70,7 @@ light::operator light_proto() const } object_type light::type() const noexcept { return object_type::light; } -void light::update(const std::shared_ptr<object>&, size_t&, const Ns&) {} +void light::update(const bptr<object>&, size_t&, const Ns&) {} bool light::is_dynamic() const { return true; } bool light::is_virtual() const { return true; } diff --git a/src/light.hpp b/src/light.hpp index a6a22fdb..97c18191 100644 --- a/src/light.hpp +++ b/src/light.hpp @@ -35,7 +35,7 @@ struct light final : object Vector2 ordinal_offset(Vector2b offset) const override; float depth_offset() const override; object_type type() const noexcept override; - void update(const std::shared_ptr<object>& ptr, size_t& i, const Ns& dt) override; + void update(const bptr<object>& ptr, size_t& i, const Ns& dt) override; bool is_dynamic() const override; bool is_virtual() const override; diff --git a/src/object.cpp b/src/object.cpp index 200179e5..7e686aa9 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -10,6 +10,7 @@ #include "compat/exception.hpp" #include "compat/limits.hpp" #include "compat/non-const.hpp" +#include "compat/borrowed-ptr.inl" #include "nanosecond.inl" #include <cmath> #include <algorithm> @@ -363,8 +364,8 @@ bool object::is_dynamic() const { return atlas->info().fps > 0; } bool object::updates_passability() const { return false; } void object::maybe_mark_neighbor_chunks_modified() {} -void object::init_script(const std::shared_ptr<object>&) {} -void object::destroy_script_pre(const std::shared_ptr<object>&, script_destroy_reason) {} +void object::init_script(const bptr<object>&) {} +void object::destroy_script_pre(const bptr<object>&, script_destroy_reason) {} void object::destroy_script_post() {} void object::check_script_update_1(script_lifecycle state) diff --git a/src/object.hpp b/src/object.hpp index d65f6a67..a73f97b1 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -1,5 +1,6 @@ #pragma once #include "compat/defs.hpp" +#include "compat/borrowed-ptr.hpp" #include "src/global-coords.hpp" #include "src/rotation.hpp" #include "src/pass-mode.hpp" @@ -7,7 +8,6 @@ #include "src/object-id.hpp" #include "src/point.hpp" #include "src/script-enums.hpp" -#include <memory> namespace floormat { @@ -18,7 +18,7 @@ struct Ns; struct object_proto { - std::shared_ptr<anim_atlas> atlas; + bptr<anim_atlas> atlas; Vector2b offset, bbox_offset; Vector2ub bbox_size = Vector2ub(tile_size_xy); uint32_t delta = 0; @@ -39,7 +39,7 @@ struct object_proto object_proto(object_proto&&) noexcept; }; -struct object +struct object : bptr_base { fm_DECLARE_DELETED_COPY_ASSIGNMENT(object); fm_DECLARE_DELETED_MOVE_ASSIGNMENT(object); @@ -47,9 +47,9 @@ struct object const object_id id = 0; uint64_t last_frame_no = 0; class chunk* const c; - const std::shared_ptr<anim_atlas> atlas; + const bptr<anim_atlas> atlas; const global_coords coord; - const std::weak_ptr<object> parent; + const bptr<object> parent; const Vector2b offset, bbox_offset; const Vector2ub bbox_size; uint32_t delta = 0; @@ -60,7 +60,7 @@ struct object bool gone : 1 = false; //char _pad[4]; // got 4 bytes left - virtual ~object() noexcept; + virtual ~object() noexcept override; virtual Vector2 ordinal_offset(Vector2b offset) const = 0; virtual float depth_offset() const = 0; @@ -77,7 +77,7 @@ struct object virtual object_type type() const noexcept = 0; virtual bool can_activate(size_t i) const; virtual bool activate(size_t i); - virtual void update(const std::shared_ptr<object>& self, size_t& i, const Ns& dt) = 0; + virtual void update(const bptr<object>& self, size_t& i, const Ns& dt) = 0; void rotate(size_t i, rotation r); bool can_rotate(global_coords coord, rotation new_r, rotation old_r, Vector2b offset, Vector2b bbox_offset, Vector2ub bbox_size); bool can_move_to(Vector2i delta, global_coords coord, Vector2b offset, Vector2b bbox_offset, Vector2ub bbox_aize); @@ -102,8 +102,8 @@ struct object requires std::is_unsigned_v<T> static uint32_t alloc_frame_time(const Ns& dt, T& accum, uint32_t hz, float speed); - virtual void init_script(const std::shared_ptr<object>& ptr); - virtual void destroy_script_pre(const std::shared_ptr<object>& ptr, script_destroy_reason r); + virtual void init_script(const bptr<object>& ptr); + virtual void destroy_script_pre(const bptr<object>& ptr, script_destroy_reason r); virtual void destroy_script_post(); protected: diff --git a/src/scenery.cpp b/src/scenery.cpp index 7e52c08e..4903afac 100644 --- a/src/scenery.cpp +++ b/src/scenery.cpp @@ -45,7 +45,7 @@ scenery::scenery(object_id id, class chunk& c, const scenery_proto& proto) : // ---------- generic_scenery ---------- -void generic_scenery::update(const std::shared_ptr<object>&, size_t&, const Ns&) {} +void generic_scenery::update(const bptr<object>&, size_t&, const Ns&) {} Vector2 generic_scenery::ordinal_offset(Vector2b offset) const { return Vector2(offset); } bool generic_scenery::can_activate(size_t) const { return interactive; } bool generic_scenery::activate(size_t) { return false; } @@ -74,7 +74,7 @@ generic_scenery::generic_scenery(object_id id, class chunk& c, const generic_sce enum scenery_type door_scenery::scenery_type() const { return scenery_type::door; } -void door_scenery::update(const std::shared_ptr<object>&, size_t&, const Ns& dt) +void door_scenery::update(const bptr<object>&, size_t&, const Ns& dt) { if (!atlas || !active) return; diff --git a/src/scenery.hpp b/src/scenery.hpp index 56675a93..65e32c17 100644 --- a/src/scenery.hpp +++ b/src/scenery.hpp @@ -27,7 +27,7 @@ struct generic_scenery final : scenery bool active : 1 = false; bool interactive : 1 = false; - void update(const std::shared_ptr<object>& ptr, size_t& i, const Ns& dt) override; + void update(const bptr<object>& ptr, size_t& i, const Ns& dt) override; Vector2 ordinal_offset(Vector2b offset) const override; bool can_activate(size_t i) const override; bool activate(size_t i) override; @@ -47,7 +47,7 @@ struct door_scenery final : scenery bool active : 1 = false; bool interactive : 1 = false; - void update(const std::shared_ptr<object>& ptr, size_t& i, const Ns& dt) override; + void update(const bptr<object>& ptr, size_t& i, const Ns& dt) override; Vector2 ordinal_offset(Vector2b offset) const override; bool can_activate(size_t i) const override; bool activate(size_t i) override; diff --git a/src/script.hpp b/src/script.hpp index 5461a208..82f16484 100644 --- a/src/script.hpp +++ b/src/script.hpp @@ -1,8 +1,8 @@ #pragma once #include "script-enums.hpp" #include "compat/defs.hpp" +#include "compat/borrowed-ptr.hpp" #include "src/object-type.hpp" -#include <memory> namespace floormat { @@ -54,11 +54,11 @@ public: void do_create(S* ptr); void do_create(Pointer<S> ptr); - void do_initialize(const std::shared_ptr<Obj>& obj); - void do_reassign(S* ptr, const std::shared_ptr<Obj>& obj); - void do_reassign(Pointer<S> ptr, const std::shared_ptr<Obj>& obj); - void do_clear(const std::shared_ptr<Obj>& obj); - void do_destroy_pre(const std::shared_ptr<Obj>& obj, script_destroy_reason r); + void do_initialize(const bptr<Obj>& obj); + void do_reassign(S* ptr, const bptr<Obj>& obj); + void do_reassign(Pointer<S> ptr, const bptr<Obj>& obj); + void do_clear(const bptr<Obj>& obj); + void do_destroy_pre(const bptr<Obj>& obj, script_destroy_reason r); void do_finish_destroy(); void do_ensure_torn_down(); void do_error_unwind(); diff --git a/src/script.inl b/src/script.inl index 27a79e31..92b0e1a6 100644 --- a/src/script.inl +++ b/src/script.inl @@ -5,13 +5,11 @@ #include <cr/StringView.h> #include <cr/Pointer.h> -// ReSharper disable CppDFAUnreachableCode - namespace floormat::detail_Script { template<typename S, typename Obj> concept BaseScript = -requires (S& script, const std::shared_ptr<Obj>& obj, size_t& i, const Ns& ns) +requires (S& script, const bptr<Obj>& obj, size_t& i, const Ns& ns) { requires std::is_base_of_v<base_script, S>; script.on_init(obj); @@ -89,7 +87,7 @@ void Script<S, Obj>::do_create(Pointer<S> p) } template <typename S, typename Obj> -void Script<S, Obj>::do_initialize(const std::shared_ptr<Obj>& obj) +void Script<S, Obj>::do_initialize(const bptr<Obj>& obj) { switch (_state) { @@ -108,7 +106,7 @@ void Script<S, Obj>::do_initialize(const std::shared_ptr<Obj>& obj) } template <typename S, typename Obj> -void Script<S, Obj>::do_reassign(S* p, const std::shared_ptr<Obj>& obj) +void Script<S, Obj>::do_reassign(S* p, const bptr<Obj>& obj) { if (!p) [[unlikely]] return do_clear(obj); @@ -121,13 +119,13 @@ void Script<S, Obj>::do_reassign(S* p, const std::shared_ptr<Obj>& obj) } template <typename S, typename Obj> -void Script<S, Obj>::do_reassign(Pointer<S> p, const std::shared_ptr<Obj>& obj) +void Script<S, Obj>::do_reassign(Pointer<S> p, const bptr<Obj>& obj) { return do_reassign(p.release(), obj); } template <typename S, typename Obj> -void Script<S, Obj>::do_clear(const std::shared_ptr<Obj>& obj) +void Script<S, Obj>::do_clear(const bptr<Obj>& obj) { FM_ASSERT_SCRIPT_STATE(script_lifecycle::created); fm_debug_assert(ptr); @@ -137,7 +135,7 @@ void Script<S, Obj>::do_clear(const std::shared_ptr<Obj>& obj) } template <typename S, typename Obj> -void Script<S, Obj>::do_destroy_pre(const std::shared_ptr<Obj>& obj, script_destroy_reason r) +void Script<S, Obj>::do_destroy_pre(const bptr<Obj>& obj, script_destroy_reason r) { FM_ASSERT_SCRIPT_STATE(script_lifecycle::created); _state = script_lifecycle::destroying; diff --git a/src/tile-image.cpp b/src/tile-image.cpp index e2d84461..20ab4098 100644 --- a/src/tile-image.cpp +++ b/src/tile-image.cpp @@ -1,4 +1,5 @@ #include "tile-image.hpp" +#include "compat/borrowed-ptr.inl" namespace floormat { @@ -17,7 +18,7 @@ image_ref_<Atlas, Proto>::image_ref_(const image_ref_<Atlas, Proto>& o) noexcept {} template<typename Atlas, typename Proto> -image_ref_<Atlas, Proto>::image_ref_(std::shared_ptr<Atlas>& atlas, variant_t& variant) noexcept +image_ref_<Atlas, Proto>::image_ref_(bptr<Atlas>& atlas, variant_t& variant) noexcept : atlas{atlas}, variant{variant} {} diff --git a/src/tile-image.hpp b/src/tile-image.hpp index a25b9fed..475b6251 100644 --- a/src/tile-image.hpp +++ b/src/tile-image.hpp @@ -1,6 +1,6 @@ #pragma once #include "tile-defs.hpp" -#include <memory> +#include "compat/borrowed-ptr.hpp" namespace floormat { @@ -10,7 +10,7 @@ class wall_atlas; template<typename Atlas> struct image_proto_ { - std::shared_ptr<Atlas> atlas; + bptr<Atlas> atlas; variant_t variant = 0; bool operator==(const image_proto_<Atlas>& b) const noexcept; @@ -20,10 +20,10 @@ struct image_proto_ template<typename Atlas, typename Proto> struct image_ref_ final { - std::shared_ptr<Atlas>& atlas; + bptr<Atlas>& atlas; variant_t& variant; - image_ref_(std::shared_ptr<Atlas>& atlas, variant_t& variant) noexcept; + image_ref_(bptr<Atlas>& atlas, variant_t& variant) noexcept; image_ref_(const image_ref_&) noexcept; image_ref_& operator=(const Proto& proto) noexcept; operator Proto() const noexcept; diff --git a/src/tile.cpp b/src/tile.cpp index 89e49017..216783f7 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -1,7 +1,7 @@ #include "tile.hpp" #include "tile-constants.hpp" #include "chunk.hpp" -#include "ground-atlas.hpp" +#include "compat/borrowed-ptr.inl" namespace floormat { @@ -24,13 +24,13 @@ wall_image_proto tile_proto::wall_west() const noexcept { return { wall_west_at tile_ref::tile_ref(class chunk& c, uint8_t i) noexcept : _chunk{&c}, i{i} {} -std::shared_ptr<class ground_atlas> tile_ref::ground_atlas() noexcept { return _chunk->_ground ? _chunk->_ground->atlases[i] : nullptr; } -std::shared_ptr<class wall_atlas> tile_ref::wall_north_atlas() noexcept { return _chunk->_walls ? _chunk->_walls->atlases[i*2+0] : nullptr; } -std::shared_ptr<class wall_atlas> tile_ref::wall_west_atlas() noexcept { return _chunk->_walls ? _chunk->_walls->atlases[i*2+1] : nullptr; } +bptr<class ground_atlas> tile_ref::ground_atlas() noexcept { return _chunk->_ground ? _chunk->_ground->atlases[i] : nullptr; } +bptr<class wall_atlas> tile_ref::wall_north_atlas() noexcept { return _chunk->_walls ? _chunk->_walls->atlases[i*2+0] : nullptr; } +bptr<class wall_atlas> tile_ref::wall_west_atlas() noexcept { return _chunk->_walls ? _chunk->_walls->atlases[i*2+1] : nullptr; } -std::shared_ptr<const class ground_atlas> tile_ref::ground_atlas() const noexcept { return _chunk->_ground ? _chunk->_ground->atlases[i] : nullptr; } -std::shared_ptr<const class wall_atlas> tile_ref::wall_north_atlas() const noexcept { return _chunk->_walls ? _chunk->_walls->atlases[i*2+0] : nullptr; } -std::shared_ptr<const class wall_atlas> tile_ref::wall_west_atlas() const noexcept { return _chunk->_walls ? _chunk->_walls->atlases[i*2+1] : nullptr; } +bptr<const class ground_atlas> tile_ref::ground_atlas() const noexcept { return _chunk->_ground ? _chunk->_ground->atlases[i] : nullptr; } +bptr<const class wall_atlas> tile_ref::wall_north_atlas() const noexcept { return _chunk->_walls ? _chunk->_walls->atlases[i*2+0] : nullptr; } +bptr<const class wall_atlas> tile_ref::wall_west_atlas() const noexcept { return _chunk->_walls ? _chunk->_walls->atlases[i*2+1] : nullptr; } tile_image_ref tile_ref::ground() noexcept { _chunk->ensure_alloc_ground(); return {_chunk->_ground->atlases[i], _chunk->_ground->variants[i] }; } wall_image_ref tile_ref::wall_north() noexcept { _chunk->ensure_alloc_walls(); return {_chunk->_walls->atlases[i*2+0], _chunk->_walls->variants[i*2+0] }; } diff --git a/src/tile.hpp b/src/tile.hpp index 43170fe7..c679b5c0 100644 --- a/src/tile.hpp +++ b/src/tile.hpp @@ -1,5 +1,6 @@ #pragma once #include "tile-image.hpp" +#include "compat/borrowed-ptr.hpp" namespace floormat { @@ -8,8 +9,8 @@ class anim_atlas; struct tile_proto final { - std::shared_ptr<class ground_atlas> ground_atlas; - std::shared_ptr<class wall_atlas> wall_north_atlas, wall_west_atlas; + bptr<class ground_atlas> ground_atlas; + bptr<class wall_atlas> wall_north_atlas, wall_west_atlas; variant_t ground_variant = 0, wall_north_variant = 0, wall_west_variant = 0; tile_image_proto ground() const noexcept; @@ -31,13 +32,13 @@ struct tile_ref final wall_image_proto wall_north() const noexcept; wall_image_proto wall_west() const noexcept; - std::shared_ptr<class ground_atlas> ground_atlas() noexcept; - std::shared_ptr<class wall_atlas> wall_north_atlas() noexcept; - std::shared_ptr<class wall_atlas> wall_west_atlas() noexcept; + bptr<class ground_atlas> ground_atlas() noexcept; + bptr<class wall_atlas> wall_north_atlas() noexcept; + bptr<class wall_atlas> wall_west_atlas() noexcept; - std::shared_ptr<const class ground_atlas> ground_atlas() const noexcept; - std::shared_ptr<const class wall_atlas> wall_north_atlas() const noexcept; - std::shared_ptr<const class wall_atlas> wall_west_atlas() const noexcept; + bptr<const class ground_atlas> ground_atlas() const noexcept; + bptr<const class wall_atlas> wall_north_atlas() const noexcept; + bptr<const class wall_atlas> wall_west_atlas() const noexcept; explicit operator tile_proto() const noexcept; diff --git a/src/wall-atlas.hpp b/src/wall-atlas.hpp index 5cf4f244..e0203165 100644 --- a/src/wall-atlas.hpp +++ b/src/wall-atlas.hpp @@ -1,4 +1,5 @@ #pragma once +#include "compat/borrowed-ptr.hpp" #include "src/rotation.hpp" #include "src/pass-mode.hpp" #include "wall-defs.hpp" @@ -106,7 +107,7 @@ struct wall_atlas_def final std::array<Wall::DirArrayIndex, Wall::Direction_COUNT> dir_map); }; -class wall_atlas final +class wall_atlas final : public bptr_base { using Frame = Wall::Frame; using Group = Wall::Group; @@ -129,7 +130,7 @@ class wall_atlas final public: fm_DECLARE_DEFAULT_MOVE_ASSIGNMENT_(wall_atlas); wall_atlas() noexcept; - ~wall_atlas() noexcept; + ~wall_atlas() noexcept override; wall_atlas(wall_atlas_def def, String path, const ImageView2D& img); void serialize(StringView filename) const; diff --git a/src/world.cpp b/src/world.cpp index 41e43468..935ca6c4 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -5,7 +5,8 @@ #include "scenery.hpp" #include "scenery-proto.hpp" #include "light.hpp" -#include "compat/shared-ptr-wrapper.hpp" +#include "compat/borrowed-ptr.inl" +#include "compat/weak-borrowed-ptr.inl" #include "compat/hash.hpp" #include "compat/exception.hpp" #include "compat/overloaded.hpp" @@ -26,10 +27,9 @@ size_t world::chunk_coords_hasher::operator()(const chunk_coords_& coord) const } namespace floormat { - -struct world::robin_map_wrapper final : tsl::robin_map<object_id, std::weak_ptr<object>, object_id_hasher> +struct world::robin_map_wrapper final : tsl::robin_map<object_id, weak_bptr<object>, object_id_hasher> { - using tsl::robin_map<object_id, std::weak_ptr<object>, object_id_hasher>::robin_map; + using tsl::robin_map<object_id, weak_bptr<object>, object_id_hasher>::robin_map; }; world::world(world&& w) noexcept = default; @@ -51,11 +51,11 @@ world& world::operator=(world&& w) noexcept _script_finalized = false; fm_assert(!w._teardown); fm_assert(!_teardown); - fm_assert(w._unique_id); _last_chunk = {}; _chunks = move(w._chunks); _objects = move(w._objects); w._objects = {}; + fm_assert(w._unique_id); _unique_id = move(w._unique_id); fm_debug_assert(_unique_id); fm_debug_assert(w._unique_id == nullptr); @@ -78,6 +78,7 @@ world::~world() noexcept for (auto& [k, c] : _chunks) c.on_teardown(); _teardown = true; + _objects->clear(); for (auto& [k, c] : _chunks) { c._teardown = true; @@ -88,10 +89,11 @@ world::~world() noexcept } _last_chunk = {}; _chunks.clear(); - _objects->clear(); } -world::world(size_t capacity) : _chunks{capacity} +bool world::unique_id::operator==(const unique_id& other) const { return this == &other; } + +world::world(size_t capacity) : _chunks{capacity}, _unique_id{InPlace} { _chunks.max_load_factor(max_load_factor); _chunks.reserve(initial_capacity); @@ -162,7 +164,7 @@ void world::collect(bool force) fm_debug("world: collected %zu/%zu chunks", len, len0); } -void world::do_make_object(const std::shared_ptr<object>& e, global_coords pos, bool sorted) +void world::do_make_object(const bptr<object>& e, global_coords pos, bool sorted) { fm_debug_assert(e->id != 0); fm_debug_assert(e->c); @@ -186,7 +188,7 @@ void world::erase_object(object_id id) fm_debug_assert(cnt > 0); } -std::shared_ptr<object> world::find_object_(object_id id) +bptr<object> world::find_object_(object_id id) { auto it = _objects->find(id); auto ret = it == _objects->end() ? nullptr : it->second.lock(); @@ -267,19 +269,19 @@ struct world::script_status world::script_status() const return { _script_initialized, _script_finalized }; } -shared_ptr_wrapper<critter> world::ensure_player_character(object_id& id) +bptr<critter> world::ensure_player_character(object_id& id) { return ensure_player_character(id, make_player_proto()); } -shared_ptr_wrapper<critter> world::ensure_player_character(object_id& id_, critter_proto p) +bptr<critter> world::ensure_player_character(object_id& id_, critter_proto p) { if (id_) { - std::shared_ptr<critter> tmp; + bptr<critter> tmp; if (auto C = find_object(id_); C && C->type() == object_type::critter) { - auto ptr = std::static_pointer_cast<critter>(C); + auto ptr = static_pointer_cast<critter>(C); return {ptr}; } } @@ -287,7 +289,7 @@ shared_ptr_wrapper<critter> world::ensure_player_character(object_id& id_, critt auto id = (object_id)-1; - shared_ptr_wrapper<critter> ret; + bptr<critter> ret; for (auto& [coord, c] : chunks()) { @@ -300,7 +302,7 @@ shared_ptr_wrapper<critter> world::ensure_player_character(object_id& id_, critt if (C.playable) { id = std::min(id, C.id); - ret.ptr = std::static_pointer_cast<critter>(eʹ); + ret = static_pointer_cast<critter>(eʹ); } } } @@ -311,18 +313,18 @@ shared_ptr_wrapper<critter> world::ensure_player_character(object_id& id_, critt else { p.playable = true; - ret.ptr = make_object<critter>(make_id(), global_coords{}, move(p)); - id_ = ret.ptr->id; + ret = make_object<critter>(make_id(), global_coords{}, move(p)); + id_ = ret->id; } - fm_debug_assert(ret.ptr); + fm_debug_assert(ret); return ret; } template<typename T> -std::shared_ptr<T> world::find_object(object_id id) +bptr<T> world::find_object(object_id id) { static_assert(std::is_base_of_v<object, T>); - if (std::shared_ptr<object> ptr = find_object_(id); !ptr) + if (bptr<object> ptr = find_object_(id); !ptr) return {}; else if constexpr(std::is_same_v<T, object>) return ptr; @@ -334,7 +336,7 @@ std::shared_ptr<T> world::find_object(object_id id) template<typename T> requires is_strict_base_of<scenery, T> -std::shared_ptr<T> world::find_object(object_id id) +bptr<T> world::find_object(object_id id) { if (auto ptr = find_object<scenery>(id); !ptr) return {}; @@ -344,17 +346,17 @@ std::shared_ptr<T> world::find_object(object_id id) return static_pointer_cast<T>(move(ptr)); } -template std::shared_ptr<object> world::find_object<object>(object_id id); -template std::shared_ptr<critter> world::find_object<critter>(object_id id); -template std::shared_ptr<scenery> world::find_object<scenery>(object_id id); -template std::shared_ptr<light> world::find_object<light>(object_id id); -template std::shared_ptr<generic_scenery> world::find_object<generic_scenery>(object_id id); -template std::shared_ptr<door_scenery> world::find_object<door_scenery>(object_id id); +template bptr<object> world::find_object<object>(object_id id); +template bptr<critter> world::find_object<critter>(object_id id); +template bptr<scenery> world::find_object<scenery>(object_id id); +template bptr<light> world::find_object<light>(object_id id); +template bptr<generic_scenery> world::find_object<generic_scenery>(object_id id); +template bptr<door_scenery> world::find_object<door_scenery>(object_id id); template<bool sorted> -std::shared_ptr<scenery> world::make_scenery(object_id id, global_coords pos, scenery_proto&& proto) +bptr<scenery> world::make_scenery(object_id id, global_coords pos, scenery_proto&& proto) { - using type = std::shared_ptr<scenery>; + using type = bptr<scenery>; return std::visit(overloaded { [&](std::monostate) -> type { @@ -369,7 +371,7 @@ std::shared_ptr<scenery> world::make_scenery(object_id id, global_coords pos, sc }, move(proto.subtype)); } -template std::shared_ptr<scenery> world::make_scenery<false>(object_id id, global_coords pos, scenery_proto&& proto); -template std::shared_ptr<scenery> world::make_scenery<true>(object_id id, global_coords pos, scenery_proto&& proto); +template bptr<scenery> world::make_scenery<false>(object_id id, global_coords pos, scenery_proto&& proto); +template bptr<scenery> world::make_scenery<true>(object_id id, global_coords pos, scenery_proto&& proto); } // namespace floormat diff --git a/src/world.hpp b/src/world.hpp index ecd58e3c..a0c2723a 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -1,17 +1,16 @@ #pragma once #include "compat/safe-ptr.hpp" #include "compat/base-of.hpp" +#include "compat/borrowed-ptr.inl" #include "chunk.hpp" #include "global-coords.hpp" #include "object-type.hpp" #include "scenery-type.hpp" #include "loader/policy.hpp" -#include <memory> #include <unordered_map> namespace floormat { -template<typename T> struct shared_ptr_wrapper; struct object; struct critter; struct critter_proto; @@ -36,12 +35,17 @@ private: chunk_coords_ pos = invalid_coords; } _last_chunk; + struct unique_id : bptr_base + { + bool operator==(const unique_id& other) const; + }; + struct object_id_hasher { size_t operator()(object_id id) const noexcept; }; struct robin_map_wrapper; std::unordered_map<chunk_coords_, chunk, chunk_coords_hasher> _chunks; safe_ptr<robin_map_wrapper> _objects; - std::shared_ptr<char> _unique_id = std::make_shared<char>('A'); + bptr<unique_id> _unique_id; object_id _object_counter = object_counter_init; uint64_t _current_frame = 1; // zero is special for struct object bool _teardown : 1 = false; @@ -50,9 +54,9 @@ 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_make_object(const bptr<object>& e, global_coords pos, bool sorted); // todo replace 2nd arg with chunk& void erase_object(object_id id); - std::shared_ptr<object> find_object_(object_id id); + bptr<object> find_object_(object_id id); [[noreturn]] static void throw_on_wrong_object_type(object_id id, object_type actual, object_type expected); [[noreturn]] static void throw_on_wrong_scenery_type(object_id id, scenery_type actual, scenery_type expected); @@ -89,19 +93,19 @@ public: T{object_id(), c, std::declval<Xs&&>()...}; std::is_base_of_v<object, T>; } - std::shared_ptr<T> make_object(object_id id, global_coords pos, Xs&&... xs) + bptr<T> make_object(object_id id, global_coords pos, Xs&&... xs) { - auto ret = std::shared_ptr<T>(new T{id, operator[](pos.chunk3()), forward<Xs>(xs)...}); - do_make_object(std::static_pointer_cast<object>(ret), pos, sorted); + auto ret = bptr<T>(new T{id, operator[](pos.chunk3()), forward<Xs>(xs)...}); + do_make_object(ret, pos, sorted); return ret; } - template<bool sorted = true> std::shared_ptr<scenery> make_scenery(object_id id, global_coords pos, scenery_proto&& proto); - template<typename T = object> std::shared_ptr<T> find_object(object_id id); - template<typename T> requires is_strict_base_of<scenery, T> std::shared_ptr<T> find_object(object_id id); + template<bool sorted = true> bptr<scenery> make_scenery(object_id id, global_coords pos, scenery_proto&& proto); + template<typename T = object> bptr<T> find_object(object_id id); + template<typename T> requires is_strict_base_of<scenery, T> bptr<T> find_object(object_id id); - shared_ptr_wrapper<critter> ensure_player_character(object_id& id, critter_proto p); - shared_ptr_wrapper<critter> ensure_player_character(object_id& id); + bptr<critter> ensure_player_character(object_id& id, critter_proto p); + bptr<critter> ensure_player_character(object_id& id); static critter_proto make_player_proto(); struct script_status { bool initialized, finalized; }; diff --git a/test/critter.cpp b/test/critter.cpp index 071fae9b..90619ce8 100644 --- a/test/critter.cpp +++ b/test/critter.cpp @@ -1,7 +1,7 @@ #include "app.hpp" #include "compat/debug.hpp" -#include "compat/shared-ptr-wrapper.hpp" #include "compat/function2.hpp" +#include "compat/borrowed-ptr.inl" #include "src/critter.hpp" #include "src/scenery-proto.hpp" #include "src/world.hpp" @@ -118,7 +118,7 @@ bool run(world& w, const function_view<Ns() const>& make_dt, mark_all_modified(w); object_id id = 0; - auto npc_ = w.ensure_player_character(id, make_proto((float)start.accel)).ptr; + auto npc_ = w.ensure_player_character(id, make_proto((float)start.accel)); auto& npc = *npc_; auto index = npc.index(); @@ -316,7 +316,7 @@ void test3(StringView instance_name, const Function& make_dt, double accel, rota { // reproduce the bug from commit 2b5a6e3f object_id id = 0; - auto npc = w.ensure_player_character(id, make_proto((float)accel)).ptr; + auto npc = w.ensure_player_character(id, make_proto((float)accel)); npc->set_bbox({}, {}, {1,1}, pass_mode::blocked); } diff --git a/test/loader.cpp b/test/loader.cpp index d551276f..c341da70 100644 --- a/test/loader.cpp +++ b/test/loader.cpp @@ -7,6 +7,7 @@ #include "src/wall-atlas.hpp" #include "src/anim-atlas.hpp" #include "src/scenery-proto.hpp" +#include "compat/borrowed-ptr.inl" namespace floormat { diff --git a/test/save.cpp b/test/save.cpp index 3d4a71a0..e30a02fb 100644 --- a/test/save.cpp +++ b/test/save.cpp @@ -292,7 +292,7 @@ void test_save_objs() constexpr auto coord = global_coords{ch, { 3, 4}}; const auto id = w.make_id(); const auto objʹ = w.make_scenery(id, coord, move(p)); - const auto obj = std::static_pointer_cast<generic_scenery>(objʹ); + const auto obj = static_pointer_cast<generic_scenery>(objʹ); const auto obj2 = w.find_object<generic_scenery>(id); //const auto obj3 = w.find_object<door_scenery>(id); // must fail fm_assert(obj == obj2); |