summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--anim-crop-tool/main.cpp3
-rw-r--r--anim/table.json11
-rw-r--r--anim/table.tgabin175134 -> 87626 bytes
-rw-r--r--draw/anim.cpp3
-rw-r--r--editor/draw.cpp6
-rw-r--r--editor/update.cpp2
-rw-r--r--loader/atlas.cpp16
-rw-r--r--main/clickable.hpp1
-rw-r--r--main/draw.cpp3
-rw-r--r--serialize/anim.cpp27
-rw-r--r--src/anim-atlas.cpp22
-rw-r--r--src/anim-atlas.hpp2
-rw-r--r--src/anim.hpp2
-rw-r--r--src/scenery.cpp4
14 files changed, 78 insertions, 24 deletions
diff --git a/anim-crop-tool/main.cpp b/anim-crop-tool/main.cpp
index ec08b257..5b6fa31e 100644
--- a/anim-crop-tool/main.cpp
+++ b/anim-crop-tool/main.cpp
@@ -130,6 +130,9 @@ static bool load_file(anim_group& group, options& opts, anim_atlas_& atlas, Stri
[[nodiscard]]
static bool load_directory(anim_group& group, options& opts, anim_atlas_& atlas)
{
+ if (!group.mirror_from.isEmpty())
+ return true;
+
const auto input_dir = Path::join(opts.input_dir, group.name);
if (!Path::exists(Path::join(input_dir, ".")))
diff --git a/anim/table.json b/anim/table.json
index 3b15dbc0..f472a4cd 100644
--- a/anim/table.json
+++ b/anim/table.json
@@ -20,14 +20,7 @@
]
},
{
- "frames": [
- {
- "ground": "90 x 88",
- "offset": "0 x 164",
- "size": "180 x 164"
- }
- ],
- "ground": "959 x 712",
+ "mirror-from": "n",
"name": "w",
"offset": [
0,
@@ -39,6 +32,6 @@
"height": 0,
"nframes": 1,
"object_name": "table",
- "pixel_size": "180 x 328",
+ "pixel_size": "180 x 164",
"width": 180
}
diff --git a/anim/table.tga b/anim/table.tga
index a3c6aed6..1f6083fc 100644
--- a/anim/table.tga
+++ b/anim/table.tga
Binary files differ
diff --git a/draw/anim.cpp b/draw/anim.cpp
index 558dd197..82f0d746 100644
--- a/draw/anim.cpp
+++ b/draw/anim.cpp
@@ -26,7 +26,8 @@ void anim_mesh::draw(tile_shader& shader, anim_atlas& atlas, rotation r, std::si
{
const auto center = Vector3(xy.x, xy.y, 0.f) * TILE_SIZE;
const auto pos = atlas.frame_quad(center, r, frame);
- const auto texcoords = atlas.texcoords_for_frame(r, frame);
+ const auto& g = atlas.group(r);
+ const auto texcoords = atlas.texcoords_for_frame(r, frame, !g.mirror_from.isEmpty());
const float depth = tile_shader::depth_value(xy, .25f);
quad_data array;
for (std::size_t i = 0; i < 4; i++)
diff --git a/editor/draw.cpp b/editor/draw.cpp
index 17be7aeb..dd4cf96b 100644
--- a/editor/draw.cpp
+++ b/editor/draw.cpp
@@ -52,7 +52,11 @@ clickable_scenery* app::find_clickable_scenery(Vector2i pixel_)
for (clickable_scenery& c : array)
if (c.depth > depth && c.dest.contains(pixel))
{
- const auto pos = pixel - c.dest.min() + c.src.min();
+
+ const auto pos_ = pixel - c.dest.min() + c.src.min();
+ const auto pos = c.atlas.group(c.item.r).mirror_from.isEmpty()
+ ? pos_
+ : Vector2ui(c.src.sizeX() - pos_[0], pos_[1]);
const auto stride = c.atlas.info().pixel_size[0];
std::size_t idx = pos.y() * stride + pos.x();
fm_debug_assert(idx < c.bitmask.size());
diff --git a/editor/update.cpp b/editor/update.cpp
index 9e479050..0c347f1d 100644
--- a/editor/update.cpp
+++ b/editor/update.cpp
@@ -31,7 +31,7 @@ void app::maybe_initialize_chunk_(const chunk_coords& pos, chunk& c)
c[{K, K+1}].wall_north() = { _wall1, 0 };
c[{K+1, K }].wall_west() = { _wall2, 0 };
c[{K+3, K+1}].scenery() = { scenery::door, rotation::N, _door, false };
- c[{ 3, 4 }].scenery() = { scenery::generic, rotation::N, _table };
+ c[{ 3, 4 }].scenery() = { scenery::generic, rotation::W, _table };
c[{K, K+1}].scenery() = { scenery::generic, rotation::N, _control_panel, true };
c.mark_modified();
}
diff --git a/loader/atlas.cpp b/loader/atlas.cpp
index 1aaa4e31..659f716a 100644
--- a/loader/atlas.cpp
+++ b/loader/atlas.cpp
@@ -3,6 +3,7 @@
#include "src/emplacer.hpp"
#include "src/tile-atlas.hpp"
#include "src/anim-atlas.hpp"
+#include <algorithm>
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/StridedArrayView.h>
@@ -34,6 +35,21 @@ std::shared_ptr<anim_atlas> loader_impl::anim_atlas(StringView name)
{
const auto path = Path::join(ANIM_PATH, Path::splitExtension(name).first());
auto anim_info = deserialize_anim(path + ".json");
+
+ for (anim_group& group : anim_info.groups)
+ {
+ if (!group.mirror_from.isEmpty())
+ {
+ auto it = std::find_if(anim_info.groups.cbegin(), anim_info.groups.cend(),
+ [&](const anim_group& x) { return x.name == group.mirror_from; });
+ if (it == anim_info.groups.cend())
+ fm_abort("can't find group '%s' to mirror from '%s'", group.mirror_from.data(), group.name.data());
+ group.frames = it->frames;
+ for (anim_frame& f : group.frames)
+ f.ground = Vector2i((Int)f.size[0] - f.ground[0], f.ground[1]);
+ }
+ }
+
auto tex = texture("", path);
fm_assert(!anim_info.object_name.isEmpty());
diff --git a/main/clickable.hpp b/main/clickable.hpp
index efc1a7fa..3eee243f 100644
--- a/main/clickable.hpp
+++ b/main/clickable.hpp
@@ -15,6 +15,7 @@ struct clickable final {
float depth = 0;
chunk_coords chunk;
local_coords pos;
+ bool mirrored = false;
};
} // namespace floormat
diff --git a/main/draw.cpp b/main/draw.cpp
index aa1b6f2e..0b797449 100644
--- a/main/draw.cpp
+++ b/main/draw.cpp
@@ -122,7 +122,8 @@ void main_impl::draw_anim() noexcept
clickable<anim_atlas, scenery> item = {
*atlas, s,
{ f.offset, f.offset + f.size }, { offset, offset + f.size },
- atlas->bitmask(), tile_shader::depth_value(xy, 0.25f), pos, xy
+ atlas->bitmask(), tile_shader::depth_value(xy, 0.25f), pos, xy,
+ !g.mirror_from.isEmpty(),
};
_clickable_scenery.push_back(item);
}
diff --git a/serialize/anim.cpp b/serialize/anim.cpp
index 8080bb02..fd5e7315 100644
--- a/serialize/anim.cpp
+++ b/serialize/anim.cpp
@@ -18,8 +18,31 @@ namespace nlohmann {
void adl_serializer<anim_frame>::to_json(json& j, const anim_frame& val) { using nlohmann::to_json; to_json(j, val); }
void adl_serializer<anim_frame>::from_json(const json& j, anim_frame& val) { using nlohmann::from_json; from_json(j, val); }
-void adl_serializer<anim_group>::to_json(json& j, const anim_group& val) { using nlohmann::to_json; to_json(j, val); }
-void adl_serializer<anim_group>::from_json(const json& j, anim_group& val) { using nlohmann::from_json; from_json(j, val); }
+void adl_serializer<anim_group>::to_json(json& j, const anim_group& val)
+{
+ using nlohmann::to_json;
+ if (!val.mirror_from.isEmpty())
+ {
+ j["name"] = val.name;
+ j["mirror-from"] = val.mirror_from;
+ j["offset"] = val.offset;
+ }
+ else
+ to_json(j, val);
+}
+
+void adl_serializer<anim_group>::from_json(const json& j, anim_group& val)
+{
+ using nlohmann::from_json;
+ if (j.contains("mirror-from"))
+ {
+ val.name = j["name"];
+ val.mirror_from = j["mirror-from"];
+ val.offset = j["offset"];
+ }
+ else
+ from_json(j, val);
+}
void adl_serializer<anim_def>::to_json(json& j, const anim_def& val) { using nlohmann::to_json; to_json(j, val); }
void adl_serializer<anim_def>::from_json(const json& j, anim_def& val) { using nlohmann::from_json; from_json(j, val); }
diff --git a/src/anim-atlas.cpp b/src/anim-atlas.cpp
index 33b107df..e8d4bd9b 100644
--- a/src/anim-atlas.cpp
+++ b/src/anim-atlas.cpp
@@ -70,18 +70,26 @@ auto anim_atlas::frame(rotation r, std::size_t frame) const noexcept -> const an
return g.frames[frame];
}
-auto anim_atlas::texcoords_for_frame(rotation r, std::size_t i) const noexcept -> texcoords
+auto anim_atlas::texcoords_for_frame(rotation r, std::size_t i, bool mirror) const noexcept -> texcoords
{
const auto f = frame(r, i);
const Vector2 p0(f.offset), p1(f.size);
const auto x0 = p0.x()+.5f, x1 = p1.x()-1, y0 = p0.y()+.5f, y1 = p1.y()-1;
const auto size = _info.pixel_size;
- return {{
- { (x0+x1) / size[0], 1 - (y0+y1) / size[1] }, // bottom right
- { (x0+x1) / size[0], 1 - y0 / size[1] }, // top right
- { x0 / size[0], 1 - (y0+y1) / size[1] }, // bottom left
- { x0 / size[0], 1 - y0 / size[1] }, // top left
- }};
+ if (!mirror)
+ return {{
+ { (x0+x1) / size[0], 1 - (y0+y1) / size[1] }, // bottom right
+ { (x0+x1) / size[0], 1 - y0 / size[1] }, // top right
+ { x0 / size[0], 1 - (y0+y1) / size[1] }, // bottom left
+ { x0 / size[0], 1 - y0 / size[1] }, // top left
+ }};
+ else
+ return {{
+ { x0 / size[0], 1 - (y0+y1) / size[1] }, // bottom right
+ { x0 / size[0], 1 - y0 / size[1] }, // top right
+ { (x0+x1) / size[0], 1 - (y0+y1) / size[1] }, // bottom left
+ { (x0+x1) / size[0], 1 - y0 / size[1] }, // top left
+ }};
}
auto anim_atlas::frame_quad(const Vector3& center, rotation r, std::size_t i) const noexcept -> quad
diff --git a/src/anim-atlas.hpp b/src/anim-atlas.hpp
index 5b79ca19..b25ff489 100644
--- a/src/anim-atlas.hpp
+++ b/src/anim-atlas.hpp
@@ -30,7 +30,7 @@ struct anim_atlas final
const anim_group& group(rotation r) const noexcept;
const anim_frame& frame(rotation r, std::size_t frame) const noexcept;
- texcoords texcoords_for_frame(rotation r, std::size_t frame) const noexcept;
+ texcoords texcoords_for_frame(rotation r, std::size_t frame, bool mirror) const noexcept;
quad frame_quad(const Vector3& center, rotation r, std::size_t frame) const noexcept;
BitArrayView bitmask() const;
diff --git a/src/anim.hpp b/src/anim.hpp
index 1a4011dc..674895ed 100644
--- a/src/anim.hpp
+++ b/src/anim.hpp
@@ -22,7 +22,7 @@ enum class anim_direction : unsigned char
struct anim_group final
{
- String name;
+ String name, mirror_from;
std::vector<anim_frame> frames;
Vector2ui ground;
Vector3b offset;
diff --git a/src/scenery.cpp b/src/scenery.cpp
index 7c3001b0..eb90b598 100644
--- a/src/scenery.cpp
+++ b/src/scenery.cpp
@@ -56,6 +56,9 @@ scenery::scenery(float dt, frame_t frame, rotation r, bool passable, scenery_typ
bool scenery::can_activate() const noexcept
{
+#if 0
+ return true;
+#else
switch (type)
{
default:
@@ -65,6 +68,7 @@ bool scenery::can_activate() const noexcept
case scenery_type::object:
return true;
}
+#endif
}
void scenery::update(float dt, const anim_atlas& anim)