summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-12-05 06:30:59 +0100
committerStanislaw Halik <sthalik@misaki.pl>2022-12-05 06:30:59 +0100
commit960e346159dbf152d9847f0998e1e717fb7dbfef (patch)
tree6aab5985d1a2f20542e152d70c9be46bbed0025e
parent4ad635e8dfe21d2dd0e0582c44379dde26ca57a8 (diff)
src: add pass_mode field to tile_atlas
-rw-r--r--editor/app.cpp8
-rw-r--r--editor/tile-editor.cpp10
-rw-r--r--images/floor.json30
-rw-r--r--images/wall.json30
-rw-r--r--loader/atlas.cpp14
-rw-r--r--loader/impl.hpp3
-rw-r--r--loader/json.cpp10
-rw-r--r--loader/loader.hpp6
-rw-r--r--serialize/tile-atlas.cpp37
-rw-r--r--serialize/world-reader.cpp4
-rw-r--r--src/tile-atlas.cpp13
-rw-r--r--src/tile-atlas.hpp9
-rw-r--r--test/json.cpp8
-rw-r--r--test/serializer.cpp6
14 files changed, 144 insertions, 44 deletions
diff --git a/editor/app.cpp b/editor/app.cpp
index ed374dd8..ed1bac7b 100644
--- a/editor/app.cpp
+++ b/editor/app.cpp
@@ -12,10 +12,10 @@ namespace floormat {
app::app(fm_settings&& opts) :
M{floormat_main::create(*this, std::move(opts))},
- _floor1{loader.tile_atlas("floor-tiles", {44, 4})},
- _floor2{loader.tile_atlas("metal1", {2, 2})},
- _wall1{loader.tile_atlas("wood2", {2, 1})},
- _wall2{loader.tile_atlas("wood1", {2, 1})},
+ _floor1{loader.tile_atlas("floor-tiles", {44, 4}, pass_mode::pass)},
+ _floor2{loader.tile_atlas("metal1", {2, 2}, pass_mode::pass)},
+ _wall1{loader.tile_atlas("wood2", {2, 1}, pass_mode::blocked)},
+ _wall2{loader.tile_atlas("wood1", {2, 1}, pass_mode::blocked)},
_door{loader.anim_atlas("door-close", loader.SCENERY_PATH)},
_table{loader.anim_atlas("table", loader.SCENERY_PATH)},
_control_panel(loader.anim_atlas("control-panel", loader.SCENERY_PATH))
diff --git a/editor/tile-editor.cpp b/editor/tile-editor.cpp
index d5743220..ffee3b66 100644
--- a/editor/tile-editor.cpp
+++ b/editor/tile-editor.cpp
@@ -16,8 +16,16 @@ tile_editor::tile_editor(editor_mode mode, StringView name) : _name{name}, _mode
void tile_editor::load_atlases()
{
+ pass_mode default_pass_mode;
+ switch (_mode)
+ {
+ case editor_mode::floor: default_pass_mode = pass_mode::pass; break;
+ case editor_mode::walls: default_pass_mode = pass_mode::blocked; break;
+ default: default_pass_mode = pass_mode::see_through; break;
+ }
+
const auto filename = _name + ".json";
- for (const auto& atlas : loader.tile_atlases(filename))
+ for (const auto& atlas : loader.tile_atlases(filename, default_pass_mode))
{
const auto [name, _ext] = Path::splitExtension(atlas->name());
auto& [_, vec] = _permutation;
diff --git a/images/floor.json b/images/floor.json
index eff4f153..2fee595f 100644
--- a/images/floor.json
+++ b/images/floor.json
@@ -1,8 +1,26 @@
[
- ["floor-tiles", "44 x 4"],
- ["metal1", "2 x 2"],
- ["tiles", "8 x 5"],
- ["wood2", "1 x 1"],
- ["concrete6", "4 x 4"],
- ["texel", "2 x 2"]
+ {
+ "name": "floor-tiles",
+ "size": "44 x 4"
+ },
+ {
+ "name": "tiles",
+ "size": "8 x 5"
+ },
+ {
+ "name": "wood2",
+ "size": "1 x 1"
+ },
+ {
+ "name": "concrete6",
+ "size": "4 x 4"
+ },
+ {
+ "name": "texel",
+ "size": "2 x 2"
+ },
+ {
+ "name": "metal1",
+ "size": "2 x 2"
+ }
]
diff --git a/images/wall.json b/images/wall.json
index 5824513f..12a3d13e 100644
--- a/images/wall.json
+++ b/images/wall.json
@@ -1,8 +1,26 @@
[
- ["wood2", "2 x 2"],
- ["wood1", "2 x 2"],
- ["teak1", "2 x 2"],
- ["metal2", "2 x 2"],
- ["concrete7", "4 x 4"],
- ["concrete6", "4 x 4"]
+ {
+ "name": "wood2",
+ "size": "2 x 2"
+ },
+ {
+ "name": "wood1",
+ "size": "2 x 2"
+ },
+ {
+ "name": "teak1",
+ "size": "2 x 2"
+ },
+ {
+ "name": "metal2",
+ "size": "2 x 2"
+ },
+ {
+ "name": "concrete7",
+ "size": "4 x 4"
+ },
+ {
+ "name": "concrete6",
+ "size": "4 x 4"
+ }
]
diff --git a/loader/atlas.cpp b/loader/atlas.cpp
index f285d3b1..1354e922 100644
--- a/loader/atlas.cpp
+++ b/loader/atlas.cpp
@@ -14,15 +14,25 @@
namespace floormat::loader_detail {
-std::shared_ptr<tile_atlas> loader_impl::tile_atlas(StringView name, Vector2ub size) noexcept(false)
+std::shared_ptr<tile_atlas> loader_impl::tile_atlas(StringView name, Vector2ub size, Optional<pass_mode> pass) noexcept(false)
{
fm_soft_assert(check_atlas_name(name));
- const emplacer e{[&] { return std::make_shared<struct tile_atlas>(name, texture(IMAGE_PATH, name), size); }};
+ const emplacer e{[&] { return std::make_shared<struct tile_atlas>(name, texture(IMAGE_PATH, name), size, pass); }};
auto atlas = tile_atlas_map.try_emplace(name, e).first->second;
+ fm_soft_assert(!pass || pass == atlas->pass_mode());
return atlas;
}
+std::shared_ptr<struct tile_atlas> loader_impl::tile_atlas(StringView filename) noexcept(false)
+{
+ fm_assert(!tile_atlas_map.empty());
+ auto it = tile_atlas_map.find(filename);
+ if (it == tile_atlas_map.end())
+ fm_throw("no such tile atlas '{}'"_cf, filename.data());
+ return it->second;
+}
+
ArrayView<String> loader_impl::anim_atlas_list()
{
if (anim_atlases.empty())
diff --git a/loader/impl.hpp b/loader/impl.hpp
index c50cb1d7..673460aa 100644
--- a/loader/impl.hpp
+++ b/loader/impl.hpp
@@ -30,7 +30,8 @@ struct loader_impl final : loader_
StringView shader(StringView filename) noexcept override;
Trade::ImageData2D texture(StringView prefix, StringView filename) noexcept(false);
- std::shared_ptr<struct tile_atlas> tile_atlas(StringView filename, Vector2ub size) noexcept(false) override;
+ std::shared_ptr<struct tile_atlas> tile_atlas(StringView filename, Vector2ub size, Optional<pass_mode> pass) noexcept(false) override;
+ std::shared_ptr<struct tile_atlas> tile_atlas(StringView filename) noexcept(false) override;
ArrayView<String> anim_atlas_list() override;
std::shared_ptr<struct anim_atlas> anim_atlas(StringView name, StringView dir) noexcept(false) override;
const std::vector<serialized_scenery>& sceneries() override;
diff --git a/loader/json.cpp b/loader/json.cpp
index dbe21d50..7e6aae68 100644
--- a/loader/json.cpp
+++ b/loader/json.cpp
@@ -1,6 +1,7 @@
#include "impl.hpp"
#include "compat/assert.hpp"
#include "compat/exception.hpp"
+#include "src/tile-atlas.hpp"
#include "serialize/json-helper.hpp"
#include "serialize/anim.hpp"
#include "serialize/tile-atlas.hpp"
@@ -52,9 +53,14 @@ const scenery_proto& loader_impl::scenery(StringView name) noexcept(false)
namespace floormat {
-std::vector<std::shared_ptr<struct tile_atlas>> loader_::tile_atlases(StringView filename)
+std::vector<std::shared_ptr<struct tile_atlas>> loader_::tile_atlases(StringView filename, pass_mode p)
{
- return json_helper::from_json<std::vector<std::shared_ptr<struct tile_atlas>>>(Path::join(loader_::IMAGE_PATH, filename));
+ auto vec = json_helper::from_json<std::vector<std::shared_ptr<struct tile_atlas>>>(
+ Path::join(loader_::IMAGE_PATH, filename));
+ for (auto& x : vec)
+ if (!x->pass_mode())
+ x->set_pass_mode(p);
+ return vec;
}
} // namespace floormat
diff --git a/loader/loader.hpp b/loader/loader.hpp
index 8883ed8a..1189a02d 100644
--- a/loader/loader.hpp
+++ b/loader/loader.hpp
@@ -1,4 +1,5 @@
#pragma once
+#include "src/pass-mode.hpp"
#include <memory>
#include <vector>
#include <Corrade/Containers/StringView.h>
@@ -15,12 +16,13 @@ struct scenery_proto;
struct loader_
{
virtual StringView shader(StringView filename) noexcept = 0;
- virtual std::shared_ptr<struct tile_atlas> tile_atlas(StringView filename, Vector2ub size) noexcept(false) = 0;
+ virtual std::shared_ptr<struct tile_atlas> tile_atlas(StringView filename, Vector2ub size, Optional<pass_mode> pass) noexcept(false) = 0;
+ virtual std::shared_ptr<struct tile_atlas> tile_atlas(StringView filename) noexcept(false) = 0;
virtual ArrayView<String> anim_atlas_list() = 0;
virtual std::shared_ptr<struct anim_atlas> anim_atlas(StringView name, StringView dir = ANIM_PATH) noexcept(false) = 0;
static void destroy();
static loader_& default_loader() noexcept;
- static std::vector<std::shared_ptr<struct tile_atlas>> tile_atlases(StringView filename);
+ static std::vector<std::shared_ptr<struct tile_atlas>> tile_atlases(StringView filename, pass_mode p);
virtual const std::vector<serialized_scenery>& sceneries() = 0;
virtual const scenery_proto& scenery(StringView name) noexcept(false) = 0;
diff --git a/serialize/tile-atlas.cpp b/serialize/tile-atlas.cpp
index a92dfc28..6a51da4c 100644
--- a/serialize/tile-atlas.cpp
+++ b/serialize/tile-atlas.cpp
@@ -3,12 +3,25 @@
#include "serialize/corrade-string.hpp"
#include "serialize/magnum-vector2i.hpp"
#include "loader/loader.hpp"
-#include <tuple>
-
+#include "serialize/pass-mode.hpp"
+#include <Corrade/Containers/Optional.h>
+#include <Corrade/Containers/String.h>
#include <nlohmann/json.hpp>
using namespace floormat;
+namespace {
+
+struct proxy {
+ String name;
+ Vector2ub size;
+ Optional<pass_mode> passability;
+};
+
+NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(proxy, name, size)
+
+} // namespace
+
namespace nlohmann {
void adl_serializer<std::shared_ptr<tile_atlas>>::to_json(json& j, const std::shared_ptr<const tile_atlas>& x)
@@ -17,18 +30,26 @@ void adl_serializer<std::shared_ptr<tile_atlas>>::to_json(json& j, const std::sh
if (!x)
j = nullptr;
else
- to_json(j, std::tuple<StringView, Vector2ub>{x->name(), x->num_tiles2()});
+ {
+ to_json(j, proxy{x->name(), x->num_tiles2(), NullOpt});
+ if (auto p = x->pass_mode())
+ j["pass-mode"] = *p;
+ }
}
-void adl_serializer<std::shared_ptr<tile_atlas>>::from_json(const json& j, std::shared_ptr<tile_atlas>& x)
+void adl_serializer<std::shared_ptr<tile_atlas>>::from_json(const json& j, std::shared_ptr<tile_atlas>& val)
{
if (j.is_null())
- x = nullptr;
+ val = nullptr;
else
{
- std::tuple<String, Vector2ub> proxy = j;
- const auto& [name, num_tiles] = proxy;
- x = loader.tile_atlas(name, num_tiles);
+ using nlohmann::from_json;
+ proxy x;
+ from_json(j, x);
+ Optional<pass_mode> p;
+ if (j.contains("pass-mode"))
+ p = {InPlaceInit, j["pass-mode"]};
+ val = loader.tile_atlas(x.name, x.size, p);
}
}
diff --git a/serialize/world-reader.cpp b/serialize/world-reader.cpp
index b0e14254..98704599 100644
--- a/serialize/world-reader.cpp
+++ b/serialize/world-reader.cpp
@@ -45,7 +45,9 @@ void reader_state::read_atlases(reader_t& s)
size[0] << s;
size[1] << s;
const auto& [buf, len] = s.read_asciiz_string<atlas_name_max>();
- atlases.push_back(loader.tile_atlas({buf, len}, size));
+ auto atlas = loader.tile_atlas({buf, len});
+ fm_soft_assert(size == atlas->num_tiles2());
+ atlases.push_back(std::move(atlas));
}
}
diff --git a/src/tile-atlas.cpp b/src/tile-atlas.cpp
index 9b3886da..6f9e832f 100644
--- a/src/tile-atlas.cpp
+++ b/src/tile-atlas.cpp
@@ -9,9 +9,9 @@
namespace floormat {
-tile_atlas::tile_atlas(StringView name, const ImageView2D& image, Vector2ub tile_count) :
+tile_atlas::tile_atlas(StringView name, const ImageView2D& image, Vector2ub tile_count, Optional<enum pass_mode> p) :
texcoords_{make_texcoords_array(Vector2ui(image.size()), tile_count)},
- name_{name}, size_{image.size()}, dims_{tile_count}
+ name_{name}, size_{image.size()}, dims_{tile_count}, passability{std::move(p)}
{
constexpr auto variant_max = std::numeric_limits<variant_t>::max();
fm_assert(num_tiles() <= variant_max);
@@ -55,4 +55,13 @@ auto tile_atlas::make_texcoords_array(Vector2ui pixel_size, Vector2ub tile_count
return ptr;
}
+std::size_t tile_atlas::num_tiles() const { return Vector2ui{dims_}.product(); }
+Optional<enum pass_mode> tile_atlas::pass_mode() const { return passability; }
+
+void tile_atlas::set_pass_mode(enum pass_mode p)
+{
+ fm_assert(!passability || passability == p);
+ passability = { InPlaceInit, p };
+}
+
} // namespace floormat
diff --git a/src/tile-atlas.hpp b/src/tile-atlas.hpp
index 066b1122..61f528ef 100644
--- a/src/tile-atlas.hpp
+++ b/src/tile-atlas.hpp
@@ -1,6 +1,8 @@
#pragma once
+#include "src/pass-mode.hpp"
#include <array>
#include <memory>
+#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/String.h>
#include <Magnum/Magnum.h>
#include <Magnum/Math/Vector2.h>
@@ -13,7 +15,7 @@ struct tile_atlas final
using quad = std::array<Vector3, 4>;
using texcoords = std::array<Vector2, 4>;
- tile_atlas(StringView name, const ImageView2D& img, Vector2ub tile_count);
+ tile_atlas(StringView name, const ImageView2D& img, Vector2ub tile_count, Optional<enum pass_mode> pass_mode);
texcoords texcoords_for_id(std::size_t id) const;
static constexpr quad floor_quad(Vector3 center, Vector2 size);
@@ -21,10 +23,12 @@ struct tile_atlas final
static constexpr quad wall_quad_W(Vector3 center, Vector3 size);
static constexpr std::array<UnsignedShort, 6> indices(std::size_t N);
[[maybe_unused]] Vector2ui pixel_size() const { return size_; }
- std::size_t num_tiles() const { return Vector2ui{dims_}.product(); }
+ std::size_t num_tiles() const;
Vector2ub num_tiles2() const { return dims_; }
GL::Texture2D& texture() { return tex_; }
StringView name() const { return name_; }
+ Optional<enum pass_mode> pass_mode() const;
+ void set_pass_mode(enum pass_mode p);
private:
static std::unique_ptr<const texcoords[]> make_texcoords_array(Vector2ui pixel_size, Vector2ub tile_count);
@@ -35,6 +39,7 @@ private:
String name_;
Vector2ui size_;
Vector2ub dims_;
+ Optional<enum pass_mode> passability;
};
constexpr std::array<UnsignedShort, 6> tile_atlas::indices(std::size_t N)
diff --git a/test/json.cpp b/test/json.cpp
index 1ef6feb8..60e464f6 100644
--- a/test/json.cpp
+++ b/test/json.cpp
@@ -16,9 +16,9 @@ namespace floormat {
[[maybe_unused]]
static chunk make_test_chunk()
{
- auto metal1 = loader.tile_atlas("metal1", {2, 2}),
- metal2 = loader.tile_atlas("metal2", {2, 2}),
- tiles = loader.tile_atlas("tiles", {8, 5});
+ auto metal1 = loader.tile_atlas("metal1", {2, 2}, pass_mode::pass),
+ metal2 = loader.tile_atlas("metal2", {2, 2}, pass_mode::blocked),
+ tiles = loader.tile_atlas("tiles", {8, 5}, pass_mode::pass);
constexpr auto N = TILE_MAX_DIM;
chunk c;
for (auto [x, k, pt] : c) {
@@ -37,7 +37,7 @@ void test_app::test_json() // NOLINT(readability-convert-member-functions-to-sta
fm_assert(Path::exists("../CMakeCache.txt"));
constexpr auto output_dir = "../test/."_s;
{
- auto atlas = loader.tile_atlas("metal1", {2, 2});
+ auto atlas = loader.tile_atlas("metal1", {2, 2}, pass_mode::pass);
json_helper::to_json(atlas, Path::join(output_dir, "atlas.json"));
}
{
diff --git a/test/serializer.cpp b/test/serializer.cpp
index 8a22d0e5..9f382602 100644
--- a/test/serializer.cpp
+++ b/test/serializer.cpp
@@ -11,9 +11,9 @@ namespace Path = Corrade::Utility::Path;
static chunk make_test_chunk()
{
- auto metal1 = loader.tile_atlas("metal1", {2, 2}),
- metal2 = loader.tile_atlas("metal2", {2, 2}),
- tiles = loader.tile_atlas("tiles", {8, 5});
+ auto metal1 = loader.tile_atlas("metal1", {2, 2}, pass_mode::pass),
+ metal2 = loader.tile_atlas("metal2", {2, 2}, pass_mode::blocked),
+ tiles = loader.tile_atlas("tiles", {8, 5}, pass_mode::pass);
constexpr auto N = TILE_MAX_DIM;
chunk c;
for (auto [x, k, pt] : c)