From: Daniel Karbach Date: Mon, 20 Nov 2017 21:19:25 +0000 (+0100) Subject: shoddy meters X-Git-Url: http://git.localhorst.tv/?p=blobs.git;a=commitdiff_plain;h=4ec93ba5186dca958be6e2a4dc2aaf3572a524cb shoddy meters --- diff --git a/src/creature/Creature.hpp b/src/creature/Creature.hpp index e912553..135cf9e 100644 --- a/src/creature/Creature.hpp +++ b/src/creature/Creature.hpp @@ -49,6 +49,7 @@ public: double Health() const noexcept { return health; } void AddNeed(const Need &n) { needs.push_back(n); } + const std::vector &Needs() const noexcept { return needs; } void Tick(double dt); diff --git a/src/ui/CreaturePanel.hpp b/src/ui/CreaturePanel.hpp index a487b1a..76455d9 100644 --- a/src/ui/CreaturePanel.hpp +++ b/src/ui/CreaturePanel.hpp @@ -1,7 +1,6 @@ #ifndef BLOBS_UI_CREATUREPANEL_HPP_ #define BLOBS_UI_CREATUREPANEL_HPP_ -#include "Label.hpp" #include "Panel.hpp" @@ -17,6 +16,9 @@ namespace graphics { } namespace ui { +class Label; +class Meter; + class CreaturePanel { public: @@ -36,11 +38,18 @@ public: void Draw(app::Assets &, graphics::Viewport &) noexcept; private: + void CreateNeeds(); + +private: + const app::Assets &assets; creature::Creature *c; Label *name; + Panel *needs; Panel panel; + std::vector meters; + }; } diff --git a/src/ui/Label.hpp b/src/ui/Label.hpp index 90ed738..1bc7e86 100644 --- a/src/ui/Label.hpp +++ b/src/ui/Label.hpp @@ -21,10 +21,10 @@ public: ~Label() override; public: - Label &Text(const std::string &); - Label &Font(const graphics::Font &); - Label &Foreground(const glm::vec4 &); - Label &Background(const glm::vec4 &); + Label *Text(const std::string &); + Label *Font(const graphics::Font &); + Label *Foreground(const glm::vec4 &); + Label *Background(const glm::vec4 &); glm::vec2 Size() override; void Draw(app::Assets &, graphics::Viewport &) noexcept override; diff --git a/src/ui/Meter.hpp b/src/ui/Meter.hpp new file mode 100644 index 0000000..12885e4 --- /dev/null +++ b/src/ui/Meter.hpp @@ -0,0 +1,46 @@ +#ifndef BLOBS_UI_METER_HPP_ +#define BLOBS_UI_METER_HPP_ + +#include "Widget.hpp" + + +namespace blobs { +namespace ui { + +class Meter +: public Widget { + +public: + Meter(); + ~Meter() override; + +public: + Meter *Size(const glm::vec2 &s) noexcept { size = s; return this; } + Meter *Padding(const glm::vec2 &p) noexcept { padding = p; return this; } + // TODO: gl line width is deprecated, use polys instead + Meter *Border(float b) noexcept { border = b; return this; } + + Meter *FillColor(const glm::vec4 &c) noexcept { fill_color = c; return this; } + Meter *BorderColor(const glm::vec4 &c) noexcept { border_color = c; return this; } + + Meter *Value(float v) noexcept { value = v; return this; } + + glm::vec2 Size() override; + void Draw(app::Assets &, graphics::Viewport &) noexcept override; + +private: + glm::vec4 fill_color; + glm::vec4 border_color; + + glm::vec2 size; + glm::vec2 padding; + float border; + + float value; + +}; + +} +} + +#endif diff --git a/src/ui/Panel.hpp b/src/ui/Panel.hpp index d62073b..9267661 100644 --- a/src/ui/Panel.hpp +++ b/src/ui/Panel.hpp @@ -18,6 +18,7 @@ public: HORIZONTAL, VERTICAL, }; + using Children_t = std::vector>; public: Panel(); @@ -25,19 +26,22 @@ public: public: // panel takes ownership - Panel &Add(Widget *); + Panel *Add(Widget *); + Panel *Clear(); + Panel *Reserve(int n) { widgets.reserve(n); return this; } + const Children_t &Children() const noexcept { return widgets; } - Panel &Background(const glm::vec4 &); - Panel &Padding(const glm::vec2 &); - Panel &Spacing(float); - Panel &Direction(Dir); + Panel *Background(const glm::vec4 &); + Panel *Padding(const glm::vec2 &); + Panel *Spacing(float); + Panel *Direction(Dir); glm::vec2 Size() override; void Relayout(); void Draw(app::Assets &, graphics::Viewport &) noexcept override; private: - std::vector> widgets; + Children_t widgets; glm::vec4 bg_color; glm::vec2 padding; float spacing; diff --git a/src/ui/Widget.hpp b/src/ui/Widget.hpp index cb83da2..ed7c848 100644 --- a/src/ui/Widget.hpp +++ b/src/ui/Widget.hpp @@ -27,12 +27,12 @@ public: Widget &operator =(Widget &&) = delete; public: - Widget &Position(const glm::vec3 &p) noexcept { pos = p; return *this; } + Widget *Position(const glm::vec3 &p) noexcept { pos = p; return this; } const glm::vec3 &Position() const noexcept { return pos; } glm::vec3 AlignedPosition() noexcept; glm::vec3 TopLeft() noexcept; - Widget &Origin(Gravity o) noexcept { origin = o; return *this; } + Widget *Origin(Gravity o) noexcept { origin = o; return this; } Gravity Origin() const noexcept { return origin; } virtual glm::vec2 Size() = 0; diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 31f0396..a1b2f9a 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -1,5 +1,7 @@ #include "CreaturePanel.hpp" +#include "Label.hpp" +#include "Meter.hpp" #include "../app/Assets.hpp" #include "../creature/Creature.hpp" #include "../graphics/Viewport.hpp" @@ -11,16 +13,19 @@ namespace blobs { namespace ui { CreaturePanel::CreaturePanel(const app::Assets &assets) -: c(nullptr) +: assets(assets) +, c(nullptr) , name(new Label(assets.fonts.large)) +, needs(new Panel) , panel() { panel .Add(name) - .Padding(glm::vec2(10.0f)) - .Spacing(10.0f) - .Direction(Panel::VERTICAL) - .Background(glm::vec4(0.7f, 0.7f, 0.7f, 1.0f)) - .Origin(Gravity::NORTH_EAST); + ->Add(needs) + ->Padding(glm::vec2(10.0f)) + ->Spacing(10.0f) + ->Direction(Panel::VERTICAL) + ->Background(glm::vec4(0.7f, 0.7f, 0.7f, 1.0f)) + ->Origin(Gravity::NORTH_EAST); } CreaturePanel::~CreaturePanel() { @@ -30,6 +35,34 @@ CreaturePanel::~CreaturePanel() { void CreaturePanel::Show(creature::Creature &cr) { c = &cr; name->Text(c->Name()); + CreateNeeds(); +} + +void CreaturePanel::CreateNeeds() { + needs->Clear()->Reserve(c->Needs().size()); + meters.clear(); + meters.reserve(c->Needs().size()); + for (auto &need : c->Needs()) { + Label *label = new Label(assets.fonts.medium); + label + ->Text(assets.data.resources[need.resource].label); + Meter *meter = new Meter; + meter + ->Value(1.0f - need.value) + ->Size(glm::vec2(100.0f, assets.fonts.medium.Height())) + ->Padding(glm::vec2(1.0f)) + ->Border(1.0f) + ->FillColor(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)) + ->BorderColor(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); + Panel *need_panel = new Panel; + need_panel + ->Direction(Panel::HORIZONTAL) + ->Spacing(10.0f) + ->Add(label) + ->Add(meter); + needs->Add(need_panel); + meters.push_back(meter); + } panel.Relayout(); } @@ -40,6 +73,19 @@ void CreaturePanel::Hide() noexcept { void CreaturePanel::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept { if (!c) return; + if (meters.size() != c->Needs().size()) { + CreateNeeds(); + } else { + auto need = c->Needs().begin(); + auto need_end = c->Needs().end(); + auto meter = meters.begin(); + for (; need != need_end; ++need, ++meter) { + (*meter)->Value(1.0f - need->value)->FillColor(need->IsSatisfied() + ? glm::vec4(0.0f, 0.0f, 0.0f, 1.0f) + : glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); + } + } + const glm::vec2 margin(20.0f); panel.Position(glm::vec3(viewport.Width() - margin.x, margin.y, 0.0f)); diff --git a/src/ui/widgets.cpp b/src/ui/widgets.cpp index 94c4182..ffaeab8 100644 --- a/src/ui/widgets.cpp +++ b/src/ui/widgets.cpp @@ -1,4 +1,5 @@ #include "Label.hpp" +#include "Meter.hpp" #include "Panel.hpp" #include "Widget.hpp" @@ -24,30 +25,30 @@ Label::Label(const graphics::Font &f) Label::~Label() { } -Label &Label::Text(const std::string &t) { +Label *Label::Text(const std::string &t) { if (text != t) { dirty = true; } text = t; - return *this; + return this; } -Label &Label::Font(const graphics::Font &f) { +Label *Label::Font(const graphics::Font &f) { if (font != &f) { dirty = true; } font = &f; - return *this; + return this; } -Label &Label::Foreground(const glm::vec4 &c) { +Label *Label::Foreground(const glm::vec4 &c) { fg_color = c; - return *this; + return this; } -Label &Label::Background(const glm::vec4 &c) { +Label *Label::Background(const glm::vec4 &c) { bg_color = c; - return *this; + return this; } glm::vec2 Label::Size() { @@ -78,6 +79,45 @@ void Label::Update() { } +Meter::Meter() +: fill_color(1.0f) +, border_color(1.0f) +, size(3.0f) +, padding(1.0f) +, border(1.0f) +, value(0.0f) { +} + +Meter::~Meter() { +} + +glm::vec2 Meter::Size() { + return size + (2.0f * padding) + (2.0f * border); +} + +void Meter::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept { + glm::vec2 fullsize = Size(); + assets.shaders.plain_color.Activate(); + + if (border > 0.0f) { + assets.shaders.plain_color.SetM(glm::translate(AlignedPosition()) + * glm::scale(glm::vec3(fullsize.x, fullsize.y, 1.0f))); + assets.shaders.plain_color.SetColor(border_color); + assets.shaders.plain_color.OutlineRect(); + } + + if (value > 0.0f) { + glm::vec3 top_left(glm::vec2(TopLeft()) + padding + glm::vec2(border), Position().z); + glm::vec3 actual_size(size.x * value, size.y, 1.0f); + + assets.shaders.plain_color.SetM(glm::translate(align(Gravity::NORTH_WEST, actual_size, top_left)) + * glm::scale(actual_size)); + assets.shaders.plain_color.SetColor(fill_color); + assets.shaders.plain_color.DrawRect(); + } +} + + Panel::Panel() : widgets() , bg_color(0.0f, 0.0f, 0.0f, 0.0f) @@ -90,7 +130,7 @@ Panel::Panel() Panel::~Panel() { } -Panel &Panel::Add(Widget *w) { +Panel *Panel::Add(Widget *w) { std::unique_ptr widget(w); glm::vec2 wsize = widget->Size(); if (dir == HORIZONTAL) { @@ -101,32 +141,38 @@ Panel &Panel::Add(Widget *w) { size.y += wsize.y; } widgets.emplace_back(std::move(widget)); - return *this; + return this; +} + +Panel *Panel::Clear() { + widgets.clear(); + size = glm::vec2(0.0f); + return this; } -Panel &Panel::Background(const glm::vec4 &c) { +Panel *Panel::Background(const glm::vec4 &c) { bg_color = c; - return *this; + return this; } -Panel &Panel::Padding(const glm::vec2 &p) { +Panel *Panel::Padding(const glm::vec2 &p) { padding = p; - return *this; + return this; } -Panel &Panel::Spacing(float s) { +Panel *Panel::Spacing(float s) { spacing = s; - return *this; + return this; } -Panel &Panel::Direction(Dir d) { +Panel *Panel::Direction(Dir d) { dir = d; Relayout(); - return *this; + return this; } glm::vec2 Panel::Size() { - return 2.0f * padding + glm::vec2(0.0f, (widgets.size() - 1) * spacing) + size; + return (2.0f * padding) + glm::vec2(0.0f, (widgets.size() - 1) * spacing) + size; } void Panel::Relayout() { @@ -161,7 +207,7 @@ void Panel::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept { cursor.y += padding.y; cursor.z -= 1.0f; for (auto &w : widgets) { - w->Position(cursor).Origin(Gravity::NORTH_WEST); + w->Position(cursor)->Origin(Gravity::NORTH_WEST); w->Draw(assets, viewport); cursor[dir] += w->Size()[dir] + spacing; }