summaryrefslogtreecommitdiffhomepage
path: root/src/wall-atlas.hpp
blob: 8df0c1ec47b83de40603712a6670c8acccfede94 (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
#pragma once
#include "compat/defs.hpp"
#include "src/rotation.hpp"
#include <array>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/String.h>
#include <Magnum/Math/Vector2.h>
#include <Magnum/Math/Color.h>
#include <Magnum/GL/Texture.h>

namespace floormat { class wall_atlas; }

namespace floormat::Wall {

struct Frame
{
    Vector2ui offset = { (unsigned)-1, (unsigned)-1 };

    bool operator==(const Frame&) const noexcept;
};

struct Group
{
    uint32_t index = (uint32_t)-1, count = 0;
    Vector2ui pixel_size;
    Color4 tint_mult{1,1,1,1};
    Color3 tint_add;
    uint8_t from_rotation = (uint8_t)-1; // applies only to images
    bool mirrored                : 1 = false,
         default_tint            : 1 = true;

    explicit operator bool() const noexcept { return !is_empty(); }
    bool is_empty() const noexcept { return count == 0; }

    bool operator==(const Group&) const noexcept;
};

enum class Tag : uint8_t { wall, overlay, side, top, corner_L, corner_R, COUNT };

enum class Direction_ : uint8_t { N, E, S, W, COUNT };

struct Direction
{
    using memfn_ptr = Group Direction::*;
    struct member_tuple { StringView str; memfn_ptr member; Tag tag; };

    explicit operator bool() const noexcept { return !is_empty(); }
    bool is_empty() const noexcept;

    Group wall, overlay, side, top;
    Group corner_L, corner_R;

    static constexpr inline member_tuple members[] = {
        { "wall"_s,     &Direction::wall,     Tag::wall      },
        { "overlay"_s,  &Direction::overlay,  Tag::overlay   },
        { "side"_s,     &Direction::side,     Tag::side      },
        { "top"_s,      &Direction::top,      Tag::top       },
        { "corner-L"_s, &Direction::corner_L, Tag::corner_L, },
        { "corner-R"_s, &Direction::corner_R, Tag::corner_R, },
    };
    static_assert(arraySize(members) == (size_t)Tag::COUNT);

    bool operator==(const Direction&) const noexcept;
};

struct Info
{
    String name = "(unnamed)"_s, description = {};
    unsigned depth = 0;

    bool operator==(const Info&) const noexcept;
};

struct DirArrayIndex {
    std::uint8_t val = (uint8_t)-1;
    operator bool() const { return val == (uint8_t)-1; }

    bool operator==(const DirArrayIndex&) const noexcept;
};

} // namespace floormat::Wall

namespace floormat {

class wall_atlas final
{
    using Frame = Wall::Frame;
    using Group = Wall::Group;
    using Direction_ = Wall::Direction_;
    using Direction = Wall::Direction;
    using Info = Wall::Info;
    using Tag = Wall::Tag;
    using DirArrayIndex = Wall::DirArrayIndex;

    Array<Direction> _dir_array;
    Array<Frame> _frame_array;
    Info _info;
    GL::Texture2D _texture;
    std::array<DirArrayIndex, 4> _direction_to_Direction_array_index;

    Direction* get_Direction(Direction_ num) const;

public:
    fm_DECLARE_DELETED_MOVE_ASSIGNMENT(wall_atlas);
    wall_atlas() noexcept;
    ~wall_atlas() noexcept;

    wall_atlas(Info info, const ImageView2D& image,
               Array<Frame> frames, Array<Direction> directions,
               std::array<DirArrayIndex, 4> direction_to_DirArrayIndex);
    StringView name() const;
    uint8_t direction_count() const;

    const Group* group(size_t dir, Tag tag) const;
    const Group* group(const Direction& dir, Tag tag) const;
    const Group* group(const Direction* dir, Tag tag) const;
    const Direction* direction(size_t dir) const;
    ArrayView<const Frame> frames(const Group& a) const;
    ArrayView<const Frame> raw_frame_array() const;

    static size_t enum_to_index(enum rotation x);
};


} // namespace floormat