mirror of
https://github.com/love2d/love.git
synced 2026-08-16 16:20:42 +02:00
Added per-character color support to love.graphics.print/printf and Text objects. Resolves issue #865.
The aforementioned functions now optionally accept an array instead of a plain string. The array is in the format of: {{r, g, b [, a]}, "first colored text, ", {r, g, b [, a]}, "second colored text", ...}, where the color values specify the color to use in the next section of the text.
This commit is contained in:
@@ -30,7 +30,7 @@ namespace graphics
|
||||
namespace opengl
|
||||
{
|
||||
|
||||
Text::Text(Font *font, const std::string &text)
|
||||
Text::Text(Font *font, const std::vector<Font::ColoredString> &text)
|
||||
: font(font)
|
||||
, vbo(nullptr)
|
||||
, text_info()
|
||||
@@ -111,13 +111,13 @@ void Text::regenerateVertices()
|
||||
void Text::addTextData(const TextData &t)
|
||||
{
|
||||
std::vector<Font::GlyphVertex> vertices;
|
||||
std::vector<Font::DrawCommand> new_commands;
|
||||
Font::DrawCommands new_commands;
|
||||
|
||||
// We only have formatted text if the align mode is valid.
|
||||
if (t.align == Font::ALIGN_MAX_ENUM)
|
||||
new_commands = font->generateVertices(t.text, vertices, 0.0f, Vector(0.0f, 0.0f), &text_info);
|
||||
new_commands = font->generateVertices(t.codepoints, vertices, 0.0f, Vector(0.0f, 0.0f), &text_info);
|
||||
else
|
||||
new_commands = font->generateVerticesFormatted(t.text, t.wrap, t.align, vertices, &text_info);
|
||||
new_commands = font->generateVerticesFormatted(t.codepoints, t.wrap, t.align, vertices, &text_info);
|
||||
|
||||
if (t.use_matrix)
|
||||
t.matrix.transform(&vertices[0], &vertices[0], (int) vertices.size());
|
||||
@@ -127,34 +127,37 @@ void Text::addTextData(const TextData &t)
|
||||
if (!t.append_vertices)
|
||||
{
|
||||
voffset = 0;
|
||||
draw_commands.clear();
|
||||
draw_commands.commands.clear();
|
||||
draw_commands.usecolors = false;
|
||||
}
|
||||
|
||||
uploadVertices(vertices, voffset);
|
||||
|
||||
if (!new_commands.empty())
|
||||
if (!new_commands.commands.empty())
|
||||
{
|
||||
// The start vertex should be adjusted to account for the vertex offset.
|
||||
for (Font::DrawCommand &cmd : new_commands)
|
||||
for (Font::DrawCommand &cmd : new_commands.commands)
|
||||
cmd.startvertex += (int) voffset;
|
||||
|
||||
auto firstcmd = new_commands.begin();
|
||||
auto firstcmd = new_commands.commands.begin();
|
||||
|
||||
// If the first draw command in the new list has the same texture as the
|
||||
// last one in the existing list we're building and its vertices are
|
||||
// in-order, we can combine them (saving a draw call.)
|
||||
if (!draw_commands.empty())
|
||||
if (!draw_commands.commands.empty())
|
||||
{
|
||||
auto prevcmd = draw_commands.back();
|
||||
auto prevcmd = draw_commands.commands.back();
|
||||
if (prevcmd.texture == firstcmd->texture && (prevcmd.startvertex + prevcmd.vertexcount) == firstcmd->startvertex)
|
||||
{
|
||||
draw_commands.back().vertexcount += firstcmd->vertexcount;
|
||||
draw_commands.commands.back().vertexcount += firstcmd->vertexcount;
|
||||
++firstcmd;
|
||||
}
|
||||
}
|
||||
|
||||
// Append the new draw commands to the list we're building.
|
||||
draw_commands.insert(draw_commands.end(), firstcmd, new_commands.end());
|
||||
draw_commands.commands.insert(draw_commands.commands.end(), firstcmd, new_commands.commands.end());
|
||||
|
||||
draw_commands.usecolors = draw_commands.usecolors || new_commands.usecolors;
|
||||
}
|
||||
|
||||
vert_offset = voffset + vertices.size();
|
||||
@@ -165,20 +168,20 @@ void Text::addTextData(const TextData &t)
|
||||
regenerateVertices();
|
||||
}
|
||||
|
||||
void Text::set(const std::string &text)
|
||||
void Text::set(const std::vector<Font::ColoredString> &text)
|
||||
{
|
||||
if (text.empty())
|
||||
return set();
|
||||
|
||||
addTextData({text, -1.0f, Font::ALIGN_MAX_ENUM, false, false, Matrix3()});
|
||||
return set(text, -1.0f, Font::ALIGN_MAX_ENUM);
|
||||
}
|
||||
|
||||
void Text::set(const std::string &text, float wrap, Font::AlignMode align)
|
||||
void Text::set(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align)
|
||||
{
|
||||
if (text.empty())
|
||||
if (text.empty() || (text.size() == 1 && text[0].str.empty()))
|
||||
return set();
|
||||
|
||||
addTextData({text, wrap, align, false, false, Matrix3()});
|
||||
Font::ColoredCodepoints codepoints;
|
||||
Font::getCodepointsFromString(text, codepoints);
|
||||
|
||||
addTextData({codepoints, wrap, align, false, false, Matrix3()});
|
||||
}
|
||||
|
||||
void Text::set()
|
||||
@@ -186,30 +189,29 @@ void Text::set()
|
||||
clear();
|
||||
}
|
||||
|
||||
void Text::add(const std::string &text, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
void Text::add(const std::vector<Font::ColoredString> &text, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
{
|
||||
if (text.empty())
|
||||
return;
|
||||
|
||||
Matrix3 m(x, y, angle, sx, sy, ox, oy, kx, ky);
|
||||
|
||||
addTextData({text, -1.0f, Font::ALIGN_MAX_ENUM, true, true, m});
|
||||
return addf(text, -1.0f, Font::ALIGN_MAX_ENUM, x, y, angle, sx, sy, ox, oy, kx, ky);
|
||||
}
|
||||
|
||||
void Text::addf(const std::string &text, float wrap, Font::AlignMode align, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
void Text::addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
{
|
||||
if (text.empty())
|
||||
if (text.empty() || (text.size() == 1 && text[0].str.empty()))
|
||||
return;
|
||||
|
||||
Font::ColoredCodepoints codepoints;
|
||||
Font::getCodepointsFromString(text, codepoints);
|
||||
|
||||
Matrix3 m(x, y, angle, sx, sy, ox, oy, kx, ky);
|
||||
|
||||
addTextData({text, wrap, align, true, true, m});
|
||||
addTextData({codepoints, wrap, align, true, true, m});
|
||||
}
|
||||
|
||||
void Text::clear()
|
||||
{
|
||||
text_data.clear();
|
||||
draw_commands.clear();
|
||||
draw_commands.commands.clear();
|
||||
draw_commands.usecolors = false;
|
||||
texture_cache_id = font->getTextureCacheID();
|
||||
text_info = {};
|
||||
vert_offset = 0;
|
||||
@@ -217,7 +219,7 @@ void Text::clear()
|
||||
|
||||
void Text::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
{
|
||||
if (vbo == nullptr || draw_commands.empty())
|
||||
if (vbo == nullptr || draw_commands.commands.empty())
|
||||
return;
|
||||
|
||||
OpenGL::TempDebugGroup debuggroup("Text object draw");
|
||||
@@ -226,8 +228,9 @@ void Text::draw(float x, float y, float angle, float sx, float sy, float ox, flo
|
||||
if (font->getTextureCacheID() != texture_cache_id)
|
||||
regenerateVertices();
|
||||
|
||||
const size_t pos_offset = offsetof(Font::GlyphVertex, x);
|
||||
const size_t tex_offset = offsetof(Font::GlyphVertex, s);
|
||||
const size_t pos_offset = offsetof(Font::GlyphVertex, x);
|
||||
const size_t tex_offset = offsetof(Font::GlyphVertex, s);
|
||||
const size_t color_offset = offsetof(Font::GlyphVertex, color.r);
|
||||
const size_t stride = sizeof(Font::GlyphVertex);
|
||||
|
||||
OpenGL::TempTransform transform(gl);
|
||||
@@ -239,10 +242,18 @@ void Text::draw(float x, float y, float angle, float sx, float sy, float ox, flo
|
||||
|
||||
// Font::drawVertices expects AttribPointer calls to be done already.
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, vbo->getPointer(pos_offset));
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, vbo->getPointer(tex_offset));
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, vbo->getPointer(tex_offset));
|
||||
|
||||
if (draw_commands.usecolors)
|
||||
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, vbo->getPointer(color_offset));
|
||||
}
|
||||
|
||||
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD);
|
||||
uint32 enabledattribs = ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD;
|
||||
|
||||
if (draw_commands.usecolors)
|
||||
enabledattribs |= ATTRIBFLAG_COLOR;
|
||||
|
||||
gl.useVertexAttribArrays(enabledattribs);
|
||||
|
||||
font->drawVertices(draw_commands);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user