// Copyright (c) 2022 Dominic Masters // // This software is released under the MIT License. // https://opensource.org/licenses/MIT #include "UIComponent.hpp" 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() { 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(); } 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]) ); // Update children auto it = this->children.begin(); while(it != this->children.end()) { (*it)->updatePositions(); ++it; } // Fire event eventAlignmentUpdated.invoke(this); } float_t UIComponent::getWidth() { return this->width; } float_t UIComponent::getHeight() { return this->height; } float_t UIComponent::getContentWidth() { return this->width; } float_t UIComponent::getContentHeight() { return this->height; } float_t UIComponent::getRelativeX() { return this->relativeX; } float_t UIComponent::getRelativeY() { return this->relativeY; } DawnGame * UIComponent::getGame() { return this->canvas->getGame(); } Scene * UIComponent::getScene() { return this->canvas->getScene(); } void UIComponent::setTransform( UIComponentAlign xAlign, UIComponentAlign yAlign, glm::vec4 alignment, float_t z ) { this->alignX = xAlign; this->alignY = yAlign; this->alignment = alignment; this->z = z; this->updatePositions(); } std::vector UIComponent::getPassItems( glm::mat4 projection, glm::mat4 view, glm::mat4 parent ) { // Calculate self transform matrix glm::mat4 selfTransform = parent * glm::translate( glm::mat4(1.0f), glm::vec3(this->relativeX, this->relativeY, this->z) ); // Draw Self auto items = this->getSelfPassItems(projection, view, selfTransform); // Render children auto it = this->children.begin(); while(it != this->children.end()) { vectorAppend(&items, (*it)->getPassItems(projection, view, selfTransform)); ++it; } return items; } void UIComponent::addChild(UIComponent *child) { if(child->parent == this) return; if(child->parent != nullptr) child->parent->removeChild(child); this->children.push_back(child); child->parent = this; this->updatePositions(); } void UIComponent::removeChild(UIComponent *child) { assertTrue(child->parent == this); auto it = this->children.begin(); while(it != this->children.end()) { if(*it == child) { this->children.erase(it); break; } ++it; } child->parent = nullptr; } UIComponent::~UIComponent() { }