diff --git a/doc/en/scripting/ui.md b/doc/en/scripting/ui.md
index c92e79f9d..4b5750286 100644
--- a/doc/en/scripting/ui.md
+++ b/doc/en/scripting/ui.md
@@ -235,17 +235,20 @@ Properties:
Properties:
-| Name | Type | Read | Write | Description |
-|------------|--------|------|-------|---------------------------------------------------------------|
-| value | float | yes | yes | current value |
-| min | float | yes | yes | minimum value |
-| max | float | yes | yes | maximum value |
-| progress | float | yes | no | progress 0..1 |
-| barColor | rgba | yes | yes | color of the filled part |
-| bgColor | rgba | yes | yes | background color (empty part) |
-| textColor | rgba | yes | yes | text color |
-| textFormat | string | yes | yes | text format (sprintf: `%1$` — raw value, `%2$` — percent 0–100) |
-| smooth | bool | yes | yes | smooth value change |
+| Name | Type | Read | Write | Description |
+|--------------|--------|------|-------|---------------------------------------------------------------|
+| value | float | yes | yes | current value |
+| min | float | yes | yes | minimum value |
+| max | float | yes | yes | maximum value |
+| progress | float | yes | no | progress 0..1 |
+| displayValue | float | yes | no | displayed (animated) value |
+| color | rgba | yes | yes | color of the filled part |
+| bgColor | rgba | yes | yes | background color (empty part) |
+| textColor | rgba | yes | yes | text color |
+| text | string | yes | yes | text centered in the bar |
+| smooth | bool | yes | yes | smooth value change |
+| smoothSpeed | number | yes | yes | smooth transition speed in units per second |
+| orientation | string | yes | yes | fill direction: "horizontal" / "vertical" |
## Inventory
diff --git a/doc/en/xml-ui-layouts.md b/doc/en/xml-ui-layouts.md
index e666b6210..89af982dc 100644
--- a/doc/en/xml-ui-layouts.md
+++ b/doc/en/xml-ui-layouts.md
@@ -200,18 +200,13 @@ Non-interactive element for displaying progress. Draws a background and a filled
- `min` - minimal value. Type: number. Default: 0
- `max` - maximal value. Type: number. Default: 100
- `value` - initial value. Type: number. Default: 0
-- `bar-color` - color of the filled part. Type: RGBA color. Default: blue `#3399FFCC`
+- `color` - color of the filled part. Type: RGBA color. Default: blue `#3399FFCC`
- `bg-color` - background color (empty part). Type: RGBA color. Default: semi-transparent black `#00000066`
- `orientation` - fill direction: `horizontal` / `vertical`
-- `supplier` - Lua function - value supplier, called every frame
- `smooth` - smooth value change on updates. Type: boolean. Default: false
-- `text-format` - format of the text centered in the bar (sprintf, two arguments: `%1$` - raw value, `%2$` - percent 0-100)
- ```xml
-
-
-
- ```
+- `smooth-speed` - smooth transition speed in units per second. Type: number. Default: 120
- `text-color` - text color. Type: RGBA color. Default: white `#FFFFFFFF`
+- `font` - font name. Type: string. Default: "normal"
## *bindbox*
diff --git a/doc/ru/scripting/ui.md b/doc/ru/scripting/ui.md
index 7fca96d34..2fa4f14f6 100644
--- a/doc/ru/scripting/ui.md
+++ b/doc/ru/scripting/ui.md
@@ -235,17 +235,20 @@ Canvas.decode(data: Bytearray, format: str) -> Canvas
Свойства:
-| Название | Тип | Чтение | Запись | Описание |
-| ---------- | ------ | ------ | ------ | ---------------------------------------------------------------------- |
-| value | float | да | да | текущее значение |
-| min | float | да | да | минимальное значение |
-| max | float | да | да | максимальное значение |
-| progress | float | да | нет | прогресс 0..1 |
-| barColor | rgba | да | да | цвет заполненной части |
-| bgColor | rgba | да | да | цвет фона (пустой части) |
-| textColor | rgba | да | да | цвет текста |
-| textFormat | string | да | да | формат текста (sprintf: `%1$` — сырое значение, `%2$` — процент 0–100) |
-| smooth | bool | да | да | плавное изменение значения |
+| Название | Тип | Чтение | Запись | Описание |
+|--------------|--------|--------|--------|------------------------------------------------------------------------|
+| value | float | да | да | текущее значение |
+| min | float | да | да | минимальное значение |
+| max | float | да | да | максимальное значение |
+| progress | float | да | нет | прогресс 0..1 |
+| displayValue | float | да | нет | отображаемое (анимированное) значение |
+| color | rgba | да | да | цвет заполненной части |
+| bgColor | rgba | да | да | цвет фона (пустой части) |
+| textColor | rgba | да | да | цвет текста |
+| text | string | да | да | текст по центру бара |
+| smooth | bool | да | да | плавное изменение значения |
+| smoothSpeed | number | да | да | скорость плавного перехода в единицах в секунду |
+| orientation | string | да | да | направление заполнения: "horizontal" / "vertical" |
## Инвентарь (inventory)
diff --git a/doc/ru/xml-ui-layouts.md b/doc/ru/xml-ui-layouts.md
index 06e73a497..79887b676 100644
--- a/doc/ru/xml-ui-layouts.md
+++ b/doc/ru/xml-ui-layouts.md
@@ -201,18 +201,13 @@
- `min` — минимальное значение. Тип: число. По-умолчанию: 0
- `max` — максимальное значение. Тип: число. По-умолчанию: 100
- `value` — начальное значение. Тип: число. По-умолчанию: 0
-- `bar-color` — цвет заполненной части. Тип: RGBA цвет. По-умолчанию: синий `#3399FFCC`
+- `color` — цвет заполненной части. Тип: RGBA цвет. По-умолчанию: синий `#3399FFCC`
- `bg-color` — цвет фона (пустой части). Тип: RGBA цвет. По-умолчанию: чёрный полупрозрачный `#00000066`
- `orientation` — направление заполнения: `horizontal` / `vertical`
-- `supplier` — Lua-функция-поставщик значения, вызывается каждый кадр
- `smooth` — плавное изменение значения при обновлениях. Тип: логический. По-умолчанию: false
-- `text-format` — формат текста по центру бара (sprintf, два аргумента: `%1$` — сырое значение, `%2$` — процент 0–100)
- ```xml
-
-
-
- ```
+- `smooth-speed` — скорость плавного перехода в единицах в секунду. Тип: число. По-умолчанию: 120
- `text-color` — цвет текста. Тип: RGBA цвет. По-умолчанию: белый `#FFFFFFFF`
+- `font` — имя шрифта. Тип: строка. По-умолчанию: "normal"
## Привязка ввода - *bindbox*
diff --git a/res/layouts/pages/bars.xml b/res/layouts/pages/bars.xml
new file mode 100644
index 000000000..435dca1a1
--- /dev/null
+++ b/res/layouts/pages/bars.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layouts/pages/bars.xml.lua b/res/layouts/pages/bars.xml.lua
new file mode 100644
index 000000000..adfa4ffd7
--- /dev/null
+++ b/res/layouts/pages/bars.xml.lua
@@ -0,0 +1,20 @@
+function on_open()
+ document.st_blue.text = "70"
+ document.st_red.text = "35"
+ document.st_green.text = "90"
+ document.bg_none.text = "70"
+ document.bg_white.text = "35"
+ document.bg_blue.text = "90"
+
+ local t = 0.0
+ document.root:setInterval(16, function()
+ t = t + time.delta()
+ local v = (math.sin(t * 2.0) + 1.0) / 2.0 * 100.0
+ document.dyn_off.value = v
+ document.dyn_slow.value = v
+ document.dyn_fast.value = v
+ document.dyn_off.text = string.format("%.0f", v)
+ document.dyn_slow.text = string.format("%.0f", v)
+ document.dyn_fast.text = string.format("%.0f", v)
+ end)
+end
diff --git a/res/layouts/pages/main.xml b/res/layouts/pages/main.xml
index b05ac7158..ef3152439 100644
--- a/res/layouts/pages/main.xml
+++ b/res/layouts/pages/main.xml
@@ -3,5 +3,6 @@
+
diff --git a/src/graphics/ui/elements/ProgressBar.cpp b/src/graphics/ui/elements/ProgressBar.cpp
index 19b8ca735..a1c698863 100644
--- a/src/graphics/ui/elements/ProgressBar.cpp
+++ b/src/graphics/ui/elements/ProgressBar.cpp
@@ -1,15 +1,12 @@
#include "ProgressBar.hpp"
-#include
-#include
#include
+#include
#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(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((displayValue - min) / (max - min)), 0.0f, 1.0f
+ static_cast((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("normal");
+ if (!text.empty()) {
+ auto font = assets.getShared(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(pos.x + (size.x - textWidth) * 0.5f);
int ty = static_cast(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;
}
diff --git a/src/graphics/ui/elements/ProgressBar.hpp b/src/graphics/ui/elements/ProgressBar.hpp
index 46f71385a..aa0b1b7a4 100644
--- a/src/graphics/ui/elements/ProgressBar.hpp
+++ b/src/graphics/ui/elements/ProgressBar.hpp
@@ -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);
};
}
diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp
index 38e90d43a..8c1e7734e 100644
--- a/src/graphics/ui/gui_xml.cpp
+++ b/src/graphics/ui/gui_xml.cpp
@@ -721,34 +721,26 @@ static std::shared_ptr 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(
- reader.getGUI(), minv, maxv, def, thickness
- );
+ auto bar = std::make_shared(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") {
diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp
index 6bbac4f6f..f7fe892ec 100644
--- a/src/logic/scripting/lua/libs/libgui.cpp
+++ b/src/logic/scripting/lua/libs/libgui.cpp
@@ -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(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(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(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(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(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(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(node)) {
return lua::pushwstring(L, box->getText());
+ } else if (auto bar = dynamic_cast(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(node)) {
box->setText(lua::require_wstring(L, idx));
+ } else if (auto bar = dynamic_cast(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(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(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(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(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(node)) {
+ bar->setSmoothSpeed(lua::tonumber(L, idx));
+ }
+}
static void p_set_step(UINode* node, lua::State* L, int idx) {
if (auto bar = dynamic_cast(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},