From 277c9719bbfb28de722516e5410ab5f88cf8ee3f Mon Sep 17 00:00:00 2001 From: Vsevolod Kremianskii Date: Sat, 27 Feb 2021 11:26:30 +0700 Subject: [PATCH] feat: Implement rendering of scroll bar thumb --- src/gui/control/listbox.cpp | 7 ++- src/gui/control/scrollbar.cpp | 84 ++++++++++++++++++++++++++++++----- src/gui/control/scrollbar.h | 26 ++++++++--- src/render/meshes.cpp | 4 +- 4 files changed, 99 insertions(+), 22 deletions(-) diff --git a/src/gui/control/listbox.cpp b/src/gui/control/listbox.cpp index 5dc73358..b969882d 100644 --- a/src/gui/control/listbox.cpp +++ b/src/gui/control/listbox.cpp @@ -214,9 +214,12 @@ void ListBox::render(const glm::ivec2 &offset, const vector &text) { } if (_scrollBar) { + ScrollBar::ScrollState state; + state.count = static_cast(_items.size()); + state.numVisible = this->_slotCount; + state.offset = _itemOffset; auto &scrollBar = static_cast(*_scrollBar); - scrollBar.setCanScrollUp(_itemOffset > 0); - scrollBar.setCanScrollDown(_items.size() - _itemOffset > _slotCount); + scrollBar.setScrollState(move(state)); scrollBar.render(offset, vector()); } } diff --git a/src/gui/control/scrollbar.cpp b/src/gui/control/scrollbar.cpp index a35da7a5..f2e707c6 100644 --- a/src/gui/control/scrollbar.cpp +++ b/src/gui/control/scrollbar.cpp @@ -42,21 +42,87 @@ void ScrollBar::load(const GffStruct &gffs) { shared_ptr dir(gffs.getStruct("DIR")); if (dir) { string image(dir->getString("IMAGE")); - _dir.image = Textures::instance().get(image, TextureUsage::Diffuse); + _dir.image = Textures::instance().get(image, TextureUsage::GUI); + } + + shared_ptr thumb(gffs.getStruct("THUMB")); + if (thumb) { + string image(thumb->getString("IMAGE")); + _thumb.image = Textures::instance().get(image, TextureUsage::GUI); } } void ScrollBar::render(const glm::ivec2 &offset, const vector &text) { + drawThumb(offset); + drawArrows(offset); +} + +void ScrollBar::drawThumb(const glm::ivec2 &offset) { + if (!_thumb.image || _state.numVisible >= _state.count) return; + + setActiveTextureUnit(TextureUnits::diffuse); + _thumb.image->bind(); + + ShaderUniforms uniforms; + uniforms.general.projection = RenderWindow::instance().getOrthoProjection(); + + // Top edge + uniforms.general.model = glm::translate(glm::mat4(1.0f), glm::vec3(_extent.left + offset.x, _extent.top + _extent.width + offset.y, 0.0f)); + uniforms.general.model = glm::scale(uniforms.general.model, glm::vec3(_extent.width, 1.0f, 1.0f)); + Shaders::instance().activate(ShaderProgram::SimpleGUI, uniforms); + Meshes::instance().getQuad()->render(); + + // Left edge + uniforms.general.model = glm::translate(glm::mat4(1.0f), glm::vec3(_extent.left + offset.x, _extent.top + _extent.width + offset.y, 0.0f)); + uniforms.general.model = glm::scale(uniforms.general.model, glm::vec3(1.0f, _extent.height - 2.0f * _extent.width, 1.0f)); + Shaders::instance().activate(ShaderProgram::SimpleGUI, uniforms); + Meshes::instance().getQuad()->render(); + + // Right edge + uniforms.general.model = glm::translate(glm::mat4(1.0f), glm::vec3(_extent.left + _extent.width - 1.0f + offset.x, _extent.top + _extent.width + offset.y, 0.0f)); + uniforms.general.model = glm::scale(uniforms.general.model, glm::vec3(1.0f, _extent.height - 2.0f * _extent.width, 1.0f)); + Shaders::instance().activate(ShaderProgram::SimpleGUI, uniforms); + Meshes::instance().getQuad()->render(); + + // Bottom edge + uniforms.general.model = glm::translate(glm::mat4(1.0f), glm::vec3(_extent.left + offset.x, _extent.top + _extent.height - _extent.width - 1.0f + offset.y, 0.0f)); + uniforms.general.model = glm::scale(uniforms.general.model, glm::vec3(_extent.width, 1.0f, 1.0f)); + Shaders::instance().activate(ShaderProgram::SimpleGUI, uniforms); + Meshes::instance().getQuad()->render(); + + // Thumb + + float frameHeight = _extent.height - 2.0f * _extent.width - 4.0f; + float thumbHeight = frameHeight * _state.numVisible / static_cast(_state.count); + float y = glm::mix(0.0f, frameHeight - thumbHeight, _state.offset / static_cast(_state.count - _state.numVisible)); + + uniforms.general.model = glm::translate(glm::mat4(1.0f), glm::vec3(_extent.left + 2.0f + offset.x, _extent.top + _extent.width + 2.0f + offset.y + y, 0.0f)); + uniforms.general.model = glm::scale(uniforms.general.model, glm::vec3(_extent.width - 4.0f, thumbHeight, 1.0f)); + Shaders::instance().activate(ShaderProgram::SimpleGUI, uniforms); + Meshes::instance().getQuad()->render(); + + // END Thumb +} + +void ScrollBar::drawArrows(const glm::ivec2 &offset) { if (!_dir.image) return; + bool canScrollUp = _state.offset > 0; + bool canScrollDown = _state.count - _state.offset > _state.numVisible; + if (!canScrollUp && !canScrollDown) return; + setActiveTextureUnit(TextureUnits::diffuse); _dir.image->bind(); - if (_canScrollUp) drawUpArrow(offset); - if (_canScrollDown) drawDownArrow(offset); + if (canScrollUp) { + drawUpArrow(offset); + } + if (canScrollDown) { + drawDownArrow(offset); + } } -void ScrollBar::drawUpArrow(const glm::vec2 &offset) { +void ScrollBar::drawUpArrow(const glm::ivec2 &offset) { glm::mat4 transform(1.0f); transform = glm::translate(transform, glm::vec3(_extent.left + offset.x, _extent.top + offset.y, 0.0f)); transform = glm::scale(transform, glm::vec3(_extent.width, _extent.width, 1.0f)); @@ -69,7 +135,7 @@ void ScrollBar::drawUpArrow(const glm::vec2 &offset) { Meshes::instance().getQuad()->render(); } -void ScrollBar::drawDownArrow(const glm::vec2 &offset) { +void ScrollBar::drawDownArrow(const glm::ivec2 &offset) { glm::mat4 transform(1.0f); transform = glm::translate(transform, glm::vec3(_extent.left + offset.x, _extent.top + _extent.height + offset.y, 0.0f)); transform = glm::scale(transform, glm::vec3(_extent.width, _extent.width, 1.0f)); @@ -83,12 +149,8 @@ void ScrollBar::drawDownArrow(const glm::vec2 &offset) { Meshes::instance().getQuad()->render(); } -void ScrollBar::setCanScrollUp(bool scroll) { - _canScrollUp = scroll; -} - -void ScrollBar::setCanScrollDown(bool scroll) { - _canScrollDown = scroll; +void ScrollBar::setScrollState(ScrollState state) { + _state = move(state); } } // namespace gui diff --git a/src/gui/control/scrollbar.h b/src/gui/control/scrollbar.h index 51aa96aa..29e515d2 100644 --- a/src/gui/control/scrollbar.h +++ b/src/gui/control/scrollbar.h @@ -25,25 +25,37 @@ namespace gui { class ScrollBar : public Control { public: + struct ScrollState { + int count { 0 }; /**< total number of list items */ + int numVisible { 0 }; /**< number of visible list items */ + int offset { 0 }; /**< offset into the list of items */ + }; + ScrollBar(GUI *gui); void load(const resource::GffStruct &gffs) override; void render(const glm::ivec2 &offset, const std::vector &text) override; - void setCanScrollUp(bool scroll); - void setCanScrollDown(bool scroll); + void setScrollState(ScrollState state); private: struct Direction { std::shared_ptr image; }; - Direction _dir; - bool _canScrollUp { false }; - bool _canScrollDown { false }; + struct Thumb { + std::shared_ptr image; + }; - void drawUpArrow(const glm::vec2 &offset); - void drawDownArrow(const glm::vec2 &offset); + Direction _dir; + Thumb _thumb; + ScrollState _state; + + void drawThumb(const glm::ivec2 &offset); + void drawArrows(const glm::ivec2 &offset); + + void drawUpArrow(const glm::ivec2 &offset); + void drawDownArrow(const glm::ivec2 &offset); }; } // namespace gui diff --git a/src/render/meshes.cpp b/src/render/meshes.cpp index ecb81a93..ed082e2a 100644 --- a/src/render/meshes.cpp +++ b/src/render/meshes.cpp @@ -26,7 +26,7 @@ namespace reone { namespace render { -// Quads +// Quad static const vector g_quadVertices { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, @@ -67,7 +67,7 @@ static const vector g_quadIndices = { 0, 1, 2, 2, 3, 0 }; static const Mesh::VertexOffsets g_quadOffsets = { 0, -1, 3 * sizeof(float), -1, -1, -1, -1, -1, 5 * sizeof(float) }; -// END Quads +// END Quad // Cube