diff --git a/res/content/base/block_materials/grass_block.json b/res/content/base/block_materials/grass_block.json index d866ff40..d45672a2 100644 --- a/res/content/base/block_materials/grass_block.json +++ b/res/content/base/block_materials/grass_block.json @@ -1,5 +1,6 @@ { "steps-sound": "steps/grass", "place-sound": "blocks/ground_place", - "break-sound": "blocks/ground_break" + "break-sound": "blocks/ground_break", + "hit-sound": "blocks/ground_hit" } diff --git a/res/content/base/block_materials/ground.json b/res/content/base/block_materials/ground.json index 36b15aed..951cb5df 100644 --- a/res/content/base/block_materials/ground.json +++ b/res/content/base/block_materials/ground.json @@ -1,5 +1,6 @@ { "steps-sound": "steps/ground", "place-sound": "blocks/ground_place", - "break-sound": "blocks/ground_break" + "break-sound": "blocks/ground_break", + "hit-sound": "blocks/ground_hit" } diff --git a/res/content/base/block_materials/stone.json b/res/content/base/block_materials/stone.json index a5b6df37..43f579e7 100644 --- a/res/content/base/block_materials/stone.json +++ b/res/content/base/block_materials/stone.json @@ -1,5 +1,6 @@ { "steps-sound": "steps/stone", "place-sound": "blocks/stone_place", - "break-sound": "blocks/stone_break" + "break-sound": "blocks/stone_break", + "hit-sound": "blocks/stone_hit" } diff --git a/res/content/base/block_materials/wood.json b/res/content/base/block_materials/wood.json index d29b8a63..0c8e9a46 100644 --- a/res/content/base/block_materials/wood.json +++ b/res/content/base/block_materials/wood.json @@ -1,5 +1,6 @@ { "steps-sound": "steps/wood", "place-sound": "blocks/wood_place", - "break-sound": "blocks/wood_break" + "break-sound": "blocks/wood_break", + "hit-sound": "blocks/wood_hit" } diff --git a/res/content/base/blocks/dirt.json b/res/content/base/blocks/dirt.json index ff512254..060325a8 100644 --- a/res/content/base/blocks/dirt.json +++ b/res/content/base/blocks/dirt.json @@ -2,5 +2,5 @@ "texture": "dirt", "material": "base:ground", "surface-replacement": "base:grass_block", - "base:durability": 1.0 + "base:durability": 1.5 } diff --git a/res/content/base/blocks/grass.json b/res/content/base/blocks/grass.json index e55bc2ac..d5b8472e 100644 --- a/res/content/base/blocks/grass.json +++ b/res/content/base/blocks/grass.json @@ -8,7 +8,7 @@ "replaceable": true, "grounded": true, "model": "X", - "hitbox": [0.15, 0.0, 0.15, 0.7, 0.7, 0.7], + "hitbox": [0.15, 0.0, 0.15, 0.7, 0.5, 0.7], "base:durability": 0.0, "base:loot": [] } diff --git a/res/content/base/blocks/grass_block.json b/res/content/base/blocks/grass_block.json index e89a774c..3a55bc5e 100644 --- a/res/content/base/blocks/grass_block.json +++ b/res/content/base/blocks/grass_block.json @@ -8,7 +8,7 @@ "grass_side", "grass_side" ], - "base:durability": 1.3, + "base:durability": 1.7, "base:loot": [ {"item": "base:dirt.item"} ] diff --git a/res/content/base/sounds/blocks/ground_hit.ogg b/res/content/base/sounds/blocks/ground_hit.ogg new file mode 100644 index 00000000..f59207cd Binary files /dev/null and b/res/content/base/sounds/blocks/ground_hit.ogg differ diff --git a/res/content/base/sounds/blocks/stone_break.ogg b/res/content/base/sounds/blocks/stone_break.ogg index b54a78a8..e35369cd 100644 Binary files a/res/content/base/sounds/blocks/stone_break.ogg and b/res/content/base/sounds/blocks/stone_break.ogg differ diff --git a/res/content/base/sounds/blocks/stone_hit.ogg b/res/content/base/sounds/blocks/stone_hit.ogg new file mode 100644 index 00000000..cb956164 Binary files /dev/null and b/res/content/base/sounds/blocks/stone_hit.ogg differ diff --git a/res/content/base/sounds/blocks/wood_hit.ogg b/res/content/base/sounds/blocks/wood_hit.ogg new file mode 100644 index 00000000..8f8bea0f Binary files /dev/null and b/res/content/base/sounds/blocks/wood_hit.ogg differ diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index acd833b0..8a5f66eb 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -355,7 +355,7 @@ function __vc_on_hud_open() hud._set_debug_cheats(value) end) input.add_callback("devtools.console", function() - if hud.is_paused() then + if menu.page ~= "" then return end time.post_runnable(function() @@ -363,7 +363,7 @@ function __vc_on_hud_open() end) end) input.add_callback("hud.chat", function() - if hud.is_paused() then + if menu.page ~= "" then return end time.post_runnable(function() diff --git a/src/graphics/ui/elements/Label.cpp b/src/graphics/ui/elements/Label.cpp index d2678fd7..392a9434 100644 --- a/src/graphics/ui/elements/Label.cpp +++ b/src/graphics/ui/elements/Label.cpp @@ -21,6 +21,20 @@ void LabelCache::prepare(Font* font, size_t wrapWidth) { } } +size_t LabelCache::getTextLineOffset(size_t line) const { + line = std::min(lines.size()-1, line); + return lines.at(line).offset; +} + +uint LabelCache::getLineByTextIndex(size_t index) const { + for (size_t i = 0; i < lines.size(); i++) { + if (lines[i].offset > index) { + return i-1; + } + } + return lines.size()-1; +} + void LabelCache::update(const std::wstring& text, bool multiline, bool wrap) { resetFlag = false; lines.clear(); @@ -49,7 +63,7 @@ void LabelCache::update(const std::wstring& text, bool multiline, bool wrap) { } Label::Label(const std::string& text, std::string fontName) - : UINode(glm::vec2(text.length() * 8, 15)), + : UINode(glm::vec2(text.length() * 8, 16)), text(util::str2wstr_utf8(text)), fontName(std::move(fontName)) { @@ -59,7 +73,7 @@ Label::Label(const std::string& text, std::string fontName) Label::Label(const std::wstring& text, std::string fontName) - : UINode(glm::vec2(text.length() * 8, 15)), + : UINode(glm::vec2(text.length() * 8, 16)), text(text), fontName(std::move(fontName)) { @@ -131,8 +145,7 @@ int Label::getTextYOffset() const { } size_t Label::getTextLineOffset(size_t line) const { - line = std::min(cache.lines.size()-1, line); - return cache.lines.at(line).offset; + return cache.getTextLineOffset(line); } bool Label::isFakeLine(size_t line) const { @@ -152,12 +165,7 @@ uint Label::getLineByYOffset(int offset) const { } uint Label::getLineByTextIndex(size_t index) const { - for (size_t i = 0; i < cache.lines.size(); i++) { - if (cache.lines[i].offset > index) { - return i-1; - } - } - return cache.lines.size()-1; + return cache.getLineByTextIndex(index); } uint Label::getLinesNumber() const { diff --git a/src/graphics/ui/elements/Label.hpp b/src/graphics/ui/elements/Label.hpp index df177f71..63637d5f 100644 --- a/src/graphics/ui/elements/Label.hpp +++ b/src/graphics/ui/elements/Label.hpp @@ -20,6 +20,9 @@ namespace gui { void prepare(Font* font, size_t wrapWidth); void update(const std::wstring& text, bool multiline, bool wrap); + + size_t getTextLineOffset(size_t line) const; + uint getLineByTextIndex(size_t index) const; }; class Label : public UINode { diff --git a/src/graphics/ui/elements/TextBox.cpp b/src/graphics/ui/elements/TextBox.cpp index 1daa590d..c7933c7e 100644 --- a/src/graphics/ui/elements/TextBox.cpp +++ b/src/graphics/ui/elements/TextBox.cpp @@ -57,6 +57,8 @@ void TextBox::draw(const DrawContext& pctx, const Assets& assets) { if (!isFocused()) { return; } + const auto& labelText = getText(); + glm::vec2 pos = calcPos(); glm::vec2 size = getSize(); @@ -70,8 +72,8 @@ void TextBox::draw(const DrawContext& pctx, const Assets& assets) { batch->texture(nullptr); batch->setColor(glm::vec4(1.0f)); if (editable && int((Window::time() - caretLastMove) * 2) % 2 == 0) { - uint line = label->getLineByTextIndex(caret); - uint lcaret = caret - label->getTextLineOffset(line); + uint line = rawTextCache.getLineByTextIndex(caret); + uint lcaret = caret - rawTextCache.getTextLineOffset(line); int width = font->calcWidth(input, lcaret); batch->rect( lcoord.x + width, @@ -89,10 +91,10 @@ void TextBox::draw(const DrawContext& pctx, const Assets& assets) { batch->setColor(glm::vec4(0.8f, 0.9f, 1.0f, 0.25f)); int start = font->calcWidth( - input, selectionStart - label->getTextLineOffset(startLine) + labelText, selectionStart - label->getTextLineOffset(startLine) ); int end = font->calcWidth( - input, selectionEnd - label->getTextLineOffset(endLine) + labelText, selectionEnd - label->getTextLineOffset(endLine) ); int lineY = label->getLineYOffset(startLine); @@ -192,11 +194,14 @@ void TextBox::drawBackground(const DrawContext& pctx, const Assets&) { } void TextBox::refreshLabel() { + rawTextCache.prepare(font, static_cast(getSize().x)); + rawTextCache.update(input, multiline, false); + label->setColor(textColor * glm::vec4(input.empty() ? 0.5f : 1.0f)); const auto& displayText = input.empty() && !hint.empty() ? hint : getText(); if (markup == "md") { - auto [processedText, styles] = markdown::process(displayText, !focused); + auto [processedText, styles] = markdown::process(displayText, !focused || !editable); label->setText(std::move(processedText)); label->setStyles(std::move(styles)); } else { @@ -313,7 +318,7 @@ size_t TextBox::getLineLength(uint line) const { size_t position = label->getTextLineOffset(line); size_t lineLength = label->getTextLineOffset(line+1)-position; if (lineLength == 0) { - lineLength = input.length() - position + 1; + lineLength = label->getText().length() - position + 1; } return lineLength; } @@ -325,8 +330,8 @@ size_t TextBox::getSelectionLength() const { /// @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; + refresh(); } void TextBox::typed(unsigned int codepoint) { @@ -403,7 +408,9 @@ void TextBox::refresh() { Container::refresh(); label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y)); label->setPos(glm::vec2( - padding.x + LINE_NUMBERS_PANE_WIDTH * showLineNumbers, padding.y + padding.x + LINE_NUMBERS_PANE_WIDTH * showLineNumbers + textInitX - + static_cast(textOffset), + padding.y )); } @@ -421,15 +428,16 @@ size_t TextBox::normalizeIndex(int index) { int TextBox::calcIndexAt(int x, int y) const { if (font == nullptr) return 0; + const auto& labelText = label->getText(); glm::vec2 lcoord = label->calcPos(); uint line = label->getLineByYOffset(y-lcoord.y); line = std::min(line, label->getLinesNumber()-1); size_t lineLength = getLineLength(line); uint offset = 0; - while (lcoord.x + font->calcWidth(input, offset) < x && offset < lineLength-1) { + while (lcoord.x + font->calcWidth(labelText, offset) < x && offset < lineLength-1) { offset++; } - return std::min(offset+label->getTextLineOffset(line), input.length()); + return std::min(offset+label->getTextLineOffset(line), labelText.length()); } static inline std::wstring get_alphabet(wchar_t c) { @@ -443,21 +451,22 @@ static inline std::wstring get_alphabet(wchar_t c) { } void TextBox::tokenSelectAt(int index) { - if (input.empty()) { + const auto& actualText = label->getText(); + if (actualText.empty()) { return; } int left = index; int right = index; - std::wstring alphabet = get_alphabet(input.at(index)); + std::wstring alphabet = get_alphabet(actualText.at(index)); while (left >= 0) { - if (alphabet.find(input.at(left)) == std::wstring::npos) { + if (alphabet.find(actualText.at(left)) == std::wstring::npos) { break; } left--; } - while (static_cast(right) < input.length()) { - if (alphabet.find(input.at(right)) == std::wstring::npos) { + while (static_cast(right) < actualText.length()) { + if (alphabet.find(actualText.at(right)) == std::wstring::npos) { break; } right++; @@ -800,7 +809,8 @@ void TextBox::setHint(const std::wstring& text) { } std::wstring TextBox::getSelection() const { - return input.substr(selectionStart, selectionEnd-selectionStart); + const auto& text = label->getText(); + return text.substr(selectionStart, selectionEnd-selectionStart); } size_t TextBox::getCaret() const { @@ -808,26 +818,34 @@ size_t TextBox::getCaret() const { } void TextBox::setCaret(size_t position) { - this->caret = std::min(static_cast(position), input.length()); + const auto& labelText = label->getText(); + caret = std::min(static_cast(position), input.length()); if (font == nullptr) { return; } - caretLastMove = Window::time(); int width = label->getSize().x; - uint line = label->getLineByTextIndex(caret); + + rawTextCache.prepare(font, width); + rawTextCache.update(input, multiline, label->isTextWrapping()); + + caretLastMove = Window::time(); + + uint line = rawTextCache.getLineByTextIndex(caret); int offset = label->getLineYOffset(line) + getContentOffset().y; uint lineHeight = font->getLineHeight()*label->getLineInterval(); if (scrollStep == 0) { scrollStep = lineHeight; } if (offset < 0) { - scrolled(-glm::floor(offset/static_cast(scrollStep)+0.5f)); + scrolled(-glm::floor(offset / static_cast(scrollStep)+0.5f)); } else if (offset >= getSize().y) { offset -= getSize().y; - scrolled(-glm::ceil(offset/static_cast(scrollStep)+0.5f)); + scrolled(-glm::ceil(offset / static_cast(scrollStep)+0.5f)); } - uint lcaret = caret - label->getTextLineOffset(line); - int realoffset = font->calcWidth(input, lcaret)-int(textOffset) + 2; + int lcaret = caret - rawTextCache.getTextLineOffset(line); + int realoffset = + font->calcWidth(labelText, lcaret) - static_cast(textOffset) + 2; + if (realoffset-width > 0) { setTextOffset(textOffset + realoffset-width); } else if (realoffset < 0) { diff --git a/src/graphics/ui/elements/TextBox.hpp b/src/graphics/ui/elements/TextBox.hpp index be459b89..0eff89f2 100644 --- a/src/graphics/ui/elements/TextBox.hpp +++ b/src/graphics/ui/elements/TextBox.hpp @@ -6,9 +6,8 @@ class Font; namespace gui { - class Label; - class TextBox : public Container { + LabelCache rawTextCache; protected: glm::vec4 focusedColor {0.0f, 0.0f, 0.0f, 1.0f}; glm::vec4 invalidColor {0.1f, 0.05f, 0.03f, 1.0f}; @@ -43,11 +42,12 @@ namespace gui { /// @brief Actual local (line) position of the caret on vertical move size_t maxLocalCaret = 0; size_t textOffset = 0; - int textInitX; + int textInitX = 0; /// @brief Last time of the caret was moved (used for blink animation) double caretLastMove = 0.0; Font* font = nullptr; + // Note: selection does not include markup size_t selectionStart = 0; size_t selectionEnd = 0; size_t selectionOrigin = 0; diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index e0c70f52..8da49514 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -49,10 +49,20 @@ CameraControl::CameraControl( offset(0.0f, 0.7f, 0.0f) { } -void CameraControl::refresh() { +void CameraControl::refreshPosition() { camera->position = player.getPosition() + offset; } +void CameraControl::refreshRotation() { + const glm::vec3& rotation = player.getRotation(); + camera->rotation = glm::mat4(1.0f); + camera->rotate( + glm::radians(rotation.y), + glm::radians(rotation.x), + glm::radians(rotation.z) + ); +} + void CameraControl::updateMouse(PlayerInput& input) { glm::vec3 rotation = player.getRotation(); @@ -177,7 +187,7 @@ void CameraControl::update( const auto& spCamera = player.spCamera; const auto& tpCamera = player.tpCamera; - refresh(); + refreshPosition(); camera->updateVectors(); if (player.currentCamera == spCamera) { @@ -274,6 +284,7 @@ void PlayerController::postUpdate(float delta, bool input, bool pause) { if (!pause && input) { camControl.updateMouse(this->input); } + camControl.refreshRotation(); player.postUpdate(); camControl.update(this->input, pause ? 0.0f : delta, *player.chunks); if (input) { diff --git a/src/logic/PlayerController.hpp b/src/logic/PlayerController.hpp index 88e3a5f4..00299e4c 100644 --- a/src/logic/PlayerController.hpp +++ b/src/logic/PlayerController.hpp @@ -42,7 +42,8 @@ public: CameraControl(Player& player, const CameraSettings& settings); void updateMouse(PlayerInput& input); void update(PlayerInput input, float delta, const Chunks& chunks); - void refresh(); + void refreshPosition(); + void refreshRotation(); }; class PlayerController {