diff --git a/README.md b/README.md index 698204d6c..a620c9fa3 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ This list is non exhaustive. - Particle system - Fluid propagation - Player model display (currently displaying an ugly box) -- Day/night cycle with sun/moon display +- Day/night cycle with sun/moon display ([#73](https://github.com/Unarelith/OpenMiner/issues/73)) - Real worldgen (seed-based, biomes, cave tunnels) - Entities (block drops, mobs, etc...) - Clouds ([#52](https://github.com/Unarelith/OpenMiner/pull/52)) diff --git a/TODO b/TODO index ef0d6d55e..026a45211 100644 --- a/TODO +++ b/TODO @@ -10,13 +10,9 @@ TODO # Issues -• DONE: Blocks can be placed inside the player (check for AABB?) -• DONE: Sometimes it’s possible to aim between two blocks and right-clicking will replace one • TODO: GUI scale issues ◦ TODO: `HUD` doesn’t update when GUI scale is changed ◦ TODO: `SettingsMenuState` should update scaling when the setting is changed - ◦ DONE: All Lua-defined GUI are not scaled correctly with lower GUI scale settings - ◦ DONE: Send client screen size and GUI scale to server ◦ TODO: Trees should block light • TODO: Blocks can be accessed from outside the world (will need a refactoring) • TODO: Collisions are fucked up with blocks placed at `x = -1` from `x = 0` @@ -27,13 +23,6 @@ TODO → Maybe this is the way to add custom vertex attributes while having default ones? Check 3dee → Or maybe it would be better to use a VAO in `GameKit` -# GUI - -• DONE: Implement `PlayerInventoryWidget` completely in Lua -• DONE: Implement `PlayerCraftingWidget` completely in Lua -• DONE: Implement `FurnaceWidget` completely in Lua - ◦ DONE: Add a `ProgressBarWidget` - # Menus • TODO: World loading/saving diff --git a/client/source/gui/Font.cpp b/client/source/gui/Font.cpp index a7cbd8c2d..ba5343fa7 100644 --- a/client/source/gui/Font.cpp +++ b/client/source/gui/Font.cpp @@ -41,6 +41,18 @@ Font::Font(const std::string &textureName, const std::string &configPath) parseConfig(configPath); } +gk::Vector2f Font::getTexCoords(u8 c, u8 x, u8 y) const { + u8 tileX = c % (m_texture.getSize().x / m_width); + u8 tileY = c / (m_texture.getSize().x / m_width); + + gk::Vector2f texCoords{ + (tileX + x) * m_width / (float)m_texture.getSize().x, + (tileY + y) * m_height / (float)m_texture.getSize().y + }; + + return texCoords; +} + void Font::parseConfig(const std::string &configPath) { std::ifstream file(configPath); diff --git a/client/source/gui/Font.hpp b/client/source/gui/Font.hpp index 8a3056a14..b3cb8f56c 100644 --- a/client/source/gui/Font.hpp +++ b/client/source/gui/Font.hpp @@ -29,7 +29,7 @@ #include -#include +#include namespace gk { class Texture; @@ -39,7 +39,10 @@ class Font { public: Font(const std::string &textureName, const std::string &configPath); - u8 getCharWidth(u8 c) { return m_charWidth[c]; } + gk::Vector2f getTexCoords(u8 c, u8 x, u8 y) const; + + u8 getCharWidth(u8 c) const { return m_charWidth[c]; } + gk::Vector2i getTileSize() const { return {m_width, m_height}; } const std::string &textureName() const { return m_textureName; } // FIXME: Will be removed later const gk::Texture &texture() const { return m_texture; } @@ -51,6 +54,8 @@ class Font { gk::Texture &m_texture; u8 m_charWidth[256]; + u8 m_width = 8; // FIXME: Hardcoded value + u8 m_height = 8; // FIXME: Hardcoded value }; #endif // FONT_HPP_ diff --git a/client/source/gui/Text.cpp b/client/source/gui/Text.cpp index 7c9e39121..a5e5f8169 100644 --- a/client/source/gui/Text.cpp +++ b/client/source/gui/Text.cpp @@ -24,6 +24,7 @@ * * ===================================================================================== */ +#include #include #include "Color.hpp" @@ -37,78 +38,137 @@ Text::Text() : m_font(gk::ResourceHandler::getInstance().get("font-ascii") void Text::setText(const std::string &text) { if (m_text != text) { m_text = text; - updateTextSprites(); + m_isUpdateNeeded = true; } } void Text::setColor(const gk::Color &color) { if (m_color != color) { m_color = color; - updateTextSprites(); + m_isUpdateNeeded = true; + } +} + +void Text::setPadding(int x, int y) { + if (m_padding.x != x || m_padding.y != y) { + m_padding.x = x; + m_padding.y = y; + m_isUpdateNeeded = true; + } +} + +void Text::setMaxLineLength(unsigned int maxLineLength) { + if (m_maxLineLength != maxLineLength) { + m_maxLineLength = maxLineLength; + m_isUpdateNeeded = true; } } void Text::draw(gk::RenderTarget &target, gk::RenderStates states) const { + if (m_isUpdateNeeded) { + updateVertexBuffer(); + m_isUpdateNeeded = false; + } + + if (m_verticesCount == 0) return; + states.transform *= getTransform(); target.draw(m_background, states); states.transform.translate(m_padding.x, m_padding.y); + states.texture = &m_font.texture(); + states.vertexAttributes = gk::VertexAttribute::Only2d; - for(const gk::Sprite &sprite : m_textSprites) { - target.draw(sprite, states); - } + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + + target.draw(m_vbo, GL_TRIANGLES, 0, m_verticesCount, states); } -// FIXME: USE A VBO INSTEAD -void Text::updateTextSprites() { - m_textSprites.clear(); +void Text::updateVertexBuffer() const { + if (!m_isUpdateNeeded) return; - unsigned int x = 0; - unsigned int y = 0; - unsigned int maxX = 0; + std::vector vertices; + + u32 x = 0; + u32 y = 0; + u32 maxX = 0; gk::Color color = gk::Color{70, 70, 70, 255}; for(char c : m_text) { if (c == '\n' || (m_maxLineLength && x + m_font.getCharWidth(c) >= m_maxLineLength)) { - y += 9; + y += m_font.getTileSize().y + 1; x = 0; continue; } - gk::Sprite sprite{m_font.textureName(), 8, 8}; - sprite.setCurrentFrame(c); - sprite.setPosition(x + 1, y + 1, 0); - sprite.setColor(color); - m_textSprites.emplace_back(std::move(sprite)); + addCharacter(x + 1, y + 1, color, c, vertices); + x += m_font.getCharWidth(c); } + x = 0; y = 0; color = m_color; for(char c : m_text) { if (c == '\n' || (m_maxLineLength && x + m_font.getCharWidth(c) >= m_maxLineLength)) { maxX = std::max(x, maxX); - y += 9; + y += m_font.getTileSize().y + 1; x = 0; continue; } - gk::Sprite sprite{m_font.textureName(), 8, 8}; - sprite.setCurrentFrame(c); - sprite.setPosition(x, y, 0); if (c == '[') color = Color::Blue; - sprite.setColor(color); - m_textSprites.emplace_back(std::move(sprite)); + + addCharacter(x, y, color, c, vertices); + x += m_font.getCharWidth(c); } + m_verticesCount = vertices.size(); + + gk::VertexBuffer::bind(&m_vbo); + m_vbo.setData(sizeof(gk::Vertex) * m_verticesCount, vertices.data(), GL_DYNAMIC_DRAW); + gk::VertexBuffer::bind(nullptr); + m_size.x = std::max(x, maxX); - m_size.y = y + 9; + m_size.y = y + m_font.getTileSize().y + 1; - unsigned int backgroundX = std::max(m_background.getSize().x, m_size.x + m_padding.x); - unsigned int backgroundY = std::max(m_background.getSize().y, m_size.y + m_padding.y); + u32 backgroundX = std::max(m_background.getSize().x, m_size.x + m_padding.x); + u32 backgroundY = std::max(m_background.getSize().y, m_size.y + m_padding.y); m_background.setSize(backgroundX, backgroundY); } +void Text::addCharacter(u32 x, u32 y, const gk::Color &color, u8 c, std::vector &vertices) const { + static const u8 coords[6][2] = { + {1, 0}, + {0, 0}, + {1, 1}, + + {1, 1}, + {0, 0}, + {0, 1}, + }; + + for (int i = 0 ; i < 6 ; ++i) { + vertices.emplace_back(); + gk::Vertex &vertex = vertices.back(); + + vertex.coord3d[0] = x + coords[i][0] * m_font.getTileSize().x; + vertex.coord3d[1] = y + coords[i][1] * m_font.getTileSize().y; + vertex.coord3d[2] = 0; + vertex.coord3d[3] = -1; + + vertex.color[0] = color.r; + vertex.color[1] = color.g; + vertex.color[2] = color.b; + vertex.color[3] = color.a; + + gk::Vector2f texCoords = m_font.getTexCoords(c, coords[i][0], coords[i][1]); + vertex.texCoord[0] = texCoords.x; + vertex.texCoord[1] = texCoords.y; + } +} + diff --git a/client/source/gui/Text.hpp b/client/source/gui/Text.hpp index 64a1f70e4..04c52b050 100644 --- a/client/source/gui/Text.hpp +++ b/client/source/gui/Text.hpp @@ -28,9 +28,10 @@ #define TEXT_HPP_ #include +#include +#include #include -#include class Font; @@ -49,28 +50,33 @@ class Text : public gk::Drawable, public gk::Transformable { void setBackgroundColor(const gk::Color &color) { m_background.setFillColor(color); } void setBackgroundSize(unsigned int width, unsigned int height) { m_background.setSize(width, height); } - void setPadding(int x, int y) { m_padding.x = x; m_padding.y = y; updateTextSprites(); } + void setPadding(int x, int y); - void setMaxLineLength(unsigned int maxLineLength) { m_maxLineLength = maxLineLength; updateTextSprites(); } + void setMaxLineLength(u32 maxLineLength); + + void updateVertexBuffer() const; private: void draw(gk::RenderTarget &target, gk::RenderStates states) const override; - void updateTextSprites(); + void addCharacter(u32 x, u32 y, const gk::Color &color, u8 c, std::vector &vertices) const; std::string m_text; - std::vector m_textSprites; Font &m_font; - gk::Vector2i m_size; + gk::VertexBuffer m_vbo; + mutable u32 m_verticesCount = 0; + mutable bool m_isUpdateNeeded = true; + + mutable gk::Vector2i m_size; gk::Vector2i m_padding{0, 0}; gk::Color m_color = gk::Color::White; - gk::RectangleShape m_background; + mutable gk::RectangleShape m_background; - unsigned int m_maxLineLength = 0; + u32 m_maxLineLength = 0; }; #endif // TEXT_HPP_ diff --git a/client/source/gui/TextButton.cpp b/client/source/gui/TextButton.cpp index 7b7338542..bce7a42a9 100644 --- a/client/source/gui/TextButton.cpp +++ b/client/source/gui/TextButton.cpp @@ -27,13 +27,6 @@ #include "TextButton.hpp" TextButton::TextButton(Widget *parent) : Widget(200, 20, parent) { - // m_text.setFont("font-default"); - // m_text.setCharacterSize(8); - // - // m_textShadow.setFont("font-default"); - // m_textShadow.setCharacterSize(8); - // m_textShadow.setColor(gk::Color{70, 70, 70, 255}); - m_background.setClipRect(0, 66, 200, 20); m_hoverBackground.setClipRect(0, 86, 200, 20); m_disabledBackground.setClipRect(0, 46, 200, 20); @@ -62,15 +55,9 @@ void TextButton::onEvent(const SDL_Event &event) { void TextButton::setText(const std::string &text) { m_text.setText(text); + m_text.updateVertexBuffer(); m_text.setPosition(m_width / 2 - m_text.getSize().x / 2, m_height / 2 - m_text.getSize().y / 2, 0); - - // m_text.setString(text); - // m_text.setPosition(m_width / 2 - m_text.getLocalBounds().width / 2, - // m_height / 2 - m_text.getLocalBounds().height / 2 - 1, 0); - - // m_textShadow.setString(text); - // m_textShadow.setPosition(m_text.getPosition() + gk::Vector3f{1.f, 1.f, 0.f}); } void TextButton::draw(gk::RenderTarget &target, gk::RenderStates states) const { @@ -83,7 +70,6 @@ void TextButton::draw(gk::RenderTarget &target, gk::RenderStates states) const { else target.draw(m_background, states); - // target.draw(m_textShadow, states); target.draw(m_text, states); } diff --git a/client/source/gui/TextButton.hpp b/client/source/gui/TextButton.hpp index 596475af3..ebec29b19 100644 --- a/client/source/gui/TextButton.hpp +++ b/client/source/gui/TextButton.hpp @@ -32,7 +32,6 @@ #include #include -// #include #include "Text.hpp" #include "Widget.hpp" @@ -63,8 +62,6 @@ class TextButton : public Widget { gk::Image m_disabledBackground{"texture-widgets"}; Text m_text; - // gk::Text m_text; - // gk::Text m_textShadow; CppCallback m_cppCallback; LuaCallback m_luaCallback; diff --git a/client/source/hud/BlockInfoWidget.hpp b/client/source/hud/BlockInfoWidget.hpp index 6c19ba23c..7312d6a41 100644 --- a/client/source/hud/BlockInfoWidget.hpp +++ b/client/source/hud/BlockInfoWidget.hpp @@ -27,6 +27,8 @@ #ifndef BLOCKINFOWIDGET_HPP_ #define BLOCKINFOWIDGET_HPP_ +#include + #include "ItemWidget.hpp" class BlockInfoWidget : public Widget { diff --git a/client/source/hud/ChatMessage.cpp b/client/source/hud/ChatMessage.cpp index 2696795e9..38a13f281 100644 --- a/client/source/hud/ChatMessage.cpp +++ b/client/source/hud/ChatMessage.cpp @@ -37,6 +37,7 @@ ChatMessage::ChatMessage(u16 clientID, const std::string &message, u32 posY) { m_text.setBackgroundSize(300, 10); m_text.setMaxLineLength(300); m_text.setPadding(1, 1); + m_text.updateVertexBuffer(); m_timer.reset(); m_timer.start(); diff --git a/client/source/hud/ChatMessage.hpp b/client/source/hud/ChatMessage.hpp index 6b0e50dbf..135921da2 100644 --- a/client/source/hud/ChatMessage.hpp +++ b/client/source/hud/ChatMessage.hpp @@ -27,6 +27,8 @@ #ifndef CHATMESSAGE_HPP_ #define CHATMESSAGE_HPP_ +#include + #include "Text.hpp" class ChatMessage : public gk::Drawable, public gk::Transformable {