From 5c45ca8998b29fa06d940b164fbb08a77c3f8287 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Tue, 24 Jan 2023 21:06:51 -0800 Subject: [PATCH] Added UI Grid --- assets/games/pokergame/locale/en.csv | 6 +- src/dawn/ui/CMakeLists.txt | 2 +- src/dawn/ui/UIComponent.cpp | 129 ++++++++++++----------- src/dawn/ui/UIComponent.hpp | 27 ++++- src/dawn/ui/UIGrid.cpp | 109 +++++++++++++++---- src/dawn/ui/UIGrid.hpp | 73 +++++++++---- src/dawnpokergame/scenes/TestUIScene.cpp | 26 +++-- src/dawnpokergame/scenes/TestUIScene.hpp | 2 + 8 files changed, 255 insertions(+), 119 deletions(-) diff --git a/assets/games/pokergame/locale/en.csv b/assets/games/pokergame/locale/en.csv index 4056a2a0..bbdeb68c 100644 --- a/assets/games/pokergame/locale/en.csv +++ b/assets/games/pokergame/locale/en.csv @@ -29,8 +29,4 @@ scene.22.1,"King Fight" scene.23.1,"Post King Fight, angry he leaves, town rallies around you" scene.24.1,"Go to one of the kingsmen who's working with the big bad, he's worried that the townspeople know more than they let on." unknown3,"Something here has to bring the big bad to town." -test.1,"Test 1 -Test 2 -Test 3 -Test 4 -" \ No newline at end of file +test.1,"Test" \ No newline at end of file diff --git a/src/dawn/ui/CMakeLists.txt b/src/dawn/ui/CMakeLists.txt index 017d8056..3ae4ab2d 100644 --- a/src/dawn/ui/CMakeLists.txt +++ b/src/dawn/ui/CMakeLists.txt @@ -11,5 +11,5 @@ target_sources(${DAWN_TARGET_NAME} UILabel.cpp UISprite.cpp UIEmpty.cpp - # UIGrid.cpp + UIGrid.cpp ) \ No newline at end of file diff --git a/src/dawn/ui/UIComponent.cpp b/src/dawn/ui/UIComponent.cpp index 5a07dea4..018d3607 100644 --- a/src/dawn/ui/UIComponent.cpp +++ b/src/dawn/ui/UIComponent.cpp @@ -7,78 +7,81 @@ using namespace Dawn; +void UIComponent::calculateDimensions( + enum UIComponentAlign align, + float_t *position, + float_t *size, + float_t outerSize, + float_t innerSize, + glm::vec2 alignment +) { + assertNotNull(position); + assertNotNull(size); + + switch(align) { + case UI_COMPONENT_ALIGN_STRETCH: + *position = alignment[0]; + *size = outerSize + (alignment[0] + alignment[1]); + break; + + case UI_COMPONENT_ALIGN_START: + *position = alignment[0]; + *size = alignment[1]; + break; + + case UI_COMPONENT_ALIGN_MIDDLE: + *size = innerSize; + *position = (outerSize / 2.0f) - (innerSize / 2.0f) + alignment[0]; + break; + + case UI_COMPONENT_ALIGN_END: + *size = alignment[0]; + *position = outerSize - innerSize - alignment[1]; + break; + + default: + assertUnreachable(); + break; + } +} + UIComponent::UIComponent(UICanvas *canvas) { assertNotNull(canvas); this->canvas = canvas; } void UIComponent::updatePositions() { - // X Alignment - if(this->alignX == UI_COMPONENT_ALIGN_STRETCH) { - if(this->parent == nullptr) { - this->width = this->canvas->getWidth(); - } else { - this->width = this->parent->getWidth(); - } - this->relativeX = this->alignment[0]; - this->width -= (this->alignment[0] + this->alignment[2]); - } else if(this->alignX == UI_COMPONENT_ALIGN_START) { - this->relativeX = this->alignment[0]; - this->width = this->alignment[2]; - } else if(this->alignX == UI_COMPONENT_ALIGN_END) { - this->width = this->alignment[0]; - if(this->parent == nullptr) { - this->relativeX = this->canvas->getWidth(); - } else { - this->relativeX = this->parent->getWidth(); - } - this->relativeX -= this->width; - this->relativeX -= this->alignment[2]; - } else if(this->alignX == UI_COMPONENT_ALIGN_MIDDLE) { - this->width = this->alignment[2]; - if(this->parent == nullptr) { - this->relativeX = this->canvas->getWidth(); - } else { - this->relativeX = this->parent->getWidth(); - } - this->relativeX = (this->relativeX / 2.0f) - (this->width / 2.0f) + this->alignment[0]; + float_t outerWidth, outerHeight; + + if(this->parent == nullptr) { + outerWidth = this->canvas->getWidth(); + outerHeight = this->canvas->getHeight(); + } else { + outerWidth = this->parent->getWidth(); + outerHeight = this->parent->getHeight(); } - // Y Alignment - if(this->alignY == UI_COMPONENT_ALIGN_STRETCH) { - if(this->parent == nullptr) { - this->height = this->canvas->getHeight(); - } else { - this->height = this->parent->getHeight(); - } - this->relativeY = this->alignment[1]; - this->height -= (this->alignment[1] + this->alignment[3]); - } else if(this->alignY == UI_COMPONENT_ALIGN_START) { - this->relativeY = this->alignment[1]; - this->height = this->alignment[3]; - } else if(this->alignY == UI_COMPONENT_ALIGN_END) { - this->height = this->alignment[1]; - if(this->parent == nullptr) { - this->relativeY = this->canvas->getHeight(); - } else { - this->relativeY = this->parent->getHeight(); - } - this->relativeY -= this->height; - this->relativeY -= this->alignment[3]; - } else if(this->alignY == UI_COMPONENT_ALIGN_MIDDLE) { - this->height = this->alignment[3]; - if(this->parent == nullptr) { - this->relativeY = this->canvas->getHeight(); - } else { - this->relativeY = this->parent->getHeight(); - } - this->relativeY = (this->relativeY / 2.0f) - (this->height / 2.0f) + this->alignment[1]; - } + UIComponent::calculateDimensions( + this->alignX, + &this->relativeX, + &this->width, + outerWidth, + this->getContentWidth(), + glm::vec2(this->alignment[0], this->alignment[2]) + ); + UIComponent::calculateDimensions( + this->alignY, + &this->relativeY, + &this->height, + outerHeight, + this->getContentHeight(), + glm::vec2(this->alignment[1], this->alignment[3]) + ); - this->relativeX = mathRound(this->relativeX); - this->relativeY = mathRound(this->relativeY); - this->width = mathRound(this->width); - this->height = mathRound(this->height); +// this->relativeX = mathRound(this->relativeX); +// this->relativeY = mathRound(this->relativeY); +// this->width = mathRound(this->width); +// this->height = mathRound(this->height); // Update children auto it = this->children.begin(); diff --git a/src/dawn/ui/UIComponent.hpp b/src/dawn/ui/UIComponent.hpp index ae25dc35..ff070dd2 100644 --- a/src/dawn/ui/UIComponent.hpp +++ b/src/dawn/ui/UIComponent.hpp @@ -18,6 +18,8 @@ namespace Dawn { UI_COMPONENT_ALIGN_END, UI_COMPONENT_ALIGN_STRETCH }; + + class UIGrid; class UIComponent { protected: @@ -67,6 +69,25 @@ namespace Dawn { ) = 0; public: + /** + * Method used to calculate alignment dimensions. + * + * @param align Alignment value enumator. + * @param position Output position floating point. + * @param size Output size floating point. + * @param outerSize Outer size (of the parent). + * @param innerSize Inner size (of this element's content). + * @param alignment Alignment settings. + */ + static void calculateDimensions( + enum UIComponentAlign align, + float_t *position, + float_t *size, + float_t outerSize, + float_t innerSize, + glm::vec2 alignment + ); + UICanvas *canvas; UIComponent(UICanvas *canvas); @@ -165,16 +186,18 @@ namespace Dawn { * * @param child Child UI Component to add. */ - void addChild(UIComponent *child); + virtual void addChild(UIComponent *child); /** * Removes a child from this UI Component. * * @param child Child to remove. */ - void removeChild(UIComponent *child); + virtual void removeChild(UIComponent *child); virtual ~UIComponent(); + friend class UICanvas; + friend class UIGrid; }; } \ No newline at end of file diff --git a/src/dawn/ui/UIGrid.cpp b/src/dawn/ui/UIGrid.cpp index 0451eae7..164a75b4 100644 --- a/src/dawn/ui/UIGrid.cpp +++ b/src/dawn/ui/UIGrid.cpp @@ -8,28 +8,101 @@ using namespace Dawn; UIGrid::UIGrid(UICanvas *canvas) : UIComponent(canvas) { + } -void UIGrid::setSize(int32_t rows, int32_t columns) { - this->gridArea.clear(); - - this->rows = rows; - this->columns = columns; +void UIGrid::updatePositions() { + UIComponent::updatePositions(); - int32_t i, l; - l = rows * columns; - for(i = 0; i < l; i++) { - struct GridArea area; - area.uiComponent = nullptr; - this->gridArea.push_back(area); + this->sizeCol = ( + this->width - (this->gutterX * (this->columns - 1)) + ) / this->columns; + this->sizeRow = ( + this->height - (this->gutterY * (this->rows - 1)) + ) / this->rows; + + auto it = this->gridChildren.begin(); + while(it != this->gridChildren.end()) { + this->alignChild(it->first, it->second); + ++it; } } -void UIGrid::setItem(int32_t x, int32_t y, UIComponent *comp) { - auto item = &this->gridArea[(y * this->rows) + x]; - - //Too lazy to support re setting. Need to mod setSize too - assertNull(item->uiComponent); - - item->uiComponent = comp; +std::vector UIGrid::getSelfPassItems( + glm::mat4 projection, + glm::mat4 view, + glm::mat4 transform +) { + return std::vector(); } + +void UIGrid::alignChild(UIComponent *child, struct UIGridPosition pos) { + float_t gridX = (this->sizeCol * pos.x) + (this->gutterX * pos.x); + float_t gridY = (this->sizeRow * pos.y) + (this->gutterY * pos.y); + + // Hack for when content width is undefined. + child->width = this->sizeCol; + child->height = this->sizeRow; + + // Alignment + float_t x, y, sizeX, sizeY; + UIComponent::calculateDimensions( + UI_COMPONENT_ALIGN_MIDDLE, + &x, + &sizeX, + this->sizeCol, + child->getContentWidth(), + glm::vec2(0, 0) + ); + UIComponent::calculateDimensions( + UI_COMPONENT_ALIGN_MIDDLE, + &y, + &sizeY, + this->sizeRow, + child->getContentHeight(), + glm::vec2(0, 0) + ); + + child->setTransform( + UI_COMPONENT_ALIGN_START, UI_COMPONENT_ALIGN_START, + glm::vec4(gridX + x, gridY + y, sizeX, sizeY), + 0.0f + ); +} + +void UIGrid::setGridSize( + int32_t columns, int32_t rows, + float_t gutterX, float_t gutterY +) { + this->rows = rows; + this->columns = columns; + this->gutterX = gutterX; + this->gutterY = gutterY; + + this->gridChildren.clear(); + this->updatePositions(); +} + +void UIGrid::addToGrid(UIComponent *ui, int32_t x, int32_t y) { + assertTrue(x >= 0 && x < this->columns); + assertTrue(y >= 0 && y < this->rows); + this->addChild(ui); + struct UIGridPosition pos; + pos.x = x; + pos.y = y; + this->gridChildren[ui] = pos; + this->alignChild(ui, pos); +} + +int32_t UIGrid::getRows() { + return this->rows; +} + +int32_t UIGrid::getColumns() { + return this->columns; +} + +void UIGrid::removeChild(UIComponent *component) { + UIComponent::removeChild(component); + assertUnreachable(); +} \ No newline at end of file diff --git a/src/dawn/ui/UIGrid.hpp b/src/dawn/ui/UIGrid.hpp index d596f585..b02deaf4 100644 --- a/src/dawn/ui/UIGrid.hpp +++ b/src/dawn/ui/UIGrid.hpp @@ -5,37 +5,70 @@ #pragma once #include "UIComponent.hpp" +#include "util/mathutils.hpp" namespace Dawn { - enum GridAlign { - ALIGN_GROW, - ALIGN_CONTENT, - ALIGN_FIXED + struct UIGridPosition { + int32_t x; + int32_t y; + UIComponentAlign alignX; + UIComponentAlign alignY; }; - struct GridArea { - enum GridAlignment xAlign; - enum GridAlignment yAlign; - float_t width, height; - float_t x, y; - UIComponent *uiComponent; - }; class UIGrid : public UIComponent { - protected: - void alignChildren(); - - public: - glm::vec2 cellPadding; - glm::vec2 cellMargin; + private: int32_t rows = 1; int32_t columns = 1; - std::vector gridArea; + float_t gutterX = 0; + float_t gutterY = 0; + float_t sizeRow, sizeCol; + std::map gridChildren; + /** + * Internal method to update the alignment of a child. + * + * @param child Child UI component. + * @param pos Positional information of the child UI item.. + */ + void alignChild(UIComponent *child, struct UIGridPosition pos); + + protected: + void updatePositions() override; + std::vector getSelfPassItems( + glm::mat4 projection, + glm::mat4 view, + glm::mat4 transform + ) override; + + public: UIGrid(UICanvas *canvas); - void setSize(int32_t rows, int32_t columns); + /** + * Sets the dimensions of the grid. + * + * @param columns Count of columns in the grid. + * @param rows Count of rows in the grid. + * @param gutterX Gutter spacing between the cells of the grid. + * @param gutterY Gutter spacing between the cells of the grid. + */ + void setGridSize( + int32_t columns, int32_t rows, + float_t gutterX, float_t gutterY + ); - void setItem(int32_t row, int32_t col, UIComponent *comp); + /** + * Adds a UI component to the grid. + * + * @param component Component to add to the grid. + * @param column Column Position. + * @param row Row Position. + */ + void addToGrid(UIComponent *component, int32_t column, int32_t row); + + int32_t getRows(); + int32_t getColumns(); + + void removeChild(UIComponent *component) override; }; } \ No newline at end of file diff --git a/src/dawnpokergame/scenes/TestUIScene.cpp b/src/dawnpokergame/scenes/TestUIScene.cpp index 7c7060e3..1a5bf486 100644 --- a/src/dawnpokergame/scenes/TestUIScene.cpp +++ b/src/dawnpokergame/scenes/TestUIScene.cpp @@ -32,7 +32,7 @@ void TestUIScene::stage() { this->canvas = UICanvas::create(this); // auto text = man->get("texture_test"); - // auto border = this->canvas->addElement(); + // auto border = this->canvas->addElement(); // border->texture = &text->texture; // border->setBorderSize(glm::vec2(4, 4)); // border->setTransform( @@ -42,13 +42,19 @@ void TestUIScene::stage() { // ); auto assetFont = man->get("truetype_alice"); - auto label = this->canvas->addElement(); - label->setFont(&assetFont->font); - label->setText("test.1"); - label->setFontSize(24); - label->setTransform( - UI_COMPONENT_ALIGN_STRETCH, UI_COMPONENT_ALIGN_STRETCH, - glm::vec4(0, 0, 0, 0), - 0.0f - ); + + auto grid = this->canvas->addElement(); + grid->setTransform(UI_COMPONENT_ALIGN_STRETCH, UI_COMPONENT_ALIGN_STRETCH, glm::vec4(0, 0, 0, 0), 0); + grid->setGridSize(4, 4, 8, 8); + + for(int32_t x = 0; x < grid->getColumns(); x++) { + for(int32_t y = 0; y < grid->getRows(); y++) { + auto label = this->canvas->addElement(); + label->setFont(&assetFont->font); + label->setText("test.1"); + label->setFontSize(24); + + grid->addToGrid(label, x, y); + } + } } \ No newline at end of file diff --git a/src/dawnpokergame/scenes/TestUIScene.hpp b/src/dawnpokergame/scenes/TestUIScene.hpp index 8440f4ce..ad76acc6 100644 --- a/src/dawnpokergame/scenes/TestUIScene.hpp +++ b/src/dawnpokergame/scenes/TestUIScene.hpp @@ -9,6 +9,8 @@ #include "scene/components/ui/UICanvas.hpp" #include "ui/UILabel.hpp" #include "ui/UIBorder.hpp" +#include "ui/UIGrid.hpp" +#include "ui/UISprite.hpp" #include "prefabs/SimpleSpinningCubePrefab.hpp" namespace Dawn {