6 #include "../app/Assets.hpp"
7 #include "../graphics/Font.hpp"
8 #include "../graphics/Viewport.hpp"
12 #include <glm/gtx/transform.hpp>
18 Label::Label(const graphics::Font &f)
22 , fg_color(0.0f, 0.0f, 0.0f, 1.0f)
23 , bg_color(0.0f, 0.0f, 0.0f, 0.0f)
30 Label *Label::Text(const std::string &t) {
38 Label *Label::Decimal(double n, int prec) {
40 s << std::fixed << std::setprecision(prec) << n;
44 Label *Label::Length(double m) {
46 s << std::fixed << std::setprecision(3);
48 s << (m * 0.001) << "km";
50 s << (m * 1000.0) << "mm";
57 Label *Label::Mass(double kg) {
59 s << std::fixed << std::setprecision(3);
61 s << (kg * 0.001) << "t";
62 } else if (kg < 0.1) {
63 s << (kg * 1000.0) << "g";
64 } else if (kg < 0.0001) {
65 s << (kg * 1.0e6) << "mg";
72 Label *Label::Percentage(double n) {
74 s << std::fixed << std::setprecision(1) << (n * 100.0) << '%';
78 Label *Label::Time(double s) {
82 ss << (is / 3600) << "h ";
86 ss << (is / 60) << "m ";
90 return Text(ss.str());
93 Label *Label::Font(const graphics::Font &f) {
101 Label *Label::Foreground(const glm::vec4 &c) {
106 Label *Label::Background(const glm::vec4 &c) {
111 glm::vec2 Label::Size() {
113 return glm::vec2(0.0f);
119 void Label::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
120 if (text.empty()) return;
122 glm::vec2 size = Size();
124 assets.shaders.alpha_sprite.Activate();
125 assets.shaders.alpha_sprite.SetM(glm::translate(glm::vec3(Position() + (size * 0.5f), -ZIndex()))
126 * glm::scale(glm::vec3(size.x, size.y, 1.0f)));
127 assets.shaders.alpha_sprite.SetTexture(tex);
128 assets.shaders.alpha_sprite.SetFgColor(fg_color);
129 assets.shaders.alpha_sprite.SetBgColor(bg_color);
130 assets.shaders.alpha_sprite.DrawRect();
133 void Label::Update() {
134 if (!dirty || text.empty()) return;
135 font->Render(text, tex);
152 glm::vec2 Meter::Size() {
153 return size + (2.0f * padding) + glm::vec2(2.0f * border);
156 void Meter::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
157 glm::vec2 fullsize = Size();
158 assets.shaders.canvas.Activate();
159 assets.shaders.canvas.ZIndex(ZIndex());
162 assets.shaders.canvas.SetColor(border_color);
163 assets.shaders.canvas.DrawRect(
164 Position() + glm::vec2(border * 0.5f),
165 Position() + fullsize - glm::vec2(border * 0.5f),
171 glm::vec2 bottom_right = Position() + fullsize - glm::vec2(border) - padding;
172 bottom_right.x -= size.x * (1.0f - value);
173 assets.shaders.canvas.SetColor(fill_color);
174 assets.shaders.canvas.FillRect(
175 Position() + glm::vec2(border) + padding,
184 , bg_color(0.0f, 0.0f, 0.0f, 0.0f)
194 Panel *Panel::Add(Widget *w) {
195 std::unique_ptr<Widget> widget(w);
196 glm::vec2 wsize = widget->Size();
197 if (dir == HORIZONTAL) {
199 size.y = std::max(size.y, wsize.y);
201 size.x = std::max(size.x, wsize.x);
204 widgets.emplace_back(std::move(widget));
208 Panel *Panel::Clear() {
210 size = glm::vec2(0.0f);
214 Panel *Panel::Background(const glm::vec4 &c) {
219 Panel *Panel::Padding(const glm::vec2 &p) {
224 Panel *Panel::Spacing(float s) {
229 Panel *Panel::Direction(Dir d) {
235 glm::vec2 Panel::Size() {
236 glm::vec2 space(0.0f);
237 space[dir] = (widgets.size() - 1) * spacing;
238 return (2.0f * padding) + space + size;
241 void Panel::Layout() {
242 size = glm::vec2(0.0f);
243 if (dir == HORIZONTAL) {
244 for (auto &w : widgets) {
245 glm::vec2 wsize = w->Size();
247 size.y = std::max(size.y, wsize.y);
250 for (auto &w : widgets) {
251 glm::vec2 wsize = w->Size();
252 size.x = std::max(size.x, wsize.x);
258 void Panel::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
259 // TODO: separate draw and layout, it's inefficient and the wrong tree order anyway
261 if (bg_color.a > 0.0f) {
262 assets.shaders.canvas.Activate();
263 assets.shaders.canvas.ZIndex(ZIndex());
264 assets.shaders.canvas.SetColor(bg_color);
265 assets.shaders.canvas.FillRect(Position(), Position() + Size());
268 glm::vec2 cursor = Position() + padding;
269 for (auto &w : widgets) {
270 w->Position(cursor)->ZIndex(ZIndex() + 1.0f);
271 w->Draw(assets, viewport);
272 cursor[dir] += w->Size()[dir] + spacing;