This commit is contained in:
Ezhulka 2026-08-02 22:13:37 +03:00
parent d74b6ca91c
commit 3d0e31b102
11 changed files with 194 additions and 153 deletions

View file

@ -1,15 +1,12 @@
#include "ProgressBar.hpp"
#include <algorithm>
#include <utility>
#include <cmath>
#include <utility>
#include "graphics/core/Batch2D.hpp"
#include "graphics/core/DrawContext.hpp"
#include "graphics/core/Font.hpp"
#include "assets/Assets.hpp"
#include "maths/voxmaths.hpp"
#include "util/stringutil.hpp"
using namespace gui;
@ -17,22 +14,19 @@ ProgressBar::ProgressBar(
GUI& gui,
double min,
double max,
double value,
int barThickness
double value
) : UINode(gui, glm::vec2(100, 16)),
min(min),
max(max),
value(value),
displayValue(value),
barThickness(barThickness)
displayValue(value)
{
if (barThickness <= 0) barThickness = static_cast<int>(size.y);
setColor(glm::vec4());
setColor(glm::vec4(0.2f, 0.6f, 1.0f, 0.8f));
setInteractive(false);
}
void ProgressBar::act(float delta) {
if (supplier) value = supplier();
UINode::act(delta);
if (smoothTransition) {
double diff = value - displayValue;
if (std::fabs(diff) < 2.0) {
@ -61,12 +55,14 @@ void ProgressBar::draw(const DrawContext& pctx, const Assets& assets) {
float t = 0.0f;
if (max > min) {
t = glm::clamp(
static_cast<float>((displayValue - min) / (max - min)), 0.0f, 1.0f
static_cast<float>((displayValue - min) / (max - min)),
0.0f,
1.0f
);
}
if (t > 0.0f) {
batch->setColor(barColor);
batch->setColor(color);
if (orientation == Orientation::HORIZONTAL) {
batch->rect(pos.x, pos.y, size.x * t, size.y);
} else {
@ -74,27 +70,19 @@ void ProgressBar::draw(const DrawContext& pctx, const Assets& assets) {
}
}
if (textVisible && !textFormat.empty()) {
auto font = assets.get<Font>("normal");
if (!text.empty()) {
auto font = assets.getShared<Font>(fontName);
if (font) {
double pct = (max > min) ? (displayValue - min) / (max - min) * 100.0 : 0.0;
char buf[64];
snprintf(buf, sizeof(buf), textFormat.c_str(), displayValue, pct);
auto wtext = util::str2wstr_utf8(buf);
int textWidth = font->calcWidth(wtext);
int textWidth = font->calcWidth(text);
int lineHeight = font->getLineHeight();
int tx = static_cast<int>(pos.x + (size.x - textWidth) * 0.5f);
int ty = static_cast<int>(pos.y + (size.y - lineHeight) * 0.5f);
batch->setColor(textColor);
font->draw(*batch, wtext, tx, ty, nullptr, 0);
font->draw(*batch, text, tx, ty, nullptr, 0);
}
}
}
void ProgressBar::setSupplier(doublesupplier supplier) {
this->supplier = std::move(supplier);
}
double ProgressBar::getValue() const {
return value;
}
@ -111,8 +99,8 @@ double ProgressBar::getProgress() const {
return (max - min != 0.0) ? (value - min) / (max - min) : 0.0;
}
glm::vec4 ProgressBar::getBarColor() const {
return barColor;
double ProgressBar::getDisplayValue() const {
return displayValue;
}
glm::vec4 ProgressBar::getBgColor() const {
@ -123,14 +111,18 @@ glm::vec4 ProgressBar::getTextColor() const {
return textColor;
}
const std::string& ProgressBar::getTextFormat() const {
return textFormat;
const std::wstring& ProgressBar::getText() const {
return text;
}
bool ProgressBar::isSmooth() const {
return smoothTransition;
}
float ProgressBar::getSmoothSpeed() const {
return smoothSpeed;
}
Orientation ProgressBar::getOrientation() const {
return orientation;
}
@ -147,14 +139,6 @@ void ProgressBar::setMax(double x) {
max = x;
}
void ProgressBar::setBarThickness(int thickness) {
barThickness = thickness;
}
void ProgressBar::setBarColor(glm::vec4 color) {
barColor = color;
}
void ProgressBar::setBgColor(glm::vec4 color) {
bgColor = color;
}
@ -163,15 +147,26 @@ void ProgressBar::setTextColor(glm::vec4 color) {
textColor = color;
}
void ProgressBar::setTextFormat(const std::string& fmt) {
textFormat = fmt;
textVisible = !fmt.empty();
void ProgressBar::setText(std::wstring text) {
this->text = std::move(text);
}
void ProgressBar::setFontName(std::string name) {
fontName = std::move(name);
}
const std::string& ProgressBar::getFontName() const {
return fontName;
}
void ProgressBar::setSmooth(bool flag) {
smoothTransition = flag;
}
void ProgressBar::setSmoothSpeed(float speed) {
smoothSpeed = speed;
}
void ProgressBar::setOrientation(Orientation ori) {
orientation = ori;
}

View file

@ -6,60 +6,51 @@
#include "commons.hpp"
namespace gui {
class ProgressBar : public UINode {
class ProgressBar final : public UINode {
protected:
glm::vec4 barColor {0.2f, 0.6f, 1.0f, 0.8f};
glm::vec4 bgColor {0.0f, 0.0f, 0.0f, 0.4f};
glm::vec4 textColor {1.0f, 1.0f, 1.0f, 1.0f};
doublesupplier supplier = nullptr;
std::wstring text;
double min;
double max;
double value;
double displayValue;
int barThickness;
float smoothSpeed = 120.0f;
float smoothSpeed = 100.0f;
Orientation orientation = Orientation::HORIZONTAL;
bool textVisible = false;
bool smoothTransition = false;
std::string textFormat;
std::string fontName = "normal";
public:
/** min, max, value, displayValue — числовой диапазон и отображаемое значение
* textFormat — формат sprintf. Аргументы:
* %1$ — displayValue (сырое значение в диапазоне min–max)
* %2$ — прогресс в процентах 0..100
* Пример: "%.0f%%" покажет "45%", "%2$.0f%%" покажет "62%" при min=10 max=50
*/
ProgressBar(
GUI& gui,
double min = 0.0,
double max = 100.0,
double value = 0.0,
int barThickness = -1
double value = 0.0
);
virtual void act(float delta) override;
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
void act(float delta) override;
void draw(const DrawContext& pctx, const Assets& assets) override;
virtual void setSupplier(doublesupplier);
virtual double getValue() const;
virtual double getMin() const;
virtual double getMax() const;
virtual double getProgress() const;
virtual glm::vec4 getBarColor() const;
virtual glm::vec4 getBgColor() const;
virtual glm::vec4 getTextColor() const;
virtual Orientation getOrientation() const;
virtual const std::string& getTextFormat() const;
virtual bool isSmooth() const;
double getValue() const;
double getMin() const;
double getMax() const;
double getProgress() const;
double getDisplayValue() const;
glm::vec4 getBgColor() const;
glm::vec4 getTextColor() const;
Orientation getOrientation() const;
const std::wstring& getText() const;
const std::string& getFontName() const;
bool isSmooth() const;
float getSmoothSpeed() const;
virtual void setValue(double);
virtual void setMin(double);
virtual void setMax(double);
virtual void setBarThickness(int);
virtual void setBarColor(glm::vec4);
virtual void setBgColor(glm::vec4);
virtual void setTextColor(glm::vec4);
virtual void setTextFormat(const std::string& fmt);
virtual void setSmooth(bool flag);
virtual void setOrientation(Orientation);
void setValue(double);
void setMin(double);
void setMax(double);
void setBgColor(glm::vec4);
void setTextColor(glm::vec4);
void setText(std::wstring text);
void setFontName(std::string name);
void setSmooth(bool flag);
void setSmoothSpeed(float speed);
void setOrientation(Orientation);
};
}

View file

@ -721,34 +721,26 @@ static std::shared_ptr<UINode> read_progress_bar(
const UiXmlReader& reader,
const xml::xmlelement& element
) {
const auto& env = reader.getEnvironment();
const auto& file = reader.getFilename();
double minv = element.attr("min", "0.0").asFloat();
double maxv = element.attr("max", "100.0").asFloat();
double def = element.attr("value", "0.0").asFloat();
int thickness = element.attr("bar-thickness", "-1").asInt();
auto bar = std::make_shared<ProgressBar>(
reader.getGUI(), minv, maxv, def, thickness
);
auto bar = std::make_shared<ProgressBar>(reader.getGUI(), minv, maxv, def);
read_uinode(reader, element, *bar);
if (element.has("supplier")) {
bar->setSupplier(scripting::create_number_supplier(env, element.attr("supplier").getText(), file));
}
if (element.has("bar-color")) {
bar->setBarColor(element.attr("bar-color").asColor());
if (element.has("font")) {
bar->setFontName(element.attr("font").getText());
}
if (element.has("bg-color")) {
bar->setBgColor(element.attr("bg-color").asColor());
}
if (element.has("text-format")) {
bar->setTextFormat(element.attr("text-format").getText());
}
if (element.has("text-color")) {
bar->setTextColor(element.attr("text-color").asColor());
}
if (element.has("smooth")) {
bar->setSmooth(element.attr("smooth").asBool());
}
if (element.has("smooth-speed")) {
bar->setSmoothSpeed(element.attr("smooth-speed").asFloat());
}
if (element.has("orientation")) {
auto& oname = element.attr("orientation").getText();
if (oname == "vertical") {

View file

@ -279,9 +279,9 @@ static int p_get_progress(UINode* node, lua::State* L) {
return 0;
}
static int p_get_bar_color(UINode* node, lua::State* L) {
static int p_get_display_value(UINode* node, lua::State* L) {
if (auto bar = dynamic_cast<ProgressBar*>(node)) {
return lua::pushcolor(L, bar->getBarColor());
return lua::pushnumber(L, bar->getDisplayValue());
}
return 0;
}
@ -293,16 +293,16 @@ static int p_get_bg_color(UINode* node, lua::State* L) {
return 0;
}
static int p_get_text_format(UINode* node, lua::State* L) {
static int p_is_smooth(UINode* node, lua::State* L) {
if (auto bar = dynamic_cast<ProgressBar*>(node)) {
return lua::pushstring(L, bar->getTextFormat());
return lua::pushboolean(L, bar->isSmooth());
}
return 0;
}
static int p_is_smooth(UINode* node, lua::State* L) {
static int p_get_smooth_speed(UINode* node, lua::State* L) {
if (auto bar = dynamic_cast<ProgressBar*>(node)) {
return lua::pushboolean(L, bar->isSmooth());
return lua::pushnumber(L, bar->getSmoothSpeed());
}
return 0;
}
@ -355,6 +355,27 @@ static int p_get_text_color(UINode* node, lua::State* L) {
return 0;
}
static int p_get_orientation(UINode* node, lua::State* L) {
if (auto bar = dynamic_cast<ProgressBar*>(node)) {
if (bar->getOrientation() == Orientation::VERTICAL) {
return lua::pushstring(L, "vertical");
}
return lua::pushstring(L, "horizontal");
}
return 0;
}
static void p_set_orientation(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<ProgressBar*>(node)) {
std::string_view name = lua::require_string(L, idx);
if (name == "vertical") {
bar->setOrientation(Orientation::VERTICAL);
} else if (name == "horizontal") {
bar->setOrientation(Orientation::HORIZONTAL);
}
}
}
static int p_is_valid(UINode* node, lua::State* L) {
if (auto box = dynamic_cast<TextBox*>(node)) {
return lua::pushboolean(L, box->validate());
@ -390,6 +411,8 @@ static int p_get_text(UINode* node, lua::State* L) {
return lua::pushwstring(L, label->getText());
} else if (auto box = dynamic_cast<TextBox*>(node)) {
return lua::pushwstring(L, box->getText());
} else if (auto bar = dynamic_cast<ProgressBar*>(node)) {
return lua::pushwstring(L, bar->getText());
}
return 0;
}
@ -721,18 +744,19 @@ static int l_gui_getattr(lua::State* L) {
{"fallback", p_get_fallback},
{"value", p_get_value},
{"progress", p_get_progress},
{"displayValue", p_get_display_value},
{"min", p_get_min},
{"max", p_get_max},
{"step", p_get_step},
{"scroll", p_get_scroll},
{"trackWidth", p_get_track_width},
{"trackColor", p_get_track_color},
{"barColor", p_get_bar_color},
{"bgColor", p_get_bg_color},
{"textColor", p_get_text_color},
{"textFormat", p_get_text_format},
{"smooth", p_is_smooth},
{"textColor", p_get_text_color},
{"smoothSpeed", p_get_smooth_speed},
{"orientation", p_get_orientation},
{"checked", p_is_checked},
{"page", p_get_page},
{"back", p_get_back},
@ -807,6 +831,8 @@ static void p_set_text(UINode* node, lua::State* L, int idx) {
button->setText(lua::require_wstring(L, idx));
} else if (auto box = dynamic_cast<TextBox*>(node)) {
box->setText(lua::require_wstring(L, idx));
} else if (auto bar = dynamic_cast<ProgressBar*>(node)) {
bar->setText(lua::require_wstring(L, idx));
}
}
static void p_set_caret(UINode* node, lua::State* L, int idx) {
@ -931,29 +957,22 @@ static void p_set_max(UINode* node, lua::State* L, int idx) {
}
}
static void p_set_bar_color(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<ProgressBar*>(node)) {
bar->setBarColor(lua::tocolor(L, idx));
}
}
static void p_set_bg_color(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<ProgressBar*>(node)) {
bar->setBgColor(lua::tocolor(L, idx));
}
}
static void p_set_text_format(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<ProgressBar*>(node)) {
bar->setTextFormat(lua::require_string(L, idx));
}
}
static void p_set_smooth(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<ProgressBar*>(node)) {
bar->setSmooth(lua::toboolean(L, idx));
}
}
static void p_set_smooth_speed(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<ProgressBar*>(node)) {
bar->setSmoothSpeed(lua::tonumber(L, idx));
}
}
static void p_set_step(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast<TrackBar*>(node)) {
bar->setStep(lua::tonumber(L, idx));
@ -1071,11 +1090,11 @@ static int l_gui_setattr(lua::State* L) {
{"scroll", p_set_scroll},
{"trackWidth", p_set_track_width},
{"trackColor", p_set_track_color},
{"barColor", p_set_bar_color},
{"bgColor", p_set_bg_color},
{"textColor", p_set_text_color},
{"textFormat", p_set_text_format},
{"smooth", p_set_smooth},
{"smoothSpeed", p_set_smooth_speed},
{"orientation", p_set_orientation},
{"checked", p_set_checked},
{"page", p_set_page},
{"inventory", p_set_inventory},