1 #include "CreaturePanel.hpp"
2 #include "RecordsPanel.hpp"
4 #include "TimePanel.hpp"
8 #include "../app/Assets.hpp"
9 #include "../creature/Creature.hpp"
10 #include "../graphics/Viewport.hpp"
11 #include "../world/Body.hpp"
12 #include "../world/Simulation.hpp"
17 #include <glm/gtx/io.hpp>
18 #include <glm/gtx/transform.hpp>
24 CreaturePanel::CreaturePanel(app::Assets &assets)
27 , name(new Label(assets.fonts.large))
28 , parents(new Label(assets.fonts.medium))
29 , born(new Label(assets.fonts.medium))
30 , age(new Label(assets.fonts.medium))
31 , mass(new Label(assets.fonts.medium))
32 , goal(new Label(assets.fonts.medium))
33 , composition(new Panel)
37 Label *parents_label = new Label(assets.fonts.medium);
38 parents_label->Text("Parents");
39 Label *born_label = new Label(assets.fonts.medium);
40 born_label->Text("Born");
41 Label *age_label = new Label(assets.fonts.medium);
42 age_label->Text("Age");
43 Label *mass_label = new Label(assets.fonts.medium);
44 mass_label->Text("Mass");
45 Label *goal_label = new Label(assets.fonts.medium);
46 goal_label->Text("Goal");
48 Panel *info_label_panel = new Panel;
50 ->Direction(Panel::VERTICAL)
56 Panel *info_value_panel = new Panel;
58 ->Direction(Panel::VERTICAL)
64 Panel *info_panel = new Panel;
66 ->Direction(Panel::HORIZONTAL)
68 ->Add(info_label_panel)
69 ->Add(info_value_panel);
72 for (int i = 0; i < 7; ++i) {
73 stat_label[i] = new Label(assets.fonts.medium);
76 ->Size(glm::vec2(100.0f, assets.fonts.medium.Height() + assets.fonts.medium.Descent()))
77 ->Padding(glm::vec2(1.0f))
79 ->BorderColor(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
81 stat_label[0]->Text("Damage");
82 stat_label[1]->Text("Breath");
83 stat_label[2]->Text("Thirst");
84 stat_label[3]->Text("Hunger");
85 stat_label[4]->Text("Exhaustion");
86 stat_label[5]->Text("Fatigue");
87 stat_label[6]->Text("Boredom");
89 Panel *stat_label_panel = new Panel;
92 ->Direction(Panel::VERTICAL);
93 Panel *stat_meter_panel = new Panel;
95 ->Spacing(stat_label[0]->Size().y - stats[0]->Size().y + 2)
96 ->Direction(Panel::VERTICAL);
97 for (int i = 0; i < 7; ++i) {
98 stat_label_panel->Add(stat_label[i]);
99 stat_meter_panel->Add(stats[i]);
101 Panel *stat_panel = new Panel;
103 ->Direction(Panel::HORIZONTAL)
105 ->Add(stat_label_panel)
106 ->Add(stat_meter_panel);
108 Label *prop_label[8];
109 for (int i = 0; i < 8; ++i) {
110 prop_label[i] = new Label(assets.fonts.medium);
111 props[i] = new Label(assets.fonts.medium);
113 prop_label[0]->Text("Strength");
114 prop_label[1]->Text("Stamina");
115 prop_label[2]->Text("Dexerty");
116 prop_label[3]->Text("Intelligence");
117 prop_label[4]->Text("Lifetime");
118 prop_label[5]->Text("Fertility");
119 prop_label[6]->Text("Mutability");
120 prop_label[7]->Text("Offspring mass");
122 Panel *prop_label_panel = new Panel;
125 ->Direction(Panel::VERTICAL);
126 Panel *prop_meter_panel = new Panel;
129 ->Direction(Panel::VERTICAL);
130 for (int i = 0; i < 8; ++i) {
131 prop_label_panel->Add(prop_label[i]);
132 prop_meter_panel->Add(props[i]);
134 Panel *prop_panel = new Panel;
136 ->Direction(Panel::HORIZONTAL)
138 ->Add(prop_label_panel)
139 ->Add(prop_meter_panel);
147 ->Padding(glm::vec2(10.0f))
149 ->Direction(Panel::VERTICAL)
150 ->Background(glm::vec4(0.7f, 0.7f, 0.7f, 1.0f));
153 CreaturePanel::~CreaturePanel() {
157 void CreaturePanel::Show(creature::Creature &cr) {
159 name->Text(c->Name());
160 born->Text(TimeString(c->Born()));
162 if (c->Parents().empty()) {
163 parents->Text("none");
165 std::string parent_string;
167 for (auto p : c->Parents()) {
171 parent_string += " and ";
173 parent_string += p->Name();
175 parents->Text(parent_string);
179 void CreaturePanel::Hide() noexcept {
183 void CreaturePanel::Draw(graphics::Viewport &viewport) noexcept {
186 age->Text(TimeString(c->Age()));
187 mass->Text(MassString(c->Mass()));
188 if (c->Goals().empty()) {
191 goal->Text(c->Goals()[0]->Describe());
194 const creature::Composition &comp = c->GetComposition();
195 if (comp.size() < components.size()) {
196 composition->Clear();
197 while (comp.size() < components.size()) {
198 delete components.back();
199 components.pop_back();
201 for (auto l : components) {
205 while (comp.size() > components.size()) {
206 components.emplace_back(new Label(assets.fonts.medium));
207 composition->Add(components.back());
212 for (auto &cmp : comp) {
214 PercentageString(cmp.value / comp.TotalMass())
215 + " " + assets.data.resources[cmp.resource].label);
220 for (int i = 0; i < 7; ++i) {
221 stats[i]->Value(c->GetStats().stat[i].value);
222 if (c->GetStats().stat[i].Okay()) {
223 stats[i]->FillColor(glm::vec4(0.0f, 0.7f, 0.0f, 1.0f));
224 } else if (c->GetStats().stat[i].Critical()) {
225 stats[i]->FillColor(glm::vec4(0.7f, 0.0f, 0.0f, 1.0f));
227 stats[i]->FillColor(glm::vec4(0.9f, 0.4f, 0.0f, 1.0f));
231 props[0]->Text(DecimalString(c->Strength(), 2));
232 props[1]->Text(DecimalString(c->Stamina(), 2));
233 props[2]->Text(DecimalString(c->Dexerty(), 2));
234 props[3]->Text(DecimalString(c->Intelligence(), 2));
235 props[4]->Text(TimeString(c->Lifetime()));
236 props[5]->Text(PercentageString(c->Fertility()));
237 props[6]->Text(PercentageString(c->Mutability()));
238 props[7]->Text(MassString(c->OffspringMass()));
240 const glm::vec2 margin(20.0f);
241 panel.Position(glm::vec2(viewport.Width() - margin.x - panel.Size().x, margin.y));
242 panel.Draw(assets, viewport);
246 RecordsPanel::RecordsPanel(world::Simulation &sim)
248 , live(new Label(sim.Assets().fonts.medium))
252 Label *live_label = new Label(sim.Assets().fonts.medium);
253 live_label->Text("Creatures alive");
255 Panel *label_panel = new Panel;
257 ->Direction(Panel::VERTICAL)
260 Panel *value_panel = new Panel;
262 ->Direction(Panel::VERTICAL)
265 Label *holder_label = new Label(sim.Assets().fonts.medium);
266 holder_label->Text("Holder");
267 Panel *holder_panel = new Panel;
269 ->Direction(Panel::VERTICAL)
272 records.reserve(sim.Records().size());
273 for (const auto &r : sim.Records()) {
274 Label *label = new Label(sim.Assets().fonts.medium);
275 label->Text(r.name + " record");
276 label_panel->Add(label);
277 Label *value = new Label(sim.Assets().fonts.medium);
279 value_panel->Add(value);
280 records.push_back(value);
281 Label *holder = new Label(sim.Assets().fonts.medium);
282 holder->Text("nobody");
283 holder_panel->Add(holder);
284 holders.push_back(holder);
288 .Direction(Panel::HORIZONTAL)
289 ->Padding(glm::vec2(10.0f))
291 ->Background(glm::vec4(0.7f, 0.7f, 0.7f, 1.0f))
297 RecordsPanel::~RecordsPanel() {
300 void RecordsPanel::Draw(graphics::Viewport &viewport) noexcept {
301 live->Text(NumberString(sim.LiveCreatures().size()));
303 for (const auto &r : sim.Records()) {
307 case world::Record::VALUE:
308 records[i]->Text(DecimalString(r.value, 2));
310 case world::Record::LENGTH:
311 records[i]->Text(LengthString(r.value));
313 case world::Record::MASS:
314 records[i]->Text(MassString(r.value));
316 case world::Record::PERCENTAGE:
317 records[i]->Text(PercentageString(r.value));
319 case world::Record::TIME:
320 records[i]->Text(TimeString(r.value));
323 std::string str(r.holder->Name());
325 for (auto p : r.holder->Parents()) {
334 holders[i]->Text(str);
338 const glm::vec2 margin(20.0f);
339 panel.Position(glm::vec2(margin.x, margin.y));
340 panel.Draw(sim.Assets(), viewport);
344 TimePanel::TimePanel(world::Simulation &sim)
347 , time(new Label(sim.Assets().fonts.medium))
348 , clock(new Label(sim.Assets().fonts.medium))
350 Label *time_label = new Label(sim.Assets().fonts.medium);
351 time_label->Text("Time");
352 Label *clock_label = new Label(sim.Assets().fonts.medium);
353 clock_label->Text("Clock");
355 Panel *label_panel = new Panel;
357 ->Direction(Panel::VERTICAL)
361 Panel *value_panel = new Panel;
363 ->Direction(Panel::VERTICAL)
368 .Direction(Panel::HORIZONTAL)
369 ->Padding(glm::vec2(10.0f))
371 ->Background(glm::vec4(0.7f, 0.7f, 0.7f, 1.0f))
376 TimePanel::~TimePanel() {
379 void TimePanel::Draw(graphics::Viewport &viewport) noexcept {
380 time->Text(TimeString(sim.Time()));
382 clock->Text(TimeString(std::fmod(sim.Time(), body->RotationalPeriod())));
384 clock->Text("no reference");
387 const glm::vec2 margin(20.0f);
388 panel.Position(glm::vec2(margin.x, viewport.Height() - margin.y - panel.Size().y));
389 panel.Draw(sim.Assets(), viewport);
393 std::string DecimalString(double n, int p) {
395 s << std::fixed << std::setprecision(p) << n;
399 std::string LengthString(double m) {
401 s << std::fixed << std::setprecision(3);
403 s << (m * 0.001) << "km";
404 } else if (m < 0.1) {
405 s << (m * 1000.0) << "mm";
412 std::string MassString(double kg) {
414 s << std::fixed << std::setprecision(3);
416 s << (kg * 0.001) << "t";
417 } else if (kg < 1.0) {
418 s << (kg * 1000.0) << "g";
419 } else if (kg < 0.001) {
420 s << (kg * 1.0e6) << "mg";
427 std::string NumberString(int n) {
428 return std::to_string(n);
431 std::string PercentageString(double n) {
433 s << std::fixed << std::setprecision(1) << (n * 100.0) << '%';
437 std::string TimeString(double s) {
439 std::stringstream ss;
441 ss << (is / 3600) << "h ";
445 ss << (is / 60) << "m ";
452 std::string VectorString(const glm::dvec3 &v, int p) {
453 std::stringstream ss;
454 ss << std::fixed << std::setprecision(p)
455 << "<" << v.x << ", " << v.y << ", " << v.z << ">";
459 std::string VectorString(const glm::ivec2 &v) {
460 std::stringstream ss;
461 ss << "<" << v.x << ", " << v.y << ">";