]> git.localhorst.tv Git - blobs.git/blob - src/ui/ui.cpp
79adbbb970031b751693f6b6bdcedff6aedf83d3
[blobs.git] / src / ui / ui.cpp
1 #include "CreaturePanel.hpp"
2
3 #include "Label.hpp"
4 #include "Meter.hpp"
5 #include "../app/Assets.hpp"
6 #include "../creature/Creature.hpp"
7 #include "../creature/Need.hpp"
8 #include "../graphics/Viewport.hpp"
9
10 #include <iomanip>
11 #include <sstream>
12 #include <glm/gtx/transform.hpp>
13
14
15 namespace blobs {
16 namespace ui {
17
18 CreaturePanel::CreaturePanel(const app::Assets &assets)
19 : assets(assets)
20 , c(nullptr)
21 , name(new Label(assets.fonts.large))
22 , age(new Label(assets.fonts.medium))
23 , mass(new Label(assets.fonts.medium))
24 , goal(new Label(assets.fonts.medium))
25 , needs(new Panel)
26 , panel()
27 , health_meter(new Meter)
28 , need_meters() {
29         Label *health_label = new Label(assets.fonts.medium);
30         health_label->Text("Health");
31         health_meter
32                 ->Size(glm::vec2(100.0f, assets.fonts.medium.Height() + assets.fonts.medium.Descent()))
33                 ->Padding(glm::vec2(1.0f))
34                 ->Border(1.0f)
35                 ->FillColor(glm::vec4(0.9f, 0.0f, 0.0f, 1.0f))
36                 ->BorderColor(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
37         Panel *health_panel = new Panel;
38         health_panel
39                 ->Add(health_label)
40                 ->Add(health_meter)
41                 ->Spacing(10.0f)
42                 ->Direction(Panel::HORIZONTAL);
43
44         Label *age_label = new Label(assets.fonts.medium);
45         age_label->Text("Age");
46         Panel *age_panel = new Panel;
47         age_panel
48                 ->Add(age_label)
49                 ->Add(age)
50                 ->Spacing(10.0f)
51                 ->Direction(Panel::HORIZONTAL);
52
53         Label *mass_label = new Label(assets.fonts.medium);
54         mass_label->Text("Mass");
55         Panel *mass_panel = new Panel;
56         mass_panel
57                 ->Add(mass_label)
58                 ->Add(mass)
59                 ->Spacing(10.0f)
60                 ->Direction(Panel::HORIZONTAL);
61
62         Label *goal_label = new Label(assets.fonts.medium);
63         goal_label->Text("Goal");
64         Panel *goal_panel = new Panel;
65         goal_panel
66                 ->Add(goal_label)
67                 ->Add(goal)
68                 ->Spacing(10.0f)
69                 ->Direction(Panel::HORIZONTAL);
70
71         panel
72                 .Add(name)
73                 ->Add(age_panel)
74                 ->Add(mass_panel)
75                 ->Add(goal_panel)
76                 ->Add(health_panel)
77                 ->Add(needs)
78                 ->Padding(glm::vec2(10.0f))
79                 ->Spacing(10.0f)
80                 ->Direction(Panel::VERTICAL)
81                 ->Background(glm::vec4(0.7f, 0.7f, 0.7f, 1.0f));
82 }
83
84 CreaturePanel::~CreaturePanel() {
85 }
86
87
88 void CreaturePanel::Show(creature::Creature &cr) {
89         c = &cr;
90         name->Text(c->Name());
91         CreateNeeds();
92 }
93
94 void CreaturePanel::CreateNeeds() {
95         needs->Clear()->Reserve(c->Needs().size());
96         need_meters.clear();
97         need_meters.reserve(c->Needs().size());
98         for (auto &need : c->Needs()) {
99                 Label *label = new Label(assets.fonts.medium);
100                 label->Text(need->name);
101                 Meter *meter = new Meter;
102                 meter
103                         ->Value(1.0f - need->value)
104                         ->Size(glm::vec2(100.0f, assets.fonts.medium.Height() + assets.fonts.medium.Descent()))
105                         ->Padding(glm::vec2(1.0f))
106                         ->Border(1.0f)
107                         ->FillColor(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f))
108                         ->BorderColor(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
109                 Panel *need_panel = new Panel;
110                 need_panel
111                         ->Direction(Panel::HORIZONTAL)
112                         ->Spacing(10.0f)
113                         ->Add(label)
114                         ->Add(meter);
115                 needs->Add(need_panel);
116                 need_meters.push_back(meter);
117         }
118         panel.Relayout();
119 }
120
121 void CreaturePanel::Hide() noexcept {
122         c = nullptr;
123 }
124
125 void CreaturePanel::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
126         if (!c) return;
127
128         age->Text(std::to_string(int(c->Age())) + "s");
129         {
130                 std::stringstream ss;
131                 ss << std::fixed << std::setprecision(3) << c->Mass() << "kg";
132                 mass->Text(ss.str());
133         }
134         if (c->Goals().empty()) {
135                 goal->Text("none");
136         } else {
137                 goal->Text(c->Goals()[0]->Describe());
138         }
139         health_meter->Value(c->Health());
140
141         if (need_meters.size() != c->Needs().size()) {
142                 CreateNeeds();
143         } else {
144                 auto need = c->Needs().begin();
145                 auto need_end = c->Needs().end();
146                 auto meter = need_meters.begin();
147                 for (; need != need_end; ++need, ++meter) {
148                         (*meter)->Value(1.0f - (*need)->value);
149                         if ((*need)->IsSatisfied()) {
150                                 (*meter)->FillColor(glm::vec4(0.0f, 0.7f, 0.0f, 1.0f));
151                         } else if ((*need)->IsInconvenient()) {
152                                 (*meter)->FillColor(glm::vec4(0.7f, 0.5f, 0.0f, 1.0f));
153                         } else {
154                                 (*meter)->FillColor(glm::vec4(0.9f, 0.0f, 0.0f, 1.0f));
155                         }
156                 }
157         }
158
159         const glm::vec2 margin(20.0f);
160
161         panel.Position(glm::vec2(viewport.Width() - margin.x - panel.Size().x, margin.y));
162         panel.Draw(assets, viewport);
163 }
164
165 }
166 }