This commit is contained in:
@clasher113 2024-03-23 18:10:15 +02:00
parent cc367ee206
commit f0153eb51e
7 changed files with 76 additions and 67 deletions

View File

@ -112,7 +112,7 @@
## Подбираемый предмет - `picking-item` ## Подбираемый предмет - `picking-item`
Предмет, который будет выбран при при нажатии средней кнопкой мыши на блок. Предмет, который будет выбран при нажатии средней кнопкой мыши на блок.
Пример: блок `door:door_open` скрыт (hidden) поэтому указывается `picking-item: "door:door.item"` Пример: блок `door:door_open` скрыт (hidden) поэтому указывается `picking-item: "door:door.item"`

View File

@ -5,8 +5,12 @@ Ok=Гаразд
Cancel=Скасувати Cancel=Скасувати
Back=Назад Back=Назад
Continue=Продовжити Continue=Продовжити
Add=Додати
Converting world...=Виконується конвертація світу...
error.pack-not-found=Не вдалося знайти пакет error.pack-not-found=Не вдалося знайти пакет
error.dependency-not-found=Використовувана залежність не знайдена
pack.remove-confirm=Видалити назавжди весь контент, що постачається паком, зі світу?
# Меню # Меню
menu.New World=Новий Світ menu.New World=Новий Світ
@ -18,14 +22,16 @@ menu.Controls=Керування
menu.Back to Main Menu=Повернутися до Меню menu.Back to Main Menu=Повернутися до Меню
menu.Settings=Налаштування menu.Settings=Налаштування
menu.Content=Контент menu.Content=Контент
menu.Audio=Звук
world.Seed=Зерно world.Seed=Зерно
world.Name=Назва world.Name=Назва
menu.Create World=Створити Світ menu.Create World=Створити Світ
world.World generator=Генератор світу world.World generator=Генератор світу
world.generators.default=Звичайні world.generators.default=Звичайний
world.generators.flat=Плоскі world.generators.flat=Плоский
world.convert-request=Є зміни в індексах! Конвертувати світ? world.convert-request=Є зміни в індексах! Конвертувати світ?
world.delete-confirm=Видалити світ назавжди?
# Налаштування # Налаштування
settings.Load Distance=Дистанція Завантаження settings.Load Distance=Дистанція Завантаження
@ -33,6 +39,12 @@ settings.Load Speed=Швидкість Завантаження
settings.Fog Curve=Крива Туману settings.Fog Curve=Крива Туману
settings.Backlight=Підсвічування settings.Backlight=Підсвічування
settings.V-Sync=Вертикальна Синхронізація settings.V-Sync=Вертикальна Синхронізація
settings.Camera Shaking=Коливання Камери
settings.Master Volume=Загальна Гучність
settings.Regular Sounds=Звичайні Звуки
settings.UI Sounds=Звуки Інтерфейсу
settings.Ambient=Середовище
settings.Music=Музика
settings.FOV=Поле зору settings.FOV=Поле зору
settings.Mouse Sensitivity=Чутливість Миші settings.Mouse Sensitivity=Чутливість Миші

View File

@ -104,8 +104,7 @@ std::shared_ptr<UINode> create_debug_panel(
glm::vec3 position = player->hitbox->position; glm::vec3 position = player->hitbox->position;
position[ax] = std::stoi(text); position[ax] = std::stoi(text);
player->teleport(position); player->teleport(position);
} catch (std::invalid_argument& _){ } catch (std::exception& _){
} catch (std::out_of_range & _) {
} }
}); });
box->setOnEditStart([=](){ box->setOnEditStart([=](){

View File

@ -90,7 +90,10 @@ void Container::draw(const GfxContext* pctx, Assets* assets) {
GfxContext ctx = pctx->sub(); GfxContext ctx = pctx->sub();
ctx.setScissors(glm::vec4(pos.x, pos.y, size.x, size.y)); ctx.setScissors(glm::vec4(pos.x, pos.y, size.x, size.y));
for (auto node : nodes) { for (auto node : nodes) {
if (node->isVisible()) glm::vec2 nodePos = node->calcPos();
glm::vec2 nodeSize = node->getSize();
if (node->isVisible() && (nodePos.y + nodeSize.y > pos.y && nodePos.y < pos.y + size.y &&
nodePos.x + nodeSize.x > pos.x && nodePos.x < pos.x + size.x))
node->draw(pctx, assets); node->draw(pctx, assets);
} }
} }
@ -121,11 +124,7 @@ void Container::add(std::shared_ptr<UINode> node, glm::vec2 pos) {
void Container::remove(std::shared_ptr<UINode> selected) { void Container::remove(std::shared_ptr<UINode> selected) {
selected->setParent(nullptr); selected->setParent(nullptr);
nodes.erase(std::remove_if(nodes.begin(), nodes.end(), nodes.erase(std::remove(nodes.begin(), nodes.end(), selected), nodes.end());
[selected](const std::shared_ptr<UINode> node) {
return node == selected;
}
), nodes.end());
refresh(); refresh();
} }
@ -143,6 +142,7 @@ void Container::setSize(glm::vec2 size) {
for (auto& node : nodes) { for (auto& node : nodes) {
node->reposition(); node->reposition();
} }
scrolled(0);
} }
void Container::refresh() { void Container::refresh() {

View File

@ -60,6 +60,14 @@ void Label::setVerticalAlign(Align align) {
this->valign = align; this->valign = align;
} }
void gui::Label::setTextOffset(glm::vec2 offset) {
textOffset = offset;
}
glm::vec2 gui::Label::getTextOffset() const {
return textOffset;
}
Align Label::getVerticalAlign() const { Align Label::getVerticalAlign() const {
return valign; return valign;
} }
@ -72,10 +80,6 @@ void Label::setLineInterval(float interval) {
lineInterval = interval; lineInterval = interval;
} }
int Label::getTextYOffset() const {
return textYOffset;
}
size_t Label::getTextLineOffset(uint line) const { size_t Label::getTextLineOffset(uint line) const {
size_t offset = 0; size_t offset = 0;
size_t linesCount = 0; size_t linesCount = 0;
@ -91,14 +95,14 @@ size_t Label::getTextLineOffset(uint line) const {
} }
int Label::getLineYOffset(uint line) const { int Label::getLineYOffset(uint line) const {
return line * totalLineHeight + textYOffset; return line * totalLineHeight + textOffset.y;
} }
uint Label::getLineByYOffset(int offset) const { uint Label::getLineByYOffset(int offset) const {
if (offset < textYOffset) { if (offset < textOffset.y) {
return 0; return 0;
} }
return (offset - textYOffset) / totalLineHeight; return (offset - textOffset.y) / totalLineHeight;
} }
uint Label::getLineByTextIndex(size_t index) const { uint Label::getLineByTextIndex(size_t index) const {
@ -139,7 +143,7 @@ void Label::draw(const GfxContext* pctx, Assets* assets) {
(lines == 1 ? lineHeight : lineHeight*lineInterval)*lines + font->getYOffset() (lines == 1 ? lineHeight : lineHeight*lineInterval)*lines + font->getYOffset()
); );
glm::vec2 pos = calcPos(); glm::vec2 pos = calcPos() + textOffset;
switch (align) { switch (align) {
case Align::left: case Align::left:
break; break;
@ -160,7 +164,7 @@ void Label::draw(const GfxContext* pctx, Assets* assets) {
pos.y += size.y-newsize.y; pos.y += size.y-newsize.y;
break; break;
} }
textYOffset = pos.y-calcPos().y;
totalLineHeight = lineHeight * lineInterval; totalLineHeight = lineHeight * lineInterval;
if (multiline) { if (multiline) {
@ -367,7 +371,7 @@ TextBox::TextBox(std::wstring placeholder, glm::vec4 padding)
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y)); label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
add(label); add(label);
setHoverColor(glm::vec4(0.05f, 0.1f, 0.2f, 0.75f)); setHoverColor(glm::vec4(0.05f, 0.1f, 0.2f, 0.75f));
scrollable = false;
textInitX = label->getPos().x; textInitX = label->getPos().x;
} }
@ -388,6 +392,7 @@ void TextBox::draw(const GfxContext* pctx, Assets* assets) {
const int lineHeight = font->getLineHeight() * label->getLineInterval(); const int lineHeight = font->getLineHeight() * label->getLineInterval();
glm::vec2 lcoord = label->calcPos(); glm::vec2 lcoord = label->calcPos();
lcoord.y -= 2; lcoord.y -= 2;
lcoord.x += label->getTextOffset().x;
auto batch = pctx->getBatch2D(); auto batch = pctx->getBatch2D();
batch->texture(nullptr); batch->texture(nullptr);
if (editable && int((Window::time() - caretLastMove) * 2) % 2 == 0) { if (editable && int((Window::time() - caretLastMove) * 2) % 2 == 0) {
@ -411,9 +416,12 @@ void TextBox::draw(const GfxContext* pctx, Assets* assets) {
if (startLine == endLine) { if (startLine == endLine) {
batch->rect(lcoord.x + start, lcoord.y+startY, end-start, lineHeight); batch->rect(lcoord.x + start, lcoord.y+startY, end-start, lineHeight);
} else { } else {
batch->rect(lcoord.x + start, lcoord.y+endY, label->getSize().x-start-padding.z-padding.x-2, lineHeight); int width = font->calcWidth(input.substr(selectionStart, label->getTextLineOffset(startLine + 1) - selectionStart-1));
batch->rect(lcoord.x + start, lcoord.y+endY, width, lineHeight);
for (uint i = startLine+1; i < endLine; i++) { for (uint i = startLine+1; i < endLine; i++) {
batch->rect(lcoord.x, lcoord.y+label->getLineYOffset(i), label->getSize().x-padding.z-padding.x-2, lineHeight); width = font->calcWidth(input.substr(label->getTextLineOffset(i), label->getTextLineOffset(i+1) - label->getTextLineOffset(i)-1));
batch->rect(lcoord.x, lcoord.y+label->getLineYOffset(i), width, lineHeight);
} }
batch->rect(lcoord.x, lcoord.y+label->getLineYOffset(endLine), end, lineHeight); batch->rect(lcoord.x, lcoord.y+label->getLineYOffset(endLine), end, lineHeight);
} }
@ -443,7 +451,7 @@ void TextBox::drawBackground(const GfxContext* pctx, Assets* assets) {
batch->rect(pos.x, pos.y, size.x, size.y); batch->rect(pos.x, pos.y, size.x, size.y);
if (!isFocused() && supplier) { if (!isFocused() && supplier) {
input = supplier(); setText(supplier());
} }
if (isFocused() && multiline) { if (isFocused() && multiline) {
@ -459,14 +467,6 @@ void TextBox::drawBackground(const GfxContext* pctx, Assets* assets) {
label->setColor(glm::vec4(input.empty() ? 0.5f : 1.0f)); label->setColor(glm::vec4(input.empty() ? 0.5f : 1.0f));
label->setText(getText()); label->setText(getText());
if (multiline && font) {
setScrollable(true);
uint height = label->getLinesNumber() * font->getLineHeight() * label->getLineInterval();
label->setSize(glm::vec2(label->getSize().x, height));
actualLength = height;
} else {
setScrollable(false);
}
} }
/// @brief Insert text at the caret. Also selected text will be erased /// @brief Insert text at the caret. Also selected text will be erased
@ -500,6 +500,7 @@ void TextBox::erase(size_t start, size_t length) {
auto left = input.substr(0, start); auto left = input.substr(0, start);
auto right = input.substr(end); auto right = input.substr(end);
input = left + right; input = left + right;
validate();
} }
/// @brief Remove all selected text and reset selection /// @brief Remove all selected text and reset selection
@ -537,13 +538,6 @@ size_t TextBox::getSelectionLength() const {
return selectionEnd - selectionStart; return selectionEnd - selectionStart;
} }
/// @brief Set scroll offset
/// @param x scroll offset
void TextBox::setTextOffset(uint x) {
label->setPos(glm::vec2(textInitX - int(x), label->getPos().y));
textOffset = x;
}
void TextBox::typed(unsigned int codepoint) { void TextBox::typed(unsigned int codepoint) {
paste(std::wstring({(wchar_t)codepoint})); paste(std::wstring({(wchar_t)codepoint}));
} }
@ -566,7 +560,7 @@ bool TextBox::isValid() const {
} }
void TextBox::setMultiline(bool multiline) { void TextBox::setMultiline(bool multiline) {
this->multiline = multiline; this->multiline = scrollable = multiline;
label->setMultiline(multiline); label->setMultiline(multiline);
label->setVerticalAlign(multiline ? Align::top : Align::center); label->setVerticalAlign(multiline ? Align::top : Align::center);
} }
@ -596,11 +590,6 @@ void TextBox::onFocus(GUI* gui) {
} }
} }
void TextBox::refresh() {
Panel::refresh();
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
}
/// @brief Clamp index to range [0, input.length()] /// @brief Clamp index to range [0, input.length()]
/// @param index non-normalized index /// @param index non-normalized index
/// @return normalized index /// @return normalized index
@ -616,6 +605,7 @@ int TextBox::calcIndexAt(int x, int y) const {
if (font == nullptr) if (font == nullptr)
return 0; return 0;
glm::vec2 lcoord = label->calcPos(); glm::vec2 lcoord = label->calcPos();
lcoord.x += label->getTextOffset().x;
uint line = label->getLineByYOffset(y-lcoord.y); uint line = label->getLineByYOffset(y-lcoord.y);
line = std::min(line, label->getLinesNumber()-1); line = std::min(line, label->getLinesNumber()-1);
size_t lineLength = getLineLength(line); size_t lineLength = getLineLength(line);
@ -640,6 +630,14 @@ void TextBox::mouseMove(GUI*, int x, int y) {
resetMaxLocalCaret(); resetMaxLocalCaret();
} }
void gui::TextBox::scrolled(int value) {
if (!scrollable || font == nullptr) return;
float lineHeight = font->getLineHeight() * label->getLineInterval();
glm::vec2 offset = label->getTextOffset();
offset.y = std::clamp(offset.y + value * lineHeight, -std::max(lineHeight * label->getLinesNumber() - label->getSize().y, 0.f), 0.f);
label->setTextOffset(offset);
}
void TextBox::resetMaxLocalCaret() { void TextBox::resetMaxLocalCaret() {
maxLocalCaret = caret - label->getTextLineOffset(label->getLineByTextIndex(caret)); maxLocalCaret = caret - label->getTextLineOffset(label->getLineByTextIndex(caret));
} }
@ -655,12 +653,10 @@ void TextBox::performEditingKeyboardEvents(keycode key) {
} }
input = input.substr(0, caret-1) + input.substr(caret); input = input.substr(0, caret-1) + input.substr(caret);
setCaret(caret-1); setCaret(caret-1);
validate();
} }
} else if (key == keycode::DELETE) { } else if (key == keycode::DELETE) {
if (!eraseSelected() && caret < input.length()) { if (!eraseSelected() && caret < input.length()) {
input = input.substr(0, caret) + input.substr(caret + 1); input = input.substr(0, caret) + input.substr(caret + 1);
validate();
} }
} else if (key == keycode::ENTER) { } else if (key == keycode::ENTER) {
if (multiline) { if (multiline) {
@ -860,20 +856,22 @@ void TextBox::setCaret(uint position) {
int width = label->getSize().x; int width = label->getSize().x;
uint line = label->getLineByTextIndex(caret); uint line = label->getLineByTextIndex(caret);
int offset = label->getLineYOffset(line) + contentOffset().y; int offset = label->getLineYOffset(line);
uint lineHeight = font->getLineHeight()*label->getLineInterval(); uint lineHeight = font->getLineHeight()*label->getLineInterval();
scrollStep = lineHeight; glm::vec2 textOffset = label->getTextOffset();
if (offset < 0) {
scrolled(1); if (offset >= label->getSize().y) {
} else if (offset >= getSize().y) { label->setTextOffset(glm::vec2(textOffset.x, std::min(0.f, textOffset.y - lineHeight)));
scrolled(-1); } else if (offset < 0) {
label->setTextOffset(glm::vec2(textOffset.x, std::min(0.f, textOffset.y + lineHeight)));
} }
textOffset = label->getTextOffset();
uint lcaret = caret - label->getTextLineOffset(line); uint lcaret = caret - label->getTextLineOffset(line);
int realoffset = font->calcWidth(input, lcaret)-int(textOffset)+2; int realoffset = font->calcWidth(input, lcaret)+textOffset.x+2;
if (realoffset-width > 0) { if (realoffset > width) {
setTextOffset(textOffset + realoffset-width); label->setTextOffset(glm::vec2(textOffset.x - (realoffset - width), textOffset.y));
} else if (realoffset < 0) { } else if (realoffset < 0) {
setTextOffset(std::max(textOffset + realoffset, 0U)); label->setTextOffset(glm::vec2(textOffset.x - realoffset, textOffset.y));
} }
} }

View File

@ -32,9 +32,9 @@ namespace gui {
// runtime values // runtime values
/// @brief Text Y offset relative to label position /// @brief Text offset relative to label position
/// (last calculated alignment) /// (last calculated alignment)
int textYOffset = 0; glm::vec2 textOffset{ 0.f, 0.f };
/// @brief Text line height multiplied by line interval /// @brief Text line height multiplied by line interval
int totalLineHeight = 1; int totalLineHeight = 1;
@ -60,9 +60,11 @@ namespace gui {
/// @brief Set line height multiplier used for multiline labels /// @brief Set line height multiplier used for multiline labels
virtual void setLineInterval(float interval); virtual void setLineInterval(float interval);
/// @brief Get Y position of the text relative to label position virtual void setTextOffset(glm::vec2 offset);
/// @return Y offset
virtual int getTextYOffset() const; /// @brief Get position of the text relative to label position
/// @return offset
virtual glm::vec2 getTextOffset() const;
/// @brief Get Y position of the line relative to label position /// @brief Get Y position of the line relative to label position
/// @param line target line index /// @param line target line index
@ -164,7 +166,6 @@ namespace gui {
uint caret = 0; uint caret = 0;
/// @brief actual local (line) position of the caret on vertical move /// @brief actual local (line) position of the caret on vertical move
uint maxLocalCaret = 0; uint maxLocalCaret = 0;
uint textOffset = 0;
int textInitX; int textInitX;
/// @brief last time of the caret was moved (used for blink animation) /// @brief last time of the caret was moved (used for blink animation)
double caretLastMove = 0.0; double caretLastMove = 0.0;
@ -181,7 +182,6 @@ namespace gui {
int calcIndexAt(int x, int y) const; int calcIndexAt(int x, int y) const;
void paste(const std::wstring& text); void paste(const std::wstring& text);
void setTextOffset(uint x);
void erase(size_t start, size_t length); void erase(size_t start, size_t length);
bool eraseSelected(); bool eraseSelected();
void resetSelection(); void resetSelection();
@ -273,9 +273,9 @@ namespace gui {
virtual void setOnEditStart(runnable oneditstart); virtual void setOnEditStart(runnable oneditstart);
virtual void onFocus(GUI*) override; virtual void onFocus(GUI*) override;
virtual void refresh() override;
virtual void click(GUI*, int, int) override; virtual void click(GUI*, int, int) override;
virtual void mouseMove(GUI*, int x, int y) override; virtual void mouseMove(GUI*, int x, int y) override;
virtual void scrolled(int value) override;
virtual bool isFocuskeeper() const override {return true;} virtual bool isFocuskeeper() const override {return true;}
virtual void draw(const GfxContext* pctx, Assets* assets) override; virtual void draw(const GfxContext* pctx, Assets* assets) override;
virtual void drawBackground(const GfxContext* pctx, Assets* assets) override; virtual void drawBackground(const GfxContext* pctx, Assets* assets) override;

View File

@ -7,7 +7,7 @@
#include "../typedefs.h" #include "../typedefs.h"
#ifdef WIN32 #ifdef _WIN32
#include <Windows.h> #include <Windows.h>
#include "./stringutil.h" #include "./stringutil.h"