Broken auto sizing
This commit is contained in:
@ -6,11 +6,11 @@
|
||||
target_sources(${DAWN_TARGET_NAME}
|
||||
PRIVATE
|
||||
UIAlignableElement.cpp
|
||||
UISubAlignableElement.cpp
|
||||
UIElement.cpp
|
||||
UIRectangle.cpp
|
||||
UILabel.cpp
|
||||
UIMenu.cpp
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(container)
|
||||
add_subdirectory(container)
|
||||
add_subdirectory(elements)
|
@ -26,8 +26,11 @@ void UIAlignableElement::updateSelfAlignment(
|
||||
const enum UIAlignmentUnit unit,
|
||||
const float_t alignment,
|
||||
const float_t parentSize,
|
||||
const float_t ratioSize
|
||||
const float_t ratioSize,
|
||||
const float_t selfSize
|
||||
) {
|
||||
if(alignment == UI_ALIGN_AUTO) return selfSize;
|
||||
|
||||
switch(unit) {
|
||||
case UIAlignmentUnit::PIXEL:
|
||||
return alignment;
|
||||
@ -55,67 +58,76 @@ void UIAlignableElement::updateSelfAlignment(
|
||||
const float_t alignment1,
|
||||
const float_t parentSize,
|
||||
const float_t ratioSize,
|
||||
float_t &selfPosition,
|
||||
float_t &selfSize
|
||||
const float_t selfSize,
|
||||
float_t &outPosition,
|
||||
float_t &outSize
|
||||
) {
|
||||
switch(type) {
|
||||
case UIAlignmentType::START:
|
||||
selfPosition = valueAxis(
|
||||
outPosition = valueAxis(
|
||||
unit0,
|
||||
alignment0,
|
||||
parentSize,
|
||||
ratioSize
|
||||
ratioSize,
|
||||
selfSize
|
||||
);
|
||||
selfSize = valueAxis(
|
||||
outSize = valueAxis(
|
||||
unit1,
|
||||
alignment1,
|
||||
parentSize,
|
||||
ratioSize
|
||||
ratioSize,
|
||||
selfSize
|
||||
);
|
||||
break;
|
||||
|
||||
case UIAlignmentType::MIDDLE:
|
||||
selfSize = valueAxis(
|
||||
outSize = valueAxis(
|
||||
unit1,
|
||||
alignment1,
|
||||
parentSize,
|
||||
ratioSize
|
||||
ratioSize,
|
||||
selfSize
|
||||
);
|
||||
selfPosition = (parentSize / 2.0f) - (selfSize / 2.0f) + valueAxis(
|
||||
outPosition = (parentSize / 2.0f) - (selfSize / 2.0f) + valueAxis(
|
||||
unit0,
|
||||
alignment0,
|
||||
parentSize,
|
||||
ratioSize
|
||||
ratioSize,
|
||||
selfSize
|
||||
);
|
||||
break;
|
||||
|
||||
case UIAlignmentType::END:
|
||||
selfSize = valueAxis(
|
||||
outSize = valueAxis(
|
||||
unit0,
|
||||
alignment0,
|
||||
parentSize,
|
||||
ratioSize
|
||||
ratioSize,
|
||||
selfSize
|
||||
);
|
||||
selfPosition = parentSize - selfSize - valueAxis(
|
||||
outPosition = parentSize - outSize - valueAxis(
|
||||
unit1,
|
||||
alignment1,
|
||||
parentSize,
|
||||
ratioSize
|
||||
ratioSize,
|
||||
selfSize
|
||||
);
|
||||
break;
|
||||
|
||||
case UIAlignmentType::STRETCH:
|
||||
selfPosition = valueAxis(
|
||||
outPosition = valueAxis(
|
||||
unit0,
|
||||
alignment0,
|
||||
parentSize,
|
||||
ratioSize
|
||||
ratioSize,
|
||||
selfSize
|
||||
);
|
||||
selfSize = parentSize - (selfPosition + valueAxis(
|
||||
outSize = parentSize - (outPosition + valueAxis(
|
||||
unit1,
|
||||
alignment1,
|
||||
parentSize,
|
||||
ratioSize
|
||||
ratioSize,
|
||||
selfSize
|
||||
));
|
||||
break;
|
||||
|
||||
@ -140,6 +152,7 @@ void UIAlignableElement::updateSelfAlignment(
|
||||
align[3],
|
||||
pSize.y,
|
||||
0,
|
||||
this->getSelfHeight(),
|
||||
position.y,
|
||||
size.y
|
||||
);
|
||||
@ -151,6 +164,7 @@ void UIAlignableElement::updateSelfAlignment(
|
||||
align[2],
|
||||
pSize.x,
|
||||
size.y,
|
||||
this->getSelfWidth(),
|
||||
position.x,
|
||||
size.x
|
||||
);
|
||||
@ -163,6 +177,7 @@ void UIAlignableElement::updateSelfAlignment(
|
||||
align[2],
|
||||
pSize.x,
|
||||
0,
|
||||
this->getSelfWidth(),
|
||||
position.x,
|
||||
size.x
|
||||
);
|
||||
@ -174,6 +189,7 @@ void UIAlignableElement::updateSelfAlignment(
|
||||
align[3],
|
||||
pSize.y,
|
||||
size.x,
|
||||
this->getSelfHeight(),
|
||||
position.y,
|
||||
size.y
|
||||
);
|
||||
@ -183,6 +199,14 @@ void UIAlignableElement::updateSelfAlignment(
|
||||
this->eventAlignmentUpdated(position, size);
|
||||
}
|
||||
|
||||
float_t UIAlignableElement::getSelfWidth() {
|
||||
return size.x;
|
||||
}
|
||||
|
||||
float_t UIAlignableElement::getSelfHeight() {
|
||||
return size.y;
|
||||
}
|
||||
|
||||
void UIAlignableElement::updateAlignment(
|
||||
const glm::vec2 pPos,
|
||||
const glm::vec2 pSize,
|
||||
|
@ -6,6 +6,8 @@
|
||||
#pragma once
|
||||
#include "ui/UIElement.hpp"
|
||||
|
||||
#define UI_ALIGN_AUTO -1
|
||||
|
||||
namespace Dawn {
|
||||
enum class UIAlignmentType {
|
||||
START,
|
||||
@ -41,9 +43,9 @@ namespace Dawn {
|
||||
|
||||
public:
|
||||
// Primary alignment controls
|
||||
glm::vec4 align = glm::vec4(0, 0, 0, 0);
|
||||
enum UIAlignmentType alignX = UIAlignmentType::STRETCH;
|
||||
enum UIAlignmentType alignY = UIAlignmentType::STRETCH;
|
||||
glm::vec4 align = glm::vec4(0, 0, UI_ALIGN_AUTO, UI_ALIGN_AUTO);
|
||||
enum UIAlignmentType alignX = UIAlignmentType::START;
|
||||
enum UIAlignmentType alignY = UIAlignmentType::START;
|
||||
enum UIAlignmentUnit alignUnit[4];
|
||||
|
||||
std::function<
|
||||
@ -55,6 +57,8 @@ namespace Dawn {
|
||||
*/
|
||||
UIAlignableElement();
|
||||
|
||||
float_t getSelfWidth() override;
|
||||
float_t getSelfHeight() override;
|
||||
void updateAlignment(
|
||||
const glm::vec2 parentPosition,
|
||||
const glm::vec2 parentSize,
|
||||
|
@ -16,6 +16,22 @@ void UIElement::getSelfQuads(UICanvas &ctx) {
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
float_t UIElement::getSelfWidth() {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float_t UIElement::getSelfHeight() {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float_t UIElement::getWidth() {
|
||||
return this->getSelfWidth();
|
||||
}
|
||||
|
||||
float_t UIElement::getHeight() {
|
||||
return this->getSelfHeight();
|
||||
}
|
||||
|
||||
void UIElement::getQuads(UICanvas &ctx) {
|
||||
this->getSelfQuads(ctx);
|
||||
|
||||
|
@ -20,6 +20,36 @@ namespace Dawn {
|
||||
virtual void getSelfQuads(UICanvas &ctx);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Overrided method by the UI Element that requests the minimum
|
||||
* width of the content.
|
||||
*
|
||||
* @return The minimum width of the content.
|
||||
*/
|
||||
virtual float_t getContentWidth();
|
||||
|
||||
/**
|
||||
* Overrided method by the UI Element that requests the minimum
|
||||
* height of the content.
|
||||
*
|
||||
* @return The minimum height of the content.
|
||||
*/
|
||||
virtual float_t getContentHeight();
|
||||
|
||||
/**
|
||||
* Returns the width of this component.
|
||||
*
|
||||
* @return The width of this component.
|
||||
*/
|
||||
virtual float_t getWidth();
|
||||
|
||||
/**
|
||||
* Returns the height of this component.
|
||||
*
|
||||
* @return The height of this component.
|
||||
*/
|
||||
virtual float_t getHeight();
|
||||
|
||||
/**
|
||||
* Virtual method overridden by the UIElement to get the children of
|
||||
* this component.
|
||||
|
@ -7,10 +7,6 @@
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::shared_ptr<UIElement>> UIMenu::getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
void UIMenu::setPosition(int32_t x, int32_t y) {
|
||||
assertTrue(x >= 0, "X position must be greater than or equal to 0.");
|
||||
assertTrue(y >= 0, "Y position must be greater than or equal to 0.");
|
||||
|
@ -16,9 +16,6 @@ namespace Dawn {
|
||||
|
||||
public:
|
||||
Event<int32_t, int32_t> eventPositionChanged;
|
||||
std::vector<std::shared_ptr<UIElement>> children;
|
||||
|
||||
std::vector<std::shared_ptr<UIElement>> getChildren() override;
|
||||
|
||||
/**
|
||||
* Sets the position of this menu.
|
||||
|
68
src/dawn/ui/UISubAlignableElement.cpp
Normal file
68
src/dawn/ui/UISubAlignableElement.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "UISubAlignableElement.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void UISubAlignableElement::updateAlignment(
|
||||
const glm::vec2 parentPosition,
|
||||
const glm::vec2 parentSize,
|
||||
const float_t canvasScale
|
||||
) {
|
||||
UIAlignableElement::updateAlignment(parentPosition, parentSize, canvasScale);
|
||||
|
||||
switch(this->subAlignX) {
|
||||
case UISubAlignment::START:
|
||||
this->subAlignedPosition.x = this->position.x;
|
||||
break;
|
||||
|
||||
case UISubAlignment::MIDDLE:
|
||||
this->subAlignedPosition.x = (
|
||||
this->position.x +
|
||||
(this->size.x / 2.0f) -
|
||||
(this->getSelfWidth() / 2.0f)
|
||||
);
|
||||
break;
|
||||
|
||||
case UISubAlignment::END:
|
||||
this->subAlignedPosition.x = (
|
||||
this->position.x +
|
||||
this->size.x -
|
||||
this->getSelfWidth()
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
assertUnreachable("Unknown UISubAlignment!");
|
||||
}
|
||||
|
||||
switch(this->subAlignY) {
|
||||
case UISubAlignment::START:
|
||||
this->subAlignedPosition.y = this->position.y;
|
||||
break;
|
||||
|
||||
case UISubAlignment::MIDDLE:
|
||||
this->subAlignedPosition.y = (
|
||||
this->position.y +
|
||||
(this->size.y / 2.0f) -
|
||||
(this->getSelfHeight() / 2.0f)
|
||||
);
|
||||
break;
|
||||
|
||||
case UISubAlignment::END:
|
||||
this->subAlignedPosition.y = (
|
||||
this->position.y +
|
||||
this->size.y -
|
||||
this->getSelfHeight()
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
assertUnreachable("Unknown UISubAlignment!");
|
||||
}
|
||||
|
||||
this->eventSubAlignmentUpdated.emit(this->subAlignedPosition);
|
||||
}
|
32
src/dawn/ui/UISubAlignableElement.hpp
Normal file
32
src/dawn/ui/UISubAlignableElement.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "ui/UIAlignableElement.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
enum class UISubAlignment {
|
||||
START,
|
||||
MIDDLE,
|
||||
END
|
||||
};
|
||||
|
||||
class UISubAlignableElement : public UIAlignableElement {
|
||||
protected:
|
||||
glm::vec2 subAlignedPosition;
|
||||
|
||||
public:
|
||||
Event<glm::vec2> eventSubAlignmentUpdated;
|
||||
|
||||
enum UISubAlignment subAlignX = UISubAlignment::START;
|
||||
enum UISubAlignment subAlignY = UISubAlignment::START;
|
||||
|
||||
void updateAlignment(
|
||||
const glm::vec2 parentPosition,
|
||||
const glm::vec2 parentSize,
|
||||
const float_t canvasScale
|
||||
) override;
|
||||
};
|
||||
}
|
@ -5,6 +5,8 @@
|
||||
|
||||
target_sources(${DAWN_TARGET_NAME}
|
||||
PRIVATE
|
||||
UIGroupContainer.cpp
|
||||
UIColumnContainer.cpp
|
||||
UIContainer.cpp
|
||||
UIPaddingContainer.cpp
|
||||
UIRowContainer.cpp
|
||||
)
|
36
src/dawn/ui/container/UIColumnContainer.cpp
Normal file
36
src/dawn/ui/container/UIColumnContainer.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "assert/assert.hpp"
|
||||
#include "UIColumnContainer.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void UIColumnContainer::updateAlignment(
|
||||
const glm::vec2 parentPosition,
|
||||
const glm::vec2 parentSize,
|
||||
const float_t canvasScale
|
||||
) {
|
||||
this->updateSelfAlignment(parentPosition, parentSize, canvasScale);
|
||||
|
||||
// Now we have our dimensions, divide evenly
|
||||
auto children = this->getChildren();
|
||||
|
||||
float_t x = 0.0f;
|
||||
float_t xPiece = this->size.x / (float_t)children.size();
|
||||
|
||||
// Update all children
|
||||
for(auto &child : children) {
|
||||
child->updateAlignment(
|
||||
this->position + glm::vec2(x, 0),
|
||||
glm::vec2(
|
||||
xPiece,
|
||||
this->size.y
|
||||
),
|
||||
canvasScale
|
||||
);
|
||||
x += xPiece;
|
||||
}
|
||||
}
|
18
src/dawn/ui/container/UIColumnContainer.hpp
Normal file
18
src/dawn/ui/container/UIColumnContainer.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "ui/container/UIContainer.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class UIColumnContainer final : public UIContainer {
|
||||
public:
|
||||
void updateAlignment(
|
||||
const glm::vec2 parentPosition,
|
||||
const glm::vec2 parentSize,
|
||||
const float_t canvasScale
|
||||
) override;
|
||||
};
|
||||
}
|
47
src/dawn/ui/container/UIContainer.cpp
Normal file
47
src/dawn/ui/container/UIContainer.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "assert/assert.hpp"
|
||||
#include "UIContainer.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::shared_ptr<UIElement>> UIContainer::getChildren() {
|
||||
return this->children;
|
||||
}
|
||||
|
||||
float_t UIContainer::getSelfWidth() {
|
||||
float_t width = 0;
|
||||
auto children = this->getChildren();
|
||||
for(auto child : children) {
|
||||
width = Math::max(width, child->getWidth());
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
float_t UIContainer::getSelfHeight() {
|
||||
float_t height = 0;
|
||||
auto children = this->getChildren();
|
||||
for(auto child : children) {
|
||||
height = Math::max(height, child->getHeight());
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
void UIContainer::appendChild(std::shared_ptr<UIElement> child) {
|
||||
assertNotNull(child, "Cannot append a null child!");
|
||||
this->children.push_back(child);
|
||||
}
|
||||
|
||||
void UIContainer::removeChild(std::shared_ptr<UIElement> child) {
|
||||
assertNotNull(child, "Cannot remove a null child!");
|
||||
auto it = std::find(this->children.begin(), this->children.end(), child);
|
||||
if(it == this->children.end()) return;
|
||||
this->children.erase(it);
|
||||
}
|
||||
|
||||
void UIContainer::clearChildren() {
|
||||
this->children.clear();
|
||||
}
|
@ -8,7 +8,32 @@
|
||||
|
||||
namespace Dawn {
|
||||
class UIContainer : public UIAlignableElement {
|
||||
private:
|
||||
std::vector<std::shared_ptr<UIElement>> children;
|
||||
|
||||
public:
|
||||
std::vector<std::shared_ptr<UIElement>> getChildren() override;
|
||||
|
||||
float_t getSelfWidth() override;
|
||||
float_t getSelfHeight() override;
|
||||
|
||||
/**
|
||||
* Appends a child to this container.
|
||||
*
|
||||
* @param child Child to append.
|
||||
*/
|
||||
void appendChild(std::shared_ptr<UIElement> child);
|
||||
|
||||
/**
|
||||
* Removes a child from this container.
|
||||
*
|
||||
* @param child Child to remove.
|
||||
*/
|
||||
void removeChild(std::shared_ptr<UIElement> child);
|
||||
|
||||
/**
|
||||
* Removes all children from this container.
|
||||
*/
|
||||
void clearChildren();
|
||||
};
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "UIGroupContainer.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::shared_ptr<UIElement>> UIGroupContainer::getChildren() {
|
||||
return this->children;
|
||||
}
|
||||
|
||||
void UIGroupContainer::appendChild(std::shared_ptr<UIElement> child) {
|
||||
assertNotNull(child, "Cannot append a null child!");
|
||||
this->children.push_back(child);
|
||||
}
|
||||
|
||||
void UIGroupContainer::removeChild(std::shared_ptr<UIElement> child) {
|
||||
assertNotNull(child, "Cannot remove a null child!");
|
||||
auto it = std::find(this->children.begin(), this->children.end(), child);
|
||||
if(it == this->children.end()) return;
|
||||
this->children.erase(it);
|
||||
}
|
||||
|
||||
void UIGroupContainer::clearChildren() {
|
||||
this->children.clear();
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "ui/container/UIContainer.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class UIGroupContainer : public UIContainer {
|
||||
private:
|
||||
std::vector<std::shared_ptr<UIElement>> children;
|
||||
|
||||
public:
|
||||
std::vector<std::shared_ptr<UIElement>> getChildren() override;
|
||||
|
||||
/**
|
||||
* Appends a child to this container.
|
||||
*
|
||||
* @param child Child to append.
|
||||
*/
|
||||
void appendChild(std::shared_ptr<UIElement> child);
|
||||
|
||||
/**
|
||||
* Removes a child from this container.
|
||||
*
|
||||
* @param child Child to remove.
|
||||
*/
|
||||
void removeChild(std::shared_ptr<UIElement> child);
|
||||
|
||||
/**
|
||||
* Removes all children from this container.
|
||||
*/
|
||||
void clearChildren();
|
||||
};
|
||||
}
|
22
src/dawn/ui/container/UIPaddingContainer.cpp
Normal file
22
src/dawn/ui/container/UIPaddingContainer.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "UIPaddingContainer.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void UIPaddingContainer::updateAlignment(
|
||||
const glm::vec2 parentPosition,
|
||||
const glm::vec2 parentSize,
|
||||
const float_t canvasScale
|
||||
) {
|
||||
glm::vec2 childPosition = parentPosition + glm::vec2(padding.x, padding.y);
|
||||
glm::vec2 childSize = parentSize - glm::vec2(padding.x + padding.z, padding.y + padding.w);
|
||||
|
||||
auto children = getChildren();
|
||||
for(auto &child : children) {
|
||||
child->updateAlignment(childPosition, childSize, canvasScale);
|
||||
}
|
||||
}
|
20
src/dawn/ui/container/UIPaddingContainer.hpp
Normal file
20
src/dawn/ui/container/UIPaddingContainer.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "ui/container/UIContainer.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class UIPaddingContainer final : public UIContainer {
|
||||
public:
|
||||
glm::vec4 padding = { 0, 0, 0, 0 };
|
||||
|
||||
void updateAlignment(
|
||||
const glm::vec2 parentPosition,
|
||||
const glm::vec2 parentSize,
|
||||
const float_t canvasScale
|
||||
) override;
|
||||
};
|
||||
}
|
@ -3,29 +3,24 @@
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "assert/assert.hpp"
|
||||
#include "UIRowContainer.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::shared_ptr<UIElement>> UIRowContainer::getChildren() {
|
||||
return this->children;
|
||||
float_t UIRowContainer::getSelfWidth() {
|
||||
float_t width = 0.0f;
|
||||
for(auto &child : this->getChildren()) {
|
||||
width += child->getWidth();
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
void UIRowContainer::appendChild(std::shared_ptr<UIElement> child) {
|
||||
assertNotNull(child, "Cannot append a null child!");
|
||||
this->children.push_back(child);
|
||||
}
|
||||
|
||||
void UIRowContainer::removeChild(std::shared_ptr<UIElement> child) {
|
||||
assertNotNull(child, "Cannot remove a null child!");
|
||||
auto it = std::find(this->children.begin(), this->children.end(), child);
|
||||
if(it == this->children.end()) return;
|
||||
this->children.erase(it);
|
||||
}
|
||||
|
||||
void UIRowContainer::clearChildren() {
|
||||
this->children.clear();
|
||||
float_t UIRowContainer::getSelfHeight() {
|
||||
float_t height = 0.0f;
|
||||
for(auto &child : this->getChildren()) {
|
||||
height = std::max(height, child->getHeight());
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
void UIRowContainer::updateAlignment(
|
||||
@ -42,7 +37,7 @@ void UIRowContainer::updateAlignment(
|
||||
float_t yPiece = this->size.y / (float_t)children.size();
|
||||
|
||||
// Update all children
|
||||
for(auto &child : this->children) {
|
||||
for(auto &child : children) {
|
||||
child->updateAlignment(
|
||||
this->position + glm::vec2(0, y),
|
||||
glm::vec2(
|
||||
|
@ -8,30 +8,9 @@
|
||||
|
||||
namespace Dawn {
|
||||
class UIRowContainer final : public UIContainer {
|
||||
private:
|
||||
std::vector<std::shared_ptr<UIElement>> children;
|
||||
|
||||
public:
|
||||
std::vector<std::shared_ptr<UIElement>> getChildren() override;
|
||||
|
||||
/**
|
||||
* Appends a child to this container.
|
||||
*
|
||||
* @param child Child to append.
|
||||
*/
|
||||
void appendChild(std::shared_ptr<UIElement> child);
|
||||
|
||||
/**
|
||||
* Removes a child from this container.
|
||||
*
|
||||
* @param child Child to remove.
|
||||
*/
|
||||
void removeChild(std::shared_ptr<UIElement> child);
|
||||
|
||||
/**
|
||||
* Removes all children from this container.
|
||||
*/
|
||||
void clearChildren();
|
||||
float_t getSelfWidth() override;
|
||||
float_t getSelfHeight() override;
|
||||
|
||||
void updateAlignment(
|
||||
const glm::vec2 parentPosition,
|
||||
|
10
src/dawn/ui/elements/CMakeLists.txt
Normal file
10
src/dawn/ui/elements/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2023 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
target_sources(${DAWN_TARGET_NAME}
|
||||
PRIVATE
|
||||
UIRectangle.cpp
|
||||
UILabel.cpp
|
||||
)
|
@ -56,7 +56,7 @@ void UILabel::getSelfQuads(UICanvas &ctx) {
|
||||
|
||||
lastCharWasSpace = false;
|
||||
}
|
||||
} else if(pos.x + info.size.x > position.x + size.x) {
|
||||
} else if(pos.x + info.size.x > subAlignedPosition.x + size.x) {
|
||||
// Not word wrap, but instead just overflow characters.
|
||||
pos.x = 0;
|
||||
pos.y += this->texture->fontSize;
|
||||
@ -64,10 +64,10 @@ void UILabel::getSelfQuads(UICanvas &ctx) {
|
||||
|
||||
ctx.addQuad(
|
||||
{
|
||||
position.x + pos.x + info.offset.x,
|
||||
position.y + pos.y + info.offset.y,
|
||||
position.x + pos.x + info.size.x + info.offset.x,
|
||||
position.y + pos.y + info.size.y + info.offset.y
|
||||
subAlignedPosition.x + pos.x + info.offset.x,
|
||||
subAlignedPosition.y + pos.y + info.offset.y,
|
||||
subAlignedPosition.x + pos.x + info.size.x + info.offset.x,
|
||||
subAlignedPosition.y + pos.y + info.size.y + info.offset.y
|
||||
},
|
||||
{
|
||||
info.quad.x,
|
||||
@ -83,6 +83,78 @@ void UILabel::getSelfQuads(UICanvas &ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
float_t UILabel::getContentWidth() {
|
||||
if(this->texture == nullptr || this->text.empty()) return 0.0f;
|
||||
|
||||
float_t lineWidth = 0.0f;
|
||||
float_t width = 0.0f;
|
||||
for(wchar_t c : text) {
|
||||
if(c == L'\n') {
|
||||
width = Math::max<float_t>(width, lineWidth);
|
||||
lineWidth = 0.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto info = texture->getCharacterData(c);
|
||||
lineWidth += info.advance.x;
|
||||
if(lineWidth >= size.x) return size.x;
|
||||
}
|
||||
|
||||
return Math::max<float_t>(width, lineWidth);
|
||||
}
|
||||
|
||||
float_t UILabel::getContentHeight() {
|
||||
if(this->texture == nullptr || this->text.empty()) return 0.0f;
|
||||
|
||||
float_t height = this->texture->fontSize;
|
||||
float_t lineWidth = 0.0f;
|
||||
bool_t lastCharWasSpace = false;
|
||||
|
||||
for(wchar_t c : text) {
|
||||
if(c == L'\n') {
|
||||
height += this->texture->fontSize;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto info = texture->getCharacterData(c);
|
||||
|
||||
if(c == L' ') {
|
||||
lineWidth += info.advance.x;
|
||||
lastCharWasSpace = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(wordWrap) {
|
||||
if(lastCharWasSpace) {
|
||||
// Scan ahead to next space
|
||||
float_t wordWidth = lineWidth;// Start at current position and scan ahead.
|
||||
for(size_t j = 0; j < text.size(); j++) {
|
||||
wchar_t c2 = text[j];
|
||||
if(c2 == L' ' || c2 == L'\n') {
|
||||
break;// If we hit another space, we are OK.
|
||||
}
|
||||
|
||||
// Will this character fit on the row? If not the whole word will wrap.
|
||||
auto info2 = texture->getCharacterData(c);
|
||||
wordWidth += info.advance.x;
|
||||
if(wordWidth > size.x) {
|
||||
height += this->texture->fontSize;
|
||||
lineWidth = 0.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lastCharWasSpace = false;
|
||||
}
|
||||
} else if(lineWidth + info.size.x > size.x) {
|
||||
height += this->texture->fontSize;
|
||||
lineWidth = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
std::shared_ptr<TrueTypeTexture> UILabel::getFont() {
|
||||
return this->texture;
|
||||
}
|
@ -4,11 +4,11 @@
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "ui/UIAlignableElement.hpp"
|
||||
#include "ui/UISubAlignableElement.hpp"
|
||||
#include "display/font/TrueTypeTexture.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class UILabel final : public UIAlignableElement {
|
||||
class UILabel final : public UISubAlignableElement {
|
||||
private:
|
||||
std::shared_ptr<TrueTypeTexture> texture = nullptr;
|
||||
std::wstring text = L"Hello World";
|
||||
@ -20,6 +20,9 @@ namespace Dawn {
|
||||
bool_t wordWrap = true;
|
||||
struct Color color = COLOR_WHITE;
|
||||
|
||||
float_t getContentWidth() override;
|
||||
float_t getContentHeight() override;
|
||||
|
||||
/**
|
||||
* Returns the font used for this label.
|
||||
*
|
@ -12,11 +12,11 @@
|
||||
#include "display/mesh/QuadMesh.hpp"
|
||||
|
||||
#include "component/ui/UICanvas.hpp"
|
||||
#include "ui/UIRectangle.hpp"
|
||||
#include "ui/UILabel.hpp"
|
||||
#include "ui/elements/UIRectangle.hpp"
|
||||
#include "ui/elements/UILabel.hpp"
|
||||
#include "ui/UIMenu.hpp"
|
||||
#include "ui/container/UIRowContainer.hpp"
|
||||
#include "ui/container/UIGroupContainer.hpp"
|
||||
#include "ui/container/UIPaddingContainer.hpp"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
@ -58,40 +58,52 @@ void Dawn::helloWorldScene(Scene &s) {
|
||||
auto uiCanvasItem = s.createSceneItem();
|
||||
auto uiCanvas = uiCanvasItem->addComponent<UICanvas>();
|
||||
|
||||
auto container = std::make_shared<UIGroupContainer>();
|
||||
container->align = { 32, 32, 300, 250 };
|
||||
auto container = std::make_shared<UIContainer>();
|
||||
container->align = { 32, 32, UI_ALIGN_AUTO, UI_ALIGN_AUTO };
|
||||
container->alignX = UIAlignmentType::START;
|
||||
container->alignY = UIAlignmentType::START;
|
||||
uiCanvas->addElement(container);
|
||||
|
||||
auto whatever = std::make_shared<UIContainer>();
|
||||
whatever->align = { 0, 0, 32, 32 };
|
||||
whatever->alignX = UIAlignmentType::START;
|
||||
whatever->alignY = UIAlignmentType::START;
|
||||
container->appendChild(whatever);
|
||||
|
||||
auto rect = std::make_shared<UIRectangle>();
|
||||
rect->color = COLOR_MAGENTA;
|
||||
rect->align = { 0, 0, 0, 0 };
|
||||
rect->alignX = UIAlignmentType::STRETCH;
|
||||
rect->alignY = UIAlignmentType::STRETCH;
|
||||
// rectPink->align = { 0, 0, 32, 32 };
|
||||
container->appendChild(rect);
|
||||
return;
|
||||
|
||||
auto menu = std::make_shared<UIMenu>();
|
||||
menu->setSize(1, 4);
|
||||
container->appendChild(menu);
|
||||
|
||||
auto rowContainer = std::make_shared<UIRowContainer>();
|
||||
menu->children.push_back(rowContainer);
|
||||
container->appendChild(rowContainer);
|
||||
|
||||
auto label0 = std::make_shared<UILabel>();
|
||||
label0->setText(L"New Game");
|
||||
label0->setFont(texture);
|
||||
rowContainer->appendChild(label0);
|
||||
std::vector<std::wstring> labels = {
|
||||
L"New Game",
|
||||
L"Load Game",
|
||||
L"Options",
|
||||
L"Exit"
|
||||
};
|
||||
|
||||
auto label1 = std::make_shared<UILabel>();
|
||||
label1->setText(L"Load Game");
|
||||
label1->setFont(texture);
|
||||
rowContainer->appendChild(label1);
|
||||
for(auto &label : labels) {
|
||||
auto padding = std::make_shared<UIPaddingContainer>();
|
||||
padding->padding = { 8, 8, 8, 8 };
|
||||
|
||||
auto label2 = std::make_shared<UILabel>();
|
||||
label2->setText(L"Options");
|
||||
label2->setFont(texture);
|
||||
rowContainer->appendChild(label2);
|
||||
|
||||
auto label3 = std::make_shared<UILabel>();
|
||||
label3->setText(L"Exit");
|
||||
label3->setFont(texture);
|
||||
rowContainer->appendChild(label3);
|
||||
auto labelElement = std::make_shared<UILabel>();
|
||||
labelElement->setText(label);
|
||||
labelElement->setFont(texture);
|
||||
// labelElement->subAlignX = UISubAlignment::MIDDLE;
|
||||
// labelElement->subAlignY = UISubAlignment::MIDDLE;
|
||||
|
||||
padding->appendChild(labelElement);
|
||||
rowContainer->appendChild(padding);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user