Added text height parameter.

This commit is contained in:
Patrick 2024-09-19 17:23:12 +02:00
parent eae595ec4a
commit a827e6edcd
7 changed files with 114 additions and 54 deletions

View File

@ -76,7 +76,8 @@ void UIApp::init(const AppInitArgs& args)
.text = "Test-Text!\nSecond $f00line$fff?", .text = "Test-Text!\nSecond $f00line$fff?",
.color = glm::vec4(0.f, 1.f, 0.f, 1.f), .color = glm::vec4(0.f, 1.f, 0.f, 1.f),
.posX = 100, .posX = 100,
.posY = 100 .posY = 100,
.textHeight = 20
}); });
mButton = mWidgetTree.getRootWidget().emplaceChild<Button>({ mButton = mWidgetTree.getRootWidget().emplaceChild<Button>({
.text = "Click Me!", .text = "Click Me!",

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) 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) 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() void Button::handleEnteredTree()
{ {
update(); update();

View File

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

View File

@ -3,7 +3,8 @@
namespace sdl_gpu_test 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) 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) 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() void Label::handleEnteredTree()
{ {
update(); update();
@ -68,6 +79,7 @@ void Label::update()
mTree->getRenderer().drawText({ mTree->getRenderer().drawText({
.x = mPosX, .x = mPosX,
.y = mPosY, .y = mPosY,
.height = mTextHeight,
.text = mText, .text = mText,
.color = mColor .color = mColor
}, &mPrimitiveID); }, &mPrimitiveID);

View File

@ -14,8 +14,9 @@ struct LabelCreateArgs
{ {
std::string text; std::string text;
glm::vec4 color = {1.f, 1.f, 1.f, 1.f}; glm::vec4 color = {1.f, 1.f, 1.f, 1.f};
int posX = 0; float posX = 0.f;
int posY = 0; float posY = 0.f;
float textHeight = 38.f;
}; };
class Label : public Widget class Label : public Widget
@ -25,8 +26,9 @@ public:
private: private:
std::string mText; std::string mText;
glm::vec4 mColor = {1.f, 1.f, 1.f, 1.f}; glm::vec4 mColor = {1.f, 1.f, 1.f, 1.f};
int mPosX = 0; float mPosX = 0.f;
int mPosY = 0; float mPosY = 0.f;
float mTextHeight = 38.f;
UIRenderer::primitive_id_t mPrimitiveID = UIRenderer::UNSET_PRIMITIVE_ID; UIRenderer::primitive_id_t mPrimitiveID = UIRenderer::UNSET_PRIMITIVE_ID;
public: public:
explicit Label(LabelCreateArgs args); explicit Label(LabelCreateArgs args);
@ -38,15 +40,19 @@ public:
const glm::vec4& getColor() const noexcept { return mColor; } const glm::vec4& getColor() const noexcept { return mColor; }
[[nodiscard]] [[nodiscard]]
int getPosX() const noexcept { return mPosX; } float getPosX() const noexcept { return mPosX; }
[[nodiscard]] [[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 setText(std::string text);
void setColor(const glm::vec4& color); void setColor(const glm::vec4& color);
void setPosX(int posX); void setPosX(float posX);
void setPosY(int posY); void setPosY(float posY);
void setTextHeight(float textHeight);
void handleEnteredTree() override; void handleEnteredTree() override;
void revalidate() 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; const float lineHeight = static_cast<float>(mFontMap.lineHeight) * static_cast<float>(args.height) / static_cast<float>(mFontMap.base);
unsigned height = mFontMap.lineHeight;
unsigned lineWidth = 0; float width = 0;
float height = lineHeight;
float lineWidth = 0;
for (std::size_t pos = 0; pos < args.text.size(); ++pos) 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': case '\n':
width = std::max(lineWidth, width); width = std::max(lineWidth, width);
lineWidth = 0; lineWidth = 0;
height += mFontMap.lineHeight; height += lineHeight;
break; break;
case '$': case '$':
++pos; ++pos;
@ -205,8 +207,9 @@ std::pair<unsigned, unsigned> UIRenderer::measureText(const MeasureTextArgs& arg
[[fallthrough]]; [[fallthrough]];
default: 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 const UVFontMapEntry& entry = mFontMap.entries[chr < 0 ? '_' : chr]; // TODO: more chars
lineWidth += entry.xAdvance; lineWidth += factor * static_cast<float>(entry.xAdvance);
break; break;
} }
} }
@ -218,9 +221,11 @@ std::pair<unsigned, unsigned> UIRenderer::measureText(const MeasureTextArgs& arg
void UIRenderer::drawText(const DrawTextArgs& args, primitive_id_t* outPrimitiveId) 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; glm::vec4 color = args.color;
int posX = args.x; float posX = args.x;
int posY = args.y; float posY = args.y;
if (outPrimitiveId != nullptr && *outPrimitiveId == UNSET_PRIMITIVE_ID) if (outPrimitiveId != nullptr && *outPrimitiveId == UNSET_PRIMITIVE_ID)
{ {
@ -234,7 +239,7 @@ void UIRenderer::drawText(const DrawTextArgs& args, primitive_id_t* outPrimitive
{ {
case '\n': case '\n':
posX = args.x; posX = args.x;
posY += static_cast<int>(mFontMap.lineHeight); posY += lineHeight;
break; break;
case '$': case '$':
++pos; ++pos;
@ -280,12 +285,13 @@ void UIRenderer::drawText(const DrawTextArgs& args, primitive_id_t* outPrimitive
chr = args.text[pos]; chr = args.text[pos];
[[fallthrough]]; [[fallthrough]];
default: default:
posX += static_cast<int>(drawChar({ posX += drawChar({
.x = posX, .x = posX,
.y = posY, .y = posY,
.height = args.height,
.chr = chr, .chr = chr,
.color = color .color = color
}, outPrimitiveId)); }, outPrimitiveId);
break; break;
} }
} }
@ -293,33 +299,37 @@ void UIRenderer::drawText(const DrawTextArgs& args, primitive_id_t* outPrimitive
void UIRenderer::drawTextCentered(DrawTextArgs args, primitive_id_t* outPrimitiveId) 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({ const auto [width, height] = measureText({
.text = args.text .text = args.text,
.height = args.height
}); });
args.x -= static_cast<int>(width / 2); args.x -= width / 2;
args.y -= static_cast<int>(height + mFontMap.lineHeight - mFontMap.base) / 2; args.y -= (height + lineHeight - args.height) / 2.f;
drawText(args, outPrimitiveId); 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) if (outPrimitiveId != nullptr && *outPrimitiveId == UNSET_PRIMITIVE_ID)
{ {
*outPrimitiveId = mNextOwner++; *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 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({ drawQuadInternal({
.topLeft = topLeft, .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}, .uvTopLeft = {entry.uvX, entry.uvY},
.uvBottomRight = {entry.uvX + entry.uvWidth, entry.uvY + entry.uvHeight}, .uvBottomRight = {entry.uvX + entry.uvWidth, entry.uvY + entry.uvHeight},
.color = args.color .color = args.color
}, outPrimitiveId == nullptr ? UNSET_PRIMITIVE_ID : *outPrimitiveId); }, 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) void UIRenderer::drawQuad(const DrawQuadArgs& args, primitive_id_t* outPrimitiveId)

View File

@ -23,20 +23,23 @@ struct UIVertex
struct MeasureTextArgs struct MeasureTextArgs
{ {
std::string_view text; std::string_view text;
float height = 38;
}; };
struct DrawTextArgs struct DrawTextArgs
{ {
int x = 0; float x = 0.f;
int y = 0; float y = 0.f;
float height = 38.f;
std::string_view text; std::string_view text;
glm::vec4 color = glm::vec4(1.f); glm::vec4 color = glm::vec4(1.f);
}; };
struct DrawCharArgs struct DrawCharArgs
{ {
int x = 0; float x = 0.f;
int y = 0; float y = 0.f;
float height = 38.f;
char chr; char chr;
glm::vec4 color = glm::vec4(1.f); glm::vec4 color = glm::vec4(1.f);
}; };
@ -44,10 +47,10 @@ struct DrawCharArgs
struct DrawQuadArgs struct DrawQuadArgs
{ {
std::string texture; std::string texture;
int x = 0; float x = 0.f;
int y = 0; float y = 0.f;
int width; float width;
int height; float height;
glm::vec4 color = glm::vec4(1.f); glm::vec4 color = glm::vec4(1.f);
}; };
@ -83,10 +86,10 @@ public:
void render(const UIRendererRenderArgs& args); void render(const UIRendererRenderArgs& args);
[[nodiscard]] [[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 drawText(const DrawTextArgs& args, primitive_id_t* outPrimitiveId = nullptr);
void drawTextCentered(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); void drawQuad(const DrawQuadArgs& args, primitive_id_t* outPrimitiveId = nullptr);
bool removePrimitive(primitive_id_t primitiveId); bool removePrimitive(primitive_id_t primitiveId);
private: private: