]> git.localhorst.tv Git - blobs.git/blob - src/ui/ui.cpp
fix resource locator
[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 , pos(new Label(assets.fonts.medium))
25 , tile(new Label(assets.fonts.medium))
26 , goal(new Label(assets.fonts.medium))
27 , needs(new Panel)
28 , panel()
29 , health_meter(new Meter)
30 , need_meters() {
31         Label *health_label = new Label(assets.fonts.medium);
32         health_label->Text("Health");
33         health_meter
34                 ->Size(glm::vec2(100.0f, assets.fonts.medium.Height() + assets.fonts.medium.Descent()))
35                 ->Padding(glm::vec2(1.0f))
36                 ->Border(1.0f)
37                 ->FillColor(glm::vec4(0.9f, 0.0f, 0.0f, 1.0f))
38                 ->BorderColor(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
39         Panel *health_panel = new Panel;
40         health_panel
41                 ->Add(health_label)
42                 ->Add(health_meter)
43                 ->Spacing(10.0f)
44                 ->Direction(Panel::HORIZONTAL);
45
46         age->Text("0000s");
47         Label *age_label = new Label(assets.fonts.medium);
48         age_label->Text("Age");
49         Panel *age_panel = new Panel;
50         age_panel
51                 ->Add(age_label)
52                 ->Add(age)
53                 ->Spacing(10.0f)
54                 ->Direction(Panel::HORIZONTAL);
55
56         mass->Text("00.000kg");
57         Label *mass_label = new Label(assets.fonts.medium);
58         mass_label->Text("Mass");
59         Panel *mass_panel = new Panel;
60         mass_panel
61                 ->Add(mass_label)
62                 ->Add(mass)
63                 ->Spacing(10.0f)
64                 ->Direction(Panel::HORIZONTAL);
65
66         pos->Text("<00.0, 00.0, 00.0>");
67         Label *pos_label = new Label(assets.fonts.medium);
68         pos_label->Text("Pos");
69         Panel *pos_panel = new Panel;
70         pos_panel
71                 ->Add(pos_label)
72                 ->Add(pos)
73                 ->Spacing(10.0f)
74                 ->Direction(Panel::HORIZONTAL);
75
76         tile->Text("<00, 00> (mountains)");
77         Label *tile_label = new Label(assets.fonts.medium);
78         tile_label->Text("Tile");
79         Panel *tile_panel = new Panel;
80         tile_panel
81                 ->Add(tile_label)
82                 ->Add(tile)
83                 ->Spacing(10.0f)
84                 ->Direction(Panel::HORIZONTAL);
85
86         goal->Text("long goal description");
87         Label *goal_label = new Label(assets.fonts.medium);
88         goal_label->Text("Goal");
89         Panel *goal_panel = new Panel;
90         goal_panel
91                 ->Add(goal_label)
92                 ->Add(goal)
93                 ->Spacing(10.0f)
94                 ->Direction(Panel::HORIZONTAL);
95
96         panel
97                 .Add(name)
98                 ->Add(age_panel)
99                 ->Add(mass_panel)
100                 ->Add(pos_panel)
101                 ->Add(tile_panel)
102                 ->Add(goal_panel)
103                 ->Add(health_panel)
104                 ->Add(needs)
105                 ->Padding(glm::vec2(10.0f))
106                 ->Spacing(10.0f)
107                 ->Direction(Panel::VERTICAL)
108                 ->Background(glm::vec4(0.7f, 0.7f, 0.7f, 1.0f));
109 }
110
111 CreaturePanel::~CreaturePanel() {
112 }
113
114
115 void CreaturePanel::Show(creature::Creature &cr) {
116         c = &cr;
117         name->Text(c->Name());
118         CreateNeeds();
119 }
120
121 void CreaturePanel::CreateNeeds() {
122         needs->Clear()->Reserve(c->Needs().size());
123         need_meters.clear();
124         need_meters.reserve(c->Needs().size());
125         for (auto &need : c->Needs()) {
126                 Label *label = new Label(assets.fonts.medium);
127                 label->Text(need->name);
128                 Meter *meter = new Meter;
129                 meter
130                         ->Value(1.0f - need->value)
131                         ->Size(glm::vec2(100.0f, assets.fonts.medium.Height() + assets.fonts.medium.Descent()))
132                         ->Padding(glm::vec2(1.0f))
133                         ->Border(1.0f)
134                         ->FillColor(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f))
135                         ->BorderColor(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
136                 Panel *need_panel = new Panel;
137                 need_panel
138                         ->Direction(Panel::HORIZONTAL)
139                         ->Spacing(10.0f)
140                         ->Add(label)
141                         ->Add(meter);
142                 needs->Add(need_panel);
143                 need_meters.push_back(meter);
144         }
145         panel.Relayout();
146 }
147
148 void CreaturePanel::Hide() noexcept {
149         c = nullptr;
150 }
151
152 void CreaturePanel::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
153         if (!c) return;
154
155         age->Text(std::to_string(int(c->Age())) + "s");
156         {
157                 std::stringstream ss;
158                 ss << std::fixed << std::setprecision(3) << c->Mass() << "kg";
159                 mass->Text(ss.str());
160         }
161         {
162                 const glm::dvec3 &p = c->GetSituation().Position();
163                 std::stringstream ss;
164                 ss << std::fixed << std::setprecision(1)
165                         << "<" << p.x << ", " << p.y << ", " << p.z << ">";
166                 pos->Text(ss.str());
167         }
168         {
169                 glm::ivec2 t = c->GetSituation().SurfacePosition();
170                 std::stringstream ss;
171                 ss << std::fixed << std::setprecision(1)
172                         << "<" << t.x << ", " << t.y
173                         << "> (" << c->GetSituation().GetTileType().label << ")";
174                 tile->Text(ss.str());
175         }
176         if (c->Goals().empty()) {
177                 goal->Text("none");
178         } else {
179                 goal->Text(c->Goals()[0]->Describe());
180         }
181         health_meter->Value(c->Health());
182
183         if (need_meters.size() != c->Needs().size()) {
184                 CreateNeeds();
185         } else {
186                 auto need = c->Needs().begin();
187                 auto need_end = c->Needs().end();
188                 auto meter = need_meters.begin();
189                 for (; need != need_end; ++need, ++meter) {
190                         (*meter)->Value(1.0f - (*need)->value);
191                         if ((*need)->IsSatisfied()) {
192                                 (*meter)->FillColor(glm::vec4(0.0f, 0.7f, 0.0f, 1.0f));
193                         } else if ((*need)->IsInconvenient()) {
194                                 (*meter)->FillColor(glm::vec4(0.7f, 0.5f, 0.0f, 1.0f));
195                         } else {
196                                 (*meter)->FillColor(glm::vec4(0.9f, 0.0f, 0.0f, 1.0f));
197                         }
198                 }
199         }
200
201         const glm::vec2 margin(20.0f);
202
203         panel.Position(glm::vec2(viewport.Width() - margin.x - panel.Size().x, margin.y));
204         panel.Draw(assets, viewport);
205 }
206
207 }
208 }