summaryrefslogtreecommitdiffhomepage
path: root/serialize/wall-atlas.cpp
blob: 31090e450e7a888fbac94063deb88fcd2b2e64dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "wall-atlas.hpp"
#include "magnum-vector2i.hpp"
#include "magnum-vector.hpp"
#include "compat/exception.hpp"
#include <utility>
#include <string_view>
#include <Corrade/Containers/StringStl.h>
#include <nlohmann/json.hpp>

// todo add test on dummy files that generates 100% coverage on the j.contains() blocks!

namespace floormat {

namespace {

using nlohmann::json;
constexpr auto none = (uint8_t)-1;
using namespace std::string_literals;
constexpr StringView rotation_names[] = { "n"_s, "e"_s, "s"_s, "w"_s, };

size_t rotation_from_name(StringView s)
{
    for (auto i = 0uz; auto n : rotation_names)
    {
        if (n == s)
            return i;
        i++;
    }
    fm_throw("bad rotation name '{}'"_cf, fmt::string_view{s.data(), s.size()});
}

StringView rotation_to_name(size_t i)
{
    fm_soft_assert(i < std::size(rotation_names));
    return rotation_names[i];
}

[[nodiscard]] wall_frames read_frames_metadata(const json& jfs)
{
    wall_frames val;

    if (jfs.contains("pixel-size"s))
        val.pixel_size = jfs["pixel-size"s];
    if (jfs.contains("tint"s))
    {
        std::tie(val.tint_mult, val.tint_add) = std::pair<Vector4, Vector3>{ jfs["tint"s]};
        fm_soft_assert(val.tint_mult >= Color4{0});
    }
    if (jfs.contains("from-rotation"s))
        val.from_rotation = (uint8_t)rotation_from_name(std::string{jfs["from-rotation"s]});
    if (jfs.contains("mirrored"s))
        val.mirrored = jfs["mirrored"s];
    if (jfs.contains("use-default-tint"s))
        val.use_default_tint = jfs["use-default-tint"s];

    return val;
}

[[nodiscard]] wall_frame_set read_frameset_metadata(const json& j)
{
    return {};
}

void read_framesets(const json& jf, wall_atlas_def& val)
{
    fm_soft_assert(jf.is_object());
    fm_soft_assert(val.framesets == nullptr && val.frameset_count == 0);
    uint8_t count = 0;

    static_assert(std::size(rotation_names) == 4);
    for (auto i = 0uz; i < 4; i++)
    {
        const auto& r = rotation_names[i];
        auto key = std::string_view{r.data(), r.size()};
        if (jf.contains(key))
        {
            fm_soft_assert(jf[key].is_object());
            auto& index = val.frameset_indexes[i];
            fm_soft_assert(index == none);
            index = count++;
        }
    }
    fm_soft_assert(count > 0);
    fm_soft_assert(count == jf.size());

    val.framesets = std::make_unique<wall_frame_set[]>(count);
    val.frameset_count = count;

    for (auto i = 0uz; i < 4; i++)
    {
        auto index = val.frameset_indexes[i];
        if (index == none)
            continue;
        auto r = rotation_to_name(i);
        auto key = std::string_view{r.data(), r.size()};

        fm_debug_assert(index < val.frameset_count);
        val.framesets[index] = read_frameset_metadata(jf[key]);
    }
}

void write_frameset_metadata(json& j, const wall_atlas& a, const wall_frames& val, size_t rot)
{
    constexpr wall_frames default_value;

    fm_soft_assert(val.count != (uint32_t)-1);
    fm_soft_assert(val.index == (uint32_t)-1 || val.index < a.frame_array().size());
    fm_soft_assert((val.index == (uint32_t)-1) == (val.count == 0));

    j["name"s] = rotation_to_name(rot);
    j["pixel-size"s] = val.pixel_size;
    if (val.tint_mult != default_value.tint_mult || val.tint_add != default_value.tint_add)
    {
        auto tint = std::pair<Vector4, Vector3>{{val.tint_mult}, {val.tint_add}};
        j["tint"s] = tint;
    }
    if (val.from_rotation != default_value.from_rotation)
    {
        fm_soft_assert(val.from_rotation != none && val.from_rotation < 4);
        j["from-rotation"s] = val.from_rotation;
    }
    if (val.mirrored != default_value.mirrored)
        j["mirrored"s] = val.mirrored;
    if (val.use_default_tint)
        if (val.tint_mult != default_value.tint_mult || val.tint_add != default_value.tint_add)
            j["use-default-tint"s] = true;
}

} // namespace

void Serialize::wall_test::read_atlas_header(const json& j, wall_atlas_def& val)
{
    val = {};
    val.info = { std::string(j["name"s]), j["depth"], };
    val.frame_count = (uint32_t)j["frames"s].size();
    read_framesets(j["framesets"s], val);
}

} // namespace floormat

namespace nlohmann {

using namespace floormat;

void adl_serializer<std::shared_ptr<wall_atlas>>::to_json(json& j, const std::shared_ptr<const wall_atlas>& x)
{

}

void adl_serializer<std::shared_ptr<wall_atlas>>::from_json(const json& j, std::shared_ptr<wall_atlas>& x)
{

}

} // namespace nlohmann