Compare commits

...

2 Commits

Author SHA1 Message Date
669bce546d Fixed the UI vertices count display. 2024-09-19 17:33:05 +02:00
a827e6edcd Added text height parameter. 2024-09-19 17:23:12 +02:00
7 changed files with 118 additions and 55 deletions

View File

@ -76,7 +76,8 @@ void UIApp::init(const AppInitArgs& args)
.text = "Test-Text!\nSecond $f00line$fff?",
.color = glm::vec4(0.f, 1.f, 0.f, 1.f),
.posX = 100,
.posY = 100
.posY = 100,
.textHeight = 20
});
mButton = mWidgetTree.getRootWidget().emplaceChild<Button>({
.text = "Click Me!",
@ -94,7 +95,7 @@ void UIApp::update(const AppUpdateArgs& args)
Application::update(args);
processInput(args);
mLabel->setText(std::format("Rotation: {}{}\n$rUI vertices: $f00{}", mRotation > 180.f ? "$00f": "$fff" , mRotation, mNumVertices));
mLabel->setText(std::format("Rotation: {}{}\n$rUI vertices: $f8c{}", mRotation > 180.f ? "$8cf": "$fff" , mRotation, mUIRenderer.getNumVertices()));
mWidgetTree.revalidateWidgets();
// begin rendering

View File

@ -52,7 +52,7 @@ void Button::setHoveredColor(const glm::vec4& color)
}
}
void Button::setPosX(int posX)
void Button::setPosX(float posX)
{
if (posX != mPosX)
{
@ -61,7 +61,7 @@ void Button::setPosX(int posX)
}
}
void Button::setPosY(int posY)
void Button::setPosY(float posY)
{
if (posY != mPosY)
{
@ -70,6 +70,26 @@ void Button::setPosY(int posY)
}
}
void Button::setWidth(float width)
{
if (width != mWidth)
{
mWidth = width;
invalidate();
}
}
void Button::setHeight(float height)
{
if (height != mHeight)
{
mHeight = height;
invalidate();
}
}
void Button::handleEnteredTree()
{
update();

View File

@ -17,10 +17,10 @@ struct ButtonCreateArgs
glm::vec4 textColor = {1.f, 1.f, 1.f, 1.f};
glm::vec4 backgroundColor = {1.f, 0.f, 0.f, 1.f};
glm::vec4 hoveredColor = {1.f, 0.9f, 0.9f, 1.f};
int posX = 0;
int posY = 0;
int width = 256;
int height = 84;
float posX = 0;
float posY = 0;
float width = 256;
float height = 84;
};
class Button : public Widget
@ -32,10 +32,10 @@ private:
glm::vec4 mTextColor;
glm::vec4 mBackgroundColor;
glm::vec4 mHoveredColor;
int mPosX = 0;
int mPosY = 0;
int mWidth = 0;
int mHeight = 0;
float mPosX = 0;
float mPosY = 0;
float mWidth = 0;
float mHeight = 0;
bool mHovered = false;
UIRenderer::primitive_id_t mPrimitiveID = UIRenderer::UNSET_PRIMITIVE_ID;
public:
@ -54,17 +54,25 @@ public:
const glm::vec4& getHoveredColor() const noexcept { return mHoveredColor; }
[[nodiscard]]
int getPosX() const noexcept { return mPosX; }
float getPosX() const noexcept { return mPosX; }
[[nodiscard]]
int getPosY() const noexcept { return mPosY; }
float getPosY() const noexcept { return mPosY; }
[[nodiscard]]
float getWidth() const noexcept { return mWidth; }
[[nodiscard]]
float getHeight() const noexcept { return mHeight; }
void setText(std::string text);
void setTextColor(const glm::vec4& color);
void setBackgroundColor(const glm::vec4& color);
void setHoveredColor(const glm::vec4& color);
void setPosX(int posX);
void setPosY(int posY);
void setPosX(float posX);
void setPosY(float posY);
void setWidth(float width);
void setHeight(float height);
void handleEnteredTree() override;
void handleMouseMotion(const sdlpp::MouseMotionEvent& event) override;

View File

@ -3,7 +3,8 @@
namespace sdl_gpu_test
{
Label::Label(LabelCreateArgs args) : mText(std::move(args.text)), mColor(args.color), mPosX(args.posX), mPosY(args.posY)
Label::Label(LabelCreateArgs args) : mText(std::move(args.text)), mColor(args.color), mPosX(args.posX),
mPosY(args.posY), mTextHeight(args.textHeight)
{
}
@ -26,7 +27,7 @@ void Label::setColor(const glm::vec4& color)
}
}
void Label::setPosX(int posX)
void Label::setPosX(float posX)
{
if (posX != mPosX)
{
@ -35,7 +36,7 @@ void Label::setPosX(int posX)
}
}
void Label::setPosY(int posY)
void Label::setPosY(float posY)
{
if (posY != mPosY)
{
@ -44,6 +45,16 @@ void Label::setPosY(int posY)
}
}
void Label::setTextHeight(float textHeight)
{
if (textHeight != mTextHeight)
{
mTextHeight = textHeight;
invalidate();
}
}
void Label::handleEnteredTree()
{
update();
@ -68,6 +79,7 @@ void Label::update()
mTree->getRenderer().drawText({
.x = mPosX,
.y = mPosY,
.height = mTextHeight,
.text = mText,
.color = mColor
}, &mPrimitiveID);

View File

@ -14,8 +14,9 @@ struct LabelCreateArgs
{
std::string text;
glm::vec4 color = {1.f, 1.f, 1.f, 1.f};
int posX = 0;
int posY = 0;
float posX = 0.f;
float posY = 0.f;
float textHeight = 38.f;
};
class Label : public Widget
@ -25,8 +26,9 @@ public:
private:
std::string mText;
glm::vec4 mColor = {1.f, 1.f, 1.f, 1.f};
int mPosX = 0;
int mPosY = 0;
float mPosX = 0.f;
float mPosY = 0.f;
float mTextHeight = 38.f;
UIRenderer::primitive_id_t mPrimitiveID = UIRenderer::UNSET_PRIMITIVE_ID;
public:
explicit Label(LabelCreateArgs args);
@ -38,15 +40,19 @@ public:
const glm::vec4& getColor() const noexcept { return mColor; }
[[nodiscard]]
int getPosX() const noexcept { return mPosX; }
float getPosX() const noexcept { return mPosX; }
[[nodiscard]]
int getPosY() const noexcept { return mPosY; }
float getPosY() const noexcept { return mPosY; }
[[nodiscard]]
float getTextHeight() const noexcept { return mTextHeight; }
void setText(std::string text);
void setColor(const glm::vec4& color);
void setPosX(int posX);
void setPosY(int posY);
void setPosX(float posX);
void setPosY(float posY);
void setTextHeight(float textHeight);
void handleEnteredTree() override;
void revalidate() override;

View File

@ -153,11 +153,13 @@ void UIRenderer::render(const UIRendererRenderArgs& args)
}
}
std::pair<unsigned, unsigned> UIRenderer::measureText(const MeasureTextArgs& args) const
std::pair<float, float> UIRenderer::measureText(const MeasureTextArgs& args) const
{
unsigned width = 0;
unsigned height = mFontMap.lineHeight;
unsigned lineWidth = 0;
const float lineHeight = static_cast<float>(mFontMap.lineHeight) * static_cast<float>(args.height) / static_cast<float>(mFontMap.base);
float width = 0;
float height = lineHeight;
float lineWidth = 0;
for (std::size_t pos = 0; pos < args.text.size(); ++pos)
{
@ -167,7 +169,7 @@ std::pair<unsigned, unsigned> UIRenderer::measureText(const MeasureTextArgs& arg
case '\n':
width = std::max(lineWidth, width);
lineWidth = 0;
height += mFontMap.lineHeight;
height += lineHeight;
break;
case '$':
++pos;
@ -205,8 +207,9 @@ std::pair<unsigned, unsigned> UIRenderer::measureText(const MeasureTextArgs& arg
[[fallthrough]];
default:
{
const float factor = static_cast<float>(args.height) / static_cast<float>(mFontMap.base);
const UVFontMapEntry& entry = mFontMap.entries[chr < 0 ? '_' : chr]; // TODO: more chars
lineWidth += entry.xAdvance;
lineWidth += factor * static_cast<float>(entry.xAdvance);
break;
}
}
@ -218,9 +221,11 @@ std::pair<unsigned, unsigned> UIRenderer::measureText(const MeasureTextArgs& arg
void UIRenderer::drawText(const DrawTextArgs& args, primitive_id_t* outPrimitiveId)
{
const float lineHeight = static_cast<float>(mFontMap.lineHeight) * static_cast<float>(args.height) / static_cast<float>(mFontMap.base);
glm::vec4 color = args.color;
int posX = args.x;
int posY = args.y;
float posX = args.x;
float posY = args.y;
if (outPrimitiveId != nullptr && *outPrimitiveId == UNSET_PRIMITIVE_ID)
{
@ -234,7 +239,7 @@ void UIRenderer::drawText(const DrawTextArgs& args, primitive_id_t* outPrimitive
{
case '\n':
posX = args.x;
posY += static_cast<int>(mFontMap.lineHeight);
posY += lineHeight;
break;
case '$':
++pos;
@ -280,12 +285,13 @@ void UIRenderer::drawText(const DrawTextArgs& args, primitive_id_t* outPrimitive
chr = args.text[pos];
[[fallthrough]];
default:
posX += static_cast<int>(drawChar({
posX += drawChar({
.x = posX,
.y = posY,
.height = args.height,
.chr = chr,
.color = color
}, outPrimitiveId));
}, outPrimitiveId);
break;
}
}
@ -293,33 +299,37 @@ void UIRenderer::drawText(const DrawTextArgs& args, primitive_id_t* outPrimitive
void UIRenderer::drawTextCentered(DrawTextArgs args, primitive_id_t* outPrimitiveId)
{
const float lineHeight = static_cast<float>(mFontMap.lineHeight) * args.height / static_cast<float>(mFontMap.base);
const auto [width, height] = measureText({
.text = args.text
.text = args.text,
.height = args.height
});
args.x -= static_cast<int>(width / 2);
args.y -= static_cast<int>(height + mFontMap.lineHeight - mFontMap.base) / 2;
args.x -= width / 2;
args.y -= (height + lineHeight - args.height) / 2.f;
drawText(args, outPrimitiveId);
}
unsigned UIRenderer::drawChar(const DrawCharArgs& args, primitive_id_t* outPrimitiveId)
float UIRenderer::drawChar(const DrawCharArgs& args, primitive_id_t* outPrimitiveId)
{
if (outPrimitiveId != nullptr && *outPrimitiveId == UNSET_PRIMITIVE_ID)
{
*outPrimitiveId = mNextOwner++;
}
const float factor = static_cast<float>(args.height) / static_cast<float>(mFontMap.base);
const UVFontMapEntry& entry = mFontMap.entries[args.chr < 0 ? '_' : args.chr]; // TODO: more chars
const glm::vec2 topLeft = {args.x + entry.xOffset, args.y + entry.yOffset};
const glm::vec2 topLeft = {args.x + factor * entry.xOffset, args.y + factor * entry.yOffset};
drawQuadInternal({
.topLeft = topLeft,
.bottomRight = {topLeft.x + static_cast<float>(entry.width), topLeft.y + static_cast<float>(entry.height)},
.bottomRight = {topLeft.x + factor * static_cast<float>(entry.width), topLeft.y + factor * static_cast<float>(entry.height)},
.uvTopLeft = {entry.uvX, entry.uvY},
.uvBottomRight = {entry.uvX + entry.uvWidth, entry.uvY + entry.uvHeight},
.color = args.color
}, outPrimitiveId == nullptr ? UNSET_PRIMITIVE_ID : *outPrimitiveId);
return entry.xAdvance;
return factor * static_cast<float>(entry.xAdvance);
}
void UIRenderer::drawQuad(const DrawQuadArgs& args, primitive_id_t* outPrimitiveId)

View File

@ -23,20 +23,23 @@ struct UIVertex
struct MeasureTextArgs
{
std::string_view text;
float height = 38;
};
struct DrawTextArgs
{
int x = 0;
int y = 0;
float x = 0.f;
float y = 0.f;
float height = 38.f;
std::string_view text;
glm::vec4 color = glm::vec4(1.f);
};
struct DrawCharArgs
{
int x = 0;
int y = 0;
float x = 0.f;
float y = 0.f;
float height = 38.f;
char chr;
glm::vec4 color = glm::vec4(1.f);
};
@ -44,10 +47,10 @@ struct DrawCharArgs
struct DrawQuadArgs
{
std::string texture;
int x = 0;
int y = 0;
int width;
int height;
float x = 0.f;
float y = 0.f;
float width;
float height;
glm::vec4 color = glm::vec4(1.f);
};
@ -79,14 +82,17 @@ private:
bool mVerticesDirty = true;
std::size_t mVertexBufferSize = 0;
public:
[[nodiscard]]
std::size_t getNumVertices() const noexcept { return mVertices.size(); }
void init(Application& application);
void render(const UIRendererRenderArgs& args);
[[nodiscard]]
std::pair<unsigned, unsigned> measureText(const MeasureTextArgs& args) const;
std::pair<float, float> measureText(const MeasureTextArgs& args) const;
void drawText(const DrawTextArgs& args, primitive_id_t* outPrimitiveId = nullptr);
void drawTextCentered(DrawTextArgs args, primitive_id_t* outPrimitiveId = nullptr);
unsigned drawChar(const DrawCharArgs& args, primitive_id_t* outPrimitiveId = nullptr);
float drawChar(const DrawCharArgs& args, primitive_id_t* outPrimitiveId = nullptr);
void drawQuad(const DrawQuadArgs& args, primitive_id_t* outPrimitiveId = nullptr);
bool removePrimitive(primitive_id_t primitiveId);
private: