Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/StarDrawable.hpp
blob: b63e7c42980a5770627ca35ffc2d6755f4ca1c9b (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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#pragma once

#include "StarString.hpp"
#include "StarDataStream.hpp"
#include "StarPoly.hpp"
#include "StarColor.hpp"
#include "StarJson.hpp"
#include "StarAssetPath.hpp"

namespace Star {

struct Drawable {
  struct LinePart {
    Line2F line;
    float width;
    Maybe<Color> endColor;
  };

  struct PolyPart {
    PolyF poly;
  };

  struct ImagePart {
    AssetPath image;
    // Transformation of the image in pixel space (0, 0) - (width, height) to
    // the final drawn space
    Mat3F transformation;

    // Add directives to this ImagePart, while optionally keeping the
    // transformed center of the image the same if the directives change the
    // image size.
    ImagePart& addDirectives(Directives const& directives, bool keepImageCenterPosition = false);
    ImagePart& addDirectivesGroup(DirectivesGroup const& directivesGroup, bool keepImageCenterPosition = false);

    // Remove directives from this ImagePart, while optionally keeping the
    // transformed center of the image the same if the directives change the
    // image size.
    ImagePart& removeDirectives(bool keepImageCenterPosition = false);
  };

  static Drawable makeLine(Line2F const& line, float lineWidth, Color const& color, Vec2F const& position = Vec2F());
  static Drawable makePoly(PolyF poly, Color const& color, Vec2F const& position = Vec2F());
  static Drawable makeImage(AssetPath image, float pixelSize, bool centered, Vec2F const& position, Color const& color = Color::White);

  template <typename DrawablesContainer>
  static void translateAll(DrawablesContainer& drawables, Vec2F const& translation);

  template <typename DrawablesContainer>
  static void rotateAll(DrawablesContainer& drawables, float rotation, Vec2F const& rotationCenter = Vec2F());

  template <typename DrawablesContainer>
  static void scaleAll(DrawablesContainer& drawables, float scaling, Vec2F const& scaleCenter = Vec2F());

  template <typename DrawablesContainer>
  static void scaleAll(DrawablesContainer& drawables, Vec2F const& scaling, Vec2F const& scaleCenter = Vec2F());

  template <typename DrawablesContainer>
  static void transformAll(DrawablesContainer& drawables, Mat3F const& transformation);

  template <typename DrawablesContainer>
  static void rebaseAll(DrawablesContainer& drawables, Vec2F const& newBase = Vec2F());

  template <typename DrawablesContainer>
  static RectF boundBoxAll(DrawablesContainer const& drawables, bool cropImages);

  Drawable();
  explicit Drawable(Json const& json);

  Json toJson() const;

  void translate(Vec2F const& translation);
  void rotate(float rotation, Vec2F const& rotationCenter = Vec2F());
  void scale(float scaling, Vec2F const& scaleCenter = Vec2F());
  void scale(Vec2F const& scaling, Vec2F const& scaleCenter = Vec2F());
  void transform(Mat3F const& transformation);

  // Change the base position of a drawable without changing the position that
  // the drawable appears, useful to re-base a set of drawables at the same
  // position so that they will be transformed together with minimal drift
  // between them.
  void rebase(Vec2F const& newBase = Vec2F());

  RectF boundBox(bool cropImages) const;

  bool isLine() const;
  LinePart& linePart();
  LinePart const& linePart() const;

  bool isPoly() const;
  PolyPart& polyPart();
  PolyPart const& polyPart() const;

  bool isImage() const;
  ImagePart& imagePart();
  ImagePart const& imagePart() const;

  MVariant<LinePart, PolyPart, ImagePart> part;

  Vec2F position;
  Color color;
  bool fullbright;
};

DataStream& operator>>(DataStream& ds, Drawable& drawable);
DataStream& operator<<(DataStream& ds, Drawable const& drawable);

template <typename DrawablesContainer>
void Drawable::translateAll(DrawablesContainer& drawables, Vec2F const& translation) {
  for (auto& drawable : drawables)
    drawable.translate(translation);
}

template <typename DrawablesContainer>
void Drawable::rotateAll(DrawablesContainer& drawables, float rotation, Vec2F const& rotationCenter) {
  for (auto& drawable : drawables)
    drawable.rotate(rotation, rotationCenter);
}

template <typename DrawablesContainer>
void Drawable::scaleAll(DrawablesContainer& drawables, float scaling, Vec2F const& scaleCenter) {
  for (auto& drawable : drawables)
    drawable.scale(scaling, scaleCenter);
}

template <typename DrawablesContainer>
void Drawable::scaleAll(DrawablesContainer& drawables, Vec2F const& scaling, Vec2F const& scaleCenter) {
  for (auto& drawable : drawables)
    drawable.scale(scaling, scaleCenter);
}

template <typename DrawablesContainer>
void Drawable::transformAll(DrawablesContainer& drawables, Mat3F const& transformation) {
  for (auto& drawable : drawables)
    drawable.transform(transformation);
}

template <typename DrawablesContainer>
void Drawable::rebaseAll(DrawablesContainer& drawables, Vec2F const& newBase) {
  for (auto& drawable : drawables)
    drawable.rebase(newBase);
}

template <typename DrawablesContainer>
RectF Drawable::boundBoxAll(DrawablesContainer const& drawables, bool cropImages) {
  RectF boundBox = RectF::null();
  for (auto const& drawable : drawables)
    boundBox.combine(drawable.boundBox(cropImages));
  return boundBox;
}

inline bool Drawable::isLine() const {
  return part.is<LinePart>();
}

inline Drawable::LinePart& Drawable::linePart() {
  return part.get<LinePart>();
}

inline Drawable::LinePart const& Drawable::linePart() const {
  return part.get<LinePart>();
}

inline bool Drawable::isPoly() const {
  return part.is<PolyPart>();
}

inline Drawable::PolyPart& Drawable::polyPart() {
  return part.get<PolyPart>();
}

inline Drawable::PolyPart const& Drawable::polyPart() const {
  return part.get<PolyPart>();
}

inline bool Drawable::isImage() const {
  return part.is<ImagePart>();
}

inline Drawable::ImagePart& Drawable::imagePart() {
  return part.get<ImagePart>();
}

inline Drawable::ImagePart const& Drawable::imagePart() const {
  return part.get<ImagePart>();
}

}