Merge branch 'main' into text3d
This commit is contained in:
@@ -74,6 +74,7 @@ Properties:
|
|||||||
| ----------- | ------ | ---- | ----- | ------------------------------------------------------------------------------------ |
|
| ----------- | ------ | ---- | ----- | ------------------------------------------------------------------------------------ |
|
||||||
| text | string | yes | yes | entered text or placeholder |
|
| text | string | yes | yes | entered text or placeholder |
|
||||||
| placeholder | string | yes | yes | placeholder (used if nothing has been entered) |
|
| placeholder | string | yes | yes | placeholder (used if nothing has been entered) |
|
||||||
|
| hint | string | yes | yes | text to display when nothing is entered |
|
||||||
| caret | int | yes | yes | carriage position. `textbox.caret = -1` will set the position to the end of the text |
|
| caret | int | yes | yes | carriage position. `textbox.caret = -1` will set the position to the end of the text |
|
||||||
| editable | bool | yes | yes | text mutability |
|
| editable | bool | yes | yes | text mutability |
|
||||||
| multiline | bool | yes | yes | multiline support |
|
| multiline | bool | yes | yes | multiline support |
|
||||||
|
|||||||
@@ -72,17 +72,20 @@ Fragments used by the generator must present in the directory:
|
|||||||
|
|
||||||
## Structures
|
## Structures
|
||||||
|
|
||||||
A structure is a set of rules for inserting a fragment into the world by the generator. It currently has no properties, being created as empty objects in the `generators/generator_name.files/structures.toml` file. Example:
|
A structure is a set of rules for inserting a fragment into the world by the generator. Structures are declared as objects in the file `generators/generator_name.files/structures.toml`. Example:
|
||||||
```toml
|
```toml
|
||||||
tree0 = {}
|
tree0 = {}
|
||||||
tree1 = {}
|
tree1 = {}
|
||||||
tree2 = {}
|
tree2 = {}
|
||||||
tower = {}
|
tower = {lowering=2}
|
||||||
coal_ore0 = {}
|
coal_ore0 = {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Currently, the name of the structure must match the name of the fragment used.
|
Currently, the name of the structure must match the name of the fragment used.
|
||||||
|
|
||||||
|
Available properties:
|
||||||
|
- lowering - depth of structure lowering.
|
||||||
|
|
||||||
## Biomes
|
## Biomes
|
||||||
|
|
||||||
A biome defines what blocks and layers the terrain is generated from, as well as a set of plants and structures.
|
A biome defines what blocks and layers the terrain is generated from, as well as a set of plants and structures.
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ document["worlds-panel"]:clear()
|
|||||||
| ----------- | ------ | ------ | ------ | ---------------------------------------------------------------------- |
|
| ----------- | ------ | ------ | ------ | ---------------------------------------------------------------------- |
|
||||||
| text | string | да | да | введенный текст или заполнитель |
|
| text | string | да | да | введенный текст или заполнитель |
|
||||||
| placeholder | string | да | да | заполнитель (используется если ничего не было введено) |
|
| placeholder | string | да | да | заполнитель (используется если ничего не было введено) |
|
||||||
|
| hint | string | да | да | текст, отображаемый, когда ничего не введено |
|
||||||
| caret | int | да | да | позиция каретки. `textbox.caret = -1` установит позицию в конец текста |
|
| caret | int | да | да | позиция каретки. `textbox.caret = -1` установит позицию в конец текста |
|
||||||
| editable | bool | да | да | изменяемость текста |
|
| editable | bool | да | да | изменяемость текста |
|
||||||
| multiline | bool | да | да | поддержка многострочности |
|
| multiline | bool | да | да | поддержка многострочности |
|
||||||
|
|||||||
@@ -72,17 +72,20 @@
|
|||||||
|
|
||||||
## Структуры
|
## Структуры
|
||||||
|
|
||||||
Структура - набор правил по вставке фрагмента в мир генератором. На данный момент не имеет свойств, создаваясь в виде пустых объектов в файле `generators/имя_генератора.files/structures.toml`. Пример:
|
Структура - набор правил по вставке фрагмента в мир генератором. Структуры объявляются в виде объектов в файле `generators/имя_генератора.files/structures.toml`. Пример:
|
||||||
```toml
|
```toml
|
||||||
tree0 = {}
|
tree0 = {}
|
||||||
tree1 = {}
|
tree1 = {}
|
||||||
tree2 = {}
|
tree2 = {}
|
||||||
tower = {}
|
tower = {lowering=-2}
|
||||||
coal_ore0 = {}
|
coal_ore0 = {}
|
||||||
```
|
```
|
||||||
|
|
||||||
На данный момент, имя структуры должно совпадать с именем использованного фрагмента.
|
На данный момент, имя структуры должно совпадать с именем использованного фрагмента.
|
||||||
|
|
||||||
|
Доступные свойства:
|
||||||
|
- lowering - глубина погружения структуры под поверхность.
|
||||||
|
|
||||||
## Биомы
|
## Биомы
|
||||||
|
|
||||||
Биом определяет то, из каких блоков и какими слоями генерируется ландшафт, а так же набор растений, структур.
|
Биом определяет то, из каких блоков и какими слоями генерируется ландшафт, а так же набор растений, структур.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
tree0 = {}
|
tree0 = {}
|
||||||
tree1 = {}
|
tree1 = {}
|
||||||
tree2 = {}
|
tree2 = {}
|
||||||
tower = {}
|
tower = {lowering=2}
|
||||||
coal_ore0 = {}
|
coal_ore0 = {}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ static VoxelStructureMeta load_structure_meta(
|
|||||||
) {
|
) {
|
||||||
VoxelStructureMeta meta;
|
VoxelStructureMeta meta;
|
||||||
meta.name = name;
|
meta.name = name;
|
||||||
|
config.at("lowering").get(meta.lowering);
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ void TextBox::drawBackground(const DrawContext* pctx, Assets*) {
|
|||||||
|
|
||||||
void TextBox::refreshLabel() {
|
void TextBox::refreshLabel() {
|
||||||
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(input.empty() && !hint.empty() ? hint : getText());
|
||||||
|
|
||||||
if (autoresize && font) {
|
if (autoresize && font) {
|
||||||
auto size = getSize();
|
auto size = getSize();
|
||||||
@@ -505,7 +505,7 @@ void TextBox::performEditingKeyboardEvents(keycode key) {
|
|||||||
} else {
|
} else {
|
||||||
defocus();
|
defocus();
|
||||||
if (validate() && consumer) {
|
if (validate() && consumer) {
|
||||||
consumer(label->getText());
|
consumer(getText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (key == keycode::TAB) {
|
} else if (key == keycode::TAB) {
|
||||||
@@ -627,7 +627,7 @@ glm::vec4 TextBox::getErrorColor() const {
|
|||||||
return invalidColor;
|
return invalidColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring TextBox::getText() const {
|
const std::wstring& TextBox::getText() const {
|
||||||
if (input.empty())
|
if (input.empty())
|
||||||
return placeholder;
|
return placeholder;
|
||||||
return input;
|
return input;
|
||||||
@@ -638,7 +638,7 @@ void TextBox::setText(const std::wstring& value) {
|
|||||||
input.erase(std::remove(input.begin(), input.end(), '\r'), input.end());
|
input.erase(std::remove(input.begin(), input.end(), '\r'), input.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring TextBox::getPlaceholder() const {
|
const std::wstring& TextBox::getPlaceholder() const {
|
||||||
return placeholder;
|
return placeholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,6 +646,15 @@ void TextBox::setPlaceholder(const std::wstring& placeholder) {
|
|||||||
this->placeholder = placeholder;
|
this->placeholder = placeholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::wstring& TextBox::getHint() const {
|
||||||
|
return hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextBox::setHint(const std::wstring& text) {
|
||||||
|
this->hint = text;
|
||||||
|
}
|
||||||
|
|
||||||
std::wstring TextBox::getSelection() const {
|
std::wstring TextBox::getSelection() const {
|
||||||
return input.substr(selectionStart, selectionEnd-selectionStart);
|
return input.substr(selectionStart, selectionEnd-selectionStart);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,23 +13,35 @@ namespace gui {
|
|||||||
glm::vec4 focusedColor {0.0f, 0.0f, 0.0f, 1.0f};
|
glm::vec4 focusedColor {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
glm::vec4 invalidColor {0.1f, 0.05f, 0.03f, 1.0f};
|
glm::vec4 invalidColor {0.1f, 0.05f, 0.03f, 1.0f};
|
||||||
std::shared_ptr<Label> label;
|
std::shared_ptr<Label> label;
|
||||||
|
/// @brief Current user input
|
||||||
std::wstring input;
|
std::wstring input;
|
||||||
|
/// @brief Text will be used if nothing entered
|
||||||
std::wstring placeholder;
|
std::wstring placeholder;
|
||||||
|
/// @brief Text will be shown when nothing entered
|
||||||
|
std::wstring hint;
|
||||||
|
/// @brief Text supplier called every frame when not focused
|
||||||
wstringsupplier supplier = nullptr;
|
wstringsupplier supplier = nullptr;
|
||||||
|
/// @brief Text supplier called on Enter pressed
|
||||||
wstringconsumer consumer = nullptr;
|
wstringconsumer consumer = nullptr;
|
||||||
|
/// @brief Text supplier called while input
|
||||||
wstringconsumer subconsumer = nullptr;
|
wstringconsumer subconsumer = nullptr;
|
||||||
|
/// @brief Text validator returning boolean value
|
||||||
wstringchecker validator = nullptr;
|
wstringchecker validator = nullptr;
|
||||||
|
/// @brief Function called on focus
|
||||||
runnable onEditStart = nullptr;
|
runnable onEditStart = nullptr;
|
||||||
|
/// @brief Function called on up arrow pressed
|
||||||
runnable onUpPressed;
|
runnable onUpPressed;
|
||||||
|
/// @brief Function called on down arrow pressed
|
||||||
runnable onDownPressed;
|
runnable onDownPressed;
|
||||||
|
/// @brief Is current input valid
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
/// @brief text input pointer, value may be greather than text length
|
/// @brief Text input pointer, value may be greather than text length
|
||||||
size_t caret = 0;
|
size_t caret = 0;
|
||||||
/// @brief actual local (line) position of the caret on vertical move
|
/// @brief Actual local (line) position of the caret on vertical move
|
||||||
size_t maxLocalCaret = 0;
|
size_t maxLocalCaret = 0;
|
||||||
size_t textOffset = 0;
|
size_t 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;
|
||||||
Font* font = nullptr;
|
Font* font = nullptr;
|
||||||
|
|
||||||
@@ -101,17 +113,24 @@ namespace gui {
|
|||||||
virtual glm::vec4 getErrorColor() const;
|
virtual glm::vec4 getErrorColor() const;
|
||||||
|
|
||||||
/// @brief Get TextBox content text or placeholder if empty
|
/// @brief Get TextBox content text or placeholder if empty
|
||||||
virtual std::wstring getText() const;
|
virtual const std::wstring& getText() const;
|
||||||
|
|
||||||
/// @brief Set TextBox content text
|
/// @brief Set TextBox content text
|
||||||
virtual void setText(const std::wstring &value);
|
virtual void setText(const std::wstring &value);
|
||||||
|
|
||||||
/// @brief Get text placeholder
|
/// @brief Get text placeholder
|
||||||
virtual std::wstring getPlaceholder() const;
|
virtual const std::wstring& getPlaceholder() const;
|
||||||
|
|
||||||
/// @brief Set text placeholder
|
/// @brief Set text placeholder
|
||||||
/// @param text will be used instead of empty
|
/// @param text will be used instead of empty
|
||||||
virtual void setPlaceholder(const std::wstring& text);
|
virtual void setPlaceholder(const std::wstring& text);
|
||||||
|
|
||||||
|
/// @brief Get textbox hint
|
||||||
|
virtual const std::wstring& getHint() const;
|
||||||
|
|
||||||
|
/// @brief Set textbox hint
|
||||||
|
/// @param text will be shown instead of empty
|
||||||
|
virtual void setHint(const std::wstring& text);
|
||||||
|
|
||||||
/// @brief Get selected text
|
/// @brief Get selected text
|
||||||
virtual std::wstring getSelection() const;
|
virtual std::wstring getSelection() const;
|
||||||
|
|||||||
@@ -67,7 +67,11 @@ static runnable create_runnable(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static onaction create_action(UiXmlReader& reader, const xml::xmlelement& element, const std::string& name) {
|
static onaction create_action(
|
||||||
|
const UiXmlReader& reader,
|
||||||
|
const xml::xmlelement& element,
|
||||||
|
const std::string& name
|
||||||
|
) {
|
||||||
auto callback = create_runnable(reader, element, name);
|
auto callback = create_runnable(reader, element, name);
|
||||||
if (callback == nullptr) {
|
if (callback == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -76,7 +80,9 @@ static onaction create_action(UiXmlReader& reader, const xml::xmlelement& elemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read basic UINode properties */
|
/* Read basic UINode properties */
|
||||||
static void _readUINode(UiXmlReader& reader, const xml::xmlelement& element, UINode& node) {
|
static void _readUINode(
|
||||||
|
const UiXmlReader& reader, const xml::xmlelement& element, UINode& node
|
||||||
|
) {
|
||||||
if (element->has("id")) {
|
if (element->has("id")) {
|
||||||
node.setId(element->attr("id").getText());
|
node.setId(element->attr("id").getText());
|
||||||
}
|
}
|
||||||
@@ -331,8 +337,11 @@ static std::shared_ptr<UINode> readCheckBox(UiXmlReader& reader, const xml::xmle
|
|||||||
|
|
||||||
static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, const xml::xmlelement& element) {
|
static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, const xml::xmlelement& element) {
|
||||||
auto placeholder = util::str2wstr_utf8(element->attr("placeholder", "").getText());
|
auto placeholder = util::str2wstr_utf8(element->attr("placeholder", "").getText());
|
||||||
|
auto hint = util::str2wstr_utf8(element->attr("hint", "").getText());
|
||||||
auto text = readAndProcessInnerText(element, reader.getContext());
|
auto text = readAndProcessInnerText(element, reader.getContext());
|
||||||
auto textbox = std::make_shared<TextBox>(placeholder, glm::vec4(0.0f));
|
auto textbox = std::make_shared<TextBox>(placeholder, glm::vec4(0.0f));
|
||||||
|
textbox->setHint(hint);
|
||||||
|
|
||||||
_readPanel(reader, element, *textbox);
|
_readPanel(reader, element, *textbox);
|
||||||
textbox->setText(text);
|
textbox->setText(text);
|
||||||
|
|
||||||
|
|||||||
@@ -242,6 +242,13 @@ static int p_get_placeholder(UINode* node, lua::State* L) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int p_get_hint(UINode* node, lua::State* L) {
|
||||||
|
if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||||
|
return lua::pushwstring(L, box->getHint());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int p_get_text(UINode* node, lua::State* L) {
|
static int p_get_text(UINode* node, lua::State* L) {
|
||||||
if (auto button = dynamic_cast<Button*>(node)) {
|
if (auto button = dynamic_cast<Button*>(node)) {
|
||||||
return lua::pushwstring(L, button->getText());
|
return lua::pushwstring(L, button->getText());
|
||||||
@@ -364,6 +371,7 @@ static int l_gui_getattr(lua::State* L) {
|
|||||||
{"clear", p_get_clear},
|
{"clear", p_get_clear},
|
||||||
{"setInterval", p_set_interval},
|
{"setInterval", p_set_interval},
|
||||||
{"placeholder", p_get_placeholder},
|
{"placeholder", p_get_placeholder},
|
||||||
|
{"hint", p_get_hint},
|
||||||
{"valid", p_is_valid},
|
{"valid", p_is_valid},
|
||||||
{"caret", p_get_caret},
|
{"caret", p_get_caret},
|
||||||
{"text", p_get_text},
|
{"text", p_get_text},
|
||||||
@@ -430,6 +438,11 @@ static void p_set_placeholder(UINode* node, lua::State* L, int idx) {
|
|||||||
box->setPlaceholder(lua::require_wstring(L, idx));
|
box->setPlaceholder(lua::require_wstring(L, idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static void p_set_hint(UINode* node, lua::State* L, int idx) {
|
||||||
|
if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||||
|
box->setHint(lua::require_wstring(L, idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
static void p_set_text(UINode* node, lua::State* L, int idx) {
|
static void p_set_text(UINode* node, lua::State* L, int idx) {
|
||||||
if (auto label = dynamic_cast<Label*>(node)) {
|
if (auto label = dynamic_cast<Label*>(node)) {
|
||||||
label->setText(lua::require_wstring(L, idx));
|
label->setText(lua::require_wstring(L, idx));
|
||||||
@@ -540,6 +553,7 @@ static int l_gui_setattr(lua::State* L) {
|
|||||||
{"visible", p_set_visible},
|
{"visible", p_set_visible},
|
||||||
{"enabled", p_set_enabled},
|
{"enabled", p_set_enabled},
|
||||||
{"placeholder", p_set_placeholder},
|
{"placeholder", p_set_placeholder},
|
||||||
|
{"hint", p_set_hint},
|
||||||
{"text", p_set_text},
|
{"text", p_set_text},
|
||||||
{"editable", p_set_editable},
|
{"editable", p_set_editable},
|
||||||
{"src", p_set_src},
|
{"src", p_set_src},
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ class VoxelFragment;
|
|||||||
struct GeneratorDef;
|
struct GeneratorDef;
|
||||||
|
|
||||||
struct VoxelStructureMeta {
|
struct VoxelStructureMeta {
|
||||||
|
/// @brief Structure name
|
||||||
std::string name;
|
std::string name;
|
||||||
|
/// @brief Structure lowering on placement
|
||||||
|
int lowering = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BlocksLayer {
|
struct BlocksLayer {
|
||||||
|
|||||||
@@ -270,10 +270,11 @@ void WorldGenerator::generateStructures(
|
|||||||
if (height < def.seaLevel) {
|
if (height < def.seaLevel) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto& structure = *def.structures[structureId]->fragments[rotation];
|
auto& structure = *def.structures[structureId];
|
||||||
glm::ivec3 position {x, height, z};
|
auto& fragment = *structure.fragments[rotation];
|
||||||
position.x -= structure.getSize().x / 2;
|
glm::ivec3 position {x, height-structure.meta.lowering, z};
|
||||||
position.z -= structure.getSize().z / 2;
|
position.x -= fragment.getSize().x / 2;
|
||||||
|
position.z -= fragment.getSize().z / 2;
|
||||||
placeStructure(
|
placeStructure(
|
||||||
StructurePlacement {
|
StructurePlacement {
|
||||||
structureId,
|
structureId,
|
||||||
|
|||||||
Reference in New Issue
Block a user