summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-04-11 21:31:35 +0200
committerStanislaw Halik <sthalik@misaki.pl>2024-04-11 21:49:45 +0200
commit2c042d30d96827941e5052d4eca0cc03965cacc8 (patch)
tree21ad2b6e71890f41fec48ceafde8de22ae8fd6ba /src
parentc362121f04ffe72eed17126affc9129bbb354c49 (diff)
w
Diffstat (limited to 'src')
-rw-r--r--src/light.hpp2
-rw-r--r--src/scenery.cpp278
-rw-r--r--src/scenery.hpp79
3 files changed, 163 insertions, 196 deletions
diff --git a/src/light.hpp b/src/light.hpp
index f32edb21..0033f1c5 100644
--- a/src/light.hpp
+++ b/src/light.hpp
@@ -26,7 +26,7 @@ struct light final : object
float max_distance;
Color4ub color;
light_falloff falloff : 2;
- uint8_t enabled : 1;
+ bool enabled : 1;
light(object_id id, class chunk& c, const light_proto& proto);
diff --git a/src/scenery.cpp b/src/scenery.cpp
index df9fffba..6f49cfca 100644
--- a/src/scenery.cpp
+++ b/src/scenery.cpp
@@ -11,19 +11,17 @@
namespace floormat {
-namespace {
+// ---------- generic_scenery_proto ----------
-template<typename T> struct proto_to_scenery_;
-template<> struct proto_to_scenery_<generic_scenery_proto> { using type = generic_scenery; };
-template<> struct proto_to_scenery_<door_scenery_proto> { using type = door_scenery; };
-template<typename T> using proto_to_scenery = typename proto_to_scenery_<T>::type;
+bool generic_scenery_proto::operator==(const generic_scenery_proto& p) const = default;
+enum scenery_type generic_scenery_proto::scenery_type() { return scenery_type::generic; }
+
+// ---------- door_scenery_proto ----------
-template<typename T> struct scenery_to_proto_;
-template<> struct scenery_to_proto_<generic_scenery> { using type = generic_scenery_proto; };
-template<> struct scenery_to_proto_<door_scenery> { using type = door_scenery_proto; };
-template<typename T> using scenery_to_proto = typename scenery_to_proto_<T>::type;
+bool door_scenery_proto::operator==(const door_scenery_proto& p) const = default;
+enum scenery_type door_scenery_proto::scenery_type() { return scenery_type::door; }
-} // namespace
+// --- scenery_proto ---
scenery_proto::scenery_proto() noexcept { type = object_type::scenery; }
@@ -32,52 +30,114 @@ scenery_proto::scenery_proto(const scenery_proto&) noexcept = default;
scenery_proto::~scenery_proto() noexcept = default;
scenery_proto::operator bool() const { return atlas != nullptr; }
-bool generic_scenery_proto::operator==(const generic_scenery_proto& p) const = default;
-enum scenery_type generic_scenery_proto::scenery_type() const { return scenery_type::generic; }
-
-void generic_scenery::update(scenery&, size_t&, Ns) {}
-Vector2 generic_scenery::ordinal_offset(const scenery&, Vector2b offset) const { return Vector2(offset); }
-bool generic_scenery::can_activate(const scenery&, size_t) const { return interactive; }
-bool generic_scenery::activate(floormat::scenery&, size_t) { return false; }
-enum scenery_type generic_scenery::scenery_type() const { return scenery_type::generic; }
-
enum scenery_type scenery_proto::scenery_type() const
{
return std::visit(
- [&]<typename T>(const T& x) { return x.scenery_type(); },
+ []<typename T>(const T&) { return T::scenery_type(); },
subtype
);
}
-generic_scenery::operator generic_scenery_proto() const { return { .active = active, .interactive = interactive, }; }
+bool scenery_proto::operator==(const object_proto& e0) const
+{
+ if (type != e0.type)
+ return false;
+
+ if (!object_proto::operator==(e0))
+ return false;
-generic_scenery::generic_scenery(object_id, class chunk&, const generic_scenery_proto& p) :
- active{p.active}, interactive{p.interactive}
-{}
+ const auto& sc = static_cast<const scenery_proto&>(e0);
-bool door_scenery_proto::operator==(const door_scenery_proto& p) const = default;
-enum scenery_type door_scenery_proto::scenery_type() const { return scenery_type::door; }
+ if (subtype.index() != sc.subtype.index())
+ return false;
-enum scenery_type door_scenery::scenery_type() const { return scenery_type::door; }
-door_scenery::operator door_scenery_proto() const { return { .active = active, .interactive = interactive, .closing = closing, }; }
+ return std::visit(
+ [](const auto& a, const auto& b) -> bool {
+ if constexpr(std::is_same_v<std::decay_t<decltype(a)>, std::decay_t<decltype(b)>>)
+ return a == b;
+ else
+ fm_assert(false);
+ },
+ subtype, sc.subtype
+ );
+}
-door_scenery::door_scenery(object_id, class chunk&, const door_scenery_proto& p) :
- closing{p.closing}, active{p.active}, interactive{p.interactive}
+// --- scenery ---
+
+enum object_type scenery::type() const override { return object_type::scenery; } // NOLINT(*-convert-*-to-static)
+
+float scenery::depth_offset() const
+{
+ constexpr auto inv_tile_size = 1.f/TILE_SIZE2;
+ Vector2 offset;
+ offset += Vector2(atlas->group(r).depth_offset) * inv_tile_size;
+ float ret = 0;
+ ret += offset[1]*TILE_MAX_DIM + offset[0];
+ ret += tile_shader::scenery_depth_offset;
+
+ return ret;
+}
+
+scenery::operator scenery_proto() const
+{
+ scenery_proto ret;
+ static_cast<object_proto&>(ret) = object::operator object_proto();
+ return ret;
+}
+
+scenery::scenery(object_id id, class chunk& c, const scenery_proto& proto) :
+ object{id, c, proto}
+{
+#ifndef FM_NO_DEBUG
+ if (id != 0)
+ fm_debug_assert(atlas); // todo add placeholder graphic
+#endif
+}
+
+// ---------- generic_scenery ----------
+
+void generic_scenery::update(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; }
+enum scenery_type generic_scenery::scenery_type() const { return scenery_type::generic; }
+
+generic_scenery::operator scenery_proto() const
+{
+ auto p = scenery::operator scenery_proto();
+ p.subtype = operator generic_scenery_proto();
+ return p;
+}
+
+generic_scenery::operator generic_scenery_proto() const
+{
+ return {
+ .active = active,
+ .interactive = interactive,
+ };
+}
+
+generic_scenery::generic_scenery(object_id id, class chunk& c, const generic_scenery_proto& p, const scenery_proto& p0) :
+ scenery{id, c, p0}, active{p.active}, interactive{p.interactive}
{}
-void door_scenery::update(scenery& s, size_t&, Ns dt)
+// ---------- door_scenery ----------
+
+enum scenery_type door_scenery::scenery_type() const { return scenery_type::door; }
+
+void door_scenery::update(size_t&, const Ns& dt)
{
- if (!s.atlas || !active)
+ if (!atlas || !active)
return;
- fm_assert(s.atlas);
- auto& anim = *s.atlas;
+ fm_assert(atlas);
+ auto& anim = *atlas;
const auto nframes = (int)anim.info().nframes;
- const auto n = (int)s.alloc_frame_time(dt, s.delta, s.atlas->info().fps, 1);
+ const auto n = (int)alloc_frame_time(dt, delta, atlas->info().fps, 1);
if (n == 0)
return;
const int8_t dir = closing ? 1 : -1;
- const int fr = s.frame + dir*n;
+ const int fr = frame + dir*n;
active = fr > 0 && fr < nframes-1;
pass_mode p;
if (fr <= 0)
@@ -86,149 +146,61 @@ void door_scenery::update(scenery& s, size_t&, Ns dt)
p = pass_mode::blocked;
else
p = pass_mode::see_through;
- s.set_bbox(s.offset, s.bbox_offset, s.bbox_size, p);
+ set_bbox(offset, bbox_offset, bbox_size, p);
const auto new_frame = (uint16_t)Math::clamp(fr, 0, nframes-1);
//Debug{} << "frame" << new_frame << nframes-1;
- s.frame = new_frame;
+ frame = new_frame;
if (!active)
- s.delta = closing = 0;
- //if ((p == pass_mode::pass) != (old_pass == pass_mode::pass)) Debug{} << "update: need reposition" << (s.frame == 0 ? "-1" : "1");
+ {
+ closing = false;
+ delta = 0;
+ }
+ //if ((p == pass_mode::pass) != (old_pass == pass_mode::pass)) Debug{} << "update: need reposition" << (frame == 0 ? "-1" : "1");
}
-Vector2 door_scenery::ordinal_offset(const scenery& s, Vector2b offset) const
+Vector2 door_scenery::ordinal_offset(Vector2b offset) const
{
constexpr auto bTILE_SIZE = Vector2b(iTILE_SIZE2);
constexpr auto off_closed_ = Vector2b(0, -bTILE_SIZE[1]/2+2);
constexpr auto off_opened_ = Vector2b(-bTILE_SIZE[0]+2, -bTILE_SIZE[1]/2+2);
- const auto off_closed = rotate_point(off_closed_, rotation::N, s.r);
- const auto off_opened = rotate_point(off_opened_, rotation::N, s.r);
- const auto vec = s.frame == s.atlas->info().nframes-1 ? off_closed : off_opened;
+ const auto off_closed = rotate_point(off_closed_, rotation::N, r);
+ const auto off_opened = rotate_point(off_opened_, rotation::N, r);
+ const auto vec = frame == atlas->info().nframes-1 ? off_closed : off_opened;
return Vector2(offset) + Vector2(vec);
}
-bool door_scenery::can_activate(const scenery&, size_t) const { return interactive; }
+bool door_scenery::can_activate(size_t) const { return interactive; }
-bool door_scenery::activate(scenery& s, size_t)
+bool door_scenery::activate(size_t)
{
if (active)
return false;
- fm_assert(s.frame == 0 || s.frame == s.atlas->info().nframes-1);
- closing = s.frame == 0;
- s.frame += closing ? 1 : -1;
+ fm_assert(frame == 0 || frame == atlas->info().nframes-1);
+ closing = frame == 0;
+ frame += closing ? 1 : -1;
active = true;
return true;
}
-bool scenery::can_activate(size_t i) const
+door_scenery::operator scenery_proto() const
{
- if (!atlas)
- return false;
-
- return std::visit(
- [&]<typename T>(const T& sc) { return sc.can_activate(*this, i); },
- subtype
- );
+ auto p = scenery::operator scenery_proto();
+ p.subtype = operator door_scenery_proto();
+ return p;
}
-void scenery::update(size_t& i, const Ns& dt)
+door_scenery::operator door_scenery_proto() const
{
- return std::visit(
- [&]<typename T>(T& sc) { sc.update(*this, i, dt); },
- subtype
- );
+ return {
+ .active = active,
+ .interactive = interactive,
+ .closing = closing,
+ };
}
-Vector2 scenery::ordinal_offset(Vector2b offset) const
-{
- return std::visit(
- [&]<typename T>(const T& sc) { return sc.ordinal_offset(*this, offset); },
- subtype
- );
-}
-
-float scenery::depth_offset() const
-{
- constexpr auto inv_tile_size = 1.f/TILE_SIZE2;
- Vector2 offset;
- offset += Vector2(atlas->group(r).depth_offset) * inv_tile_size;
- float ret = 0;
- ret += offset[1]*TILE_MAX_DIM + offset[0];
- ret += tile_shader::scenery_depth_offset;
-
- return ret;
-}
-
-bool scenery::activate(size_t i)
-{
- return std::visit(
- [&]<typename T>(T& sc) { return sc.activate(*this, i); },
- subtype
- );
-}
-
-bool scenery_proto::operator==(const object_proto& e0) const
-{
- if (type != e0.type)
- return false;
-
- if (!object_proto::operator==(e0))
- return false;
-
- const auto& sc = static_cast<const scenery_proto&>(e0);
-
- if (subtype.index() != sc.subtype.index())
- return false;
-
- return std::visit(
- [](const auto& a, const auto& b) -> bool {
- if constexpr(std::is_same_v<std::decay_t<decltype(a)>, std::decay_t<decltype(b)>>)
- return a == b;
- else
- fm_assert(false);
- },
- subtype, sc.subtype
- );
-}
-
-object_type scenery::type() const noexcept { return object_type::scenery; }
-
-scenery::operator scenery_proto() const
-{
- scenery_proto ret;
- static_cast<object_proto&>(ret) = object::operator object_proto();
- std::visit(
- [&]<typename T>(const T& s) { ret.subtype = scenery_to_proto<T>(s); },
- subtype
- );
- return ret;
-}
-
-enum scenery_type scenery::scenery_type() const
-{
- return std::visit(
- [&]<typename T>(const T& sc) { return sc.scenery_type(); },
- subtype
- );
-}
-
-scenery_variants scenery::subtype_from_proto(object_id id, class chunk& c, const scenery_proto_variants& variant)
-{
- return std::visit(
- [&]<typename T>(const T& p) {
- return scenery_variants { std::in_place_type_t<proto_to_scenery<T>>{}, id, c, p };
- },
- variant
- );
-}
-
-scenery::scenery(object_id id, class chunk& c, const scenery_proto& proto) :
- object{id, c, proto}, subtype{ subtype_from_proto(id, c, proto.subtype) }
-{
-#ifndef FM_NO_DEBUG
- if (id != 0)
- fm_debug_assert(atlas); // todo add placeholder graphic
-#endif
-}
+door_scenery::door_scenery(object_id id, class chunk& c, const door_scenery_proto& p, const scenery_proto& p0) :
+ scenery{id, c, p0}, closing{p.closing}, active{p.active}, interactive{p.interactive}
+{}
} // namespace floormat
diff --git a/src/scenery.hpp b/src/scenery.hpp
index 6729e462..32ba3742 100644
--- a/src/scenery.hpp
+++ b/src/scenery.hpp
@@ -1,6 +1,5 @@
#pragma once
#include "object.hpp"
-#include <type_traits>
#include <variant>
#include <Magnum/Math/Vector2.h>
#include <Magnum/Magnum.h>
@@ -17,21 +16,21 @@ enum class scenery_type : unsigned char {
struct generic_scenery_proto
{
- unsigned char active : 1 = false;
- unsigned char interactive : 1 = false;
+ bool active : 1 = false;
+ bool interactive : 1 = false;
bool operator==(const generic_scenery_proto& p) const;
- enum scenery_type scenery_type() const;
+ static enum scenery_type scenery_type();
};
struct door_scenery_proto
{
- unsigned char active : 1 = false;
- unsigned char interactive : 1 = true;
- unsigned char closing : 1 = false;
+ bool active : 1 = false;
+ bool interactive : 1 = true;
+ bool closing : 1 = false;
bool operator==(const door_scenery_proto& p) const;
- enum scenery_type scenery_type() const;
+ static enum scenery_type scenery_type();
};
using scenery_proto_variants = std::variant<generic_scenery_proto, door_scenery_proto>;
@@ -51,63 +50,59 @@ struct scenery_proto : object_proto
struct scenery;
-struct generic_scenery
+struct scenery : object
{
- unsigned char active : 1 = false;
- unsigned char interactive : 1 = false;
-
- void update(scenery& sc, size_t& i, Ns dt);
- Vector2 ordinal_offset(const scenery& sc, Vector2b offset) const;
- bool can_activate(const scenery& sc, size_t i) const;
- bool activate(scenery& sc, size_t i);
-
- enum scenery_type scenery_type() const;
- explicit operator generic_scenery_proto() const;
+ float depth_offset() const override;
+ enum object_type type() const noexcept override;
+ virtual enum scenery_type scenery_type() const = 0;
- generic_scenery(object_id id, class chunk& c, const generic_scenery_proto& p);
+protected:
+ virtual explicit operator scenery_proto() const;
+ scenery(object_id id, class chunk& c, const scenery_proto& proto);
};
-struct door_scenery
+struct generic_scenery final : scenery
{
- unsigned char closing : 1 = false;
- unsigned char active : 1 = false;
- unsigned char interactive : 1 = false;
+ bool active : 1 = false;
+ bool interactive : 1 = false;
- void update(scenery& sc, size_t& i, Ns dt);
- Vector2 ordinal_offset(const scenery& sc, Vector2b offset) const;
- bool can_activate(const scenery& sc, size_t i) const;
- bool activate(scenery& sc, size_t i);
+ void update(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;
- enum scenery_type scenery_type() const;
- explicit operator door_scenery_proto() const;
+ enum scenery_type scenery_type() const override;
+ explicit operator scenery_proto() const override;
+ explicit operator generic_scenery_proto() const;
- door_scenery(object_id id, class chunk& c, const door_scenery_proto& p);
+private:
+ friend class world;
+ generic_scenery(object_id id, class chunk& c, const generic_scenery_proto& p, const scenery_proto& p0);
};
-using scenery_variants = std::variant<generic_scenery, door_scenery>;
-
-struct scenery final : object
+struct door_scenery final : scenery
{
- scenery_variants subtype;
+ bool closing : 1 = false;
+ bool active : 1 = false;
+ bool interactive : 1 = false;
void update(size_t& i, const Ns& dt) override;
Vector2 ordinal_offset(Vector2b offset) const override;
- float depth_offset() const override;
bool can_activate(size_t i) const override;
bool activate(size_t i) override;
- object_type type() const noexcept override;
- explicit operator scenery_proto() const;
- enum scenery_type scenery_type() const;
-
- static scenery_variants subtype_from_proto(object_id id, class chunk& c, const scenery_proto_variants& variants);
+ enum scenery_type scenery_type() const override;
+ explicit operator scenery_proto() const override;
+ explicit operator door_scenery_proto() const;
private:
friend class world;
- scenery(object_id id, class chunk& c, const scenery_proto& proto);
+ door_scenery(object_id id, class chunk& c, const door_scenery_proto& p, const scenery_proto& p0);
};
template<> struct object_type_<scenery> : std::integral_constant<object_type, object_type::scenery> {};
+template<> struct object_type_<generic_scenery> : std::integral_constant<object_type, object_type::scenery> {};
+template<> struct object_type_<door_scenery> : std::integral_constant<object_type, object_type::scenery> {};
template<> struct object_type_<scenery_proto> : std::integral_constant<object_type, object_type::scenery> {};
} // namespace floormat