Added UI Grid
This commit is contained in:
		| @@ -11,5 +11,5 @@ target_sources(${DAWN_TARGET_NAME} | ||||
|     UILabel.cpp | ||||
|     UISprite.cpp | ||||
|     UIEmpty.cpp | ||||
|     # UIGrid.cpp | ||||
|     UIGrid.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<float_t>(this->relativeX); | ||||
|   this->relativeY = mathRound<float_t>(this->relativeY); | ||||
|   this->width = mathRound<float_t>(this->width); | ||||
|   this->height = mathRound<float_t>(this->height); | ||||
| //   this->relativeX = mathRound<float_t>(this->relativeX); | ||||
| //   this->relativeY = mathRound<float_t>(this->relativeY); | ||||
| //   this->width = mathRound<float_t>(this->width); | ||||
| //   this->height = mathRound<float_t>(this->height); | ||||
|  | ||||
|   // Update children | ||||
|   auto it = this->children.begin(); | ||||
|   | ||||
| @@ -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; | ||||
|   }; | ||||
| } | ||||
| @@ -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<struct ShaderPassItem> UIGrid::getSelfPassItems( | ||||
|   glm::mat4 projection, | ||||
|   glm::mat4 view, | ||||
|   glm::mat4 transform | ||||
| ) { | ||||
|   return std::vector<struct ShaderPassItem>(); | ||||
| } | ||||
|  | ||||
| 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(); | ||||
| } | ||||
| @@ -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<struct GridArea> gridArea; | ||||
|       float_t gutterX = 0; | ||||
|       float_t gutterY = 0; | ||||
|       float_t sizeRow, sizeCol; | ||||
|       std::map<UIComponent*, struct UIGridPosition> 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<struct ShaderPassItem> 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; | ||||
|   }; | ||||
| } | ||||
| @@ -32,7 +32,7 @@ void TestUIScene::stage() { | ||||
|   this->canvas = UICanvas::create(this); | ||||
|  | ||||
|   // auto text = man->get<TextureAsset>("texture_test"); | ||||
|   // auto border = this->canvas->addElement<UIBorder>(); | ||||
|   // auto border = this->canvas->addElement<UIBorder>();   | ||||
|   // border->texture = &text->texture; | ||||
|   // border->setBorderSize(glm::vec2(4, 4)); | ||||
|   // border->setTransform( | ||||
| @@ -42,13 +42,19 @@ void TestUIScene::stage() { | ||||
|   // ); | ||||
|  | ||||
|   auto assetFont = man->get<TrueTypeAsset>("truetype_alice"); | ||||
|   auto label = this->canvas->addElement<UILabel>(); | ||||
|   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<UIGrid>(); | ||||
|   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<UILabel>(); | ||||
|       label->setFont(&assetFont->font); | ||||
|       label->setText("test.1"); | ||||
|       label->setFontSize(24); | ||||
|  | ||||
|       grid->addToGrid(label, x, y); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -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 { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user